ROSE  0.11.96.11
Yaml.h
1 // This is mini-yaml version 22d3dcf5684a11f9c0508c1ad8b3282a1d888319 subsequently modified by the ROSE team.
3 //
4 // Do not upgrade to a new version without consulting Dan Quinlan. Any new version needs to be code reviewed before being
5 // added to ROSE.
7 
8 /*
9 * MIT License
10 *
11 * Copyright(c) 2018 Jimmie Bergmann
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining a copy
14 * of this software and associated documentation files(the "Software"), to deal
15 * in the Software without restriction, including without limitation the rights
16 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 * copies of the Software, and to permit persons to whom the Software is
18 * furnished to do so, subject to the following conditions :
19 *
20 * The above copyright notice and this permission notice shall be included in all
21 * copies or substantial portions of the Software.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
26 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 * SOFTWARE.
30 *
31 */
32 
33 /*
34 YAML documentation:
35 http://yaml.org/spec/1.0/index.html
36 https://www.codeproject.com/Articles/28720/YAML-Parser-in-C
37 */
38 
39 #ifndef ROSE_Yaml_H
40 #define ROSE_Yaml_H
41 
42 #include <algorithm>
43 #include <boost/filesystem.hpp>
44 #include <boost/lexical_cast.hpp>
45 #include <exception>
46 #include <iostream>
47 #include <map>
48 #include <memory>
49 #include <rose_strtoull.h>
50 #include <sstream>
51 #include <string>
52 #include <type_traits>
53 
54 namespace Rose {
55 
57 namespace Yaml {
58 
59 class Node;
60 
62 // Helper classes and functions
64 
65 namespace impl {
66 
67 // Helper functionality, converting string to any data type. Strings are left untouched.
68 template<typename T, class Enable = void>
70  static T Get(const std::string &data) {
71  return boost::lexical_cast<T>(data);
72  }
73 
74  static T Get(const std::string &data, const T &defaultValue) {
75  T result{};
76  return boost::conversion::try_lexical_convert(data, result) ? result : defaultValue;
77  }
78 };
79 
80 // Converter from string to integral types handles hexadecimal, octal, and decimal.
81 template<typename T>
82 struct StringConverter<T, typename std::enable_if<std::is_integral<T>::value>::type> {
83  static T Get(const std::string &data) {
84  const char *s = data.c_str();
85  char *rest = nullptr;
86  static_assert(sizeof(T) <= sizeof(uint64_t), "sizeof(T) is too big for implementation");
87  if (strlen(s) != data.size() || data.empty() || isspace(data[0]))
88  throw std::runtime_error("string is not a recognized integral literal");
89  errno = 0;
90  uint64_t big = rose_strtoull(s, &rest, 0);
91  if (*rest) {
92  throw std::runtime_error("string is not a recognized integral literal");
93  } else if (ULLONG_MAX == big && ERANGE == errno) {
94  throw std::runtime_error("integral literal out of range");
95  } else {
96  return boost::numeric_cast<T>(big);
97  }
98  }
99 
100  static T Get(const std::string &data, const T &defaultValue) {
101  try {
102  return Get(data);
103  } catch (...) {
104  return defaultValue;
105  }
106  }
107 };
108 
109 template<>
110 struct StringConverter<std::string> {
111  static std::string Get(const std::string &data) {
112  return data;
113  }
114 
115  static std::string Get(const std::string &data, const std::string &defaultValue) {
116  if (data.size() == 0) {
117  return defaultValue;
118  }
119  return data;
120  }
121 };
122 
123 template<>
124 struct StringConverter<bool> {
125  static bool Get(const std::string &data) {
126  std::string tmpData = data;
127  std::transform(tmpData.begin(), tmpData.end(), tmpData.begin(), ::tolower);
128  if (tmpData == "true" || tmpData == "yes" || tmpData == "1") {
129  return true;
130  }
131 
132  return false;
133  }
134 
135  static bool Get(const std::string &data, const bool &defaultValue) {
136  if (data.size() == 0) {
137  return defaultValue;
138  }
139 
140  return Get(data);
141  }
142 };
143 
144 } // namespace
145 
147 // Exceptions
149 
151 class Exception : public std::runtime_error {
152 public:
154  enum eType {
158  };
159 
164  Exception(const std::string &message, const eType type);
165 
167  eType Type() const;
168 
170  const char* Message() const;
171 
172 private:
173  eType m_Type; // Type of exception.
174 };
175 
176 
180 class InternalException : public Exception {
181 public:
185  InternalException(const std::string &message);
186 };
187 
188 
192 class ParsingException : public Exception {
193 public:
197  ParsingException(const std::string &message);
198 };
199 
200 
205 public:
209  OperationException(const std::string &message);
210 };
211 
212 
214 class Iterator {
215 public:
216  friend class Node;
217 
219  Iterator();
220 
222  Iterator(const Iterator&);
223 
225  Iterator& operator=(const Iterator&);
226 
228  ~Iterator();
229 
233  std::pair<const std::string&, Node&> operator*();
234 
236  std::unique_ptr<std::pair<const std::string&, Node&>> operator->();
237 
241  Iterator& operator++();
242  Iterator operator++(int);
248  Iterator& operator--();
249  Iterator operator--(int);
253  bool operator==(const Iterator&);
254 
256  bool operator!=(const Iterator&);
257 
258 private:
259  enum eType {
260  None,
261  SequenceType,
262  MapType
263  };
264 
265  eType m_Type; // Type of iterator.
266  void *m_pImp; // Implementation of iterator class.
267 };
268 
269 
272 public:
273  friend class Node;
274 
276  ConstIterator();
277 
280 
283 
285  ~ConstIterator();
286 
290  std::pair<const std::string&, const Node&> operator*();
291 
293  std::unique_ptr<std::pair<const std::string&, const Node&>> operator->();
294 
310  bool operator==(const ConstIterator&);
311 
313  bool operator!=(const ConstIterator&);
314 
315 private:
316  enum eType {
317  None,
318  SequenceType,
319  MapType
320  };
321 
322  eType m_Type; // Type of iterator.
323  void *m_pImp; // Implementation of constant iterator class.
324 };
325 
326 
328 class Node {
329 public:
330  friend class Iterator;
331 
333  enum eType {
334  None,
335  SequenceType,
336  MapType,
337  ScalarType
338  };
339 
341  Node();
342 
344  Node(const Node &node);
345 
351  Node(const std::string &value);
352  Node(const char* value);
356  ~Node();
357 
361  eType type() const { return Type(); }
362  bool isNone() const { return IsNone(); }
363  bool isSequence() const { return IsSequence(); }
364  bool isMap() const { return IsMap(); }
365  bool isScalar() const { return IsScalar(); }
371  explicit operator bool() const {
372  return !isNone();
373  }
374 
378  bool operator!() const {
379  return isNone();
380  }
381 
383  void clear() { Clear(); }
384 
388  template<typename T>
389  T as() const {
390  return impl::StringConverter<T>::Get(AsString());
391  }
392 
393  template<typename T>
394  T as(const T &defaultValue) const {
395  return impl::StringConverter<T>::Get(AsString(), defaultValue);
396  }
402  size_t size() const { return Size(); }
403 
404  // Sequence operators
405 
409  Node& insert(const size_t index) { return Insert(index); }
410 
414  Node& pushFront() { return PushFront(); }
415 
419  Node& pushBack() { return PushBack(); }
420 
429  Node& operator[](const size_t index);
430  Node& operator[](const size_t index) const;
431  Node& operator[](const std::string& key);
432  Node& operator[](const std::string& key) const;
440  void erase(const size_t index) { Erase(index); }
441  void erase(const std::string& key) { Erase(key); }
447  Node& operator=(const Node& node);
448  Node& operator=(const std::string& value);
449  Node& operator=(const char* value);
455  Iterator begin() { return Begin(); }
456  ConstIterator begin() const { return Begin(); }
462  Iterator end() { return End(); }
463  ConstIterator end() const { return End(); }
466  // Original function names with unusual capitalization.
467  eType Type() const;
468  bool IsNone() const;
469  bool IsSequence() const;
470  bool IsMap() const;
471  bool IsScalar() const;
472  void Clear();
473  size_t Size() const;
474  Node& Insert(const size_t index);
475  Node& PushFront();
476  Node& PushBack();
477  void Erase(const size_t index);
478  void Erase(const std::string &key);
479  Iterator Begin();
480  ConstIterator Begin() const;
481  Iterator End();
482  ConstIterator End() const;
483 
484  template<typename T>
485  T As() const {
486  return impl::StringConverter<T>::Get(AsString());
487  }
488 
489  template<typename T>
490  T As(const T &defaultValue) const {
491  return impl::StringConverter<T>::Get(AsString(), defaultValue);
492  }
493 
494 
495 private:
496  // Get as string. If type is scalar, else empty.
497  const std::string& AsString() const;
498 
499  // Implementation of node class.
500  void *m_pImp;
501 };
502 
503 
504 // Original oddly capitalized functions
505 void Parse(Node &root, const boost::filesystem::path&);
506 void Parse(Node &root, std::iostream&);
507 void Parse(Node &root, const std::string &data);
508 void Parse(Node &root, const char *data, const size_t size);
509 
511 void parse(Node &root, const boost::filesystem::path&);
512 
514 void parse(Node &root, std::iostream&);
515 
519 void parse(Node &root, const std::string &data);
520 void parse(Node &root, const char *data);
532  SerializeConfig(const size_t spaceIndentation = 2,
533  const size_t scalarMaxLength = 64,
534  const bool sequenceMapNewline = false,
535  const bool mapScalarNewline = false);
536 
541 };
542 
543 
557 void Serialize(const Node &root, const char *filename, const SerializeConfig &config = {2, 64, false, false});
558 void Serialize(const Node &root, std::iostream &stream, const SerializeConfig &config = {2, 64, false, false});
559 void Serialize(const Node &root, std::string &string, const SerializeConfig &config = {2, 64, false, false});
562 } // namespace
563 } // namespace
564 
565 #endif
Rose::Yaml::Node::isSequence
bool isSequence() const
Functions for checking type of node.
Definition: Yaml.h:363
Rose::Yaml::ConstIterator::operator++
ConstIterator & operator++()
Increment operator.
Rose::Yaml::Node::operator[]
Node & operator[](const size_t index)
Get sequence/map item.
Rose::Yaml::Iterator::~Iterator
~Iterator()
Destructor.
Rose::Yaml::InternalException
Internal exception.
Definition: Yaml.h:180
Rose::Yaml::Iterator::Iterator
Iterator()
Default constructor.
Rose::Yaml::Node::clear
void clear()
Completely clear node.
Definition: Yaml.h:383
Rose::Yaml::SerializeConfig::ScalarMaxLength
size_t ScalarMaxLength
Maximum length of scalars.
Definition: Yaml.h:538
Rose::Yaml::Exception::OperationError
@ OperationError
User operation error.
Definition: Yaml.h:157
Rose::Yaml::Iterator::operator->
std::unique_ptr< std::pair< const std::string &, Node & > > operator->()
Dereference.
Rose::Yaml::Iterator::operator++
Iterator & operator++()
Increment operator.
Rose::Yaml::Node::size
size_t size() const
Get size of node.
Definition: Yaml.h:402
Rose::Yaml::ConstIterator::operator!=
bool operator!=(const ConstIterator &)
Check if this iterator is not equal to another iterator.
Rose::Yaml::OperationException::OperationException
OperationException(const std::string &message)
Constructor.
Rose::Yaml::ParsingException::ParsingException
ParsingException(const std::string &message)
Constructor.
Rose::Yaml::ConstIterator::operator==
bool operator==(const ConstIterator &)
Check if this iterator is equal to another iterator.
Rose::Yaml::Node::end
Iterator end()
Get end iterator.
Definition: Yaml.h:462
Rose::Yaml::Exception::Message
const char * Message() const
Get message of exception.
Rose::Yaml::InternalException::InternalException
InternalException(const std::string &message)
Constructor.
Rose::Yaml::OperationException
Operation exception.
Definition: Yaml.h:204
Rose::Yaml::Exception::eType
eType
Exception types.
Definition: Yaml.h:154
Rose::Yaml::Iterator
Iterator over YAML nodes.
Definition: Yaml.h:214
Rose::Yaml::Node
YAML node.
Definition: Yaml.h:328
Rose::Yaml::SerializeConfig::SequenceMapNewline
bool SequenceMapNewline
Put maps on a new line if parent node is a sequence.
Definition: Yaml.h:539
Rose::Yaml::Exception::InternalError
@ InternalError
Internal error.
Definition: Yaml.h:155
Rose::Yaml::Node::eType
eType
Enumeration of node types.
Definition: Yaml.h:333
Rose::Yaml::ParsingException
Parsing exception.
Definition: Yaml.h:192
Rose::Yaml::ConstIterator::operator=
ConstIterator & operator=(const ConstIterator &)
Assignment operator.
Rose::Yaml::Node::begin
Iterator begin()
Get start iterator.
Definition: Yaml.h:455
Rose::Yaml::Node::~Node
~Node()
Destructor.
Rose::Yaml::ConstIterator
Iterator over constant YAML nodes.
Definition: Yaml.h:271
Rose::Yaml::parse
void parse(Node &root, const boost::filesystem::path &)
Parse YAML from file into node.
Rose::Yaml::SerializeConfig::MapScalarNewline
bool MapScalarNewline
Put scalars on a new line if parent node is a map.
Definition: Yaml.h:540
Rose::Yaml::Node::pushFront
Node & pushFront()
Add new sequence index to back.
Definition: Yaml.h:414
Rose::Yaml::SerializeConfig::SerializeConfig
SerializeConfig(const size_t spaceIndentation=2, const size_t scalarMaxLength=64, const bool sequenceMapNewline=false, const bool mapScalarNewline=false)
Constructor.
Rose::Yaml::Node::isNone
bool isNone() const
Functions for checking type of node.
Definition: Yaml.h:362
Rose::Yaml::Node::Node
Node()
Default constructor.
Rose::Yaml::Iterator::operator==
bool operator==(const Iterator &)
Check if this iterator is equal to another iterator.
Rose::Yaml::Iterator::operator!=
bool operator!=(const Iterator &)
Check if this iterator is not equal to another iterator.
Rose::Yaml::Node::isScalar
bool isScalar() const
Functions for checking type of node.
Definition: Yaml.h:365
Rose::Yaml::Node::type
eType type() const
Functions for checking type of node.
Definition: Yaml.h:361
Rose::Yaml::Exception::Type
eType Type() const
Get type of exception.
Rose::Yaml::ConstIterator::operator--
ConstIterator & operator--()
Decrement operator.
Rose::Yaml::Node::pushBack
Node & pushBack()
Add new sequence index to front.
Definition: Yaml.h:419
Rose::Yaml::SerializeConfig
Serialization configuration structure, describing output behavior.
Definition: Yaml.h:524
Rose::Yaml::Exception::Exception
Exception(const std::string &message, const eType type)
Constructor.
Rose::Yaml::Iterator::operator=
Iterator & operator=(const Iterator &)
Assignment operator.
Rose::Yaml::Exception::ParsingError
@ ParsingError
Invalid parsing data.
Definition: Yaml.h:156
Rose
Main namespace for the ROSE library.
Definition: BinaryTutorial.dox:3
Rose::Yaml::Node::as
T as() const
Get node as given template type.
Definition: Yaml.h:389
Rose::Yaml::Node::erase
void erase(const std::string &key)
Erase item.
Definition: Yaml.h:441
Rose::Yaml::Node::isMap
bool isMap() const
Functions for checking type of node.
Definition: Yaml.h:364
Rose::Yaml::ConstIterator::operator*
std::pair< const std::string &, const Node & > operator*()
Get node of iterator.
Rose::Yaml::ConstIterator::ConstIterator
ConstIterator()
Default constructor.
Rose::Yaml::Node::begin
ConstIterator begin() const
Get start iterator.
Definition: Yaml.h:456
Rose::Yaml::impl::StringConverter
Definition: Yaml.h:69
Rose::Yaml::Node::operator=
Node & operator=(const Node &node)
Assignment operators.
Rose::Yaml::ConstIterator::operator->
std::unique_ptr< std::pair< const std::string &, const Node & > > operator->()
Dereference.
Rose::Yaml::SerializeConfig::SpaceIndentation
size_t SpaceIndentation
Number of spaces per indentation.
Definition: Yaml.h:537
Rose::Yaml::Node::end
ConstIterator end() const
Get end iterator.
Definition: Yaml.h:463
Rose::Yaml::Node::as
T as(const T &defaultValue) const
Get node as given template type.
Definition: Yaml.h:394
Rose::Yaml::Iterator::operator*
std::pair< const std::string &, Node & > operator*()
Get node of iterator.
Rose::Yaml::ConstIterator::~ConstIterator
~ConstIterator()
Destructor.
Rose::Yaml::Iterator::operator--
Iterator & operator--()
Decrement operator.
Rose::Yaml::Serialize
void Serialize(const Node &root, const char *filename, const SerializeConfig &config={2, 64, false, false})
Serialize YAML.
Rose::Yaml::Node::insert
Node & insert(const size_t index)
Insert sequence item at given index.
Definition: Yaml.h:409
Rose::Yaml::Node::operator!
bool operator!() const
Predicate to test whether node exists.
Definition: Yaml.h:378
Rose::Yaml::Exception
Base class for YAML exceptions.
Definition: Yaml.h:151
Rose::Yaml::Node::erase
void erase(const size_t index)
Erase item.
Definition: Yaml.h:440