55
66#include < cstdint>
77#include < iterator>
8+ #include < optional>
89#include < string>
910#include < string_view>
10- #include < system_error>
1111
1212namespace evmc
1313{
@@ -17,74 +17,12 @@ using bytes = std::basic_string<uint8_t>;
1717// / String view of uint8_t chars.
1818using bytes_view = std::basic_string_view<uint8_t >;
1919
20- // / Hex decoding error codes.
21- enum class hex_errc
22- {
23- // / Invalid hex digit encountered during decoding.
24- invalid_hex_digit = 1 ,
25-
26- // / Input contains incomplete hex byte (length is odd).
27- incomplete_hex_byte_pair = 2 ,
28- };
29- } // namespace evmc
30-
31- namespace std
32- {
33- // / Template specialization of std::is_error_code_enum for evmc::hex_errc.
34- // / This enabled implicit conversions from evmc::hex_errc to std::error_code.
35- template <>
36- struct is_error_code_enum <evmc::hex_errc> : true_type
37- {};
38- } // namespace std
39-
40- namespace evmc
41- {
42-
43- // / Obtains a reference to the static error category object for hex errors.
44- inline const std::error_category& hex_category () noexcept
45- {
46- struct hex_category_impl : std::error_category
47- {
48- const char * name () const noexcept final { return " hex" ; }
49-
50- std::string message (int ev) const final
51- {
52- switch (static_cast <hex_errc>(ev))
53- {
54- case hex_errc::invalid_hex_digit:
55- return " invalid hex digit" ;
56- case hex_errc::incomplete_hex_byte_pair:
57- return " incomplete hex byte pair" ;
58- default :
59- return " unknown error" ;
60- }
61- }
62- };
63-
64- // Create static category object. This involves mutex-protected dynamic initialization.
65- // Because of the C++ CWG defect 253, the {} syntax is used.
66- static const hex_category_impl category_instance{};
67-
68- return category_instance;
69- }
70-
71- // / Creates error_code object out of a hex error code value.
72- inline std::error_code make_error_code (hex_errc errc) noexcept
73- {
74- return {static_cast <int >(errc), hex_category ()};
75- }
76-
77- // / Hex decoding exception.
78- struct hex_error : std::system_error
79- {
80- using system_error::system_error;
81- };
8220
8321// / Encode a byte to a hex string.
8422inline std::string hex (uint8_t b) noexcept
8523{
86- static constexpr auto hex_chars = " 0123456789abcdef" ;
87- return {hex_chars [b >> 4 ], hex_chars [b & 0xf ]};
24+ static constexpr auto hex_digits = " 0123456789abcdef" ;
25+ return {hex_digits [b >> 4 ], hex_digits [b & 0xf ]};
8826}
8927
9028// / Encodes bytes as hex string.
@@ -121,7 +59,7 @@ inline constexpr bool isspace(char ch) noexcept
12159}
12260
12361template <typename OutputIt>
124- inline constexpr hex_errc from_hex (std::string_view hex, OutputIt result) noexcept
62+ inline constexpr bool from_hex (std::string_view hex, OutputIt result) noexcept
12563{
12664 // Omit the optional 0x prefix.
12765 if (hex.size () >= 2 && hex[0 ] == ' 0' && hex[1 ] == ' x' )
@@ -136,7 +74,7 @@ inline constexpr hex_errc from_hex(std::string_view hex, OutputIt result) noexce
13674
13775 const int v = from_hex_digit (h);
13876 if (v < 0 )
139- return hex_errc::invalid_hex_digit ;
77+ return false ;
14078
14179 if (hi_nibble == empty_mark)
14280 {
@@ -149,14 +87,14 @@ inline constexpr hex_errc from_hex(std::string_view hex, OutputIt result) noexce
14987 }
15088 }
15189
152- if (hi_nibble != empty_mark)
153- return hex_errc::incomplete_hex_byte_pair;
154- return {};
90+ return hi_nibble == empty_mark;
15591}
15692} // namespace internal_hex
15793
15894// / Validates hex encoded string.
159- inline std::error_code validate_hex (std::string_view hex) noexcept
95+ // /
96+ // / @return True if the input is valid hex.
97+ inline bool validate_hex (std::string_view hex) noexcept
16098{
16199 struct noop_output_iterator
162100 {
@@ -170,14 +108,15 @@ inline std::error_code validate_hex(std::string_view hex) noexcept
170108
171109// / Decodes hex encoded string to bytes.
172110// /
173- // / Throws hex_error with the appropriate error code.
174- inline bytes from_hex (std::string_view hex)
111+ // / In case the input is invalid the returned value is std::nullopt.
112+ // / This can happen if a non-hex digit or odd number of digits is encountered.
113+ // / Whitespace in the input is ignored.
114+ inline std::optional<bytes> from_hex (std::string_view hex)
175115{
176116 bytes bs;
177117 bs.reserve (hex.size () / 2 );
178- const auto ec = internal_hex::from_hex (hex, std::back_inserter (bs));
179- if (static_cast <int >(ec) != 0 )
180- throw hex_error{ec};
118+ if (!internal_hex::from_hex (hex, std::back_inserter (bs)))
119+ return {};
181120 return bs;
182121}
183122} // namespace evmc
0 commit comments