297 lines
10 KiB
C
297 lines
10 KiB
C
#ifndef _EMPACK_H_
|
|
#define _EMPACK_H_
|
|
|
|
#include <stdint.h>
|
|
|
|
/** Pairing struct for maps */
|
|
typedef struct empack_map_pair_struct empack_map_pair_t;
|
|
/** Map struct for all MAP type values */
|
|
typedef struct empack_map_struct empack_map_t;
|
|
/** Array struct for all ARRAY type values */
|
|
typedef struct empack_array_struct empack_array_t;
|
|
/** String struct for all STR type values */
|
|
typedef struct empack_str_struct empack_str_t;
|
|
/** Binary struct for all BIN type values */
|
|
typedef struct empack_bin_struct empack_bin_t;
|
|
/** Extension struct for all EXT type values */
|
|
typedef struct empack_ext_struct empack_ext_t;
|
|
/** Object struct for all types of MessagePack objects */
|
|
typedef struct empack_obj_struct empack_obj_t;
|
|
/** Empack struct for constructing a MessagePack tree structure */
|
|
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
|
|
*/
|
|
typedef 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,
|
|
/** FIXSTR, enum field `val.str` */
|
|
EMPACK_TYPE_FIXSTR = 0xa0,
|
|
/** NIL, no value */
|
|
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,
|
|
/** FALSE, no value */
|
|
EMPACK_TYPE_FALSE = 0xc2,
|
|
/** TRUE, no value */
|
|
EMPACK_TYPE_TRUE = 0xc3,
|
|
/** BIN8, enum field `val.bin` */
|
|
EMPACK_TYPE_BIN8 = 0xc4,
|
|
/** BIN16, enum field `val.bin` */
|
|
EMPACK_TYPE_BIN16 = 0xc5,
|
|
/** BIN32, enum field `val.bin` */
|
|
EMPACK_TYPE_BIN32 = 0xc6,
|
|
/** EXT8, enum field `val.ext` */
|
|
EMPACK_TYPE_EXT8 = 0xc7,
|
|
/** EXT16, enum field `val.ext` */
|
|
EMPACK_TYPE_EXT16 = 0xc8,
|
|
/** EXT32, enum field `val.ext` */
|
|
EMPACK_TYPE_EXT32 = 0xc9,
|
|
/** FLOAT32, enum field `val.float32` */
|
|
EMPACK_TYPE_FLOAT32 = 0xca,
|
|
/** FLOAT64, enum field `val.float64` */
|
|
EMPACK_TYPE_FLOAT64 = 0xcb,
|
|
/** UINT8, enum field `val.uint8` */
|
|
EMPACK_TYPE_UINT8 = 0xcc,
|
|
/** UINT16, enum field `val.uint16` */
|
|
EMPACK_TYPE_UINT16 = 0xcd,
|
|
/** UINT32, enum field `val.uint32` */
|
|
EMPACK_TYPE_UINT32 = 0xce,
|
|
/** UINT64, enum field `val.uint64` */
|
|
EMPACK_TYPE_UINT64 = 0xcf,
|
|
/** INT8, enum field `val.int8` */
|
|
EMPACK_TYPE_INT8 = 0xd0,
|
|
/** INT16, enum field `val.int16` */
|
|
EMPACK_TYPE_INT16 = 0xd1,
|
|
/** INT32, enum field `val.int32` */
|
|
EMPACK_TYPE_INT32 = 0xd2,
|
|
/** INT64, enum field `val.int64` */
|
|
EMPACK_TYPE_INT64 = 0xd3,
|
|
/** FIXEXT1, enum field `val.ext` */
|
|
EMPACK_TYPE_FIXEXT1 = 0xd4,
|
|
/** FIXEXT2, enum field `val.ext` */
|
|
EMPACK_TYPE_FIXEXT2 = 0xd5,
|
|
/** FIXEXT4, enum field `val.ext` */
|
|
EMPACK_TYPE_FIXEXT4 = 0xd6,
|
|
/** FIXEXT8, enum field `val.ext` */
|
|
EMPACK_TYPE_FIXEXT8 = 0xd7,
|
|
/** FIXEXT16, enum field `val.ext` */
|
|
EMPACK_TYPE_FIXEXT16 = 0xd8,
|
|
/** STR8, enum field `val.str */
|
|
EMPACK_TYPE_STR8 = 0xd9,
|
|
/** STR16, enum field `val.str */
|
|
EMPACK_TYPE_STR16 = 0xda,
|
|
/** STR32, enum field `val.str */
|
|
EMPACK_TYPE_STR32 = 0xdb,
|
|
/** ARRAY16, enum field `val.array` */
|
|
EMPACK_TYPE_ARRAY16 = 0xdc,
|
|
/** ARRAY32, enum field `val.array` */
|
|
EMPACK_TYPE_ARRAY32 = 0xdd,
|
|
/** MAP16, enum field `val.map` */
|
|
EMPACK_TYPE_MAP16 = 0xde,
|
|
/** MAP32, enum field `val.map` */
|
|
EMPACK_TYPE_MAP32 = 0xdf,
|
|
/** Negative FIXINT, enum field `val.int8` */
|
|
EMPACK_TYPE_NEG_FIXINT = 0xe0,
|
|
} empack_type_e;
|
|
|
|
/** Enum parsing status return codes */
|
|
typedef 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,
|
|
} empack_status_e;
|
|
|
|
|
|
|
|
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;
|
|
/** Parsed count utilized in tree traversal */
|
|
uint32_t pairs_parsed;
|
|
};
|
|
|
|
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;
|
|
/** Parsed count utilized in tree traversal */
|
|
uint32_t objects_parsed;
|
|
};
|
|
|
|
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;
|
|
/**
|
|
* Object that comes immediately after this one in the original Msgpack
|
|
* buffer, NULL if last object
|
|
*/
|
|
empack_obj_t *next;
|
|
};
|
|
|
|
struct empack_map_pair_struct {
|
|
/** Key object for this pair */
|
|
empack_obj_t key;
|
|
/** Value object for this pair */
|
|
empack_obj_t value;
|
|
};
|
|
|
|
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;
|
|
};
|
|
|
|
/** 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))
|
|
|
|
/**
|
|
* Initialize an empack struct, allowing it to be used for parsing. Calling this
|
|
* on a previously initialized 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 initialize
|
|
* @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 initialized by empack_init
|
|
* @param msgpack Msgpack buffer to parse
|
|
* @param len Size of the Msgpack buffer
|
|
*
|
|
* @returns An EMPACK_STATUS_* value
|
|
*/
|
|
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
|
|
*
|
|
* @returns An EMPACK_STATUS_* value
|
|
*/
|
|
empack_status_e empack_parse_one(empack_obj_t *object, const void *msgpack, uint32_t *len);
|
|
|
|
/**
|
|
* Given an empack struct that has successfully been called with empack_parse,
|
|
* print a JSON formatted string via the supplied print function. An optional
|
|
* indent string can be supplied for formatting, if NULL the JSON will be
|
|
* minified.
|
|
*
|
|
* Note that not all MessagePack trees can transform into valid JSON, such as
|
|
* the BIN/EXT data types, or using non-string values as keys in maps.
|
|
*
|
|
* @param empack Empack struct to print
|
|
* @param print_func Print function to be called for outputting characters
|
|
* @param arg User argument for print_func
|
|
* @param indent Optional indent string
|
|
*
|
|
* @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);
|
|
|
|
#endif /* _EMPACK_H_ */
|