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 */
10#include <string_view>
11#include <type_traits>
12namespace CxxUtils {
13namespace detail {
19template <std::size_t N>
22 char buf[N]{};
27 constexpr FixedString(const char (&str)[N]) {
28 for (std::size_t i = 0; i < N; ++i) buf[i] = str[i];
29 }
30
34 constexpr std::size_t length() const { return N - 1; }
35};
36inline constexpr char UpperHexDigits[] = "0123456789ABCDEF";
37inline constexpr char LowerHexDigits[] = "0123456789abcdef";
46template <FixedString FormatStr, const char* Digits>
48private:
50 static constexpr std::size_t s_FormatLen = FormatStr.length();
55 static constexpr std::size_t get_placeholder_pos() {
56 for (std::size_t i = 0; i + 1 < s_FormatLen; ++i) {
57 if (FormatStr.buf[i] == '{' && FormatStr.buf[i + 1] == '}') return i;
58 }
59 return static_cast<std::size_t>(-1);
60 }
61
62
63 static constexpr std::size_t s_PlaceholderPos = get_placeholder_pos();
64 static_assert(s_PlaceholderPos != static_cast<std::size_t>(-1), "Format string must contain a '{}' placeholder.");
66 static constexpr std::size_t s_PrefixLen = s_PlaceholderPos;
68 static constexpr std::size_t s_PostfixLen = s_FormatLen - s_PrefixLen - 2;
70 static constexpr std::size_t s_MaxHexDigits = 16;
74 std::size_t m_actual_size = 0;
75public:
83 template <typename T>
84 constexpr explicit BasicHexString(T context) {
85 static_assert(std::is_integral_v<T>, "HexString only accepts integer types.");
86 // 1. Calculate hex digits needed for this specific type (e.g., sizeof(uint16_t) * 2 = 4 digits)
87 constexpr std::size_t HexDigits = sizeof(T) * 2;
89 static_assert(HexDigits <= s_MaxHexDigits);
90 // Cast to an unsigned equivalent of the same size to prevent sign-extension bugs during shifting
91 using UnsignedT = std::make_unsigned_t<T>;
92 UnsignedT value = static_cast<UnsignedT>(context);
93 // 2. Write prefix
94 if constexpr (s_PrefixLen>0){
95 for (std::size_t i = 0; i < s_PrefixLen; ++i) {
96 m_text[i] = FormatStr.buf[i];
97 }
98 }
99 // 3. Write hex digits dynamically based on type size
100 for (std::size_t i = 0; i < HexDigits; ++i) {
101 const std::size_t shift = (HexDigits - 1 - i) * 4;
102 m_text[s_PrefixLen + i] = Digits[(value >> shift) & static_cast<UnsignedT>(0xF)];
103 }
104 // 4. Write postfix
105 if constexpr (s_PostfixLen>0){
106 for (std::size_t i = 0; i < s_PostfixLen; ++i) {
107 m_text[s_PrefixLen + HexDigits + i] = FormatStr.buf[s_PrefixLen + 2 + i];
108 }
109 }
110 // 5. Null terminator
111 m_text[m_actual_size] = '\0';
112 }
113
117 constexpr operator std::string_view() const noexcept {
118 return std::string_view(m_text, m_actual_size);
119 }
120 //Helper friend functions to allow compilation of common use-cases.
121 friend constexpr std::string operator+(std::string lhs, const BasicHexString& rhs) {
122 lhs.append(static_cast<std::string_view>(rhs));
123 return lhs;
124
125 }
126 friend constexpr std::string operator+(const BasicHexString& lhs, const std::string& rhs) {
127 std::string_view lhs_view = lhs;
128 std::string result;
129 result.reserve(lhs_view.size() + rhs.size());
130 result.append(lhs_view).append(rhs);
131 return result;
132 }
133
134 // Needed to prevent ambiguities.
135 friend constexpr std::string operator+(const BasicHexString& lhs, std::string&& rhs) {
136 const std::string& rhs_l = rhs;
137 return lhs + rhs_l;
138 }
139
140 friend constexpr std::string operator+(const char* lhs, const BasicHexString& rhs) {
141 return std::string(lhs) + rhs;
142 }
143 friend constexpr std::string operator+(const BasicHexString& lhs, const char* rhs) {
144 return lhs + std::string(rhs);
145 }
146
150 constexpr std::size_t size() const noexcept { return m_actual_size;}
155 const char* c_str() const noexcept { return m_text; }
156};
157} // namespace detail
158template <detail::FixedString FormatStr> using HexString = detail::BasicHexString<FormatStr, detail::UpperHexDigits>;
159template <detail::FixedString FormatStr> using hexstring = detail::BasicHexString<FormatStr, detail::LowerHexDigits>;
160} // namespace CxxUtils
A class that formats an integer as a hexadecimal string embedded within a format string.
Definition HexString.h:47
constexpr std::size_t size() const noexcept
Returns the total size of the formatted string.
Definition HexString.h:150
static constexpr std::size_t get_placeholder_pos()
Finds the position of the "{}" placeholder within the format string.
Definition HexString.h:55
friend constexpr std::string operator+(const char *lhs, const BasicHexString &rhs)
Definition HexString.h:140
constexpr BasicHexString(T context)
Constructs the formatted string by injecting the hex value of the context into the placeholder.
Definition HexString.h:84
friend constexpr std::string operator+(std::string lhs, const BasicHexString &rhs)
Definition HexString.h:121
friend constexpr std::string operator+(const BasicHexString &lhs, std::string &&rhs)
Definition HexString.h:135
char m_text[s_PrefixLen+s_MaxHexDigits+s_PostfixLen+1]
Definition HexString.h:72
friend constexpr std::string operator+(const BasicHexString &lhs, const char *rhs)
Definition HexString.h:143
const char * c_str() const noexcept
Returns a pointer to the underlying null-terminated character array.
Definition HexString.h:155
friend constexpr std::string operator+(const BasicHexString &lhs, const std::string &rhs)
Definition HexString.h:126
constexpr char LowerHexDigits[]
Definition HexString.h:37
constexpr char UpperHexDigits[]
Definition HexString.h:36
detail::BasicHexString< FormatStr, detail::LowerHexDigits > hexstring
Definition HexString.h:159
detail::BasicHexString< FormatStr, detail::UpperHexDigits > HexString
Definition HexString.h:158
constexpr std::size_t length() const
Gets the length of the string excluding the null terminator.
Definition HexString.h:34
constexpr FixedString(const char(&str)[N])
Constructs a FixedString from a string literal.
Definition HexString.h:27
char buf[N]
The internal character buffer.
Definition HexString.h:22