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