diff --git a/sys/net/crosslayer/ng_netif/ng_netif_addr_from_str.c b/sys/net/crosslayer/ng_netif/ng_netif_addr_from_str.c index 7686d92030..3a357f164f 100644 --- a/sys/net/crosslayer/ng_netif/ng_netif_addr_from_str.c +++ b/sys/net/crosslayer/ng_netif/ng_netif_addr_from_str.c @@ -15,47 +15,76 @@ #include "net/ng_netif.h" -static int _dehex(char c) +static inline int _dehex(char c, int default_) { - return ('0' <= c && c <= '9') ? c - '0' - : ('A' <= c && c <= 'F') ? c - 'A' + 10 - : ('a' <= c && c <= 'f') ? c - 'a' + 10 - : -1; + if ('0' <= c && c <= '9') { + return c - '0'; + } + else if ('A' <= c && c <= 'F') { + return c - 'A' + 10; + } + else if ('a' <= c && c <= 'f') { + return c - 'a' + 10; + } + else { + return default_; + } } size_t ng_netif_addr_from_str(uint8_t *out, size_t out_len, const char *str) { - size_t len = 0; - while (1) { - ++len; - if (len > out_len) { - return 0; - } + /* Walk over str from the end. */ + /* Take two chars a time as one hex value (%hhx). */ + /* Leading zeros can be omitted. */ + /* Every non-hexadimal character is a delimiter. */ + /* Leading, tailing and adjacent delimiters are forbidden. */ - int a = _dehex(*str++); - if (a < 0) { - return 0; - } + const char *end_str = str; + uint8_t *out_end = out; + size_t count = 0; + int assert_cell = 1; - int b = _dehex(*str++); - if (b < 0) { - return 0; - } - - *out++ = (a << 4) | b; - - if (*str == ':') { - ++str; - } - else if (*str == '\0') { - break; - } - else { - return 0; - } + if (!str || !*str) { + return 0; + } + while (end_str[1]) { + ++end_str; } - return len; + while (end_str >= str) { + int a = 0, b = _dehex(*end_str--, -1); + if (b < 0) { + if (assert_cell) { + return 0; + } + else { + assert_cell = 1; + continue; + } + } + assert_cell = 0; + + if (end_str >= str) { + a = _dehex(*end_str--, 0); + } + + if (++count > out_len) { + return 0; + } + *out_end++ = (a << 4) | b; + } + if (assert_cell) { + return 0; + } + /* out is reversed */ + + while (out < --out_end) { + uint8_t tmp = *out_end; + *out_end = *out; + *out++ = tmp; + } + + return count; } /** @} */ diff --git a/tests/unittests/Makefile b/tests/unittests/Makefile index 6a733ce433..49d7578d11 100644 --- a/tests/unittests/Makefile +++ b/tests/unittests/Makefile @@ -4,7 +4,7 @@ include ../Makefile.tests_common BOARD_INSUFFICIENT_RAM := airfy-beacon chronos msb-430 msb-430h pca10000 \ pca10005 redbee-econotag spark-core stm32f0discovery \ telosb wsn430-v1_3b wsn430-v1_4 z1 nucleo-f334 \ - yunjia-nrf51822 samr21-xpro + yunjia-nrf51822 samr21-xpro arduino-mega2560 USEMODULE += embunit diff --git a/tests/unittests/tests-netif/tests-netif.c b/tests/unittests/tests-netif/tests-netif.c index d248b2451c..e5d5cdd068 100644 --- a/tests/unittests/tests-netif/tests-netif.c +++ b/tests/unittests/tests-netif/tests-netif.c @@ -184,12 +184,15 @@ static void test_ng_netif_addr_from_str__out_too_short(void) TEST_ASSERT_EQUAL_INT(0, ng_netif_addr_from_str(out, sizeof(out), str)); } -static void test_ng_netif_addr_from_str__ill_formated1(void) +static void test_ng_netif_addr_from_str__omitted_delimitter(void) { - static const char str[] = "576:cd"; - uint8_t out[sizeof(str)]; + static const char str[] = "4567:cd"; + uint8_t out[3]; - TEST_ASSERT_EQUAL_INT(0, ng_netif_addr_from_str(out, sizeof(out), str)); + TEST_ASSERT_EQUAL_INT(3, ng_netif_addr_from_str(out, sizeof(out), str)); + TEST_ASSERT_EQUAL_INT(0x45, out[0]); + TEST_ASSERT_EQUAL_INT(0x67, out[1]); + TEST_ASSERT_EQUAL_INT(0xcd, out[2]); } static void test_ng_netif_addr_from_str__ill_formated2(void) @@ -200,33 +203,55 @@ static void test_ng_netif_addr_from_str__ill_formated2(void) TEST_ASSERT_EQUAL_INT(0, ng_netif_addr_from_str(out, sizeof(out), str)); } -static void test_ng_netif_addr_from_str__ill_formated3(void) +static void test_ng_netif_addr_from_str__dash_delimitter(void) { static const char str[] = "05-cd"; - uint8_t out[sizeof(str)]; + uint8_t out[2]; - TEST_ASSERT_EQUAL_INT(0, ng_netif_addr_from_str(out, sizeof(out), str)); + TEST_ASSERT_EQUAL_INT(2, ng_netif_addr_from_str(out, sizeof(out), str)); + TEST_ASSERT_EQUAL_INT(0x05, out[0]); + TEST_ASSERT_EQUAL_INT(0xcd, out[1]); } -static void test_ng_netif_addr_from_str__ill_formated4(void) +static void test_ng_netif_addr_from_str__zero_omitted_back(void) { static const char str[] = "05:c"; - uint8_t out[sizeof(str)]; + uint8_t out[2]; - TEST_ASSERT_EQUAL_INT(0, ng_netif_addr_from_str(out, sizeof(out), str)); + TEST_ASSERT_EQUAL_INT(2, ng_netif_addr_from_str(out, sizeof(out), str)); + TEST_ASSERT_EQUAL_INT(0x05, out[0]); + TEST_ASSERT_EQUAL_INT(0x0c, out[1]); } -static void test_ng_netif_addr_from_str__ill_formated5(void) +static void test_ng_netif_addr_from_str__zero_omitted_front(void) { static const char str[] = "5:cd"; + uint8_t out[2]; + + TEST_ASSERT_EQUAL_INT(2, ng_netif_addr_from_str(out, sizeof(out), str)); + TEST_ASSERT_EQUAL_INT(0x05, out[0]); + TEST_ASSERT_EQUAL_INT(0xcd, out[1]); +} + +static void test_ng_netif_addr_from_str__ill_trailing_delimitter(void) +{ + static const char str[] = "05:cd:"; uint8_t out[sizeof(str)]; TEST_ASSERT_EQUAL_INT(0, ng_netif_addr_from_str(out, sizeof(out), str)); } -static void test_ng_netif_addr_from_str__ill_formated6(void) +static void test_ng_netif_addr_from_str__ill_leading_delimitter(void) { - static const char str[] = "05:cd:"; + static const char str[] = ":05:cd"; + uint8_t out[sizeof(str)]; + + TEST_ASSERT_EQUAL_INT(0, ng_netif_addr_from_str(out, sizeof(out), str)); +} + +static void test_ng_netif_addr_from_str__ill_extra_delimitter(void) +{ + static const char str[] = "05::cd"; uint8_t out[sizeof(str)]; TEST_ASSERT_EQUAL_INT(0, ng_netif_addr_from_str(out, sizeof(out), str)); @@ -258,12 +283,14 @@ Test *tests_netif_tests(void) new_TestFixture(test_ng_netif_addr_to_str__out_too_short), new_TestFixture(test_ng_netif_addr_to_str__success), new_TestFixture(test_ng_netif_addr_from_str__out_too_short), - new_TestFixture(test_ng_netif_addr_from_str__ill_formated1), + new_TestFixture(test_ng_netif_addr_from_str__omitted_delimitter), new_TestFixture(test_ng_netif_addr_from_str__ill_formated2), - new_TestFixture(test_ng_netif_addr_from_str__ill_formated3), - new_TestFixture(test_ng_netif_addr_from_str__ill_formated4), - new_TestFixture(test_ng_netif_addr_from_str__ill_formated5), - new_TestFixture(test_ng_netif_addr_from_str__ill_formated6), + new_TestFixture(test_ng_netif_addr_from_str__dash_delimitter), + new_TestFixture(test_ng_netif_addr_from_str__zero_omitted_back), + new_TestFixture(test_ng_netif_addr_from_str__zero_omitted_front), + new_TestFixture(test_ng_netif_addr_from_str__ill_trailing_delimitter), + new_TestFixture(test_ng_netif_addr_from_str__ill_leading_delimitter), + new_TestFixture(test_ng_netif_addr_from_str__ill_extra_delimitter), new_TestFixture(test_ng_netif_addr_from_str__success), };