Compare commits

...
Sign in to create a new pull request.
Author SHA1 Message Date
6cde97a952 WIP 2026-01-10 19:04:46 -06:00
3 changed files with 307 additions and 1 deletions

6
.clangd Normal file
View file

@ -0,0 +1,6 @@
CompileFlags:
Add: [ -Wall, -I/home/aaron/Projects/empack/src ]
InlayHints:
Enabled: false
Completion:
ArgumentLists: None

View file

@ -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)
{

View file

@ -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_ */