Ariles
reader.cpp
Go to the documentation of this file.
1 /**
2  @file
3  @author Alexander Sherikov
4 
5  @copyright 2018 Alexander Sherikov, Licensed under the Apache License, Version 2.0.
6  (see @ref LICENSE or http://www.apache.org/licenses/LICENSE-2.0)
7 
8  @brief
9 */
10 
11 #include <set>
12 
13 #include <boost/lexical_cast.hpp>
14 
16 
17 #include "node_wrapper.h"
18 
19 
20 namespace ariles2
21 {
22  namespace ns_ros2param
23  {
24  class ReaderNodeWrapper : public NodeBase
25  {
26  protected:
27  std::set<std::string> childs_;
28  std::set<std::string>::const_iterator childs_iterator_;
29  const rclcpp::Parameter parameter_;
30 
31  public:
32  using NodeBase::NodeBase;
33 
34  ReaderNodeWrapper(const std::string &name, std::set<std::string> childs)
35  : NodeBase(name, NodeBase::Type::ITERATED_MAP), childs_(std::move(childs))
36  {
37  size_ = childs_.size();
38  childs_iterator_ = childs_.begin();
39  }
40 
41  const std::string &getChildName()
42  {
43  return (*childs_iterator_++);
44  }
45 
46  explicit ReaderNodeWrapper(const rclcpp::Parameter &&parameter)
47  : NodeBase(NodeBase::Type::ARRAY), parameter_(parameter)
48  {
49  index_ = 0;
51 
52  switch (parameter_.get_type())
53  {
54  case rclcpp::ParameterType::PARAMETER_BYTE_ARRAY:
55  size_ = parameter_.as_byte_array().size();
56  return;
57  case rclcpp::ParameterType::PARAMETER_BOOL_ARRAY:
58  size_ = parameter_.as_bool_array().size();
59  return;
60  case rclcpp::ParameterType::PARAMETER_INTEGER_ARRAY:
61  size_ = parameter_.as_integer_array().size();
62  return;
63  case rclcpp::ParameterType::PARAMETER_DOUBLE_ARRAY:
64  size_ = parameter_.as_double_array().size();
65  return;
66  case rclcpp::ParameterType::PARAMETER_STRING_ARRAY:
67  size_ = parameter_.as_string_array().size();
68  return;
69  default:
70  CPPUT_THROW("Unexpected value type");
71  }
72  }
73 
74  bool tryReadArray(int64_t &value)
75  {
76  if (isBuiltinArray())
77  {
78  switch (parameter_.get_type())
79  {
80  case rclcpp::ParameterType::PARAMETER_BYTE_ARRAY:
81  value = parameter_.as_byte_array()[index_];
82  return (true);
83  case rclcpp::ParameterType::PARAMETER_INTEGER_ARRAY:
84  value = parameter_.as_integer_array()[index_];
85  return (true);
86  default:
87  CPPUT_THROW("Unexpected array value type");
88  }
89  }
90  return (false);
91  }
92 
93  bool tryReadArray(double &value)
94  {
95  if (isBuiltinArray())
96  {
97  switch (parameter_.get_type())
98  {
99  case rclcpp::ParameterType::PARAMETER_DOUBLE_ARRAY:
100  value = parameter_.as_double_array()[index_];
101  return (true);
102  default:
103  CPPUT_THROW("Unexpected array value type");
104  }
105  }
106  return (false);
107  }
108 
109  bool tryReadArray(std::string &value)
110  {
111  if (isBuiltinArray())
112  {
113  switch (parameter_.get_type())
114  {
115  case rclcpp::ParameterType::PARAMETER_STRING_ARRAY:
116  value = parameter_.as_string_array()[index_];
117  return (true);
118  default:
119  CPPUT_THROW("Unexpected array value type");
120  }
121  }
122  return (false);
123  }
124 
125  bool tryReadArray(bool &value)
126  {
127  if (isBuiltinArray())
128  {
129  switch (parameter_.get_type())
130  {
131  case rclcpp::ParameterType::PARAMETER_BOOL_ARRAY:
132  value = parameter_.as_bool_array()[index_];
133  return (true);
134  default:
135  CPPUT_THROW("Unexpected array value type");
136  }
137  }
138  return (false);
139  }
140  };
141 
142  namespace impl
143  {
144  class Reader : public serialization::NodeStackBase<ReaderNodeWrapper>
145  {
146  public:
147  // https://docs.ros2.org/latest/api/rclcpp/classrclcpp_1_1Node.html
148  rclcpp::node_interfaces::NodeParametersInterface::SharedPtr nh_;
149 
150  std::vector<std::string> parameter_names_;
151 
152  const std::string separator_ = ".";
153 
154 
155  public:
156  explicit Reader(const rclcpp::node_interfaces::NodeParametersInterface::SharedPtr &nh)
157  {
158  nh_ = nh;
159  }
160 
161 
162  bool getParameter(rclcpp::Parameter &parameter) const
163  {
165  CPPUT_TRACE_VALUE(back().node_);
166 
167  return (nh_->get_parameter(back().node_, parameter));
168  }
169 
170 
171  [[nodiscard]] bool isParameter() const
172  {
173  for (const std::string &name : parameter_names_)
174  {
175  if (back().node_ == name)
176  {
177  return (true);
178  }
179  }
180  return (false);
181  }
182 
183  void reset()
184  {
185  clear();
186 
187  parameter_names_ = std::move(nh_->list_parameters({}, std::numeric_limits<uint64_t>::max()).names);
188  }
189 
190 
191  [[nodiscard]] static bool isPrefix(const std::string &prefix, const std::string &name)
192  {
193  if (prefix.empty())
194  {
195  return (true); // zero prefix
196  }
197 
198  if (prefix.size() <= name.size())
199  {
200  if (name.substr(0, prefix.size()) == prefix)
201  {
202  if (prefix.size() == name.size())
203  {
204  return (true); // name = prefix
205  }
206 
207  if ('.' == name[prefix.size()])
208  {
209  return (true); // normal prefix
210  }
211  }
212  }
213 
214  return (false);
215  }
216 
217 
218  [[nodiscard]] std::set<std::string> listParameters() const
219  {
220  std::size_t substr_start = 0;
221 
222  if (not empty())
223  {
224  substr_start = back().node_.size() + 1; // + 1 for dot
225  }
226 
227  std::set<std::string> names;
228  for (const std::string &name : parameter_names_)
229  {
230  if (isPrefix(back().node_, name))
231  {
232  const std::size_t substr_end = name.find('.', substr_start);
233  names.insert(name.substr(substr_start, substr_end - substr_start));
234  }
235  }
236 
237  return (names);
238  }
239 
241  {
242  for (const std::string &name : parameter_names_)
243  {
244  if (isPrefix(back().node_, name))
245  {
246  return (true);
247  }
248  }
249  return (false);
250  }
251 
252  template <int t_expected_parameter_type, class t_Element>
253  void readElement(t_Element &element)
254  {
256  if (not back().tryReadArray(element))
257  {
258  rclcpp::Parameter parameter;
259  CPPUT_ASSERT(getParameter(parameter), std::string("Cannot read parameter: ") + back().node_);
260  CPPUT_ASSERT(t_expected_parameter_type == parameter.get_type(), "Unexpected parameter type.");
261  element = parameter.get_value<t_Element>();
262  }
263  }
264  };
265  } // namespace impl
266  } // namespace ns_ros2param
267 } // namespace ariles2
268 
269 
270 namespace ariles2
271 {
272  namespace ns_ros2param
273  {
274  Reader::Reader(const rclcpp::node_interfaces::NodeParametersInterface::SharedPtr &nh)
275  {
276  makeImplPtr(nh);
277  }
278 
279 
280  bool Reader::startRoot(const std::string &name)
281  {
283  CPPUT_TRACE_VALUE(name);
284 
285  impl_->reset();
286  return (Parent::startRoot(name));
287  }
288 
289 
290  bool Reader::startMapEntry(const std::string &child_name)
291  {
293  if (impl_->empty())
294  {
295  impl_->emplace(child_name);
296  }
297  else
298  {
299  CPPUT_ASSERT(not impl_->back().isBuiltinArray(), "Unexpected parent type (builtin array).");
300 
301  impl_->concatWithNodeAndEmplace(impl_->separator_, child_name);
302  }
303 
304  return (impl_->hasParameterPrefix());
305  }
306 
308  {
310  impl_->pop();
311  }
312 
313 
314 
316  const SizeLimitEnforcementType limit_type,
317  const std::size_t min,
318  const std::size_t max)
319  {
321 
322  std::set<std::string> name_list = impl_->listParameters();
323 
324  checkSize(limit_type, name_list.size(), min, max);
325 
326  impl_->emplace(impl_->back().node_, std::move(name_list));
327  return (true);
328  }
329 
330  bool Reader::startIteratedMapElement(std::string &entry_name)
331  {
333  if (impl_->back().isCompleted())
334  {
335  return (false);
336  }
337 
338  entry_name = impl_->back().getChildName();
339  impl_->concatWithNodeAndEmplace(impl_->separator_, entry_name);
340 
341  return (true);
342  }
343 
345  {
346  impl_->pop();
347  ++(impl_->back().index_);
348  }
349 
351  {
353  CPPUT_ASSERT(impl_->back().isCompleted(), "End of iterated map has not been reached.");
354  impl_->pop();
355  }
356 
357 
358  std::size_t Reader::startArray()
359  {
361 
362  if (not impl_->empty() and impl_->isParameter())
363  {
364  rclcpp::Parameter values;
365  impl_->getParameter(values);
366  impl_->emplace(std::move(values));
367  }
368  else
369  {
370  impl_->emplace(impl_->back().node_, 0, impl_->listParameters().size());
371  }
372 
373  return (impl_->back().size_);
374  }
375 
377  {
379 
380  CPPUT_ASSERT(not impl_->back().isCompleted(), "Internal error: array has more elements than expected.");
381  if (impl_->back().isNonBuiltinArray())
382  {
383  impl_->concatWithNodeAndEmplace(
384  impl_->separator_, boost::lexical_cast<std::string>(impl_->back().index_));
385  }
386  }
387 
389  {
391  if (not impl_->back().isBuiltinArray())
392  {
393  impl_->pop();
394  }
395  impl_->shiftArray();
396  }
397 
399  {
401  impl_->pop();
402  }
403 
404 
405 
406 #define ARILES2_BASIC_TYPE(type) \
407  void Reader::readElement(type &element) \
408  { \
409  int64_t tmp_value; \
410  impl_->readElement<rclcpp::ParameterType::PARAMETER_INTEGER>(tmp_value); \
411  CPPUT_ASSERT( \
412  tmp_value <= std::numeric_limits<type>::max() && tmp_value >= std::numeric_limits<type>::min(), \
413  "Value is out of range."); \
414  element = static_cast<type>(tmp_value); \
415  }
416 
418 
419 #undef ARILES2_BASIC_TYPE
420 
421 
422 #define ARILES2_BASIC_TYPE(type) \
423  void Reader::readElement(type &element) \
424  { \
425  CPPUT_TRACE_FUNCTION; \
426  int64_t tmp_value; \
427  impl_->readElement<rclcpp::ParameterType::PARAMETER_INTEGER>(tmp_value); \
428  CPPUT_ASSERT(tmp_value >= 0, "Expected positive value."); \
429  CPPUT_ASSERT(static_cast<uint64_t>(tmp_value) <= std::numeric_limits<type>::max(), "Value is too large."); \
430  element = static_cast<type>(tmp_value); \
431  }
432 
434 
435 #undef ARILES2_BASIC_TYPE
436 
437 
438 #define ARILES2_BASIC_TYPE(type) \
439  void Reader::readElement(type &element) \
440  { \
441  CPPUT_TRACE_FUNCTION; \
442  double tmp_value; \
443  impl_->readElement<rclcpp::ParameterType::PARAMETER_DOUBLE>(tmp_value); \
444  element = static_cast<type>(tmp_value); \
445  }
446 
448 
449 #undef ARILES2_BASIC_TYPE
450 
451 
452  void Reader::readElement(std::string &element)
453  {
455  impl_->readElement<rclcpp::ParameterType::PARAMETER_STRING>(element);
456  }
457 
458 
459  void Reader::readElement(bool &element)
460  {
462  impl_->readElement<rclcpp::ParameterType::PARAMETER_BOOL>(element);
463  }
464  } // namespace ns_ros2param
465 } // namespace ariles2
bool tryReadArray(std::string &value)
Definition: reader.cpp:109
std::set< std::string > childs_
Definition: reader.cpp:27
ReaderNodeWrapper(const std::string &name, std::set< std::string > childs)
Definition: reader.cpp:34
const rclcpp::Parameter parameter_
Definition: reader.cpp:29
const std::string & getChildName()
Definition: reader.cpp:41
std::set< std::string >::const_iterator childs_iterator_
Definition: reader.cpp:28
ReaderNodeWrapper(const rclcpp::Parameter &&parameter)
Definition: reader.cpp:46
bool tryReadArray(int64_t &value)
Definition: reader.cpp:74
bool startIteratedMap(const SizeLimitEnforcementType=SIZE_LIMIT_NONE, const std::size_t=0, const std::size_t=0)
Definition: reader.cpp:315
void endMapEntry()
endMapEntry from the current entry to its parent.
Definition: reader.cpp:307
bool startIteratedMapElement(std::string &entry_name)
Definition: reader.cpp:330
bool startMapEntry(const std::string &child_name)
startMapEntry to the entry with the given name
Definition: reader.cpp:290
Reader(const rclcpp::node_interfaces::NodeParametersInterface::SharedPtr &nh)
Constructor.
Definition: reader.cpp:274
bool startRoot(const std::string &name)
Definition: reader.cpp:280
rclcpp::node_interfaces::NodeParametersInterface::SharedPtr nh_
Definition: reader.cpp:148
Reader(const rclcpp::node_interfaces::NodeParametersInterface::SharedPtr &nh)
Definition: reader.cpp:156
bool getParameter(rclcpp::Parameter &parameter) const
Definition: reader.cpp:162
void readElement(t_Element &element)
Definition: reader.cpp:253
std::vector< std::string > parameter_names_
Definition: reader.cpp:150
static bool isPrefix(const std::string &prefix, const std::string &name)
Definition: reader.cpp:191
std::set< std::string > listParameters() const
Definition: reader.cpp:218
void checkSize(const SizeLimitEnforcementType limit_type, const std::size_t size=0, const std::size_t min=0, const std::size_t max=0) const
Definition: read.h:47
virtual bool startRoot(const std::string &name)
Definition: read.h:73
void readElement(std::complex< t_Scalar > &entry)
Definition: read.h:357
#define CPPUT_THROW(...)
Definition: exception.h:19
#define CPPUT_ASSERT(condition,...)
Definition: exception.h:32
#define ARILES2_BASIC_REAL_TYPES_LIST
Definition: helpers.h:59
#define ARILES2_BASIC_UNSIGNED_INTEGER_TYPES_LIST
Definition: helpers.h:50
#define ARILES2_BASIC_SIGNED_INTEGER_TYPES_LIST
Definition: helpers.h:37
CPPUT_MACRO_SUBSTITUTE(ARILES2_BASIC_SIGNED_INTEGER_TYPES_LIST) CPPUT_MACRO_SUBSTITUTE(ARILES2_BASIC_UNSIGNED_INTEGER_TYPES_LIST) CPPUT_MACRO_SUBSTITUTE(ARILES2_BASIC_REAL_TYPES_LIST) void Reader
Definition: reader.cpp:417
Definition: basic.h:17
#define CPPUT_TRACE_FUNCTION
Definition: trace.h:126
#define CPPUT_TRACE_VALUE(value)
Definition: trace.h:127