humoto
reader.h
Go to the documentation of this file.
1 /**
2  @file
3  @author Alexander Sherikov
4  @copyright 2014-2017 INRIA. Licensed under the Apache License, Version 2.0.
5  (see @ref LICENSE or http://www.apache.org/licenses/LICENSE-2.0)
6 
7  @brief
8 */
9 
10 #pragma once
11 
12 namespace humoto
13 {
14  namespace config
15  {
16  namespace msgpack
17  {
18  /**
19  * @brief Configuration reader class
20  */
22  {
23  private:
24  std::string buffer_;
25 
26  std::vector< boost::shared_ptr< ::msgpack::object_handle > > handles_;
27 
28  /// Stack of nodes.
29  std::stack< const ::msgpack::object * > node_stack_;
30 
31 
32  private:
33  /**
34  * @brief open configuration file
35  *
36  * @param[in] file_name
37  */
38  void openFile(const std::string& file_name)
39  {
40  std::ifstream config_ifs_;
41 
42  config_ifs_.open(file_name.c_str());
43  if (!config_ifs_.good())
44  {
45  std::string file_name_default = std::string(HUMOTO_DEFAULT_CONFIG_PREFIX) + file_name;
46  config_ifs_.open(file_name_default.c_str());
47  }
48  if (!config_ifs_.good())
49  {
50  HUMOTO_THROW_MSG(std::string("Could not open configuration file: ") + file_name.c_str());
51  }
52 
53 
54  std::stringstream str_stream;
55  str_stream << config_ifs_.rdbuf();
56  buffer_ = str_stream.str();
57 
58 
59  handles_.clear();
60  try
61  {
62  std::size_t buffer_offset = 0;
63 
64  while (buffer_offset != buffer_.size())
65  {
66  handles_.push_back(boost::shared_ptr< ::msgpack::object_handle >(new ::msgpack::object_handle));
67 
68  unpack(*handles_[handles_.size()-1], buffer_.data(), buffer_.size(), buffer_offset);
69  }
70  }
71  catch(const std::exception &e)
72  {
73  HUMOTO_THROW_MSG(std::string("Failed to parse the configuration file: ") + e.what());
74  }
75  }
76 
77 
78  /**
79  * @brief Get current node
80  *
81  * @return pointer to the current node
82  */
83  const ::msgpack::object * getCurrentNode() const
84  {
85  return(node_stack_.top());
86  }
87 
88 
89  public:
90  /**
91  * @brief Constructor
92  *
93  * @param[in] file_name
94  */
95  explicit Reader(const std::string& file_name)
96  {
97  openFile(file_name);
98  }
99 
100 
101  /**
102  * @brief Default constructor
103  */
105  {
106  }
107 
108 
109 
110  /**
111  * @brief Descend to the entry with the given name
112  *
113  * @param[in] child_name child node name
114  *
115  * @return true if successful.
116  */
117  bool descend(const std::string & child_name)
118  {
119  if (node_stack_.size() == 0)
120  {
121  for (std::size_t i = 0; i < handles_.size(); ++i)
122  {
123  if (::msgpack::type::MAP == handles_[i]->get().type)
124  {
125  if (child_name == handles_[i]->get().via.map.ptr[0].key.as<std::string>())
126  {
127  if (::msgpack::type::MAP == handles_[i]->get().via.map.ptr[0].val.type)
128  {
129  node_stack_.push( &(handles_[i]->get().via.map.ptr[0].val) );
130  return(true);
131  }
132  }
133  }
134  }
135  }
136  else
137  {
138  if (::msgpack::type::MAP == getCurrentNode()->type)
139  {
140  for (std::size_t i = 0; i < getCurrentNode()->via.map.size; ++i)
141  {
142  if (child_name == getCurrentNode()->via.map.ptr[i].key.as<std::string>())
143  {
144  node_stack_.push( &(getCurrentNode()->via.map.ptr[i].val) );
145  return(true);
146  }
147  }
148  }
149  }
150 
151  return (false);
152  }
153 
154 
155  /**
156  * @brief Ascend from the current entry to its parent.
157  */
158  void ascend()
159  {
160  node_stack_.pop();
161  }
162 
163 
164  /**
165  * @brief Read configuration entry (vector)
166  *
167  * @tparam t_Scalar Eigen template parameter
168  * @tparam t_rows Eigen template parameter
169  * @tparam t_flags Eigen template parameter
170  *
171  * @param[out] entry configuration parameter
172  * @param[in] entry_name name of the configuration parameter
173  * @param[in] crash_on_missing_entry
174  */
175  template < typename t_Scalar,
176  int t_rows,
177  int t_flags>
178  void readCompound(Eigen::Matrix<t_Scalar, t_rows, 1, t_flags> &entry,
179  const std::string & entry_name,
180  const bool crash_on_missing_entry = false)
181  {
182  if (descend(entry_name))
183  {
184  HUMOTO_ASSERT( (::msgpack::type::ARRAY == getCurrentNode()->type),
185  "[Config] Entry is not an array.");
186 
187  if (Eigen::Dynamic == t_rows)
188  {
189  entry.resize(getCurrentNode()->via.array.size);
190  }
191  else
192  {
193  HUMOTO_ASSERT( (static_cast<int>(getCurrentNode()->via.array.size) == t_rows),
194  "[Config] Wrong entry sequence size.");
195  }
196 
197  for(humoto::EigenIndex i = 0; i < (Eigen::Dynamic == t_rows ? entry.rows() : t_rows); ++i)
198  {
199  getCurrentNode()->via.array.ptr[i] >> entry[i];
200  }
201 
202  ascend();
203  }
204  else
205  {
206  if (crash_on_missing_entry)
207  {
208  HUMOTO_THROW_MSG(std::string("Configuration file does not contain entry '") + entry_name + "'.");
209  }
210  }
211  }
212 
213 
214 
215  /**
216  * @brief Read a configuration entry (matrix)
217  *
218  * @tparam t_Scalar Eigen template parameter
219  * @tparam t_rows Eigen template parameter
220  * @tparam t_cols Eigen template parameter
221  * @tparam t_flags Eigen template parameter
222  *
223  * @param[out] entry data
224  * @param[in] entry_name name
225  * @param[in] crash_on_missing_entry
226  */
227  template < typename t_Scalar,
228  int t_rows,
229  int t_cols,
230  int t_flags>
231  void readCompound( Eigen::Matrix<t_Scalar, t_rows, t_cols, t_flags> &entry,
232  const std::string& entry_name,
233  const bool crash_on_missing_entry = false)
234  {
235  if (descend(entry_name))
236  {
237  humoto::EigenIndex num_rows;
238  humoto::EigenIndex num_cols;
239 
240  readScalar(num_rows, "rows", true);
241  readScalar(num_cols, "cols", true);
242 
243 
244  Eigen::VectorXd v;
245  readCompound(v, "data", true);
246 
247  HUMOTO_ASSERT( v.rows() == num_rows*num_cols,
248  std::string("Inconsistent configuration file entry: ") + entry_name);
249 
250  Eigen::Map< Eigen::Matrix< double,
251  Eigen::Dynamic,
252  Eigen::Dynamic,
253  Eigen::RowMajor> > map(v.data(),
254  num_rows,
255  num_cols);
256  entry = map;
257 
258  ascend();
259  }
260  else
261  {
262  if (crash_on_missing_entry)
263  {
264  HUMOTO_THROW_MSG(std::string("Configuration file does not contain entry '") + entry_name + "'.");
265  }
266  }
267  }
268 
269 
270  /**
271  * @brief Read configuration entry (std::vector)
272  *
273  * @tparam t_VectorEntryType type of the entry of std::vector
274  *
275  * @param[out] entry configuration parameter
276  * @param[in] entry_name name of the configuration parameter
277  * @param[in] crash_on_missing_entry
278  */
279  template <typename t_VectorEntryType>
280  void readCompound( std::vector<t_VectorEntryType> & entry,
281  const std::string & entry_name,
282  const bool crash_on_missing_entry = false)
283  {
284  if (descend(entry_name))
285  {
286  HUMOTO_ASSERT( (::msgpack::type::ARRAY == getCurrentNode()->type),
287  "[Config] Entry is not an array.");
288 
289  entry.resize(getCurrentNode()->via.array.size);
290 
291  for(std::size_t i = 0; i < entry.size(); ++i)
292  {
293  getCurrentNode()->via.array.ptr[i] >> entry[i];
294  }
295 
296  ascend();
297  }
298  else
299  {
300  if (crash_on_missing_entry)
301  {
302  HUMOTO_THROW_MSG(std::string("Configuration file does not contain entry '") + entry_name + "'.");
303  }
304  }
305  }
306 
307 
308 
309  /**
310  * @brief Read configuration entry (scalar template)
311  *
312  * @tparam t_EntryType type of the entry
313  *
314  * @param[out] entry configuration parameter
315  * @param[in] entry_name name of the configuration parameter
316  * @param[in] crash_on_missing_entry
317  */
318  template <typename t_EntryType>
319  void readScalar(t_EntryType & entry,
320  const std::string & entry_name,
321  const bool crash_on_missing_entry = false)
322  {
323  if (descend(entry_name))
324  {
325  *getCurrentNode() >> entry;
326  ascend();
327  }
328  else
329  {
330  if (crash_on_missing_entry)
331  {
332  HUMOTO_THROW_MSG(std::string("Configuration file does not contain entry '") + entry_name + "'.");
333  }
334  }
335  }
336 
337 
338  /**
339  * @brief Read configuration entry (an enum). This method
340  * is added since an explicit casting to integer is needed.
341  *
342  * @tparam t_EnumerationType enumeration type
343  *
344  * @param[out] entry configuration parameter
345  * @param[in] entry_name name of the configuration parameter
346  * @param[in] crash_on_missing_entry
347  */
348  template <typename t_EnumerationType>
349  void readEnum( t_EnumerationType & entry,
350  const std::string & entry_name,
351  const bool crash_on_missing_entry = false)
352  {
353  if (descend(entry_name))
354  {
355  int tmp_value = 0;
356  *getCurrentNode() >> tmp_value;
357 
358  entry = static_cast<t_EnumerationType> (tmp_value);
359 
360  ascend();
361  }
362  else
363  {
364  if (crash_on_missing_entry)
365  {
366  HUMOTO_THROW_MSG(std::string("Configuration file does not contain entry '") + entry_name + "'.");
367  }
368  }
369  }
370  };
371  }
372  }
373 }
#define HUMOTO_LOCAL
Definition: export_import.h:26
std::vector< boost::shared_ptr< ::msgpack::object_handle > > handles_
Definition: reader.h:26
#define HUMOTO_ASSERT(condition, message)
void readEnum(t_EnumerationType &entry, const std::string &entry_name, const bool crash_on_missing_entry=false)
Read configuration entry (an enum). This method is added since an explicit casting to integer is need...
Definition: reader.h:349
#define HUMOTO_THROW_MSG(s)
HUMOTO_THROW_MSG throws an error message concatenated with the name of the function (if supported)...
EIGEN_DEFAULT_DENSE_INDEX_TYPE EigenIndex
Definition: utility.h:26
void readCompound(Eigen::Matrix< t_Scalar, t_rows, t_cols, t_flags > &entry, const std::string &entry_name, const bool crash_on_missing_entry=false)
Read a configuration entry (matrix)
Definition: reader.h:231
bool descend(const std::string &child_name)
Descend to the entry with the given name.
Definition: reader.h:117
void ascend()
Ascend from the current entry to its parent.
Definition: reader.h:158
Reader(const std::string &file_name)
Constructor.
Definition: reader.h:95
Reader()
Default constructor.
Definition: reader.h:104
void readCompound(Eigen::Matrix< t_Scalar, t_rows, 1, t_flags > &entry, const std::string &entry_name, const bool crash_on_missing_entry=false)
Read configuration entry (vector)
Definition: reader.h:178
std::stack< const ::msgpack::object *> node_stack_
Stack of nodes.
Definition: reader.h:29
The root namespace of HuMoTo.
Definition: config.h:12
void openFile(const std::string &file_name)
open configuration file
Definition: reader.h:38
const ::msgpack::object * getCurrentNode() const
Get current node.
Definition: reader.h:83
Configuration reader class.
Definition: reader.h:21
void readScalar(t_EntryType &entry, const std::string &entry_name, const bool crash_on_missing_entry=false)
Read configuration entry (scalar template)
Definition: reader.h:319
void readCompound(std::vector< t_VectorEntryType > &entry, const std::string &entry_name, const bool crash_on_missing_entry=false)
Read configuration entry (std::vector)
Definition: reader.h:280