Implementation:ClickHouse ClickHouse Hex Encoding
| Knowledge Sources | |
|---|---|
| Domains | Encoding, String_Processing |
| Last Updated | 2026-02-08 00:00 GMT |
Overview
Fast hexadecimal encoding and decoding functions using lookup tables for converting between binary data and hex string representations.
Description
This code provides efficient functions for converting binary data to hexadecimal strings and vice versa. The implementation uses pre-computed lookup tables that map bytes (0-255) directly to their two-character hex representations, and hex digits to their numeric values. This table-based approach avoids expensive division and modulo operations, making encoding/decoding several times faster than arithmetic-based methods. The code supports both uppercase and lowercase hex output, handles various integer types (including wide integers and CityHash uint128), and provides specialized functions for common operations like converting single bytes or hex digits.
Usage
Use this when you need to display binary data as hex strings (checksums, hashes, binary dumps), convert hex strings back to binary (parsing hex literals, configuration values), or debug binary data. The table-based approach makes it ideal for high-throughput scenarios like generating hex dumps of large data structures or processing many hash values.
Code Reference
Source Location
- Repository: ClickHouse
- File: base/base/hex.h
- Lines: 1-303
Signature
// Convert integer to hex string
template <typename T>
void writeHexUIntUppercase(const T & value, char * out);
template <typename T>
void writeHexUIntLowercase(const T & value, char * out);
template <typename T>
std::string getHexUIntUppercase(const T & value);
template <typename T>
std::string getHexUIntLowercase(const T & value);
// Convert single hex digit (0-15 to '0'-'F')
constexpr char hexDigitUppercase(unsigned char c);
constexpr char hexDigitLowercase(unsigned char c);
// Convert single byte to two hex characters
inline void writeHexByteUppercase(UInt8 byte, void * out);
inline void writeHexByteLowercase(UInt8 byte, void * out);
// Convert hex string back to integer
template <typename T>
constexpr T unhexUInt(const char * data);
// Convert single hex digit ('0'-'F' to 0-15)
constexpr UInt8 unhex(char c);
// Convert two hex characters to byte
constexpr UInt8 unhex2(const char * data);
// Convert four hex characters to UInt16
constexpr UInt16 unhex4(const char * data);
// Convert byte to binary string
inline void writeBinByte(UInt8 byte, void * out);
// Debug helper: convert byte array to hex string
inline std::string hexString(const void * data, size_t size);
Import
#include <base/hex.h>
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| value | Integer type (UInt8-UInt256, wide::integer) | Yes | Value to encode as hex |
| byte | UInt8 | Yes | Single byte to encode |
| data | const char * | Yes | Hex string to decode |
| size | size_t | Yes | Length of byte array |
| c | char | Yes | Single hex digit to decode |
Outputs
| Name | Type | Description |
|---|---|---|
| out | char * | Buffer for hex string output |
| hex_string | std::string | Allocated hex string |
| value | Integer type | Decoded integer value |
| digit | UInt8 | Decoded hex digit value (0-15) |
Usage Examples
#include <base/hex.h>
// Convert integer to hex string
UInt32 value = 0xDEADBEEF;
char buffer[8];
writeHexUIntUppercase(value, buffer);
// buffer = "DEADBEEF"
// Get hex string (allocates)
std::string hex = getHexUIntLowercase(value);
// hex = "deadbeef"
// Convert single byte
UInt8 byte = 0xA5;
char byte_hex[2];
writeHexByteUppercase(byte, byte_hex);
// byte_hex = "A5"
// Convert hex back to integer
const char * hex_input = "DEADBEEF";
UInt32 decoded = unhexUInt<UInt32>(hex_input);
// decoded = 0xDEADBEEF
// Parse single hex digit
UInt8 digit = unhex('F'); // 15
UInt8 digit2 = unhex('a'); // 10
// Parse two hex characters to byte
const char * hex_byte = "A5";
UInt8 byte_value = unhex2(hex_byte); // 0xA5
// Binary representation
UInt8 b = 0b10101010;
char bin_str[8];
writeBinByte(b, bin_str);
// bin_str = "10101010"
// Debug: dump memory as hex
uint8_t data[] = {0xDE, 0xAD, 0xBE, 0xEF};
std::string dump = hexString(data, sizeof(data));
// dump = "deadbeef"
// Convert hash/checksum to hex
UInt64 hash = 0x123456789ABCDEF0;
std::string hash_str = getHexUIntUppercase(hash);
// hash_str = "123456789ABCDEF0"
// Wide integers (128-bit, 256-bit)
UInt128 wide_value = UInt128{0x0123456789ABCDEF, 0xFEDCBA9876543210};
char wide_hex[32];
writeHexUIntLowercase(wide_value, wide_hex);
// 32-character hex string