librlp

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

commit 68af64b2767413d8fef74f3af7f210ee62ae450b
parent c825af3f0032fc453a1c4882abcfc215ccb1c51d
Author: nolash <dev@holbrook.no>
Date:   Mon, 12 Apr 2021 01:00:44 +0200

Add ascend report step in decode

Diffstat:
Msrc/decode.c | 79+++++++++++++++++++++++++++++--------------------------------------------------
Msrc/rlp.c | 16+++++++++-------
Msrc/rlp.h | 9++++-----
Mtests/check_decoder.c | 12++++++------
Mtests/check_vectors.c | 45++++++++++++++++++++++++++++++++++++++++-----
5 files changed, 88 insertions(+), 73 deletions(-)

diff --git a/src/decode.c b/src/decode.c @@ -6,12 +6,16 @@ static int process_state_token(rlp_encoder_t *encoder) { int len = 0; int lenlen = 0; - int r; unsigned char token; token = *encoder->ptr; - if (token >= 0xf7) { + if (encoder->ptr == encoder->list_ptr[encoder->depth]) { + encoder->depth--; + encoder->state = RLP_LIST_ASCEND; + len = 0; + + } else if (token >= 0xf7) { lenlen = token - 0xf7; encoder->ptr++; len = 0; @@ -19,24 +23,25 @@ static int process_state_token(rlp_encoder_t *encoder) { if (lenlen > 1 && is_le()) { to_endian(CONVERT_LITTLEENDIAN, lenlen, &len); } - encoder->list_ptr[encoder->depth] = (char*)&len; + encoder->depth++; encoder->ptr += lenlen; + encoder->buf = encoder->ptr; + encoder->list_ptr[encoder->depth] = encoder->buf + len; - r = encoder->depth; - encoder->depth++; - encoder->state = RLP_LIST; + encoder->state = RLP_LIST_DESCEND; } else if (token >= 0xc0) { len = token - 0xc0; if (is_le()) { to_endian(CONVERT_LITTLEENDIAN, sizeof(len), &len); } - encoder->list_ptr[encoder->depth] = (char*)&len; + encoder->depth++; encoder->ptr++; + encoder->buf = encoder->ptr; + encoder->list_ptr[encoder->depth] = encoder->buf + len; + + encoder->state = RLP_LIST_DESCEND; - r = encoder->depth; - encoder->depth++; - encoder->state = RLP_LIST; } else if (token >= 0xb7) { lenlen = token - 0xb7; encoder->ptr++; @@ -47,65 +52,39 @@ static int process_state_token(rlp_encoder_t *encoder) { } encoder->ptr += lenlen; - encoder->list_ptr[encoder->depth] = encoder->ptr; - r = encoder->depth; + encoder->buf = encoder->ptr; encoder->ptr += len; - encoder->depth--; encoder->state = RLP_STRING; + } else if (token >= 0x80) { len = token - 0x80; encoder->ptr++; - encoder->list_ptr[encoder->depth] = encoder->ptr; - r = encoder->depth; + encoder->buf = encoder->ptr; encoder->ptr += len; - encoder->depth--; encoder->state = RLP_STRING; + } else { encoder->list_ptr[encoder->depth] = encoder->ptr; - r = encoder->depth; + encoder->buf = encoder->ptr; encoder->ptr++; - encoder->depth--; + len = 1; encoder->state = RLP_STRING; } - - return r; -} - -static int assert_complete(rlp_encoder_t *encoder) { - int r = 0; - - if (encoder->ptr - encoder->buf < encoder->size) { - encoder->state = RLP_INCOMPLETE; - r = -1; - } else if (encoder->ptr - encoder->buf > encoder->size) { - encoder->state = RLP_OVERFLOW; - r = -1; - } else { - encoder->state = RLP_END; - } - return r; + + return len; } int rlp_next(rlp_encoder_t *encoder, int *zlen, char **zdest) { int r; - - if (encoder->depth == -1) { - return assert_complete(encoder); - } - r = process_state_token(encoder); - - switch (encoder->state) { - case RLP_LIST: - *zlen = *((int*)encoder->list_ptr[r]); - break; + if (encoder->list_ptr[0] == encoder->ptr) { + encoder->state = RLP_END; + return -1; + } - case RLP_STRING: - *zlen = encoder->ptr - encoder->list_ptr[r]; - break; - } - *zdest = encoder->list_ptr[r]; + *zlen = process_state_token(encoder); + *zdest = encoder->buf; return 0; } diff --git a/src/rlp.c b/src/rlp.c @@ -9,13 +9,15 @@ int rlp_init(rlp_encoder_t *encoder, int buffer_capacity, char *content) { encoder->alloc = 0; encoder->state = RLP_DECODE; encoder->size = buffer_capacity; - } else { + encoder->ptr = encoder->buf; + encoder->list_ptr[0] = encoder->buf + buffer_capacity; + } else { encoder->buf = malloc(buffer_capacity); encoder->alloc = 1; encoder->state = RLP_ENCODE; encoder->size = 0; + encoder->ptr = encoder->buf; } - encoder->ptr = encoder->buf; } void rlp_free(rlp_encoder_t *encoder) { @@ -25,8 +27,8 @@ void rlp_free(rlp_encoder_t *encoder) { encoder->ptr = NULL; } -int rlp_get(rlp_encoder_t *encoder, int *zl, char **zdest) { - *zdest = encoder->buf; - *zl = encoder->size; - return 0; -} +//int rlp_get(rlp_encoder_t *encoder, int *zl, char **zdest) { +// *zdest = encoder->buf; +// *zl = encoder->size; +// return 0; +//} diff --git a/src/rlp.h b/src/rlp.h @@ -14,11 +14,10 @@ enum rlp_state { RLP_DECODE, RLP_ENCODE, - RLP_LIST, + RLP_LIST_ASCEND, + RLP_LIST_DESCEND, RLP_STRING, RLP_END, - RLP_OVERFLOW, - RLP_INCOMPLETE, }; @@ -36,12 +35,12 @@ typedef struct rlp_encoder { int rlp_init(rlp_encoder_t *encoder, int buffer_capacity, char *content); void rlp_free(rlp_encoder_t *encoder); +// encode int rlp_descend(rlp_encoder_t *encoder); int rlp_ascend(rlp_encoder_t *encoder); int rlp_add(rlp_encoder_t *encoder, int len, const char *data); -size_t rlp_length(rlp_encoder_t *encoder); -int rlp_get(rlp_encoder_t *encoder, int *zl, char **zdest); +// decode int rlp_next(rlp_encoder_t *encoder, int *zl, char **zdest); #endif diff --git a/tests/check_decoder.c b/tests/check_decoder.c @@ -91,7 +91,7 @@ START_TEST(rlp_decode_zero_list_test) { char buf = 0; char *zbuf = (char*)&buf; - char state = RLP_LIST; + char state = RLP_LIST_DESCEND; rlp_encoder_t encoder; @@ -114,7 +114,7 @@ START_TEST(rlp_decode_short_list_test) { char buf[2]; char *zbuf = (char*)&buf; - char state = RLP_LIST; + char state = RLP_LIST_DESCEND; rlp_encoder_t encoder; @@ -141,7 +141,7 @@ START_TEST(rlp_decode_long_list_test) { char buf[56]; char *zbuf = (char*)&buf; - char state = RLP_LIST; + char state = RLP_LIST_DESCEND; rlp_encoder_t encoder; @@ -160,7 +160,7 @@ START_TEST(rlp_decode_adjacent_strings_test) { int l; int r; - char s[] = {0x83, 0x66, 0x6f, 0x6f, 0x84, 0x62, 0x61, 0x72, 0x0a}; + char s[] = {0x83, 0x66, 0x6f, 0x6f, 0x84, 0x62, 0x61, 0x72, 0x00}; char state = RLP_STRING; @@ -174,12 +174,12 @@ START_TEST(rlp_decode_adjacent_strings_test) { ck_assert_mem_eq(&encoder.state, &state, 1); ck_assert_int_eq(r, 0); ck_assert_int_eq(l, 3); + ck_assert_mem_eq(zbuf, "foo", 3); r = rlp_next(&encoder, &l, &zbuf); - ck_assert_mem_eq(&encoder.state, &state, 1); + ck_assert_mem_eq(&encoder.state, &state, 1); // fail because every string process decrements depth, should only at end of list ck_assert_int_eq(r, 0); ck_assert_int_eq(l, 4); - ck_assert_mem_eq(zbuf, "foo", 3); ck_assert_mem_eq(zbuf, "bar\0", 4); } END_TEST diff --git a/tests/check_vectors.c b/tests/check_vectors.c @@ -56,7 +56,7 @@ START_TEST(rlp_catdog_test) { ck_assert_int_eq(encoder.size, 9); // reuse for decode - state = RLP_LIST; + state = RLP_LIST_DESCEND; rlp_init(&encoder, 9, encoder.buf); rlp_next(&encoder, &l, &zbuf); ck_assert_mem_eq(&encoder.state, &state, 1); @@ -115,11 +115,46 @@ END_TEST START_TEST(rlp_set_theoretical_representation_of_three) { unsigned char target[8] = {0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0}; + int target_lengths[15] = { + 7, + 0, + 0, + 1, + 0, + 0, + 0, + 3, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + }; + + enum rlp_state target_states[15] = { + RLP_LIST_DESCEND, + RLP_LIST_DESCEND, + RLP_LIST_ASCEND, + RLP_LIST_DESCEND, + RLP_LIST_DESCEND, + RLP_LIST_ASCEND, + RLP_LIST_ASCEND, + RLP_LIST_DESCEND, + RLP_LIST_DESCEND, + RLP_LIST_ASCEND, + RLP_LIST_DESCEND, + RLP_LIST_DESCEND, + RLP_LIST_ASCEND, + RLP_LIST_ASCEND, + RLP_LIST_ASCEND, + }; char *zbuf = NULL; int i; int l; - char state = RLP_LIST; + char state = RLP_LIST_ASCEND; rlp_encoder_t encoder; @@ -151,10 +186,10 @@ START_TEST(rlp_set_theoretical_representation_of_three) { ck_assert_int_eq(encoder.size, 8); rlp_init(&encoder, 1024, encoder.buf); - for (i = 0; i < sizeof(target); i++) { + for (i = 0; i < 15; i++) { rlp_next(&encoder, &l, &zbuf); - ck_assert_mem_eq(&encoder.state, &state, 1); - ck_assert_int_eq(l, target[i] - 0xc0); + ck_assert_int_eq(target_states[i], encoder.state); + ck_assert_int_eq(target_lengths[i], l); } rlp_free(&encoder);