From f3dfe21ec5dde5f914e6589426395c35aeac7a3e Mon Sep 17 00:00:00 2001 From: Juri Glass Date: Thu, 14 Jul 2011 21:39:33 +0200 Subject: [PATCH] added sml_value_write, refactored sml_value_parse --- sml/src/sml_value.c | 97 +++++++++++++-------------------------- test/src/sml_value_test.c | 66 ++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 65 deletions(-) diff --git a/sml/src/sml_value.c b/sml/src/sml_value.c index bd5e2d4..22278e1 100644 --- a/sml/src/sml_value.c +++ b/sml/src/sml_value.c @@ -22,11 +22,12 @@ #include sml_value *sml_value_parse(sml_buffer *buf) { + int max = 1; int type = sml_buf_get_next_type(buf); unsigned char byte = sml_buf_get_current_byte(buf); sml_value *value = (sml_value *) malloc(sizeof(sml_value)); - value->type = type; + value->type = type; switch (type) { case SML_TYPE_OCTET_STRING: @@ -36,63 +37,14 @@ sml_value *sml_value_parse(sml_buffer *buf) { value->data.boolean = sml_boolean_parse(buf); break; case SML_TYPE_UNSIGNED: - switch (byte & SML_LENGTH_FIELD) { - case SML_TYPE_NUMBER_8: - value->data.uint8 = sml_u8_parse(buf); - value->type |= SML_TYPE_NUMBER_8; - break; - case SML_TYPE_NUMBER_16: - value->data.uint16 = sml_u16_parse(buf); - value->type |= SML_TYPE_NUMBER_16; - break; - case SML_TYPE_NUMBER_16 + 1: - case SML_TYPE_NUMBER_32: - value->data.uint32 = sml_u32_parse(buf); - value->type |= SML_TYPE_NUMBER_32; - break; - case SML_TYPE_NUMBER_32 + 1: - case SML_TYPE_NUMBER_32 + 2: - case SML_TYPE_NUMBER_32 + 3: - case SML_TYPE_NUMBER_64: - value->data.uint64 = sml_u64_parse(buf); - value->type |= SML_TYPE_NUMBER_64; - break; - default: - buf->error = 1; - break; - } - break; - case SML_TYPE_INTEGER: - //switch (byte & SML_LENGTH_FIELD) { - // Integer 59 00 00 00 00 00 01 20 09 could'nt be evaluated cause (byte & SML_LENGTH_FIELD)=9 - // but 8 is maximum :( -> now it's working - // TODO: check if same problem exists for other SML_TYPEs too - switch ((byte & SML_LENGTH_FIELD)-1) { - case SML_TYPE_NUMBER_8: - value->data.int8 = sml_i8_parse(buf); - value->type |= SML_TYPE_NUMBER_8; - break; - case SML_TYPE_NUMBER_16: - value->data.int16 = sml_i16_parse(buf); - value->type |= SML_TYPE_NUMBER_16; - break; - case SML_TYPE_NUMBER_16 + 1: - case SML_TYPE_NUMBER_32: - value->data.int32 = sml_i32_parse(buf); - value->type |= SML_TYPE_NUMBER_32; - break; - case SML_TYPE_NUMBER_32 + 1: - case SML_TYPE_NUMBER_32 + 2: - case SML_TYPE_NUMBER_32 + 3: - case SML_TYPE_NUMBER_64: - value->data.int64 = sml_i64_parse(buf); - value->type |= SML_TYPE_NUMBER_64; - break; - default: - buf->error = 1; - break; + // get maximal size, if not all bytes are used (example: only 6 bytes for a u64) + while (max < ((byte & SML_LENGTH_FIELD) - 1)) { + max <<= 1; } + + value->data.uint8 = sml_number_parse(buf, type, max); + value->type |= max; break; default: buf->error = 1; @@ -107,19 +59,34 @@ sml_value *sml_value_parse(sml_buffer *buf) { } void sml_value_write(sml_value *value, sml_buffer *buf) { - if (value->type == SML_TYPE_BOOLEAN) { - sml_boolean_write(value->data.boolean, buf); - } + if (value == 0) { + sml_buf_optional_write(buf); + return; + } + + switch (value->type & SML_TYPE_FIELD) { + case SML_TYPE_OCTET_STRING: + sml_octet_string_write(value->data.bytes, buf); + break; + case SML_TYPE_BOOLEAN: + sml_boolean_write(value->data.boolean, buf); + break; + case SML_TYPE_UNSIGNED: + case SML_TYPE_INTEGER: + sml_number_write(value->data.uint8, (value->type & SML_TYPE_FIELD), + (value->type & SML_LENGTH_FIELD), buf); + break; + } } sml_value *sml_value_init() { - sml_value *value = (sml_value *) malloc(sizeof(sml_value)); - memset(value, 0, sizeof(value)); - return value; + sml_value *value = (sml_value *) malloc(sizeof(sml_value)); + memset(value, 0, sizeof(value)); + return value; } void sml_value_free(sml_value *value) { - if (value) { + if (value) { switch (value->type) { case SML_TYPE_OCTET_STRING: sml_octet_string_free(value->data.bytes); @@ -131,7 +98,7 @@ void sml_value_free(sml_value *value) { sml_number_free(value->data.int8); break; } - free(value); - } + free(value); + } } diff --git a/test/src/sml_value_test.c b/test/src/sml_value_test.c index cb269ba..e53ef42 100644 --- a/test/src/sml_value_test.c +++ b/test/src/sml_value_test.c @@ -55,8 +55,74 @@ TEST(sml_value, parse_boolean) { TEST_ASSERT_FALSE(*(v->data.boolean)); } +TEST(sml_value, parse_unsigned32) { + hex2binary("6500000001", sml_buf_get_current_buf(buf)); + sml_value *v = sml_value_parse(buf); + + TEST_ASSERT_NOT_NULL(v); + TEST_ASSERT_EQUAL(1, *(v->data.uint32)); + TEST_ASSERT_EQUAL((SML_TYPE_UNSIGNED | SML_TYPE_NUMBER_32), v->type); + +} + +TEST(sml_value, parse_integer64_fewer_bytes) { + hex2binary("58FFFFFFFFFFFF0F", sml_buf_get_current_buf(buf)); + sml_value *v = sml_value_parse(buf); + + TEST_ASSERT_EQUAL(-241, *(v->data.int64)); + TEST_ASSERT_EQUAL((SML_TYPE_INTEGER | SML_TYPE_NUMBER_64), v->type); +} + +TEST(sml_value, write_octet_string) { + sml_value *v = sml_value_init(); + v->type = SML_TYPE_OCTET_STRING; + v->data.bytes = sml_octet_string_init((unsigned char *)"Hallo", 5); + + sml_value_write(v, buf); + expected_buf(buf, "0648616C6C6F", 6); +} + +TEST(sml_value, write_boolean) { + sml_value *v = sml_value_init(); + v->type = SML_TYPE_BOOLEAN; + v->data.boolean = sml_boolean_init(SML_BOOLEAN_FALSE); + + sml_value_write(v, buf); + expected_buf(buf, "4200", 2); +} + +TEST(sml_value, write_unsigned32) { + sml_value *v = sml_value_init(); + v->type = SML_TYPE_UNSIGNED | SML_TYPE_NUMBER_32; + v->data.uint32 = sml_u32_init(42); + + sml_value_write(v, buf); + expected_buf(buf, "650000002A", 5); +} + +TEST(sml_value, write_integer16) { + sml_value *v = sml_value_init(); + v->type = SML_TYPE_INTEGER | SML_TYPE_NUMBER_16; + v->data.int16 = sml_i16_init(-5); + + sml_value_write(v, buf); + expected_buf(buf, "53FFFB", 3); +} + +TEST(sml_value, write_optional) { + sml_value_write(0, buf); + expected_buf(buf, "01", 1); +} + TEST_GROUP_RUNNER(sml_value) { RUN_TEST_CASE(sml_value, init); RUN_TEST_CASE(sml_value, parse_octet_string); RUN_TEST_CASE(sml_value, parse_boolean); + RUN_TEST_CASE(sml_value, parse_unsigned32); + RUN_TEST_CASE(sml_value, parse_integer64_fewer_bytes); + RUN_TEST_CASE(sml_value, write_octet_string); + RUN_TEST_CASE(sml_value, write_boolean); + RUN_TEST_CASE(sml_value, write_unsigned32); + RUN_TEST_CASE(sml_value, write_integer16); + RUN_TEST_CASE(sml_value, write_optional); }