BitShares-Core  5.0.0
BitShares blockchain implementation and command-line interface 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  {
72  fc::raw::pack( stream, unsigned_int( which ), max_depth );
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;
93  fc::raw::unpack( stream, c, max_depth );
94  count_left = c.value;
95  maybe_read_next_which();
96  }
97 
99  {
100  if( count_left > 0 )
101  {
102  unsigned_int w;
103  fc::raw::unpack( stream, w, max_depth );
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;
117  maybe_read_next_which();
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
void to_variant(const graphene::protocol::extension< T > &value, fc::variant &var, uint32_t max_depth)
Definition: ext.hpp:199
graphene_extension_unpack_visitor(Stream &s, T &v, uint32_t _max_depth)
Definition: ext.hpp:88
limited_mutable_variant_object mvo
Definition: ext.hpp:195
graphene_extension_to_variant_visitor(const T &v, uint32_t max_depth)
Definition: ext.hpp:185
void pack(Stream &s, const flat_set< T, A... > &value, uint32_t _max_depth)
Definition: flat.hpp:11
An order-perserving dictionary of variant&#39;s.
bool is_array() const
Definition: variant.cpp:368
Definition: api.cpp:56
Defines types and macros used to provide reflection.
bool is_null() const
Definition: variant.cpp:309
void operator()(const char *name) const
Definition: ext.hpp:148
void unpack(Stream &s, flat_set< T, A... > &value, uint32_t _max_depth)
Definition: flat.hpp:23
size_t size() const
Definition: variant.cpp:570
void pack(Stream &stream, const graphene::protocol::extension< T > &value, uint32_t _max_depth=FC_PACK_MAX_DEPTH)
Definition: ext.hpp:209
variant_object & get_object()
Definition: variant.cpp:554
void unpack(Stream &s, graphene::protocol::extension< T > &value, uint32_t _max_depth=FC_PACK_MAX_DEPTH)
Definition: ext.hpp:222
defines visit functions for T Unless this is specialized, visit() will not be defined for T...
Definition: reflect.hpp:25
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
void from_variant(const fc::variant &var, graphene::protocol::extension< T > &value, uint32_t max_depth)
Definition: ext.hpp:166
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object&#39;s.
Definition: variant.hpp:198
Defines exception&#39;s used by fc.
void operator()(const char *name) const
Definition: ext.hpp:188
graphene_extension_from_variant_visitor(const variant_object &v, T &val, uint32_t max_depth)
Definition: ext.hpp:140
graphene_extension_pack_read_visitor(Stream &s, const T &v, uint32_t _max_depth)
Definition: ext.hpp:61
void operator()(const char *name) const
Definition: ext.hpp:109
Definition: api.hpp:15
uint64_t value
Definition: varint.hpp:17
#define FC_PACK_MAX_DEPTH
Definition: config.hpp:3
void operator()(const char *name) const
Definition: ext.hpp:68