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 <stdio.h>
|
||||
#include <string.h>
|
||||
|
|
@ -713,6 +714,217 @@ empack_print(empack_t *empack,
|
|||
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 *
|
||||
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
|
||||
*/
|
||||
EMPACK_STATUS_NOMEM,
|
||||
/** An invalid value has been passed in while constructing a messagepack tree */
|
||||
EMPACK_STATUS_INVALID,
|
||||
/** Generic error while parsing */
|
||||
EMPACK_STATUS_ERROR,
|
||||
} empack_status_e;
|
||||
|
|
@ -209,7 +211,7 @@ struct empack_map_pair_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;
|
||||
/** Memory arena empack can use to construct the object tree */
|
||||
void *arena;
|
||||
|
|
@ -217,6 +219,7 @@ struct empack_struct {
|
|||
uint32_t arena_sz;
|
||||
/** How much of the memory arena is used */
|
||||
uint32_t arena_used;
|
||||
empack_obj_t *parent;
|
||||
};
|
||||
|
||||
/** Macro for whether the given type is a map */
|
||||
|
|
@ -294,4 +297,89 @@ uint32_t empack_print(empack_t *empack,
|
|||
void *arg,
|
||||
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_ */
|
||||
|
|
|
|||
Loading…
Reference in a new issue