Path: blob/main/contrib/libcbor/examples/crash_course.c
178428 views
/*1* Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]>2*3* libcbor is free software; you can redistribute it and/or modify4* it under the terms of the MIT license. See LICENSE for details.5*/67#include <stdbool.h>8#include <stdio.h>9#include <string.h>10#include "cbor.h"1112// Part 1: Begin13void item_examples() {14// A cbor_item_t can contain any CBOR data type15cbor_item_t* float_item = cbor_build_float4(3.14f);16cbor_item_t* string_item = cbor_build_string("Hello World!");17cbor_item_t* array_item = cbor_new_indefinite_array();1819// They can be inspected20assert(cbor_is_float(float_item));21assert(cbor_typeof(string_item) == CBOR_TYPE_STRING);22assert(cbor_array_is_indefinite(array_item));23assert(cbor_array_size(array_item) == 0);2425// The data can be accessed26assert(cbor_float_get_float4(float_item) == 3.14f);27assert(memcmp(cbor_string_handle(string_item), "Hello World!",28cbor_string_length(string_item)) == 0);2930// And they can be modified31assert(cbor_array_push(array_item, float_item));32assert(cbor_array_push(array_item, string_item));33assert(cbor_array_size(array_item) == 2);3435// At the end of their lifetime, items must be freed36cbor_decref(&float_item);37cbor_decref(&string_item);38cbor_decref(&array_item);39}40// Part 1: End4142// Part 2: Begin43void encode_decode() {44cbor_item_t* item = cbor_build_uint8(42);4546// Serialize the item to a buffer (it will be allocated by libcbor)47unsigned char* buffer;48size_t buffer_size;49cbor_serialize_alloc(item, &buffer, &buffer_size);50assert(buffer_size == 2);51assert(buffer[0] == 0x18); // Encoding byte for uint852assert(buffer[1] == 42); // The value itself5354// And deserialize bytes back to an item55struct cbor_load_result result;56cbor_item_t* decoded_item = cbor_load(buffer, buffer_size, &result);57assert(result.error.code == CBOR_ERR_NONE);58assert(cbor_isa_uint(decoded_item));59assert(cbor_get_uint8(decoded_item) == 42);6061// Free the allocated buffer and items62free(buffer);63cbor_decref(&decoded_item);64cbor_decref(&item);65}66// Part 2: End6768// Part 3: Begin69void reference_counting() {70// cbor_item_t is a reference counted pointer under the hood71cbor_item_t* item = cbor_build_uint8(42);7273// Reference count starts at 174assert(cbor_refcount(item) == 1);7576// Most operations have reference semantics77cbor_item_t* array_item = cbor_new_definite_array(1);78assert(cbor_array_push(array_item, item));79assert(cbor_refcount(item) == 2); // item and array_item reference it80cbor_item_t* first_array_element = cbor_array_get(array_item, 0);81assert(first_array_element == item); // same item under the hood82assert(cbor_refcount(item) ==833); // and now first_array_element also points to it8485// To release the reference, use cbor_decref86cbor_decref(&first_array_element);8788// When reference count reaches 0, the item is freed89assert(cbor_refcount(array_item) == 1);90cbor_decref(&array_item);91assert(array_item == NULL);92assert(cbor_refcount(item) == 1);9394// Be careful, loops leak memory!9596// Deep copy copies the whole item tree97cbor_item_t* item_copy = cbor_copy(item);98assert(cbor_refcount(item) == 1);99assert(cbor_refcount(item_copy) == 1);100assert(item_copy != item);101cbor_decref(&item);102cbor_decref(&item_copy);103}104// Part 3: End105106// Part 4: Begin107void moving_values() {108{109// Move the "42" into an array.110cbor_item_t* array_item = cbor_new_definite_array(1);111// The line below leaks memory!112assert(cbor_array_push(array_item, cbor_build_uint8(42)));113cbor_item_t* first_array_element = cbor_array_get(array_item, 0);114assert(cbor_refcount(first_array_element) == 3); // Should be 2!115cbor_decref(&first_array_element);116cbor_decref(&array_item);117assert(cbor_refcount(first_array_element) == 1); // Shouldn't exist!118// Clean up119cbor_decref(&first_array_element);120}121122{123// A correct way to move values is to decref them in the caller scope.124cbor_item_t* array_item = cbor_new_definite_array(1);125cbor_item_t* item = cbor_build_uint8(42);126assert(cbor_array_push(array_item, item));127assert(cbor_refcount(item) == 2);128// "Give up" the item129cbor_decref(&item);130cbor_decref(&array_item);131// item is a dangling pointer at this point132}133134{135// cbor_move avoids the need to decref and the dangling pointer136cbor_item_t* array_item = cbor_new_definite_array(1);137assert(cbor_array_push(array_item, cbor_move(cbor_build_uint8(42))));138cbor_item_t* first_array_element = cbor_array_get(array_item, 0);139assert(cbor_refcount(first_array_element) == 2);140cbor_decref(&first_array_element);141cbor_decref(&array_item);142}143}144// Part 4: End145146// Part 5: Begin147// Refcount can be managed in conjunction with ownership148static cbor_item_t* global_item = NULL;149150// This function takes shared ownership of the item151void borrow_item(cbor_item_t* item) {152global_item = item;153// Mark the extra reference154cbor_incref(item);155}156157void return_item() {158cbor_decref(&global_item);159global_item = NULL;160}161162void reference_ownership() {163cbor_item_t* item = cbor_build_uint8(42);164165// Lend the item166borrow_item(item);167assert(cbor_refcount(item) == 2);168cbor_decref(&item);169170// Release the shared ownership. return_item will deallocate the item.171return_item();172}173// Part 5: End174175int main(void) {176item_examples();177encode_decode();178reference_counting();179moving_values();180reference_ownership();181return 0;182}183184185