commit 66047667307d534d0586c30c322698f9aee2b797
parent b300a936f4160a780164f9efd1dc06b2d8136ce6
Author: nolash <dev@holbrook.no>
Date: Sat, 10 Apr 2021 12:46:19 +0200
Add multi byte type add
Diffstat:
11 files changed, 342 insertions(+), 4 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,10 +1,14 @@
build:
gcc -I./src -g3 -c src/rlp.c -o src/rlp.o
+ gcc -I./src -g3 -c src/bits.c -o src/bits.o
+ gcc -I./src -g3 -c src/endian.c -o src/endian.o
tests_build: build
- gcc -I./src -g3 tests/check_rlp.c src/rlp.o -o tests/check_rlp -lcheck
+ gcc -I./src -g3 tests/check_rlp.c src/bits.o src/rlp.o src/endian.o -o tests/check_rlp -lcheck
+ gcc -I./src -g3 tests/check_bits.c src/bits.o src/rlp.o src/endian.o -o tests/check_bits -lcheck
check: tests_build
tests/check_rlp
+ tests/check_bits
.PHONY test: check
diff --git a/src/bits.c b/src/bits.c
@@ -0,0 +1,30 @@
+
+int intbits_le(int len, char *n) {
+ char ri = 0;
+ char ry = 0;
+ char i = 0;
+
+ if (len == 0) {
+ return 0;
+ }
+
+ for (int b = 0; b < len; b++) {
+ for (i = 0; i < 8; i++) {
+ if (((1 << i) & *(n + b)) > 0) {
+ ri = i + 1;
+ ry = b;
+ }
+ }
+ }
+
+ if (ri == 0 && ry == 0) {
+ ri = 1;
+ }
+
+ return ri + (ry * 8);
+}
+
+int intbytes_le(int len, char *n) {
+ int r = intbits_le(len, n);
+ return (r - 1) / 8 + 1;
+}
diff --git a/src/bits.h b/src/bits.h
@@ -0,0 +1,7 @@
+#ifndef LASH_BITS_H_
+#define LASH_BITS_H_
+
+char intbits_le(int len, char *n);
+char intbytes_le(int len, char *n);
+
+#endif
diff --git a/src/endian.c b/src/endian.c
@@ -0,0 +1,44 @@
+#include "endian.h"
+
+int is_le() {
+ short s = 42;
+ return *((unsigned char*)&s) == 42;
+}
+
+// convert unsigned integer to little-endian representation
+int to_endian(char direction, int l, void *n) {
+ union le un;
+
+ if (l == 1 || is_le() == direction) {
+ return 0;
+ }
+ switch(l) {
+ case sizeof(long long):
+ un.ll = (long long*)n;
+ break;
+ case sizeof(int):
+ un.i = (int*)n;
+ break;
+ case sizeof(short):
+ un.s = (short*)n;
+ break;
+ default:
+ un.c = (char*)n;
+ }
+ flip_endian(l, &un);
+
+ return 0;
+}
+
+void flip_endian(int l, union le *n) {
+ int i;
+ char t;
+ char *ne;
+
+ ne = (n->c)+(l-1);
+ for (i = 0; i < l/2; i++) {
+ t = *(n->c+i);
+ *((n->c)+i) = *(ne-i);
+ *(ne-i) = t;
+ }
+}
diff --git a/src/endian.h b/src/endian.h
@@ -0,0 +1,20 @@
+#ifndef LASH_ENDIAN_H_
+#define LASH_ENDIAN_H_
+
+#define CONVERT_BIGENDIAN 0x00
+#define CONVERT_LITTLEENDIAN 0x01
+#define CONVERT_PLATFORM is_le()
+
+union le {
+ short *s;
+ int *i;
+ long long *ll;
+ char *c;
+};
+
+int le(int l, void *n);
+int is_le();
+int to_endian(char direction, int l, void *n);
+void flip_endian(int l, union le *n);
+
+#endif // LASH_ENDIAN_H_
diff --git a/src/rlp.c b/src/rlp.c
@@ -1,13 +1,57 @@
#include <stdint.h>
#include <stdlib.h>
+#include <string.h>
#include "rlp.h"
+#include "bits.h"
+#include "endian.h"
int rlp_init(rlp_encoder_t *encoder, int buffer_capacity) {
- encoder->data_buf = malloc(buffer_capacity);
+ encoder->buf = malloc(buffer_capacity);
encoder->depth = 0;
+ encoder->ptr = encoder->buf;
}
void rlp_free(rlp_encoder_t *encoder) {
- free(encoder->data_buf);
+ free(encoder->buf);
+ encoder->ptr = NULL;
}
+
+
+int rlp_add(rlp_encoder_t *encoder, int len, char *data) {
+ char v;
+ int lenlen;
+ size_t r;
+
+ r = (size_t)encoder->ptr;
+
+ if (len == 0) {
+ *(encoder->ptr) = 0x80;
+ encoder->ptr++;
+ } else {
+ v = (char)*data;
+ if (len == 1 && v < 56) {
+ *(encoder->ptr) = v;
+ encoder->ptr++;
+ } else {
+ v = (char)*data;
+ if (len < 56) {
+ *(encoder->ptr) = len + 0x80;
+ encoder->ptr++;
+ memcpy(encoder->ptr, data, len);
+ encoder->ptr += len;
+ } else {
+ lenlen = intbytes_le(sizeof(int), (char*)&len);
+ *(encoder->ptr) = lenlen + 0xb7;
+ encoder->ptr++;
+ to_endian(CONVERT_BIGENDIAN, lenlen, &len);
+ memcpy(encoder->ptr, &len, lenlen);
+ to_endian(CONVERT_PLATFORM, lenlen, &len);
+ encoder->ptr+=lenlen;
+ memcpy(encoder->ptr, data, len);
+ encoder->ptr+=len;
+ }
+ }
+ }
+ return (int)(r - (size_t)encoder->ptr);
+}
diff --git a/src/rlp.h b/src/rlp.h
@@ -8,7 +8,9 @@
typedef struct rlp_encoder {
uint32_t depth;
uint32_t list_buf[RLP_MAX_LIST_DEPTH];
- char *data_buf;
+ char *buf;
+ char *ptr;
+
} rlp_encoder_t;
int rlp_init(rlp_encoder_t *encoder, int buffer_capacity);
diff --git a/tests/check_bits b/tests/check_bits
Binary files differ.
diff --git a/tests/check_bits.c b/tests/check_bits.c
@@ -0,0 +1,86 @@
+#include <check.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "bits.h"
+
+START_TEST(le_test) {
+ char v[10];
+ int r;
+
+ memset(v, 0, 10);
+
+ r = intbits_le(0, NULL);
+ ck_assert_int_eq(r, 0);
+
+ r = intbits_le(10, (char*)v);
+ ck_assert_int_eq(r, 1);
+
+ v[0] = 2;
+ r = intbits_le(10, (char*)v);
+ ck_assert_int_eq(r, 2);
+
+ v[1] = 2;
+ r = intbits_le(10, v);
+ ck_assert_int_eq(r, 10);
+ r = intbytes_le(10, v);
+ ck_assert_int_eq(r, 2);
+
+ v[9] = 7;
+ r = intbits_le(10, v);
+ ck_assert_int_eq(r, 75);
+ r = intbytes_le(10, v);
+ ck_assert_int_eq(r, 10);
+}
+END_TEST
+
+
+START_TEST(le_boundary_test) {
+ char v[10];
+ int r;
+
+ memset(v, 0, 10);
+
+
+ v[1] = 0x80;
+ r = intbytes_le(10, v);
+ ck_assert_int_eq(r, 2);
+
+ v[2] = 0x01;
+ r = intbytes_le(10, v);
+ ck_assert_int_eq(r, 3);
+
+}
+END_TEST
+
+
+Suite *bits_suite(void) {
+ Suite *s;
+ TCase *tc;
+
+ s = suite_create("Rlp");
+ tc = tcase_create("Init");
+
+ tcase_add_test(tc, le_test);
+ tcase_add_test(tc, le_boundary_test);
+ suite_add_tcase(s, tc);
+
+ return s;
+}
+
+
+int main(void) {
+ int num_fail;
+
+ Suite *s;
+ SRunner *sr;
+
+ s = bits_suite();
+ sr = srunner_create(s);
+
+ srunner_run_all(sr, CK_VERBOSE);
+ num_fail = srunner_ntests_failed(sr);
+ srunner_free(sr);
+
+ return (num_fail == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
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
@@ -7,8 +7,102 @@ START_TEST(rlp_init_test) {
rlp_encoder_t encoder;
rlp_init(&encoder, 1024);
+
rlp_free(&encoder);
+}
+END_TEST
+
+
+START_TEST(rlp_encode_single_zero_byte_test) {
+ char v = 0x00;
+
+ rlp_encoder_t encoder;
+ rlp_init(&encoder, 1024);
+ rlp_add(&encoder, 1, &v);
+ ck_assert_mem_eq(encoder.buf, &v, 1);
+
+ rlp_free(&encoder);
+}
+END_TEST
+
+
+START_TEST(rlp_encode_empty_byte_test) {
+ char v = 0x80;
+
+ rlp_encoder_t encoder;
+ rlp_init(&encoder, 1024);
+
+ rlp_add(&encoder, 0, NULL);
+ ck_assert_mem_eq(encoder.buf, &v, 1);
+
+ rlp_free(&encoder);
+}
+END_TEST
+
+
+START_TEST(rlp_encode_single_byte_test) {
+ char v = 55;
+
+ rlp_encoder_t encoder;
+ rlp_init(&encoder, 1024);
+
+ rlp_add(&encoder, 1, &v);
+ ck_assert_mem_eq(encoder.buf, &v, 1);
+
+ rlp_free(&encoder);
+}
+END_TEST
+
+
+START_TEST(rlp_encode_single_byte_with_length_test) {
+ char l = 0x81;
+ char v = 56;
+
+ rlp_encoder_t encoder;
+ rlp_init(&encoder, 1024);
+
+ rlp_add(&encoder, 1, &v);
+ ck_assert_mem_eq(encoder.buf, &l, 1);
+ ck_assert_mem_eq(encoder.buf+1, &v, 1);
+
+ rlp_free(&encoder);
+}
+END_TEST
+
+
+START_TEST(rlp_encode_short_bytes_with_length_test) {
+ char l = 0xb7;
+ char v[55];
+ v[54] = 42;
+
+ rlp_encoder_t encoder;
+ rlp_init(&encoder, 1024);
+
+ rlp_add(&encoder, 55, (char*)&v);
+ ck_assert_mem_eq(encoder.buf, &l, 1);
+ ck_assert_mem_eq(encoder.buf+55, (char*)&(v[54]), 1);
+
+ rlp_free(&encoder);
+}
+END_TEST
+
+
+START_TEST(rlp_encode_long_bytes_with_length_test) {
+ char l = 0xb8;
+ char ll = 56;
+ char v[56];
+ v[55] = 42;
+
+ rlp_encoder_t encoder;
+ rlp_init(&encoder, 1024);
+
+ rlp_add(&encoder, 56, (char*)&v);
+ ck_assert_mem_eq(encoder.buf, &l, 1);
+ ck_assert_mem_eq(encoder.buf+1, &ll, 1);
+ ck_assert_mem_eq(encoder.buf+57, (char*)&(v[55]), 1);
+
+ rlp_free(&encoder);
}
END_TEST
@@ -20,11 +114,18 @@ Suite *rlp_suite(void) {
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);
return s;
}
+
int main(void) {
int num_fail;