/* * Copyright (C) 2017 Freie Universität Berlin * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level * directory for more details. */ /** * @{ * * @file * @author Martine Lenders */ #include #include "fmt.h" char *netif_addr_to_str(const uint8_t *addr, size_t addr_len, char *out) { char *res = out; assert((out != NULL) && ((addr != NULL) || (addr_len == 0U))); out[0] = '\0'; for (size_t i = 0; i < addr_len; i++) { out += fmt_byte_hex((out), *(addr++)); *(out++) = (i == (addr_len - 1)) ? '\0' : ':'; } return res; } static inline int _dehex(char c, int default_) { 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 netif_addr_from_str(const char *str, uint8_t *out) { /* 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. */ const char *end_str = str; uint8_t *out_end = out; size_t count = 0; int assert_cell = 1; assert(out != NULL); if ((str == NULL) || (str[0] == '\0')) { return 0; } /* find end of string */ while (end_str[1]) { ++end_str; } 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); } count++; *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; } /** @} */