Commit fcebd9f0 authored by johan's avatar johan

Add bytes buffer/uints to hexa string conversion functions

parent c6517880
......@@ -483,6 +483,78 @@ BCTBX_PUBLIC bool_t bctbx_is_multicast_addr(const struct sockaddr *addr);
#endif
/**
* @brief convert an hexa char [0-9a-fA-F] into the corresponding unsigned integer value
* Any invalid char will be converted to zero without any warning
*
* @param[in] inputChar a char which shall be in range [0-9a-fA-F]
*
* @return the unsigned integer value in range [0-15]
*/
BCTBX_PUBLIC uint8_t bctbx_charToByte(const uint8_t inputChar);
/**
* @brief convert a byte which value is in range [0-15] into an hexa char [0-9a-fA-F]
*
* @param[in] inputByte an integer which shall be in range [0-15]
*
* @return the hexa char [0-9a-f] corresponding to the input
*/
BCTBX_PUBLIC uint8_t bctbx_byteToChar(const uint8_t inputByte);
/**
* @brief Convert an hexadecimal string into the corresponding byte buffer
*
* @param[out] outputBytes The output bytes buffer, must have a length of half the input string buffer
* @param[in] inputString The input string buffer, must be hexadecimal(it is not checked by function, any non hexa char is converted to 0)
* @param[in] inputStringLength The lenght in chars of the string buffer, output is half this length
*/
BCTBX_PUBLIC void bctbx_strToUint8(uint8_t *outputBytes, const uint8_t *inputString, const uint16_t inputStringLength);
/**
* @brief Convert a byte buffer into the corresponding hexadecimal string
*
* @param[out] outputString The output string buffer, must have a length of twice the input bytes buffer
* @param[in] inputBytes The input bytes buffer
* @param[in] inputBytesLength The lenght in bytes buffer, output is twice this length
*/
BCTBX_PUBLIC void bctbx_int8ToStr(uint8_t *outputString, const uint8_t *inputBytes, const uint16_t inputBytesLength);
/**
* @brief Convert an unsigned 32 bits integer into the corresponding hexadecimal string(including null termination character)
*
* @param[out] outputString The output string buffer, must have a length of at least 9 bytes(8 nibbles and the '\0')
* @param[in] inputUint32 The input unsigned int
*/
BCTBX_PUBLIC void bctbx_uint32ToStr(uint8_t outputString[9], const uint32_t inputUint32);
/**
* @brief Convert an hexadecimal string of 8 char length into the corresponding 32 bits unsigned integer
*
* @param[in] inputString The input string buffer, must be hexadecimal and at least 8 char long
*
* Note : there is no check on the length or validity as an hexa string on the input, incorrect byte is silently mapped to 0
*/
BCTBX_PUBLIC uint32_t bctbx_strToUint32(const uint8_t inputString[9]);
/**
* @brief Convert an unsigned 64 bits integer into the corresponding hexadecimal string(including null termination character)
*
* @param[out] outputString The output string buffer, must have a length of at least 17 bytes(16 nibbles and the '\0')
* @param[in] inputUint64 The input unsigned int
*/
BCTBX_PUBLIC void bctbx_uint64ToStr(uint8_t outputString[17], const uint64_t inputUint64);
/**
* @brief Convert an hexadecimal string of 8 char length into the corresponding 64 bits unsigned integer
*
* @param[in] inputString The input string buffer, must be hexadecimal and at leat 16 char long
*
* Note : there is no check on the length or validity as an hexa string on the input, incorrect byte is silently mapped to 0
*/
BCTBX_PUBLIC uint64_t bctbx_strToUint64(const uint8_t inputString[17]);
#ifdef __cplusplus
}
......
......@@ -1452,3 +1452,171 @@ void bctbx_freeaddrinfo(struct addrinfo *res){
else freeaddrinfo(beginit);
}
/* Useful byte buffer to/from hexa string manipulation */
/**
* @brief convert an hexa char [0-9a-fA-F] into the corresponding unsigned integer value
* Any invalid char will be converted to zero without any warning
*
* @param[in] inputChar a char which shall be in range [0-9a-fA-F]
*
* @return the unsigned integer value in range [0-15]
*/
uint8_t bctbx_charToByte(const uint8_t inputChar) {
/* 0-9 */
if (inputChar>0x29 && inputChar<0x3A) {
return inputChar - 0x30;
}
/* a-f */
if (inputChar>0x60 && inputChar<0x67) {
return inputChar - 0x57; /* 0x57 = 0x61(a) + 0x0A*/
}
/* A-F */
if (inputChar>0x40 && inputChar<0x47) {
return inputChar - 0x37; /* 0x37 = 0x41(a) + 0x0A*/
}
/* shall never arrive here, string is not Hex*/
return 0;
}
/**
* @brief convert a byte which value is in range [0-15] into an hexa char [0-9a-fA-F]
*
* @param[in] inputByte an integer which shall be in range [0-15]
*
* @return the hexa char [0-9a-f] corresponding to the input
*/
uint8_t bctbx_byteToChar(const uint8_t inputByte) {
uint8_t inputByteCrop = inputByte&0x0F; /* restrict the input value to range [0-15] */
/* 0-9 */
if(inputByteCrop<0x0A) {
return inputByteCrop+0x30;
}
/* a-f */
return inputByteCrop + 0x57;
}
/**
* @brief Convert an hexadecimal string into the corresponding byte buffer
*
* @param[out] outputBytes The output bytes buffer, must have a length of half the input string buffer
* @param[in] inputString The input string buffer, must be hexadecimal(it is not checked by function, any non hexa char is converted to 0)
* @param[in] inputStringLength The lenght in chars of the string buffer, output is half this length
*/
void bctbx_strToUint8(uint8_t *outputBytes, const uint8_t *inputString, const uint16_t inputStringLength) {
int i;
for (i=0; i<inputStringLength/2; i++) {
outputBytes[i] = (bctbx_charToByte(inputString[2*i]))<<4 | bctbx_charToByte(inputString[2*i+1]);
}
}
/**
* @brief Convert a byte buffer into the corresponding hexadecimal string
*
* @param[out] outputString The output string buffer, must have a length of twice the input bytes buffer
* @param[in] inputBytes The input bytes buffer
* @param[in] inputBytesLength The lenght in bytes buffer, output is twice this length
*/
void bctbx_int8ToStr(uint8_t *outputString, const uint8_t *inputBytes, const uint16_t inputBytesLength) {
int i;
for (i=0; i<inputBytesLength; i++) {
outputString[2*i] = bctbx_byteToChar((inputBytes[i]>>4)&0x0F);
outputString[2*i+1] = bctbx_byteToChar(inputBytes[i]&0x0F);
}
}
/**
* @brief Convert an unsigned 32 bits integer into the corresponding hexadecimal string(including null termination character)
*
* @param[out] outputString The output string buffer, must have a length of at least 9 bytes(8 nibbles and the '\0')
* @param[in] inputUint32 The input unsigned int
*/
void bctbx_uint32ToStr(uint8_t outputString[9], const uint32_t inputUint32) {
outputString[0] = bctbx_byteToChar((uint8_t)((inputUint32>>28)&0x0F));
outputString[1] = bctbx_byteToChar((uint8_t)((inputUint32>>24)&0x0F));
outputString[2] = bctbx_byteToChar((uint8_t)((inputUint32>>20)&0x0F));
outputString[3] = bctbx_byteToChar((uint8_t)((inputUint32>>16)&0x0F));
outputString[4] = bctbx_byteToChar((uint8_t)((inputUint32>>12)&0x0F));
outputString[5] = bctbx_byteToChar((uint8_t)((inputUint32>>8)&0x0F));
outputString[6] = bctbx_byteToChar((uint8_t)((inputUint32>>4)&0x0F));
outputString[7] = bctbx_byteToChar((uint8_t)((inputUint32)&0x0F));
outputString[8] = '\0';
}
/**
* @brief Convert an hexadecimal string of 8 char length into the corresponding 32 bits unsigned integer
*
* @param[in] inputString The input string buffer, must be hexadecimal(it is not checked by function, any non hexa char is converted to 0)
*
* Note : there is no check on the length or validity as an hexa string on the input, incorrect byte is silently mapped to 0
*/
uint32_t bctbx_strToUint32(const uint8_t *inputString) {
return (((uint32_t)bctbx_charToByte(inputString[0]))<<28)
| (((uint32_t)bctbx_charToByte(inputString[1]))<<24)
| (((uint32_t)bctbx_charToByte(inputString[2]))<<20)
| (((uint32_t)bctbx_charToByte(inputString[3]))<<16)
| (((uint32_t)bctbx_charToByte(inputString[4]))<<12)
| (((uint32_t)bctbx_charToByte(inputString[5]))<<8)
| (((uint32_t)bctbx_charToByte(inputString[6]))<<4)
| (((uint32_t)bctbx_charToByte(inputString[7])));
}
/**
* @brief Convert an unsigned 64 bits integer into the corresponding hexadecimal string(including null termination character)
*
* @param[out] outputString The output string buffer, must have a length of at least 17 bytes(16 nibbles and the '\0')
* @param[in] inputUint64 The input unsigned int
*/
void bctbx_uint64ToStr(uint8_t outputString[17], const uint64_t inputUint64) {
outputString[0] = bctbx_byteToChar((uint8_t)((inputUint64>>60)&0x0F));
outputString[1] = bctbx_byteToChar((uint8_t)((inputUint64>>56)&0x0F));
outputString[2] = bctbx_byteToChar((uint8_t)((inputUint64>>52)&0x0F));
outputString[3] = bctbx_byteToChar((uint8_t)((inputUint64>>48)&0x0F));
outputString[4] = bctbx_byteToChar((uint8_t)((inputUint64>>44)&0x0F));
outputString[5] = bctbx_byteToChar((uint8_t)((inputUint64>>40)&0x0F));
outputString[6] = bctbx_byteToChar((uint8_t)((inputUint64>>36)&0x0F));
outputString[7] = bctbx_byteToChar((uint8_t)((inputUint64>>32)&0x0F));
outputString[8] = bctbx_byteToChar((uint8_t)((inputUint64>>28)&0x0F));
outputString[9] = bctbx_byteToChar((uint8_t)((inputUint64>>24)&0x0F));
outputString[10] = bctbx_byteToChar((uint8_t)((inputUint64>>20)&0x0F));
outputString[11] = bctbx_byteToChar((uint8_t)((inputUint64>>16)&0x0F));
outputString[12] = bctbx_byteToChar((uint8_t)((inputUint64>>12)&0x0F));
outputString[13] = bctbx_byteToChar((uint8_t)((inputUint64>>8)&0x0F));
outputString[14] = bctbx_byteToChar((uint8_t)((inputUint64>>4)&0x0F));
outputString[15] = bctbx_byteToChar((uint8_t)((inputUint64)&0x0F));
outputString[16] = '\0';
}
/**
* @brief Convert an hexadecimal string of 8 char length into the corresponding 64 bits unsigned integer
*
* @param[in] inputString The input string buffer, must be hexadecimal and at leat 16 char long
*
* Note : there is no check on the length or validity as an hexa string on the input, incorrect byte is silently mapped to 0
*/
uint64_t bctbx_strToUint64(const uint8_t inputString[17]) {
return (((uint64_t)bctbx_charToByte(inputString[0]))<<60)
| (((uint64_t)bctbx_charToByte(inputString[1]))<<56)
| (((uint64_t)bctbx_charToByte(inputString[2]))<<52)
| (((uint64_t)bctbx_charToByte(inputString[3]))<<48)
| (((uint64_t)bctbx_charToByte(inputString[4]))<<44)
| (((uint64_t)bctbx_charToByte(inputString[5]))<<40)
| (((uint64_t)bctbx_charToByte(inputString[6]))<<36)
| (((uint64_t)bctbx_charToByte(inputString[7]))<<32)
| (((uint64_t)bctbx_charToByte(inputString[8]))<<28)
| (((uint64_t)bctbx_charToByte(inputString[9]))<<24)
| (((uint64_t)bctbx_charToByte(inputString[10]))<<20)
| (((uint64_t)bctbx_charToByte(inputString[11]))<<16)
| (((uint64_t)bctbx_charToByte(inputString[12]))<<12)
| (((uint64_t)bctbx_charToByte(inputString[13]))<<8)
| (((uint64_t)bctbx_charToByte(inputString[14]))<<4)
| (((uint64_t)bctbx_charToByte(inputString[15])));
}
......@@ -31,6 +31,7 @@ if(BCUNIT_FOUND AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
bctoolbox_tester.c
bctoolbox_tester.h
containers.cc
port.c
)
string(REPLACE ";" " " LINK_FLAGS_STR "${LINK_FLAGS}")
......
......@@ -44,6 +44,7 @@ static void log_handler(int lev, const char *fmt, va_list args) {
void bctoolbox_tester_init(void(*ftester_printf)(int level, const char *fmt, va_list args)) {
bc_tester_init(log_handler,BCTBX_LOG_ERROR, 0,NULL);
bc_tester_add_suite(&containers_test_suite);
bc_tester_add_suite(&utils_test_suite);
}
void bctoolbox_tester_uninit(void) {
......
......@@ -33,6 +33,7 @@ extern "C" {
#endif
extern test_suite_t containers_test_suite;
extern test_suite_t utils_test_suite;
#ifdef __cplusplus
};
......
/*
bctoolbox
Copyright (C) 2017 Belledonne Communications SARL
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include "bctoolbox_tester.h"
#include "bctoolbox/port.h"
static void bytesToFromHexaStrings(void) {
const uint8_t a55aBytes[2] = {0xa5, 0x5a};
const uint8_t a55aString[5] = "a55a";
const uint8_t upBytes[8] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
const uint8_t upString[17] = "0123456789abcdef";
const uint8_t downBytes[8] = {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
const uint8_t downString[17] = "fedcba9876543210";
uint8_t outputBytes[16];
uint8_t outputString[16];
BC_ASSERT_EQUAL(bctbx_charToByte("1"[0]), 1, uint8_t, "%d");
BC_ASSERT_EQUAL(bctbx_charToByte("5"[0]), 5, uint8_t, "%d");
BC_ASSERT_EQUAL(bctbx_charToByte("a"[0]), 10, uint8_t, "%d");
BC_ASSERT_EQUAL(bctbx_charToByte("e"[0]), 14, uint8_t, "%d");
BC_ASSERT_EQUAL(bctbx_charToByte("B"[0]), 11, uint8_t, "%d");
BC_ASSERT_EQUAL(bctbx_charToByte("F"[0]), 15, uint8_t, "%d");
BC_ASSERT_EQUAL(bctbx_byteToChar(0), "0"[0], char, "%c");
BC_ASSERT_EQUAL(bctbx_byteToChar(2), "2"[0], char, "%c");
BC_ASSERT_EQUAL(bctbx_byteToChar(5), "5"[0], char, "%c");
BC_ASSERT_EQUAL(bctbx_byteToChar(0x0a), "a"[0], char, "%c");
BC_ASSERT_EQUAL(bctbx_byteToChar(0x0c), "c"[0], char, "%c");
BC_ASSERT_EQUAL(bctbx_byteToChar(0x0e), "e"[0], char, "%c");
bctbx_strToUint8(outputBytes, a55aString, 4);
BC_ASSERT_NSTRING_EQUAL(outputBytes, a55aBytes, 2);
bctbx_strToUint8(outputBytes, upString, 16);
BC_ASSERT_NSTRING_EQUAL(outputBytes, upBytes, 8);
bctbx_strToUint8(outputBytes, downString, 16);
BC_ASSERT_NSTRING_EQUAL(outputBytes, downBytes, 8);
bctbx_int8ToStr(outputString, a55aBytes, 2);
BC_ASSERT_NSTRING_EQUAL(outputString, a55aString, 4);
bctbx_int8ToStr(outputString, upBytes, 8);
BC_ASSERT_NSTRING_EQUAL(outputString, upString, 16);
bctbx_int8ToStr(outputString, downBytes, 8);
BC_ASSERT_NSTRING_EQUAL(outputString, downString, 16);
bctbx_uint32ToStr(outputString, 0x5aa5c376);
BC_ASSERT_NSTRING_EQUAL(outputString, "5aa5c376", 8);
bctbx_uint32ToStr(outputString, 0x01234567);
BC_ASSERT_NSTRING_EQUAL(outputString, "01234567", 8);
bctbx_uint32ToStr(outputString, 0xfedcba98);
BC_ASSERT_NSTRING_EQUAL(outputString, "fedcba98", 8);
BC_ASSERT_EQUAL(bctbx_strToUint32("5aa5c376"), 0x5aa5c376, uint32_t, "0x%08x");
BC_ASSERT_EQUAL(bctbx_strToUint32("01234567"), 0x01234567, uint32_t, "0x%08x");
BC_ASSERT_EQUAL(bctbx_strToUint32("fedcba98"), 0xfedcba98, uint32_t, "0x%08x");
bctbx_uint64ToStr(outputString, 0xfa5c37643cde8de0);
BC_ASSERT_NSTRING_EQUAL(outputString, "fa5c37643cde8de0", 16);
bctbx_uint64ToStr(outputString, 0x0123456789abcdef);
BC_ASSERT_NSTRING_EQUAL(outputString, "0123456789abcdef", 16);
bctbx_uint64ToStr(outputString, 0xfedcba9876543210);
BC_ASSERT_NSTRING_EQUAL(outputString, "fedcba9876543210", 16);
BC_ASSERT_EQUAL(bctbx_strToUint64("fa5c37643cde8de0"), 0xfa5c37643cde8de0, uint64_t, "0x%016lx");
BC_ASSERT_EQUAL(bctbx_strToUint64("0123456789abcdef"), 0x0123456789abcdef, uint64_t, "0x%016lx");
BC_ASSERT_EQUAL(bctbx_strToUint64("fedcba9876543210"), 0xfedcba9876543210, uint64_t, "0x%016lx");
}
static test_t utils_tests[] = {
TEST_NO_TAG("Bytes to/from Hexa strings", bytesToFromHexaStrings),
};
test_suite_t utils_test_suite = {"Utils", NULL, NULL, NULL, NULL,
sizeof(utils_tests) / sizeof(utils_tests[0]), utils_tests};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment