/*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#ifndef LIBCBOR_DATA_H8#define LIBCBOR_DATA_H910#include <stdbool.h>11#include <stddef.h>12#include <stdint.h>13#include <stdlib.h>1415#ifdef __cplusplus16extern "C" {17#endif1819typedef const unsigned char* cbor_data;20typedef unsigned char* cbor_mutable_data;2122/** Specifies the Major type of ::cbor_item_t */23typedef enum cbor_type {24CBOR_TYPE_UINT /** 0 - positive integers */25,26CBOR_TYPE_NEGINT /** 1 - negative integers*/27,28CBOR_TYPE_BYTESTRING /** 2 - byte strings */29,30CBOR_TYPE_STRING /** 3 - strings */31,32CBOR_TYPE_ARRAY /** 4 - arrays */33,34CBOR_TYPE_MAP /** 5 - maps */35,36CBOR_TYPE_TAG /** 6 - tags */37,38CBOR_TYPE_FLOAT_CTRL /** 7 - decimals and special values (true, false, nil,39...) */40} cbor_type;4142/** Possible decoding errors */43typedef enum {44CBOR_ERR_NONE,45CBOR_ERR_NOTENOUGHDATA,46CBOR_ERR_NODATA,47// TODO: Should be "malformed" or at least "malformatted". Retained for48// backwards compatibility.49CBOR_ERR_MALFORMATED,50CBOR_ERR_MEMERROR /** Memory error - item allocation failed. Is it too big for51your allocator? */52,53CBOR_ERR_SYNTAXERROR /** Stack parsing algorithm failed */54} cbor_error_code;5556/** Possible widths of #CBOR_TYPE_UINT items */57typedef enum {58CBOR_INT_8,59CBOR_INT_16,60CBOR_INT_32,61CBOR_INT_6462} cbor_int_width;6364/** Possible widths of #CBOR_TYPE_FLOAT_CTRL items */65typedef enum {66CBOR_FLOAT_0 /** Internal use - ctrl and special values */67,68CBOR_FLOAT_16 /** Half float */69,70CBOR_FLOAT_32 /** Single float */71,72CBOR_FLOAT_64 /** Double */73} cbor_float_width;7475/** Metadata for dynamically sized types */76typedef enum {77_CBOR_METADATA_DEFINITE,78_CBOR_METADATA_INDEFINITE79} _cbor_dst_metadata;8081/** Semantic mapping for CTRL simple values */82typedef enum {83CBOR_CTRL_NONE = 0,84CBOR_CTRL_FALSE = 20,85CBOR_CTRL_TRUE = 21,86CBOR_CTRL_NULL = 22,87CBOR_CTRL_UNDEF = 2388} _cbor_ctrl;8990// Metadata items use size_t (instead of uint64_t) because items in memory take91// up at least 1B per entry or string byte, so if size_t is narrower than92// uint64_t, we wouldn't be able to create them in the first place and can save93// some space.9495/** Integers specific metadata */96struct _cbor_int_metadata {97cbor_int_width width;98};99100/** Bytestrings specific metadata */101struct _cbor_bytestring_metadata {102size_t length;103_cbor_dst_metadata type;104};105106/** Strings specific metadata */107struct _cbor_string_metadata {108size_t length;109size_t codepoint_count; /* Sum of chunks' codepoint_counts for indefinite110strings */111_cbor_dst_metadata type;112};113114/** Arrays specific metadata */115struct _cbor_array_metadata {116size_t allocated;117size_t end_ptr;118_cbor_dst_metadata type;119};120121/** Maps specific metadata */122struct _cbor_map_metadata {123size_t allocated;124size_t end_ptr;125_cbor_dst_metadata type;126};127128/** Arrays specific metadata129*130* The pointer is included - cbor_item_metadata is131* 2 * sizeof(size_t) + sizeof(_cbor_string_type_metadata),132* lets use the space133*/134struct _cbor_tag_metadata {135struct cbor_item_t* tagged_item;136uint64_t value;137};138139/** Floats specific metadata - includes CTRL values */140struct _cbor_float_ctrl_metadata {141cbor_float_width width;142uint8_t ctrl;143};144145/** Raw memory casts helper */146union _cbor_float_helper {147float as_float;148uint32_t as_uint;149};150151/** Raw memory casts helper */152union _cbor_double_helper {153double as_double;154uint64_t as_uint;155};156157/** Union of metadata across all possible types - discriminated in #cbor_item_t158*/159union cbor_item_metadata {160struct _cbor_int_metadata int_metadata;161struct _cbor_bytestring_metadata bytestring_metadata;162struct _cbor_string_metadata string_metadata;163struct _cbor_array_metadata array_metadata;164struct _cbor_map_metadata map_metadata;165struct _cbor_tag_metadata tag_metadata;166struct _cbor_float_ctrl_metadata float_ctrl_metadata;167};168169/** The item handle */170typedef struct cbor_item_t {171/** Discriminated by type */172union cbor_item_metadata metadata;173/** Reference count - initialize to 0 */174size_t refcount;175/** Major type discriminator */176cbor_type type;177/** Raw data block - interpretation depends on metadata */178unsigned char* data;179} cbor_item_t;180181/** Defines cbor_item_t#data structure for indefinite strings and bytestrings182*183* Used to cast the raw representation for a sane manipulation184*/185struct cbor_indefinite_string_data {186size_t chunk_count;187size_t chunk_capacity;188cbor_item_t** chunks;189};190191/** High-level decoding error */192struct cbor_error {193/** Approximate position */194size_t position;195/** Description */196cbor_error_code code;197};198199/** Simple pair of items for use in maps */200struct cbor_pair {201cbor_item_t *key, *value;202};203204/** High-level decoding result */205struct cbor_load_result {206/** Error indicator */207struct cbor_error error;208/** Number of bytes read */209size_t read;210};211212/** Streaming decoder result - status */213enum cbor_decoder_status {214/** Decoding finished successfully (a callback has been invoked)215*216* Note that this does *not* mean that the buffer has been fully decoded;217* there may still be unread bytes for which no callback has been involved.218*/219CBOR_DECODER_FINISHED,220/** Not enough data to invoke a callback */221// TODO: The name is inconsistent with CBOR_ERR_NOTENOUGHDATA. Retained for222// backwards compatibility.223CBOR_DECODER_NEDATA,224/** Bad data (reserved MTB, malformed value, etc.) */225CBOR_DECODER_ERROR226};227228/** Streaming decoder result */229struct cbor_decoder_result {230/** Input bytes read/consumed231*232* If this is less than the size of input buffer, the client will likely233* resume parsing starting at the next byte (e.g. `buffer + result.read`).234*235* Set to 0 if the #status is not #CBOR_DECODER_FINISHED.236*/237size_t read;238239/** The decoding status */240enum cbor_decoder_status status;241242/** Number of bytes in the input buffer needed to resume parsing243*244* Set to 0 unless the result status is #CBOR_DECODER_NEDATA. If it is, then:245* - If at least one byte was passed, #required will be set to the minimum246* number of bytes needed to invoke a decoded callback on the current247* prefix.248*249* For example: Attempting to decode a 1B buffer containing `0x19` will250* set #required to 3 as `0x19` signals a 2B integer item, so we need at251* least 3B to continue (the `0x19` MTB byte and two bytes of data needed252* to invoke #cbor_callbacks.uint16).253*254* - If there was no data at all, #read will always be set to 1255*/256size_t required;257};258259#ifdef __cplusplus260}261#endif262263#endif // LIBCBOR_DATA_H264265266