#ifndef _EMPACK_H_ #define _EMPACK_H_ #include /** Forward definitions of all types */ typedef enum empack_type_enum empack_type_e; typedef struct empack_map_pair_struct empack_map_pair_t; typedef struct empack_map_struct empack_map_t; typedef struct empack_array_struct empack_array_t; typedef struct empack_str_struct empack_str_t; typedef struct empack_bin_struct empack_bin_t; typedef struct empack_ext_struct empack_ext_t; typedef struct empack_obj_struct empack_obj_t; typedef enum empack_status_enum empack_status_e; typedef struct empack_struct empack_t; /** * Enum of the first bytes for each msgpack type. For types with a range of * values that could be the first byte, the lowest is used */ enum empack_type_enum { /** Positive FIXINT, stored in `empack_obj_t::val.uint8` */ EMPACK_TYPE_POS_FIXINT = 0x00, /** FIXMAP, enum field `val.map` */ EMPACK_TYPE_FIXMAP = 0x80, /** FIXARRAY, enum field `val.map` */ EMPACK_TYPE_FIXARRAY = 0x90, EMPACK_TYPE_FIXSTR = 0xa0, EMPACK_TYPE_NIL = 0xc0, /** * Special error type reserved for a type parsing error. This type is never * used in the Msgpack spec. */ EMPACK_TYPE_ERROR = 0xc1, EMPACK_TYPE_FALSE = 0xc2, EMPACK_TYPE_TRUE = 0xc3, EMPACK_TYPE_BIN8 = 0xc4, EMPACK_TYPE_BIN16 = 0xc5, EMPACK_TYPE_BIN32 = 0xc6, EMPACK_TYPE_EXT8 = 0xc7, EMPACK_TYPE_EXT16 = 0xc8, EMPACK_TYPE_EXT32 = 0xc9, EMPACK_TYPE_FLOAT32 = 0xca, EMPACK_TYPE_FLOAT64 = 0xcb, EMPACK_TYPE_UINT8 = 0xcc, EMPACK_TYPE_UINT16 = 0xcd, EMPACK_TYPE_UINT32 = 0xce, EMPACK_TYPE_UINT64 = 0xcf, EMPACK_TYPE_INT8 = 0xd0, EMPACK_TYPE_INT16 = 0xd1, EMPACK_TYPE_INT32 = 0xd2, EMPACK_TYPE_INT64 = 0xd3, EMPACK_TYPE_FIXEXT1 = 0xd4, EMPACK_TYPE_FIXEXT2 = 0xd5, EMPACK_TYPE_FIXEXT4 = 0xd6, EMPACK_TYPE_FIXEXT8 = 0xd7, EMPACK_TYPE_FIXEXT16 = 0xd8, EMPACK_TYPE_STR8 = 0xd9, EMPACK_TYPE_STR16 = 0xda, EMPACK_TYPE_STR32 = 0xdb, EMPACK_TYPE_ARRAY16 = 0xdc, EMPACK_TYPE_ARRAY32 = 0xdd, EMPACK_TYPE_MAP16 = 0xde, EMPACK_TYPE_MAP32 = 0xdf, EMPACK_TYPE_NEG_FIXINT = 0xe0, }; struct empack_map_struct { /** List of key-value pairs in the map */ empack_map_pair_t *pairs; /** Number of key-value pairs expected to be in the map */ uint32_t pair_count; /** Number of key-value pairs actually in the map */ uint32_t pair_count_real; }; struct empack_array_struct { /** List of the objects in the array */ empack_obj_t *objects; /** Number of objects expected to be in the array */ uint32_t object_count; /** Number of objects actually in the array */ uint32_t object_count_real; }; struct empack_str_struct { /** Data value, points into the originally supplied Msgpack buffer */ const char *data; /** Expected size of the string buffer */ uint32_t size; }; struct empack_bin_struct { /** Data value, points into the originally supplied Msgpack buffer */ const void *data; /** Expected size of the buffer */ uint32_t size; }; struct empack_ext_struct { /** Data value, points into the originally supplied Msgpack buffer */ const void *data; /** Size of the buffer */ uint32_t size; /** Type value for the EXT object */ uint8_t type; }; struct empack_obj_struct { empack_type_e type; union { /** Union value valid for all MAP type data */ empack_map_t map; /** Union value valid for all ARRAY type data */ empack_array_t array; /** Union value valid for all STR type data */ empack_str_t str; /** Union value valid for all BIN type data */ empack_bin_t bin; /** Union value valid for all EXT type data */ empack_ext_t ext; float float32; double float64; uint8_t uint8; uint16_t uint16; uint32_t uint32; uint64_t uint64; int8_t int8; int16_t int16; int32_t int32; int64_t int64; } val; /** * If this object is in a MAP or ARRAY, this is a pointer to the parent * object. Needed for parsing purposes, and useful for tree traversal after * parsing. NULL if no parent is present. */ empack_obj_t *parent; }; struct empack_map_pair_struct { /** Key object for this pair */ empack_obj_t key; /** Value object for this pair */ empack_obj_t value; }; enum empack_status_enum { /** Parsing is completed with no errors */ EMPACK_STATUS_COMPLETE = 0, /** No errors in parsing, but the Msgpack supplied is incomplete */ EMPACK_STATUS_WANT_MORE, /** Parsing completed, but extra data was supplied and not parsed */ EMPACK_STATUS_EXTRA, /** * Ran out of arena memory, the empack->arena_used value will show the * amount of memory required to fully parse the supplied Msgpack buffer */ EMPACK_STATUS_NOMEM, /** Generic error while parsing */ EMPACK_STATUS_ERROR, }; struct empack_struct { /** Root object of the Msgpack object tree, filled out during parsing */ empack_obj_t root; /** Memory arena empack can use to construct the object tree */ void *arena; /** Size of the memory arena */ uint32_t arena_sz; /** How much of the memory arena is used */ uint32_t arena_used; }; /** * Initialize an empack struct, allowing it to be used for parsing. Calling this * on a previously initialzed empack struct will effectively reset it. * * The arena memory supplied must be valid for the entire lifetime of the empack * struct. * * @param empack Empack struct to intialize * @param arena Memory arena empack will use for storing Msgpack object tree information * @param arena_sz Size of the memory arena */ void empack_init(empack_t *empack, void *arena, uint32_t arena_sz); /** * Parse the provided Msgpack data. Note that the resulting object tree in the * empack struct may point into the supplied buffer for certain objects such as * BIN types. * * Spec for reference: https://github.com/msgpack/msgpack/blob/master/spec.md * * @param empack Empack struct, must be initialzed by empack_init * @param msgpack Msgpack buffer to parse * @param len Size of the Msgpack buffer */ empack_status_e empack_parse(empack_t *empack, const void *msgpack, uint32_t len); /** * Parse a singular Msgpack object, useful for use cases where the Msgpack data * must be streamed or the caller does not want to allocate a memory arena. * * Note that for MAP and ARRAY types, the object pointers to child objects will * not be allocated and set to NULL. * * @param object Empack object struct to fill out * @param msgpack Msgpack buffer to parse * @param len Length of the Msgpack buffer, set on return to the number of bytes * processed */ empack_status_e empack_parse_one(empack_obj_t *object, const void *msgpack, uint32_t *len); #endif /* _EMPACK_H_ */