ROSE 0.11.145.134
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://gitlab.com/charger7534/sawyer.git.
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/*
41YAML documentation:
42http://yaml.org/spec/1.0/index.html
43https://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
63namespace Sawyer {
64
66namespace Yaml {
67
68class Node;
69
71// Helper classes and functions
73
74namespace impl {
75
76// Helper functionality, converting string to any data type. Strings are left untouched.
77template<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.
90template<typename T>
91struct 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
106template<>
107struct 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
120template<>
121struct 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
148class Exception : public std::runtime_error {
149public:
156
161 Exception(const std::string &message, const eType type);
162
164 eType Type() const;
165
167 const char* Message() const;
168
169private:
170 eType m_Type; // Type of exception.
171};
172
173
178public:
182 InternalException(const std::string &message);
183};
184
185
190public:
194 ParsingException(const std::string &message);
195};
196
197
202public:
206 OperationException(const std::string &message);
207};
208
209
211class Iterator {
212public:
213 friend class Node;
214
217
220
223
226
230 std::pair<const std::string&, Node&> operator*();
231
233 std::unique_ptr<std::pair<const std::string&, Node&>> operator->();
234
250 bool operator==(const Iterator&);
251
253 bool operator!=(const Iterator&);
254
255private:
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
269public:
270 friend class Node;
271
274
277
280
283
287 std::pair<const std::string&, const Node&> operator*();
288
290 std::unique_ptr<std::pair<const std::string&, const Node&>> operator->();
291
308
311
312private:
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
325class Node {
326public:
327 friend class Iterator;
328
330 enum eType {
331 None,
332 SequenceType,
333 MapType,
334 ScalarType
335 };
336
339
341 Node(const Node &node);
342
348 explicit Node(const std::string &value);
349 explicit Node(const char* value);
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
504private:
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
514void Parse(Node &root, const boost::filesystem::path&);
515void Parse(Node &root, std::istream&);
516void Parse(Node &root, const std::string &data);
517void Parse(Node &root, const char *data, const size_t size);
518
520Yaml::Node parse(const boost::filesystem::path&);
521
523Yaml::Node parse(std::istream&);
524
527Yaml::Node parse(const std::string&);
528Yaml::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
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
561void Serialize(const Node &root, std::ostream &stream, const SerializeConfig &config = SerializeConfig());
562
576void serialize(const Node &root, const char *filename, const SerializeConfig &config = SerializeConfig());
577void serialize(const Node &root, std::ostream &stream, const SerializeConfig &config = SerializeConfig());
578void serialize(const Node &root, std::string &string, const SerializeConfig &config = SerializeConfig());
581} // namespace
582} // namespace
583
584#endif
Base class for Sawyer runtime errors.
Iterator over constant YAML nodes.
ConstIterator & operator++()
Increment operator.
ConstIterator operator++(int)
Increment operator.
bool operator!=(const ConstIterator &)
Check if this iterator is not equal to another iterator.
bool operator==(const ConstIterator &)
Check if this iterator is equal to another iterator.
ConstIterator & operator=(const ConstIterator &)
Assignment operator.
ConstIterator operator--(int)
Decrement operator.
std::pair< const std::string &, const Node & > operator*()
Get node of iterator.
ConstIterator & operator--()
Decrement operator.
ConstIterator()
Default constructor.
ConstIterator(const ConstIterator &)
Copy constructor.
std::unique_ptr< std::pair< const std::string &, const Node & > > operator->()
Dereference.
Base class for YAML exceptions.
Exception(const std::string &message, const eType type)
Constructor.
const char * Message() const
Get message of exception.
eType Type() const
Get type of exception.
eType
Exception types.
@ ParsingError
Invalid parsing data.
@ OperationError
User operation error.
@ InternalError
Internal error.
InternalException(const std::string &message)
Constructor.
Iterator over YAML nodes.
Iterator & operator--()
Decrement operator.
std::pair< const std::string &, Node & > operator*()
Get node of iterator.
Iterator operator--(int)
Decrement operator.
std::unique_ptr< std::pair< const std::string &, Node & > > operator->()
Dereference.
bool operator==(const Iterator &)
Check if this iterator is equal to another iterator.
~Iterator()
Destructor.
bool operator!=(const Iterator &)
Check if this iterator is not equal to another iterator.
Iterator()
Default constructor.
Iterator & operator=(const Iterator &)
Assignment operator.
Iterator & operator++()
Increment operator.
Iterator operator++(int)
Increment operator.
Iterator(const Iterator &)
Copy constructor.
T as() const
Get node as given template type.
Node & operator[](const size_t index)
Get sequence/map item.
Node(const std::string &value)
Assignment constructors.
bool isMap() const
Functions for checking type of node.
Node & operator=(const char *value)
Assignment operators.
Node & insert(const size_t index)
Insert sequence item at given index.
bool exists(const std::string &key) const
Test whether a map item exists without inserting it.
Node & operator=(const std::string &value)
Assignment operators.
Iterator begin()
Get start iterator.
bool isScalar() const
Functions for checking type of node.
Node & pushBack()
Add new sequence index to back.
size_t size() const
Get size of node.
Node & operator[](const size_t index) const
Get sequence/map item.
bool operator!() const
Predicate to test whether node exists.
void clear()
Completely clear node.
eType type() const
Functions for checking type of node.
Node(const Node &node)
Copy constructor.
Iterator end()
Get end iterator.
T as(const T &defaultValue) const
Get node as given template type.
Node & operator=(const T &value)
Assignment operators.
ConstIterator begin() const
Get start iterator.
Node()
Default constructor.
~Node()
Destructor.
bool isNone() const
Functions for checking type of node.
Node & pushFront()
Add new sequence index to front.
bool isSequence() const
Functions for checking type of node.
Node & operator[](const std::string &key)
Get sequence/map item.
void erase(const std::string &key)
Erase item.
Node & operator[](const std::string &key) const
Get sequence/map item.
Node(const char *value)
Assignment constructors.
eType
Enumeration of node types.
ConstIterator end() const
Get end iterator.
void erase(const size_t index)
Erase item.
Node & operator=(const Node &node)
Assignment operators.
OperationException(const std::string &message)
Constructor.
ParsingException(const std::string &message)
Constructor.
Sawyer support library.
Serialization configuration structure, describing output behavior.
size_t SpaceIndentation
Number of spaces per indentation.
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.
bool SequenceMapNewline
Put maps on a new line if parent node is a sequence.
bool MapScalarNewline
Put scalars on a new line if parent node is a map.
size_t ScalarMaxLength
Maximum length of scalars.