WIP
This commit is contained in:
parent
0ab449bb65
commit
6cde97a952
3 changed files with 307 additions and 1 deletions
6
.clangd
Normal file
6
.clangd
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
CompileFlags:
|
||||||
|
Add: [ -Wall, -I/home/aaron/Projects/empack/src ]
|
||||||
|
InlayHints:
|
||||||
|
Enabled: false
|
||||||
|
Completion:
|
||||||
|
ArgumentLists: None
|
||||||
212
src/empack.c
212
src/empack.c
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <cstddef>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -713,6 +714,217 @@ empack_print(empack_t *empack,
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static empack_status_e
|
||||||
|
_empack_allocate_packed_object(empack_t *empack, empack_obj_t **obj)
|
||||||
|
{
|
||||||
|
if (empack->parent == NULL) {
|
||||||
|
(*obj) = &empack->root;
|
||||||
|
empack->parent = &empack->root;
|
||||||
|
return EMPACK_STATUS_WANT_MORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (empack->parent == NULL) {
|
||||||
|
return EMPACK_STATUS_EXTRA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EMPACK_IS_MAP(empack->parent->type)) {
|
||||||
|
empack_map_t *pmap = &empack->parent->val.map;
|
||||||
|
|
||||||
|
if (pmap->pairs_parsed == pmap->pair_count) {
|
||||||
|
empack->parent = empack->parent->parent;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we set the key's type to error to indicate whether it's been
|
||||||
|
* filled out already or not */
|
||||||
|
if (pmap->pairs[pmap->pairs_parsed].key.type == EMPACK_TYPE_ERROR) {
|
||||||
|
(*obj) = &pmap->pairs[pmap->pairs_parsed].key;
|
||||||
|
} else {
|
||||||
|
(*obj) = &pmap->pairs[pmap->pairs_parsed].value;
|
||||||
|
pmap->pairs_parsed++;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
} else if (EMPACK_IS_ARRAY(empack->parent->type)) {
|
||||||
|
empack_array_t *parr = &empack->parent->val.array;
|
||||||
|
|
||||||
|
if (parr->objects_parsed == parr->object_count) {
|
||||||
|
empack->parent = empack->parent->parent;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*obj) = &parr->objects[parr->objects_parsed];
|
||||||
|
parr->objects_parsed++;
|
||||||
|
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
/* this shouldn't be possible */
|
||||||
|
return EMPACK_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EMPACK_STATUS_WANT_MORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
empack_status_e
|
||||||
|
empack_pack_map(empack_t *empack, uint32_t pair_count, empack_obj_t **obj)
|
||||||
|
{
|
||||||
|
if (pair_count > UINT16_MAX) {
|
||||||
|
return empack_pack_map32(empack, pair_count, obj);
|
||||||
|
} else if (pair_count > EMPACK_FIXMAP_MAX) {
|
||||||
|
return empack_pack_map16(empack, pair_count, obj);
|
||||||
|
} else {
|
||||||
|
return empack_pack_fixmap(empack, pair_count, obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
empack_status_e
|
||||||
|
_empack_init_map(empack_t *empack, empack_obj_t *obj, uint32_t pair_count)
|
||||||
|
{
|
||||||
|
empack_map_t *map = &obj->val.map;
|
||||||
|
map->pair_count = pair_count;
|
||||||
|
|
||||||
|
if (pair_count > 0) {
|
||||||
|
map->pairs = empack_allocate(empack, sizeof(*map->pairs) * pair_count);
|
||||||
|
if (map->pairs == NULL) {
|
||||||
|
return EMPACK_STATUS_NOMEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mark all of the key's types as error to assist in figuring out what's
|
||||||
|
* been packed or not */
|
||||||
|
for (uint32_t i = 0; i < pair_count; i++) {
|
||||||
|
map->pairs[i].key.type = EMPACK_TYPE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pair_count == 0) {
|
||||||
|
return EMPACK_STATUS_COMPLETE;
|
||||||
|
} else {
|
||||||
|
return EMPACK_STATUS_WANT_MORE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
empack_status_e
|
||||||
|
empack_pack_fixmap(empack_t *empack, uint8_t pair_count, empack_obj_t **obj)
|
||||||
|
{
|
||||||
|
empack_status_e ret;
|
||||||
|
empack_obj_t *new_obj;
|
||||||
|
|
||||||
|
if (pair_count > EMPACK_FIXMAP_MAX) {
|
||||||
|
return EMPACK_STATUS_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = _empack_allocate_packed_object(empack, &new_obj);
|
||||||
|
if (ret != EMPACK_STATUS_WANT_MORE) {
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj) {
|
||||||
|
*obj = new_obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_obj->type = EMPACK_TYPE_FIXMAP;
|
||||||
|
return _empack_init_map(empack, new_obj, pair_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
empack_status_e
|
||||||
|
empack_pack_map16(empack_t *empack, uint16_t pair_count, empack_obj_t **obj)
|
||||||
|
{
|
||||||
|
empack_status_e ret;
|
||||||
|
empack_obj_t *new_obj;
|
||||||
|
|
||||||
|
if (pair_count > UINT16_MAX) {
|
||||||
|
return EMPACK_STATUS_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = _empack_allocate_packed_object(empack, &new_obj);
|
||||||
|
if (ret != EMPACK_STATUS_WANT_MORE) {
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj) {
|
||||||
|
*obj = new_obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_obj->type = EMPACK_TYPE_MAP16;
|
||||||
|
return _empack_init_map(empack, new_obj, pair_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
empack_status_e
|
||||||
|
empack_pack_map32(empack_t *empack, uint32_t pair_count, empack_obj_t **obj)
|
||||||
|
{
|
||||||
|
empack_status_e ret;
|
||||||
|
empack_obj_t *new_obj;
|
||||||
|
|
||||||
|
if (pair_count > UINT32_MAX) {
|
||||||
|
return EMPACK_STATUS_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = _empack_allocate_packed_object(empack, &new_obj);
|
||||||
|
if (ret != EMPACK_STATUS_WANT_MORE) {
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj) {
|
||||||
|
*obj = new_obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_obj->type = EMPACK_TYPE_MAP32;
|
||||||
|
return _empack_init_map(empack, new_obj, pair_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
empack_status_e
|
||||||
|
empack_pack_array(empack_t *empack, uint32_t obj_count, empack_obj_t **obj)
|
||||||
|
{
|
||||||
|
if (obj_count > UINT16_MAX) {
|
||||||
|
return empack_pack_array32(empack, obj_count, obj);
|
||||||
|
} else if (obj_count > EMPACK_FIXARRAY_MAX) {
|
||||||
|
return empack_pack_array16(empack, obj_count, obj);
|
||||||
|
} else {
|
||||||
|
return empack_pack_fixarray(empack, obj_count, obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
empack_status_e
|
||||||
|
_empack_init_array(empack_t *empack, empack_obj_t *obj, uint32_t obj_count)
|
||||||
|
{
|
||||||
|
empack_array_t *array = &obj->val.array;
|
||||||
|
array->object_count = obj_count;
|
||||||
|
|
||||||
|
if (obj_count > 0) {
|
||||||
|
array->objects = empack_allocate(empack, sizeof(*array->objects) * obj_count);
|
||||||
|
if (array->objects == NULL) {
|
||||||
|
return EMPACK_STATUS_NOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EMPACK_STATUS_WANT_MORE;
|
||||||
|
} else {
|
||||||
|
return EMPACK_STATUS_COMPLETE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
empack_status_e
|
||||||
|
empack_pack_fixarray(empack_t *empack, uint8_t obj_count, empack_obj_t **obj)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
empack_status_e empack_pack_array16(empack_t *empack, uint16_t obj_count, empack_obj_t **obj);
|
||||||
|
|
||||||
|
empack_status_e empack_pack_array32(empack_t *empack, uint32_t obj_count, empack_obj_t **obj);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
empack_allocate(empack_t *empack, uint32_t size)
|
empack_allocate(empack_t *empack, uint32_t size)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
90
src/empack.h
90
src/empack.h
|
|
@ -117,6 +117,8 @@ typedef enum empack_status_enum {
|
||||||
* amount of memory required to fully parse the supplied Msgpack buffer
|
* amount of memory required to fully parse the supplied Msgpack buffer
|
||||||
*/
|
*/
|
||||||
EMPACK_STATUS_NOMEM,
|
EMPACK_STATUS_NOMEM,
|
||||||
|
/** An invalid value has been passed in while constructing a messagepack tree */
|
||||||
|
EMPACK_STATUS_INVALID,
|
||||||
/** Generic error while parsing */
|
/** Generic error while parsing */
|
||||||
EMPACK_STATUS_ERROR,
|
EMPACK_STATUS_ERROR,
|
||||||
} empack_status_e;
|
} empack_status_e;
|
||||||
|
|
@ -209,7 +211,7 @@ struct empack_map_pair_struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct empack_struct {
|
struct empack_struct {
|
||||||
/** Root object of the Msgpack object tree, filled out during parsing */
|
/** Root object of the Msgpack object tree, filled out during parsing/packing */
|
||||||
empack_obj_t root;
|
empack_obj_t root;
|
||||||
/** Memory arena empack can use to construct the object tree */
|
/** Memory arena empack can use to construct the object tree */
|
||||||
void *arena;
|
void *arena;
|
||||||
|
|
@ -217,6 +219,7 @@ struct empack_struct {
|
||||||
uint32_t arena_sz;
|
uint32_t arena_sz;
|
||||||
/** How much of the memory arena is used */
|
/** How much of the memory arena is used */
|
||||||
uint32_t arena_used;
|
uint32_t arena_used;
|
||||||
|
empack_obj_t *parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Macro for whether the given type is a map */
|
/** Macro for whether the given type is a map */
|
||||||
|
|
@ -294,4 +297,89 @@ uint32_t empack_print(empack_t *empack,
|
||||||
void *arg,
|
void *arg,
|
||||||
const char *indent);
|
const char *indent);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a fully construct or parsed empack struct, dump the equivalent Msgpack
|
||||||
|
* bytes via the provided write function callback.
|
||||||
|
*
|
||||||
|
* @param empack Empack struct to dump
|
||||||
|
* @param write_func Write function callback
|
||||||
|
* @param arg User argument for write_func
|
||||||
|
*
|
||||||
|
* @returns Number of bytes written
|
||||||
|
*/
|
||||||
|
uint32_t empack_dump(empack_t *empack,
|
||||||
|
void (*write_func)(const uint8_t *buf, uint32_t buflen, void *arg),
|
||||||
|
void *arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pack a map object, selecting the minimum required map type depending on the
|
||||||
|
* number of pairs.
|
||||||
|
*
|
||||||
|
* @param empack Empack struct to pack into
|
||||||
|
* @param pair_count Number of key-value pairs should end up in this map
|
||||||
|
* @param obj Optional return argument to get a pointer to the newly created object
|
||||||
|
*
|
||||||
|
* @returns An EMPACK_STATUS_* value
|
||||||
|
*/
|
||||||
|
empack_status_e empack_pack_map(empack_t *empack, uint32_t pair_count, empack_obj_t **obj);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pack a fixmap object
|
||||||
|
*
|
||||||
|
* @param empack Empack struct to pack into
|
||||||
|
* @param pair_count Number of key-value pairs should end up in this map
|
||||||
|
* @param obj Optional return argument to get a pointer to the newly created object
|
||||||
|
*
|
||||||
|
* @returns An EMPACK_STATUS_* value
|
||||||
|
*/
|
||||||
|
empack_status_e empack_pack_fixmap(empack_t *empack, uint8_t pair_count, empack_obj_t **obj);
|
||||||
|
|
||||||
|
empack_status_e empack_pack_map16(empack_t *empack, uint16_t pair_count, empack_obj_t **obj);
|
||||||
|
|
||||||
|
empack_status_e empack_pack_map32(empack_t *empack, uint32_t pair_count, empack_obj_t **obj);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
empack_status_e empack_pack_array(empack_t *empack, uint32_t obj_count, empack_obj_t **obj);
|
||||||
|
|
||||||
|
empack_status_e empack_pack_fixarray(empack_t *empack, uint8_t obj_count, empack_obj_t **obj);
|
||||||
|
|
||||||
|
empack_status_e empack_pack_array16(empack_t *empack, uint16_t obj_count, empack_obj_t **obj);
|
||||||
|
|
||||||
|
empack_status_e empack_pack_array32(empack_t *empack, uint32_t obj_count, empack_obj_t **obj);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pack an integer into the empack tree, choosing the smallest object type that
|
||||||
|
* the value will fit into.
|
||||||
|
*
|
||||||
|
* @param empack Empack struct to pack into
|
||||||
|
* @param val Integer value to pack
|
||||||
|
* @param obj Optional return argument to get a pointer to the newly created object
|
||||||
|
*
|
||||||
|
* @returns An EMPACK_STATUS_* value
|
||||||
|
*/
|
||||||
|
empack_status_e empack_pack_int(empack_t *empack, long val, empack_obj_t **obj);
|
||||||
|
|
||||||
|
empack_status_e empack_pack_pos_fixint(empack_t *empack, uint8_t val, empack_obj_t **obj);
|
||||||
|
|
||||||
|
empack_status_e empack_pack_uint8(empack_t *empack, uint8_t val, empack_obj_t **obj);
|
||||||
|
|
||||||
|
empack_status_e empack_pack_uint16(empack_t *empack, uint16_t val, empack_obj_t **obj);
|
||||||
|
|
||||||
|
empack_status_e empack_pack_uint32(empack_t *empack, uint32_t val, empack_obj_t **obj);
|
||||||
|
|
||||||
|
empack_status_e empack_pack_uint64(empack_t *empack, uint64_t val, empack_obj_t **obj);
|
||||||
|
|
||||||
|
empack_status_e empack_pack_neg_fixint(empack_t *empack, int8_t val, empack_obj_t **obj);
|
||||||
|
|
||||||
|
empack_status_e empack_pack_int8(empack_t *empack, int8_t val, empack_obj_t **obj);
|
||||||
|
|
||||||
|
empack_status_e empack_pack_int16(empack_t *empack, int16_t val, empack_obj_t **obj);
|
||||||
|
|
||||||
|
empack_status_e empack_pack_int32(empack_t *empack, int32_t val, empack_obj_t **obj);
|
||||||
|
|
||||||
|
empack_status_e empack_pack_int64(empack_t *empack, int64_t val, empack_obj_t **obj);
|
||||||
|
|
||||||
#endif /* _EMPACK_H_ */
|
#endif /* _EMPACK_H_ */
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue