1 #pragma once 2 3 #include <array> 4 #include <cstddef> 5 #include <string> 6 #include <vector> 7 8 static constexpr std::array<char, 16> digitsArray = { 9 '0', '1', '2', '3', '4', '5', '6', '7', 10 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; 11 12 inline std::string intToHexString(uint64_t value, size_t digits) 13 { 14 std::string rc(digits, '0'); 15 size_t bitIndex = (digits - 1) * 4; 16 for (size_t digitIndex = 0; digitIndex < digits; digitIndex++) 17 { 18 rc[digitIndex] = digitsArray[(value >> bitIndex) & 0x0f]; 19 bitIndex -= 4; 20 } 21 return rc; 22 } 23 24 inline std::string bytesToHexString(const std::vector<uint8_t>& bytes) 25 { 26 std::string rc(bytes.size() * 2, '0'); 27 for (size_t i = 0; i < bytes.size(); ++i) 28 { 29 rc[i * 2] = digitsArray[(bytes[i] & 0xf0) >> 4]; 30 rc[i * 2 + 1] = digitsArray[bytes[i] & 0x0f]; 31 } 32 return rc; 33 } 34 35 // Returns nibble. 36 inline uint8_t hexCharToNibble(char ch) 37 { 38 uint8_t rc = 16; 39 if (ch >= '0' && ch <= '9') 40 { 41 rc = static_cast<uint8_t>(ch) - '0'; 42 } 43 else if (ch >= 'A' && ch <= 'F') 44 { 45 rc = static_cast<uint8_t>(ch) - 'A' + 10; 46 } 47 else if (ch >= 'a' && ch <= 'f') 48 { 49 rc = static_cast<uint8_t>(ch) - 'a' + 10; 50 } 51 52 return rc; 53 } 54 55 // Returns empty vector in case of malformed hex-string. 56 inline std::vector<uint8_t> hexStringToBytes(const std::string& str) 57 { 58 std::vector<uint8_t> rc(str.size() / 2, 0); 59 for (size_t i = 0; i < str.length(); i += 2) 60 { 61 uint8_t hi = hexCharToNibble(str[i]); 62 if (i == str.length() - 1) 63 { 64 return {}; 65 } 66 uint8_t lo = hexCharToNibble(str[i + 1]); 67 if (lo == 16 || hi == 16) 68 { 69 return {}; 70 } 71 72 rc[i / 2] = static_cast<uint8_t>(hi << 4) | lo; 73 } 74 return rc; 75 } 76