librlp

C library for the Recursive Length Prefix (RLP) serialization format
git clone git://git.defalsify.org/librlp.git
Log | Files | Refs | LICENSE

commit 321d42e146f8efb3369f62ec4b6884668bc54d70
parent 66047667307d534d0586c30c322698f9aee2b797
Author: nolash <dev@holbrook.no>
Date:   Sat, 10 Apr 2021 13:38:29 +0200

Add single length prefix list

Diffstat:
Msrc/rlp.c | 43+++++++++++++++++++++++++++++++++++++++++--
Msrc/rlp.h | 5+++--
Mtests/check_bits | 0
Mtests/check_rlp | 0
Mtests/check_rlp.c | 124++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
5 files changed, 157 insertions(+), 15 deletions(-)

diff --git a/src/rlp.c b/src/rlp.c @@ -8,7 +8,7 @@ int rlp_init(rlp_encoder_t *encoder, int buffer_capacity) { encoder->buf = malloc(buffer_capacity); - encoder->depth = 0; + encoder->depth = -1; encoder->ptr = encoder->buf; } @@ -23,6 +23,10 @@ int rlp_add(rlp_encoder_t *encoder, int len, char *data) { int lenlen; size_t r; + if (list_register(encoder) < 0) { + return -1; + } + r = (size_t)encoder->ptr; if (len == 0) { @@ -53,5 +57,40 @@ int rlp_add(rlp_encoder_t *encoder, int len, char *data) { } } } + return (int)(r - (size_t)encoder->ptr); -} +} + +int rlp_descend(rlp_encoder_t *encoder, uint32_t num_items) { + encoder->depth++; +// memcpy(&encoder->list_buf[encoder->depth], &num_items, sizeof(uint32_t)); + encoder->list_buf[encoder->depth] = num_items + 1; + if (num_items < 56) { + *(encoder->ptr) = 0xc0 + num_items; + encoder->ptr++; + } + return encoder->depth + 1; +} + +static int list_register(rlp_encoder_t *encoder) { + if (encoder->depth == -1) { + return 0; + } + encoder->list_buf[encoder->depth]--; + if (encoder->list_buf[encoder->depth] < 0) { + return -1; + } else if (encoder->list_buf[encoder->depth] == 0) { + encoder->depth--; + } + return encoder->depth + 1; +} + +int rlp_finish(rlp_encoder_t *encoder) { + while (encoder->depth > -1) { + if (encoder->list_buf[encoder->depth] > 1) { + return -1; + } + list_register(encoder); + } + return 0; +} diff --git a/src/rlp.h b/src/rlp.h @@ -6,7 +6,7 @@ #define RLP_MAX_LIST_DEPTH 1024 typedef struct rlp_encoder { - uint32_t depth; + int depth; uint32_t list_buf[RLP_MAX_LIST_DEPTH]; char *buf; char *ptr; @@ -17,7 +17,8 @@ int rlp_init(rlp_encoder_t *encoder, int buffer_capacity); void rlp_free(rlp_encoder_t *encoder); int rlp_descend(rlp_encoder_t *encoder, uint32_t num_items); -static int rlp_ascend(rlp_encoder_t *encoder); +static int list_register(rlp_encoder_t *encoder); int rlp_add(rlp_encoder_t *encoder, int len, char *data); +int rlp_finish(rlp_encoder_t *encoder); #endif diff --git a/tests/check_bits b/tests/check_bits Binary files differ. diff --git a/tests/check_rlp b/tests/check_rlp Binary files differ. diff --git a/tests/check_rlp.c b/tests/check_rlp.c @@ -106,21 +106,123 @@ START_TEST(rlp_encode_long_bytes_with_length_test) { } END_TEST + +START_TEST(rlp_encode_list_descend_state_test) { + //char one = 42; + //char two = 13; + int r; + + rlp_encoder_t encoder; + rlp_init(&encoder, 1024); + + r = rlp_descend(&encoder, 2); + ck_assert_int_eq(1, r); + ck_assert_int_eq(encoder.depth, 0); + ck_assert_int_eq(encoder.list_buf[0], 3); + + r = rlp_descend(&encoder, 4); + ck_assert_int_eq(2, r); + ck_assert_int_eq(encoder.depth, 1); + ck_assert_int_eq(encoder.list_buf[1], 5); + + rlp_free(&encoder); +} +END_TEST + + +START_TEST(rlp_encode_list_roundtrip_state_test) { + char one = 42; + char two = 13; + int r; + + rlp_encoder_t encoder; + rlp_init(&encoder, 1024); + + r = rlp_descend(&encoder, 2); + rlp_add(&encoder, 1, &one); + rlp_add(&encoder, 1, &two); + ck_assert_int_eq(encoder.depth, 0); + ck_assert_int_eq(encoder.list_buf[0], 1); + + r = rlp_finish(&encoder); + ck_assert_int_eq(r, 0); + ck_assert_int_eq(encoder.depth, -1); + ck_assert_int_eq(encoder.list_buf[0], 0); + + rlp_free(&encoder); +} +END_TEST + + +START_TEST(rlp_encode_list_single_depth_test) { + char one = 42; + char two = 13; + char target[3] = {0xc2, 42, 13}; + int r; + + rlp_encoder_t encoder; + rlp_init(&encoder, 1024); + + r = rlp_descend(&encoder, 2); + rlp_add(&encoder, 1, &one); + rlp_add(&encoder, 1, &two); + ck_assert_mem_eq(encoder.buf, target, 3); + + rlp_free(&encoder); +} +END_TEST + + +START_TEST(rlp_encode_list_two_depth_test) { + char one[2] = {42, 13}; + char two[3] = {0x66, 0x6f, 0x6f}; + char target[8] = {0xc2, 42, 13, 0xc1, 0x83, 0x66, 0x6f, 0x6f}; + int r; + + rlp_encoder_t encoder; + rlp_init(&encoder, 1024); + + r = rlp_descend(&encoder, 2); + rlp_add(&encoder, 1, &one[0]); + rlp_add(&encoder, 1, &one[1]); + r = rlp_descend(&encoder, 1); + rlp_add(&encoder, 3, two); + ck_assert_mem_eq(encoder.buf, target, 8); + + r = rlp_finish(&encoder); + ck_assert_int_eq(r, 0); + + rlp_free(&encoder); +} +END_TEST + Suite *rlp_suite(void) { Suite *s; - TCase *tc; + TCase *tci; + TCase *tcb; + TCase *tcl; s = suite_create("Rlp"); - tc = tcase_create("Init"); - - tcase_add_test(tc, rlp_init_test); - tcase_add_test(tc, rlp_encode_empty_byte_test); - tcase_add_test(tc, rlp_encode_single_zero_byte_test); - tcase_add_test(tc, rlp_encode_single_byte_test); - tcase_add_test(tc, rlp_encode_single_byte_with_length_test); - tcase_add_test(tc, rlp_encode_short_bytes_with_length_test); - tcase_add_test(tc, rlp_encode_long_bytes_with_length_test); - suite_add_tcase(s, tc); + tci = tcase_create("Init"); + tcb = tcase_create("Bytes"); + tcl = tcase_create("List"); + + tcase_add_test(tci, rlp_init_test); + suite_add_tcase(s, tci); + + tcase_add_test(tcb, rlp_encode_empty_byte_test); + tcase_add_test(tcb, rlp_encode_single_zero_byte_test); + tcase_add_test(tcb, rlp_encode_single_byte_test); + tcase_add_test(tcb, rlp_encode_single_byte_with_length_test); + tcase_add_test(tcb, rlp_encode_short_bytes_with_length_test); + tcase_add_test(tcb, rlp_encode_long_bytes_with_length_test); + suite_add_tcase(s, tcb); + + tcase_add_test(tcl, rlp_encode_list_descend_state_test); + tcase_add_test(tcl, rlp_encode_list_roundtrip_state_test); + tcase_add_test(tcl, rlp_encode_list_single_depth_test); + tcase_add_test(tcl, rlp_encode_list_two_depth_test); + suite_add_tcase(s, tcl); return s; }