CDT  v4.2.0
инструменты разработчика
fixed_bytes.hpp
См. документацию.
1
5#pragma once
6#include "datastream.hpp"
7
8#include <array>
9#include <algorithm>
10#include <functional>
11#include <type_traits>
12
13namespace eosio {
14
16
17 template<size_t Size>
18 class fixed_bytes;
19
20 template<size_t Size>
21 bool operator ==(const fixed_bytes<Size> &c1, const fixed_bytes<Size> &c2);
22
23 template<size_t Size>
24 bool operator !=(const fixed_bytes<Size> &c1, const fixed_bytes<Size> &c2);
25
26 template<size_t Size>
27 bool operator >(const fixed_bytes<Size> &c1, const fixed_bytes<Size> &c2);
28
29 template<size_t Size>
30 bool operator <(const fixed_bytes<Size> &c1, const fixed_bytes<Size> &c2);
31
32 template<size_t Size>
33 bool operator >=(const fixed_bytes<Size> &c1, const fixed_bytes<Size> &c2);
34
35 template<size_t Size>
36 bool operator <=(const fixed_bytes<Size> &c1, const fixed_bytes<Size> &c2);
37
39
53 template<size_t Size>
55 private:
56
57 template<bool...> struct bool_pack;
58 template<bool... bs>
59 using all_true = std::is_same< bool_pack<bs..., true>, bool_pack<true, bs...> >;
60
61 template<typename Word, size_t NumWords>
62 static void set_from_word_sequence(const Word* arr_begin, const Word* arr_end, fixed_bytes<Size>& key)
63 {
64 auto itr = key._data.begin();
65 word_t temp_word = 0;
66 const size_t sub_word_shift = 8 * sizeof(Word);
67 const size_t num_sub_words = sizeof(word_t) / sizeof(Word);
68 auto sub_words_left = num_sub_words;
69 for( auto w_itr = arr_begin; w_itr != arr_end; ++w_itr ) {
70 if( sub_words_left > 1 ) {
71 temp_word |= static_cast<word_t>(*w_itr);
72 temp_word <<= sub_word_shift;
73 --sub_words_left;
74 continue;
75 }
76
77 eosio::check( sub_words_left == 1, "unexpected error in fixed_bytes constructor" );
78 temp_word |= static_cast<word_t>(*w_itr);
79 sub_words_left = num_sub_words;
80
81 *itr = temp_word;
82 temp_word = 0;
83 ++itr;
84 }
85 if( sub_words_left != num_sub_words ) {
86 if( sub_words_left > 1 )
87 temp_word <<= 8 * (sub_words_left-1);
88 *itr = temp_word;
89 }
90 }
91
92 public:
93
94 typedef uint128_t word_t;
95
100 static constexpr size_t num_words() { return (Size + sizeof(word_t) - 1) / sizeof(word_t); }
101
105 static constexpr size_t padded_bytes() { return num_words() * sizeof(word_t) - Size; }
106
110 constexpr fixed_bytes() : _data() {}
111
117 fixed_bytes(const std::array<word_t, num_words()>& arr)
118 {
119 std::copy(arr.begin(), arr.end(), _data.begin());
120 }
121
127 template<typename Word, size_t NumWords,
128 typename Enable = typename std::enable_if<std::is_integral<Word>::value &&
129 std::is_unsigned<Word>::value &&
130 !std::is_same<Word, bool>::value &&
131 std::less<size_t>{}(sizeof(Word), sizeof(word_t))>::type >
132 fixed_bytes(const std::array<Word, NumWords>& arr)
133 {
134 static_assert( sizeof(word_t) == (sizeof(word_t)/sizeof(Word)) * sizeof(Word),
135 "size of the backing word size is not divisible by the size of the array element" );
136 static_assert( sizeof(Word) * NumWords <= Size, "too many words supplied to fixed_bytes constructor" );
137
138 set_from_word_sequence<Word, NumWords>(arr.data(), arr.data() + arr.size(), *this);
139 }
140
146 template<typename Word, size_t NumWords,
147 typename Enable = typename std::enable_if<std::is_integral<Word>::value &&
148 std::is_unsigned<Word>::value &&
149 !std::is_same<Word, bool>::value &&
150 std::less<size_t>{}(sizeof(Word), sizeof(word_t))>::type >
151 fixed_bytes(const Word(&arr)[NumWords])
152 {
153 static_assert( sizeof(word_t) == (sizeof(word_t)/sizeof(Word)) * sizeof(Word),
154 "size of the backing word size is not divisible by the size of the array element" );
155 static_assert( sizeof(Word) * NumWords <= Size, "too many words supplied to fixed_bytes constructor" );
156
157 set_from_word_sequence<Word, NumWords>(arr, arr + NumWords, *this);
158 }
159
168 template<typename FirstWord, typename... Rest>
169 static
171 make_from_word_sequence(typename std::enable_if<std::is_integral<FirstWord>::value &&
172 std::is_unsigned<FirstWord>::value &&
173 !std::is_same<FirstWord, bool>::value &&
174 sizeof(FirstWord) <= sizeof(word_t) &&
175 all_true<(std::is_same<FirstWord, Rest>::value)...>::value,
176 FirstWord>::type first_word,
177 Rest... rest)
178 {
179 static_assert( sizeof(word_t) == (sizeof(word_t)/sizeof(FirstWord)) * sizeof(FirstWord),
180 "size of the backing word size is not divisible by the size of the words supplied as arguments" );
181 static_assert( sizeof(FirstWord) * (1 + sizeof...(Rest)) <= Size, "too many words supplied to make_from_word_sequence" );
182
184 std::array<FirstWord, 1+sizeof...(Rest)> arr{{ first_word, rest... }};
185 set_from_word_sequence<FirstWord, 1+sizeof...(Rest)>(arr.data(), arr.data() + arr.size(), key);
186 return key;
187 }
188
192 const auto& get_array()const { return _data; }
193
197 auto data() { return _data.data(); }
198
200
204 auto data()const { return _data.data(); }
205
207
211 auto size()const { return _data.size(); }
212
213
219 std::array<uint8_t, Size> extract_as_byte_array()const {
220 std::array<uint8_t, Size> arr;
221
222 const size_t num_sub_words = sizeof(word_t);
223
224 auto arr_itr = arr.begin();
225 auto data_itr = _data.begin();
226
227 for( size_t counter = _data.size(); counter > 0; --counter, ++data_itr ) {
228 size_t sub_words_left = num_sub_words;
229
230 auto temp_word = *data_itr;
231 if( counter == 1 ) { // If last word in _data array...
232 sub_words_left -= padded_bytes();
233 temp_word >>= 8*padded_bytes();
234 }
235 for( ; sub_words_left > 0; --sub_words_left ) {
236 *(arr_itr + sub_words_left - 1) = static_cast<uint8_t>(temp_word & 0xFF);
237 temp_word >>= 8;
238 }
239 arr_itr += num_sub_words;
240 }
241
242 return arr;
243 }
244
249 inline void print()const {
250 auto arr = extract_as_byte_array();
251 printhex(static_cast<const void*>(arr.data()), arr.size());
252 }
253
255
256 friend bool operator == <>(const fixed_bytes<Size> &c1, const fixed_bytes<Size> &c2);
257
258 friend bool operator != <>(const fixed_bytes<Size> &c1, const fixed_bytes<Size> &c2);
259
260 friend bool operator > <>(const fixed_bytes<Size> &c1, const fixed_bytes<Size> &c2);
261
262 friend bool operator < <>(const fixed_bytes<Size> &c1, const fixed_bytes<Size> &c2);
263
264 friend bool operator >= <>(const fixed_bytes<Size> &c1, const fixed_bytes<Size> &c2);
265
266 friend bool operator <= <>(const fixed_bytes<Size> &c1, const fixed_bytes<Size> &c2);
267
269
270 private:
271
272 std::array<word_t, num_words()> _data;
273 };
274
276
284 template<size_t Size>
285 bool operator ==(const fixed_bytes<Size> &c1, const fixed_bytes<Size> &c2) {
286 return c1._data == c2._data;
287 }
288
296 template<size_t Size>
297 bool operator !=(const fixed_bytes<Size> &c1, const fixed_bytes<Size> &c2) {
298 return c1._data != c2._data;
299 }
300
308 template<size_t Size>
309 bool operator >(const fixed_bytes<Size>& c1, const fixed_bytes<Size>& c2) {
310 return c1._data > c2._data;
311 }
312
320 template<size_t Size>
321 bool operator <(const fixed_bytes<Size> &c1, const fixed_bytes<Size> &c2) {
322 return c1._data < c2._data;
323 }
324
332 template<size_t Size>
333 bool operator >=(const fixed_bytes<Size>& c1, const fixed_bytes<Size>& c2) {
334 return c1._data >= c2._data;
335 }
336
344 template<size_t Size>
345 bool operator <=(const fixed_bytes<Size> &c1, const fixed_bytes<Size> &c2) {
346 return c1._data <= c2._data;
347 }
348
349
350 using checksum160 = fixed_bytes<20>;
351 using checksum256 = fixed_bytes<32>;
352 using checksum512 = fixed_bytes<64>;
353
363 template<typename DataStream, size_t Size>
364 inline DataStream& operator<<(DataStream& ds, const fixed_bytes<Size>& d) {
365 auto arr = d.extract_as_byte_array();
366 ds.write( (const char*)arr.data(), arr.size() );
367 return ds;
368 }
369
379 template<typename DataStream, size_t Size>
380 inline DataStream& operator>>(DataStream& ds, fixed_bytes<Size>& d) {
381 std::array<uint8_t, Size> arr;
382 ds.read( (char*)arr.data(), arr.size() );
383 d = fixed_bytes<Size>( arr );
384 return ds;
385 }
386
388}