commit 18eb77a2e7cf13b2e1f961c5a0bac246e04d0d50 Author: Aaron Cook Date: Mon Sep 15 01:16:49 2025 -0500 Define types and API diff --git a/src/empack.h b/src/empack.h new file mode 100644 index 0000000..b753459 --- /dev/null +++ b/src/empack.h @@ -0,0 +1,216 @@ +#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_ */