Ariles
read.h
Go to the documentation of this file.
1 /**
2  @file
3  @author Alexander Sherikov
4 
5  @copyright 2017-2020 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 #pragma once
12 
13 #include <vector>
14 
15 #include "serialization.h"
16 #include "count.h"
17 
18 /**
19 @defgroup read Read
20 @ingroup serialization
21 
22 @brief Base for deserialization.
23 */
24 
25 namespace ariles2
26 {
27  /// @ingroup read
28  namespace read
29  {
31 
32 
33  class Visitor : public serialization::Base<Visitor, Parameters>
34  {
35  public:
37  {
42  SIZE_LIMIT_MIN = 4
43  };
44 
45 
46  protected:
47  void checkSize(
48  const SizeLimitEnforcementType limit_type,
49  const std::size_t size = 0,
50  const std::size_t min = 0,
51  const std::size_t max = 0) const
52  {
53  switch (limit_type)
54  {
55  case SIZE_LIMIT_NONE:
56  return;
57  case SIZE_LIMIT_EQUAL:
58  CPPUT_ASSERT(size == min, "Actual number of entries is not the same as expected.");
59  return;
60  case SIZE_LIMIT_RANGE:
61  CPPUT_ASSERT(min <= size, "Actual number of entries is lower than expected.");
62  CPPUT_ASSERT(max >= size, "Actual number of entries is larger than expected.");
63  return;
64  case SIZE_LIMIT_MIN:
65  CPPUT_ASSERT(min <= size, "Actual number of entries is lower than expected.");
66  return;
67  default:
68  CPPUT_THROW("Internal logic error.");
69  }
70  }
71 
72 
73  virtual bool startRoot(const std::string &name)
74  {
76  CPPUT_TRACE_VALUE(name);
77 
78  if (not name.empty())
79  {
80  return (startMapEntry(name));
81  }
82  return (true);
83  }
84 
85  virtual void endRoot(const std::string &name)
86  {
88  if (not name.empty())
89  {
90  endMapEntry();
91  }
92  }
93 
94 
95  virtual bool startRoot(const std::vector<std::string> &subtree)
96  {
98 
99  bool result = false;
100  if (0 == subtree.size())
101  {
102  result = this->startRoot("");
103  }
104  else
105  {
106  result = this->startRoot(subtree[0]);
107  for (std::size_t i = 1; i < subtree.size() and result; ++i)
108  {
109  this->startMap(SIZE_LIMIT_MIN, 1);
110  result &= (this->startMapEntry(subtree[i]));
111  }
112  }
113 
114  return (result);
115  }
116 
117  virtual void endRoot(const std::vector<std::string> &subtree)
118  {
120  for (std::size_t i = 1; i < subtree.size(); ++i)
121  {
122  this->endMapEntry();
123  this->endMap();
124  }
125  if (0 == subtree.size())
126  {
127  endRoot("");
128  }
129  else
130  {
131  endRoot(subtree[0]);
132  }
133  }
134 
135 
136  const std::string &convertSubtreeToString(const std::string &subtree) const
137  {
138  return (subtree);
139  }
140 
141  std::string convertSubtreeToString(const std::vector<std::string> &subtree) const
142  {
143  std::string result;
144  for (std::size_t i = 0; i < subtree.size(); ++i)
145  {
146  if (i > 0)
147  {
148  result += "/";
149  }
150  result += subtree[i];
151  }
152  return (result);
153  }
154 
155 
156  public:
157  template <class t_Entry>
158  void startMap(t_Entry &entry, const Parameters &parameters)
159  {
160  startMap(
161  parameters.allow_missing_entries_ ? SIZE_LIMIT_NONE : SIZE_LIMIT_MIN,
162  ariles2::apply<ariles2::Count>(entry));
163  }
164 
165  virtual void startMap(
166  const SizeLimitEnforcementType /*limit_type*/ = SIZE_LIMIT_NONE,
167  const std::size_t /*min*/ = 0,
168  const std::size_t /*max*/ = 0)
169  {
170  }
171 
172  /**
173  * @brief startMapEntry to the entry with the given name
174  *
175  * @param[in] child_name child node name
176  *
177  * @return true if successful.
178  */
179  virtual bool startMapEntry(const std::string &child_name)
180  {
182  CPPUT_UNUSED_ARG(child_name)
183  return (true);
184  }
185 
186  /**
187  * @brief endMapEntry from the current entry to its parent.
188  */
189  virtual void endMapEntry() = 0;
190 
191  virtual void endMap()
192  {
193  }
194 
195 
196  virtual bool startIteratedMap(
197  const SizeLimitEnforcementType /*limit_type*/ = SIZE_LIMIT_NONE,
198  const std::size_t /*min*/ = 0,
199  const std::size_t /*max*/ = 0)
200  {
201  return (false);
202  }
203  virtual bool startIteratedMapElement(std::string & /*entry_name*/)
204  {
205  CPPUT_THROW("startIteratedMapElement() is not supported.");
206  }
207  virtual void endIteratedMapElement()
208  {
209  }
210  virtual void endIteratedMap()
211  {
212  }
213 
214 
215  bool startPointer(const Parameters &param)
216  {
218 
219  bool is_null = true;
220 
221  this->startMap(SIZE_LIMIT_RANGE, 1, 2);
222 
223  if (this->startMapEntry("is_null"))
224  {
225  this->readElement(is_null);
226  this->endMapEntry();
227  }
228  else
229  {
231  param.allow_missing_entries_, "Pointer entry does not include 'is_null' subentry.");
232  }
233 
234  if (not is_null)
235  {
236  CPPUT_ASSERT(this->startMapEntry("value"), "Missing value in a pointer entry.");
237  }
238 
239  return (is_null);
240  }
241  void endPointer(const bool is_null)
242  {
243  if (not is_null)
244  {
245  this->endMapEntry();
246  }
247  this->endMap();
248  }
249 
250 
251  virtual std::size_t startArray() = 0;
252  virtual void startArrayElement(){};
253  virtual void endArrayElement() = 0;
254  virtual void endArray() = 0;
255 
256  virtual std::size_t startVector()
257  {
258  return (startArray());
259  }
260  virtual void startVectorElement()
261  {
263  }
264  virtual void endVectorElement()
265  {
266  endArrayElement();
267  }
268  virtual void endVector()
269  {
270  endArray();
271  }
272 
273 
274  virtual void startMatrix(std::size_t &cols, std::size_t &rows, const bool dynamic, const Parameters &param)
275  {
276  if (param.flat_matrices_)
277  {
278  if (dynamic or param.explicit_matrix_size_)
279  {
280  this->startMap(SIZE_LIMIT_EQUAL, 3);
281 
282  CPPUT_ASSERT(this->startMapEntry("cols"), "Missing 'cols' in a matrix entry.");
283  this->readElement(cols);
284  this->endMapEntry();
285 
286  CPPUT_ASSERT(this->startMapEntry("rows"), "Missing 'rows' in a matrix entry.");
287  this->readElement(rows);
288  this->endMapEntry();
289 
290  CPPUT_ASSERT(this->startMapEntry("data"), "Missing 'data' in a matrix entry.");
291 
292  // cppcheck-suppress unreadVariable
293  const std::size_t vec_len = this->startVector();
294  CPPUT_ASSERT(cols * rows == vec_len, "Inconsistent matrix size.");
295  }
296  else
297  {
298  this->startVector();
299  }
300  }
301  else
302  {
303  rows = this->startArray();
304  if (rows > 0)
305  {
306  this->startArrayElement();
307  cols = this->startVector();
308  }
309  }
310  }
311  virtual void startMatrixRow(const std::size_t row_index, const std::size_t cols, const Parameters &param)
312  {
313  if (not param.flat_matrices_ and 0 != row_index)
314  {
315  this->startArrayElement();
316  // cppcheck-suppress unreadVariable
317  const std::size_t vec_len = this->startVector();
318  CPPUT_ASSERT(cols == vec_len, "Inconsistent matrix row length.");
319  }
320  }
321  virtual void startMatrixElement()
322  {
323  this->startVectorElement();
324  }
325  virtual void endMatrixElement()
326  {
327  this->endVectorElement();
328  }
329  virtual void endMatrixRow(const Parameters &param)
330  {
331  if (not param.flat_matrices_)
332  {
333  this->endVector();
334  this->endArrayElement();
335  }
336  }
337  virtual void endMatrix(const bool dynamic, const Parameters &param)
338  {
339  if (param.flat_matrices_)
340  {
341  this->endVector();
342 
343  if (dynamic)
344  {
345  this->endMapEntry();
346  this->endMap();
347  }
348  }
349  else
350  {
351  this->endArray();
352  }
353  }
354 
355 
356  template <class t_Scalar>
357  void readElement(std::complex<t_Scalar> &entry)
358  {
359  CPPUT_PERSISTENT_ASSERT(2 == this->startArray(), "Wrong number of elements in a complex number");
360  t_Scalar value;
361  this->startArrayElement();
362  this->readElement(value);
363  entry.real(value);
364  this->endArrayElement();
365  this->startArrayElement();
366  this->readElement(value);
367  entry.imag(value);
368  this->endArrayElement();
369  this->endArray();
370  }
371  virtual void readElement(std::complex<float> &entry)
372  {
373  readElement<float>(entry);
374  }
375  virtual void readElement(std::complex<double> &entry)
376  {
377  readElement<double>(entry);
378  }
379 
380 
381 #define ARILES2_BASIC_TYPE(type) virtual void readElement(type &entry) = 0;
382 
384 
385 #undef ARILES2_BASIC_TYPE
386 
387 
388  template <class t_Entry, class t_Subtree>
389  void visit(t_Entry &entry, const t_Subtree &subtree, const Parameters &param)
390  {
392  CPPUT_TRACE_TYPE(entry);
393 
394 
395  if (this->startRoot(subtree))
396  {
397  try
398  {
399  apply_read(*this, entry, param);
400  }
401  catch (const std::exception &e)
402  {
403  CPPUT_THROW("Failed to parse entry <", convertSubtreeToString(subtree), "> || ", e.what());
404  }
405 
406  this->endRoot(subtree);
407  }
408  else
409  {
411  param.allow_missing_entries_,
412  "Configuration file does not contain entry '",
413  convertSubtreeToString(subtree),
414  "'.");
415  }
416  }
417 
418 
419  template <class t_Entry>
421  t_Entry &entry,
422  const std::string &name,
423  const Parameters &param,
424  const bool override_missing_entries_locally = false)
425  {
427  CPPUT_TRACE_VALUE(name);
428  CPPUT_TRACE_TYPE(entry);
429 
430  if (this->startMapEntry(name))
431  {
432  try
433  {
434  apply_read(*this, entry, param);
435  }
436  catch (const std::exception &e)
437  {
438  CPPUT_THROW("Failed to parse entry <", name, "> || ", e.what());
439  }
440 
441  this->endMapEntry();
442  return (true);
443  }
444  else
445  {
447  not override_missing_entries_locally and param.allow_missing_entries_,
448  "Configuration file does not contain entry '",
449  name,
450  "'.");
451  return (false);
452  }
453  }
454 
455  template <typename t_Element>
456  void visitArrayElement(t_Element &element, const Parameters &param)
457  {
459  CPPUT_TRACE_TYPE(element);
460 
461  this->startArrayElement();
462  apply_read(*this, element, param);
463  this->endArrayElement();
464  }
465 
466  template <typename t_Element>
467  void visitVectorElement(t_Element &element, const Parameters & /*param*/)
468  {
470  CPPUT_TRACE_TYPE(element);
471 
472  this->startVectorElement();
473  this->readElement(element);
474  this->endVectorElement();
475  }
476 
477  template <typename t_Element>
478  void visitMatrixElement(t_Element &element, const Parameters & /*param*/)
479  {
481 
482  this->startMatrixElement();
483  this->readElement(element);
484  this->endMatrixElement();
485  }
486  };
487 
488 
490  {
491  protected:
492  std::ifstream config_ifs_;
493 
494  std::istream *input_stream_;
495 
496  protected:
498 
499  explicit FileVisitorImplementation(const std::string &file_name)
500  {
501  openFile(file_name);
503  }
504 
505  explicit FileVisitorImplementation(std::istream &input_stream)
506  {
507  input_stream_ = &input_stream;
508  }
509 
510 
511  /**
512  * @brief open configuration file
513  *
514  * @param[in] file_name
515  */
516  void openFile(const std::string &file_name)
517  {
518  config_ifs_.open(file_name.c_str());
519  if (!config_ifs_.good())
520  {
521  std::string file_name_default = file_name;
522  config_ifs_.open(file_name_default.c_str());
523  }
524  CPPUT_PERSISTENT_ASSERT(config_ifs_.good(), "Could not open configuration file: ", file_name.c_str());
525  }
526  };
527 
528 
530 
531 
532 #define ARILES2_NAMED_ENTRY_read(v, entry, name) visitor.visitMapEntry(entry, #name, parameters);
533 #define ARILES2_PARENT_read(v, entry)
534 #define ARILES2_VISIT_read \
535  template <class t_Visitor> /* cppcheck-suppress duplInheritedMember */ \
536  void arilesVisit( \
537  t_Visitor &visitor, \
538  const typename t_Visitor::Parameters &parameters, \
539  ARILES2_IS_BASE_ENABLER(ariles2::read::Visitor, t_Visitor)) \
540  { \
541  CPPUT_TRACE_FUNCTION; \
542  CPPUT_UNUSED_ARG(visitor); \
543  CPPUT_UNUSED_ARG(parameters); \
544  arilesVisitParents(visitor, parameters); \
545  ARILES2_ENTRIES(read) \
546  }
547 
548 #define ARILES2_METHODS_read ARILES2_METHODS(read, ARILES2_EMPTY_MACRO, ARILES2_EMPTY_MACRO)
549 #define ARILES2_BASE_METHODS_read ARILES2_BASE_METHODS(read)
550  } // namespace read
551 
552 
553  /// @ingroup read
555 } // namespace ariles2
FileVisitorImplementation(const std::string &file_name)
Definition: read.h:499
void openFile(const std::string &file_name)
open configuration file
Definition: read.h:516
FileVisitorImplementation(std::istream &input_stream)
Definition: read.h:505
virtual void startMatrixRow(const std::size_t row_index, const std::size_t cols, const Parameters &param)
Definition: read.h:311
virtual bool startRoot(const std::vector< std::string > &subtree)
Definition: read.h:95
void visitVectorElement(t_Element &element, const Parameters &)
Definition: read.h:467
virtual void endIteratedMapElement()
Definition: read.h:207
virtual void endVector()
Definition: read.h:268
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
const std::string & convertSubtreeToString(const std::string &subtree) const
Definition: read.h:136
virtual void endMatrix(const bool dynamic, const Parameters &param)
Definition: read.h:337
virtual void endRoot(const std::string &name)
Definition: read.h:85
std::string convertSubtreeToString(const std::vector< std::string > &subtree) const
Definition: read.h:141
virtual bool startRoot(const std::string &name)
Definition: read.h:73
virtual void startVectorElement()
Definition: read.h:260
ARILES2_BASIC_TYPES_LIST void visit(t_Entry &entry, const t_Subtree &subtree, const Parameters &param)
Definition: read.h:389
bool startPointer(const Parameters &param)
Definition: read.h:215
virtual void endArrayElement()=0
virtual void startArrayElement()
Definition: read.h:252
void visitMatrixElement(t_Element &element, const Parameters &)
Definition: read.h:478
virtual void endArray()=0
virtual void endMatrixRow(const Parameters &param)
Definition: read.h:329
virtual void endIteratedMap()
Definition: read.h:210
void visitArrayElement(t_Element &element, const Parameters &param)
Definition: read.h:456
bool visitMapEntry(t_Entry &entry, const std::string &name, const Parameters &param, const bool override_missing_entries_locally=false)
Definition: read.h:420
virtual void readElement(std::complex< float > &entry)
Definition: read.h:371
virtual void endMatrixElement()
Definition: read.h:325
virtual void endMapEntry()=0
endMapEntry from the current entry to its parent.
void readElement(std::complex< t_Scalar > &entry)
Definition: read.h:357
virtual void endRoot(const std::vector< std::string > &subtree)
Definition: read.h:117
virtual std::size_t startVector()
Definition: read.h:256
virtual bool startIteratedMap(const SizeLimitEnforcementType=SIZE_LIMIT_NONE, const std::size_t=0, const std::size_t=0)
Definition: read.h:196
virtual bool startMapEntry(const std::string &child_name)
startMapEntry to the entry with the given name
Definition: read.h:179
virtual void endMap()
Definition: read.h:191
virtual void endVectorElement()
Definition: read.h:264
virtual std::size_t startArray()=0
void startMap(t_Entry &entry, const Parameters &parameters)
Definition: read.h:158
void endPointer(const bool is_null)
Definition: read.h:241
virtual void startMatrixElement()
Definition: read.h:321
virtual bool startIteratedMapElement(std::string &)
Definition: read.h:203
virtual void startMap(const SizeLimitEnforcementType=SIZE_LIMIT_NONE, const std::size_t=0, const std::size_t=0)
Definition: read.h:165
virtual void startMatrix(std::size_t &cols, std::size_t &rows, const bool dynamic, const Parameters &param)
Definition: read.h:274
virtual void readElement(std::complex< double > &entry)
Definition: read.h:375
#define CPPUT_PERSISTENT_ASSERT(condition,...)
Definition: exception.h:23
#define CPPUT_THROW(...)
Definition: exception.h:19
#define CPPUT_ASSERT(condition,...)
Definition: exception.h:32
#define ARILES2_BASIC_TYPES_LIST
Definition: helpers.h:72
#define CPPUT_UNUSED_ARG(parameter)
Definition: misc.h:19
void apply_read(t_Visitor &visitor, t_Entry &entry, const typename t_Visitor::Parameters &parameters, ARILES2_IS_BASE_ENABLER(ariles2::read::Base, t_Entry))
Definition: basic.h:21
serialization::Parameters Parameters
Definition: read.h:30
Definition: basic.h:17
#define CPPUT_TRACE_FUNCTION
Definition: trace.h:126
#define CPPUT_TRACE_TYPE(type)
Definition: trace.h:128
#define CPPUT_TRACE_VALUE(value)
Definition: trace.h:127