BitShares-Core  7.0.2
BitShares blockchain node software and command-line wallet software
ext.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cryptonomex, Inc., and contributors.
3  *
4  * The MIT License
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #pragma once
25 
26 #include <fc/io/varint.hpp>
27 #include <fc/io/raw_fwd.hpp>
28 #include <fc/reflect/reflect.hpp>
30 
31 namespace graphene { namespace protocol {
32 
33 using fc::unsigned_int;
34 
35 template< typename T >
36 struct extension
37 {
38  extension() {}
39 
40  T value;
41 };
42 
43 template< typename T >
45 {
47 
48  template<typename Member, class Class, Member (Class::*member)>
49  void operator()( const char* name )const
50  {
51  count += ((value.*member).valid()) ? 1 : 0;
52  }
53 
54  const T& value;
55  mutable uint32_t count = 0;
56 };
57 
58 template< typename Stream, typename T >
60 {
61  graphene_extension_pack_read_visitor( Stream& s, const T& v, uint32_t _max_depth )
62  : stream(s), value(v), max_depth(_max_depth - 1)
63  {
64  FC_ASSERT( _max_depth > 0 );
65  }
66 
67  template<typename Member, class Class, Member (Class::*member)>
68  void operator()( const char* name )const
69  {
70  if( (value.*member).valid() )
71  {
73  fc::raw::pack( stream, *(value.*member), max_depth );
74  }
75  ++which;
76  }
77 
78  Stream& stream;
79  const T& value;
80  mutable uint32_t which = 0;
81  const uint32_t max_depth;
82 };
83 
84 
85 template< typename Stream, typename T >
87 {
88  graphene_extension_unpack_visitor( Stream& s, T& v, uint32_t _max_depth )
89  : stream(s), value(v), max_depth(_max_depth - 1)
90  {
91  FC_ASSERT( _max_depth > 0 );
92  unsigned_int c;
94  count_left = c.value;
96  }
97 
99  {
100  if( count_left > 0 )
101  {
102  unsigned_int w;
104  next_which = w.value;
105  }
106  }
107 
108  template< typename Member, class Class, Member (Class::*member)>
109  void operator()( const char* name )const
110  {
111  if( (count_left > 0) && (which == next_which) )
112  {
113  typename Member::value_type temp;
114  fc::raw::unpack( stream, temp, max_depth );
115  (value.*member) = temp;
116  --count_left;
118  }
119  else
120  (value.*member).reset();
121  ++which;
122  }
123 
124  mutable uint32_t which = 0;
125  mutable uint32_t next_which = 0;
126  mutable uint32_t count_left = 0;
127 
128  Stream& stream;
129  T& value;
130  const uint32_t max_depth;
131 };
132 
133 } } // graphene::protocol
134 
135 namespace fc {
136 
137 template< typename T >
139 {
140  graphene_extension_from_variant_visitor( const variant_object& v, T& val, uint32_t max_depth )
141  : vo( v ), value( val ), _max_depth(max_depth - 1)
142  {
143  FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" );
144  count_left = vo.size();
145  }
146 
147  template<typename Member, class Class, Member (Class::*member)>
148  void operator()( const char* name )const
149  {
150  auto it = vo.find(name);
151  if( it != vo.end() )
152  {
153  from_variant( it->value(), (value.*member), _max_depth );
154  assert( count_left > 0 ); // x.find(k) returns true for n distinct values of k only if x.size() >= n
155  --count_left;
156  }
157  }
158 
160  T& value;
161  const uint32_t _max_depth;
162  mutable uint32_t count_left = 0;
163 };
164 
165 template< typename T >
166 void from_variant( const fc::variant& var, graphene::protocol::extension<T>& value, uint32_t max_depth )
167 {
169  if( var.is_null() )
170  return;
171  if( var.is_array() )
172  {
173  FC_ASSERT( var.size() == 0 );
174  return;
175  }
176 
177  graphene_extension_from_variant_visitor<T> vtor( var.get_object(), value.value, max_depth );
178  fc::reflector<T>::visit( vtor );
179  FC_ASSERT( vtor.count_left == 0 ); // unrecognized extension throws here
180 }
181 
182 template< typename T >
184 {
185  graphene_extension_to_variant_visitor( const T& v, uint32_t max_depth ) : value(v), mvo(max_depth) {}
186 
187  template<typename Member, class Class, Member (Class::*member)>
188  void operator()( const char* name )const
189  {
190  if( (value.*member).valid() )
191  mvo( name, value.*member );
192  }
193 
194  const T& value;
196 };
197 
198 template< typename T >
199 void to_variant( const graphene::protocol::extension<T>& value, fc::variant& var, uint32_t max_depth )
200 {
201  graphene_extension_to_variant_visitor<T> vtor( value.value, max_depth );
202  fc::reflector<T>::visit( vtor );
203  var = vtor.mvo;
204 }
205 
206 namespace raw {
207 
208 template< typename Stream, typename T >
209 void pack( Stream& stream, const graphene::protocol::extension<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH )
210 {
211  FC_ASSERT( _max_depth > 0 );
212  --_max_depth;
214  fc::reflector<T>::visit( count_vtor );
215  fc::raw::pack( stream, unsigned_int( count_vtor.count ), _max_depth );
216  graphene::protocol::graphene_extension_pack_read_visitor<Stream,T> read_vtor( stream, value.value, _max_depth );
217  fc::reflector<T>::visit( read_vtor );
218 }
219 
220 
221 template< typename Stream, typename T >
222 void unpack( Stream& s, graphene::protocol::extension<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH )
223 {
224  FC_ASSERT( _max_depth > 0 );
225  --_max_depth;
228  fc::reflector<T>::visit( vtor );
229  FC_ASSERT( vtor.count_left == 0 ); // unrecognized extension throws here
230 }
231 
232 } // fc::raw
233 
234 template<typename T> struct get_typename< graphene::protocol::extension<T> >
235 {
236  static const char* name()
237  {
238  static std::string n = std::string("graphene::protocol::extension<")
239  + fc::get_typename<T>::name() + std::string(">");
240  return n.c_str();
241  }
242 };
243 
244 
245 } // fc
fc::variant_object::find
iterator find(const string &key) const
Definition: variant_object.cpp:64
FC_PACK_MAX_DEPTH
#define FC_PACK_MAX_DEPTH
Definition: config.hpp:3
graphene::protocol::graphene_extension_pack_count_visitor::count
uint32_t count
Definition: ext.hpp:55
fc::variant_object
An order-perserving dictionary of variant's.
Definition: variant_object.hpp:20
graphene::protocol::extension
Definition: ext.hpp:36
fc::graphene_extension_to_variant_visitor::value
const T & value
Definition: ext.hpp:194
fc::graphene_extension_from_variant_visitor
Definition: ext.hpp:138
graphene::protocol::graphene_extension_unpack_visitor::which
uint32_t which
Definition: ext.hpp:124
fc::graphene_extension_from_variant_visitor::graphene_extension_from_variant_visitor
graphene_extension_from_variant_visitor(const variant_object &v, T &val, uint32_t max_depth)
Definition: ext.hpp:140
graphene::protocol::graphene_extension_unpack_visitor::count_left
uint32_t count_left
Definition: ext.hpp:126
fc::raw::unpack
void unpack(Stream &s, flat_set< T, A... > &value, uint32_t _max_depth)
Definition: flat.hpp:23
graphene::protocol::graphene_extension_unpack_visitor::maybe_read_next_which
void maybe_read_next_which() const
Definition: ext.hpp:98
fc
Definition: api.hpp:15
fc::graphene_extension_from_variant_visitor::count_left
uint32_t count_left
Definition: ext.hpp:162
fc::graphene_extension_from_variant_visitor::operator()
void operator()(const char *name) const
Definition: ext.hpp:148
fc::graphene_extension_to_variant_visitor::graphene_extension_to_variant_visitor
graphene_extension_to_variant_visitor(const T &v, uint32_t max_depth)
Definition: ext.hpp:185
fc::variant::is_array
bool is_array() const
Definition: variant.cpp:368
fc::graphene_extension_to_variant_visitor::operator()
void operator()(const char *name) const
Definition: ext.hpp:188
fc::from_variant
void from_variant(const variant &var, flat_set< T, A... > &vo, uint32_t _max_depth)
Definition: flat.hpp:116
reflect.hpp
Defines types and macros used to provide reflection.
graphene::protocol::graphene_extension_unpack_visitor::max_depth
const uint32_t max_depth
Definition: ext.hpp:130
graphene::protocol::graphene_extension_pack_count_visitor::value
const T & value
Definition: ext.hpp:54
graphene::protocol::graphene_extension_pack_read_visitor::operator()
void operator()(const char *name) const
Definition: ext.hpp:68
fc::graphene_extension_to_variant_visitor::mvo
limited_mutable_variant_object mvo
Definition: ext.hpp:195
graphene::protocol::graphene_extension_pack_count_visitor::operator()
void operator()(const char *name) const
Definition: ext.hpp:49
graphene::protocol::graphene_extension_pack_read_visitor::max_depth
const uint32_t max_depth
Definition: ext.hpp:81
fc::unsigned_int
Definition: varint.hpp:6
fc::variant::size
size_t size() const
Definition: variant.cpp:570
fc::get_typename
Definition: typename.hpp:20
fc::variant_object::size
size_t size() const
Definition: variant_object.cpp:93
graphene::protocol::graphene_extension_unpack_visitor::value
T & value
Definition: ext.hpp:129
graphene::protocol::graphene_extension_pack_count_visitor
Definition: ext.hpp:44
graphene::protocol::graphene_extension_pack_read_visitor::value
const T & value
Definition: ext.hpp:79
fc::to_variant
void to_variant(const flat_set< T, A... > &var, variant &vo, uint32_t _max_depth)
Definition: flat.hpp:105
graphene::protocol::graphene_extension_pack_read_visitor::graphene_extension_pack_read_visitor
graphene_extension_pack_read_visitor(Stream &s, const T &v, uint32_t _max_depth)
Definition: ext.hpp:61
fc::limited_mutable_variant_object
Definition: variant_object.hpp:220
graphene::protocol::graphene_extension_unpack_visitor::graphene_extension_unpack_visitor
graphene_extension_unpack_visitor(Stream &s, T &v, uint32_t _max_depth)
Definition: ext.hpp:88
graphene::protocol::graphene_extension_pack_read_visitor::which
uint32_t which
Definition: ext.hpp:80
graphene::protocol::graphene_extension_unpack_visitor::operator()
void operator()(const char *name) const
Definition: ext.hpp:109
FC_ASSERT
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
graphene::protocol::graphene_extension_unpack_visitor::next_which
uint32_t next_which
Definition: ext.hpp:125
graphene::protocol::graphene_extension_pack_read_visitor::stream
Stream & stream
Definition: ext.hpp:78
fc::variant::get_object
variant_object & get_object()
Definition: variant.cpp:554
fc::variant
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object's.
Definition: variant.hpp:198
fc::unsigned_int::value
uint64_t value
Definition: varint.hpp:17
graphene::protocol::graphene_extension_unpack_visitor
Definition: ext.hpp:86
exception.hpp
Defines exception's used by fc.
fc::variant::is_null
bool is_null() const
Definition: variant.cpp:309
graphene::protocol::graphene_extension_pack_count_visitor::graphene_extension_pack_count_visitor
graphene_extension_pack_count_visitor(const T &v)
Definition: ext.hpp:46
graphene::protocol::graphene_extension_unpack_visitor::stream
Stream & stream
Definition: ext.hpp:128
raw_fwd.hpp
fc::reflector
defines visit functions for T Unless this is specialized, visit() will not be defined for T.
Definition: reflect.hpp:25
graphene::protocol::extension::extension
extension()
Definition: ext.hpp:38
fc::graphene_extension_to_variant_visitor
Definition: ext.hpp:183
fc::graphene_extension_from_variant_visitor::vo
const variant_object & vo
Definition: ext.hpp:159
fc::graphene_extension_from_variant_visitor::value
T & value
Definition: ext.hpp:160
graphene::protocol::graphene_extension_pack_read_visitor
Definition: ext.hpp:59
fc::variant_object::end
iterator end() const
Definition: variant_object.cpp:59
fc::get_typename< graphene::protocol::extension< T > >::name
static const char * name()
Definition: ext.hpp:236
varint.hpp
fc::graphene_extension_from_variant_visitor::_max_depth
const uint32_t _max_depth
Definition: ext.hpp:161
graphene
Definition: api.cpp:48
graphene::protocol::extension::value
T value
Definition: ext.hpp:40
fc::raw::pack
void pack(Stream &s, const flat_set< T, A... > &value, uint32_t _max_depth)
Definition: flat.hpp:11