ATLAS Offline Software
Loading...
Searching...
No Matches
HexString.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration.
3 */
4
11
12
13#include <string_view>
14#include <string>
15#include <type_traits> // Required for std::is_integral_v and std::make_unsigned_t
16
17
18namespace CxxUtils {
19
20namespace detail{
26template <std::size_t N>
29 char buf[N]{};
34 constexpr FixedString(const char (&str)[N]) {
35 for (std::size_t i = 0; i < N; ++i) buf[i] = str[i];
36 }
37
41 constexpr std::size_t length() const { return N - 1; }
42};
43}
44
53template <detail::FixedString FormatStr>
54class HexString {
55private:
57 static constexpr std::size_t s_FormatLen = FormatStr.length();
58
63 static constexpr std::size_t get_placeholder_pos() {
64 for (std::size_t i = 0; i + 1 < s_FormatLen; ++i) {
65 if (FormatStr.buf[i] == '{' && FormatStr.buf[i + 1] == '}') return i;
66 }
67 return static_cast<std::size_t>(-1);
68 }
69
71 static constexpr std::size_t s_PlaceholderPos = get_placeholder_pos();
72 static_assert(s_PlaceholderPos != static_cast<std::size_t>(-1), "Format string must contain a '{}' placeholder.");
73
75 static constexpr std::size_t s_PrefixLen = s_PlaceholderPos;
77 static constexpr std::size_t s_PostfixLen = s_FormatLen - s_PrefixLen - 2;
79 static constexpr std::size_t s_MaxHexDigits = 16;
80
84 std::size_t m_actual_size = 0;
85
86public:
94 template <typename T>
95 constexpr explicit HexString(T context) {
96 static_assert(std::is_integral_v<T>, "HexString only accepts integer types.");
97
98 constexpr char digits[] = "0123456789ABCDEF";
99
100 // 1. Calculate hex digits needed for this specific type (e.g., sizeof(uint16_t) * 2 = 4 digits)
101 constexpr std::size_t HexDigits = sizeof(T) * 2;
102
103 m_actual_size = s_PrefixLen + HexDigits + s_PostfixLen;
104 static_assert(HexDigits <= s_MaxHexDigits);
105 // Cast to an unsigned equivalent of the same size to prevent sign-extension bugs during shifting
106 using UnsignedT = std::make_unsigned_t<T>;
107 UnsignedT value = static_cast<UnsignedT>(context);
108
109 // 2. Write prefix
110 for (std::size_t i = 0; i < s_PrefixLen; ++i) {
111 m_text[i] = FormatStr.buf[i];
112 }
113
114 // 3. Write hex digits dynamically based on type size
115 for (std::size_t i = 0; i < HexDigits; ++i) {
116 std::size_t shift = (HexDigits - 1 - i) * 4;
117 m_text[s_PrefixLen + i] = digits[(value >> shift) & 0xFU];
118 }
119
120 // 4. Write postfix
121 for (std::size_t i = 0; i < s_PostfixLen; ++i) {
122 m_text[s_PrefixLen + HexDigits + i] = FormatStr.buf[s_PrefixLen + 2 + i];
123 }
124
125 // 5. Null terminator
126 m_text[m_actual_size] = '\0';
127 }
128
133 constexpr operator std::string_view() const noexcept {
134 return std::string_view(m_text, m_actual_size);
135 }
136
137
138 //Helper friend functions to allow compilation of common use-cases.
139
140 friend constexpr std::string operator+(std::string lhs, const HexString& rhs) {
141 lhs.append(static_cast<std::string_view>(rhs));
142 return lhs;
143 }
144
145 friend constexpr std::string operator+(const HexString& lhs, const std::string& rhs) {
146 std::string_view lhs_view = lhs;
147 std::string result;
148 result.reserve(lhs_view.size() + rhs.size());
149 result.append(lhs_view).append(rhs);
150 return result;
151 }
152
153 friend constexpr std::string operator+(const char* lhs, const HexString& rhs) {
154 return std::string(lhs) + rhs;
155 }
156
157 friend constexpr std::string operator+(const HexString& lhs, const char* rhs) {
158 return lhs + std::string(rhs);
159 }
160
165 constexpr std::size_t size() const noexcept { return m_actual_size; }
166
171 const char* c_str() const noexcept { return m_text; }
172};
173}
174
std::size_t m_actual_size
The actual length of the generated string.
Definition HexString.h:84
static constexpr std::size_t get_placeholder_pos()
Finds the position of the "{}" placeholder within the format string.
Definition HexString.h:63
friend constexpr std::string operator+(const HexString &lhs, const char *rhs)
Definition HexString.h:157
friend constexpr std::string operator+(std::string lhs, const HexString &rhs)
Definition HexString.h:140
static constexpr std::size_t s_PostfixLen
The length of the string postfix (after the placeholder).
Definition HexString.h:77
const char * c_str() const noexcept
Returns a pointer to the underlying null-terminated character array.
Definition HexString.h:171
static constexpr std::size_t s_FormatLen
The total length of the format string.
Definition HexString.h:57
constexpr HexString(T context)
Constructs the formatted string by injecting the hex value of the context into the placeholder.
Definition HexString.h:95
static constexpr std::size_t s_MaxHexDigits
The maximum number of hex digits (supports up to 64-bit integers).
Definition HexString.h:79
friend constexpr std::string operator+(const char *lhs, const HexString &rhs)
Definition HexString.h:153
friend constexpr std::string operator+(const HexString &lhs, const std::string &rhs)
Definition HexString.h:145
static constexpr std::size_t s_PlaceholderPos
The index of the "{}" placeholder.
Definition HexString.h:71
static constexpr std::size_t s_PrefixLen
The index of the "{}" placeholder.
Definition HexString.h:75
char m_text[s_PrefixLen+s_MaxHexDigits+s_PostfixLen+1]
The internal buffer storing the fully formatted string.
Definition HexString.h:82
constexpr std::size_t size() const noexcept
Returns the total size of the formatted string.
Definition HexString.h:165
constexpr std::size_t length() const
Gets the length of the string excluding the null terminator.
Definition HexString.h:41
constexpr FixedString(const char(&str)[N])
Constructs a FixedString from a string literal.
Definition HexString.h:34
char buf[N]
The internal character buffer.
Definition HexString.h:29