empack/src/empack.h

239 lines
7.9 KiB
C
Raw Normal View History

2025-09-15 01:16:49 -05:00
#ifndef _EMPACK_H_
#define _EMPACK_H_
#include <stdint.h>
/** 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;
2025-09-20 23:15:04 -05:00
/** Parsed count utilized in tree traversal */
uint32_t pairs_parsed;
2025-09-15 01:16:49 -05:00
};
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;
2025-09-20 23:15:04 -05:00
/** Parsed count utilized in tree traversal */
uint32_t objects_parsed;
2025-09-15 01:16:49 -05:00
};
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;
2025-09-20 23:15:04 -05:00
/**
* Object that comes immediately after this one in the original Msgpack
* buffer, NULL if last object
*/
empack_obj_t *next;
2025-09-15 01:16:49 -05:00
};
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;
};
2025-09-20 23:15:04 -05:00
/** Macro for whether the given type is a map */
#define EMPACK_IS_MAP(type) ((type == EMPACK_TYPE_FIXMAP) || \
(type == EMPACK_TYPE_MAP16) || \
(type == EMPACK_TYPE_MAP32))
/** Macro for whether the given type is an array */
#define EMPACK_IS_ARRAY(type) ((type == EMPACK_TYPE_FIXARRAY) || \
(type == EMPACK_TYPE_ARRAY16) || \
(type == EMPACK_TYPE_ARRAY16))
2025-09-15 01:16:49 -05:00
/**
* 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);
2025-09-20 23:15:04 -05:00
/**
* @returns Number of characters printed excluding the NULL terminator
*/
uint32_t empack_print(empack_t *empack,
void (*print_func)(const char *buf, uint32_t buflen, void *arg),
void *arg,
const char *indent);
2025-09-15 01:16:49 -05:00
#endif /* _EMPACK_H_ */