tue_config
reader_writer.cpp
Go to the documentation of this file.
2 #include "tue/config/node.h"
3 #include "tue/config/data.h"
4 
5 // Merge
6 #include "tue/config/sequence.h"
7 #include "tue/config/map.h"
8 
9 #include <boost/make_shared.hpp>
10 
11 // SDF
12 #include "tue/config/loaders/sdf.h"
13 
14 // XML
15 #include "tue/config/loaders/xml.h"
16 
17 // YAML
20 #include <sstream>
21 
22 // Sync
23 #include <tue/filesystem/path.h>
24 #include <boost/filesystem.hpp>
25 
26 namespace tue
27 {
28 namespace config
29 {
30 
31 // ----------------------------------------------------------------------------------------------------
32 
33 ReaderWriter::ReaderWriter() : idx_(0), scope_(0), cfg_(new Data), error_(new Error)
34 {
35 }
36 
37 // ----------------------------------------------------------------------------------------------------
38 
39 ReaderWriter::ReaderWriter(DataPointer& cfg) : idx_(cfg.idx), scope_(0), cfg_(cfg.data), error_(new Error)
40 {
41  if (!cfg_)
42  {
43  cfg_.reset(new Data);
44  cfg.data = cfg_;
45  }
46 }
47 
48 // ----------------------------------------------------------------------------------------------------
49 
51 {
52 }
53 
54 // ----------------------------------------------------------------------------------------------------
55 
56 bool ReaderWriter::read(const std::string& name, const NodeType type, const RequiredOrOptional opt)
57 {
58  Label label;
59  NodeIdx child_idx; // Needed for checking if the child node is indeed the type(map/array) we are looking for.
60  if (cfg_->getLabel(name, label) && cfg_->nodes[idx_]->readGroup(label, child_idx))
61  {
62  // check if child matches the type you want to read.
63  if (cfg_->nodes[child_idx]->type() == type)
64  {
65  idx_ = child_idx;
66  return true;
67  }
68  }
69 
70  if (opt == REQUIRED)
71  addError("Expected group: '" + name + "', found none.");
72 
73  return false;
74 }
75 
76 // ----------------------------------------------------------------------------------------------------
77 
79 {
80  if (idx_ == scope_)
81  return false;
82 
83  NodeIdx parent = cfg_->getParent(idx_);
84  if (parent == static_cast<NodeIdx>(-1))
85  return false;
86 
87  idx_ = parent;
88 
89  // If the parent is an array, go up one more
90  if (cfg_->nodes[idx_]->type() == ARRAY)
91  idx_ = cfg_->getParent(idx_);
92 
93  return true;
94 }
95 
96 // ----------------------------------------------------------------------------------------------------
97 
99 {
100  if (cfg_->nodes[idx_]->type() == ARRAY)
101  return cfg_->nodes[idx_]->firstChild(idx_);
102 
103  NodeIdx right_sibling = cfg_->getRightSibling(idx_);
104  if (right_sibling == static_cast<NodeIdx>(-1))
105  return false;
106 
107  idx_ = right_sibling;
108  return true;
109 }
110 
111 // ----------------------------------------------------------------------------------------------------
112 
114 {
115  ReaderWriter r(*this);
116  r.scope_ = r.idx_;
117  return r;
118 }
119 
120 // ----------------------------------------------------------------------------------------------------
121 
122 bool ReaderWriter::hasChild(const std::string& name, NodeType type) const
123 {
124  Label label;
125  NodeIdx child_idx; // Needed for checking if the child node is indeed the type(map/array) we are looking for.
126  if (cfg_->getLabel(name, label) && cfg_->nodes[idx_]->readGroup(label, child_idx))
127  {
128  // check if child matches the type you want to read.
129  return cfg_->nodes[child_idx]->type() == type;
130  }
131  return false;
132 }
133 
134 // ----------------------------------------------------------------------------------------------------
135 
137 {
138  std::string& error_msg = error_->message;
139 
140  // build context
141  std::vector<std::string> context;
142 
143  if (error_context_)
144  {
145  error_msg += *error_context_ + "\n\n";
146  }
147  else
148  {
149  // Default error context
150 
151  NodeIdx c = idx_;
152  while(c != static_cast<NodeIdx>(-1))
153  {
154  const NodePtr& n = cfg_->nodes[c];
155  context.push_back(n->name());
156  c = cfg_->getParent(c);
157  }
158 
159  if (context.size() > 1)
160  {
161  error_msg += "In '";
162 
163  for(int i = context.size() - 2; i > 0; --i)
164  {
165  error_msg += context[i] + ".";
166  }
167 
168  error_msg += context[0] + "': \n\n";
169  }
170  else
171  {
172  error_msg += "In root of configuration:\n\n";
173  }
174  }
175 
176  error_msg += " " + msg + "\n\n";
177 }
178 
179 // ----------------------------------------------------------------------------------------------------
180 
182 {
183  if (cfg_->nodes[idx_]->type() != MAP)
184  return false;
185 
186  Label label = cfg_->getOrAddLabel(name);
187 
188  if (cfg_->nodes[idx_]->readGroup(label, idx_))
189  return true;
190 
191  // If no child node with name is known, create a new one.
192  NodeIdx n = cfg_->addNode(boost::make_shared<Map>(label), idx_);
193 
194  if (!cfg_->nodes[idx_]->addGroup(label, n, idx_))
195  return false;
196 
197  return true;
198 }
199 
200 // ----------------------------------------------------------------------------------------------------
201 
203 {
204  if (cfg_->nodes[idx_]->type() != MAP)
205  return false;
206 
207  Label label = cfg_->getOrAddLabel(name);
208 
209  if (cfg_->nodes[idx_]->readGroup(label, idx_))
210  return true;
211 
212  // If no child node with name is known, create a new one.
213  NodeIdx n = cfg_->addNode(boost::make_shared<Sequence>(label), idx_);
214 
215  if (!cfg_->nodes[idx_]->addGroup(label, n, idx_))
216  return false;
217 
218  return true;
219 }
220 
221 // ----------------------------------------------------------------------------------------------------
222 
224 {
225  if (cfg_->nodes[idx_]->type() != ARRAY)
226  return false;
227 
228  NodePtr node = boost::make_shared<Map>("");
229  NodeIdx n = cfg_->addNode(node, idx_);
230 
231  NodeIdx previous;
232  if (!cfg_->nodes[idx_]->add(n, previous))
233  return false;
234 
235  if (previous != static_cast<NodeIdx>(-1))
236  cfg_->setRightSibling(previous, n);
237 
238  idx_ = n;
239 
240  return true;
241 }
242 
243 // ----------------------------------------------------------------------------------------------------
244 
246 {
247  NodeIdx parent = cfg_->getParent(idx_);
248  if (parent == static_cast<NodeIdx>(-1))
249  return false;
250 
251  idx_ = parent;
252  return true;
253 }
254 
255 // ----------------------------------------------------------------------------------------------------
256 
258 {
259  YAMLEmitter emitter;
261  emitter.emit(DataConstPointer(cfg_, idx_), s);
262  return s.str();
263 }
264 
265 // ----------------------------------------------------------------------------------------------------
266 
268 {
269  // Remove possible previous errors
270  error_->message.clear();
271 
272  // Reset head
273  idx_ = scope_;
274 
275  if (!config::loadFromSDFFile(filename, *this))
276  return false;
277 
278  filename_ = filename;
280 
281  return true;
282 }
283 
284 // ----------------------------------------------------------------------------------------------------
285 
287 {
288  // Remove possible previous errors
289  error_->message.clear();
290 
291  // Reset head
292  idx_ = scope_;
293 
294  if (!config::loadFromXMLFile(filename, *this))
295  return false;
296 
297  filename_ = filename;
299 
300  return true;
301 }
302 
303 // ----------------------------------------------------------------------------------------------------
304 
305 bool ReaderWriter::loadFromYAMLFile(const std::string& filename, const ResolveConfig& resolve_config)
306 {
307  // Remove possible previous errors
308  error_->message.clear();
309 
310  // Reset head
311  idx_ = scope_;
312 
313  if (!config::loadFromYAMLFile(filename, *this, resolve_config))
314  return false;
315 
316  filename_ = filename;
318  resolve_config_ = resolve_config;
319 
320  return true;
321 }
322 
323 // ----------------------------------------------------------------------------------------------------
324 
326 
327  if (!filename_.empty() )
328  {
329  std::time_t last_write_time;
330 
331  try
332  {
333  last_write_time = tue::filesystem::Path(filename_).lastWriteTime();
334  }
335  catch (boost::filesystem::filesystem_error& e)
336  {
337  return false;
338  }
339 
340  if (last_write_time > source_last_write_time_)
341  {
343  if ( extension == ".sdf" || extension == ".world")
345  else if (extension == ".xml")
347  else if (extension == ".yml" || extension == ".yaml")
349  else
350  std::cout << "[ReaderWriter::Sync] extension: '" << extension << "' is not supported." << std::endl;
351  source_last_write_time_ = last_write_time;
352  return true;
353  }
354  }
355 
356  return false;
357 }
358 
359 // ----------------------------------------------------------------------------------------------------
360 
362 {
363  out << DataPointer(rw.cfg_, rw.idx_);
364  return out;
365 }
366 
367 } // end namespace config
368 
369 } // end namespace tue
370 
sstream
tue::config::ReaderWriter::loadFromSDFFile
bool loadFromSDFFile(const std::string &filename)
loadFromSDFFile loads a sdf file into a ReaderWriter class
Definition: reader_writer.cpp:267
std::string
tue::config::ReaderWriter::filename_
std::string filename_
Definition: reader_writer.h:310
tue::config::Error
Definition: reader_writer.h:19
tue::config::ReaderWriter::endArrayItem
bool endArrayItem()
endArrayItem go back to the array level
Definition: reader_writer.cpp:245
tue::config::loadFromXMLFile
bool loadFromXMLFile(const std::string &filename, ReaderWriter &config)
loadFromXMLFile loads a xml file into a ReaderWriter class
Definition: xml.cpp:159
tue::filesystem::Path
std::vector< std::string >
std::vector::size
T size(T... args)
tue::config::YAMLEmitter
Definition: yaml_emitter.h:16
tue::config::NodeIdx
unsigned int NodeIdx
Definition: data_pointer.h:12
tue::filesystem::Path::extension
std::string extension() const
tue::config::DataPointer
Definition: data_pointer.h:17
std::stringstream
tue::config::ReaderWriter::writeArray
bool writeArray(const std::string &name)
writeArray starts writing an array. Or start extending it, if it already exists.
Definition: reader_writer.cpp:202
tue::config::ReaderWriter::next
bool next()
next go to next item in an array
Definition: reader_writer.cpp:98
tue::config::ReaderWriter::loadFromYAMLFile
bool loadFromYAMLFile(const std::string &filename, const ResolveConfig &resolve_config=ResolveConfig::defaultConfig())
loadFromYAMLFile loads a yaml file into a ReaderWriter class
Definition: reader_writer.cpp:305
tue::config::ReaderWriter::writeGroup
bool writeGroup(const std::string &name)
writeGroup starts writing a group. Or start extending it, if it already exists.
Definition: reader_writer.cpp:181
xml.h
sequence.h
tue::config::ReaderWriter::addArrayItem
bool addArrayItem()
addArrayItem create a new item in the array
Definition: reader_writer.cpp:223
std::vector::push_back
T push_back(T... args)
tue::config::operator<<
std::ostream & operator<<(std::ostream &out, const DataConstPointer &d)
Definition: data_pointer.cpp:128
std::cout
tue::config::ReaderWriter
Definition: reader_writer.h:26
tue::config::ReaderWriter::loadFromXMLFile
bool loadFromXMLFile(const std::string &filename)
loadFromXMLFile loads a xml file into a ReaderWriter class
Definition: reader_writer.cpp:286
tue::config::loadFromYAMLFile
bool loadFromYAMLFile(const std::string &filename, ReaderWriter &config, const ResolveConfig &resolve_config=ResolveConfig::defaultConfig())
loadFromYAMLFile loads a yaml file into a ReaderWriter class
Definition: yaml.cpp:185
tue::config::ReaderWriter::toYAMLString
std::string toYAMLString() const
toYAMLString convert data (from current reading/writing point) to yaml string
Definition: reader_writer.cpp:257
tue::config::ReaderWriter::sync
bool sync()
sync re-read the source file if the file has changed since last reading time.
Definition: reader_writer.cpp:325
tue::config::ReaderWriter::end
bool end()
end go to parent node.
Definition: reader_writer.cpp:78
node.h
tue::config::ReaderWriter::cfg_
boost::shared_ptr< Data > cfg_
Definition: reader_writer.h:301
std::ostream
tue::config::ReaderWriter::resolve_config_
ResolveConfig resolve_config_
Definition: reader_writer.h:314
tue::config::RequiredOrOptional
RequiredOrOptional
Definition: types.h:15
yaml.h
tue::config::ReaderWriter::read
bool read(const std::string &name, const NodeType type, RequiredOrOptional opt=OPTIONAL)
read read child with key 'name' of type ARRAY or MAP
Definition: reader_writer.cpp:56
tue::config::ReaderWriter::error_
boost::shared_ptr< Error > error_
Definition: reader_writer.h:303
tue::config::DataPointer::data
boost::shared_ptr< Data > data
Definition: data_pointer.h:23
map.h
tue::config::loadFromSDFFile
bool loadFromSDFFile(const std::string &filename, ReaderWriter &config)
loadFromSDFFile loads a sdf file into a ReaderWriter class
Definition: sdf.cpp:188
reader_writer.h
tue::config::ReaderWriter::scope_
NodeIdx scope_
Definition: reader_writer.h:299
std::time_t
tue::config::ARRAY
@ ARRAY
Definition: node_type.h:13
tue::config::Data
Definition: data.h:17
tue::config::ReaderWriter::addError
void addError(const std::string &msg)
Definition: reader_writer.cpp:136
path.h
tue::config::MAP
@ MAP
Definition: node_type.h:12
std::endl
T endl(T... args)
tue::config::ReaderWriter::limitScope
ReaderWriter limitScope() const
limitScope Limit the data to the current position. All parents and siblings incl. their child aren't ...
Definition: reader_writer.cpp:113
tue::config::YAMLEmitter::emit
void emit(const tue::config::DataConstPointer &cfg, std::ostream &out, const std::string &indent="")
Definition: yaml_emitter.cpp:64
tue::config::ReaderWriter::idx_
NodeIdx idx_
Definition: reader_writer.h:297
tue::config::ReaderWriter::error_context_
boost::shared_ptr< std::string > error_context_
Definition: reader_writer.h:305
tue::config::ReaderWriter::hasChild
bool hasChild(const std::string &name, NodeType type) const
hasChild check if node has a child with key 'name' and type ARRAY or MAP
Definition: reader_writer.cpp:122
data.h
tue::config::NodePtr
boost::shared_ptr< Node > NodePtr
Definition: types.h:21
tue::config::DataConstPointer
Definition: data_pointer.h:35
std::string::empty
T empty(T... args)
tue::config::NodeType
NodeType
Definition: node_type.h:10
std::stringstream::str
T str(T... args)
tue::config::ResolveConfig
Class to config the resolve behaviour of a loader.
Definition: resolve_config.h:16
tue::config::ReaderWriter::source_last_write_time_
std::time_t source_last_write_time_
Definition: reader_writer.h:312
tue::config::REQUIRED
@ REQUIRED
Definition: types.h:17
tue::config::ReaderWriter::~ReaderWriter
virtual ~ReaderWriter()
Definition: reader_writer.cpp:50
tue::filesystem::Path::lastWriteTime
std::time_t lastWriteTime() const
sdf.h
tue::config::ReaderWriter::ReaderWriter
ReaderWriter()
Definition: reader_writer.cpp:33
tue
config
tue::config::ReaderWriter config
Definition: sdf_gtest.cpp:9
yaml_emitter.h