emlabcpp
modern opinionated embedded C++ library
request_adapter.h
Go to the documentation of this file.
1 
24 #pragma once
25 
26 #include "./base.h"
27 
28 #include <optional>
29 #include <variant>
30 
31 namespace emlabcpp
32 {
33 
34 template < typename Tree >
36 {
37 public:
38  using value_type = typename Tree::value_type;
39  using key_type = typename Tree::key_type;
40  using node_id = typename Tree::node_id;
41  using node_type = typename Tree::node_type;
42  using child_id = typename Tree::child_id;
45  using const_object_handle = typename Tree::const_object_handle;
46  using const_array_handle = typename Tree::const_array_handle;
47  using object_handle = typename Tree::object_handle;
48  using array_handle = typename Tree::array_handle;
49 
50  explicit contiguous_request_adapter( Tree& tree )
51  : tree_( tree )
52  {
53  }
54 
55  [[nodiscard]] std::variant< std::reference_wrapper< value_type const >, error_enum >
56  get_value( node_id id ) const
57  {
58  auto n = get_node( id );
59  if ( auto* e = std::get_if< error_enum >( &n ) )
60  return *e;
61  auto& node = std::get_if< 0 >( &n )->get();
62  value_type const* val_ptr = node.get_value();
63  if ( val_ptr == nullptr )
64  return error_enum::WRONG_TYPE;
65  return std::ref( *val_ptr );
66  }
67 
68  [[nodiscard]] std::variant< node_id, error_enum >
69  get_child( node_id nid, std::variant< key_type, child_id > const& id_var ) const
70  {
71  auto get_object_child = []( const_object_handle& h,
72  std::variant< key_type, child_id > const& key ) {
73  return visit(
74  [&h]( auto const& k ) {
75  return h.get_child( k );
76  },
77  key );
78  };
79 
80  auto get_array_child = []( const_array_handle& h,
81  std::variant< key_type, child_id > const& key )
82  -> std::optional< node_id > {
83  child_id const* const id_ptr = std::get_if< child_id >( &key );
84  if ( id_ptr == nullptr )
85  return std::nullopt;
86  return h.get_child( *id_ptr );
87  };
88 
89  auto tmp = get_containers( nid );
90  if ( auto* e = std::get_if< error_enum >( &tmp ) )
91  return *e;
92 
93  const_object_handle* oh_ptr = std::get_if< 0 >( &tmp );
94  const_array_handle* ah_ptr = std::get_if< 1 >( &tmp );
95 
96  std::optional< node_id > res;
97  if ( oh_ptr != nullptr )
98  res = get_object_child( *oh_ptr, id_var );
99  else if ( ah_ptr != nullptr )
100  res = get_array_child( *ah_ptr, id_var );
101  else
102  return error_enum::WRONG_TYPE;
103  if ( res )
104  return *res;
105 
106  return error_enum::CHILD_MISSING;
107  }
108 
109  [[nodiscard]] std::variant< child_id, error_enum > get_child_count( node_id nid ) const
110  {
111  using R = std::variant< child_id, error_enum >;
112  return match(
113  get_containers( nid ),
114  []( const_object_handle const& oh ) -> R {
115  return oh.size();
116  },
117  []( const_array_handle const& ah ) -> R {
118  return ah.size();
119  },
120  []( error_enum e ) -> R {
121  return e;
122  } );
123  }
124 
125  [[nodiscard]] std::variant< key_type, error_enum >
126  get_key( node_id nid, child_id chid ) const
127  {
128  auto tmp = get_object_handle( nid );
129  if ( auto* e = std::get_if< error_enum >( &tmp ) )
130  return *e;
131  auto& oh = *std::get_if< const_object_handle >( &tmp );
132  key_type const* key_ptr = oh.get_key( chid );
133 
134  if ( key_ptr == nullptr )
135  return error_enum::CHILD_MISSING;
136  return *key_ptr;
137  }
138 
139  [[nodiscard]] std::variant< type_enum, error_enum > get_type( node_id nid ) const
140  {
141  auto tmp = get_node( nid );
142  if ( auto* e = std::get_if< error_enum >( &tmp ) )
143  return *e;
144  auto& node = *std::get_if< 0 >( &tmp );
145  return node.get().get_type();
146  }
147 
148  [[nodiscard]] std::variant< node_id, error_enum > insert(
149  node_id parent,
150  key_type const& key,
151  std::variant< value_type, contiguous_container_type > const& val )
152  {
153  auto obj = get_object_handle( parent );
154  if ( auto* e = std::get_if< error_enum >( &obj ) )
155  return *e;
156  auto& oh = *std::get_if< object_handle >( &obj );
157  auto cnode = construct_node( val );
158  if ( auto* e = std::get_if< error_enum >( &cnode ) )
159  return *e;
160  auto& nid = *std::get_if< node_id >( &cnode );
161  oh.set( key, nid );
162  return nid;
163  }
164 
165  [[nodiscard]] std::variant< node_id, error_enum >
166  insert( node_id parent, std::variant< value_type, contiguous_container_type > const& val )
167  {
168  auto tmp = get_array_handle( parent );
169  if ( auto* e = std::get_if< error_enum >( &tmp ) )
170  return *e;
171  auto& ah = *std::get_if< array_handle >( &tmp );
172  auto nid = construct_node( val );
173  if ( auto* e = std::get_if< error_enum >( &nid ) )
174  return *e;
175  auto& val_nid = *std::get_if< node_id >( &nid );
176  ah.append( val_nid );
177  return nid;
178  }
179 
180 private:
181  [[nodiscard]] std::variant< node_id, error_enum >
182  construct_node( std::variant< value_type, contiguous_container_type > const& var )
183  {
184  std::optional< node_id > opt_nid = match(
185  var,
186  [this]( value_type const& val ) {
187  return tree_.make_value_node( val );
188  },
189  [this]( contiguous_container_type const type ) -> std::optional< node_id > {
190  if ( type == contiguous_container_type::ARRAY ) {
191  auto opt_res = tree_.make_array_node();
192  if ( opt_res )
193  return opt_res->first;
194  return std::nullopt;
195 
196  } else if ( type == contiguous_container_type::OBJECT ) {
197  auto opt_res = tree_.make_object_node();
198  if ( opt_res )
199  return opt_res->first;
200  return std::nullopt;
201  } else {
202  return std::nullopt;
203  }
204  } );
205  if ( !opt_nid )
206  return error_enum::FULL;
207  return *opt_nid;
208  }
209 
210  [[nodiscard]] std::variant< std::reference_wrapper< node_type const >, error_enum >
211  get_node( node_id nid ) const
212  {
213  return get_node_impl< node_type const >( this, nid );
214  }
215 
216  [[nodiscard]] std::variant< std::reference_wrapper< node_type >, error_enum >
217  get_node( node_id nid )
218  {
219  return get_node_impl< node_type >( this, nid );
220  }
221 
222  template < typename Node, typename Self >
223  [[nodiscard]] static std::variant< std::reference_wrapper< Node >, error_enum >
224  get_node_impl( Self* self, node_id nid )
225  {
226  Node* node_ptr = self->tree_.get_node( nid );
227 
228  if ( node_ptr == nullptr )
229  return error_enum::MISSING_NODE;
230 
231  return std::ref( *node_ptr );
232  }
233 
234  [[nodiscard]] std::variant< const_object_handle, const_array_handle, error_enum >
235  get_containers( node_id nid ) const
236  {
237  return get_containers_impl< const_object_handle, const_array_handle >( this, nid );
238  }
239 
240  [[nodiscard]] std::variant< object_handle, array_handle, error_enum >
241  get_containers( node_id nid )
242  {
243  return get_containers_impl< object_handle, array_handle >( this, nid );
244  }
245 
246  template < typename OHandle, typename AHandle, typename Self >
247  [[nodiscard]] static std::variant< OHandle, AHandle, error_enum >
248  get_containers_impl( Self* self, node_id nid )
249  {
250  auto tmp = self->get_node( nid );
251  if ( auto* e_ptr = std::get_if< error_enum >( &tmp ) )
252  return *e_ptr;
253  auto& node_wrapper = *std::get_if< 0 >( &tmp );
254  auto& node = node_wrapper.get();
255  std::variant< std::reference_wrapper< value_type const >, OHandle, AHandle > cont =
256  node.get_container_handle();
257 
258  auto* ah_ptr = std::get_if< AHandle >( &cont );
259  if ( ah_ptr != nullptr )
260  return *ah_ptr;
261  auto* oh_ptr = std::get_if< OHandle >( &cont );
262  if ( oh_ptr != nullptr )
263  return *oh_ptr;
264  return error_enum::WRONG_TYPE;
265  }
266 
267  [[nodiscard]] std::variant< const_object_handle, error_enum >
268  get_object_handle( node_id nid ) const
269  {
270  return get_handle_impl< const_object_handle >( this, nid );
271  };
272 
273  [[nodiscard]] std::variant< object_handle, error_enum > get_object_handle( node_id nid )
274  {
275  return get_handle_impl< object_handle >( this, nid );
276  };
277 
278  [[nodiscard]] std::variant< const_array_handle, error_enum >
279  get_array_handle( node_id nid ) const
280  {
281  return get_handle_impl< const_array_handle >( this, nid );
282  };
283 
284  [[nodiscard]] std::variant< array_handle, error_enum > get_array_handle( node_id nid )
285  {
286  return get_handle_impl< array_handle >( this, nid );
287  };
288 
289  template < typename Handle, typename Self >
290  [[nodiscard]] static std::variant< Handle, error_enum >
291  get_handle_impl( Self* self, node_id nid )
292  {
293  auto var = self->get_containers( nid );
294  if ( auto* e_ptr = std::get_if< error_enum >( &var ) )
295  return *e_ptr;
296 
297  auto* h_ptr = std::get_if< Handle >( &var );
298  if ( h_ptr != nullptr )
299  return *h_ptr;
300  return error_enum::WRONG_TYPE;
301  }
302 
303  Tree& tree_;
304 };
305 
306 } // namespace emlabcpp
Definition: request_adapter.h:36
std::variant< node_id, error_enum > insert(node_id parent, key_type const &key, std::variant< value_type, contiguous_container_type > const &val)
Definition: request_adapter.h:148
contiguous_request_adapter(Tree &tree)
Definition: request_adapter.h:50
typename Tree::const_array_handle const_array_handle
Definition: request_adapter.h:46
typename Tree::node_id node_id
Definition: request_adapter.h:40
typename Tree::array_handle array_handle
Definition: request_adapter.h:48
typename Tree::child_id child_id
Definition: request_adapter.h:42
typename Tree::object_handle object_handle
Definition: request_adapter.h:47
contiguous_request_adapter_errors error_enum
Definition: request_adapter.h:44
std::variant< node_id, error_enum > insert(node_id parent, std::variant< value_type, contiguous_container_type > const &val)
Definition: request_adapter.h:166
typename Tree::node_type node_type
Definition: request_adapter.h:41
std::variant< std::reference_wrapper< value_type const >, error_enum > get_value(node_id id) const
Definition: request_adapter.h:56
typename Tree::key_type key_type
Definition: request_adapter.h:39
std::variant< child_id, error_enum > get_child_count(node_id nid) const
Definition: request_adapter.h:109
std::variant< key_type, error_enum > get_key(node_id nid, child_id chid) const
Definition: request_adapter.h:126
std::variant< node_id, error_enum > get_child(node_id nid, std::variant< key_type, child_id > const &id_var) const
Definition: request_adapter.h:69
std::variant< type_enum, error_enum > get_type(node_id nid) const
Definition: request_adapter.h:139
typename Tree::const_object_handle const_object_handle
Definition: request_adapter.h:45
typename Tree::value_type value_type
Definition: request_adapter.h:38
uint32_t node_id
Definition: base.h:42
key_type_buffer key_type
Definition: base.h:47
std::variant< int64_t, float, bool, string_buffer > value_type
Definition: base.h:51
uint32_t child_id
Definition: base.h:44
MIT License.
Definition: impl.h:31
contiguous_request_adapter_errors
Definition: base.h:46
decltype(auto) match(Variant &&var, Callables &&... cals)
Definition: match.h:55
T value_type
Definition: static_storage.h:100
decltype(auto) visit(Visitor &&vis, Variant &&var)
Reimplementation of std::visit.
Definition: visit.h:44
contiguous_tree_type
Definition: base.h:33
T res
Definition: algorithm.h:505
contiguous_container_type
Definition: base.h:40