CDT  v4.2.0
инструменты разработчика
datastream.hpp
См. документацию.
5#pragma once
6#include "check.hpp"
7#include "varint.hpp"
8#include <bluegrass/meta/for_each.hpp>
9
10#include <list>
11#include <queue>
12#include <vector>
13#include <array>
14#include <set>
15#include <map>
16#include <string>
17#include <optional>
18#include <variant>
19
20#include <string.h>
21
22namespace eosio {
23
35template<typename T>
37 public:
45 datastream( T start, size_t s )
46 :_start(start),_pos(start),_end(start+s){}
47
53 inline void skip( size_t s ){ _pos += s; }
54
62 inline bool read( void* d, size_t s ) {
63 eosio::check( size_t(_end - _pos) >= (size_t)s, "datastream attempted to read past the end" );
64 memcpy( d, _pos, s );
65 _pos += s;
66 return true;
67 }
68
76 inline bool write( const char* d, size_t s ) {
77 eosio::check( _end - _pos >= (int32_t)s, "datastream attempted to write past the end" );
78 memcpy( (void*)_pos, d, s );
79 _pos += s;
80 return true;
81 }
82
89 inline bool write( char d ) {
90 eosio::check( _end - _pos >= 1, "datastream attempted to write past the end" );
91 *_pos++ = d;
92 return true;
93 }
94
102 inline bool write( const void* d, size_t s ) {
103 eosio::check( _end - _pos >= (int32_t)s, "datastream attempted to write past the end" );
104 memcpy( (void*)_pos, d, s );
105 _pos += s;
106 return true;
107 }
108
115 inline bool put(char c) {
116 eosio::check( _pos < _end, "put" );
117 *_pos = c;
118 ++_pos;
119 return true;
120 }
121
128 inline bool get( unsigned char& c ) { return get( *(char*)&c ); }
129
136 inline bool get( char& c )
137 {
138 eosio::check( _pos < _end, "get" );
139 c = *_pos;
140 ++_pos;
141 return true;
142 }
143
149 T pos()const { return _pos; }
150 inline bool valid()const { return _pos <= _end && _pos >= _start; }
151
159 inline bool seekp(size_t p) { _pos = _start + p; return _pos <= _end; }
160
166 inline size_t tellp()const { return size_t(_pos - _start); }
167
173 inline size_t remaining()const { return _end - _pos; }
174 private:
178 T _start;
182 T _pos;
186 T _end;
187};
188
192template<>
194 public:
200 datastream( size_t init_size = 0):_size(init_size){}
201
208 inline bool skip( size_t s ) { _size += s; return true; }
209
216 inline bool write( const char* ,size_t s ) { _size += s; return true; }
217
224 inline bool write( char ) { _size++; return true; }
225
232 inline bool write( const void* ,size_t s ) { _size += s; return true; }
233
239 inline bool put(char ) { ++_size; return true; }
240
246 inline bool valid()const { return true; }
247
254 inline bool seekp(size_t p) { _size = p; return true; }
255
261 inline size_t tellp()const { return _size; }
262
268 inline size_t remaining()const { return 0; }
269 private:
273 size_t _size;
274};
275
284template<typename Stream, typename T>
285inline datastream<Stream>& operator<<(datastream<Stream>& ds, const std::list<T>& l) {
286 ds << unsigned_int( l.size() );
287 for ( const auto& elem : l )
288 ds << elem;
289 return ds;
290}
291
300template<typename Stream, typename T>
301inline datastream<Stream>& operator>>(datastream<Stream>& ds, std::list<T>& l) {
302 unsigned_int s;
303 ds >> s;
304 l.resize(s.value);
305 for( auto& i : l )
306 ds >> i;
307 return ds;
308}
309
318template<typename Stream, typename T>
319inline datastream<Stream>& operator<<(datastream<Stream>& ds, const std::deque<T>& d) {
320 ds << unsigned_int( d.size() );
321 for ( const auto& elem : d )
322 ds << elem;
323 return ds;
324}
325
334template<typename Stream, typename T>
335inline datastream<Stream>& operator>>(datastream<Stream>& ds, std::deque<T>& d) {
336 unsigned_int s;
337 ds >> s;
338 d.resize(s.value);
339 for( auto& i : d )
340 ds >> i;
341 return ds;
342}
343
352template<typename Stream, typename... Ts>
353inline datastream<Stream>& operator<<(datastream<Stream>& ds, const std::variant<Ts...>& var) {
354 unsigned_int index = var.index();
355 ds << index;
356 std::visit([&ds](auto& val){ ds << val; }, var);
357 return ds;
358}
359
360template<int I, typename Stream, typename... Ts>
361void deserialize(datastream<Stream>& ds, std::variant<Ts...>& var, int i) {
362 if constexpr (I < std::variant_size_v<std::variant<Ts...>>) {
363 if (i == I) {
364 std::variant_alternative_t<I, std::variant<Ts...>> tmp;
365 ds >> tmp;
366 var.template emplace<I>(std::move(tmp));
367 } else {
368 deserialize<I+1>(ds,var,i);
369 }
370 } else {
371 eosio::check(false, "invalid variant index");
372 }
373}
374
383template<typename Stream, typename... Ts>
384inline datastream<Stream>& operator>>(datastream<Stream>& ds, std::variant<Ts...>& var) {
385 unsigned_int index;
386 ds >> index;
387 deserialize<0>(ds,var,index);
388 return ds;
389}
390
400template<typename Stream, typename T1, typename T2>
401datastream<Stream>& operator<<( datastream<Stream>& ds, const std::pair<T1, T2>& t ) {
402 ds << std::get<0>(t);
403 ds << std::get<1>(t);
404 return ds;
405}
406
416template<typename Stream, typename T1, typename T2>
417datastream<Stream>& operator>>( datastream<Stream>& ds, std::pair<T1, T2>& t ) {
418 T1 t1;
419 T2 t2;
420 ds >> t1;
421 ds >> t2;
422 t = std::pair<T1, T2>{t1, t2};
423 return ds;
424}
425
434template<typename Stream, typename T>
435inline datastream<Stream>& operator<<(datastream<Stream>& ds, const std::optional<T>& opt) {
436 char valid = opt.has_value();
437 ds << valid;
438 if (valid)
439 ds << *opt;
440 return ds;
441}
442
451template<typename Stream, typename T>
452inline datastream<Stream>& operator>>(datastream<Stream>& ds, std::optional<T>& opt) {
453 char valid = 0;
454 ds >> valid;
455 if (valid) {
456 T val;
457 ds >> val;
458 opt = val;
459 }
460 return ds;
461}
462
463
472template<typename Stream>
473inline datastream<Stream>& operator<<(datastream<Stream>& ds, const bool& d) {
474 return ds << uint8_t(d);
475}
476
485template<typename Stream>
487 uint8_t t;
488 ds >> t;
489 d = t;
490 return ds;
491}
492
501template<typename Stream>
502datastream<Stream>& operator << ( datastream<Stream>& ds, const std::string& v ) {
503 ds << unsigned_int( v.size() );
504 if (v.size())
505 ds.write(v.data(), v.size());
506 return ds;
507}
508
517template<typename Stream>
519 std::vector<char> tmp;
520 ds >> tmp;
521 if( tmp.size() )
522 v = std::string(tmp.data(),tmp.data()+tmp.size());
523 else
524 v = std::string();
525 return ds;
526}
527
538template<typename Stream, typename T, std::size_t N>
539datastream<Stream>& operator << ( datastream<Stream>& ds, const std::array<T,N>& v ) {
540 for( const auto& i : v )
541 ds << i;
542 return ds;
543}
544
545
556template<typename Stream, typename T, std::size_t N>
558 for( auto& i : v )
559 ds >> i;
560 return ds;
561}
562
563namespace _datastream_detail {
571 template<typename T>
572 constexpr bool is_pointer() {
573 return std::is_pointer<T>::value ||
574 std::is_null_pointer<T>::value ||
575 std::is_member_pointer<T>::value;
576 }
577
585 template<typename T>
586 constexpr bool is_primitive() {
587 return std::is_arithmetic<T>::value ||
588 std::is_enum<T>::value;
589 }
590
591 /*
592 * Проверяет, является ли T специализацией datastream
593 *
594 * @tparam T - Проверяемый тип
595 */
596 template<typename T>
597 struct is_datastream { static constexpr bool value = false; };
598 template<typename T>
599 struct is_datastream<datastream<T>> { static constexpr bool value = true; };
600}
601
612template<typename Stream, typename T, std::enable_if_t<_datastream_detail::is_pointer<T>()>* = nullptr>
614 static_assert(!_datastream_detail::is_pointer<T>(), "Pointers should not be serialized" );
615 return ds;
616}
617
627template<typename Stream, typename T, std::size_t N,
628 std::enable_if_t<!_datastream_detail::is_primitive<T>() &&
629 !_datastream_detail::is_pointer<T>()>* = nullptr>
630datastream<Stream>& operator << ( datastream<Stream>& ds, const T (&v)[N] ) {
631 ds << unsigned_int( N );
632 for( uint32_t i = 0; i < N; ++i )
633 ds << v[i];
634 return ds;
635}
636
646template<typename Stream, typename T, std::size_t N,
647 std::enable_if_t<_datastream_detail::is_primitive<T>()>* = nullptr>
648datastream<Stream>& operator << ( datastream<Stream>& ds, const T (&v)[N] ) {
649 ds << unsigned_int( N );
650 ds.write((char*)&v[0], sizeof(v));
651 return ds;
652}
653
664template<typename Stream, typename T, std::size_t N,
665 std::enable_if_t<!_datastream_detail::is_primitive<T>() &&
666 !_datastream_detail::is_pointer<T>()>* = nullptr>
668 unsigned_int s;
669 ds >> s;
670 eosio::check( N == s.value, "T[] size and unpacked size don't match");
671 for( uint32_t i = 0; i < N; ++i )
672 ds >> v[i];
673 return ds;
674}
675
686template<typename Stream, typename T, std::size_t N,
687 std::enable_if_t<_datastream_detail::is_primitive<T>()>* = nullptr>
689 unsigned_int s;
690 ds >> s;
691 eosio::check( N == s.value, "T[] size and unpacked size don't match");
692 ds.read((char*)&v[0], sizeof(v));
693 return ds;
694}
695
704template<typename Stream, typename T,
705 std::enable_if_t<_datastream_detail::is_primitive<T>()>* = nullptr>
706datastream<Stream>& operator << ( datastream<Stream>& ds, const std::vector<T>& v ) {
707 ds << unsigned_int( v.size() );
708 ds.write( (const void*)v.data(), v.size()*sizeof(T) );
709 return ds;
710}
711
721template<typename Stream, typename T,
722 std::enable_if_t<!_datastream_detail::is_primitive<T>()>* = nullptr>
723datastream<Stream>& operator << ( datastream<Stream>& ds, const std::vector<T>& v ) {
724 ds << unsigned_int( v.size() );
725 for( const auto& i : v )
726 ds << i;
727 return ds;
728}
729
738template<typename Stream, typename T,
739 std::enable_if_t<_datastream_detail::is_primitive<T>()>* = nullptr>
741 unsigned_int s;
742 ds >> s;
743 v.resize( s.value );
744 ds.read( (char*)v.data(), v.size()*sizeof(T) );
745 return ds;
746}
747
757template<typename Stream, typename T,
758 std::enable_if_t<!_datastream_detail::is_primitive<T>()>* = nullptr>
760 unsigned_int s;
761 ds >> s;
762 v.resize(s.value);
763 for( auto& i : v )
764 ds >> i;
765 return ds;
766}
767
777template<typename Stream, typename T>
778datastream<Stream>& operator << ( datastream<Stream>& ds, const std::basic_string<T>& s ) {
779 ds << unsigned_int(s.size());
780 if (s.size())
781 ds.write(s.data(), s.size()*sizeof(T));
782 return ds;
783}
784
794template<typename Stream, typename T>
795datastream<Stream>& operator >> ( datastream<Stream>& ds, std::basic_string<T>& s ) {
796 unsigned_int v;
797 ds >> v;
798 s.resize(v.value);
799 ds.read(s.data(), s.size()*sizeof(T));
800 return ds;
801}
802
812template<typename Stream>
813datastream<Stream>& operator << ( datastream<Stream>& ds, const std::basic_string<uint8_t>& s ) {
814 ds << unsigned_int(s.size());
815 if (s.size())
816 ds.write(s.data(), s.size());
817 return ds;
818}
819
829template<typename Stream>
830datastream<Stream>& operator >> ( datastream<Stream>& ds, std::basic_string<uint8_t>& s ) {
831 unsigned_int v;
832 ds >> v;
833 s.resize(v.value);
834 ds.read(s.data(), s.size());
835 return ds;
836}
837
838
848template<typename Stream, typename T>
849datastream<Stream>& operator << ( datastream<Stream>& ds, const std::set<T>& s ) {
850 ds << unsigned_int( s.size() );
851 for( const auto& i : s ) {
852 ds << i;
853 }
854 return ds;
855}
856
857
867template<typename Stream, typename T>
869 s.clear();
870 unsigned_int sz; ds >> sz;
871
872 for( uint32_t i = 0; i < sz.value; ++i ) {
873 T v;
874 ds >> v;
875 s.emplace( std::move(v) );
876 }
877 return ds;
878}
879
890template<typename Stream, typename K, typename V>
891datastream<Stream>& operator << ( datastream<Stream>& ds, const std::map<K,V>& m ) {
892 ds << unsigned_int( m.size() );
893 for( const auto& i : m ) {
894 ds << i.first << i.second;
895 }
896 return ds;
897}
898
909template<typename Stream, typename K, typename V>
911 m.clear();
912 unsigned_int s; ds >> s;
913
914 for (uint32_t i = 0; i < s.value; ++i) {
915 K k; V v;
916 ds >> k >> v;
917 m.emplace( std::move(k), std::move(v) );
918 }
919 return ds;
920}
921
931template<typename Stream, typename... Args>
932datastream<Stream>& operator<<( datastream<Stream>& ds, const std::tuple<Args...>& t ) {
933 bluegrass::meta::for_each( t, [&]( const auto& i ) {
934 ds << i;
935 });
936 return ds;
937}
938
948template<typename Stream, typename... Args>
949datastream<Stream>& operator>>( datastream<Stream>& ds, std::tuple<Args...>& t ) {
950 bluegrass::meta::for_each( t, [&]( auto& i ) {
951 ds >> i;
952 });
953 return ds;
954}
955
965template<typename DataStream, typename T, std::enable_if_t<std::is_class<T>::value && _datastream_detail::is_datastream<DataStream>::value>* = nullptr>
966DataStream& operator<<( DataStream& ds, const T& v ) {
967 bluegrass::meta::for_each_field(v, [&](const auto& field) {
968 ds << field;
969 });
970 return ds;
971}
972
982template<typename DataStream, typename T, std::enable_if_t<std::is_class<T>::value && _datastream_detail::is_datastream<DataStream>::value>* = nullptr>
983DataStream& operator>>( DataStream& ds, T& v ) {
984 bluegrass::meta::for_each_field(v, [&](auto& field) {
985 ds >> field;
986 });
987 return ds;
988}
989
999template<typename Stream, typename T, std::enable_if_t<_datastream_detail::is_primitive<T>()>* = nullptr>
1000datastream<Stream>& operator<<( datastream<Stream>& ds, const T& v ) {
1001 ds.write( (const char*)&v, sizeof(T) );
1002 return ds;
1003}
1004
1014template<typename Stream, typename T, std::enable_if_t<_datastream_detail::is_primitive<T>()>* = nullptr>
1016 ds.read( (char*)&v, sizeof(T) );
1017 return ds;
1018}
1019
1029template<typename T>
1030T unpack( const char* buffer, size_t len ) {
1031 T result;
1032 datastream<const char*> ds(buffer,len);
1033 ds >> result;
1034 return result;
1035}
1036
1046template<typename T>
1047void unpack( T& res, const char* buffer, size_t len ) {
1048 datastream<const char*> ds(buffer,len);
1049 ds >> res;
1050}
1051
1060template<typename T>
1061T unpack( const std::vector<char>& bytes ) {
1062 return unpack<T>( bytes.data(), bytes.size() );
1063}
1064
1073template<typename T>
1074size_t pack_size( const T& value ) {
1076 ps << value;
1077 return ps.tellp();
1078}
1079
1088template<typename T>
1089std::vector<char> pack( const T& value ) {
1090 std::vector<char> result;
1091 result.resize(pack_size(value));
1092
1093 datastream<char*> ds( result.data(), result.size() );
1094 ds << value;
1095 return result;
1096}
1097}