Merge pull request #8343 from aabadie/pr/fmt_hex_bytes

sys/fmt: add hex/bytes sequence converters
This commit is contained in:
Kaspar Schleiser 2018-01-11 10:02:58 +01:00 committed by GitHub
commit 7a8138615a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 173 additions and 0 deletions

View File

@ -62,6 +62,18 @@ size_t fmt_byte_hex(char *out, uint8_t byte)
return 2; return 2;
} }
size_t fmt_bytes_hex(char *out, const uint8_t *ptr, size_t n)
{
size_t len = n * 2;
if (out) {
while (n--) {
out += fmt_byte_hex(out, *ptr++);
}
}
return len;
}
size_t fmt_strlen(const char *str) size_t fmt_strlen(const char *str)
{ {
const char *tmp = str; const char *tmp = str;
@ -95,6 +107,39 @@ size_t fmt_bytes_hex_reverse(char *out, const uint8_t *ptr, size_t n)
return (n<<1); return (n<<1);
} }
static uint8_t _byte_mod25(uint8_t x)
{
for (unsigned divisor = 200; divisor >= 25; divisor >>= 1) {
if (x >= divisor) {
x -= divisor;
}
}
return x;
}
static uint8_t _hex_nib(uint8_t nib)
{
return _byte_mod25((nib & 0x1f) + 9);
}
size_t fmt_hex_bytes(uint8_t *out, const char *hex)
{
size_t len = fmt_strlen(hex);
if (len & 1) {
out = NULL;
return 0;
}
size_t final_len = len >> 1;
for (size_t i = 0, j = 0; j < final_len; i += 2, j++) {
out[j] = (_hex_nib(hex[i]) << 4) | _hex_nib(hex[i+1]);
}
return final_len;
}
size_t fmt_u32_hex(char *out, uint32_t val) size_t fmt_u32_hex(char *out, uint32_t val)
{ {
return fmt_bytes_hex_reverse(out, (uint8_t*) &val, 4); return fmt_bytes_hex_reverse(out, (uint8_t*) &val, 4);

View File

@ -61,6 +61,21 @@ extern "C" {
*/ */
size_t fmt_byte_hex(char *out, uint8_t byte); size_t fmt_byte_hex(char *out, uint8_t byte);
/**
* @brief Formats a sequence of bytes as hex bytes
*
* Will write 2*n bytes to @p out.
* If @p out is NULL, will only return the number of bytes that would have
* been written.
*
* @param[out] out Pointer to output buffer, or NULL
* @param[in] ptr Pointer to bytes to convert
* @param[in] n Number of bytes to convert
*
* @return 2*n
*/
size_t fmt_bytes_hex(char *out, const uint8_t *ptr, size_t n);
/** /**
* @brief Formats a sequence of bytes as hex bytes, starting with the last byte * @brief Formats a sequence of bytes as hex bytes, starting with the last byte
* *
@ -76,6 +91,23 @@ size_t fmt_byte_hex(char *out, uint8_t byte);
*/ */
size_t fmt_bytes_hex_reverse(char *out, const uint8_t *ptr, size_t n); size_t fmt_bytes_hex_reverse(char *out, const uint8_t *ptr, size_t n);
/**
* @brief Converts a sequence of hex bytes to an array of bytes
*
* The sequence of hex characters must have an even length:
* 2 hex character => 1 byte. If the sequence of hex has an odd length, this
* function returns 0 and an empty @p out.
*
* The hex characters sequence must contain valid hexadecimal characters
* otherwise the result in @p out is undefined.
*
* @param[out] out Pointer to converted bytes, or NULL
* @param[in] hex Pointer to input buffer
* @returns strlen(hex) / 2 when length of @p hex was even
* @returns 0 otherwise
*/
size_t fmt_hex_bytes(uint8_t *out, const char *hex);
/** /**
* @brief Convert a uint32 value to hex string. * @brief Convert a uint32 value to hex string.
* *

View File

@ -34,6 +34,53 @@ static void test_fmt_byte_hex(void)
TEST_ASSERT_EQUAL_STRING("FF", (char *) out); TEST_ASSERT_EQUAL_STRING("FF", (char *) out);
} }
static void test_fmt_bytes_hex(void)
{
char out[15] = "--------------";
uint8_t val[7] = { 0xAA, 9, 8, 7, 6, 0xA8, 0xEF};
uint8_t bytes = 0;
bytes = fmt_bytes_hex(out, val, 0);
out[bytes] = '\0';
TEST_ASSERT_EQUAL_INT(0, bytes);
TEST_ASSERT_EQUAL_STRING("", (char *) out);
bytes = fmt_bytes_hex(out, val, 1);
out[bytes] = '\0';
TEST_ASSERT_EQUAL_INT(2, bytes);
TEST_ASSERT_EQUAL_STRING("AA", (char *) out);
bytes = fmt_bytes_hex(out, val, 2);
out[bytes] = '\0';
TEST_ASSERT_EQUAL_INT(4, bytes);
TEST_ASSERT_EQUAL_STRING("AA09", (char *) out);
bytes = fmt_bytes_hex(out, val, 3);
out[bytes] = '\0';
TEST_ASSERT_EQUAL_INT(6, bytes);
TEST_ASSERT_EQUAL_STRING("AA0908", (char *) out);
bytes = fmt_bytes_hex(out, val, 4);
out[bytes] = '\0';
TEST_ASSERT_EQUAL_INT(8, bytes);
TEST_ASSERT_EQUAL_STRING("AA090807", (char *) out);
bytes = fmt_bytes_hex(out, val, 5);
out[bytes] = '\0';
TEST_ASSERT_EQUAL_INT(10, bytes);
TEST_ASSERT_EQUAL_STRING("AA09080706", (char *) out);
bytes = fmt_bytes_hex(out, val, 6);
out[bytes] = '\0';
TEST_ASSERT_EQUAL_INT(12, bytes);
TEST_ASSERT_EQUAL_STRING("AA09080706A8", (char *) out);
bytes = fmt_bytes_hex(out, val, 7);
out[bytes] = '\0';
TEST_ASSERT_EQUAL_INT(14, bytes);
TEST_ASSERT_EQUAL_STRING("AA09080706A8EF", (char *) out);
}
static void test_fmt_bytes_hex_reverse(void) static void test_fmt_bytes_hex_reverse(void)
{ {
char out[9] = "--------"; char out[9] = "--------";
@ -61,6 +108,53 @@ static void test_fmt_bytes_hex_reverse(void)
TEST_ASSERT_EQUAL_STRING("06070809", (char *) out); TEST_ASSERT_EQUAL_STRING("06070809", (char *) out);
} }
static void test_fmt_hex_bytes(void)
{
uint8_t val = 0;
uint8_t bytes = fmt_hex_bytes(&val, "");
TEST_ASSERT_EQUAL_INT(0, bytes);
TEST_ASSERT_EQUAL_INT(0, val);
bytes = fmt_hex_bytes(&val, "A");
TEST_ASSERT_EQUAL_INT(0, val);
TEST_ASSERT_EQUAL_INT(0, bytes);
char hex2[3] = "00";
uint8_t val1[1] = { 0 };
bytes = fmt_hex_bytes(val1, hex2);
TEST_ASSERT_EQUAL_INT(1, bytes);
TEST_ASSERT_EQUAL_INT(0, val1[0]);
memcpy(hex2, "AB", 2);
hex2[2] = '\0';
val1[0] = 0;
bytes = fmt_hex_bytes(val1, hex2);
TEST_ASSERT_EQUAL_INT(1, bytes);
TEST_ASSERT_EQUAL_INT(0xAB, val1[0]);
memcpy(hex2, "CD", 2);
hex2[2] = '\0';
val1[0] = 0;
bytes = fmt_hex_bytes(val1, hex2);
TEST_ASSERT_EQUAL_INT(1, bytes);
TEST_ASSERT_EQUAL_INT(0xCD, val1[0]);
memcpy(hex2, "EF", 2);
hex2[2] = '\0';
val1[0] = 0;
bytes = fmt_hex_bytes(val1, hex2);
TEST_ASSERT_EQUAL_INT(1, bytes);
TEST_ASSERT_EQUAL_INT(0xEF, val1[0]);
char hex6[] = "0102aF";
uint8_t val3[3];
bytes = fmt_hex_bytes(val3, hex6);
TEST_ASSERT_EQUAL_INT(3, bytes);
TEST_ASSERT_EQUAL_INT(1, val3[0]);
TEST_ASSERT_EQUAL_INT(2, val3[1]);
TEST_ASSERT_EQUAL_INT(0xAF, val3[2]);
}
static void test_fmt_u32_hex(void) static void test_fmt_u32_hex(void)
{ {
char out[9] = "--------"; char out[9] = "--------";
@ -376,7 +470,9 @@ Test *tests_fmt_tests(void)
{ {
EMB_UNIT_TESTFIXTURES(fixtures) { EMB_UNIT_TESTFIXTURES(fixtures) {
new_TestFixture(test_fmt_byte_hex), new_TestFixture(test_fmt_byte_hex),
new_TestFixture(test_fmt_bytes_hex),
new_TestFixture(test_fmt_bytes_hex_reverse), new_TestFixture(test_fmt_bytes_hex_reverse),
new_TestFixture(test_fmt_hex_bytes),
new_TestFixture(test_fmt_u32_hex), new_TestFixture(test_fmt_u32_hex),
new_TestFixture(test_fmt_u64_hex), new_TestFixture(test_fmt_u64_hex),
new_TestFixture(test_fmt_u32_dec), new_TestFixture(test_fmt_u32_dec),