Ariles
reader.cpp
Go to the documentation of this file.
1 /**
2  @file
3  @author Alexander Sherikov
4 
5  @copyright 2018-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 #include <boost/math/special_functions.hpp>
13 #include "common.h"
14 
15 
16 namespace ariles2
17 {
18  namespace ns_rapidjson
19  {
20  namespace impl
21  {
22  class Reader : public ariles2::ns_rapidjson::ImplBase<const ::rapidjson::Value>,
24  {
25  public:
26  std::vector<::rapidjson::Value::ConstMemberIterator> iterator_stack_;
27 
28  public:
29  Reader() = default;
30 
31  template <class... t_Args>
32  explicit Reader(t_Args &&...args) : FileVisitorImplementation(std::forward<t_Args>(args)...)
33  {
34  initialize();
35  }
36 
37 
38  void initialize()
39  {
41  document_.ParseStream(isw);
42  CPPUT_ASSERT(not document_.HasParseError(), "Parsing failed");
43  }
44  };
45  } // namespace impl
46  } // namespace ns_rapidjson
47 } // namespace ariles2
48 
49 
50 
51 namespace ariles2
52 {
53  namespace ns_rapidjson
54  {
55  Reader::Reader(const std::string &file_name)
56  {
57  makeImplPtr(file_name);
58  }
59 
60 
61  Reader::Reader(std::istream &input_stream)
62  {
63  makeImplPtr(input_stream);
64  }
65 
66 
67  void Reader::constructFromString(const char *input_string)
68  {
69  makeImplPtr();
70  impl_->document_.Parse(input_string);
71  }
72 
73 
74  void Reader::startMap(const SizeLimitEnforcementType limit_type, const std::size_t min, const std::size_t max)
75  {
77  checkSize(limit_type, impl_->getRawNode().MemberCount(), min, max);
78  }
79 
80  bool Reader::startMapEntry(const std::string &child_name)
81  {
82  const ::rapidjson::Value::ConstMemberIterator child = impl_->getRawNode().FindMember(child_name.c_str());
83 
84  if (impl_->getRawNode().MemberEnd() == child)
85  {
86  return (false);
87  }
88  impl_->emplace(&(child->value));
89  return (true);
90  }
91 
93  {
94  impl_->pop();
95  }
96 
97 
99  const SizeLimitEnforcementType limit_type,
100  const std::size_t min,
101  const std::size_t max)
102  {
104  checkSize(limit_type, impl_->getRawNode().MemberCount(), min, max);
105 
106 
107  const ::rapidjson::Value &selected_node = impl_->getRawNode();
108 
109  if (selected_node.IsObject())
110  {
111  impl_->iterator_stack_.push_back(selected_node.MemberBegin());
112  return (true);
113  }
114  return (false);
115  }
116 
117  bool Reader::startIteratedMapElement(std::string &entry_name)
118  {
119  if (impl_->iterator_stack_.back() != impl_->getRawNode().MemberEnd())
120  {
121  impl_->emplace(&(impl_->iterator_stack_.back()->value));
122  entry_name = impl_->iterator_stack_.back()->name.GetString();
123  return (true);
124  }
125  return (false);
126  }
127 
129  {
130  ++impl_->iterator_stack_.back();
131  impl_->pop();
132  }
133 
135  {
136  CPPUT_ASSERT(
137  impl_->iterator_stack_.back() == impl_->getRawNode().MemberEnd(),
138  "End of iterated map has not been reached.");
139  impl_->iterator_stack_.pop_back();
140  }
141 
142 
143  std::size_t Reader::startArray()
144  {
145  CPPUT_ASSERT(impl_->getRawNode().IsArray(), "Internal error: expected array.");
146 
147  std::size_t size = impl_->getRawNode().Size();
148  impl_->emplace(0, size);
149 
150  return (size);
151  }
152 
153 
155  {
156  CPPUT_ASSERT(
157  impl_->back().index_ < impl_->back().size_,
158  "Internal error: array has more elements than expected.");
159  }
160 
161 
163  {
164  impl_->shiftArray();
165  }
166 
167 
169  {
170  impl_->pop();
171  }
172 
173 
174  void Reader::readElement(std::string &element)
175  {
176  element = impl_->getRawNode().GetString();
177  }
178 
179 
180  void Reader::readElement(bool &element)
181  {
182  element = impl_->getRawNode().GetBool();
183  }
184 
185 
186  void Reader::readElement(float &element)
187  {
188  float tmp_value = 0.0;
189  if (impl_->getRawNode().IsString())
190  {
191  tmp_value = boost::lexical_cast<float>(impl_->getRawNode().GetString());
192  if (boost::math::isnan(tmp_value))
193  {
194  element = std::numeric_limits<float>::signaling_NaN();
195  return;
196  }
197  if (boost::math::isinf(tmp_value))
198  {
199  element = static_cast<float>(tmp_value);
200  return;
201  }
202  }
203  else
204  {
205  tmp_value = static_cast<float>(impl_->getRawNode().GetDouble()); // old API compatibility
206  // tmp_value = impl_->getRawNode().GetFloat();
207  }
208  CPPUT_ASSERT(
209  tmp_value <= std::numeric_limits<float>::max() && tmp_value >= -std::numeric_limits<float>::max(),
210  "Value is out of range.");
211  element = static_cast<float>(tmp_value);
212  }
213 
214 
215  void Reader::readElement(double &element)
216  {
217  double tmp_value = 0.0;
218  if (impl_->getRawNode().IsString())
219  {
220  tmp_value = boost::lexical_cast<double>(impl_->getRawNode().GetString());
221  if (boost::math::isnan(tmp_value))
222  {
223  element = std::numeric_limits<double>::signaling_NaN();
224  return;
225  }
226  if (boost::math::isinf(tmp_value))
227  {
228  element = static_cast<double>(tmp_value);
229  return;
230  }
231  }
232  else
233  {
234  tmp_value = impl_->getRawNode().GetDouble();
235  }
236  CPPUT_ASSERT(
237  tmp_value <= std::numeric_limits<double>::max() && tmp_value >= -std::numeric_limits<double>::max(),
238  "Value is out of range.");
239  element = static_cast<double>(tmp_value);
240  }
241 
242 
243 #define ARILES2_BASIC_TYPE(type) \
244  void Reader::readElement(type &element) \
245  { \
246  int64_t tmp_value = impl_->getRawNode().GetInt64(); \
247  CPPUT_ASSERT( \
248  tmp_value <= std::numeric_limits<type>::max() && tmp_value >= std::numeric_limits<type>::min(), \
249  "Value is out of range."); \
250  element = static_cast<type>(tmp_value); \
251  }
252 
254 
255 #undef ARILES2_BASIC_TYPE
256 
257 
258 #define ARILES2_BASIC_TYPE(type) \
259  void Reader::readElement(type &element) \
260  { \
261  uint64_t tmp_value = impl_->getRawNode().GetUint64(); \
262  CPPUT_ASSERT(tmp_value <= std::numeric_limits<type>::max(), "Value is too large."); \
263  element = static_cast<type>(tmp_value); \
264  }
265 
267 
268 #undef ARILES2_BASIC_TYPE
269  } // namespace ns_rapidjson
270 } // namespace ariles2
Wrapper of std::basic_istream into RapidJSON's Stream concept.
::rapidjson::Document document_
instance of the parser
Definition: common.h:40
bool startIteratedMapElement(std::string &entry_name)
Definition: reader.cpp:117
void endMapEntry()
endMapEntry from the current entry to its parent.
Definition: reader.cpp:92
bool startIteratedMap(const SizeLimitEnforcementType=SIZE_LIMIT_NONE, const std::size_t=0, const std::size_t=0)
Definition: reader.cpp:98
void startMap(const SizeLimitEnforcementType limit_type=SIZE_LIMIT_NONE, const std::size_t min=0, const std::size_t max=0)
Definition: reader.cpp:74
bool startMapEntry(const std::string &child_name)
startMapEntry to the entry with the given name
Definition: reader.cpp:80
void constructFromString(const char *)
Definition: reader.cpp:67
std::vector<::rapidjson::Value::ConstMemberIterator > iterator_stack_
Definition: reader.cpp:26
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
void readElement(std::complex< t_Scalar > &entry)
Definition: read.h:357
#define CPPUT_ASSERT(condition,...)
Definition: exception.h:32
#define ARILES2_BASIC_UNSIGNED_INTEGER_TYPES_LIST
Definition: helpers.h:50
#define ARILES2_BASIC_SIGNED_INTEGER_TYPES_LIST
Definition: helpers.h:37
#define CPPUT_MACRO_SUBSTITUTE(macro)
Definition: misc.h:21
Definition: basic.h:17
#define CPPUT_TRACE_FUNCTION
Definition: trace.h:126