Strutils: add hex-decoding helper
This will be used to allow entering hex bytes in XML files, for HID descriptor support on Windows.
This commit is contained in:
parent
454df4872a
commit
e9e2053c64
@ -897,6 +897,69 @@ std::string encodeHex(const unsigned char* rawBytes, unsigned int length)
|
||||
return hex;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> decodeHex(const std::string& input)
|
||||
{
|
||||
std::vector<uint8_t> result;
|
||||
char* ptr = const_cast<char*>(input.data());
|
||||
const char* end = ptr + input.length();
|
||||
|
||||
bool highNibble = true;
|
||||
uint8_t b = 0;
|
||||
|
||||
while (ptr != end) {
|
||||
const char c = *ptr;
|
||||
char val = 0;
|
||||
|
||||
if (c == '0') {
|
||||
val = 0;
|
||||
if ((ptr + 1) < end) {
|
||||
const auto peek = *(ptr + 1);
|
||||
if (peek == 'x') {
|
||||
// tolerate 0x prefixing
|
||||
highNibble = true;
|
||||
ptr += 2; // skip both bytes
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else if (isdigit(c)) {
|
||||
val = c - '0';
|
||||
} else if ((c >= 'A') && (c <= 'F')) {
|
||||
val = c - 'A' + 10;
|
||||
} else if ((c >= 'a') && (c <= 'f')) {
|
||||
val = c - 'a' + 10;
|
||||
} else {
|
||||
// any other input: newline, space, tab, comma...
|
||||
if (!highNibble) {
|
||||
// allow a single digit to work, if we have spacing
|
||||
highNibble = true;
|
||||
result.push_back(b >> 4);
|
||||
}
|
||||
|
||||
++ptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (highNibble) {
|
||||
highNibble = false;
|
||||
b = val << 4;
|
||||
} else {
|
||||
highNibble = true;
|
||||
b |= val;
|
||||
result.push_back(b);
|
||||
}
|
||||
|
||||
++ptr;
|
||||
}
|
||||
|
||||
// watch for trailing single digit
|
||||
// this is reqquired so a stirng ending in 0x3 is decoded.
|
||||
if (!highNibble) {
|
||||
result.push_back(b >> 4);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Write an octal backslash-escaped respresentation of 'val' to 'buf'.
|
||||
//
|
||||
// At least 4 write positions must be available at 'buf'. The result is *not*
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
#include <cstdlib>
|
||||
#include <cstdint>
|
||||
|
||||
typedef std::vector < std::string > string_list;
|
||||
|
||||
@ -304,6 +305,9 @@ namespace simgear {
|
||||
|
||||
std::string encodeHex(const unsigned char* rawBytes, unsigned int length);
|
||||
|
||||
|
||||
std::vector<uint8_t> decodeHex(const std::string& input);
|
||||
|
||||
/**
|
||||
* Backslash-escape a string for C/C++ string literal syntax.
|
||||
*
|
||||
|
@ -730,6 +730,13 @@ void test_formatGeod()
|
||||
|
||||
}
|
||||
|
||||
void testDecodeHex()
|
||||
{
|
||||
const auto decoded = simgear::strutils::decodeHex("01 0xff,0xcd \n\t99 0xcD abcdef\n\r0x1 0x2 0x3");
|
||||
vector<uint8_t> data1 = {0x1, 0xff, 0xcd, 0x99, 0xcd, 0xAB, 0xCD,0xEF, 1, 2, 3};
|
||||
SG_VERIFY(decoded == data1);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
test_strip();
|
||||
@ -753,6 +760,7 @@ int main(int argc, char* argv[])
|
||||
test_parseGeod();
|
||||
test_formatGeod();
|
||||
test_iequals();
|
||||
testDecodeHex();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user