|
5 | 5 |
|
6 | 6 | #include <evmc/evmc.h>
|
7 | 7 | #include <evmc/helpers.h>
|
| 8 | +#include <evmc/hex.hpp> |
8 | 9 |
|
9 | 10 | #include <functional>
|
10 | 11 | #include <initializer_list>
|
@@ -280,71 +281,37 @@ inline constexpr bytes32::operator bool() const noexcept
|
280 | 281 |
|
281 | 282 | namespace literals
|
282 | 283 | {
|
283 |
| -namespace internal |
284 |
| -{ |
285 |
| -constexpr int from_hex(char c) noexcept |
286 |
| -{ |
287 |
| - return (c >= 'a' && c <= 'f') ? c - ('a' - 10) : |
288 |
| - (c >= 'A' && c <= 'F') ? c - ('A' - 10) : |
289 |
| - c - '0'; |
290 |
| -} |
291 |
| - |
292 |
| -constexpr uint8_t byte(const char* s, size_t i) noexcept |
293 |
| -{ |
294 |
| - return static_cast<uint8_t>((from_hex(s[2 * i]) << 4) | from_hex(s[2 * i + 1])); |
295 |
| -} |
| 284 | +/// Breaks compilation and reports error string in constexpr context. |
| 285 | +inline void error([[maybe_unused]] const char* message) noexcept {} |
296 | 286 |
|
| 287 | +/// Converts a raw literal into value of type T. |
297 | 288 | template <typename T>
|
298 |
| -T from_hex(const char*) noexcept; |
299 |
| - |
300 |
| -template <> |
301 |
| -constexpr bytes32 from_hex<bytes32>(const char* s) noexcept |
302 |
| -{ |
303 |
| - return { |
304 |
| - {{byte(s, 0), byte(s, 1), byte(s, 2), byte(s, 3), byte(s, 4), byte(s, 5), byte(s, 6), |
305 |
| - byte(s, 7), byte(s, 8), byte(s, 9), byte(s, 10), byte(s, 11), byte(s, 12), byte(s, 13), |
306 |
| - byte(s, 14), byte(s, 15), byte(s, 16), byte(s, 17), byte(s, 18), byte(s, 19), byte(s, 20), |
307 |
| - byte(s, 21), byte(s, 22), byte(s, 23), byte(s, 24), byte(s, 25), byte(s, 26), byte(s, 27), |
308 |
| - byte(s, 28), byte(s, 29), byte(s, 30), byte(s, 31)}}}; |
309 |
| -} |
310 |
| - |
311 |
| -template <> |
312 |
| -constexpr address from_hex<address>(const char* s) noexcept |
| 289 | +constexpr T to(std::string_view s) noexcept |
313 | 290 | {
|
314 |
| - return { |
315 |
| - {{byte(s, 0), byte(s, 1), byte(s, 2), byte(s, 3), byte(s, 4), byte(s, 5), byte(s, 6), |
316 |
| - byte(s, 7), byte(s, 8), byte(s, 9), byte(s, 10), byte(s, 11), byte(s, 12), byte(s, 13), |
317 |
| - byte(s, 14), byte(s, 15), byte(s, 16), byte(s, 17), byte(s, 18), byte(s, 19)}}}; |
318 |
| -} |
| 291 | + if (s == "0") |
| 292 | + return T{}; |
319 | 293 |
|
320 |
| -template <typename T, char... c> |
321 |
| -constexpr T from_literal() noexcept |
322 |
| -{ |
323 |
| - constexpr auto size = sizeof...(c); |
324 |
| - constexpr char literal[] = {c...}; |
325 |
| - constexpr bool is_simple_zero = size == 1 && literal[0] == '0'; |
| 294 | + if (s[0] != '0' || s[1] != 'x') |
| 295 | + error("literal must be in hexadecimal notation"); |
326 | 296 |
|
327 |
| - static_assert(is_simple_zero || (literal[0] == '0' && literal[1] == 'x'), |
328 |
| - "literal must be in hexadecimal notation"); |
329 |
| - static_assert(is_simple_zero || size == 2 * sizeof(T) + 2, |
330 |
| - "literal must match the result type size"); |
| 297 | + if (s.length() != 2 * sizeof(T) + 2) |
| 298 | + error("literal must match the result type size"); |
331 | 299 |
|
332 |
| - return is_simple_zero ? T{} : from_hex<T>(&literal[2]); |
| 300 | + T r{}; |
| 301 | + internal::from_hex(s, r.bytes); |
| 302 | + return r; |
333 | 303 | }
|
334 |
| -} // namespace internal |
335 | 304 |
|
336 | 305 | /// Literal for evmc::address.
|
337 |
| -template <char... c> |
338 |
| -constexpr address operator""_address() noexcept |
| 306 | +constexpr address operator""_address(const char* s) noexcept |
339 | 307 | {
|
340 |
| - return internal::from_literal<address, c...>(); |
| 308 | + return to<address>(s); |
341 | 309 | }
|
342 | 310 |
|
343 | 311 | /// Literal for evmc::bytes32.
|
344 |
| -template <char... c> |
345 |
| -constexpr bytes32 operator""_bytes32() noexcept |
| 312 | +constexpr bytes32 operator""_bytes32(const char* s) noexcept |
346 | 313 | {
|
347 |
| - return internal::from_literal<bytes32, c...>(); |
| 314 | + return to<bytes32>(s); |
348 | 315 | }
|
349 | 316 | } // namespace literals
|
350 | 317 |
|
|
0 commit comments