ROSE  0.11.145.0
util/Sawyer/Yaml.h
1 // WARNING: Changes to this file must be contributed back to Sawyer or else they will
2 // be clobbered by the next update from Sawyer. The Sawyer repository is at
3 // https://github.com/matzke1/sawyer.
4 
5 
6 
7 
9 // This is mini-yaml version 22d3dcf5684a11f9c0508c1ad8b3282a1d888319 subsequently modified by the ROSE team.
10 //
11 // Do not upgrade to a new version without consulting Dan Quinlan. Any new version needs to be code reviewed before being
12 // added to ROSE.
14 
15 /*
16 * MIT License
17 *
18 * Copyright(c) 2018 Jimmie Bergmann
19 *
20 * Permission is hereby granted, free of charge, to any person obtaining a copy
21 * of this software and associated documentation files(the "Software"), to deal
22 * in the Software without restriction, including without limitation the rights
23 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24 * copies of the Software, and to permit persons to whom the Software is
25 * furnished to do so, subject to the following conditions :
26 *
27 * The above copyright notice and this permission notice shall be included in all
28 * copies or substantial portions of the Software.
29 *
30 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
33 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36 * SOFTWARE.
37 *
38 */
39 
40 /*
41 YAML documentation:
42 http://yaml.org/spec/1.0/index.html
43 https://www.codeproject.com/Articles/28720/YAML-Parser-in-C
44 */
45 #ifndef Sawyer_Yaml_H
46 #define Sawyer_Yaml_H
47 
48 #include <Sawyer/Exception.h>
49 #include <Sawyer/Parse.h>
50 
51 #include <boost/filesystem.hpp>
52 #include <boost/lexical_cast.hpp>
53 
54 #include <algorithm>
55 #include <exception>
56 #include <iostream>
57 #include <map>
58 #include <memory>
59 #include <sstream>
60 #include <string>
61 #include <type_traits>
62 
63 namespace Sawyer {
64 
66 namespace Yaml {
67 
68 class Node;
69 
71 // Helper classes and functions
73 
74 namespace impl {
75 
76 // Helper functionality, converting string to any data type. Strings are left untouched.
77 template<typename T, class Enable = void>
79  static T Get(const std::string &data) {
80  return boost::lexical_cast<T>(data);
81  }
82 
83  static T Get(const std::string &data, const T &defaultValue) {
84  T result{};
85  return boost::conversion::try_lexical_convert(data, result) ? result : defaultValue;
86  }
87 };
88 
89 // Converter from string to integral types handles hexadecimal (0x), binary (0b), and decimal.
90 template<typename T>
91 struct StringConverter<T, typename std::enable_if<std::is_integral<T>::value>::type> {
92  static T Get(const std::string &data) {
93  auto big = parse<uint64_t>(data).orThrow<Exception::RuntimeError>();
94  return boost::numeric_cast<T>(big);
95  }
96 
97  static T Get(const std::string &data, const T &defaultValue) {
98  try {
99  return Get(data);
100  } catch (...) {
101  return defaultValue;
102  }
103  }
104 };
105 
106 template<>
107 struct StringConverter<std::string> {
108  static std::string Get(const std::string &data) {
109  return data;
110  }
111 
112  static std::string Get(const std::string &data, const std::string &defaultValue) {
113  if (data.size() == 0) {
114  return defaultValue;
115  }
116  return data;
117  }
118 };
119 
120 template<>
121 struct StringConverter<bool> {
122  static bool Get(const std::string &data) {
123  std::string tmpData = data;
124  std::transform(tmpData.begin(), tmpData.end(), tmpData.begin(), ::tolower);
125  if (tmpData == "true" || tmpData == "yes" || tmpData == "1") {
126  return true;
127  }
128 
129  return false;
130  }
131 
132  static bool Get(const std::string &data, const bool &defaultValue) {
133  if (data.size() == 0) {
134  return defaultValue;
135  }
136 
137  return Get(data);
138  }
139 };
140 
141 } // namespace
142 
144 // Exceptions
146 
148 class Exception : public std::runtime_error {
149 public:
151  enum eType {
155  };
156 
161  Exception(const std::string &message, const eType type);
162 
164  eType Type() const;
165 
167  const char* Message() const;
168 
169 private:
170  eType m_Type; // Type of exception.
171 };
172 
173 
177 class InternalException : public Exception {
178 public:
182  InternalException(const std::string &message);
183 };
184 
185 
189 class ParsingException : public Exception {
190 public:
194  ParsingException(const std::string &message);
195 };
196 
197 
202 public:
206  OperationException(const std::string &message);
207 };
208 
209 
211 class Iterator {
212 public:
213  friend class Node;
214 
216  Iterator();
217 
219  Iterator(const Iterator&);
220 
222  Iterator& operator=(const Iterator&);
223 
225  ~Iterator();
226 
230  std::pair<const std::string&, Node&> operator*();
231 
233  std::unique_ptr<std::pair<const std::string&, Node&>> operator->();
234 
238  Iterator& operator++();
239  Iterator operator++(int);
245  Iterator& operator--();
246  Iterator operator--(int);
250  bool operator==(const Iterator&);
251 
253  bool operator!=(const Iterator&);
254 
255 private:
256  enum eType {
257  None,
258  SequenceType,
259  MapType
260  };
261 
262  eType m_Type; // Type of iterator.
263  void *m_pImp; // Implementation of iterator class.
264 };
265 
266 
269 public:
270  friend class Node;
271 
273  ConstIterator();
274 
277 
280 
282  ~ConstIterator();
283 
287  std::pair<const std::string&, const Node&> operator*();
288 
290  std::unique_ptr<std::pair<const std::string&, const Node&>> operator->();
291 
307  bool operator==(const ConstIterator&);
308 
310  bool operator!=(const ConstIterator&);
311 
312 private:
313  enum eType {
314  None,
315  SequenceType,
316  MapType
317  };
318 
319  eType m_Type; // Type of iterator.
320  void *m_pImp; // Implementation of constant iterator class.
321 };
322 
323 
325 class Node {
326 public:
327  friend class Iterator;
328 
330  enum eType {
331  None,
332  SequenceType,
333  MapType,
334  ScalarType
335  };
336 
338  Node();
339 
341  Node(const Node &node);
342 
348  explicit Node(const std::string &value);
349  explicit Node(const char* value);
353  ~Node();
354 
358  eType type() const { return Type(); }
359  bool isNone() const { return IsNone(); }
360  bool isSequence() const { return IsSequence(); }
361  bool isMap() const { return IsMap(); }
362  bool isScalar() const { return IsScalar(); }
368  explicit operator bool() const {
369  return !isNone();
370  }
371 
375  bool operator!() const {
376  return isNone();
377  }
378 
380  void clear() { Clear(); }
381 
385  template<typename T>
386  T as() const {
387  return impl::StringConverter<T>::Get(AsString());
388  }
389 
390  template<typename T>
391  T as(const T &defaultValue) const {
392  return impl::StringConverter<T>::Get(AsString(), defaultValue);
393  }
399  size_t size() const { return Size(); }
400 
401  // Sequence operators
402 
406  Node& insert(const size_t index) { return Insert(index); }
407 
411  Node& pushFront() { return PushFront(); }
412 
416  Node& pushBack() { return PushBack(); }
417 
426  Node& operator[](const size_t index);
427  Node& operator[](const size_t index) const;
428  Node& operator[](const std::string& key);
429  Node& operator[](const std::string& key) const;
433  bool exists(const std::string &key) const {
434  // Because of const this, the operator[] does not add the node, it only returns an empty node
435  return (*this)[key] ? true : false;
436  }
437 
443  void erase(const size_t index) { Erase(index); }
444  void erase(const std::string& key) { Erase(key); }
450  Node& operator=(const Node& node);
451  Node& operator=(const std::string& value);
452  Node& operator=(const char* value);
453 
454  template<class T>
455  Node& operator=(const T& value) {
456  (*this) = boost::lexical_cast<std::string>(value);
457  return *this;
458  }
464  Iterator begin() { return Begin(); }
465  ConstIterator begin() const { return Begin(); }
471  Iterator end() { return End(); }
472  ConstIterator end() const { return End(); }
475  // Original function names with unusual capitalization.
476  eType Type() const;
477  bool IsNone() const;
478  bool IsSequence() const;
479  bool IsMap() const;
480  bool IsScalar() const;
481  void Clear();
482  size_t Size() const;
483  Node& Insert(const size_t index);
484  Node& PushFront();
485  Node& PushBack();
486  void Erase(const size_t index);
487  void Erase(const std::string &key);
488  Iterator Begin();
489  ConstIterator Begin() const;
490  Iterator End();
491  ConstIterator End() const;
492 
493  template<typename T>
494  T As() const {
495  return impl::StringConverter<T>::Get(AsString());
496  }
497 
498  template<typename T>
499  T As(const T &defaultValue) const {
500  return impl::StringConverter<T>::Get(AsString(), defaultValue);
501  }
502 
503 
504 private:
505  // Get as string. If type is scalar, else empty.
506  const std::string& AsString() const;
507 
508  // Implementation of node class.
509  void *m_pImp;
510 };
511 
512 
513 // Original oddly capitalized functions
514 void Parse(Node &root, const boost::filesystem::path&);
515 void Parse(Node &root, std::istream&);
516 void Parse(Node &root, const std::string &data);
517 void Parse(Node &root, const char *data, const size_t size);
518 
520 Yaml::Node parse(const boost::filesystem::path&);
521 
523 Yaml::Node parse(std::istream&);
524 
527 Yaml::Node parse(const std::string&);
528 Yaml::Node parse(const char*);
540  explicit SerializeConfig(const size_t spaceIndentation = 2,
541  const size_t scalarMaxLength = std::numeric_limits<size_t>::max(),
542  const bool sequenceMapNewline = false,
543  const bool mapScalarNewline = false);
544 
546  size_t SpaceIndentation = 2;
547 
551  size_t ScalarMaxLength = std::numeric_limits<size_t>::max();
552 
554  bool SequenceMapNewline = false;
555 
557  bool MapScalarNewline = false;
558 };
559 
560 // Original names with incorrect capitalization
561 void Serialize(const Node &root, std::ostream &stream, const SerializeConfig &config = SerializeConfig());
562 
576 void serialize(const Node &root, const char *filename, const SerializeConfig &config = SerializeConfig());
577 void serialize(const Node &root, std::ostream &stream, const SerializeConfig &config = SerializeConfig());
578 void serialize(const Node &root, std::string &string, const SerializeConfig &config = SerializeConfig());
581 } // namespace
582 } // namespace
583 
584 #endif
bool SequenceMapNewline
Put maps on a new line if parent node is a sequence.
Iterator over YAML nodes.
void clear()
Completely clear node.
std::unique_ptr< std::pair< const std::string &, Node & > > operator->()
Dereference.
void serialize(const Node &root, const char *filename, const SerializeConfig &config=SerializeConfig())
Serialize YAML.
bool operator!() const
Predicate to test whether node exists.
Node & pushFront()
Add new sequence index to front.
std::pair< const std::string &, const Node & > operator*()
Get node of iterator.
size_t SpaceIndentation
Number of spaces per indentation.
bool isSequence() const
Functions for checking type of node.
STL namespace.
size_t ScalarMaxLength
Maximum length of scalars.
Iterator begin()
Get start iterator.
bool isNone() const
Functions for checking type of node.
~Node()
Destructor.
size_t size() const
Get size of node.
T as() const
Get node as given template type.
std::pair< const std::string &, Node & > operator*()
Get node of iterator.
SerializeConfig(const size_t spaceIndentation=2, const size_t scalarMaxLength=std::numeric_limits< size_t >::max(), const bool sequenceMapNewline=false, const bool mapScalarNewline=false)
Constructor.
Exception(const std::string &message, const eType type)
Constructor.
void erase(const size_t index)
Erase item.
bool operator!=(const Iterator &)
Check if this iterator is not equal to another iterator.
bool isMap() const
Functions for checking type of node.
Name space for the entire library.
Definition: FeasiblePath.h:767
ConstIterator & operator=(const ConstIterator &)
Assignment operator.
eType
Enumeration of node types.
bool operator!=(const ConstIterator &)
Check if this iterator is not equal to another iterator.
eType type() const
Functions for checking type of node.
Yaml::Node parse(const boost::filesystem::path &)
Parse YAML from file.
Node & insert(const size_t index)
Insert sequence item at given index.
Iterator()
Default constructor.
Base class for YAML exceptions.
eType Type() const
Get type of exception.
Node & pushBack()
Add new sequence index to back.
const char * Message() const
Get message of exception.
ConstIterator()
Default constructor.
ConstIterator begin() const
Get start iterator.
Node()
Default constructor.
Iterator end()
Get end iterator.
bool operator==(const Iterator &)
Check if this iterator is equal to another iterator.
bool exists(const std::string &key) const
Test whether a map item exists without inserting it.
InternalException(const std::string &message)
Constructor.
Iterator & operator=(const Iterator &)
Assignment operator.
OperationException(const std::string &message)
Constructor.
bool operator==(const ConstIterator &)
Check if this iterator is equal to another iterator.
Node & operator=(const Node &node)
Assignment operators.
Iterator & operator--()
Decrement operator.
Node & operator[](const size_t index)
Get sequence/map item.
T as(const T &defaultValue) const
Get node as given template type.
Node & operator=(const T &value)
Assignment operators.
~Iterator()
Destructor.
ConstIterator & operator--()
Decrement operator.
Iterator over constant YAML nodes.
Serialization configuration structure, describing output behavior.
ConstIterator end() const
Get end iterator.
std::unique_ptr< std::pair< const std::string &, const Node & > > operator->()
Dereference.
void erase(const std::string &key)
Erase item.
bool isScalar() const
Functions for checking type of node.
Iterator & operator++()
Increment operator.
bool MapScalarNewline
Put scalars on a new line if parent node is a map.
ConstIterator & operator++()
Increment operator.
ParsingException(const std::string &message)
Constructor.