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