Line data Source code
1 : /*
2 : This file is part of cpp-ethereum.
3 :
4 : cpp-ethereum is free software: you can redistribute it and/or modify
5 : it under the terms of the GNU General Public License as published by
6 : the Free Software Foundation, either version 3 of the License, or
7 : (at your option) any later version.
8 :
9 : cpp-ethereum is distributed in the hope that it will be useful,
10 : but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : GNU General Public License for more details.
13 :
14 : You should have received a copy of the GNU General Public License
15 : along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 : /** @file CommonData.h
18 : * @author Gav Wood <i@gavwood.com>
19 : * @date 2014
20 : *
21 : * Shared algorithms and data types.
22 : */
23 :
24 : #pragma once
25 :
26 : #include <vector>
27 : #include <algorithm>
28 : #include <unordered_set>
29 : #include <type_traits>
30 : #include <cstring>
31 : #include <string>
32 : #include "Common.h"
33 :
34 : namespace dev {
35 :
36 : // String conversion functions, mainly to/from hex/nibble/byte representations.
37 :
38 : enum class WhenError {
39 : DontThrow = 0,
40 : Throw = 1,
41 : };
42 :
43 : template<class Iterator>
44 : std::string
45 784 : toHex(Iterator _it, Iterator _end, std::string _prefix)
46 : {
47 : typedef std::iterator_traits<Iterator> traits;
48 : static_assert(sizeof(typename traits::value_type) == 1, "toHex needs byte-sized element type");
49 :
50 : static char const* hexdigits = "0123456789abcdef";
51 784 : size_t off = _prefix.size();
52 784 : std::string hex(std::distance(_it, _end) * 2 + off, '0');
53 784 : hex.replace(0, off, _prefix);
54 16464 : for (; _it != _end; _it++) {
55 15680 : hex[off++] = hexdigits[(*_it >> 4) & 0x0f];
56 15680 : hex[off++] = hexdigits[*_it & 0x0f];
57 : }
58 784 : return hex;
59 0 : }
60 :
61 : /// Convert a series of bytes to the corresponding hex string.
62 : /// @example toHex("A\x69") == "4169"
63 : template<class T>
64 : std::string
65 784 : toHex(T const& _data)
66 : {
67 784 : return toHex(_data.begin(), _data.end(), "");
68 : }
69 :
70 : /// Convert a series of bytes to the corresponding hex string with 0x prefix.
71 : /// @example toHexPrefixed("A\x69") == "0x4169"
72 : template<class T>
73 : std::string
74 : toHexPrefixed(T const& _data)
75 : {
76 : return toHex(_data.begin(), _data.end(), "0x");
77 : }
78 :
79 : /// Converts a (printable) ASCII hex string into the corresponding byte stream.
80 : /// @example fromHex("41626261") == asBytes("Abba")
81 : /// If _throw = ThrowType::DontThrow, it replaces bad hex characters with 0's, otherwise it will
82 : /// throw an exception.
83 : bytes fromHex(std::string const& _s, WhenError _throw = WhenError::DontThrow);
84 :
85 : /// @returns true if @a _s is a hex string.
86 : bool isHex(std::string const& _s) noexcept;
87 :
88 : /// @returns true if @a _hash is a hash conforming to FixedHash type @a T.
89 : template<class T>
90 : static bool
91 : isHash(std::string const& _hash)
92 : {
93 : return (_hash.size() == T::size * 2
94 : || (_hash.size() == T::size * 2 + 2 && _hash.substr(0, 2) == "0x"))
95 : && isHex(_hash);
96 : }
97 :
98 : /// Converts byte array to a string containing the same (binary) data. Unless
99 : /// the byte array happens to contain ASCII data, this won't be printable.
100 : inline std::string
101 : asString(bytes const& _b)
102 : {
103 : return std::string((char const*) _b.data(), (char const*) (_b.data() + _b.size()));
104 : }
105 :
106 : /// Converts byte array ref to a string containing the same (binary) data. Unless
107 : /// the byte array happens to contain ASCII data, this won't be printable.
108 : inline std::string
109 : asString(bytesConstRef _b)
110 : {
111 : return std::string((char const*) _b.data(), (char const*) (_b.data() + _b.size()));
112 : }
113 :
114 : /// Converts a string to a byte array containing the string's (byte) data.
115 : inline bytes
116 0 : asBytes(std::string const& _b)
117 : {
118 0 : return bytes((uint8_t const*) _b.data(), (uint8_t const*) (_b.data() + _b.size()));
119 : }
120 :
121 : /// Converts a string into the big-endian base-16 stream of integers (NOT ASCII).
122 : /// @example asNibbles("A")[0] == 4 && asNibbles("A")[1] == 1
123 : bytes asNibbles(bytesConstRef const& _s);
124 :
125 : // Big-endian to/from host endian conversion functions.
126 :
127 : /// Converts a big-endian byte-stream represented on a templated collection to a templated integer
128 : /// value.
129 : /// @a _In will typically be either std::string or bytes.
130 : /// @a T will typically by unsigned, u160, u256 or bigint.
131 : template<class T, class _In>
132 : inline T
133 : fromBigEndian(_In const& _bytes)
134 : {
135 : T ret = (T) 0;
136 : for (auto i : _bytes)
137 : ret = (T)((ret << 8) | (uint8_t)(typename std::make_unsigned<decltype(i)>::type) i);
138 : return ret;
139 : }
140 :
141 : inline bytes
142 : toCompactBigEndian(uint8_t _val, unsigned _min = 0)
143 : {
144 : return (_min || _val) ? bytes {_val} : bytes {};
145 : }
146 :
147 : // Algorithms for string and string-like collections.
148 :
149 : /// Determines the length of the common prefix of the two collections given.
150 : /// @returns the number of elements both @a _t and @a _u share, in order, at the beginning.
151 : /// @example commonPrefix("Hello world!", "Hello, world!") == 5
152 : template<class T, class _U>
153 : unsigned
154 : commonPrefix(T const& _t, _U const& _u)
155 : {
156 : unsigned s = std::min<unsigned>(_t.size(), _u.size());
157 : for (unsigned i = 0;; ++i)
158 : if (i == s || _t[i] != _u[i])
159 : return i;
160 : return s;
161 : }
162 :
163 : /// Trims a given number of elements from the front of a collection.
164 : /// Only works for POD element types.
165 : template<class T>
166 : void
167 : trimFront(T& _t, unsigned _elements)
168 : {
169 : static_assert(std::is_pod<typename T::value_type>::value, "");
170 : memmove(_t.data(), _t.data() + _elements, (_t.size() - _elements) * sizeof(_t[0]));
171 : _t.resize(_t.size() - _elements);
172 : }
173 :
174 : /// Pushes an element on to the front of a collection.
175 : /// Only works for POD element types.
176 : template<class T, class _U>
177 : void
178 : pushFront(T& _t, _U _e)
179 : {
180 : static_assert(std::is_pod<typename T::value_type>::value, "");
181 : _t.push_back(_e);
182 : memmove(_t.data() + 1, _t.data(), (_t.size() - 1) * sizeof(_e));
183 : _t[0] = _e;
184 : }
185 :
186 : /// Concatenate two vectors of elements of POD types.
187 : template<class T>
188 : inline std::vector<T>&
189 : operator+=(std::vector<typename std::enable_if<std::is_pod<T>::value, T>::type>& _a,
190 : std::vector<T> const& _b)
191 : {
192 : auto s = _a.size();
193 : _a.resize(_a.size() + _b.size());
194 : memcpy(_a.data() + s, _b.data(), _b.size() * sizeof(T));
195 : return _a;
196 : }
197 :
198 : /// Concatenate two vectors of elements.
199 : template<class T>
200 : inline std::vector<T>&
201 : operator+=(std::vector<typename std::enable_if<!std::is_pod<T>::value, T>::type>& _a,
202 : std::vector<T> const& _b)
203 : {
204 : _a.reserve(_a.size() + _b.size());
205 : for (auto& i : _b)
206 : _a.push_back(i);
207 : return _a;
208 : }
209 :
210 : /// Insert the contents of a container into a set
211 : template<class T, class U>
212 : std::set<T>&
213 : operator+=(std::set<T>& _a, U const& _b)
214 : {
215 : for (auto const& i : _b)
216 : _a.insert(i);
217 : return _a;
218 : }
219 :
220 : /// Insert the contents of a container into an unordered_set
221 : template<class T, class U>
222 : std::unordered_set<T>&
223 : operator+=(std::unordered_set<T>& _a, U const& _b)
224 : {
225 : for (auto const& i : _b)
226 : _a.insert(i);
227 : return _a;
228 : }
229 :
230 : /// Concatenate the contents of a container onto a vector
231 : template<class T, class U>
232 : std::vector<T>&
233 : operator+=(std::vector<T>& _a, U const& _b)
234 : {
235 : for (auto const& i : _b)
236 : _a.push_back(i);
237 : return _a;
238 : }
239 :
240 : /// Insert the contents of a container into a set
241 : template<class T, class U>
242 : std::set<T>
243 : operator+(std::set<T> _a, U const& _b)
244 : {
245 : return _a += _b;
246 : }
247 :
248 : /// Insert the contents of a container into an unordered_set
249 : template<class T, class U>
250 : std::unordered_set<T>
251 : operator+(std::unordered_set<T> _a, U const& _b)
252 : {
253 : return _a += _b;
254 : }
255 :
256 : /// Concatenate the contents of a container onto a vector
257 : template<class T, class U>
258 : std::vector<T>
259 : operator+(std::vector<T> _a, U const& _b)
260 : {
261 : return _a += _b;
262 : }
263 :
264 : /// Concatenate two vectors of elements.
265 : template<class T>
266 : inline std::vector<T>
267 : operator+(std::vector<T> const& _a, std::vector<T> const& _b)
268 : {
269 : std::vector<T> ret(_a);
270 : return ret += _b;
271 : }
272 :
273 : template<class T, class U>
274 : std::vector<T>
275 : keysOf(std::map<T, U> const& _m)
276 : {
277 : std::vector<T> ret;
278 : for (auto const& i : _m)
279 : ret.push_back(i.first);
280 : return ret;
281 : }
282 :
283 : template<class T, class U>
284 : std::vector<T>
285 : keysOf(std::unordered_map<T, U> const& _m)
286 : {
287 : std::vector<T> ret;
288 : for (auto const& i : _m)
289 : ret.push_back(i.first);
290 : return ret;
291 : }
292 :
293 : template<class T, class U>
294 : std::vector<U>
295 : valuesOf(std::map<T, U> const& _m)
296 : {
297 : std::vector<U> ret;
298 : ret.reserve(_m.size());
299 : for (auto const& i : _m)
300 : ret.push_back(i.second);
301 : return ret;
302 : }
303 :
304 : template<class T, class U>
305 : std::vector<U>
306 : valuesOf(std::unordered_map<T, U> const& _m)
307 : {
308 : std::vector<U> ret;
309 : ret.reserve(_m.size());
310 : for (auto const& i : _m)
311 : ret.push_back(i.second);
312 : return ret;
313 : }
314 :
315 : template<class T, class V>
316 : bool
317 : contains(T const& _t, V const& _v)
318 : {
319 : return std::end(_t) != std::find(std::begin(_t), std::end(_t), _v);
320 : }
321 :
322 : } // namespace dev
|