Ariles
reader.cpp
Go to the documentation of this file.
1 /**
2  @file
3  @author Alexander Sherikov
4 
5  @copyright 2014-2017 INRIA. Licensed under the Apache License, Version 2.0.
6  (see @ref LICENSE or http://www.apache.org/licenses/LICENSE-2.0)
7 
8  @copyright 2017-2018 Alexander Sherikov, Licensed under the Apache License, Version 2.0.
9  (see @ref LICENSE or http://www.apache.org/licenses/LICENSE-2.0)
10 
11  @brief
12 */
13 
14 #include <sstream>
15 #include <msgpack.hpp>
16 
18 
19 namespace ariles2
20 {
21  namespace ns_msgpack
22  {
24  }
25 } // namespace ariles2
26 
27 
28 namespace ariles2
29 {
30  namespace ns_msgpack
31  {
32  namespace impl
33  {
35  {
36  public:
37  std::string buffer_;
38 
39  std::vector<std::shared_ptr<::msgpack::object_handle>> handles_;
40 
41  std::size_t nameless_counter_;
42 
43 
44  public:
45  template <class... t_Args>
46  explicit Reader(t_Args &&...args) : FileVisitorImplementation(std::forward<t_Args>(args)...)
47  {
48  initialize();
49  }
50 
51 
52  /**
53  * @brief open configuration file
54  */
55  void initialize()
56  {
58  std::stringstream str_stream;
59  str_stream << input_stream_->rdbuf();
60  buffer_ = str_stream.str();
61 
62 
63  handles_.clear();
64  try
65  {
66  std::size_t buffer_offset = 0;
67 
68  while (buffer_offset != buffer_.size())
69  {
70  handles_.push_back(std::make_shared<::msgpack::object_handle>());
71 
72  unpack(*handles_.back(), buffer_.data(), buffer_.size(), buffer_offset);
73  }
74  }
75  catch (const std::exception &e)
76  {
77  CPPUT_THROW("Failed to parse the configuration file: ", e.what());
78  }
79 
81  }
82 
83 
84  /**
85  * @brief Get current node
86  *
87  * @return pointer to the current node
88  */
89  const ::msgpack::object &getRawNode(const std::size_t depth)
90  {
92  if (node_stack_[depth].isArray())
93  {
94  return (getRawNode(depth - 1).via.array.ptr[node_stack_[depth].index_]);
95  }
96  return (*node_stack_[depth].node_);
97  }
98 
99 
100  const ::msgpack::object &getRawNode()
101  {
103  return (getRawNode(node_stack_.size() - 1));
104  }
105  };
106  } // namespace impl
107  } // namespace ns_msgpack
108 } // namespace ariles2
109 
110 
111 namespace ariles2
112 {
113  namespace ns_msgpack
114  {
115  Reader::Reader(const std::string &file_name)
116  {
117  makeImplPtr(file_name);
118  }
119 
120 
121  Reader::Reader(std::istream &input_stream)
122  {
123  makeImplPtr(input_stream);
124  }
125 
126 
127  void Reader::startMap(const SizeLimitEnforcementType limit_type, const std::size_t min, const std::size_t max)
128  {
130  checkSize(limit_type, impl_->getRawNode().via.map.size, min, max);
131  }
132 
133 
134 
135  bool Reader::startMapEntry(const std::string &child_name)
136  {
138  CPPUT_TRACE_VALUE(child_name);
139  if (impl_->empty())
140  {
141  for (std::size_t i = 0; i < impl_->handles_.size(); ++i)
142  {
143  if (::msgpack::type::MAP == impl_->handles_[i]->get().type)
144  {
145  if (child_name == impl_->handles_[i]->get().via.map.ptr[0].key.as<std::string>())
146  {
147  if (::msgpack::type::MAP == impl_->handles_[i]->get().via.map.ptr[0].val.type)
148  {
149  impl_->emplace(&(impl_->handles_[i]->get().via.map.ptr[0].val));
150  return (true);
151  }
152  }
153  }
154  }
155  }
156  else
157  {
158  if (::msgpack::type::MAP == impl_->getRawNode().type)
159  {
160  for (std::size_t i = 0; i < impl_->getRawNode().via.map.size; ++i)
161  {
162  if (child_name == impl_->getRawNode().via.map.ptr[i].key.as<std::string>())
163  {
164  impl_->emplace(&(impl_->getRawNode().via.map.ptr[i].val));
165  return (true);
166  }
167  }
168  }
169  }
170 
171  return (false);
172  }
173 
174 
176  {
178  impl_->pop();
179  }
180 
181 
182  std::size_t Reader::startArray()
183  {
185  const std::size_t size = impl_->getRawNode().via.array.size;
186  impl_->emplace(0, size);
187 
188  return (size);
189  }
190 
191 
193  {
195  impl_->pop();
196  }
197 
198 
200  {
201  CPPUT_ASSERT(
202  impl_->back().index_ < impl_->back().size_,
203  "Internal error: array has more elements than expected.");
204  }
205 
206 
208  {
210  impl_->shiftArray();
211  }
212 
213 
214  bool Reader::startRoot(const std::string &name)
215  {
217  if (name.empty())
218  {
219  CPPUT_ASSERT(
220  0 == impl_->nameless_counter_,
221  "Multiple nameless root entries are not supported, specify root names explicitly.");
222  ++impl_->nameless_counter_;
223  return (startMapEntry("ariles"));
224  }
225  return (startMapEntry(name));
226  }
227 
228  void Reader::endRoot(const std::string & /*name*/)
229  {
231  endMapEntry();
232  }
233 
234 
235 #define ARILES2_BASIC_TYPE(type) \
236  void Reader::readElement(type &element) \
237  { \
238  CPPUT_TRACE_FUNCTION; \
239  impl_->getRawNode() >> element; \
240  }
241 
243 
244 #undef ARILES2_BASIC_TYPE
245  } // namespace ns_msgpack
246 } // namespace ariles2
void endMapEntry()
endMapEntry from the current entry to its parent.
Definition: reader.cpp:175
bool startRoot(const std::string &name)
Definition: reader.cpp:214
bool startMapEntry(const std::string &child_name)
startMapEntry to the entry with the given name
Definition: reader.cpp:135
void startMap(const SizeLimitEnforcementType limit_type=SIZE_LIMIT_NONE, const std::size_t min=0, const std::size_t max=0)
Definition: reader.cpp:127
void endRoot(const std::string &name)
Definition: reader.cpp:228
Reader(const std::string &file_name)
Constructor.
Definition: reader.cpp:115
std::size_t startArray()
Definition: reader.cpp:182
const ::msgpack::object & getRawNode(const std::size_t depth)
Get current node.
Definition: reader.cpp:89
const ::msgpack::object & getRawNode()
Definition: reader.cpp:100
void initialize()
open configuration file
Definition: reader.cpp:55
Reader(t_Args &&...args)
Definition: reader.cpp:46
std::vector< std::shared_ptr<::msgpack::object_handle > > handles_
Definition: reader.cpp:39
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
#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_MACRO_SUBSTITUTE(macro)
Definition: misc.h:21
Definition: basic.h:17
#define CPPUT_TRACE_FUNCTION
Definition: trace.h:126
#define CPPUT_TRACE_VALUE(value)
Definition: trace.h:127