EVMC
hex.hpp
1// EVMC: Ethereum Client-VM Connector API.
2// Copyright 2021 The EVMC Authors.
3// Licensed under the Apache License, Version 2.0.
4#pragma once
5
6#include <evmc/bytes.hpp>
7#include <evmc/filter_iterator.hpp>
8#include <cstdint>
9#include <optional>
10#include <string>
11#include <string_view>
12
13namespace evmc
14{
16inline std::string hex(uint8_t b) noexcept
17{
18 static constexpr auto hex_digits = "0123456789abcdef";
19 return {hex_digits[b >> 4], hex_digits[b & 0xf]};
20}
21
23inline std::string hex(bytes_view bs)
24{
25 std::string str;
26 str.reserve(bs.size() * 2);
27 for (const auto b : bs)
28 str += hex(b);
29 return str;
30}
31
32namespace internal
33{
36inline constexpr int from_hex_digit(char h) noexcept
37{
38 if (h >= '0' && h <= '9')
39 return h - '0';
40 else if (h >= 'a' && h <= 'f')
41 return h - 'a' + 10;
42 else if (h >= 'A' && h <= 'F')
43 return h - 'A' + 10;
44 else
45 return -1;
46}
47} // namespace internal
48
57template <typename InputIt, typename OutputIt>
58inline constexpr bool from_hex(InputIt begin, InputIt end, OutputIt out) noexcept
59{
60 int hi_nibble = -1; // Init with invalid value, should never be used.
61 size_t i = 0;
62 for (auto it = begin; it != end; ++it, ++i)
63 {
64 const auto h = *it;
65 const int v = evmc::internal::from_hex_digit(h);
66 if (v < 0)
67 {
68 if (i == 1 && hi_nibble == 0 && h == 'x') // 0x prefix
69 continue;
70 return false;
71 }
72
73 if (i % 2 == 0)
74 hi_nibble = v << 4;
75 else
76 *out++ = static_cast<uint8_t>(hi_nibble | v);
77 }
78
79 return i % 2 == 0;
80}
81
85inline bool validate_hex(std::string_view hex) noexcept
86{
87 struct noop_output_iterator
88 {
89 uint8_t sink = {};
90 uint8_t& operator*() noexcept { return sink; }
91 noop_output_iterator operator++(int) noexcept { return *this; } // NOLINT(cert-dcl21-cpp)
92 };
93
94 return from_hex(hex.begin(), hex.end(), noop_output_iterator{});
95}
96
101inline std::optional<bytes> from_hex(std::string_view hex)
102{
103 bytes bs;
104 bs.reserve(hex.size() / 2);
105 if (!from_hex(hex.begin(), hex.end(), std::back_inserter(bs)))
106 return {};
107 return bs;
108}
109
115template <typename T>
116constexpr std::optional<T> from_hex(std::string_view s) noexcept
117{
118 // Omit the optional 0x prefix.
119 if (s.size() >= 2 && s[0] == '0' && s[1] == 'x')
120 s.remove_prefix(2);
121
122 T r{}; // The T must have .bytes array. This may be lifted if std::bit_cast is available.
123 constexpr auto num_out_bytes = std::size(r.bytes);
124 const auto num_in_bytes = s.length() / 2;
125 if (num_in_bytes > num_out_bytes)
126 return {};
127 if (!from_hex(s.begin(), s.end(), &r.bytes[num_out_bytes - num_in_bytes]))
128 return {};
129 return r;
130}
131
137template <typename InputIterator>
138std::optional<bytes> from_spaced_hex(InputIterator begin, InputIterator end) noexcept
139{
140 bytes bs;
141 if (!from_hex(skip_space_iterator{begin, end}, skip_space_iterator{end, end},
142 std::back_inserter(bs)))
143 return {};
144 return bs;
145}
146
148inline std::optional<bytes> from_spaced_hex(std::string_view hex) noexcept
149{
150 return from_spaced_hex(hex.begin(), hex.end());
151}
152} // namespace evmc
EVMC C++ API - wrappers and bindings for C++.
Definition: bytes.hpp:12
std::string hex(uint8_t b) noexcept
Encode a byte to a hex string.
Definition: hex.hpp:16
bool validate_hex(std::string_view hex) noexcept
Validates hex encoded string.
Definition: hex.hpp:85
constexpr bool from_hex(InputIt begin, InputIt end, OutputIt out) noexcept
Decodes hex-encoded sequence of characters.
Definition: hex.hpp:58
std::basic_string_view< unsigned char, byte_traits< unsigned char > > bytes_view
String view of unsigned chars representing bytes.
Definition: bytes.hpp:92
std::optional< bytes > from_spaced_hex(InputIterator begin, InputIterator end) noexcept
Decodes hex encoded string to bytes.
Definition: hex.hpp:138
std::basic_string< unsigned char, byte_traits< unsigned char > > bytes
String of unsigned chars representing bytes.
Definition: bytes.hpp:89
The input filter iterator which skips whitespace characters from the base input iterator.