/** * Digital Voice Modem - Host Software * GPLv2 Open Source. Use is subject to license terms. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * @package DVM / Host Software * */ // // Based on code from the mini-yaml project. (https://github.com/jimmiebergmann/mini-yaml) // Licensed under the MIT License (https://opensource.org/licenses/MIT) // /* * Copyright(c) 2018 Jimmie Bergmann * Copyright (C) 2020 Bryan Biedenkapp N2PLL * * MIT License * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files(the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions : * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * */ /* * YAML documentation: * http://yaml.org/spec/1.0/index.html * https://www.codeproject.com/Articles/28720/YAML-Parser-in-C */ #if !defined(__YAML_H__) #define __YAML_H__ #include "Defines.h" #include #include #include #include #include #include namespace yaml { // --------------------------------------------------------------------------- // Class Prototypes // --------------------------------------------------------------------------- class HOST_SW_API Node; // --------------------------------------------------------------------------- // Helper classes and functions // --------------------------------------------------------------------------- namespace impl { // --------------------------------------------------------------------------- // Class Declaration // Helper functionality, converting string to any data type. // Strings are left untouched. // --------------------------------------------------------------------------- template struct StringConverter { /// /// /// static T get(const std::string& data) { T type; std::stringstream ss(data); ss >> type; return type; } /// /// /// /// static T get(const std::string& data, const T& defaultValue) { T type; std::stringstream ss(data); ss >> type; if (ss.fail()) { return defaultValue; } return type; } }; // --------------------------------------------------------------------------- // Class Declaration // // --------------------------------------------------------------------------- template<> struct StringConverter { /// /// /// static std::string get(const std::string& data) { return data; } /// /// /// /// static std::string get(const std::string& data, const std::string& defaultValue) { if (data.size() == 0) { return defaultValue; } return data; } }; // --------------------------------------------------------------------------- // Class Declaration // // --------------------------------------------------------------------------- template<> struct StringConverter { /// /// /// static bool get(const std::string& data) { std::string tmpData = data; std::transform(tmpData.begin(), tmpData.end(), tmpData.begin(), ::tolower); if (tmpData == "true" || tmpData == "yes" || tmpData == "1") { return true; } return false; } /// /// /// /// static bool get(const std::string& data, const bool& defaultValue) { if (data.size() == 0) { return defaultValue; } return get(data); } }; } // namespace impl // --------------------------------------------------------------------------- // Class Declaration // Exception class. // --------------------------------------------------------------------------- class HOST_SW_API Exception : public std::runtime_error { public: /// /// Enumeration of exception types. /// enum eType { InternalError, // Internal error. ParsingError, // Invalid parsing data. OperationError // User operation error. }; /// Initializes a new instance of the Exception class. Exception(const std::string & message, const eType type); /// Get type of exception. eType type() const; /// Get message of exception. const char* message() const; private: eType m_Type; }; // --------------------------------------------------------------------------- // Class Declaration // Internal exception class. // --------------------------------------------------------------------------- class HOST_SW_API InternalException : public Exception { public: /// Initializes a new instance of the InternalException class. InternalException(const std::string& message); }; // --------------------------------------------------------------------------- // Class Declaration // Parsing exception class. // --------------------------------------------------------------------------- class HOST_SW_API ParsingException : public Exception { public: /// Initializes a new instance of the ParsingException class. ParsingException(const std::string & message); }; // --------------------------------------------------------------------------- // Class Declaration // Parsing exception class. // --------------------------------------------------------------------------- class HOST_SW_API OperationException : public Exception { public: /// Initializes a new instance of the OperationException class. OperationException(const std::string & message); }; // --------------------------------------------------------------------------- // Class Declaration // Iterator class. // --------------------------------------------------------------------------- class HOST_SW_API Iterator { public: friend class Node; /// Initializes a new instance of the Iterator class. Iterator(); /// Copies an instance of the Iterator class to a new instance of the Iterator class. Iterator(const Iterator & it); /// Finalizes a instance of the Iterator class. ~Iterator(); /// Assignment operator. Iterator& operator = (const Iterator& it); /// Get node of iterator. First pair item is the key of map value, empty if type is sequence. std::pair operator *(); /// Post-increment operator. Iterator& operator ++ (int); /// Post-decrement operator. Iterator& operator -- (int); /// Check if iterator is equal to other iterator. bool operator == (const Iterator& it); /// Check if iterator is not equal to other iterator. bool operator != (const Iterator& it); private: enum eType { None, SequenceType, MapType }; eType m_Type; void* m_pImp; }; // --------------------------------------------------------------------------- // Class Declaration // Constant iterator class. // --------------------------------------------------------------------------- class HOST_SW_API ConstIterator { public: friend class Node; /// Initializes a new instance of the ConstIterator class. ConstIterator(); /// Copies an instance of the ConstIterator class to a new instance of the ConstIterator class. ConstIterator(const ConstIterator & it); /// Finalizes a instance of the ConstIterator class. ~ConstIterator(); /// Assignment operator. ConstIterator& operator = (const ConstIterator& it); /// Get node of iterator. First pair item is the key of map value, empty if type is sequence. std::pair operator *(); /// Post-increment operator. ConstIterator& operator ++ (int); /// Post-decrement operator. ConstIterator& operator -- (int); /// Check if iterator is equal to other iterator. bool operator == (const ConstIterator& it); /// Check if iterator is not equal to other iterator. bool operator != (const ConstIterator& it); private: enum eType { None, SequenceType, MapType }; eType m_Type; void* m_pImp; }; // --------------------------------------------------------------------------- // Class Declaration // Node class. // --------------------------------------------------------------------------- class HOST_SW_API Node { public: friend class Iterator; /// Enumeration of node types. enum eType { None, SequenceType, MapType, ScalarType }; /// Initializes a new instance of the Node class. Node(); /// Copies an instance of the Node class to a new instance of the Node class. Node(const Node& node); /// Initializes a new instance of the Node class. Node(const std::string& value); /// Initializes a new instance of the Node class. Node(const char* value); /// Finalizes a instance of the Node class. ~Node(); /// Gets the type of node. eType type() const; /// Checks if the node contains nothing. bool isNone() const; /// Checks if the node is a sequence node. bool isSequence() const; /// Checks if the node is a map node. bool isMap() const; /// Checks if the node is a scalar node. bool isScalar() const; /// Completely clear node. void clear(); /// Get node as given template type. template T as() const { return impl::StringConverter::get(asString()); } /// Get node as given template type with a default value if no value is found. template T as(const T& defaultValue) const { return impl::StringConverter::get(asString(), defaultValue); } /// Get size of node. Nodes of type None or Scalar will return 0. size_t size() const; // Sequence operators /// Insert sequence item at given index. Converts node to sequence type if needed. /// Adding new item to end of sequence if index is larger than sequence size. Node& insert(const size_t index); /// Add new sequence index to back. Converts node to sequence type if needed. Node& push_front(); /// Add new sequence index to front. Converts node to sequence type if needed. Node& push_back(); /// Get sequence/map item. Converts node to sequence/map type if needed. Node& operator [] (const size_t index); /// Get sequence/map item. Converts node to sequence/map type if needed. Node& operator [] (const std::string& key); /// Erase item. No action if node is not a sequence or map. void erase(const size_t index); /// Erase item. No action if node is not a sequence or map. void erase(const std::string& key); /// Assignment operator. Node& operator = (const Node& node); /// Assignment operator. Node& operator = (const std::string& value); /// Assignment operator. Node& operator = (const char* value); /// Get start iterator. Iterator begin(); /// Get start constant iterator. ConstIterator begin() const; /// Get end iterator. Iterator end(); /// Get end constant iterator. ConstIterator end() const; private: const std::string& asString() const; void* m_pImp; }; /// Populate given root node with deserialized data. /// Root node to populate. /// Path of input file. bool Parse(Node& root, const char* filename); /// Populate given root node with deserialized data. /// Root node to populate. /// Input stream. bool Parse(Node& root, std::iostream& stream); /// Populate given root node with deserialized data. /// Root node to populate. /// String of input data. bool Parse(Node& root, const std::string& string); /// Populate given root node with deserialized data. /// Character array of input data. /// Buffer size. bool Parse(Node& root, const char* buffer, const size_t size); // --------------------------------------------------------------------------- // Structure Declaration // Serialization configuration structure, describing output behavior. // --------------------------------------------------------------------------- struct SerializeConfig { /// Initializes a new instance of the SerializeConfig struct. /// Number of spaces per indentation. /// Maximum length of scalars. Serialized as folder scalars if exceeded. Ignored if equal to 0. /// Put maps on a new line if parent node is a sequence. /// Put scalars on a new line if parent node is a map. SerializeConfig(const size_t spaceIndentation = 2, const size_t scalarMaxLength = 64, const bool sequenceMapNewline = false, const bool mapScalarNewline = false); size_t SpaceIndentation; // Number of spaces per indentation. size_t ScalarMaxLength; // Maximum length of scalars. Serialized as folder scalars if exceeded. 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. }; /// Serialize node data. /// Root node to serialize. /// Path of output file. /// Serialization configuration. void Serialize(const Node& root, const char* filename, const SerializeConfig& config = {2, 64, false, false}); /// Serialize node data. /// Root node to serialize. /// Output stream. /// Serialization configuration. void Serialize(const Node& root, std::iostream& stream, const SerializeConfig& config = {2, 64, false, false}); /// Serialize node data. /// Root node to serialize. /// String of output data. /// Serialization configuration. void Serialize(const Node& root, std::string& string, const SerializeConfig& config = {2, 64, false, false}); } // namespace yaml #endif // __YAML_H__