Skip to content

Commit d1a2416

Browse files
committed
Simple implementation for maps
1 parent 83c9d82 commit d1a2416

File tree

5 files changed

+124
-8
lines changed

5 files changed

+124
-8
lines changed

src/cbor.c

+50-7
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ cbor_item_t * cbor_load(cbor_data source,
9898
.array_start = &cbor_builder_array_start_callback,
9999
.indef_array_start = &cbor_builder_indef_array_start_callback,
100100

101+
.map_start = &cbor_builder_map_start_callback,
102+
101103
.tag = &cbor_builder_tag_callback,
102104

103105
.null = &cbor_builder_null_callback,
@@ -1221,17 +1223,58 @@ cbor_item_t * cbor_new_definite_map(size_t size)
12211223
*item = (cbor_item_t){
12221224
.refcount = 1,
12231225
.type = CBOR_TYPE_MAP,
1224-
.metadata = { .map_metadata = { .size = 0} },
1225-
.data = malloc(sizeof(cbor_item_t *) * size)
1226+
.metadata = { .map_metadata = { .size = 0, .type = _CBOR_METADATA_DEFINITE } },
1227+
.data = malloc(sizeof(struct cbor_pair) * size)
12261228
};
12271229
return item;
12281230
}
12291231

1230-
cbor_item_t * cbor_new_indefinite_map();
1231-
cbor_item_t * cbor_map_add(cbor_item_t * item, struct cbor_pair pair);
1232-
bool cbor_map_is_definite(cbor_item_t * item);
1233-
bool cbor_map_is_indefinite(cbor_item_t * item);
1234-
struct cbor_pair * cbor_map_handle(cbor_item_t * item);
1232+
cbor_item_t * cbor_new_indefinite_map()
1233+
{
1234+
cbor_item_t * item = malloc(sizeof(cbor_item_t));
1235+
*item = (cbor_item_t){
1236+
.refcount = 1,
1237+
.type = CBOR_TYPE_MAP,
1238+
.metadata = { .map_metadata = { .size = 0, .type = _CBOR_METADATA_INDEFINITE } },
1239+
.data = NULL
1240+
};
1241+
return item;
1242+
}
1243+
1244+
cbor_item_t * cbor_map_add(cbor_item_t * item, struct cbor_pair pair)
1245+
{
1246+
assert(cbor_isa_map(item));
1247+
struct _cbor_map_metadata * metadata = (struct _cbor_map_metadata *)&item->metadata;
1248+
struct cbor_pair * data = cbor_map_handle(item);
1249+
if (cbor_map_is_definite(item)) {
1250+
// TODO check size - throw
1251+
data[metadata->size++] = pair;
1252+
} else {
1253+
// TODO exponential reallocs?
1254+
// TOOD check realloc
1255+
data = realloc(data, (metadata->size + 1) * sizeof(struct cbor_pair));
1256+
data[metadata->size++] = pair;
1257+
item->data = (unsigned char *)data;
1258+
}
1259+
return item;
1260+
}
1261+
1262+
bool cbor_map_is_definite(cbor_item_t * item)
1263+
{
1264+
assert(cbor_isa_map(item));
1265+
return item->metadata.map_metadata.type == _CBOR_METADATA_DEFINITE;
1266+
}
1267+
1268+
bool cbor_map_is_indefinite(cbor_item_t * item)
1269+
{
1270+
return !cbor_map_is_definite(item);
1271+
}
1272+
1273+
struct cbor_pair * cbor_map_handle(cbor_item_t * item)
1274+
{
1275+
assert(cbor_isa_map(item));
1276+
return (struct cbor_pair *)item->data;
1277+
}
12351278

12361279

12371280
cbor_item_t * cbor_new_tag(uint64_t value)

src/cbor.h

+1
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ struct _cbor_array_metadata {
110110

111111
struct _cbor_map_metadata {
112112
size_t size;
113+
_cbor_dst_metadata type;
113114
};
114115

115116
/* cbor_item_metadata is 2 * sizeof(size_t) + sizeof(_cbor_string_type_metadata), lets use the space */

src/cbor_internal.c

+37-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#include <assert.h>
44
#include <string.h>
55
#include <math.h>
6-
#include <zlib.h>
76

87
// TODO asserts
98
// TODO check mallocs
@@ -106,6 +105,25 @@ void _cbor_builder_append(cbor_item_t * item, struct _cbor_decoder_context * ctx
106105
}
107106
break;
108107
}
108+
case CBOR_TYPE_MAP:
109+
{
110+
if (cbor_map_is_definite(ctx->stack->top->item)) {
111+
assert(ctx->stack->top->subitems > 0);
112+
if (ctx->stack->top->subitems % 2) {
113+
/* Even record, this is a key */
114+
cbor_map_add(ctx->stack->top->item, (struct cbor_pair){ .key = item, .value = NULL });
115+
} else {
116+
// TODO this is fugly
117+
cbor_map_handle(ctx->stack->top->item)[cbor_map_size(ctx->stack->top->item) - 1].value = item;
118+
}
119+
ctx->stack->top->subitems--;
120+
if (ctx->stack->top->subitems == 0) {
121+
cbor_item_t *item = ctx->stack->top->item;
122+
_cbor_stack_pop(ctx->stack);
123+
_cbor_builder_append(item, ctx);
124+
}
125+
}
126+
}
109127
case CBOR_TYPE_TAG:
110128
{
111129
assert(ctx->stack->top->subitems == 1);
@@ -291,6 +309,24 @@ enum cbor_callback_result cbor_builder_indef_array_start_callback(void * context
291309
return CBOR_CALLBACK_OK;
292310
}
293311

312+
enum cbor_callback_result cbor_builder_indef_map_start_callback(void * context)
313+
{
314+
struct _cbor_decoder_context * ctx = context;
315+
_cbor_stack_push(ctx->stack, cbor_new_indefinite_map(), 0);
316+
return CBOR_CALLBACK_OK;
317+
}
318+
319+
enum cbor_callback_result cbor_builder_map_start_callback(void * context, size_t size)
320+
{
321+
struct _cbor_decoder_context * ctx = context;
322+
if (size > 0) {
323+
_cbor_stack_push(ctx->stack, cbor_new_definite_map(size), size * 2);
324+
} else {
325+
_cbor_builder_append(cbor_new_definite_map(size), ctx);
326+
}
327+
return CBOR_CALLBACK_OK;
328+
}
329+
294330
enum cbor_callback_result cbor_builder_indef_break_callback(void * context)
295331
{
296332
struct _cbor_decoder_context * ctx = context;

src/cbor_internal.h

+3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ enum cbor_callback_result cbor_builder_byte_string_start_callback(void *);
3737
enum cbor_callback_result cbor_builder_array_start_callback(void *, size_t);
3838
enum cbor_callback_result cbor_builder_indef_array_start_callback(void *);
3939

40+
enum cbor_callback_result cbor_builder_map_start_callback(void *, size_t);
41+
enum cbor_callback_result cbor_builder_indef_map_start_callback(void *);
42+
4043
enum cbor_callback_result cbor_builder_tag_callback(void *, uint64_t);
4144

4245
enum cbor_callback_result cbor_builder_float2_callback(void *, float);

test/type_5_test.c

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#include <stdarg.h>
2+
#include <stddef.h>
3+
#include <setjmp.h>
4+
#include <cmocka.h>
5+
#include <stdio.h>
6+
#include "cbor.h"
7+
#include <inttypes.h>
8+
#include "assertions.h"
9+
10+
11+
cbor_item_t * map;
12+
struct cbor_load_result res;
13+
14+
unsigned char empty_map[] = { 0xA0 };
15+
static void test_empty_map(void **state)
16+
{
17+
map = cbor_load(empty_map, 1, CBOR_FLAGS_NONE, &res);
18+
assert_non_null(map);
19+
assert_true(cbor_typeof(map) == CBOR_TYPE_MAP);
20+
assert_true(cbor_isa_map(map));
21+
assert_true(cbor_map_size(map) == 0);
22+
assert_true(res.read == 1);
23+
cbor_decref(&map);
24+
assert_null(map);
25+
}
26+
27+
28+
int main(void) {
29+
const UnitTest tests[] = {
30+
unit_test(test_empty_map),
31+
};
32+
return run_tests(tests);
33+
}

0 commit comments

Comments
 (0)