Electroneum
Loading...
Searching...
No Matches
hex.cpp
Go to the documentation of this file.
1// Copyright (c) 2017-Present, Electroneum
2// Copyright (c) 2017-2019, The Monero Project
3//
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without modification, are
7// permitted provided that the following conditions are met:
8//
9// 1. Redistributions of source code must retain the above copyright notice, this list of
10// conditions and the following disclaimer.
11//
12// 2. Redistributions in binary form must reproduce the above copyright notice, this list
13// of conditions and the following disclaimer in the documentation and/or other
14// materials provided with the distribution.
15//
16// 3. Neither the name of the copyright holder nor the names of its contributors may be
17// used to endorse or promote products derived from this software without specific
18// prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30#include "hex.h"
31
32#include <iterator>
33#include <limits>
34#include <ostream>
35#include <stdexcept>
36
37namespace epee
38{
39 namespace
40 {
41 template<typename T>
42 void write_hex(T&& out, const span<const std::uint8_t> src)
43 {
44 static constexpr const char hex[] = u8"0123456789abcdef";
45 static_assert(sizeof(hex) == 17, "bad string size");
46 for (const std::uint8_t byte : src)
47 {
48 *out = hex[byte >> 4];
49 ++out;
50 *out = hex[byte & 0x0F];
51 ++out;
52 }
53 }
54 }
55
56 template<typename T>
57 T to_hex::convert(const span<const std::uint8_t> src)
58 {
59 if (std::numeric_limits<std::size_t>::max() / 2 < src.size())
60 throw std::range_error("hex_view::to_string exceeded maximum size");
61
62 T out{};
63 out.resize(src.size() * 2);
64 to_hex::buffer_unchecked((char*)out.data(), src); // can't see the non const version in wipeable_string??
65 return out;
66 }
67
68 std::string to_hex::string(const span<const std::uint8_t> src) { return convert<std::string>(src); }
69 epee::wipeable_string to_hex::wipeable_string(const span<const std::uint8_t> src) { return convert<epee::wipeable_string>(src); }
70
71 void to_hex::buffer(std::ostream& out, const span<const std::uint8_t> src)
72 {
73 write_hex(std::ostreambuf_iterator<char>{out}, src);
74 }
75
76 void to_hex::formatted(std::ostream& out, const span<const std::uint8_t> src)
77 {
78 out.put('<');
79 buffer(out, src);
80 out.put('>');
81 }
82
83 void to_hex::buffer_unchecked(char* out, const span<const std::uint8_t> src) noexcept
84 {
85 return write_hex(out, src);
86 }
87
88 std::vector<uint8_t> from_hex::vector(boost::string_ref src)
89 {
90 // should we include a specific character
91 auto include = [](char input) {
92 // we ignore spaces and colons
93 return !std::isspace(input) && input != ':';
94 };
95
96 // the number of relevant characters to decode
97 auto count = std::count_if(src.begin(), src.end(), include);
98
99 // this must be a multiple of two, otherwise we have a truncated input
100 if (count % 2) {
101 throw std::length_error{ "Invalid hexadecimal input length" };
102 }
103
104 std::vector<uint8_t> result;
105 result.reserve(count / 2);
106
107 // the data to work with (std::string is always null-terminated)
108 auto data = src.data();
109
110 // convert a single hex character to an unsigned integer
111 auto char_to_int = [](const char *input) {
112 switch (std::tolower(*input)) {
113 case '0': return 0;
114 case '1': return 1;
115 case '2': return 2;
116 case '3': return 3;
117 case '4': return 4;
118 case '5': return 5;
119 case '6': return 6;
120 case '7': return 7;
121 case '8': return 8;
122 case '9': return 9;
123 case 'a': return 10;
124 case 'b': return 11;
125 case 'c': return 12;
126 case 'd': return 13;
127 case 'e': return 14;
128 case 'f': return 15;
129 default: throw std::range_error{ "Invalid hexadecimal input" };
130 }
131 };
132
133 // keep going until we reach the end
134 while (data[0] != '\0') {
135 // skip unwanted characters
136 if (!include(data[0])) {
137 ++data;
138 continue;
139 }
140
141 // convert two matching characters to int
142 auto high = char_to_int(data++);
143 auto low = char_to_int(data++);
144
145 result.push_back(high << 4 | low);
146 }
147
148 return result;
149 }
150}
unsigned char u8
Non-owning sequence of data. Does not deep copy.
Definition span.h:57
std::string hex(difficulty_type v)
static std::vector< uint8_t > vector(boost::string_ref src)
Definition hex.cpp:88
static epee::wipeable_string wipeable_string(const span< const std::uint8_t > src)
Definition hex.cpp:69
static std::string string(const span< const std::uint8_t > src)
Definition hex.cpp:68
static void formatted(std::ostream &out, const span< const std::uint8_t > src)
Append < + src + > as hex to out.
Definition hex.cpp:76
static void buffer(std::ostream &out, const span< const std::uint8_t > src)
Append src as hex to out.
Definition hex.cpp:71
#define T(x)