number parsing with optionals
This commit is contained in:
parent
cd078d5f3f
commit
268bfe423c
3 changed files with 95 additions and 54 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -21,10 +21,21 @@
|
|||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
// along with libSML. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "../unity/unity_fixture.h"
|
||||
#include "../unity/unity.h"
|
||||
#include "test_helper.h"
|
||||
#include <sml/sml_number.h>
|
||||
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue