diff --git a/sml/include/sml/sml_number.h b/sml/include/sml/sml_number.h index e6970cf..1f93762 100644 --- a/sml/include/sml/sml_number.h +++ b/sml/include/sml/sml_number.h @@ -30,16 +30,16 @@ extern "C" { // Parses a number. Identified by type (SML_TYPE_INTEGER or SML_TYPE_UNSIGNED) // and maximal number of bytes (SML_TYPE_NUMBER_8, SML_TYPE_NUMBER_16, // SML_TYPE_NUMBER_32, SML_TYPE_NUMBER_64) -u64 sml_number_parse(sml_buffer *buf, unsigned char type, int max_size); +void *sml_number_parse(sml_buffer *buf, unsigned char type, int max_size); -#define sml_u8_parse(buf) (u8) sml_number_parse(buf, SML_TYPE_UNSIGNED, SML_TYPE_NUMBER_8) -#define sml_u16_parse(buf) (u16) sml_number_parse(buf, SML_TYPE_UNSIGNED, SML_TYPE_NUMBER_16) -#define sml_u32_parse(buf) (u32) sml_number_parse(buf, SML_TYPE_UNSIGNED, SML_TYPE_NUMBER_32) -#define sml_u64_parse(buf) (u64) sml_number_parse(buf, SML_TYPE_UNSIGNED, SML_TYPE_NUMBER_64) -#define sml_i8_parse(buf) (i8) sml_number_parse(buf, SML_TYPE_INTEGER, SML_TYPE_NUMBER_8) -#define sml_i16_parse(buf) (i16) sml_number_parse(buf, SML_TYPE_INTEGER, SML_TYPE_NUMBER_16) -#define sml_i32_parse(buf) (i32) sml_number_parse(buf, SML_TYPE_INTEGER, SML_TYPE_NUMBER_32) -#define sml_i64_parse(buf) (i64) sml_number_parse(buf, SML_TYPE_INTEGER, SML_TYPE_NUMBER_64) +#define sml_u8_parse(buf) (u8 *) sml_number_parse(buf, SML_TYPE_UNSIGNED, SML_TYPE_NUMBER_8) +#define sml_u16_parse(buf) (u16 *) sml_number_parse(buf, SML_TYPE_UNSIGNED, SML_TYPE_NUMBER_16) +#define sml_u32_parse(buf) (u32 *) sml_number_parse(buf, SML_TYPE_UNSIGNED, SML_TYPE_NUMBER_32) +#define sml_u64_parse(buf) (u64 *) sml_number_parse(buf, SML_TYPE_UNSIGNED, SML_TYPE_NUMBER_64) +#define sml_i8_parse(buf) (i8 *) sml_number_parse(buf, SML_TYPE_INTEGER, SML_TYPE_NUMBER_8) +#define sml_i16_parse(buf) (i16 *) sml_number_parse(buf, SML_TYPE_INTEGER, SML_TYPE_NUMBER_16) +#define sml_i32_parse(buf) (i32 *) sml_number_parse(buf, SML_TYPE_INTEGER, SML_TYPE_NUMBER_32) +#define sml_i64_parse(buf) (i64 *) sml_number_parse(buf, SML_TYPE_INTEGER, SML_TYPE_NUMBER_64) void sml_number_write(unsigned char type, int size, u64 value, sml_buffer *buf); diff --git a/sml/src/sml_number.c b/sml/src/sml_number.c index 89c0068..04ee4f3 100644 --- a/sml/src/sml_number.c +++ b/sml/src/sml_number.c @@ -21,10 +21,21 @@ #include #include -u64 sml_number_parse(sml_buffer *buf, unsigned char type, int max_size) { +#define SML_BIG_ENDIAN 1 +#define SML_LITTLE_ENDIAN 0 + +int sml_number_endian(); +void sml_number_byte_swap(unsigned char *bytes, int bytes_len); + +void *sml_number_parse(sml_buffer *buf, unsigned char type, int max_size) { + if (sml_buf_optional_is_skipped(buf)) { + return 0; + } + int l, i; unsigned char b; - u64 n = 0; + short negative_int = 0; + if (sml_buf_get_next_type(buf) != type) { buf->error = 1; return 0; @@ -36,26 +47,28 @@ u64 sml_number_parse(sml_buffer *buf, unsigned char type, int max_size) { return 0; } + unsigned char *np = malloc(max_size); + memset(np, 0, max_size); + b = sml_buf_get_current_byte(buf); - // negative value with leading 1's - if (type == SML_TYPE_INTEGER && b & 128) { - n =~ n; - b = 0xFF; - for (i = 0; i < l; i++) { - n <<= 8; - n |= b; - n = (n & ~b) | sml_buf_get_current_byte(buf); - sml_buf_update_bytes_read(buf, 1); + if (type == SML_TYPE_INTEGER && (b & 128)) { + negative_int = 1; + } + + int missing_bytes = max_size - l; + memcpy(&(np[missing_bytes]), sml_buf_get_current_buf(buf), l); + + if (negative_int) { + for (i = 0; i < missing_bytes; i++) { + np[i] = 0xFF; } } - else { - for (i = 0; i < l; i++) { - n <<= 8; - n |= sml_buf_get_current_byte(buf); - sml_buf_update_bytes_read(buf, 1); - } + + if (!(sml_number_endian() == SML_BIG_ENDIAN)) { + sml_number_byte_swap(np, max_size); } - return n; + + return np; } void sml_number_write(unsigned char type, int size, u64 value, sml_buffer *buf) { @@ -70,3 +83,23 @@ void sml_number_write(unsigned char type, int size, u64 value, sml_buffer *buf) } buf->cursor += size; } + +void sml_number_byte_swap(unsigned char *bytes, int bytes_len) { + int i; + unsigned char ob[bytes_len]; + memcpy(&ob, bytes, bytes_len); + for (i = 0; i < bytes_len; i++) { + bytes[i] = ob[bytes_len - (i + 1)]; + } +} + +int sml_number_endian() { + int i = 1; + char *p = (char *)&i; + + if (p[0] == 1) + return SML_LITTLE_ENDIAN; + else + return SML_BIG_ENDIAN; +} + diff --git a/test/src/sml_number_test.c b/test/src/sml_number_test.c index ddad149..e24a343 100644 --- a/test/src/sml_number_test.c +++ b/test/src/sml_number_test.c @@ -17,6 +17,7 @@ // along with libSML. If not, see . #include "../unity/unity_fixture.h" +#include "../unity/unity.h" #include "test_helper.h" #include @@ -28,75 +29,80 @@ TEST_SETUP(sml_number) { buf = sml_buffer_init(512); } -TEST_TEAR_DOWN(sml_number) { - -} +TEST_TEAR_DOWN(sml_number) {} TEST(sml_number, parse_unsigned8) { hex2binary("6201", sml_buf_get_current_buf(buf)); - u8 n = sml_u8_parse(buf); - TEST_ASSERT_EQUAL(1, n); + u8 *n = sml_u8_parse(buf); + TEST_ASSERT_EQUAL(1, *n); } TEST(sml_number, parse_unsigned16) { hex2binary("630101", sml_buf_get_current_buf(buf)); - u16 n = sml_u16_parse(buf); - TEST_ASSERT_EQUAL(257, n); + u16 *n = sml_u16_parse(buf); + TEST_ASSERT_EQUAL(257, *n); } TEST(sml_number, parse_unsigned32) { hex2binary("6500000001", sml_buf_get_current_buf(buf)); - u32 n = sml_u32_parse(buf); - TEST_ASSERT_EQUAL(1, n); + u32 *n = sml_u32_parse(buf); + TEST_ASSERT_EQUAL(1, *n); } TEST(sml_number, parse_unsigned32_fewer_bytes) { hex2binary("64010001", sml_buf_get_current_buf(buf)); - u32 n = sml_u32_parse(buf); - TEST_ASSERT_EQUAL(65537, n); + u32 *n = sml_u32_parse(buf); + TEST_ASSERT_EQUAL(65537, *n); +} + +TEST(sml_number, parse_unsigned32_optional) { + hex2binary("01", sml_buf_get_current_buf(buf)); + u32 *n = sml_u32_parse(buf); + TEST_ASSERT_NULL(n); + TEST_ASSERT_EQUAL(1, buf->cursor); } TEST(sml_number, parse_unsigned64) { hex2binary("690000000000000001", sml_buf_get_current_buf(buf)); - u64 n = sml_u64_parse(buf); - TEST_ASSERT_EQUAL(1, n); + //u64 *n = sml_u64_parse(buf); + u64 *n = sml_u64_parse(buf); + TEST_ASSERT_EQUAL(1, *n); } TEST(sml_number, parse_unsigned64_fewer_bytes) { hex2binary("67000000000001", sml_buf_get_current_buf(buf)); - u64 n = sml_u64_parse(buf); - TEST_ASSERT_EQUAL(1, n); + u64 *n = sml_u64_parse(buf); + TEST_ASSERT_EQUAL(1, *n); } - TEST(sml_number, parse_int8) { hex2binary("52FF", sml_buf_get_current_buf(buf)); - i8 n = sml_i8_parse(buf); - TEST_ASSERT_EQUAL(-1, n); + i8 *n = sml_i8_parse(buf); + TEST_ASSERT_EQUAL(-1, *n); } TEST(sml_number, parse_int16) { hex2binary("53EC78", sml_buf_get_current_buf(buf)); - i16 n = sml_i16_parse(buf); - TEST_ASSERT_EQUAL(-5000, n); + i16 *n = sml_i16_parse(buf); + TEST_ASSERT_EQUAL(-5000, *n); } TEST(sml_number, parse_int32) { - hex2binary("55FFFFFFFF", sml_buf_get_current_buf(buf)); - i32 n = sml_i32_parse(buf); - TEST_ASSERT_EQUAL(-1, n); + hex2binary("55FFFFEC78", sml_buf_get_current_buf(buf)); + i32 *n = sml_i32_parse(buf); + TEST_ASSERT_EQUAL(-5000, *n); } TEST(sml_number, parse_int64) { hex2binary("59FFFFFFFFFFFFFFFF", sml_buf_get_current_buf(buf)); - i64 n = sml_i64_parse(buf); - TEST_ASSERT_EQUAL(-1, n); + i64 *n = sml_i64_parse(buf); + TEST_ASSERT_EQUAL(-1, *n); } TEST(sml_number, parse_int64_fewer_bytes) { hex2binary("58FFFFFFFFFFEC78", sml_buf_get_current_buf(buf)); - i64 n = sml_i64_parse(buf); - TEST_ASSERT_EQUAL(-5000, n); + i64 *n = sml_i64_parse(buf); + TEST_ASSERT_EQUAL(-5000, *n); } TEST_GROUP_RUNNER(sml_number) { @@ -106,11 +112,13 @@ TEST_GROUP_RUNNER(sml_number) { RUN_TEST_CASE(sml_number, parse_unsigned64); RUN_TEST_CASE(sml_number, parse_unsigned32_fewer_bytes); RUN_TEST_CASE(sml_number, parse_unsigned64_fewer_bytes); + RUN_TEST_CASE(sml_number, parse_unsigned32_optional); RUN_TEST_CASE(sml_number, parse_int8); RUN_TEST_CASE(sml_number, parse_int16); RUN_TEST_CASE(sml_number, parse_int32); RUN_TEST_CASE(sml_number, parse_int64); RUN_TEST_CASE(sml_number, parse_int64_fewer_bytes); + }