From 557102972663c53aa79a319e89cfe2c939b7d6bc Mon Sep 17 00:00:00 2001 From: beder Date: Sat, 19 May 2012 15:34:02 -0500 Subject: [PATCH 01/43] Copied all files from new-api branch of old repo --- include/yaml-cpp/exceptions.h | 91 ++ include/yaml-cpp/node/convert.h | 209 +++ include/yaml-cpp/node/detail/bool_type.h | 26 + include/yaml-cpp/node/detail/impl.h | 142 ++ include/yaml-cpp/node/detail/iterator.h | 64 + include/yaml-cpp/node/detail/iterator_fwd.h | 27 + include/yaml-cpp/node/detail/memory.h | 39 + include/yaml-cpp/node/detail/node.h | 126 ++ include/yaml-cpp/node/detail/node_data.h | 105 ++ include/yaml-cpp/node/detail/node_iterator.h | 139 ++ include/yaml-cpp/node/detail/node_ref.h | 65 + include/yaml-cpp/node/emit.h | 23 + include/yaml-cpp/node/impl.h | 355 +++++ include/yaml-cpp/node/iterator.h | 28 + include/yaml-cpp/node/node.h | 113 ++ include/yaml-cpp/node/parse.h | 28 + include/yaml-cpp/node/ptr.h | 29 + include/yaml-cpp/node/type.h | 14 + include/yaml-cpp/parser.h | 4 +- include/yaml-cpp/yaml.h | 8 + src/convert.cpp | 83 ++ src/emit.cpp | 30 + src/memory.cpp | 29 + src/node_data.cpp | 295 ++++ src/nodebuilder.cpp | 138 ++ src/nodebuilder.h | 58 + src/nodeevents.cpp | 99 ++ src/nodeevents.h | 57 + src/parse.cpp | 64 + src/singledocparser.cpp | 5 +- test/CMakeLists.txt | 4 +- test/emittertests.cpp | 21 +- test/new-api/nodetests.cpp | 433 ++++++ test/new-api/parsertests.cpp | 8 + test/new-api/spectests.cpp | 1365 ++++++++++++++++++ test/nodetests.h | 13 + test/parsertests.h | 13 + test/tests.cpp | 10 +- 38 files changed, 4333 insertions(+), 27 deletions(-) create mode 100644 include/yaml-cpp/node/convert.h create mode 100644 include/yaml-cpp/node/detail/bool_type.h create mode 100644 include/yaml-cpp/node/detail/impl.h create mode 100644 include/yaml-cpp/node/detail/iterator.h create mode 100644 include/yaml-cpp/node/detail/iterator_fwd.h create mode 100644 include/yaml-cpp/node/detail/memory.h create mode 100644 include/yaml-cpp/node/detail/node.h create mode 100644 include/yaml-cpp/node/detail/node_data.h create mode 100644 include/yaml-cpp/node/detail/node_iterator.h create mode 100644 include/yaml-cpp/node/detail/node_ref.h create mode 100644 include/yaml-cpp/node/emit.h create mode 100644 include/yaml-cpp/node/impl.h create mode 100644 include/yaml-cpp/node/iterator.h create mode 100644 include/yaml-cpp/node/node.h create mode 100644 include/yaml-cpp/node/parse.h create mode 100644 include/yaml-cpp/node/ptr.h create mode 100644 include/yaml-cpp/node/type.h create mode 100644 src/convert.cpp create mode 100644 src/emit.cpp create mode 100644 src/memory.cpp create mode 100644 src/node_data.cpp create mode 100644 src/nodebuilder.cpp create mode 100644 src/nodebuilder.h create mode 100644 src/nodeevents.cpp create mode 100644 src/nodeevents.h create mode 100644 src/parse.cpp create mode 100644 test/new-api/nodetests.cpp create mode 100644 test/new-api/parsertests.cpp create mode 100644 test/new-api/spectests.cpp create mode 100644 test/nodetests.h create mode 100644 test/parsertests.h diff --git a/include/yaml-cpp/exceptions.h b/include/yaml-cpp/exceptions.h index 9e19637..04babd7 100644 --- a/include/yaml-cpp/exceptions.h +++ b/include/yaml-cpp/exceptions.h @@ -55,6 +55,13 @@ namespace YAML const char * const AMBIGUOUS_ANCHOR = "cannot assign the same alias to multiple nodes"; const char * const UNKNOWN_ANCHOR = "the referenced anchor is not defined"; + const char * const INVALID_SCALAR = "invalid scalar"; + const char * const KEY_NOT_FOUND = "key not found"; + const char * const BAD_CONVERSION = "bad conversion"; + const char * const BAD_DEREFERENCE = "bad dereference"; + const char * const BAD_SUBSCRIPT = "operator[] call on a scalar"; + const char * const BAD_PUSHBACK = "appending to a non-sequence"; + const char * const UNMATCHED_GROUP_TAG = "unmatched group tag"; const char * const UNEXPECTED_END_SEQ = "unexpected end sequence token"; const char * const UNEXPECTED_END_MAP = "unexpected end map token"; @@ -66,6 +73,24 @@ namespace YAML const char * const EXPECTED_VALUE_TOKEN = "expected value token"; const char * const UNEXPECTED_KEY_TOKEN = "unexpected key token"; const char * const UNEXPECTED_VALUE_TOKEN = "unexpected value token"; + + template + inline const std::string KEY_NOT_FOUND_WITH_KEY(const T&, typename disable_if >::type * = 0) { + return KEY_NOT_FOUND; + } + + inline const std::string KEY_NOT_FOUND_WITH_KEY(const std::string& key) { + std::stringstream stream; + stream << KEY_NOT_FOUND << ": " << key; + return stream.str(); + } + + template + inline const std::string KEY_NOT_FOUND_WITH_KEY(const T& key, typename enable_if >::type * = 0) { + std::stringstream stream; + stream << KEY_NOT_FOUND << ": " << key; + return stream.str(); + } } class Exception: public std::runtime_error { @@ -91,6 +116,72 @@ namespace YAML : Exception(mark_, msg_) {} }; + class RepresentationException: public Exception { + public: + RepresentationException(const Mark& mark_, const std::string& msg_) + : Exception(mark_, msg_) {} + }; + + // representation exceptions + class InvalidScalar: public RepresentationException { + public: + InvalidScalar(const Mark& mark_) + : RepresentationException(mark_, ErrorMsg::INVALID_SCALAR) {} + }; + + class KeyNotFound: public RepresentationException { + public: + template + KeyNotFound(const Mark& mark_, const T& key_) + : RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) {} + }; + + template + class TypedKeyNotFound: public KeyNotFound { + public: + TypedKeyNotFound(const Mark& mark_, const T& key_) + : KeyNotFound(mark_, key_), key(key_) {} + virtual ~TypedKeyNotFound() throw() {} + + T key; + }; + + template + inline TypedKeyNotFound MakeTypedKeyNotFound(const Mark& mark, const T& key) { + return TypedKeyNotFound (mark, key); + } + + class BadConversion: public RepresentationException { + public: + BadConversion() + : RepresentationException(Mark::null(), ErrorMsg::BAD_CONVERSION) {} + }; + + template + class TypedBadConversion: public BadConversion { + public: + TypedBadConversion() + : BadConversion() {} + }; + + class BadDereference: public RepresentationException { + public: + BadDereference() + : RepresentationException(Mark::null(), ErrorMsg::BAD_DEREFERENCE) {} + }; + + class BadSubscript: public RepresentationException { + public: + BadSubscript() + : RepresentationException(Mark::null(), ErrorMsg::BAD_SUBSCRIPT) {} + }; + + class BadPushback: public RepresentationException { + public: + BadPushback() + : RepresentationException(Mark::null(), ErrorMsg::BAD_PUSHBACK) {} + }; + class EmitterException: public Exception { public: EmitterException(const std::string& msg_) diff --git a/include/yaml-cpp/node/convert.h b/include/yaml-cpp/node/convert.h new file mode 100644 index 0000000..f78332a --- /dev/null +++ b/include/yaml-cpp/node/convert.h @@ -0,0 +1,209 @@ +#ifndef NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + + +#include "yaml-cpp/binary.h" +#include "yaml-cpp/node/node.h" +#include "yaml-cpp/node/iterator.h" +#include "yaml-cpp/null.h" +#include +#include +#include +#include +#include + +namespace YAML +{ + namespace conversion { + inline bool IsInfinity(const std::string& input) { + return input == ".inf" || input == ".Inf" || input == ".INF" || input == "+.inf" || input == "+.Inf" || input == "+.INF"; + } + + inline bool IsNegativeInfinity(const std::string& input) { + return input == "-.inf" || input == "-.Inf" || input == "-.INF"; + } + + inline bool IsNaN(const std::string& input) { + return input == ".nan" || input == ".NaN" || input == ".NAN"; + } + } + + // std::string + template<> + struct convert { + static Node encode(const std::string& rhs) { + return Node(rhs); + } + + static bool decode(const Node& node, std::string& rhs) { + if(!node.IsScalar()) + return false; + rhs = node.Scalar(); + return true; + } + }; + + template<> + struct convert<_Null> { + static Node encode(const _Null& /* rhs */) { + return Node(); + } + + static bool decode(const Node& node, _Null& /* rhs */) { + return node.IsNull(); + } + }; + +#define YAML_DEFINE_CONVERT_STREAMABLE(type)\ + template<>\ + struct convert {\ + static Node encode(const type& rhs) {\ + std::stringstream stream;\ + stream << rhs;\ + return Node(stream.str());\ + }\ + \ + static bool decode(const Node& node, type& rhs) {\ + if(node.Type() != NodeType::Scalar)\ + return false;\ + const std::string& input = node.Scalar();\ + std::stringstream stream(input);\ + stream.unsetf(std::ios::dec);\ + if((stream >> rhs) && (stream >> std::ws).eof())\ + return true;\ + if(std::numeric_limits::has_infinity) {\ + if(conversion::IsInfinity(input)) {\ + rhs = std::numeric_limits::infinity();\ + return true;\ + } else if(conversion::IsNegativeInfinity(input)) {\ + rhs = -std::numeric_limits::infinity();\ + return true;\ + }\ + }\ + \ + if(std::numeric_limits::has_quiet_NaN && conversion::IsNaN(input)) {\ + rhs = std::numeric_limits::quiet_NaN();\ + return true;\ + }\ + \ + return false;\ + }\ + } + + YAML_DEFINE_CONVERT_STREAMABLE(int); + YAML_DEFINE_CONVERT_STREAMABLE(unsigned); + YAML_DEFINE_CONVERT_STREAMABLE(short); + YAML_DEFINE_CONVERT_STREAMABLE(unsigned short); + YAML_DEFINE_CONVERT_STREAMABLE(long); + YAML_DEFINE_CONVERT_STREAMABLE(unsigned long); + YAML_DEFINE_CONVERT_STREAMABLE(long long); + YAML_DEFINE_CONVERT_STREAMABLE(unsigned long long); + + YAML_DEFINE_CONVERT_STREAMABLE(char); + YAML_DEFINE_CONVERT_STREAMABLE(unsigned char); + + YAML_DEFINE_CONVERT_STREAMABLE(float); + YAML_DEFINE_CONVERT_STREAMABLE(double); + YAML_DEFINE_CONVERT_STREAMABLE(long double); + +#undef YAML_DEFINE_CONVERT_STREAMABLE + + // bool + template<> + struct convert { + static Node encode(bool rhs) { + return rhs ? Node("true") : Node("false"); + } + + static bool decode(const Node& node, bool& rhs); + }; + + // std::map + template + struct convert > { + static Node encode(const std::map& rhs) { + Node node(NodeType::Map); + for(typename std::map::const_iterator it=rhs.begin();it!=rhs.end();++it) + node[it->first] = it->second; + return node; + } + + static bool decode(const Node& node, std::map& rhs) { + if(!node.IsMap()) + return false; + + rhs.clear(); + for(const_iterator it=node.begin();it!=node.end();++it) + rhs[it->first.as()] = it->second.as(); + return true; + } + }; + + // std::vector + template + struct convert > { + static Node encode(const std::vector& rhs) { + Node node(NodeType::Sequence); + for(typename std::vector::const_iterator it=rhs.begin();it!=rhs.end();++it) + node.push_back(*it); + return node; + } + + static bool decode(const Node& node, std::vector& rhs) { + if(!node.IsSequence()) + return false; + + rhs.clear(); + for(const_iterator it=node.begin();it!=node.end();++it) + rhs.push_back(it->as()); + return true; + } + }; + + // std::list + template + struct convert > { + static Node encode(const std::list& rhs) { + Node node(NodeType::Sequence); + for(typename std::list::const_iterator it=rhs.begin();it!=rhs.end();++it) + node.push_back(*it); + return node; + } + + static bool decode(const Node& node, std::list& rhs) { + if(!node.IsSequence()) + return false; + + rhs.clear(); + for(const_iterator it=node.begin();it!=node.end();++it) + rhs.push_back(it->as()); + return true; + } + }; + + // binary + template<> + struct convert { + static Node encode(const Binary& rhs) { + return Node(EncodeBase64(rhs.data(), rhs.size())); + } + + static bool decode(const Node& node, Binary& rhs) { + if(!node.IsScalar()) + return false; + + std::vector data = DecodeBase64(node.Scalar()); + if(data.empty() && !node.Scalar().empty()) + return false; + + rhs.swap(data); + return true; + } + }; +} + +#endif // NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/detail/bool_type.h b/include/yaml-cpp/node/detail/bool_type.h new file mode 100644 index 0000000..80ed9a4 --- /dev/null +++ b/include/yaml-cpp/node/detail/bool_type.h @@ -0,0 +1,26 @@ +#ifndef NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +namespace YAML +{ + namespace detail + { + struct unspecified_bool { + struct NOT_ALLOWED; + static void true_value(NOT_ALLOWED*) {} + }; + typedef void (*unspecified_bool_type)(unspecified_bool::NOT_ALLOWED*); + } +} + +#define YAML_CPP_OPERATOR_BOOL()\ +operator YAML::detail::unspecified_bool_type() const\ +{\ + return this->operator!() ? 0 : &YAML::detail::unspecified_bool::true_value;\ +} + +#endif // NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/detail/impl.h b/include/yaml-cpp/node/detail/impl.h new file mode 100644 index 0000000..e3d17af --- /dev/null +++ b/include/yaml-cpp/node/detail/impl.h @@ -0,0 +1,142 @@ +#ifndef NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + + +#include "yaml-cpp/node/detail/node.h" +#include "yaml-cpp/node/detail/node_data.h" +#include + +namespace YAML +{ + namespace detail + { + template + struct get_idx { + static node *get(const std::vector& /* sequence */, const Key& /* key */, shared_memory_holder /* pMemory */) { + return 0; + } + }; + + template + struct get_idx >::type> { + static node *get(const std::vector& sequence, const Key& key, shared_memory_holder /* pMemory */) { + return key < sequence.size() ? sequence[key] : 0; + } + + static node *get(std::vector& sequence, const Key& key, shared_memory_holder pMemory) { + if(key > sequence.size()) + return 0; + if(key == sequence.size()) + sequence.push_back(&pMemory->create_node()); + return sequence[key]; + } + }; + + template + struct get_idx >::type> { + static node *get(const std::vector& sequence, const Key& key, shared_memory_holder pMemory) { + return key >= 0 ? get_idx::get(sequence, static_cast(key), pMemory) : 0; + } + static node *get(std::vector& sequence, const Key& key, shared_memory_holder pMemory) { + return key >= 0 ? get_idx::get(sequence, static_cast(key), pMemory) : 0; + } + }; + + // indexing + template + inline node& node_data::get(const Key& key, shared_memory_holder pMemory) const + { + switch(m_type) { + case NodeType::Map: + break; + case NodeType::Undefined: + case NodeType::Null: + return pMemory->create_node(); + case NodeType::Sequence: + if(node *pNode = get_idx::get(m_sequence, key, pMemory)) + return *pNode; + return pMemory->create_node(); + case NodeType::Scalar: + throw BadSubscript(); + } + + for(node_map::const_iterator it=m_map.begin();it!=m_map.end();++it) { + if(equals(*it->first, key, pMemory)) + return *it->second; + } + + return pMemory->create_node(); + } + + template + inline node& node_data::get(const Key& key, shared_memory_holder pMemory) + { + switch(m_type) { + case NodeType::Map: + break; + case NodeType::Undefined: + case NodeType::Null: + case NodeType::Sequence: + if(node *pNode = get_idx::get(m_sequence, key, pMemory)) { + m_type = NodeType::Sequence; + return *pNode; + } + + convert_to_map(pMemory); + break; + case NodeType::Scalar: + throw BadSubscript(); + } + + for(node_map::const_iterator it=m_map.begin();it!=m_map.end();++it) { + if(equals(*it->first, key, pMemory)) + return *it->second; + } + + node& k = convert_to_node(key, pMemory); + node& v = pMemory->create_node(); + insert_map_pair(k, v); + return v; + } + + template + inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) + { + if(m_type != NodeType::Map) + return false; + + for(node_map::iterator it=m_map.begin();it!=m_map.end();++it) { + if(equals(*it->first, key, pMemory)) { + m_map.erase(it); + return true; + } + } + + return false; + } + + template + inline bool node_data::equals(node& node, const T& rhs, shared_memory_holder pMemory) + { + T lhs; + if(convert::decode(Node(node, pMemory), lhs)) + return lhs == rhs; + return false; + } + + template + inline node& node_data::convert_to_node(const T& rhs, shared_memory_holder pMemory) + { + Node value = convert::encode(rhs); + value.EnsureNodeExists(); + pMemory->merge(*value.m_pMemory); + return *value.m_pNode; + } + } +} + +#endif // NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/detail/iterator.h b/include/yaml-cpp/node/detail/iterator.h new file mode 100644 index 0000000..dc699f4 --- /dev/null +++ b/include/yaml-cpp/node/detail/iterator.h @@ -0,0 +1,64 @@ +#ifndef VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + + +#include "yaml-cpp/dll.h" +#include "yaml-cpp/node/ptr.h" +#include "yaml-cpp/node/detail/node_iterator.h" +#include +#include + +namespace YAML +{ + namespace detail + { + struct iterator_value; + + template + class iterator_base: public boost::iterator_adaptor< + iterator_base, + node_iterator, + V, + std::forward_iterator_tag, + V> + { + private: + template friend class iterator_base; + struct enabler {}; + typedef typename iterator_base::base_type base_type; + + public: + typedef typename iterator_base::value_type value_type; + + public: + iterator_base() {} + explicit iterator_base(base_type rhs, shared_memory_holder pMemory): iterator_base::iterator_adaptor_(rhs), m_pMemory(pMemory) {} + + template + iterator_base(const iterator_base& rhs, typename boost::enable_if, enabler>::type = enabler()): iterator_base::iterator_adaptor_(rhs.base()), m_pMemory(rhs.m_pMemory) {} + + private: + friend class boost::iterator_core_access; + + void increment() { this->base_reference() = boost::next(this->base()); } + + value_type dereference() const { + const typename base_type::value_type& v = *this->base(); + if(v.pNode) + return value_type(Node(*v, m_pMemory)); + if(v.first && v.second) + return value_type(Node(*v.first, m_pMemory), Node(*v.second, m_pMemory)); + return value_type(); + } + + private: + shared_memory_holder m_pMemory; + }; + } +} + +#endif // VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/detail/iterator_fwd.h b/include/yaml-cpp/node/detail/iterator_fwd.h new file mode 100644 index 0000000..c4efb2c --- /dev/null +++ b/include/yaml-cpp/node/detail/iterator_fwd.h @@ -0,0 +1,27 @@ +#ifndef VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + + +#include "yaml-cpp/dll.h" +#include +#include +#include + +namespace YAML +{ + class node; + + namespace detail { + struct iterator_value; + template class iterator_base; + } + + typedef detail::iterator_base iterator; + typedef detail::iterator_base const_iterator; +} + +#endif // VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/detail/memory.h b/include/yaml-cpp/node/detail/memory.h new file mode 100644 index 0000000..243a81a --- /dev/null +++ b/include/yaml-cpp/node/detail/memory.h @@ -0,0 +1,39 @@ +#ifndef VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include "yaml-cpp/node/ptr.h" +#include +#include + +namespace YAML +{ + namespace detail + { + class memory { + public: + node& create_node(); + void merge(const memory& rhs); + + private: + typedef std::set Nodes; + Nodes m_nodes; + }; + + class memory_holder { + public: + memory_holder(): m_pMemory(new memory) {} + + node& create_node() { return m_pMemory->create_node(); } + void merge(memory_holder& rhs); + + private: + boost::shared_ptr m_pMemory; + }; + } +} + +#endif // VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/detail/node.h b/include/yaml-cpp/node/detail/node.h new file mode 100644 index 0000000..846e279 --- /dev/null +++ b/include/yaml-cpp/node/detail/node.h @@ -0,0 +1,126 @@ +#ifndef NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + + +#include "yaml-cpp/dll.h" +#include "yaml-cpp/node/type.h" +#include "yaml-cpp/node/ptr.h" +#include "yaml-cpp/node/detail/node_ref.h" +#include +#include + +namespace YAML +{ + namespace detail + { + class node: private boost::noncopyable + { + public: + node(): m_pRef(new node_ref) {} + + bool is(const node& rhs) const { return m_pRef == rhs.m_pRef; } + const node_ref *ref() const { return m_pRef.get(); } + + bool is_defined() const { return m_pRef->is_defined(); } + NodeType::value type() const { return m_pRef->type(); } + + const std::string& scalar() const { return m_pRef->scalar(); } + const std::string& tag() const { return m_pRef->tag(); } + + void mark_defined() { + if(is_defined()) + return; + + m_pRef->mark_defined(); + for(nodes::iterator it=m_dependencies.begin();it!=m_dependencies.end();++it) + (*it)->mark_defined(); + m_dependencies.clear(); + } + + void add_dependency(node& rhs) { + if(is_defined()) + rhs.mark_defined(); + else + m_dependencies.insert(&rhs); + } + + void set_ref(const node& rhs) { + if(rhs.is_defined()) + mark_defined(); + m_pRef = rhs.m_pRef; + } + void set_data(const node& rhs) { + if(rhs.is_defined()) + mark_defined(); + m_pRef->set_data(*rhs.m_pRef); + } + + void set_type(NodeType::value type) { + if(type != NodeType::Undefined) + mark_defined(); + m_pRef->set_type(type); + } + void set_null() { + mark_defined(); + m_pRef->set_null(); + } + void set_scalar(const std::string& scalar) { + mark_defined(); + m_pRef->set_scalar(scalar); + } + void set_tag(const std::string& tag) { + mark_defined(); + m_pRef->set_tag(tag); + } + + // size/iterator + std::size_t size() const { return m_pRef->size(); } + + const_node_iterator begin() const { return static_cast(*m_pRef).begin(); } + node_iterator begin() { return m_pRef->begin(); } + + const_node_iterator end() const { return static_cast(*m_pRef).end(); } + node_iterator end() { return m_pRef->end(); } + + // sequence + void push_back(node& node, shared_memory_holder pMemory) { + m_pRef->push_back(node, pMemory); + node.add_dependency(*this); + } + void insert(node& key, node& value, shared_memory_holder pMemory) { + m_pRef->insert(key, value, pMemory); + key.add_dependency(*this); + value.add_dependency(*this); + } + + // indexing + template node& get(const Key& key, shared_memory_holder pMemory) const { return static_cast(*m_pRef).get(key, pMemory); } + template node& get(const Key& key, shared_memory_holder pMemory) { + node& value = m_pRef->get(key, pMemory); + value.add_dependency(*this); + return value; + } + template bool remove(const Key& key, shared_memory_holder pMemory) { return m_pRef->remove(key, pMemory); } + + node& get(node& key, shared_memory_holder pMemory) const { return static_cast(*m_pRef).get(key, pMemory); } + node& get(node& key, shared_memory_holder pMemory) { + node& value = m_pRef->get(key, pMemory); + key.add_dependency(*this); + value.add_dependency(*this); + return value; + } + bool remove(node& key, shared_memory_holder pMemory) { return m_pRef->remove(key, pMemory); } + + private: + shared_node_ref m_pRef; + typedef std::set nodes; + nodes m_dependencies; + }; + } +} + +#endif // NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/detail/node_data.h b/include/yaml-cpp/node/detail/node_data.h new file mode 100644 index 0000000..c0be2b8 --- /dev/null +++ b/include/yaml-cpp/node/detail/node_data.h @@ -0,0 +1,105 @@ +#ifndef VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + + +#include "yaml-cpp/dll.h" +#include "yaml-cpp/node/iterator.h" +#include "yaml-cpp/node/ptr.h" +#include "yaml-cpp/node/type.h" +#include +#include +#include +#include + +namespace YAML +{ + namespace detail + { + class node_data: private boost::noncopyable + { + public: + node_data(); + + void mark_defined(); + void set_type(NodeType::value type); + void set_tag(const std::string& tag); + void set_null(); + void set_scalar(const std::string& scalar); + + bool is_defined() const { return m_isDefined; } + NodeType::value type() const { return m_isDefined ? m_type : NodeType::Undefined; } + const std::string& scalar() const { return m_scalar; } + const std::string& tag() const { return m_tag; } + + // size/iterator + std::size_t size() const; + + const_node_iterator begin() const; + node_iterator begin(); + + const_node_iterator end() const; + node_iterator end(); + + // sequence + void push_back(node& node, shared_memory_holder pMemory); + void insert(node& key, node& value, shared_memory_holder pMemory); + + // indexing + template node& get(const Key& key, shared_memory_holder pMemory) const; + template node& get(const Key& key, shared_memory_holder pMemory); + template bool remove(const Key& key, shared_memory_holder pMemory); + + node& get(node& key, shared_memory_holder pMemory) const; + node& get(node& key, shared_memory_holder pMemory); + bool remove(node& key, shared_memory_holder pMemory); + + public: + static std::string empty_scalar; + + private: + void compute_seq_size() const; + void compute_map_size() const; + + void reset_sequence(); + void reset_map(); + + void insert_map_pair(node& key, node& value); + void convert_to_map(shared_memory_holder pMemory); + void convert_sequence_to_map(shared_memory_holder pMemory); + + template + static bool equals(node& node, const T& rhs, shared_memory_holder pMemory); + + template + static node& convert_to_node(const T& rhs, shared_memory_holder pMemory); + + private: + bool m_isDefined; + NodeType::value m_type; + std::string m_tag; + + // scalar + std::string m_scalar; + + // sequence + typedef std::vector node_seq; + node_seq m_sequence; + + mutable std::size_t m_seqSize; + + // map + typedef std::map node_map; + node_map m_map; + + typedef std::pair kv_pair; + typedef std::list kv_pairs; + mutable kv_pairs m_undefinedPairs; + }; + } +} + +#endif // VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/detail/node_iterator.h b/include/yaml-cpp/node/detail/node_iterator.h new file mode 100644 index 0000000..294921b --- /dev/null +++ b/include/yaml-cpp/node/detail/node_iterator.h @@ -0,0 +1,139 @@ +#ifndef VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + + +#include "yaml-cpp/dll.h" +#include "yaml-cpp/node/ptr.h" +#include +#include +#include +#include +#include + +namespace YAML +{ + namespace detail + { + struct iterator_type { enum value { None, Sequence, Map }; }; + + template + struct node_iterator_value: public std::pair { + typedef std::pair kv; + + node_iterator_value(): kv(), pNode(0) {} + explicit node_iterator_value(V& rhs): kv(), pNode(&rhs) {} + explicit node_iterator_value(V& key, V& value): kv(&key, &value), pNode(0) {} + + V& operator *() const { return *pNode; } + V& operator ->() const { return *pNode; } + + V *pNode; + }; + + typedef std::vector node_seq; + typedef std::map node_map; + + template + struct node_iterator_type { + typedef node_seq::iterator seq; + typedef node_map::iterator map; + }; + + template + struct node_iterator_type { + typedef node_seq::const_iterator seq; + typedef node_map::const_iterator map; + }; + + + template + class node_iterator_base: public boost::iterator_facade< + node_iterator_base, + node_iterator_value, + std::forward_iterator_tag, + node_iterator_value > + { + private: + struct enabler {}; + + public: + typedef typename node_iterator_type::seq SeqIter; + typedef typename node_iterator_type::map MapIter; + typedef node_iterator_value value_type; + + node_iterator_base(): m_type(iterator_type::None) {} + explicit node_iterator_base(SeqIter seqIt): m_type(iterator_type::Sequence), m_seqIt(seqIt) {} + explicit node_iterator_base(MapIter mapIt, MapIter mapEnd): m_type(iterator_type::Map), m_mapIt(mapIt), m_mapEnd(mapEnd) { + m_mapIt = increment_until_defined(m_mapIt); + } + + template + node_iterator_base(const node_iterator_base& rhs, typename boost::enable_if, enabler>::type = enabler()) + : m_type(rhs.m_type), m_seqIt(rhs.m_seqIt), m_mapIt(rhs.m_mapIt), m_mapEnd(rhs.m_mapEnd) {} + + private: + friend class boost::iterator_core_access; + template friend class node_iterator_base; + + template + bool equal(const node_iterator_base& rhs) const { + if(m_type != rhs.m_type) + return false; + + switch(m_type) { + case iterator_type::None: return true; + case iterator_type::Sequence: return m_seqIt == rhs.m_seqIt; + case iterator_type::Map: return m_mapIt == rhs.m_mapIt; + } + return true; + } + + void increment() { + switch(m_type) { + case iterator_type::None: break; + case iterator_type::Sequence: + ++m_seqIt; + break; + case iterator_type::Map: + ++m_mapIt; + m_mapIt = increment_until_defined(m_mapIt); + break; + } + } + + value_type dereference() const { + switch(m_type) { + case iterator_type::None: return value_type(); + case iterator_type::Sequence: return value_type(**m_seqIt); + case iterator_type::Map: return value_type(*m_mapIt->first, *m_mapIt->second); + } + return value_type(); + } + + MapIter increment_until_defined(MapIter it) { + while(it != m_mapEnd && !is_defined(it)) + ++it; + return it; + } + + bool is_defined(MapIter it) const { + return it->first->is_defined() && it->second->is_defined(); + } + + private: + typename iterator_type::value m_type; + + SeqIter m_seqIt; + MapIter m_mapIt, m_mapEnd; + }; + + typedef node_iterator_base node_iterator; + typedef node_iterator_base const_node_iterator; + } +} + +#endif // VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/detail/node_ref.h b/include/yaml-cpp/node/detail/node_ref.h new file mode 100644 index 0000000..d1b06c5 --- /dev/null +++ b/include/yaml-cpp/node/detail/node_ref.h @@ -0,0 +1,65 @@ +#ifndef VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + + +#include "yaml-cpp/dll.h" +#include "yaml-cpp/node/type.h" +#include "yaml-cpp/node/ptr.h" +#include "yaml-cpp/node/detail/node_data.h" +#include + +namespace YAML +{ + namespace detail + { + class node_ref: private boost::noncopyable + { + public: + node_ref(): m_pData(new node_data) {} + + bool is_defined() const { return m_pData->is_defined(); } + NodeType::value type() const { return m_pData->type(); } + const std::string& scalar() const { return m_pData->scalar(); } + const std::string& tag() const { return m_pData->tag(); } + + void mark_defined() { m_pData->mark_defined(); } + void set_data(const node_ref& rhs) { m_pData = rhs.m_pData; } + + void set_type(NodeType::value type) { m_pData->set_type(type); } + void set_tag(const std::string& tag) { m_pData->set_tag(tag); } + void set_null() { m_pData->set_null(); } + void set_scalar(const std::string& scalar) { m_pData->set_scalar(scalar); } + + // size/iterator + std::size_t size() const { return m_pData->size(); } + + const_node_iterator begin() const { return static_cast(*m_pData).begin(); } + node_iterator begin() {return m_pData->begin(); } + + const_node_iterator end() const { return static_cast(*m_pData).end(); } + node_iterator end() {return m_pData->end(); } + + // sequence + void push_back(node& node, shared_memory_holder pMemory) { m_pData->push_back(node, pMemory); } + void insert(node& key, node& value, shared_memory_holder pMemory) { m_pData->insert(key, value, pMemory); } + + // indexing + template node& get(const Key& key, shared_memory_holder pMemory) const { return static_cast(*m_pData).get(key, pMemory); } + template node& get(const Key& key, shared_memory_holder pMemory) { return m_pData->get(key, pMemory); } + template bool remove(const Key& key, shared_memory_holder pMemory) { return m_pData->remove(key, pMemory); } + + node& get(node& key, shared_memory_holder pMemory) const { return static_cast(*m_pData).get(key, pMemory); } + node& get(node& key, shared_memory_holder pMemory) { return m_pData->get(key, pMemory); } + bool remove(node& key, shared_memory_holder pMemory) { return m_pData->remove(key, pMemory); } + + private: + shared_node_data m_pData; + }; + } +} + +#endif // VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/emit.h b/include/yaml-cpp/node/emit.h new file mode 100644 index 0000000..7abf80b --- /dev/null +++ b/include/yaml-cpp/node/emit.h @@ -0,0 +1,23 @@ +#ifndef NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include +#include + +namespace YAML +{ + class Emitter; + class Node; + + Emitter& operator << (Emitter& out, const Node& node); + std::ostream& operator << (std::ostream& out, const Node& node); + + std::string Dump(const Node& node); +} + +#endif // NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + diff --git a/include/yaml-cpp/node/impl.h b/include/yaml-cpp/node/impl.h new file mode 100644 index 0000000..00ae1f6 --- /dev/null +++ b/include/yaml-cpp/node/impl.h @@ -0,0 +1,355 @@ +#ifndef NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + + +#include "yaml-cpp/node/node.h" +#include "yaml-cpp/node/iterator.h" +#include "yaml-cpp/node/detail/memory.h" +#include "yaml-cpp/node/detail/node.h" +#include "yaml-cpp/exceptions.h" +#include + +namespace YAML +{ + inline Node::Node(): m_pNode(0) + { + } + + inline Node::Node(NodeType::value type): m_pMemory(new detail::memory_holder), m_pNode(&m_pMemory->create_node()) + { + m_pNode->set_type(type); + } + + template + inline Node::Node(const T& rhs): m_pMemory(new detail::memory_holder), m_pNode(&m_pMemory->create_node()) + { + Assign(rhs); + } + + inline Node::Node(const detail::iterator_value& rhs): m_pMemory(rhs.m_pMemory), m_pNode(rhs.m_pNode) + { + } + + inline Node::Node(const Node& rhs): m_pMemory(rhs.m_pMemory), m_pNode(rhs.m_pNode) + { + } + + inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory): m_pMemory(pMemory), m_pNode(&node) + { + } + + inline Node::~Node() + { + } + + inline void Node::EnsureNodeExists() const + { + if(!m_pNode) { + m_pMemory.reset(new detail::memory_holder); + m_pNode = &m_pMemory->create_node(); + m_pNode->set_null(); + } + } + + inline bool Node::IsDefined() const + { + return m_pNode ? m_pNode->is_defined() : true; + } + + inline NodeType::value Node::Type() const + { + return m_pNode ? m_pNode->type() : NodeType::Null; + } + + // access + + // template helpers + template + struct as_if { + explicit as_if(const Node& node_): node(node_) {} + const Node& node; + + const T operator()(const S& fallback) const { + if(!node.m_pNode) + return fallback; + + T t; + if(convert::decode(node, t)) + return t; + return fallback; + } + }; + + template + struct as_if { + explicit as_if(const Node& node_): node(node_) {} + const Node& node; + + const std::string operator()(const S& fallback) const { + if(node.Type() != NodeType::Scalar) + return fallback; + return node.Scalar(); + } + }; + + template + struct as_if { + explicit as_if(const Node& node_): node(node_) {} + const Node& node; + + const T operator()() const { + if(!node.m_pNode) + throw TypedBadConversion(); + + T t; + if(convert::decode(node, t)) + return t; + throw TypedBadConversion(); + } + }; + + template<> + struct as_if { + explicit as_if(const Node& node_): node(node_) {} + const Node& node; + + const std::string operator()() const { + if(node.Type() != NodeType::Scalar) + throw TypedBadConversion(); + return node.Scalar(); + } + }; + + // access functions + template + inline const T Node::as() const + { + return as_if(*this)(); + } + + template + inline const T Node::as(const S& fallback) const + { + return as_if(*this)(fallback); + } + + inline const std::string& Node::Scalar() const + { + return m_pNode ? m_pNode->scalar() : detail::node_data::empty_scalar; + } + + inline const std::string& Node::Tag() const + { + return m_pNode ? m_pNode->tag() : detail::node_data::empty_scalar; + } + + inline void Node::SetTag(const std::string& tag) + { + EnsureNodeExists(); + m_pNode->set_tag(tag); + } + + // assignment + inline bool Node::is(const Node& rhs) const + { + if(!m_pNode || !rhs.m_pNode) + return false; + return m_pNode->is(*rhs.m_pNode); + } + + template + inline Node& Node::operator=(const T& rhs) + { + Assign(rhs); + return *this; + } + + template + inline void Node::Assign(const T& rhs) + { + AssignData(convert::encode(rhs)); + } + + template<> + inline void Node::Assign(const std::string& rhs) + { + EnsureNodeExists(); + m_pNode->set_scalar(rhs); + } + + inline void Node::Assign(const char *rhs) + { + EnsureNodeExists(); + m_pNode->set_scalar(rhs); + } + + inline void Node::Assign(char *rhs) + { + EnsureNodeExists(); + m_pNode->set_scalar(rhs); + } + + inline Node& Node::operator=(const Node& rhs) + { + if(is(rhs)) + return *this; + AssignNode(rhs); + return *this; + } + + inline void Node::AssignData(const Node& rhs) + { + EnsureNodeExists(); + rhs.EnsureNodeExists(); + + m_pNode->set_data(*rhs.m_pNode); + m_pMemory->merge(*rhs.m_pMemory); + } + + inline void Node::AssignNode(const Node& rhs) + { + rhs.EnsureNodeExists(); + + if(!m_pNode) { + m_pNode = rhs.m_pNode; + m_pMemory = rhs.m_pMemory; + return; + } + + m_pNode->set_ref(*rhs.m_pNode); + m_pMemory->merge(*rhs.m_pMemory); + m_pNode = rhs.m_pNode; + } + + // size/iterator + inline std::size_t Node::size() const + { + return m_pNode ? m_pNode->size() : 0; + } + + inline const_iterator Node::begin() const + { + return m_pNode ? const_iterator(m_pNode->begin(), m_pMemory) : const_iterator(); + } + + inline iterator Node::begin() + { + return m_pNode ? iterator(m_pNode->begin(), m_pMemory) : iterator(); + } + + inline const_iterator Node::end() const + { + return m_pNode ? const_iterator(m_pNode->end(), m_pMemory) : const_iterator(); + } + + inline iterator Node::end() + { + return m_pNode ? iterator(m_pNode->end(), m_pMemory) : iterator(); + } + + // sequence + template + inline void Node::push_back(const T& rhs) + { + push_back(Node(rhs)); + } + + inline void Node::push_back(const Node& rhs) + { + EnsureNodeExists(); + rhs.EnsureNodeExists(); + + m_pNode->push_back(*rhs.m_pNode, m_pMemory); + m_pMemory->merge(*rhs.m_pMemory); + } + + // indexing + template + inline const Node Node::operator[](const Key& key) const + { + EnsureNodeExists(); + detail::node& value = static_cast(*m_pNode).get(key, m_pMemory); + return Node(value, m_pMemory); + } + + template + inline Node Node::operator[](const Key& key) + { + EnsureNodeExists(); + detail::node& value = m_pNode->get(key, m_pMemory); + return Node(value, m_pMemory); + } + + template + inline bool Node::remove(const Key& key) + { + EnsureNodeExists(); + return m_pNode->remove(key, m_pMemory); + } + + inline const Node Node::operator[](const Node& key) const + { + EnsureNodeExists(); + key.EnsureNodeExists(); + detail::node& value = static_cast(*m_pNode).get(*key.m_pNode, m_pMemory); + return Node(value, m_pMemory); + } + + inline Node Node::operator[](const Node& key) + { + EnsureNodeExists(); + key.EnsureNodeExists(); + detail::node& value = m_pNode->get(*key.m_pNode, m_pMemory); + return Node(value, m_pMemory); + } + + inline bool Node::remove(const Node& key) + { + EnsureNodeExists(); + key.EnsureNodeExists(); + return m_pNode->remove(*key.m_pNode, m_pMemory); + } + + inline const Node Node::operator[](const char *key) const + { + return operator[](std::string(key)); + } + + inline Node Node::operator[](const char *key) + { + return operator[](std::string(key)); + } + + inline bool Node::remove(const char *key) + { + return remove(std::string(key)); + } + + inline const Node Node::operator[](char *key) const + { + return operator[](static_cast(key)); + } + + inline Node Node::operator[](char *key) + { + return operator[](static_cast(key)); + } + + inline bool Node::remove(char *key) + { + return remove(static_cast(key)); + } + + // free functions + + inline bool operator==(const Node& lhs, const Node& rhs) + { + return lhs.is(rhs); + } +} + +#endif // NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/iterator.h b/include/yaml-cpp/node/iterator.h new file mode 100644 index 0000000..4cc4719 --- /dev/null +++ b/include/yaml-cpp/node/iterator.h @@ -0,0 +1,28 @@ +#ifndef VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + + +#include "yaml-cpp/dll.h" +#include "yaml-cpp/node/node.h" +#include "yaml-cpp/node/detail/iterator_fwd.h" +#include "yaml-cpp/node/detail/iterator.h" +#include +#include +#include + +namespace YAML +{ + namespace detail { + struct iterator_value: public Node, std::pair { + iterator_value() {} + explicit iterator_value(const Node& rhs): Node(rhs) {} + explicit iterator_value(const Node& key, const Node& value): std::pair(key, value) {} + }; + } +} + +#endif // VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/node.h b/include/yaml-cpp/node/node.h new file mode 100644 index 0000000..e230e4a --- /dev/null +++ b/include/yaml-cpp/node/node.h @@ -0,0 +1,113 @@ +#ifndef NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + + +#include "yaml-cpp/dll.h" +#include "yaml-cpp/node/ptr.h" +#include "yaml-cpp/node/type.h" +#include "yaml-cpp/node/detail/iterator_fwd.h" +#include "yaml-cpp/node/detail/bool_type.h" +#include + +namespace YAML +{ + class Node + { + public: + friend class NodeBuilder; + friend class NodeEvents; + friend class detail::node_data; + template friend class detail::iterator_base; + template friend struct as_if; + + typedef YAML::iterator iterator; + typedef YAML::const_iterator const_iterator; + + Node(); + explicit Node(NodeType::value type); + template explicit Node(const T& rhs); + explicit Node(const detail::iterator_value& rhs); + Node(const Node& rhs); + ~Node(); + + NodeType::value Type() const; + bool IsDefined() const; + bool IsNull() const { return Type() == NodeType::Null; } + bool IsScalar() const { return Type() == NodeType::Scalar; } + bool IsSequence() const { return Type() == NodeType::Sequence; } + bool IsMap() const { return Type() == NodeType::Map; } + + // bool conversions + YAML_CPP_OPERATOR_BOOL(); + bool operator!() const { return !IsDefined(); } + + // access + template const T as() const; + template const T as(const S& fallback) const; + const std::string& Scalar() const; + const std::string& Tag() const; + void SetTag(const std::string& tag); + + // assignment + bool is(const Node& rhs) const; + template Node& operator=(const T& rhs); + Node& operator=(const Node& rhs); + + // size/iterator + std::size_t size() const; + + const_iterator begin() const; + iterator begin(); + + const_iterator end() const; + iterator end(); + + // sequence + template void push_back(const T& rhs); + void push_back(const Node& rhs); + + // indexing + template const Node operator[](const Key& key) const; + template Node operator[](const Key& key); + template bool remove(const Key& key); + + const Node operator[](const Node& key) const; + Node operator[](const Node& key); + bool remove(const Node& key); + + const Node operator[](const char *key) const; + Node operator[](const char *key); + bool remove(const char *key); + + const Node operator[](char *key) const; + Node operator[](char *key); + bool remove(char *key); + + private: + explicit Node(detail::node& node, detail::shared_memory_holder pMemory); + + void EnsureNodeExists() const; + + template void Assign(const T& rhs); + void Assign(const char *rhs); + void Assign(char *rhs); + + void AssignData(const Node& rhs); + void AssignNode(const Node& rhs); + + private: + mutable detail::shared_memory_holder m_pMemory; + mutable detail::node *m_pNode; + }; + + bool operator==(const Node& lhs, const Node& rhs); + + template + struct convert; +} + +#endif // NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/parse.h b/include/yaml-cpp/node/parse.h new file mode 100644 index 0000000..82dbdc1 --- /dev/null +++ b/include/yaml-cpp/node/parse.h @@ -0,0 +1,28 @@ +#ifndef VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include +#include +#include + +namespace YAML +{ + class Node; + + Node Load(const std::string& input); + Node Load(const char *input); + Node Load(std::istream& input); + Node LoadFile(const std::string& filename); + + std::vector LoadAll(const std::string& input); + std::vector LoadAll(const char *input); + std::vector LoadAll(std::istream& input); + std::vector LoadAllFromFile(const std::string& filename); +} + +#endif // VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + diff --git a/include/yaml-cpp/node/ptr.h b/include/yaml-cpp/node/ptr.h new file mode 100644 index 0000000..316dbd2 --- /dev/null +++ b/include/yaml-cpp/node/ptr.h @@ -0,0 +1,29 @@ +#ifndef VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + + +#include "yaml-cpp/dll.h" +#include + +namespace YAML +{ + namespace detail { + class node; + class node_ref; + class node_data; + class memory; + class memory_holder; + + typedef boost::shared_ptr shared_node; + typedef boost::shared_ptr shared_node_ref; + typedef boost::shared_ptr shared_node_data; + typedef boost::shared_ptr shared_memory_holder; + typedef boost::shared_ptr shared_memory; + } +} + +#endif // VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/type.h b/include/yaml-cpp/node/type.h new file mode 100644 index 0000000..5ac8041 --- /dev/null +++ b/include/yaml-cpp/node/type.h @@ -0,0 +1,14 @@ +#ifndef VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + + +namespace YAML +{ + struct NodeType { enum value { Undefined, Null, Scalar, Sequence, Map }; }; +} + +#endif // VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/parser.h b/include/yaml-cpp/parser.h index ffc21f5..f71cdff 100644 --- a/include/yaml-cpp/parser.h +++ b/include/yaml-cpp/parser.h @@ -31,7 +31,9 @@ namespace YAML void Load(std::istream& in); bool HandleNextDocument(EventHandler& eventHandler); - + + bool GetNextDocument(Node& document); // old API only + void PrintTokens(std::ostream& out); private: diff --git a/include/yaml-cpp/yaml.h b/include/yaml-cpp/yaml.h index 0c219b3..4e63408 100644 --- a/include/yaml-cpp/yaml.h +++ b/include/yaml-cpp/yaml.h @@ -10,4 +10,12 @@ #include "yaml-cpp/stlemitter.h" #include "yaml-cpp/exceptions.h" +#include "yaml-cpp/node/node.h" +#include "yaml-cpp/node/impl.h" +#include "yaml-cpp/node/convert.h" +#include "yaml-cpp/node/iterator.h" +#include "yaml-cpp/node/detail/impl.h" +#include "yaml-cpp/node/parse.h" +#include "yaml-cpp/node/emit.h" + #endif // YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/src/convert.cpp b/src/convert.cpp new file mode 100644 index 0000000..dc715f7 --- /dev/null +++ b/src/convert.cpp @@ -0,0 +1,83 @@ +#include "yaml-cpp/node/convert.h" +#include "yaml-cpp/node/impl.h" +#include + +namespace +{ + // we're not gonna mess with the mess that is all the isupper/etc. functions + bool IsLower(char ch) { return 'a' <= ch && ch <= 'z'; } + bool IsUpper(char ch) { return 'A' <= ch && ch <= 'Z'; } + char ToLower(char ch) { return IsUpper(ch) ? ch + 'a' - 'A' : ch; } + + std::string tolower(const std::string& str) + { + std::string s(str); + std::transform(s.begin(), s.end(), s.begin(), ToLower); + return s; + } + + template + bool IsEntirely(const std::string& str, T func) + { + for(std::size_t i=0;i::decode(const Node& node, bool& rhs) { + if(!node.IsScalar()) + return false; + + // we can't use iostream bool extraction operators as they don't + // recognize all possible values in the table below (taken from + // http://yaml.org/type/bool.html) + static const struct { + std::string truename, falsename; + } names[] = { + { "y", "n" }, + { "yes", "no" }, + { "true", "false" }, + { "on", "off" }, + }; + + if(!IsFlexibleCase(node.Scalar())) + return false; + + for(unsigned i=0;imerge(*rhs.m_pMemory); + rhs.m_pMemory = m_pMemory; + } + + node& memory::create_node() + { + shared_node pNode(new node); + m_nodes.insert(pNode); + return *pNode; + } + + void memory::merge(const memory& rhs) + { + m_nodes.insert(rhs.m_nodes.begin(), rhs.m_nodes.end()); + } + } +} diff --git a/src/node_data.cpp b/src/node_data.cpp new file mode 100644 index 0000000..6f82f7b --- /dev/null +++ b/src/node_data.cpp @@ -0,0 +1,295 @@ +#include "yaml-cpp/node/detail/node_data.h" +#include "yaml-cpp/node/detail/memory.h" +#include "yaml-cpp/node/detail/node.h" +#include "yaml-cpp/exceptions.h" +#include + +namespace YAML +{ + namespace detail + { + std::string node_data::empty_scalar; + + node_data::node_data(): m_isDefined(false), m_type(NodeType::Null), m_seqSize(0) + { + } + + void node_data::mark_defined() + { + if(m_type == NodeType::Undefined) + m_type = NodeType::Null; + m_isDefined = true; + } + + void node_data::set_type(NodeType::value type) + { + if(type == NodeType::Undefined) { + m_type = type; + m_isDefined = false; + return; + } + + + m_isDefined = true; + if(type == m_type) + return; + + m_type = type; + + switch(m_type) { + case NodeType::Null: + break; + case NodeType::Scalar: + m_scalar.clear(); + break; + case NodeType::Sequence: + reset_sequence(); + break; + case NodeType::Map: + reset_map(); + break; + case NodeType::Undefined: + assert(false); + break; + } + } + + void node_data::set_tag(const std::string& tag) + { + m_tag = tag; + } + + void node_data::set_null() + { + m_isDefined = true; + m_type = NodeType::Null; + } + + void node_data::set_scalar(const std::string& scalar) + { + m_isDefined = true; + m_type = NodeType::Scalar; + m_scalar = scalar; + } + + // size/iterator + std::size_t node_data::size() const + { + if(!m_isDefined) + return 0; + + switch(m_type) { + case NodeType::Sequence: compute_seq_size(); return m_seqSize; + case NodeType::Map: compute_map_size(); return m_map.size() - m_undefinedPairs.size(); + default: + return 0; + } + return 0; + } + + void node_data::compute_seq_size() const + { + while(m_seqSize < m_sequence.size() && m_sequence[m_seqSize]->is_defined()) + m_seqSize++; + } + + void node_data::compute_map_size() const + { + kv_pairs::iterator it = m_undefinedPairs.begin(); + while(it != m_undefinedPairs.end()) { + kv_pairs::iterator jt = boost::next(it); + if(it->first->is_defined() && it->second->is_defined()) + m_undefinedPairs.erase(it); + it = jt; + } + } + + const_node_iterator node_data::begin() const + { + if(!m_isDefined) + return const_node_iterator(); + + switch(m_type) { + case NodeType::Sequence: return const_node_iterator(m_sequence.begin()); + case NodeType::Map: return const_node_iterator(m_map.begin(), m_map.end()); + default: return const_node_iterator(); + } + } + + node_iterator node_data::begin() + { + if(!m_isDefined) + return node_iterator(); + + switch(m_type) { + case NodeType::Sequence: return node_iterator(m_sequence.begin()); + case NodeType::Map: return node_iterator(m_map.begin(), m_map.end()); + default: return node_iterator(); + } + } + + const_node_iterator node_data::end() const + { + if(!m_isDefined) + return const_node_iterator(); + + switch(m_type) { + case NodeType::Sequence: return const_node_iterator(m_sequence.end()); + case NodeType::Map: return const_node_iterator(m_map.end(), m_map.end()); + default: return const_node_iterator(); + } + } + + node_iterator node_data::end() + { + if(!m_isDefined) + return node_iterator(); + + switch(m_type) { + case NodeType::Sequence: return node_iterator(m_sequence.end()); + case NodeType::Map: return node_iterator(m_map.end(), m_map.end()); + default: return node_iterator(); + } + } + + // sequence + void node_data::push_back(node& node, shared_memory_holder /* pMemory */) + { + if(m_type == NodeType::Undefined || m_type == NodeType::Null) { + m_type = NodeType::Sequence; + reset_sequence(); + } + + if(m_type != NodeType::Sequence) + throw BadPushback(); + + m_sequence.push_back(&node); + } + + void node_data::insert(node& key, node& value, shared_memory_holder pMemory) + { + switch(m_type) { + case NodeType::Map: + break; + case NodeType::Undefined: + case NodeType::Null: + case NodeType::Sequence: + convert_to_map(pMemory); + break; + case NodeType::Scalar: + throw BadSubscript(); + } + + insert_map_pair(key, value); + } + + // indexing + node& node_data::get(node& key, shared_memory_holder pMemory) const + { + if(m_type != NodeType::Map) + return pMemory->create_node(); + + for(node_map::const_iterator it=m_map.begin();it!=m_map.end();++it) { + if(it->first->is(key)) + return *it->second; + } + + return pMemory->create_node(); + } + + node& node_data::get(node& key, shared_memory_holder pMemory) + { + switch(m_type) { + case NodeType::Map: + break; + case NodeType::Undefined: + case NodeType::Null: + case NodeType::Sequence: + convert_to_map(pMemory); + break; + case NodeType::Scalar: + throw BadSubscript(); + } + + for(node_map::const_iterator it=m_map.begin();it!=m_map.end();++it) { + if(it->first->is(key)) + return *it->second; + } + + node& value = pMemory->create_node(); + insert_map_pair(key, value); + return value; + } + + bool node_data::remove(node& key, shared_memory_holder /* pMemory */) + { + if(m_type != NodeType::Map) + return false; + + for(node_map::iterator it=m_map.begin();it!=m_map.end();++it) { + if(it->first->is(key)) { + m_map.erase(it); + return true; + } + } + + return false; + } + + void node_data::reset_sequence() + { + m_sequence.clear(); + m_seqSize = 0; + } + + void node_data::reset_map() + { + m_map.clear(); + m_undefinedPairs.clear(); + } + + void node_data::insert_map_pair(node& key, node& value) + { + m_map[&key] = &value; + if(!key.is_defined() || !value.is_defined()) + m_undefinedPairs.push_back(kv_pair(&key, &value)); + } + + void node_data::convert_to_map(shared_memory_holder pMemory) + { + switch(m_type) { + case NodeType::Undefined: + case NodeType::Null: + reset_map(); + m_type = NodeType::Map; + break; + case NodeType::Sequence: + convert_sequence_to_map(pMemory); + break; + case NodeType::Map: + break; + case NodeType::Scalar: + assert(false); + break; + } + } + + void node_data::convert_sequence_to_map(shared_memory_holder pMemory) + { + assert(m_type == NodeType::Sequence); + + reset_map(); + for(std::size_t i=0;icreate_node(); + key.set_scalar(stream.str()); + insert_map_pair(key, *m_sequence[i]); + } + + reset_sequence(); + m_type = NodeType::Map; + } + } +} diff --git a/src/nodebuilder.cpp b/src/nodebuilder.cpp new file mode 100644 index 0000000..6735f73 --- /dev/null +++ b/src/nodebuilder.cpp @@ -0,0 +1,138 @@ +#include "nodebuilder.h" +#include "yaml-cpp/mark.h" +#include "yaml-cpp/node/node.h" +#include "yaml-cpp/node/impl.h" +#include + +namespace YAML +{ + NodeBuilder::NodeBuilder(): m_pMemory(new detail::memory_holder), m_pRoot(0), m_mapDepth(0) + { + m_anchors.push_back(0); // since the anchors start at 1 + } + + NodeBuilder::~NodeBuilder() + { + } + + Node NodeBuilder::Root() + { + if(!m_pRoot) + return Node(); + + return Node(*m_pRoot, m_pMemory); + } + + void NodeBuilder::OnDocumentStart(const Mark&) + { + } + + void NodeBuilder::OnDocumentEnd() + { + } + + void NodeBuilder::OnNull(const Mark& /* mark */, anchor_t anchor) + { + detail::node& node = Push(anchor); + node.set_null(); + Pop(); + } + + void NodeBuilder::OnAlias(const Mark& /* mark */, anchor_t anchor) + { + detail::node& node = *m_anchors[anchor]; + Push(node); + Pop(); + } + + void NodeBuilder::OnScalar(const Mark& /* mark */, const std::string& tag, anchor_t anchor, const std::string& value) + { + detail::node& node = Push(anchor); + node.set_scalar(value); + node.set_tag(tag); + Pop(); + } + + void NodeBuilder::OnSequenceStart(const Mark& /* mark */, const std::string& tag, anchor_t anchor) + { + detail::node& node = Push(anchor); + node.set_tag(tag); + node.set_type(NodeType::Sequence); + } + + void NodeBuilder::OnSequenceEnd() + { + Pop(); + } + + void NodeBuilder::OnMapStart(const Mark& /* mark */, const std::string& tag, anchor_t anchor) + { + detail::node& node = Push(anchor); + node.set_type(NodeType::Map); + node.set_tag(tag); + m_mapDepth++; + } + + void NodeBuilder::OnMapEnd() + { + assert(m_mapDepth > 0); + m_mapDepth--; + Pop(); + } + + detail::node& NodeBuilder::Push(anchor_t anchor) + { + detail::node& node = m_pMemory->create_node(); + RegisterAnchor(anchor, node); + Push(node); + return node; + } + + void NodeBuilder::Push(detail::node& node) + { + const bool needsKey = (!m_stack.empty() && m_stack.back()->type() == NodeType::Map && m_keys.size() < m_mapDepth); + + m_stack.push_back(&node); + if(needsKey) + m_keys.push_back(PushedKey(&node, false)); + } + + void NodeBuilder::Pop() + { + assert(!m_stack.empty()); + if(m_stack.size() == 1) { + m_pRoot = m_stack[0]; + m_stack.pop_back(); + return; + } + + detail::node& node = *m_stack.back(); + m_stack.pop_back(); + + detail::node& collection = *m_stack.back(); + + if(collection.type() == NodeType::Sequence) { + collection.push_back(node, m_pMemory); + } else if(collection.type() == NodeType::Map) { + assert(!m_keys.empty()); + PushedKey& key = m_keys.back(); + if(key.second) { + collection.insert(*key.first, node, m_pMemory); + m_keys.pop_back(); + } else { + key.second = true; + } + } else { + assert(false); + m_stack.clear(); + } + } + + void NodeBuilder::RegisterAnchor(anchor_t anchor, detail::node& node) + { + if(anchor) { + assert(anchor == m_anchors.size()); + m_anchors.push_back(&node); + } + } +} diff --git a/src/nodebuilder.h b/src/nodebuilder.h new file mode 100644 index 0000000..cce91d3 --- /dev/null +++ b/src/nodebuilder.h @@ -0,0 +1,58 @@ +#ifndef NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include "yaml-cpp/eventhandler.h" +#include "yaml-cpp/node/ptr.h" +#include + +namespace YAML +{ + class Node; + + class NodeBuilder: public EventHandler + { + public: + NodeBuilder(); + virtual ~NodeBuilder(); + + Node Root(); + + virtual void OnDocumentStart(const Mark& mark); + virtual void OnDocumentEnd(); + + virtual void OnNull(const Mark& mark, anchor_t anchor); + virtual void OnAlias(const Mark& mark, anchor_t anchor); + virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value); + + virtual void OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor); + virtual void OnSequenceEnd(); + + virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor); + virtual void OnMapEnd(); + + private: + detail::node& Push(anchor_t anchor); + void Push(detail::node& node); + void Pop(); + void RegisterAnchor(anchor_t anchor, detail::node& node); + + private: + detail::shared_memory_holder m_pMemory; + detail::node *m_pRoot; + + typedef std::vector Nodes; + Nodes m_stack; + Nodes m_anchors; + + typedef std::pair PushedKey; + std::vector m_keys; + std::size_t m_mapDepth; + }; +} + +#endif // NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + diff --git a/src/nodeevents.cpp b/src/nodeevents.cpp new file mode 100644 index 0000000..721f9c6 --- /dev/null +++ b/src/nodeevents.cpp @@ -0,0 +1,99 @@ +#include "nodeevents.h" +#include "yaml-cpp/node/node.h" +#include "yaml-cpp/node/impl.h" +#include "yaml-cpp/eventhandler.h" +#include "yaml-cpp/mark.h" + +namespace YAML +{ + void NodeEvents::AliasManager::RegisterReference(const detail::node& node) + { + m_anchorByIdentity.insert(std::make_pair(node.ref(), _CreateNewAnchor())); + } + + anchor_t NodeEvents::AliasManager::LookupAnchor(const detail::node& node) const + { + AnchorByIdentity::const_iterator it = m_anchorByIdentity.find(node.ref()); + if(it == m_anchorByIdentity.end()) + return 0; + return it->second; + } + + NodeEvents::NodeEvents(const Node& node): m_pMemory(node.m_pMemory), m_root(*node.m_pNode) + { + Setup(m_root); + } + + void NodeEvents::Setup(const detail::node& node) + { + int& refCount = m_refCount[node.ref()]; + refCount++; + if(refCount > 1) + return; + + if(node.type() == NodeType::Sequence) { + for(detail::const_node_iterator it=node.begin();it!=node.end();++it) + Setup(**it); + } else if(node.type() == NodeType::Map) { + for(detail::const_node_iterator it=node.begin();it!=node.end();++it) { + Setup(*it->first); + Setup(*it->second); + } + } + } + + void NodeEvents::Emit(EventHandler& handler) + { + AliasManager am; + + handler.OnDocumentStart(Mark()); + Emit(m_root, handler, am); + handler.OnDocumentEnd(); + } + + void NodeEvents::Emit(const detail::node& node, EventHandler& handler, AliasManager& am) const + { + anchor_t anchor = NullAnchor; + if(IsAliased(node)) { + anchor = am.LookupAnchor(node); + if(anchor) { + handler.OnAlias(Mark(), anchor); + return; + } + + am.RegisterReference(node); + anchor = am.LookupAnchor(node); + } + + switch(node.type()) { + case NodeType::Undefined: + break; + case NodeType::Null: + handler.OnNull(Mark(), anchor); + break; + case NodeType::Scalar: + handler.OnScalar(Mark(), node.tag(), anchor, node.scalar()); + break; + case NodeType::Sequence: + handler.OnSequenceStart(Mark(), node.tag(), anchor); + for(detail::const_node_iterator it=node.begin();it!=node.end();++it) + Emit(**it, handler, am); + handler.OnSequenceEnd(); + break; + case NodeType::Map: + handler.OnMapStart(Mark(), node.tag(), anchor); + for(detail::const_node_iterator it=node.begin();it!=node.end();++it) { + Emit(*it->first, handler, am); + Emit(*it->second, handler, am); + } + handler.OnMapEnd(); + break; + } + } + + bool NodeEvents::IsAliased(const detail::node& node) const + { + RefCount::const_iterator it = m_refCount.find(node.ref()); + return it != m_refCount.end() && it->second > 1; + } +} diff --git a/src/nodeevents.h b/src/nodeevents.h new file mode 100644 index 0000000..d142115 --- /dev/null +++ b/src/nodeevents.h @@ -0,0 +1,57 @@ +#ifndef NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include "yaml-cpp/anchor.h" +#include "yaml-cpp/node/ptr.h" +#include +#include + +namespace YAML +{ + class EventHandler; + class Node; + + class NodeEvents + { + public: + explicit NodeEvents(const Node& node); + + void Emit(EventHandler& handler); + + private: + class AliasManager { + public: + AliasManager(): m_curAnchor(0) {} + + void RegisterReference(const detail::node& node); + anchor_t LookupAnchor(const detail::node& node) const; + + private: + anchor_t _CreateNewAnchor() { return ++m_curAnchor; } + + private: + typedef std::map AnchorByIdentity; + AnchorByIdentity m_anchorByIdentity; + + anchor_t m_curAnchor; + }; + + void Setup(const detail::node& node); + void Emit(const detail::node& node, EventHandler& handler, AliasManager& am) const; + bool IsAliased(const detail::node& node) const; + + private: + detail::shared_memory_holder m_pMemory; + detail::node& m_root; + + typedef std::map RefCount; + RefCount m_refCount; + }; +} + +#endif // NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + diff --git a/src/parse.cpp b/src/parse.cpp new file mode 100644 index 0000000..3a33931 --- /dev/null +++ b/src/parse.cpp @@ -0,0 +1,64 @@ +#include "yaml-cpp/node/parse.h" +#include "yaml-cpp/node/node.h" +#include "yaml-cpp/node/impl.h" +#include "yaml-cpp/parser.h" +#include "nodebuilder.h" + +#include +#include + +namespace YAML +{ + Node Load(const std::string& input) { + std::stringstream stream(input); + return Load(stream); + } + + Node Load(const char *input) { + std::stringstream stream(input); + return Load(stream); + } + + Node Load(std::istream& input) { + Parser parser(input); + NodeBuilder builder; + if(!parser.HandleNextDocument(builder)) + return Node(); + + return builder.Root(); + } + + Node LoadFile(const std::string& filename) { + std::ifstream fin(filename.c_str()); + return Load(fin); + } + + std::vector LoadAll(const std::string& input) { + std::stringstream stream(input); + return LoadAll(stream); + } + + std::vector LoadAll(const char *input) { + std::stringstream stream(input); + return LoadAll(stream); + } + + std::vector LoadAll(std::istream& input) { + std::vector docs; + + Parser parser(input); + while(1) { + NodeBuilder builder; + if(!parser.HandleNextDocument(builder)) + break; + docs.push_back(builder.Root()); + } + + return docs; + } + + std::vector LoadAllFromFile(const std::string& filename) { + std::ifstream fin(filename.c_str()); + return LoadAll(fin); + } +} diff --git a/src/singledocparser.cpp b/src/singledocparser.cpp index 4cad59e..47759c3 100644 --- a/src/singledocparser.cpp +++ b/src/singledocparser.cpp @@ -253,7 +253,6 @@ namespace YAML throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP_FLOW); Token& token = m_scanner.peek(); - const Mark mark = token.mark; // first check for end if(token.type == Token::FLOW_MAP_END) { m_scanner.pop(); @@ -265,7 +264,7 @@ namespace YAML m_scanner.pop(); HandleNode(eventHandler); } else { - eventHandler.OnNull(mark, NullAnchor); + eventHandler.OnNull(token.mark, NullAnchor); } // now grab value (optional) @@ -273,7 +272,7 @@ namespace YAML m_scanner.pop(); HandleNode(eventHandler); } else { - eventHandler.OnNull(mark, NullAnchor); + eventHandler.OnNull(token.mark, NullAnchor); } // now eat the separator (or could be a map end, which we ignore - but if it's neither, then it's a bad node) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8ee63d0..98777be 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,8 +1,8 @@ file(GLOB test_headers [a-z]*.h) file(GLOB test_sources [a-z]*.cpp) -file(GLOB test_core_sources core/[a-z]*.cpp) +file(GLOB test_new_api_sources new-api/[a-z]*.cpp) -list(APPEND test_sources ${test_core_sources}) +list(APPEND test_sources ${test_new_api_sources}) include_directories(${YAML_CPP_SOURCE_DIR}/test) diff --git a/test/emittertests.cpp b/test/emittertests.cpp index 8da5b70..f16d25a 100644 --- a/test/emittertests.cpp +++ b/test/emittertests.cpp @@ -1,6 +1,5 @@ #include "tests.h" #include "yaml-cpp/yaml.h" -#include "yaml-cpp/eventhandler.h" #include namespace Test @@ -1000,21 +999,6 @@ namespace Test } namespace { - class NullEventHandler: public YAML::EventHandler { - virtual void OnDocumentStart(const YAML::Mark&) {} - virtual void OnDocumentEnd() {} - - virtual void OnNull(const YAML::Mark&, YAML::anchor_t) {} - virtual void OnAlias(const YAML::Mark&, YAML::anchor_t) {} - virtual void OnScalar(const YAML::Mark&, const std::string&, YAML::anchor_t, const std::string&) {} - - virtual void OnSequenceStart(const YAML::Mark&, const std::string&, YAML::anchor_t) {} - virtual void OnSequenceEnd() {} - - virtual void OnMapStart(const YAML::Mark&, const std::string&, YAML::anchor_t) {} - virtual void OnMapEnd() {} - }; - void RunEmitterTest(void (*test)(YAML::Emitter&, std::string&), const std::string& name, int& passed, int& total) { YAML::Emitter out; std::string desiredOutput; @@ -1024,10 +1008,7 @@ namespace Test if(output == desiredOutput) { try { - std::stringstream stream(output); - YAML::Parser parser; - NullEventHandler handler; - parser.HandleNextDocument(handler); + YAML::Node node = YAML::Load(output); passed++; } catch(const YAML::Exception& e) { std::cout << "Emitter test failed: " << name << "\n"; diff --git a/test/new-api/nodetests.cpp b/test/new-api/nodetests.cpp new file mode 100644 index 0000000..ee40110 --- /dev/null +++ b/test/new-api/nodetests.cpp @@ -0,0 +1,433 @@ +#include "nodetests.h" +#include "yaml-cpp/yaml.h" +#include +#include + +namespace { + struct TEST { + TEST(): ok(false) {} + TEST(bool ok_): ok(ok_) {} + TEST(const char *error_): ok(false), error(error_) {} + + bool ok; + std::string error; + }; +} + +#define YAML_ASSERT(cond) do { if(!(cond)) return " Assert failed: " #cond; } while(false) + +#define YAML_ASSERT_THROWS(cond, exc) do { try { (cond); return " Expression did not throw: " #cond; } catch(const exc&) {} catch(...) { return " Expression threw something other than " #exc ": " #cond; } } while(false) + +namespace Test +{ + namespace Node + { + TEST SimpleScalar() + { + YAML::Node node = YAML::Node("Hello, World!"); + YAML_ASSERT(node.IsScalar()); + YAML_ASSERT(node.as() == "Hello, World!"); + return true; + } + + TEST IntScalar() + { + YAML::Node node = YAML::Node(15); + YAML_ASSERT(node.IsScalar()); + YAML_ASSERT(node.as() == 15); + return true; + } + + TEST SimpleAppendSequence() + { + YAML::Node node; + node.push_back(10); + node.push_back("foo"); + node.push_back("monkey"); + YAML_ASSERT(node.IsSequence()); + YAML_ASSERT(node.size() == 3); + YAML_ASSERT(node[0].as() == 10); + YAML_ASSERT(node[1].as() == "foo"); + YAML_ASSERT(node[2].as() == "monkey"); + YAML_ASSERT(node.IsSequence()); + return true; + } + + TEST SimpleAssignSequence() + { + YAML::Node node; + node[0] = 10; + node[1] = "foo"; + node[2] = "monkey"; + YAML_ASSERT(node.IsSequence()); + YAML_ASSERT(node.size() == 3); + YAML_ASSERT(node[0].as() == 10); + YAML_ASSERT(node[1].as() == "foo"); + YAML_ASSERT(node[2].as() == "monkey"); + YAML_ASSERT(node.IsSequence()); + return true; + } + + TEST SimpleMap() + { + YAML::Node node; + node["key"] = "value"; + YAML_ASSERT(node.IsMap()); + YAML_ASSERT(node["key"].as() == "value"); + YAML_ASSERT(node.size() == 1); + return true; + } + + TEST MapWithUndefinedValues() + { + YAML::Node node; + node["key"] = "value"; + node["undefined"]; + YAML_ASSERT(node.IsMap()); + YAML_ASSERT(node["key"].as() == "value"); + YAML_ASSERT(node.size() == 1); + + node["undefined"] = "monkey"; + YAML_ASSERT(node["undefined"].as() == "monkey"); + YAML_ASSERT(node.size() == 2); + + return true; + } + + TEST MapIteratorWithUndefinedValues() + { + YAML::Node node; + node["key"] = "value"; + node["undefined"]; + + std::size_t count = 0; + for(YAML::const_iterator it=node.begin();it!=node.end();++it) + count++; + YAML_ASSERT(count == 1); + return true; + } + + TEST SimpleSubkeys() + { + YAML::Node node; + node["device"]["udid"] = "12345"; + node["device"]["name"] = "iPhone"; + node["device"]["os"] = "4.0"; + node["username"] = "monkey"; + YAML_ASSERT(node["device"]["udid"].as() == "12345"); + YAML_ASSERT(node["device"]["name"].as() == "iPhone"); + YAML_ASSERT(node["device"]["os"].as() == "4.0"); + YAML_ASSERT(node["username"].as() == "monkey"); + return true; + } + + TEST StdVector() + { + std::vector primes; + primes.push_back(2); + primes.push_back(3); + primes.push_back(5); + primes.push_back(7); + primes.push_back(11); + primes.push_back(13); + + YAML::Node node; + node["primes"] = primes; + YAML_ASSERT(node["primes"].as >() == primes); + return true; + } + + TEST StdList() + { + std::list primes; + primes.push_back(2); + primes.push_back(3); + primes.push_back(5); + primes.push_back(7); + primes.push_back(11); + primes.push_back(13); + + YAML::Node node; + node["primes"] = primes; + YAML_ASSERT(node["primes"].as >() == primes); + return true; + } + + TEST StdMap() + { + std::map squares; + squares[0] = 0; + squares[1] = 1; + squares[2] = 4; + squares[3] = 9; + squares[4] = 16; + + YAML::Node node; + node["squares"] = squares; + YAML_ASSERT((node["squares"].as >() == squares)); + return true; + } + + TEST SimpleAlias() + { + YAML::Node node; + node["foo"] = "value"; + node["bar"] = node["foo"]; + YAML_ASSERT(node["foo"].as() == "value"); + YAML_ASSERT(node["bar"].as() == "value"); + YAML_ASSERT(node["foo"] == node["bar"]); + YAML_ASSERT(node.size() == 2); + return true; + } + + TEST AliasAsKey() + { + YAML::Node node; + node["foo"] = "value"; + YAML::Node value = node["foo"]; + node[value] = "foo"; + YAML_ASSERT(node["foo"].as() == "value"); + YAML_ASSERT(node[value].as() == "foo"); + YAML_ASSERT(node["value"].as() == "foo"); + YAML_ASSERT(node.size() == 2); + return true; + } + + TEST SelfReferenceSequence() + { + YAML::Node node; + node[0] = node; + YAML_ASSERT(node.IsSequence()); + YAML_ASSERT(node.size() == 1); + YAML_ASSERT(node[0] == node); + YAML_ASSERT(node[0][0] == node); + YAML_ASSERT(node[0][0] == node[0]); + return true; + } + + TEST ValueSelfReferenceMap() + { + YAML::Node node; + node["key"] = node; + YAML_ASSERT(node.IsMap()); + YAML_ASSERT(node.size() == 1); + YAML_ASSERT(node["key"] == node); + YAML_ASSERT(node["key"]["key"] == node); + YAML_ASSERT(node["key"]["key"] == node["key"]); + return true; + } + + TEST KeySelfReferenceMap() + { + YAML::Node node; + node[node] = "value"; + YAML_ASSERT(node.IsMap()); + YAML_ASSERT(node.size() == 1); + YAML_ASSERT(node[node].as() == "value"); + return true; + } + + TEST SelfReferenceMap() + { + YAML::Node node; + node[node] = node; + YAML_ASSERT(node.IsMap()); + YAML_ASSERT(node.size() == 1); + YAML_ASSERT(node[node] == node); + YAML_ASSERT(node[node][node] == node); + YAML_ASSERT(node[node][node] == node[node]); + return true; + } + + TEST TempMapVariable() + { + YAML::Node node; + YAML::Node tmp = node["key"]; + tmp = "value"; + YAML_ASSERT(node.IsMap()); + YAML_ASSERT(node.size() == 1); + YAML_ASSERT(node["key"].as() == "value"); + return true; + } + + TEST TempMapVariableAlias() + { + YAML::Node node; + YAML::Node tmp = node["key"]; + tmp = node["other"]; + node["other"] = "value"; + YAML_ASSERT(node.IsMap()); + YAML_ASSERT(node.size() == 2); + YAML_ASSERT(node["key"].as() == "value"); + YAML_ASSERT(node["other"].as() == "value"); + YAML_ASSERT(node["other"] == node["key"]); + return true; + } + + TEST Bool() + { + YAML::Node node; + node[true] = false; + YAML_ASSERT(node.IsMap()); + YAML_ASSERT(node[true].as() == false); + return true; + } + + TEST AutoBoolConversion() + { + YAML::Node node; + node["foo"] = "bar"; + YAML_ASSERT(static_cast(node["foo"])); + YAML_ASSERT(!node["monkey"]); + YAML_ASSERT(!!node["foo"]); + return true; + } + + TEST Reassign() + { + YAML::Node node = YAML::Load("foo"); + node = YAML::Node(); + return true; + } + + TEST FallbackValues() + { + YAML::Node node = YAML::Load("foo: bar\nx: 2"); + YAML_ASSERT(node["foo"].as() == "bar"); + YAML_ASSERT(node["foo"].as("hello") == "bar"); + YAML_ASSERT(node["baz"].as("hello") == "hello"); + YAML_ASSERT(node["x"].as() == 2); + YAML_ASSERT(node["x"].as(5) == 2); + YAML_ASSERT(node["y"].as(5) == 5); + return true; + } + + TEST NumericConversion() + { + YAML::Node node = YAML::Load("[1.5, 1, .nan, .inf, -.inf, 0x15, 015]"); + YAML_ASSERT(node[0].as() == 1.5f); + YAML_ASSERT(node[0].as() == 1.5); + YAML_ASSERT_THROWS(node[0].as(), std::runtime_error); + YAML_ASSERT(node[1].as() == 1); + YAML_ASSERT(node[1].as() == 1.0f); + YAML_ASSERT(node[2].as() != node[2].as()); + YAML_ASSERT(node[3].as() == std::numeric_limits::infinity()); + YAML_ASSERT(node[4].as() == -std::numeric_limits::infinity()); + YAML_ASSERT(node[5].as() == 21); + YAML_ASSERT(node[6].as() == 13); + return true; + } + + TEST Binary() + { + YAML::Node node = YAML::Load("[!!binary \"SGVsbG8sIFdvcmxkIQ==\", !!binary \"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4K\"]"); + YAML_ASSERT(node[0].as() == YAML::Binary(reinterpret_cast("Hello, World!"), 13)); + YAML_ASSERT(node[1].as() == YAML::Binary(reinterpret_cast("Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.\n"), 270)); + return true; + } + + TEST IterateSequence() + { + YAML::Node node = YAML::Load("[1, 3, 5, 7]"); + int seq[] = {1, 3, 5, 7}; + int i=0; + for(YAML::const_iterator it=node.begin();it!=node.end();++it) { + YAML_ASSERT(i < 4); + int x = seq[i++]; + YAML_ASSERT(it->as() == x); + } + YAML_ASSERT(i == 4); + return true; + } + + TEST IterateMap() + { + YAML::Node node = YAML::Load("{a: A, b: B, c: C}"); + int i=0; + for(YAML::const_iterator it=node.begin();it!=node.end();++it) { + YAML_ASSERT(i < 3); + i++; + YAML_ASSERT(it->first.as() + 'A' - 'a' == it->second.as()); + } + YAML_ASSERT(i == 3); + return true; + } + + TEST ForEach() + { + YAML::Node node = YAML::Load("[1, 3, 5, 7]"); + int seq[] = {1, 3, 5, 7}; + int i = 0; + BOOST_FOREACH(const YAML::Node &item, node) { + int x = seq[i++]; + YAML_ASSERT(item.as() == x); + } + return true; + } + + TEST ForEachMap() + { + YAML::Node node = YAML::Load("{a: A, b: B, c: C}"); + BOOST_FOREACH(const YAML::const_iterator::value_type &p, node) { + YAML_ASSERT(p.first.as() + 'A' - 'a' == p.second.as()); + } + return true; + } + } + + void RunNodeTest(TEST (*test)(), const std::string& name, int& passed, int& total) { + TEST ret; + try { + ret = test(); + } catch(...) { + ret.ok = false; + } + if(ret.ok) { + passed++; + } else { + std::cout << "Node test failed: " << name << "\n"; + if(ret.error != "") + std::cout << ret.error << "\n"; + } + total++; + } + + bool RunNodeTests() + { + int passed = 0; + int total = 0; + + RunNodeTest(&Node::SimpleScalar, "simple scalar", passed, total); + RunNodeTest(&Node::IntScalar, "int scalar", passed, total); + RunNodeTest(&Node::SimpleAppendSequence, "simple append sequence", passed, total); + RunNodeTest(&Node::SimpleAssignSequence, "simple assign sequence", passed, total); + RunNodeTest(&Node::SimpleMap, "simple map", passed, total); + RunNodeTest(&Node::MapWithUndefinedValues, "map with undefined values", passed, total); + RunNodeTest(&Node::MapIteratorWithUndefinedValues, "map iterator with undefined values", passed, total); + RunNodeTest(&Node::SimpleSubkeys, "simple subkey", passed, total); + RunNodeTest(&Node::StdVector, "std::vector", passed, total); + RunNodeTest(&Node::StdList, "std::list", passed, total); + RunNodeTest(&Node::StdMap, "std::map", passed, total); + RunNodeTest(&Node::SimpleAlias, "simple alias", passed, total); + RunNodeTest(&Node::AliasAsKey, "alias as key", passed, total); + RunNodeTest(&Node::SelfReferenceSequence, "self reference sequence", passed, total); + RunNodeTest(&Node::ValueSelfReferenceMap, "value self reference map", passed, total); + RunNodeTest(&Node::KeySelfReferenceMap, "key self reference map", passed, total); + RunNodeTest(&Node::SelfReferenceMap, "self reference map", passed, total); + RunNodeTest(&Node::TempMapVariable, "temp map variable", passed, total); + RunNodeTest(&Node::TempMapVariableAlias, "temp map variable alias", passed, total); + RunNodeTest(&Node::Bool, "bool", passed, total); + RunNodeTest(&Node::AutoBoolConversion, "auto bool conversion", passed, total); + RunNodeTest(&Node::Reassign, "reassign", passed, total); + RunNodeTest(&Node::FallbackValues, "fallback values", passed, total); + RunNodeTest(&Node::NumericConversion, "numeric conversion", passed, total); + RunNodeTest(&Node::Binary, "binary", passed, total); + RunNodeTest(&Node::IterateSequence, "iterate sequence", passed, total); + RunNodeTest(&Node::IterateMap, "iterate map", passed, total); + RunNodeTest(&Node::ForEach, "for each", passed, total); + RunNodeTest(&Node::ForEachMap, "for each map", passed, total); + + std::cout << "Node tests: " << passed << "/" << total << " passed\n"; + return passed == total; + } +} diff --git a/test/new-api/parsertests.cpp b/test/new-api/parsertests.cpp new file mode 100644 index 0000000..1d50ca6 --- /dev/null +++ b/test/new-api/parsertests.cpp @@ -0,0 +1,8 @@ +#include "parsertests.h" + +namespace Test { + bool RunParserTests() + { + return true; + } +} diff --git a/test/new-api/spectests.cpp b/test/new-api/spectests.cpp new file mode 100644 index 0000000..328ae7a --- /dev/null +++ b/test/new-api/spectests.cpp @@ -0,0 +1,1365 @@ +#include "spectests.h" +#include "specexamples.h" +#include "yaml-cpp/yaml.h" +#include + +#define YAML_ASSERT(cond) do { if(!(cond)) return " Assert failed: " #cond; } while(false) + +namespace Test +{ + namespace Spec + { + // 2.1 + TEST SeqScalars() { + YAML::Node doc = YAML::Load(ex2_1); + YAML_ASSERT(doc.IsSequence()); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc[0].as() == "Mark McGwire"); + YAML_ASSERT(doc[1].as() == "Sammy Sosa"); + YAML_ASSERT(doc[2].as() == "Ken Griffey"); + return true; + } + + // 2.2 + TEST MappingScalarsToScalars() { + YAML::Node doc = YAML::Load(ex2_2); + YAML_ASSERT(doc.IsMap()); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["hr"].as() == "65"); + YAML_ASSERT(doc["avg"].as() == "0.278"); + YAML_ASSERT(doc["rbi"].as() == "147"); + return true; + } + + // 2.3 + TEST MappingScalarsToSequences() { + YAML::Node doc = YAML::Load(ex2_3); + YAML_ASSERT(doc.IsMap()); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["american"].size() == 3); + YAML_ASSERT(doc["american"][0].as() == "Boston Red Sox"); + YAML_ASSERT(doc["american"][1].as() == "Detroit Tigers"); + YAML_ASSERT(doc["american"][2].as() == "New York Yankees"); + YAML_ASSERT(doc["national"].size() == 3); + YAML_ASSERT(doc["national"][0].as() == "New York Mets"); + YAML_ASSERT(doc["national"][1].as() == "Chicago Cubs"); + YAML_ASSERT(doc["national"][2].as() == "Atlanta Braves"); + return true; + } + + // 2.4 + TEST SequenceOfMappings() { + YAML::Node doc = YAML::Load(ex2_4); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc[0].size() == 3); + YAML_ASSERT(doc[0]["name"].as() == "Mark McGwire"); + YAML_ASSERT(doc[0]["hr"].as() == "65"); + YAML_ASSERT(doc[0]["avg"].as() == "0.278"); + YAML_ASSERT(doc[1].size() == 3); + YAML_ASSERT(doc[1]["name"].as() == "Sammy Sosa"); + YAML_ASSERT(doc[1]["hr"].as() == "63"); + YAML_ASSERT(doc[1]["avg"].as() == "0.288"); + return true; + } + + // 2.5 + TEST SequenceOfSequences() { + YAML::Node doc = YAML::Load(ex2_5); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc[0].size() == 3); + YAML_ASSERT(doc[0][0].as() == "name"); + YAML_ASSERT(doc[0][1].as() == "hr"); + YAML_ASSERT(doc[0][2].as() == "avg"); + YAML_ASSERT(doc[1].size() == 3); + YAML_ASSERT(doc[1][0].as() == "Mark McGwire"); + YAML_ASSERT(doc[1][1].as() == "65"); + YAML_ASSERT(doc[1][2].as() == "0.278"); + YAML_ASSERT(doc[2].size() == 3); + YAML_ASSERT(doc[2][0].as() == "Sammy Sosa"); + YAML_ASSERT(doc[2][1].as() == "63"); + YAML_ASSERT(doc[2][2].as() == "0.288"); + return true; + } + + // 2.6 + TEST MappingOfMappings() { + YAML::Node doc = YAML::Load(ex2_6); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["Mark McGwire"].size() == 2); + YAML_ASSERT(doc["Mark McGwire"]["hr"].as() == "65"); + YAML_ASSERT(doc["Mark McGwire"]["avg"].as() == "0.278"); + YAML_ASSERT(doc["Sammy Sosa"].size() == 2); + YAML_ASSERT(doc["Sammy Sosa"]["hr"].as() == "63"); + YAML_ASSERT(doc["Sammy Sosa"]["avg"].as() == "0.288"); + return true; + } + + // 2.7 + TEST TwoDocumentsInAStream() { + std::vector docs = YAML::LoadAll(ex2_7); + YAML_ASSERT(docs.size() == 2); + + { + YAML::Node doc = docs[0]; + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc[0].as() == "Mark McGwire"); + YAML_ASSERT(doc[1].as() == "Sammy Sosa"); + YAML_ASSERT(doc[2].as() == "Ken Griffey"); + } + + { + YAML::Node doc = docs[1]; + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc[0].as() == "Chicago Cubs"); + YAML_ASSERT(doc[1].as() == "St Louis Cardinals"); + } + return true; + } + + // 2.8 + TEST PlayByPlayFeed() { + std::vector docs = YAML::LoadAll(ex2_8); + YAML_ASSERT(docs.size() == 2); + + { + YAML::Node doc = docs[0]; + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["time"].as() == "20:03:20"); + YAML_ASSERT(doc["player"].as() == "Sammy Sosa"); + YAML_ASSERT(doc["action"].as() == "strike (miss)"); + } + + { + YAML::Node doc = docs[1]; + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["time"].as() == "20:03:47"); + YAML_ASSERT(doc["player"].as() == "Sammy Sosa"); + YAML_ASSERT(doc["action"].as() == "grand slam"); + } + return true; + } + + // 2.9 + TEST SingleDocumentWithTwoComments() { + YAML::Node doc = YAML::Load(ex2_9); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["hr"].size() == 2); + YAML_ASSERT(doc["hr"][0].as() == "Mark McGwire"); + YAML_ASSERT(doc["hr"][1].as() == "Sammy Sosa"); + YAML_ASSERT(doc["rbi"].size() == 2); + YAML_ASSERT(doc["rbi"][0].as() == "Sammy Sosa"); + YAML_ASSERT(doc["rbi"][1].as() == "Ken Griffey"); + return true; + } + + // 2.10 + TEST SimpleAnchor() { + YAML::Node doc = YAML::Load(ex2_10); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["hr"].size() == 2); + YAML_ASSERT(doc["hr"][0].as() == "Mark McGwire"); + YAML_ASSERT(doc["hr"][1].as() == "Sammy Sosa"); + YAML_ASSERT(doc["rbi"].size() == 2); + YAML_ASSERT(doc["rbi"][0].as() == "Sammy Sosa"); + YAML_ASSERT(doc["rbi"][1].as() == "Ken Griffey"); + return true; + } + + // 2.11 + TEST MappingBetweenSequences() { + YAML::Node doc = YAML::Load(ex2_11); + + std::vector tigers_cubs; + tigers_cubs.push_back("Detroit Tigers"); + tigers_cubs.push_back("Chicago cubs"); + + std::vector yankees_braves; + yankees_braves.push_back("New York Yankees"); + yankees_braves.push_back("Atlanta Braves"); + + + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc[tigers_cubs].size() == 1); + YAML_ASSERT(doc[tigers_cubs][0].as() == "2001-07-23"); + YAML_ASSERT(doc[yankees_braves].size() == 3); + YAML_ASSERT(doc[yankees_braves][0].as() == "2001-07-02"); + YAML_ASSERT(doc[yankees_braves][1].as() == "2001-08-12"); + YAML_ASSERT(doc[yankees_braves][2].as() == "2001-08-14"); + return true; + } + + // 2.12 + TEST CompactNestedMapping() { + YAML::Node doc = YAML::Load(ex2_12); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc[0].size() == 2); + YAML_ASSERT(doc[0]["item"].as() == "Super Hoop"); + YAML_ASSERT(doc[0]["quantity"].as() == 1); + YAML_ASSERT(doc[1].size() == 2); + YAML_ASSERT(doc[1]["item"].as() == "Basketball"); + YAML_ASSERT(doc[1]["quantity"].as() == 4); + YAML_ASSERT(doc[2].size() == 2); + YAML_ASSERT(doc[2]["item"].as() == "Big Shoes"); + YAML_ASSERT(doc[2]["quantity"].as() == 1); + return true; + } + + // 2.13 + TEST InLiteralsNewlinesArePreserved() { + YAML::Node doc = YAML::Load(ex2_13); + YAML_ASSERT(doc.as() == + "\\//||\\/||\n" + "// || ||__"); + return true; + } + + // 2.14 + TEST InFoldedScalarsNewlinesBecomeSpaces() { + YAML::Node doc = YAML::Load(ex2_14); + YAML_ASSERT(doc.as() == "Mark McGwire's year was crippled by a knee injury."); + return true; + } + + // 2.15 + TEST FoldedNewlinesArePreservedForMoreIndentedAndBlankLines() { + YAML::Node doc = YAML::Load(ex2_15); + YAML_ASSERT(doc.as() == + "Sammy Sosa completed another fine season with great stats.\n\n" + " 63 Home Runs\n" + " 0.288 Batting Average\n\n" + "What a year!"); + return true; + } + + // 2.16 + TEST IndentationDeterminesScope() { + YAML::Node doc = YAML::Load(ex2_16); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["name"].as() == "Mark McGwire"); + YAML_ASSERT(doc["accomplishment"].as() == "Mark set a major league home run record in 1998.\n"); + YAML_ASSERT(doc["stats"].as() == "65 Home Runs\n0.278 Batting Average\n"); + return true; + } + + // 2.17 + TEST QuotedScalars() { + YAML::Node doc = YAML::Load(ex2_17); + YAML_ASSERT(doc.size() == 6); + YAML_ASSERT(doc["unicode"].as() == "Sosa did fine.\xe2\x98\xba"); + YAML_ASSERT(doc["control"].as() == "\b1998\t1999\t2000\n"); + YAML_ASSERT(doc["hex esc"].as() == "\x0d\x0a is \r\n"); + YAML_ASSERT(doc["single"].as() == "\"Howdy!\" he cried."); + YAML_ASSERT(doc["quoted"].as() == " # Not a 'comment'."); + YAML_ASSERT(doc["tie-fighter"].as() == "|\\-*-/|"); + return true; + } + + // 2.18 + TEST MultiLineFlowScalars() { + YAML::Node doc = YAML::Load(ex2_18); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["plain"].as() == "This unquoted scalar spans many lines."); + YAML_ASSERT(doc["quoted"].as() == "So does this quoted scalar.\n"); + return true; + } + + // TODO: 2.19 - 2.22 schema tags + + // 2.23 + TEST VariousExplicitTags() { + YAML::Node doc = YAML::Load(ex2_23); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["not-date"].Tag() == "tag:yaml.org,2002:str"); + YAML_ASSERT(doc["not-date"].as() == "2002-04-28"); + YAML_ASSERT(doc["picture"].Tag() == "tag:yaml.org,2002:binary"); + YAML_ASSERT(doc["picture"].as() == + "R0lGODlhDAAMAIQAAP//9/X\n" + "17unp5WZmZgAAAOfn515eXv\n" + "Pz7Y6OjuDg4J+fn5OTk6enp\n" + "56enmleECcgggoBADs=\n" + ); + YAML_ASSERT(doc["application specific tag"].Tag() == "!something"); + YAML_ASSERT(doc["application specific tag"].as() == + "The semantics of the tag\n" + "above may be different for\n" + "different documents." + ); + return true; + } + + // 2.24 + TEST GlobalTags() { + YAML::Node doc = YAML::Load(ex2_24); + YAML_ASSERT(doc.Tag() == "tag:clarkevans.com,2002:shape"); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc[0].Tag() == "tag:clarkevans.com,2002:circle"); + YAML_ASSERT(doc[0].size() == 2); + YAML_ASSERT(doc[0]["center"].size() == 2); + YAML_ASSERT(doc[0]["center"]["x"].as() == 73); + YAML_ASSERT(doc[0]["center"]["y"].as() == 129); + YAML_ASSERT(doc[0]["radius"].as() == 7); + YAML_ASSERT(doc[1].Tag() == "tag:clarkevans.com,2002:line"); + YAML_ASSERT(doc[1].size() == 2); + YAML_ASSERT(doc[1]["start"].size() == 2); + YAML_ASSERT(doc[1]["start"]["x"].as() == 73); + YAML_ASSERT(doc[1]["start"]["y"].as() == 129); + YAML_ASSERT(doc[1]["finish"].size() == 2); + YAML_ASSERT(doc[1]["finish"]["x"].as() == 89); + YAML_ASSERT(doc[1]["finish"]["y"].as() == 102); + YAML_ASSERT(doc[2].Tag() == "tag:clarkevans.com,2002:label"); + YAML_ASSERT(doc[2].size() == 3); + YAML_ASSERT(doc[2]["start"].size() == 2); + YAML_ASSERT(doc[2]["start"]["x"].as() == 73); + YAML_ASSERT(doc[2]["start"]["y"].as() == 129); + YAML_ASSERT(doc[2]["color"].as() == "0xFFEEBB"); + YAML_ASSERT(doc[2]["text"].as() == "Pretty vector drawing."); + return true; + } + + // 2.25 + TEST UnorderedSets() { + YAML::Node doc = YAML::Load(ex2_25); + YAML_ASSERT(doc.Tag() == "tag:yaml.org,2002:set"); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["Mark McGwire"].IsNull()); + YAML_ASSERT(doc["Sammy Sosa"].IsNull()); + YAML_ASSERT(doc["Ken Griffey"].IsNull()); + return true; + } + + // 2.26 + TEST OrderedMappings() { + YAML::Node doc = YAML::Load(ex2_26); + YAML_ASSERT(doc.Tag() == "tag:yaml.org,2002:omap"); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc[0].size() == 1); + YAML_ASSERT(doc[0]["Mark McGwire"].as() == 65); + YAML_ASSERT(doc[1].size() == 1); + YAML_ASSERT(doc[1]["Sammy Sosa"].as() == 63); + YAML_ASSERT(doc[2].size() == 1); + YAML_ASSERT(doc[2]["Ken Griffey"].as() == 58); + return true; + } + + // 2.27 + TEST Invoice() { + YAML::Node doc = YAML::Load(ex2_27); + YAML_ASSERT(doc.Tag() == "tag:clarkevans.com,2002:invoice"); + YAML_ASSERT(doc.size() == 8); + YAML_ASSERT(doc["invoice"].as() == 34843); + YAML_ASSERT(doc["date"].as() == "2001-01-23"); + YAML_ASSERT(doc["bill-to"].size() == 3); + YAML_ASSERT(doc["bill-to"]["given"].as() == "Chris"); + YAML_ASSERT(doc["bill-to"]["family"].as() == "Dumars"); + YAML_ASSERT(doc["bill-to"]["address"].size() == 4); + YAML_ASSERT(doc["bill-to"]["address"]["lines"].as() == "458 Walkman Dr.\nSuite #292\n"); + YAML_ASSERT(doc["bill-to"]["address"]["city"].as() == "Royal Oak"); + YAML_ASSERT(doc["bill-to"]["address"]["state"].as() == "MI"); + YAML_ASSERT(doc["bill-to"]["address"]["postal"].as() == "48046"); + YAML_ASSERT(doc["ship-to"].size() == 3); + YAML_ASSERT(doc["ship-to"]["given"].as() == "Chris"); + YAML_ASSERT(doc["ship-to"]["family"].as() == "Dumars"); + YAML_ASSERT(doc["ship-to"]["address"].size() == 4); + YAML_ASSERT(doc["ship-to"]["address"]["lines"].as() == "458 Walkman Dr.\nSuite #292\n"); + YAML_ASSERT(doc["ship-to"]["address"]["city"].as() == "Royal Oak"); + YAML_ASSERT(doc["ship-to"]["address"]["state"].as() == "MI"); + YAML_ASSERT(doc["ship-to"]["address"]["postal"].as() == "48046"); + YAML_ASSERT(doc["product"].size() == 2); + YAML_ASSERT(doc["product"][0].size() == 4); + YAML_ASSERT(doc["product"][0]["sku"].as() == "BL394D"); + YAML_ASSERT(doc["product"][0]["quantity"].as() == 4); + YAML_ASSERT(doc["product"][0]["description"].as() == "Basketball"); + YAML_ASSERT(doc["product"][0]["price"].as() == "450.00"); + YAML_ASSERT(doc["product"][1].size() == 4); + YAML_ASSERT(doc["product"][1]["sku"].as() == "BL4438H"); + YAML_ASSERT(doc["product"][1]["quantity"].as() == 1); + YAML_ASSERT(doc["product"][1]["description"].as() == "Super Hoop"); + YAML_ASSERT(doc["product"][1]["price"].as() == "2392.00"); + YAML_ASSERT(doc["tax"].as() == "251.42"); + YAML_ASSERT(doc["total"].as() == "4443.52"); + YAML_ASSERT(doc["comments"].as() == "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338."); + return true; + } + + // 2.28 + TEST LogFile() { + std::vector docs = YAML::LoadAll(ex2_28); + YAML_ASSERT(docs.size() == 3); + + { + YAML::Node doc = docs[0]; + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["Time"].as() == "2001-11-23 15:01:42 -5"); + YAML_ASSERT(doc["User"].as() == "ed"); + YAML_ASSERT(doc["Warning"].as() == "This is an error message for the log file"); + } + + { + YAML::Node doc = docs[1]; + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["Time"].as() == "2001-11-23 15:02:31 -5"); + YAML_ASSERT(doc["User"].as() == "ed"); + YAML_ASSERT(doc["Warning"].as() == "A slightly different error message."); + } + + { + YAML::Node doc = docs[2]; + YAML_ASSERT(doc.size() == 4); + YAML_ASSERT(doc["Date"].as() == "2001-11-23 15:03:17 -5"); + YAML_ASSERT(doc["User"].as() == "ed"); + YAML_ASSERT(doc["Fatal"].as() == "Unknown variable \"bar\""); + YAML_ASSERT(doc["Stack"].size() == 2); + YAML_ASSERT(doc["Stack"][0].size() == 3); + YAML_ASSERT(doc["Stack"][0]["file"].as() == "TopClass.py"); + YAML_ASSERT(doc["Stack"][0]["line"].as() == "23"); + YAML_ASSERT(doc["Stack"][0]["code"].as() == "x = MoreObject(\"345\\n\")\n"); + YAML_ASSERT(doc["Stack"][1].size() == 3); + YAML_ASSERT(doc["Stack"][1]["file"].as() == "MoreClass.py"); + YAML_ASSERT(doc["Stack"][1]["line"].as() == "58"); + YAML_ASSERT(doc["Stack"][1]["code"].as() == "foo = bar"); + } + return true; + } + + // TODO: 5.1 - 5.2 BOM + + // 5.3 + TEST BlockStructureIndicators() { + YAML::Node doc = YAML::Load(ex5_3); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["sequence"].size() == 2); + YAML_ASSERT(doc["sequence"][0].as() == "one"); + YAML_ASSERT(doc["sequence"][1].as() == "two"); + YAML_ASSERT(doc["mapping"].size() == 2); + YAML_ASSERT(doc["mapping"]["sky"].as() == "blue"); + YAML_ASSERT(doc["mapping"]["sea"].as() == "green"); + return true; + } + + // 5.4 + TEST FlowStructureIndicators() { + YAML::Node doc = YAML::Load(ex5_4); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["sequence"].size() == 2); + YAML_ASSERT(doc["sequence"][0].as() == "one"); + YAML_ASSERT(doc["sequence"][1].as() == "two"); + YAML_ASSERT(doc["mapping"].size() == 2); + YAML_ASSERT(doc["mapping"]["sky"].as() == "blue"); + YAML_ASSERT(doc["mapping"]["sea"].as() == "green"); + return true; + } + + // 5.5 + TEST CommentIndicator() { + YAML::Node doc = YAML::Load(ex5_5); + YAML_ASSERT(doc.IsNull()); + return true; + } + + // 5.6 + TEST NodePropertyIndicators() { + YAML::Node doc = YAML::Load(ex5_6); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["anchored"].as() == "value"); // TODO: assert tag + YAML_ASSERT(doc["alias"].as() == "value"); + return true; + } + + // 5.7 + TEST BlockScalarIndicators() { + YAML::Node doc = YAML::Load(ex5_7); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["literal"].as() == "some\ntext\n"); + YAML_ASSERT(doc["folded"].as() == "some text\n"); + return true; + } + + // 5.8 + TEST QuotedScalarIndicators() { + YAML::Node doc = YAML::Load(ex5_8); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["single"].as() == "text"); + YAML_ASSERT(doc["double"].as() == "text"); + return true; + } + + // TODO: 5.9 directive + // TODO: 5.10 reserved indicator + + // 5.11 + TEST LineBreakCharacters() { + YAML::Node doc = YAML::Load(ex5_11); + YAML_ASSERT(doc.as() == "Line break (no glyph)\nLine break (glyphed)\n"); + return true; + } + + // 5.12 + TEST TabsAndSpaces() { + YAML::Node doc = YAML::Load(ex5_12); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["quoted"].as() == "Quoted\t"); + YAML_ASSERT(doc["block"].as() == + "void main() {\n" + "\tprintf(\"Hello, world!\\n\");\n" + "}"); + return true; + } + + // 5.13 + TEST EscapedCharacters() { + YAML::Node doc = YAML::Load(ex5_13); + YAML_ASSERT(doc.as() == "Fun with \x5C \x22 \x07 \x08 \x1B \x0C \x0A \x0D \x09 \x0B " + std::string("\x00", 1) + " \x20 \xA0 \x85 \xe2\x80\xa8 \xe2\x80\xa9 A A A"); + return true; + } + + // 5.14 + TEST InvalidEscapedCharacters() { + try { + YAML::Load(ex5_14); + } catch(const YAML::ParserException& e) { + YAML_ASSERT(e.msg == std::string(YAML::ErrorMsg::INVALID_ESCAPE) + "c"); + return true; + } + + return false; + } + + // 6.1 + TEST IndentationSpaces() { + YAML::Node doc = YAML::Load(ex6_1); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc["Not indented"].size() == 2); + YAML_ASSERT(doc["Not indented"]["By one space"].as() == "By four\n spaces\n"); + YAML_ASSERT(doc["Not indented"]["Flow style"].size() == 3); + YAML_ASSERT(doc["Not indented"]["Flow style"][0].as() == "By two"); + YAML_ASSERT(doc["Not indented"]["Flow style"][1].as() == "Also by two"); + YAML_ASSERT(doc["Not indented"]["Flow style"][2].as() == "Still by two"); + return true; + } + + // 6.2 + TEST IndentationIndicators() { + YAML::Node doc = YAML::Load(ex6_2); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc["a"].size() == 2); + YAML_ASSERT(doc["a"][0].as() == "b"); + YAML_ASSERT(doc["a"][1].size() == 2); + YAML_ASSERT(doc["a"][1][0].as() == "c"); + YAML_ASSERT(doc["a"][1][1].as() == "d"); + return true; + } + + // 6.3 + TEST SeparationSpaces() { + YAML::Node doc = YAML::Load(ex6_3); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc[0].size() == 1); + YAML_ASSERT(doc[0]["foo"].as() == "bar"); + YAML_ASSERT(doc[1].size() == 2); + YAML_ASSERT(doc[1][0].as() == "baz"); + YAML_ASSERT(doc[1][1].as() == "baz"); + return true; + } + + // 6.4 + TEST LinePrefixes() { + YAML::Node doc = YAML::Load(ex6_4); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["plain"].as() == "text lines"); + YAML_ASSERT(doc["quoted"].as() == "text lines"); + YAML_ASSERT(doc["block"].as() == "text\n \tlines\n"); + return true; + } + + // 6.5 + TEST EmptyLines() { + YAML::Node doc = YAML::Load(ex6_5); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["Folding"].as() == "Empty line\nas a line feed"); + YAML_ASSERT(doc["Chomping"].as() == "Clipped empty lines\n"); + return true; + } + + // 6.6 + TEST LineFolding() { + YAML::Node doc = YAML::Load(ex6_6); + YAML_ASSERT(doc.as() == "trimmed\n\n\nas space"); + return true; + } + + // 6.7 + TEST BlockFolding() { + YAML::Node doc = YAML::Load(ex6_7); + YAML_ASSERT(doc.as() == "foo \n\n\t bar\n\nbaz\n"); + return true; + } + + // 6.8 + TEST FlowFolding() { + YAML::Node doc = YAML::Load(ex6_8); + YAML_ASSERT(doc.as() == " foo\nbar\nbaz "); + return true; + } + + // 6.9 + TEST SeparatedComment() { + YAML::Node doc = YAML::Load(ex6_9); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc["key"].as() == "value"); + return true; + } + + // 6.10 + TEST CommentLines() { + YAML::Node doc = YAML::Load(ex6_10); + YAML_ASSERT(doc.IsNull()); + return true; + } + + // 6.11 + TEST MultiLineComments() { + YAML::Node doc = YAML::Load(ex6_11); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc["key"].as() == "value"); + return true; + } + + // 6.12 + TEST SeparationSpacesII() { + YAML::Node doc = YAML::Load(ex6_12); + + std::map sammy; + sammy["first"] = "Sammy"; + sammy["last"] = "Sosa"; + + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc[sammy].size() == 2); + YAML_ASSERT(doc[sammy]["hr"].as() == 65); + YAML_ASSERT(doc[sammy]["avg"].as() == "0.278"); + return true; + } + + // 6.13 + TEST ReservedDirectives() { + YAML::Node doc = YAML::Load(ex6_13); + YAML_ASSERT(doc.as() == "foo"); + return true; + } + + // 6.14 + TEST YAMLDirective() { + YAML::Node doc = YAML::Load(ex6_14); + YAML_ASSERT(doc.as() == "foo"); + return true; + } + + // 6.15 + TEST InvalidRepeatedYAMLDirective() { + try { + YAML::Load(ex6_15); + } catch(const YAML::ParserException& e) { + YAML_ASSERT(e.msg == YAML::ErrorMsg::REPEATED_YAML_DIRECTIVE); + return true; + } + + return " No exception was thrown"; + } + + // 6.16 + TEST TagDirective() { + YAML::Node doc = YAML::Load(ex6_16); + YAML_ASSERT(doc.Tag() == "tag:yaml.org,2002:str"); + YAML_ASSERT(doc.as() == "foo"); + return true; + } + + // 6.17 + TEST InvalidRepeatedTagDirective() { + try { + YAML::Load(ex6_17); + } catch(const YAML::ParserException& e) { + if(e.msg == YAML::ErrorMsg::REPEATED_TAG_DIRECTIVE) + return true; + + throw; + } + + return " No exception was thrown"; + } + + // 6.18 + TEST PrimaryTagHandle() { + std::vector docs = YAML::LoadAll(ex6_18); + YAML_ASSERT(docs.size() == 2); + + { + YAML::Node doc = docs[0]; + YAML_ASSERT(doc.Tag() == "!foo"); + YAML_ASSERT(doc.as() == "bar"); + } + + { + YAML::Node doc = docs[1]; + YAML_ASSERT(doc.Tag() == "tag:example.com,2000:app/foo"); + YAML_ASSERT(doc.as() == "bar"); + } + return true; + } + + // 6.19 + TEST SecondaryTagHandle() { + YAML::Node doc = YAML::Load(ex6_19); + YAML_ASSERT(doc.Tag() == "tag:example.com,2000:app/int"); + YAML_ASSERT(doc.as() == "1 - 3"); + return true; + } + + // 6.20 + TEST TagHandles() { + YAML::Node doc = YAML::Load(ex6_20); + YAML_ASSERT(doc.Tag() == "tag:example.com,2000:app/foo"); + YAML_ASSERT(doc.as() == "bar"); + return true; + } + + // 6.21 + TEST LocalTagPrefix() { + std::vector docs = YAML::LoadAll(ex6_21); + YAML_ASSERT(docs.size() == 2); + + { + YAML::Node doc = docs[0]; + YAML_ASSERT(doc.Tag() == "!my-light"); + YAML_ASSERT(doc.as() == "fluorescent"); + } + + { + YAML::Node doc = docs[1]; + YAML_ASSERT(doc.Tag() == "!my-light"); + YAML_ASSERT(doc.as() == "green"); + } + return true; + } + + // 6.22 + TEST GlobalTagPrefix() { + YAML::Node doc = YAML::Load(ex6_22); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc[0].Tag() == "tag:example.com,2000:app/foo"); + YAML_ASSERT(doc[0].as() == "bar"); + return true; + } + + // 6.23 + TEST NodeProperties() { + YAML::Node doc = YAML::Load(ex6_23); + YAML_ASSERT(doc.size() == 2); + for(YAML::const_iterator it=doc.begin();it!=doc.end();++it) { + if(it->first.as() == "foo") { + YAML_ASSERT(it->first.Tag() == "tag:yaml.org,2002:str"); + YAML_ASSERT(it->second.Tag() == "tag:yaml.org,2002:str"); + YAML_ASSERT(it->second.as() == "bar"); + } else if(it->first.as() == "baz") { + YAML_ASSERT(it->second.as() == "foo"); + } else + return " unknown key"; + } + + return true; + } + + // 6.24 + TEST VerbatimTags() { + YAML::Node doc = YAML::Load(ex6_24); + YAML_ASSERT(doc.size() == 1); + for(YAML::const_iterator it=doc.begin();it!=doc.end();++it) { + YAML_ASSERT(it->first.Tag() == "tag:yaml.org,2002:str"); + YAML_ASSERT(it->first.as() == "foo"); + YAML_ASSERT(it->second.Tag() == "!bar"); + YAML_ASSERT(it->second.as() == "baz"); + } + return true; + } + + // 6.25 + TEST InvalidVerbatimTags() { + YAML::Node doc = YAML::Load(ex6_25); + return " not implemented yet"; // TODO: check tags (but we probably will say these are valid, I think) + } + + // 6.26 + TEST TagShorthands() { + YAML::Node doc = YAML::Load(ex6_26); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc[0].Tag() == "!local"); + YAML_ASSERT(doc[0].as() == "foo"); + YAML_ASSERT(doc[1].Tag() == "tag:yaml.org,2002:str"); + YAML_ASSERT(doc[1].as() == "bar"); + YAML_ASSERT(doc[2].Tag() == "tag:example.com,2000:app/tag%21"); + YAML_ASSERT(doc[2].as() == "baz"); + return true; + } + + // 6.27 + TEST InvalidTagShorthands() { + bool threw = false; + try { + YAML::Load(ex6_27a); + } catch(const YAML::ParserException& e) { + threw = true; + if(e.msg != YAML::ErrorMsg::TAG_WITH_NO_SUFFIX) + throw; + } + + if(!threw) + return " No exception was thrown for a tag with no suffix"; + + YAML::Load(ex6_27b); // TODO: should we reject this one (since !h! is not declared)? + return " not implemented yet"; + } + + // 6.28 + TEST NonSpecificTags() { + YAML::Node doc = YAML::Load(ex6_28); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc[0].as() == "12"); // TODO: check tags. How? + YAML_ASSERT(doc[1].as() == 12); + YAML_ASSERT(doc[2].as() == "12"); + return true; + } + + // 6.29 + TEST NodeAnchors() { + YAML::Node doc = YAML::Load(ex6_29); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["First occurrence"].as() == "Value"); + YAML_ASSERT(doc["Second occurrence"].as() == "Value"); + return true; + } + + // 7.1 + TEST AliasNodes() { + YAML::Node doc = YAML::Load(ex7_1); + YAML_ASSERT(doc.size() == 4); + YAML_ASSERT(doc["First occurrence"].as() == "Foo"); + YAML_ASSERT(doc["Second occurrence"].as() == "Foo"); + YAML_ASSERT(doc["Override anchor"].as() == "Bar"); + YAML_ASSERT(doc["Reuse anchor"].as() == "Bar"); + return true; + } + + // 7.2 + TEST EmptyNodes() { + YAML::Node doc = YAML::Load(ex7_2); + YAML_ASSERT(doc.size() == 2); + for(YAML::const_iterator it=doc.begin();it!=doc.end();++it) { + if(it->first.as() == "foo") { + YAML_ASSERT(it->second.Tag() == "tag:yaml.org,2002:str"); + YAML_ASSERT(it->second.as() == ""); + } else if(it->first.as() == "") { + YAML_ASSERT(it->first.Tag() == "tag:yaml.org,2002:str"); + YAML_ASSERT(it->second.as() == "bar"); + } else + return " unexpected key"; + } + return true; + } + + // 7.3 + TEST CompletelyEmptyNodes() { + YAML::Node doc = YAML::Load(ex7_3); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["foo"].IsNull()); + YAML_ASSERT(doc[YAML::Null].as() == "bar"); + return true; + } + + // 7.4 + TEST DoubleQuotedImplicitKeys() { + YAML::Node doc = YAML::Load(ex7_4); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc["implicit block key"].size() == 1); + YAML_ASSERT(doc["implicit block key"][0].size() == 1); + YAML_ASSERT(doc["implicit block key"][0]["implicit flow key"].as() == "value"); + return true; + } + + // 7.5 + TEST DoubleQuotedLineBreaks() { + YAML::Node doc = YAML::Load(ex7_5); + YAML_ASSERT(doc.as() == "folded to a space,\nto a line feed, or \t \tnon-content"); + return true; + } + + // 7.6 + TEST DoubleQuotedLines() { + YAML::Node doc = YAML::Load(ex7_6); + YAML_ASSERT(doc.as() == " 1st non-empty\n2nd non-empty 3rd non-empty "); + return true; + } + + // 7.7 + TEST SingleQuotedCharacters() { + YAML::Node doc = YAML::Load(ex7_7); + YAML_ASSERT(doc.as() == "here's to \"quotes\""); + return true; + } + + // 7.8 + TEST SingleQuotedImplicitKeys() { + YAML::Node doc = YAML::Load(ex7_8); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc["implicit block key"].size() == 1); + YAML_ASSERT(doc["implicit block key"][0].size() == 1); + YAML_ASSERT(doc["implicit block key"][0]["implicit flow key"].as() == "value"); + return true; + } + + // 7.9 + TEST SingleQuotedLines() { + YAML::Node doc = YAML::Load(ex7_9); + YAML_ASSERT(doc.as() == " 1st non-empty\n2nd non-empty 3rd non-empty "); + return true; + } + + // 7.10 + TEST PlainCharacters() { + YAML::Node doc = YAML::Load(ex7_10); + YAML_ASSERT(doc.size() == 6); + YAML_ASSERT(doc[0].as() == "::vector"); + YAML_ASSERT(doc[1].as() == ": - ()"); + YAML_ASSERT(doc[2].as() == "Up, up, and away!"); + YAML_ASSERT(doc[3].as() == -123); + YAML_ASSERT(doc[4].as() == "http://example.com/foo#bar"); + YAML_ASSERT(doc[5].size() == 5); + YAML_ASSERT(doc[5][0].as() == "::vector"); + YAML_ASSERT(doc[5][1].as() == ": - ()"); + YAML_ASSERT(doc[5][2].as() == "Up, up, and away!"); + YAML_ASSERT(doc[5][3].as() == -123); + YAML_ASSERT(doc[5][4].as() == "http://example.com/foo#bar"); + return true; + } + + // 7.11 + TEST PlainImplicitKeys() { + YAML::Node doc = YAML::Load(ex7_11); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc["implicit block key"].size() == 1); + YAML_ASSERT(doc["implicit block key"][0].size() == 1); + YAML_ASSERT(doc["implicit block key"][0]["implicit flow key"].as() == "value"); + return true; + } + + // 7.12 + TEST PlainLines() { + YAML::Node doc = YAML::Load(ex7_12); + YAML_ASSERT(doc.as() == "1st non-empty\n2nd non-empty 3rd non-empty"); + return true; + } + + // 7.13 + TEST FlowSequence() { + YAML::Node doc = YAML::Load(ex7_13); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc[0].size() == 2); + YAML_ASSERT(doc[0][0].as() == "one"); + YAML_ASSERT(doc[0][1].as() == "two"); + YAML_ASSERT(doc[1].size() == 2); + YAML_ASSERT(doc[1][0].as() == "three"); + YAML_ASSERT(doc[1][1].as() == "four"); + return true; + } + + // 7.14 + TEST FlowSequenceEntries() { + YAML::Node doc = YAML::Load(ex7_14); + YAML_ASSERT(doc.size() == 5); + YAML_ASSERT(doc[0].as() == "double quoted"); + YAML_ASSERT(doc[1].as() == "single quoted"); + YAML_ASSERT(doc[2].as() == "plain text"); + YAML_ASSERT(doc[3].size() == 1); + YAML_ASSERT(doc[3][0].as() == "nested"); + YAML_ASSERT(doc[4].size() == 1); + YAML_ASSERT(doc[4]["single"].as() == "pair"); + return true; + } + + // 7.15 + TEST FlowMappings() { + YAML::Node doc = YAML::Load(ex7_15); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc[0].size() == 2); + YAML_ASSERT(doc[0]["one"].as() == "two"); + YAML_ASSERT(doc[0]["three"].as() == "four"); + YAML_ASSERT(doc[1].size() == 2); + YAML_ASSERT(doc[1]["five"].as() == "six"); + YAML_ASSERT(doc[1]["seven"].as() == "eight"); + return true; + } + + // 7.16 + TEST FlowMappingEntries() { + YAML::Node doc = YAML::Load(ex7_16); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["explicit"].as() == "entry"); + YAML_ASSERT(doc["implicit"].as() == "entry"); + YAML_ASSERT(doc[YAML::Null].IsNull()); + return true; + } + + // 7.17 + TEST FlowMappingSeparateValues() { + YAML::Node doc = YAML::Load(ex7_17); + YAML_ASSERT(doc.size() == 4); + YAML_ASSERT(doc["unquoted"].as() == "separate"); + YAML_ASSERT(doc["http://foo.com"].IsNull()); + YAML_ASSERT(doc["omitted value"].IsNull()); + YAML_ASSERT(doc[YAML::Null].as() == "omitted key"); + return true; + } + + // 7.18 + TEST FlowMappingAdjacentValues() { + YAML::Node doc = YAML::Load(ex7_18); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["adjacent"].as() == "value"); + YAML_ASSERT(doc["readable"].as() == "value"); + YAML_ASSERT(doc["empty"].IsNull()); + return true; + } + + // 7.19 + TEST SinglePairFlowMappings() { + YAML::Node doc = YAML::Load(ex7_19); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc[0].size() == 1); + YAML_ASSERT(doc[0]["foo"].as() == "bar"); + return true; + } + + // 7.20 + TEST SinglePairExplicitEntry() { + YAML::Node doc = YAML::Load(ex7_20); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc[0].size() == 1); + YAML_ASSERT(doc[0]["foo bar"].as() == "baz"); + return true; + } + + // 7.21 + TEST SinglePairImplicitEntries() { + YAML::Node doc = YAML::Load(ex7_21); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc[0].size() == 1); + YAML_ASSERT(doc[0][0].size() == 1); + YAML_ASSERT(doc[0][0]["YAML"].as() == "separate"); + YAML_ASSERT(doc[1].size() == 1); + YAML_ASSERT(doc[1][0].size() == 1); + YAML_ASSERT(doc[1][0][YAML::Null].as() == "empty key entry"); + YAML_ASSERT(doc[2].size() == 1); + YAML_ASSERT(doc[2][0].size() == 1); + + std::map key; + key["JSON"] = "like"; + YAML_ASSERT(doc[2][0][key].as() == "adjacent"); + return true; + } + + // 7.22 + TEST InvalidImplicitKeys() { + try { + YAML::Load(ex7_22); + } catch(const YAML::Exception& e) { + if(e.msg == YAML::ErrorMsg::END_OF_SEQ_FLOW) + return true; + + throw; + } + return " no exception thrown"; + } + + // 7.23 + TEST FlowContent() { + YAML::Node doc = YAML::Load(ex7_23); + YAML_ASSERT(doc.size() == 5); + YAML_ASSERT(doc[0].size() == 2); + YAML_ASSERT(doc[0][0].as() == "a"); + YAML_ASSERT(doc[0][1].as() == "b"); + YAML_ASSERT(doc[1].size() == 1); + YAML_ASSERT(doc[1]["a"].as() == "b"); + YAML_ASSERT(doc[2].as() == "a"); + YAML_ASSERT(doc[3].as() == 'b'); + YAML_ASSERT(doc[4].as() == "c"); + return true; + } + + // 7.24 + TEST FlowNodes() { + YAML::Node doc = YAML::Load(ex7_24); + YAML_ASSERT(doc.size() == 5); + YAML_ASSERT(doc[0].Tag() == "tag:yaml.org,2002:str"); + YAML_ASSERT(doc[0].as() == "a"); + YAML_ASSERT(doc[1].as() == 'b'); + YAML_ASSERT(doc[2].as() == "c"); + YAML_ASSERT(doc[3].as() == "c"); + YAML_ASSERT(doc[4].Tag() == "tag:yaml.org,2002:str"); + YAML_ASSERT(doc[4].as() == ""); + return true; + } + + // 8.1 + TEST BlockScalarHeader() { + YAML::Node doc = YAML::Load(ex8_1); + YAML_ASSERT(doc.size() == 4); + YAML_ASSERT(doc[0].as() == "literal\n"); + YAML_ASSERT(doc[1].as() == " folded\n"); + YAML_ASSERT(doc[2].as() == "keep\n\n"); + YAML_ASSERT(doc[3].as() == " strip"); + return true; + } + + // 8.2 + TEST BlockIndentationHeader() { + YAML::Node doc = YAML::Load(ex8_2); + YAML_ASSERT(doc.size() == 4); + YAML_ASSERT(doc[0].as() == "detected\n"); + YAML_ASSERT(doc[1].as() == "\n\n# detected\n"); + YAML_ASSERT(doc[2].as() == " explicit\n"); + YAML_ASSERT(doc[3].as() == "\t\ndetected\n"); + return true; + } + + // 8.3 + TEST InvalidBlockScalarIndentationIndicators() { + { + bool threw = false; + try { + YAML::Load(ex8_3a); + } catch(const YAML::Exception& e) { + if(e.msg != YAML::ErrorMsg::END_OF_SEQ) + throw; + + threw = true; + } + + if(!threw) + return " no exception thrown for less indented auto-detecting indentation for a literal block scalar"; + } + + { + bool threw = false; + try { + YAML::Load(ex8_3b); + } catch(const YAML::Exception& e) { + if(e.msg != YAML::ErrorMsg::END_OF_SEQ) + throw; + + threw = true; + } + + if(!threw) + return " no exception thrown for less indented auto-detecting indentation for a folded block scalar"; + } + + { + bool threw = false; + try { + YAML::Load(ex8_3c); + } catch(const YAML::Exception& e) { + if(e.msg != YAML::ErrorMsg::END_OF_SEQ) + throw; + + threw = true; + } + + if(!threw) + return " no exception thrown for less indented explicit indentation for a literal block scalar"; + } + + return true; + } + + // 8.4 + TEST ChompingFinalLineBreak() { + YAML::Node doc = YAML::Load(ex8_4); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["strip"].as() == "text"); + YAML_ASSERT(doc["clip"].as() == "text\n"); + YAML_ASSERT(doc["keep"].as() == "text\n"); + return true; + } + + // 8.5 + TEST ChompingTrailingLines() { + YAML::Node doc = YAML::Load(ex8_5); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["strip"].as() == "# text"); + YAML_ASSERT(doc["clip"].as() == "# text\n"); + YAML_ASSERT(doc["keep"].as() == "# text\n"); // Note: I believe this is a bug in the YAML spec - it should be "# text\n\n" + return true; + } + + // 8.6 + TEST EmptyScalarChomping() { + YAML::Node doc = YAML::Load(ex8_6); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["strip"].as() == ""); + YAML_ASSERT(doc["clip"].as() == ""); + YAML_ASSERT(doc["keep"].as() == "\n"); + return true; + } + + // 8.7 + TEST LiteralScalar() { + YAML::Node doc = YAML::Load(ex8_7); + YAML_ASSERT(doc.as() == "literal\n\ttext\n"); + return true; + } + + // 8.8 + TEST LiteralContent() { + YAML::Node doc = YAML::Load(ex8_8); + YAML_ASSERT(doc.as() == "\n\nliteral\n \n\ntext\n"); + return true; + } + + // 8.9 + TEST FoldedScalar() { + YAML::Node doc = YAML::Load(ex8_9); + YAML_ASSERT(doc.as() == "folded text\n"); + return true; + } + + // 8.10 + TEST FoldedLines() { + YAML::Node doc = YAML::Load(ex8_10); + YAML_ASSERT(doc.as() == "\nfolded line\nnext line\n * bullet\n\n * list\n * lines\n\nlast line\n"); + return true; + } + + // 8.11 + TEST MoreIndentedLines() { + YAML::Node doc = YAML::Load(ex8_11); + YAML_ASSERT(doc.as() == "\nfolded line\nnext line\n * bullet\n\n * list\n * lines\n\nlast line\n"); + return true; + } + + // 8.12 + TEST EmptySeparationLines() { + YAML::Node doc = YAML::Load(ex8_12); + YAML_ASSERT(doc.as() == "\nfolded line\nnext line\n * bullet\n\n * list\n * lines\n\nlast line\n"); + return true; + } + + // 8.13 + TEST FinalEmptyLines() { + YAML::Node doc = YAML::Load(ex8_13); + YAML_ASSERT(doc.as() == "\nfolded line\nnext line\n * bullet\n\n * list\n * lines\n\nlast line\n"); + return true; + } + + // 8.14 + TEST BlockSequence() { + YAML::Node doc = YAML::Load(ex8_14); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc["block sequence"].size() == 2); + YAML_ASSERT(doc["block sequence"][0].as() == "one"); + YAML_ASSERT(doc["block sequence"][1].size() == 1); + YAML_ASSERT(doc["block sequence"][1]["two"].as() == "three"); + return true; + } + + // 8.15 + TEST BlockSequenceEntryTypes() { + YAML::Node doc = YAML::Load(ex8_15); + YAML_ASSERT(doc.size() == 4); + YAML_ASSERT(doc[0].IsNull()); + YAML_ASSERT(doc[1].as() == "block node\n"); + YAML_ASSERT(doc[2].size() == 2); + YAML_ASSERT(doc[2][0].as() == "one"); + YAML_ASSERT(doc[2][1].as() == "two"); + YAML_ASSERT(doc[3].size() == 1); + YAML_ASSERT(doc[3]["one"].as() == "two"); + return true; + } + + // 8.16 + TEST BlockMappings() { + YAML::Node doc = YAML::Load(ex8_16); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc["block mapping"].size() == 1); + YAML_ASSERT(doc["block mapping"]["key"].as() == "value"); + return true; + } + + // 8.17 + TEST ExplicitBlockMappingEntries() { + YAML::Node doc = YAML::Load(ex8_17); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["explicit key"].IsNull()); + YAML_ASSERT(doc["block key\n"].size() == 2); + YAML_ASSERT(doc["block key\n"][0].as() == "one"); + YAML_ASSERT(doc["block key\n"][1].as() == "two"); + return true; + } + + // 8.18 + TEST ImplicitBlockMappingEntries() { + YAML::Node doc = YAML::Load(ex8_18); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["plain key"].as() == "in-line value"); + YAML_ASSERT(doc[YAML::Null].IsNull()); + YAML_ASSERT(doc["quoted key"].size() == 1); + YAML_ASSERT(doc["quoted key"][0].as() == "entry"); + return true; + } + + // 8.19 + TEST CompactBlockMappings() { + YAML::Node doc = YAML::Load(ex8_19); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc[0].size() == 1); + YAML_ASSERT(doc[0]["sun"].as() == "yellow"); + YAML_ASSERT(doc[1].size() == 1); + std::map key; + key["earth"] = "blue"; + YAML_ASSERT(doc[1][key].size() == 1); + YAML_ASSERT(doc[1][key]["moon"].as() == "white"); + return true; + } + + // 8.20 + TEST BlockNodeTypes() { + YAML::Node doc = YAML::Load(ex8_20); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc[0].as() == "flow in block"); + YAML_ASSERT(doc[1].as() == "Block scalar\n"); + YAML_ASSERT(doc[2].size() == 1); + YAML_ASSERT(doc[2]["foo"].as() == "bar"); + return true; + } + + // 8.21 + TEST BlockScalarNodes() { + YAML::Node doc = YAML::Load(ex8_21); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["literal"].as() == "value"); // Note: I believe this is a bug in the YAML spec - it should be "value\n" + YAML_ASSERT(doc["folded"].as() == "value"); + YAML_ASSERT(doc["folded"].Tag() == "!foo"); + return true; + } + + // 8.22 + TEST BlockCollectionNodes() { + YAML::Node doc = YAML::Load(ex8_22); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["sequence"].size() == 2); + YAML_ASSERT(doc["sequence"][0].as() == "entry"); + YAML_ASSERT(doc["sequence"][1].size() == 1); + YAML_ASSERT(doc["sequence"][1][0].as() == "nested"); + YAML_ASSERT(doc["mapping"].size() == 1); + YAML_ASSERT(doc["mapping"]["foo"].as() == "bar"); + return true; + } + } +} diff --git a/test/nodetests.h b/test/nodetests.h new file mode 100644 index 0000000..733e782 --- /dev/null +++ b/test/nodetests.h @@ -0,0 +1,13 @@ +#ifndef NODETESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define NODETESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +namespace Test { + bool RunNodeTests(); +} + +#endif // NODETESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A6666 + diff --git a/test/parsertests.h b/test/parsertests.h new file mode 100644 index 0000000..f3de1b8 --- /dev/null +++ b/test/parsertests.h @@ -0,0 +1,13 @@ +#ifndef PARSERTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define PARSERTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +namespace Test { + bool RunParserTests(); +} + +#endif // PARSERTESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + diff --git a/test/tests.cpp b/test/tests.cpp index ce8d338..efe82fc 100644 --- a/test/tests.cpp +++ b/test/tests.cpp @@ -1,5 +1,7 @@ #include "tests.h" #include "emittertests.h" +#include "nodetests.h" +#include "parsertests.h" #include "spectests.h" #include "yaml-cpp/yaml.h" #include @@ -12,12 +14,18 @@ namespace Test void RunAll() { bool passed = true; + if(!RunParserTests()) + passed = false; + if(!RunEmitterTests()) passed = false; if(!RunSpecTests()) passed = false; - + + if(!RunNodeTests()) + passed = false; + if(passed) std::cout << "All tests passed!\n"; } From 9e87a9cec3dd73c6f87b1734e733bba799e0855b Mon Sep 17 00:00:00 2001 From: beder Date: Sat, 19 May 2012 15:34:49 -0500 Subject: [PATCH 02/43] Added old parse utility --- util/parse.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/util/parse.cpp b/util/parse.cpp index d02a76a..ca112e0 100644 --- a/util/parse.cpp +++ b/util/parse.cpp @@ -37,13 +37,8 @@ public: void parse(std::istream& input) { try { - YAML::Parser parser(input); - YAML::Node doc; - while(parser.GetNextDocument(doc)) { - YAML::Emitter emitter; - emitter << doc; - std::cout << emitter.c_str() << "\n"; - } + YAML::Node doc = YAML::Load(input); + std::cout << doc << "\n"; } catch(const YAML::Exception& e) { std::cerr << e.what() << "\n"; } From d3e3d1619f0c245889bccf6113adee215f9edb70 Mon Sep 17 00:00:00 2001 From: beder Date: Sat, 19 May 2012 15:36:22 -0500 Subject: [PATCH 03/43] Updated CMakeLists from new-api --- CMakeLists.txt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 823ce20..8c56c53 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,7 @@ include(CheckCXXCompilerFlag) project(YAML_CPP) set(YAML_CPP_VERSION_MAJOR "0") -set(YAML_CPP_VERSION_MINOR "3") +set(YAML_CPP_VERSION_MINOR "5") set(YAML_CPP_VERSION_PATCH "0") set(YAML_CPP_VERSION "${YAML_CPP_VERSION_MAJOR}.${YAML_CPP_VERSION_MINOR}.${YAML_CPP_VERSION_PATCH}") @@ -57,7 +57,7 @@ option(MSVC_STHREADED_RT "MSVC: Build with single-threaded static runtime libs ( set(header_directory "include/yaml-cpp/") file(GLOB sources "src/[a-zA-Z]*.cpp") -file(GLOB public_headers "include/yaml-cpp/[a-zA-Z]*.h") +file(GLOB_RECURSE public_headers "include/yaml-cpp/[a-zA-Z]*.h") file(GLOB private_headers "src/[a-zA-Z]*.h") if(YAML_CPP_BUILD_CONTRIB) @@ -77,8 +77,11 @@ if(VERBOSE) message(STATUS "contrib_private_headers: ${contrib_private_headers}") endif() -include_directories(${YAML_CPP_SOURCE_DIR}/include) include_directories(${YAML_CPP_SOURCE_DIR}/src) +include_directories(${YAML_CPP_SOURCE_DIR}/include) + +find_package(Boost REQUIRED) +include_directories(${Boost_INCLUDE_DIRS}) ### From b244ada735ca0f096856f98d527d126743f66b8b Mon Sep 17 00:00:00 2001 From: beder Date: Sat, 19 May 2012 15:55:13 -0500 Subject: [PATCH 04/43] Backed out of removing parse --- util/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/util/CMakeLists.txt b/util/CMakeLists.txt index e69de29..22339f0 100644 --- a/util/CMakeLists.txt +++ b/util/CMakeLists.txt @@ -0,0 +1,2 @@ +add_executable(parse parse.cpp) +target_link_libraries(parse yaml-cpp) From f7168f0aec4370d018bccfc4afabe08f45075436 Mon Sep 17 00:00:00 2001 From: beder Date: Fri, 25 May 2012 19:38:20 -0500 Subject: [PATCH 05/43] Updated the ostream emitting overload to user the new ostream-handling emitters --- src/emit.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/emit.cpp b/src/emit.cpp index 5b1145c..1f0a647 100644 --- a/src/emit.cpp +++ b/src/emit.cpp @@ -15,9 +15,8 @@ namespace YAML std::ostream& operator << (std::ostream& out, const Node& node) { - Emitter emitter; + Emitter emitter(out); emitter << node; - out << emitter.c_str(); return out; } From 9bd35af092a4ed036a5ee0b014857a298f11d3c2 Mon Sep 17 00:00:00 2001 From: beder Date: Fri, 8 Jun 2012 10:25:42 -0500 Subject: [PATCH 06/43] Removed stray GetNextDocument declaration from the parser (it's from the old API, and not the new one) --- include/yaml-cpp/parser.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/yaml-cpp/parser.h b/include/yaml-cpp/parser.h index f71cdff..ffc21f5 100644 --- a/include/yaml-cpp/parser.h +++ b/include/yaml-cpp/parser.h @@ -31,9 +31,7 @@ namespace YAML void Load(std::istream& in); bool HandleNextDocument(EventHandler& eventHandler); - - bool GetNextDocument(Node& document); // old API only - + void PrintTokens(std::ostream& out); private: From 96ae51dd254764239e7d5b2913fd4e7381d28a93 Mon Sep 17 00:00:00 2001 From: beder Date: Fri, 8 Jun 2012 10:26:49 -0500 Subject: [PATCH 07/43] Removed unnecessary forward declarations --- include/yaml-cpp/parser.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/yaml-cpp/parser.h b/include/yaml-cpp/parser.h index ffc21f5..8ec926b 100644 --- a/include/yaml-cpp/parser.h +++ b/include/yaml-cpp/parser.h @@ -14,10 +14,8 @@ namespace YAML { struct Directives; - struct Mark; struct Token; class EventHandler; - class Node; class Scanner; class YAML_CPP_API Parser: private noncopyable From 72f90c6c2349021046bdb79c049b64bd2a2c9202 Mon Sep 17 00:00:00 2001 From: beder Date: Wed, 4 Jul 2012 15:26:37 -0500 Subject: [PATCH 08/43] Added free Clone() function for Nodes --- include/yaml-cpp/node/impl.h | 2 +- include/yaml-cpp/node/node.h | 4 ++- src/node.cpp | 14 ++++++++++ test/new-api/nodetests.cpp | 50 +++++++++++++++++++++++++++++++++++- 4 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 src/node.cpp diff --git a/include/yaml-cpp/node/impl.h b/include/yaml-cpp/node/impl.h index 00ae1f6..65c0e1d 100644 --- a/include/yaml-cpp/node/impl.h +++ b/include/yaml-cpp/node/impl.h @@ -224,7 +224,7 @@ namespace YAML m_pMemory->merge(*rhs.m_pMemory); m_pNode = rhs.m_pNode; } - + // size/iterator inline std::size_t Node::size() const { diff --git a/include/yaml-cpp/node/node.h b/include/yaml-cpp/node/node.h index e230e4a..bdcb36e 100644 --- a/include/yaml-cpp/node/node.h +++ b/include/yaml-cpp/node/node.h @@ -56,7 +56,7 @@ namespace YAML bool is(const Node& rhs) const; template Node& operator=(const T& rhs); Node& operator=(const Node& rhs); - + // size/iterator std::size_t size() const; @@ -105,6 +105,8 @@ namespace YAML }; bool operator==(const Node& lhs, const Node& rhs); + + Node Clone(const Node& node); template struct convert; diff --git a/src/node.cpp b/src/node.cpp new file mode 100644 index 0000000..2d21aa9 --- /dev/null +++ b/src/node.cpp @@ -0,0 +1,14 @@ +#include "yaml-cpp/node/node.h" +#include "nodebuilder.h" +#include "nodeevents.h" + +namespace YAML +{ + Node Clone(const Node& node) + { + NodeEvents events(node); + NodeBuilder builder; + events.Emit(builder); + return builder.Root(); + } +} diff --git a/test/new-api/nodetests.cpp b/test/new-api/nodetests.cpp index ee40110..54a3e18 100644 --- a/test/new-api/nodetests.cpp +++ b/test/new-api/nodetests.cpp @@ -373,7 +373,51 @@ namespace Test } return true; } - } + + TEST CloneScalar() + { + YAML::Node node = YAML::Load("!foo monkey"); + YAML::Node clone = Clone(node); + YAML_ASSERT(!(node == clone)); + YAML_ASSERT(node.as() == clone.as()); + YAML_ASSERT(node.Tag() == clone.Tag()); + return true; + } + + TEST CloneSeq() + { + YAML::Node node = YAML::Load("[1, 3, 5, 7]"); + YAML::Node clone = Clone(node); + YAML_ASSERT(!(node == clone)); + YAML_ASSERT(clone.Type() == YAML::NodeType::Sequence); + YAML_ASSERT(node.size() == clone.size()); + for(std::size_t i=0;i() == clone[i].as()); + return true; + } + + TEST CloneMap() + { + YAML::Node node = YAML::Load("{foo: bar}"); + YAML::Node clone = Clone(node); + YAML_ASSERT(!(node == clone)); + YAML_ASSERT(clone.Type() == YAML::NodeType::Map); + YAML_ASSERT(node.size() == clone.size()); + YAML_ASSERT(node["foo"].as() == clone["foo"].as()); + return true; + } + + TEST CloneAlias() + { + YAML::Node node = YAML::Load("&foo [*foo]"); + YAML::Node clone = Clone(node); + YAML_ASSERT(!(node == clone)); + YAML_ASSERT(clone.Type() == YAML::NodeType::Sequence); + YAML_ASSERT(node.size() == clone.size()); + YAML_ASSERT(clone == clone[0]); + return true; + } + } void RunNodeTest(TEST (*test)(), const std::string& name, int& passed, int& total) { TEST ret; @@ -426,6 +470,10 @@ namespace Test RunNodeTest(&Node::IterateMap, "iterate map", passed, total); RunNodeTest(&Node::ForEach, "for each", passed, total); RunNodeTest(&Node::ForEachMap, "for each map", passed, total); + RunNodeTest(&Node::CloneScalar, "clone scalar", passed, total); + RunNodeTest(&Node::CloneSeq, "clone seq", passed, total); + RunNodeTest(&Node::CloneMap, "clone map", passed, total); + RunNodeTest(&Node::CloneAlias, "clone alias", passed, total); std::cout << "Node tests: " << passed << "/" << total << " passed\n"; return passed == total; From bbdfee7af7a465bf468840af22bdc56293812e05 Mon Sep 17 00:00:00 2001 From: Jeff Wang Date: Tue, 17 Jul 2012 11:55:45 -0500 Subject: [PATCH 09/43] workaround for gcc 3 --- include/yaml-cpp/node/convert.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/yaml-cpp/node/convert.h b/include/yaml-cpp/node/convert.h index f78332a..6f19d8e 100644 --- a/include/yaml-cpp/node/convert.h +++ b/include/yaml-cpp/node/convert.h @@ -138,7 +138,12 @@ namespace YAML rhs.clear(); for(const_iterator it=node.begin();it!=node.end();++it) +#if defined(__GNUC__) && __GNUC__ < 4 +//workaround for GCC 3: + rhs[it->first.template as()] = it->second.template as(); +#else rhs[it->first.as()] = it->second.as(); +#endif return true; } }; @@ -159,7 +164,12 @@ namespace YAML rhs.clear(); for(const_iterator it=node.begin();it!=node.end();++it) +#if defined(__GNUC__) && __GNUC__ < 4 +//workaround for GCC 3: + rhs.push_back(it->template as()); +#else rhs.push_back(it->as()); +#endif return true; } }; @@ -180,7 +190,12 @@ namespace YAML rhs.clear(); for(const_iterator it=node.begin();it!=node.end();++it) +#if defined(__GNUC__) && __GNUC__ < 4 +//workaround for GCC 3: + rhs.push_back(it->template as()); +#else rhs.push_back(it->as()); +#endif return true; } }; From 595dc8277a5dd8b351c54b0c6d53235474418e8f Mon Sep 17 00:00:00 2001 From: beder Date: Wed, 31 Oct 2012 18:55:07 -0500 Subject: [PATCH 10/43] Simplified Node::operator[] interface by removing the C-string overloads, using a helper to_value --- include/yaml-cpp/node/impl.h | 83 +++++++++++++++++++++--------------- include/yaml-cpp/node/node.h | 8 ---- 2 files changed, 49 insertions(+), 42 deletions(-) diff --git a/include/yaml-cpp/node/impl.h b/include/yaml-cpp/node/impl.h index 65c0e1d..3b466d5 100644 --- a/include/yaml-cpp/node/impl.h +++ b/include/yaml-cpp/node/impl.h @@ -123,7 +123,7 @@ namespace YAML return node.Scalar(); } }; - + // access functions template inline const T Node::as() const @@ -267,12 +267,57 @@ namespace YAML m_pMemory->merge(*rhs.m_pMemory); } + // helpers for indexing + namespace detail { + template + struct to_value_t { + explicit to_value_t(const T& t_): t(t_) {} + const T& t; + typedef const T& return_type; + + const T& operator()() const { return t; } + }; + + template<> + struct to_value_t { + explicit to_value_t(const char *t_): t(t_) {} + const char *t; + typedef std::string return_type; + + const std::string operator()() const { return t; } + }; + + template<> + struct to_value_t { + explicit to_value_t(char *t_): t(t_) {} + const char *t; + typedef std::string return_type; + + const std::string operator()() const { return t; } + }; + + template + struct to_value_t { + explicit to_value_t(const char *t_): t(t_) {} + const char *t; + typedef std::string return_type; + + const std::string operator()() const { return t; } + }; + + // converts C-strings to std::strings so they can be copied + template + inline typename to_value_t::return_type to_value(const T& t) { + return to_value_t(t)(); + } + } + // indexing template inline const Node Node::operator[](const Key& key) const { EnsureNodeExists(); - detail::node& value = static_cast(*m_pNode).get(key, m_pMemory); + detail::node& value = static_cast(*m_pNode).get(detail::to_value(key), m_pMemory); return Node(value, m_pMemory); } @@ -280,7 +325,7 @@ namespace YAML inline Node Node::operator[](const Key& key) { EnsureNodeExists(); - detail::node& value = m_pNode->get(key, m_pMemory); + detail::node& value = m_pNode->get(detail::to_value(key), m_pMemory); return Node(value, m_pMemory); } @@ -288,7 +333,7 @@ namespace YAML inline bool Node::remove(const Key& key) { EnsureNodeExists(); - return m_pNode->remove(key, m_pMemory); + return m_pNode->remove(detail::to_value(key), m_pMemory); } inline const Node Node::operator[](const Node& key) const @@ -313,36 +358,6 @@ namespace YAML key.EnsureNodeExists(); return m_pNode->remove(*key.m_pNode, m_pMemory); } - - inline const Node Node::operator[](const char *key) const - { - return operator[](std::string(key)); - } - - inline Node Node::operator[](const char *key) - { - return operator[](std::string(key)); - } - - inline bool Node::remove(const char *key) - { - return remove(std::string(key)); - } - - inline const Node Node::operator[](char *key) const - { - return operator[](static_cast(key)); - } - - inline Node Node::operator[](char *key) - { - return operator[](static_cast(key)); - } - - inline bool Node::remove(char *key) - { - return remove(static_cast(key)); - } // free functions diff --git a/include/yaml-cpp/node/node.h b/include/yaml-cpp/node/node.h index bdcb36e..6fafd26 100644 --- a/include/yaml-cpp/node/node.h +++ b/include/yaml-cpp/node/node.h @@ -78,15 +78,7 @@ namespace YAML const Node operator[](const Node& key) const; Node operator[](const Node& key); bool remove(const Node& key); - - const Node operator[](const char *key) const; - Node operator[](const char *key); - bool remove(const char *key); - const Node operator[](char *key) const; - Node operator[](char *key); - bool remove(char *key); - private: explicit Node(detail::node& node, detail::shared_memory_holder pMemory); From e4a18300033de9394f9d2de2c3f9d5671998ef83 Mon Sep 17 00:00:00 2001 From: beder Date: Wed, 31 Oct 2012 19:08:09 -0500 Subject: [PATCH 11/43] Added force_insert for mapping nodes that doesn't check to see if the key exists already (so it could duplicate keys) --- include/yaml-cpp/exceptions.h | 7 ++++++ include/yaml-cpp/node/detail/impl.h | 21 ++++++++++++++++++ include/yaml-cpp/node/detail/node.h | 4 ++++ include/yaml-cpp/node/detail/node_data.h | 4 ++++ include/yaml-cpp/node/detail/node_ref.h | 4 ++++ include/yaml-cpp/node/impl.h | 9 +++++++- include/yaml-cpp/node/node.h | 4 ++++ test/new-api/nodetests.cpp | 27 ++++++++++++++++++++++++ 8 files changed, 79 insertions(+), 1 deletion(-) diff --git a/include/yaml-cpp/exceptions.h b/include/yaml-cpp/exceptions.h index 9624303..02aeb61 100644 --- a/include/yaml-cpp/exceptions.h +++ b/include/yaml-cpp/exceptions.h @@ -61,6 +61,7 @@ namespace YAML const char * const BAD_DEREFERENCE = "bad dereference"; const char * const BAD_SUBSCRIPT = "operator[] call on a scalar"; const char * const BAD_PUSHBACK = "appending to a non-sequence"; + const char * const BAD_INSERT = "inserting in a non-convertible-to-map"; const char * const UNMATCHED_GROUP_TAG = "unmatched group tag"; const char * const UNEXPECTED_END_SEQ = "unexpected end sequence token"; @@ -178,6 +179,12 @@ namespace YAML : RepresentationException(Mark::null(), ErrorMsg::BAD_PUSHBACK) {} }; + class BadInsert: public RepresentationException { + public: + BadInsert() + : RepresentationException(Mark::null(), ErrorMsg::BAD_INSERT) {} + }; + class EmitterException: public Exception { public: EmitterException(const std::string& msg_) diff --git a/include/yaml-cpp/node/detail/impl.h b/include/yaml-cpp/node/detail/impl.h index e3d17af..b04fc05 100644 --- a/include/yaml-cpp/node/detail/impl.h +++ b/include/yaml-cpp/node/detail/impl.h @@ -118,6 +118,27 @@ namespace YAML return false; } + + // map + template + inline void node_data::force_insert(const Key& key, const Value& value, shared_memory_holder pMemory) + { + switch(m_type) { + case NodeType::Map: + break; + case NodeType::Undefined: + case NodeType::Null: + case NodeType::Sequence: + convert_to_map(pMemory); + break; + case NodeType::Scalar: + throw BadInsert(); + } + + node& k = convert_to_node(key, pMemory); + node& v = convert_to_node(value, pMemory); + insert_map_pair(k, v); + } template inline bool node_data::equals(node& node, const T& rhs, shared_memory_holder pMemory) diff --git a/include/yaml-cpp/node/detail/node.h b/include/yaml-cpp/node/detail/node.h index 846e279..ce3a76d 100644 --- a/include/yaml-cpp/node/detail/node.h +++ b/include/yaml-cpp/node/detail/node.h @@ -115,6 +115,10 @@ namespace YAML } bool remove(node& key, shared_memory_holder pMemory) { return m_pRef->remove(key, pMemory); } + // map + template + void force_insert(const Key& key, const Value& value, shared_memory_holder pMemory){ m_pRef->force_insert(key, value, pMemory); } + private: shared_node_ref m_pRef; typedef std::set nodes; diff --git a/include/yaml-cpp/node/detail/node_data.h b/include/yaml-cpp/node/detail/node_data.h index c0be2b8..7fe05b8 100644 --- a/include/yaml-cpp/node/detail/node_data.h +++ b/include/yaml-cpp/node/detail/node_data.h @@ -56,6 +56,10 @@ namespace YAML node& get(node& key, shared_memory_holder pMemory) const; node& get(node& key, shared_memory_holder pMemory); bool remove(node& key, shared_memory_holder pMemory); + + // map + template + void force_insert(const Key& key, const Value& value, shared_memory_holder pMemory); public: static std::string empty_scalar; diff --git a/include/yaml-cpp/node/detail/node_ref.h b/include/yaml-cpp/node/detail/node_ref.h index d1b06c5..64cdb98 100644 --- a/include/yaml-cpp/node/detail/node_ref.h +++ b/include/yaml-cpp/node/detail/node_ref.h @@ -55,6 +55,10 @@ namespace YAML node& get(node& key, shared_memory_holder pMemory) const { return static_cast(*m_pData).get(key, pMemory); } node& get(node& key, shared_memory_holder pMemory) { return m_pData->get(key, pMemory); } bool remove(node& key, shared_memory_holder pMemory) { return m_pData->remove(key, pMemory); } + + // map + template + void force_insert(const Key& key, const Value& value, shared_memory_holder pMemory) { m_pData->force_insert(key, value, pMemory); } private: shared_node_data m_pData; diff --git a/include/yaml-cpp/node/impl.h b/include/yaml-cpp/node/impl.h index 3b466d5..e25bff0 100644 --- a/include/yaml-cpp/node/impl.h +++ b/include/yaml-cpp/node/impl.h @@ -358,9 +358,16 @@ namespace YAML key.EnsureNodeExists(); return m_pNode->remove(*key.m_pNode, m_pMemory); } + + // map + template + inline void Node::force_insert(const Key& key, const Value& value) + { + EnsureNodeExists(); + m_pNode->force_insert(detail::to_value(key), detail::to_value(value), m_pMemory); + } // free functions - inline bool operator==(const Node& lhs, const Node& rhs) { return lhs.is(rhs); diff --git a/include/yaml-cpp/node/node.h b/include/yaml-cpp/node/node.h index 6fafd26..70acb3e 100644 --- a/include/yaml-cpp/node/node.h +++ b/include/yaml-cpp/node/node.h @@ -78,6 +78,10 @@ namespace YAML const Node operator[](const Node& key) const; Node operator[](const Node& key); bool remove(const Node& key); + + // map + template + void force_insert(const Key& key, const Value& value); private: explicit Node(detail::node& node, detail::shared_memory_holder pMemory); diff --git a/test/new-api/nodetests.cpp b/test/new-api/nodetests.cpp index 54a3e18..556e06b 100644 --- a/test/new-api/nodetests.cpp +++ b/test/new-api/nodetests.cpp @@ -417,6 +417,32 @@ namespace Test YAML_ASSERT(clone == clone[0]); return true; } + + TEST ForceInsertIntoMap() + { + YAML::Node node; + node["a"] = "b"; + node.force_insert("x", "y"); + node.force_insert("a", 5); + YAML_ASSERT(node.size() == 3); + YAML_ASSERT(node.Type() == YAML::NodeType::Map); + bool ab = false; + bool a5 = false; + bool xy = false; + for(YAML::const_iterator it=node.begin();it!=node.end();++it) { + if(it->first.as() == "a") { + if(it->second.as() == "b") + ab = true; + else if(it->second.as() == "5") + a5 = true; + } else if(it->first.as() == "x" && it->second.as() == "y") + xy = true; + } + YAML_ASSERT(ab); + YAML_ASSERT(a5); + YAML_ASSERT(xy); + return true; + } } void RunNodeTest(TEST (*test)(), const std::string& name, int& passed, int& total) { @@ -474,6 +500,7 @@ namespace Test RunNodeTest(&Node::CloneSeq, "clone seq", passed, total); RunNodeTest(&Node::CloneMap, "clone map", passed, total); RunNodeTest(&Node::CloneAlias, "clone alias", passed, total); + RunNodeTest(&Node::ForceInsertIntoMap, "force insert into map", passed, total); std::cout << "Node tests: " << passed << "/" << total << " passed\n"; return passed == total; From ba0274298ec65fb5cd24be14f53a23104914216a Mon Sep 17 00:00:00 2001 From: beder Date: Wed, 31 Oct 2012 19:10:45 -0500 Subject: [PATCH 12/43] Switched map's convert<> specialization to use the new force_insert --- include/yaml-cpp/node/convert.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/yaml-cpp/node/convert.h b/include/yaml-cpp/node/convert.h index 6f19d8e..2e2f3f9 100644 --- a/include/yaml-cpp/node/convert.h +++ b/include/yaml-cpp/node/convert.h @@ -128,7 +128,7 @@ namespace YAML static Node encode(const std::map& rhs) { Node node(NodeType::Map); for(typename std::map::const_iterator it=rhs.begin();it!=rhs.end();++it) - node[it->first] = it->second; + node.force_insert(it->first, it->second); return node; } From 62bb76865c18124345801b3fd38d41668403cfbf Mon Sep 17 00:00:00 2001 From: beder Date: Thu, 8 Nov 2012 18:14:26 -0600 Subject: [PATCH 13/43] Set LoadFile and LoadAllFromFile to throw an exception if we can't load the file --- include/yaml-cpp/exceptions.h | 6 ++++++ src/parse.cpp | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/include/yaml-cpp/exceptions.h b/include/yaml-cpp/exceptions.h index 02aeb61..fabb33a 100644 --- a/include/yaml-cpp/exceptions.h +++ b/include/yaml-cpp/exceptions.h @@ -70,6 +70,7 @@ namespace YAML const char * const INVALID_ANCHOR = "invalid anchor"; const char * const INVALID_ALIAS = "invalid alias"; const char * const INVALID_TAG = "invalid tag"; + const char * const BAD_FILE = "bad file"; template inline const std::string KEY_NOT_FOUND_WITH_KEY(const T&, typename disable_if >::type * = 0) { @@ -190,6 +191,11 @@ namespace YAML EmitterException(const std::string& msg_) : Exception(Mark::null(), msg_) {} }; + + class BadFile: public Exception { + public: + BadFile(): Exception(Mark::null(), ErrorMsg::BAD_FILE) {} + }; } #endif // EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/src/parse.cpp b/src/parse.cpp index 3a33931..1537d55 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -30,6 +30,8 @@ namespace YAML Node LoadFile(const std::string& filename) { std::ifstream fin(filename.c_str()); + if(!fin) + throw BadFile(); return Load(fin); } @@ -59,6 +61,8 @@ namespace YAML std::vector LoadAllFromFile(const std::string& filename) { std::ifstream fin(filename.c_str()); + if(!fin) + throw BadFile(); return LoadAll(fin); } } From 93d635d5a52320aae45e250aeb2ec5d05e75557b Mon Sep 17 00:00:00 2001 From: beder Date: Thu, 8 Nov 2012 18:40:44 -0600 Subject: [PATCH 14/43] Fixed typo from null fix --- include/yaml-cpp/exceptions.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/yaml-cpp/exceptions.h b/include/yaml-cpp/exceptions.h index ca27f41..3a2bd22 100644 --- a/include/yaml-cpp/exceptions.h +++ b/include/yaml-cpp/exceptions.h @@ -152,7 +152,7 @@ namespace YAML class BadConversion: public RepresentationException { public: BadConversion() - : RepresentationException(Mark::null(), ErrorMsg::BAD_CONVERSION) {} + : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_CONVERSION) {} }; template @@ -165,25 +165,25 @@ namespace YAML class BadDereference: public RepresentationException { public: BadDereference() - : RepresentationException(Mark::null(), ErrorMsg::BAD_DEREFERENCE) {} + : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_DEREFERENCE) {} }; class BadSubscript: public RepresentationException { public: BadSubscript() - : RepresentationException(Mark::null(), ErrorMsg::BAD_SUBSCRIPT) {} + : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_SUBSCRIPT) {} }; class BadPushback: public RepresentationException { public: BadPushback() - : RepresentationException(Mark::null(), ErrorMsg::BAD_PUSHBACK) {} + : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_PUSHBACK) {} }; class BadInsert: public RepresentationException { public: BadInsert() - : RepresentationException(Mark::null(), ErrorMsg::BAD_INSERT) {} + : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_INSERT) {} }; class EmitterException: public Exception { @@ -194,7 +194,7 @@ namespace YAML class BadFile: public Exception { public: - BadFile(): Exception(Mark::null(), ErrorMsg::BAD_FILE) {} + BadFile(): Exception(Mark::null_mark(), ErrorMsg::BAD_FILE) {} }; } From 892176f0d7635ba20f6ac3ece0107750920f2ca1 Mon Sep 17 00:00:00 2001 From: beder Date: Thu, 8 Nov 2012 18:47:22 -0600 Subject: [PATCH 15/43] Added Node::clear() function --- include/yaml-cpp/node/impl.h | 7 ++++++- include/yaml-cpp/node/node.h | 1 + test/new-api/nodetests.cpp | 10 ++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/include/yaml-cpp/node/impl.h b/include/yaml-cpp/node/impl.h index e25bff0..d46f329 100644 --- a/include/yaml-cpp/node/impl.h +++ b/include/yaml-cpp/node/impl.h @@ -15,7 +15,7 @@ namespace YAML { - inline Node::Node(): m_pNode(0) + inline Node::Node(): m_pNode(NULL) { } @@ -168,6 +168,11 @@ namespace YAML return *this; } + inline void Node::clear() + { + m_pNode = NULL; + } + template inline void Node::Assign(const T& rhs) { diff --git a/include/yaml-cpp/node/node.h b/include/yaml-cpp/node/node.h index 70acb3e..d4ee442 100644 --- a/include/yaml-cpp/node/node.h +++ b/include/yaml-cpp/node/node.h @@ -56,6 +56,7 @@ namespace YAML bool is(const Node& rhs) const; template Node& operator=(const T& rhs); Node& operator=(const Node& rhs); + void clear(); // size/iterator std::size_t size() const; diff --git a/test/new-api/nodetests.cpp b/test/new-api/nodetests.cpp index 556e06b..bc6d6fa 100644 --- a/test/new-api/nodetests.cpp +++ b/test/new-api/nodetests.cpp @@ -443,6 +443,15 @@ namespace Test YAML_ASSERT(xy); return true; } + + TEST ClearNode() + { + YAML::Node node = YAML::Load("[1, 2, 3]"); + YAML_ASSERT(!node.IsNull()); + node.clear(); + YAML_ASSERT(node.IsNull()); + return true; + } } void RunNodeTest(TEST (*test)(), const std::string& name, int& passed, int& total) { @@ -501,6 +510,7 @@ namespace Test RunNodeTest(&Node::CloneMap, "clone map", passed, total); RunNodeTest(&Node::CloneAlias, "clone alias", passed, total); RunNodeTest(&Node::ForceInsertIntoMap, "force insert into map", passed, total); + RunNodeTest(&Node::ClearNode, "clear node", passed, total); std::cout << "Node tests: " << passed << "/" << total << " passed\n"; return passed == total; From f565ee4c35f25d7f02130ea7e25e021011821132 Mon Sep 17 00:00:00 2001 From: beder Date: Fri, 28 Dec 2012 18:59:29 -0600 Subject: [PATCH 16/43] Added tag release-0.5.0 for changeset d042aa2fa32d From 85f43cd3de7e7ceecaaa965cceb3d3db05f19c6b Mon Sep 17 00:00:00 2001 From: Jesse Beder Date: Mon, 1 Apr 2013 21:43:09 -0500 Subject: [PATCH 17/43] Fix warning in Visual Studio: warning C4146: unary minus operator applied to unsigned type, result still unsigned --- include/yaml-cpp/node/convert.h | 38 ++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/include/yaml-cpp/node/convert.h b/include/yaml-cpp/node/convert.h index 2e2f3f9..6a22a3d 100644 --- a/include/yaml-cpp/node/convert.h +++ b/include/yaml-cpp/node/convert.h @@ -58,7 +58,7 @@ namespace YAML } }; -#define YAML_DEFINE_CONVERT_STREAMABLE(type)\ +#define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op)\ template<>\ struct convert {\ static Node encode(const type& rhs) {\ @@ -80,7 +80,7 @@ namespace YAML rhs = std::numeric_limits::infinity();\ return true;\ } else if(conversion::IsNegativeInfinity(input)) {\ - rhs = -std::numeric_limits::infinity();\ + rhs = negative_op std::numeric_limits::infinity();\ return true;\ }\ }\ @@ -94,22 +94,30 @@ namespace YAML }\ } - YAML_DEFINE_CONVERT_STREAMABLE(int); - YAML_DEFINE_CONVERT_STREAMABLE(unsigned); - YAML_DEFINE_CONVERT_STREAMABLE(short); - YAML_DEFINE_CONVERT_STREAMABLE(unsigned short); - YAML_DEFINE_CONVERT_STREAMABLE(long); - YAML_DEFINE_CONVERT_STREAMABLE(unsigned long); - YAML_DEFINE_CONVERT_STREAMABLE(long long); - YAML_DEFINE_CONVERT_STREAMABLE(unsigned long long); +#define YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(type)\ + YAML_DEFINE_CONVERT_STREAMABLE(type, -) + +#define YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(type)\ + YAML_DEFINE_CONVERT_STREAMABLE(type, +) + + YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(int); + YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(short); + YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long); + YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long long); + YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(unsigned); + YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned short); + YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long); + YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long long); - YAML_DEFINE_CONVERT_STREAMABLE(char); - YAML_DEFINE_CONVERT_STREAMABLE(unsigned char); + YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(char); + YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned char); - YAML_DEFINE_CONVERT_STREAMABLE(float); - YAML_DEFINE_CONVERT_STREAMABLE(double); - YAML_DEFINE_CONVERT_STREAMABLE(long double); + YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(float); + YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(double); + YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long double); +#undef YAML_DEFINE_CONVERT_STREAMABLE_SIGNED +#undef YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED #undef YAML_DEFINE_CONVERT_STREAMABLE // bool From 624a9fa9da67cfe5a5c05456cdb4739614b958e2 Mon Sep 17 00:00:00 2001 From: Jesse Beder Date: Mon, 1 Apr 2013 21:52:32 -0500 Subject: [PATCH 18/43] Add missing line from previous fix. --- include/yaml-cpp/node/convert.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/yaml-cpp/node/convert.h b/include/yaml-cpp/node/convert.h index 6a22a3d..a8de752 100644 --- a/include/yaml-cpp/node/convert.h +++ b/include/yaml-cpp/node/convert.h @@ -104,7 +104,7 @@ namespace YAML YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(short); YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long); YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long long); - YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(unsigned); + YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned); YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned short); YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long); YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long long); From 325041a14e62584c34178fed4cc2b07d7a5773b2 Mon Sep 17 00:00:00 2001 From: Jesse Beder Date: Mon, 1 Apr 2013 22:06:09 -0500 Subject: [PATCH 19/43] Explicity disallow get_idx for boolean type, to avoid ambiguity with a map. --- include/yaml-cpp/node/detail/impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/yaml-cpp/node/detail/impl.h b/include/yaml-cpp/node/detail/impl.h index b04fc05..c618758 100644 --- a/include/yaml-cpp/node/detail/impl.h +++ b/include/yaml-cpp/node/detail/impl.h @@ -22,7 +22,7 @@ namespace YAML }; template - struct get_idx >::type> { + struct get_idx::value && !boost::is_same::value>::type> { static node *get(const std::vector& sequence, const Key& key, shared_memory_holder /* pMemory */) { return key < sequence.size() ? sequence[key] : 0; } From e8dcdc8142325c7ab8622730383b66ed67bf6886 Mon Sep 17 00:00:00 2001 From: Jesse Beder Date: Mon, 1 Apr 2013 22:25:53 -0500 Subject: [PATCH 20/43] Fix conversion for C-strings (both literals and normal C-strings) so it compiles on Visual Studio. --- include/yaml-cpp/node/convert.h | 15 +++++++++++++++ include/yaml-cpp/node/detail/impl.h | 7 ++++++- include/yaml-cpp/node/detail/node_data.h | 1 + 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/include/yaml-cpp/node/convert.h b/include/yaml-cpp/node/convert.h index a8de752..146067b 100644 --- a/include/yaml-cpp/node/convert.h +++ b/include/yaml-cpp/node/convert.h @@ -47,7 +47,22 @@ namespace YAML } }; + // C-strings can only be encoded template<> + struct convert { + static Node encode(const char *&rhs) { + return Node(rhs); + } + }; + + template + struct convert { + static Node encode(const char (&rhs)[N]) { + return Node(rhs); + } + }; + + template<> struct convert<_Null> { static Node encode(const _Null& /* rhs */) { return Node(); diff --git a/include/yaml-cpp/node/detail/impl.h b/include/yaml-cpp/node/detail/impl.h index c618758..ce5fd57 100644 --- a/include/yaml-cpp/node/detail/impl.h +++ b/include/yaml-cpp/node/detail/impl.h @@ -149,7 +149,12 @@ namespace YAML return false; } - template + inline bool node_data::equals(node& node, const char *rhs, shared_memory_holder pMemory) + { + return equals(node, rhs, pMemory); + } + + template inline node& node_data::convert_to_node(const T& rhs, shared_memory_holder pMemory) { Node value = convert::encode(rhs); diff --git a/include/yaml-cpp/node/detail/node_data.h b/include/yaml-cpp/node/detail/node_data.h index 7fe05b8..413da5f 100644 --- a/include/yaml-cpp/node/detail/node_data.h +++ b/include/yaml-cpp/node/detail/node_data.h @@ -77,6 +77,7 @@ namespace YAML template static bool equals(node& node, const T& rhs, shared_memory_holder pMemory); + static bool equals(node& node, const char *rhs, shared_memory_holder pMemory); template static node& convert_to_node(const T& rhs, shared_memory_holder pMemory); From 95a8e7c5d39a2a51c523bcb7a8c5f2d3a30d2f06 Mon Sep 17 00:00:00 2001 From: Jesse Beder Date: Tue, 2 Apr 2013 20:39:54 -0500 Subject: [PATCH 21/43] Rename clear() to reset(), and it now takes an optional node parameter. --- include/yaml-cpp/node/impl.h | 5 +++-- include/yaml-cpp/node/node.h | 2 +- test/new-api/nodetests.cpp | 11 ++++++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/include/yaml-cpp/node/impl.h b/include/yaml-cpp/node/impl.h index d46f329..803557c 100644 --- a/include/yaml-cpp/node/impl.h +++ b/include/yaml-cpp/node/impl.h @@ -168,9 +168,10 @@ namespace YAML return *this; } - inline void Node::clear() + inline void Node::reset(const YAML::Node& rhs) { - m_pNode = NULL; + m_pMemory = rhs.m_pMemory; + m_pNode = rhs.m_pNode; } template diff --git a/include/yaml-cpp/node/node.h b/include/yaml-cpp/node/node.h index d4ee442..179716c 100644 --- a/include/yaml-cpp/node/node.h +++ b/include/yaml-cpp/node/node.h @@ -56,7 +56,7 @@ namespace YAML bool is(const Node& rhs) const; template Node& operator=(const T& rhs); Node& operator=(const Node& rhs); - void clear(); + void reset(const Node& rhs = Node()); // size/iterator std::size_t size() const; diff --git a/test/new-api/nodetests.cpp b/test/new-api/nodetests.cpp index bc6d6fa..394a04a 100644 --- a/test/new-api/nodetests.cpp +++ b/test/new-api/nodetests.cpp @@ -444,12 +444,17 @@ namespace Test return true; } - TEST ClearNode() + TEST ResetNode() { YAML::Node node = YAML::Load("[1, 2, 3]"); YAML_ASSERT(!node.IsNull()); - node.clear(); + YAML::Node other = node; + node.reset(); YAML_ASSERT(node.IsNull()); + YAML_ASSERT(!other.IsNull()); + node.reset(other); + YAML_ASSERT(!node.IsNull()); + YAML_ASSERT(other == node); return true; } } @@ -510,7 +515,7 @@ namespace Test RunNodeTest(&Node::CloneMap, "clone map", passed, total); RunNodeTest(&Node::CloneAlias, "clone alias", passed, total); RunNodeTest(&Node::ForceInsertIntoMap, "force insert into map", passed, total); - RunNodeTest(&Node::ClearNode, "clear node", passed, total); + RunNodeTest(&Node::ResetNode, "reset node", passed, total); std::cout << "Node tests: " << passed << "/" << total << " passed\n"; return passed == total; From fc935e03674dc8857d9580ebfcbbe996c779d8a6 Mon Sep 17 00:00:00 2001 From: Jesse Beder Date: Tue, 2 Apr 2013 21:04:17 -0500 Subject: [PATCH 22/43] Add std::pair conversion specialization. --- include/yaml-cpp/node/convert.h | 32 ++++++++++++++++++++++++++++++++ test/new-api/nodetests.cpp | 18 ++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/include/yaml-cpp/node/convert.h b/include/yaml-cpp/node/convert.h index 146067b..1010d7e 100644 --- a/include/yaml-cpp/node/convert.h +++ b/include/yaml-cpp/node/convert.h @@ -223,6 +223,38 @@ namespace YAML } }; + // std::pair + template + struct convert > { + static Node encode(const std::pair& rhs) { + Node node(NodeType::Sequence); + node.push_back(rhs.first); + node.push_back(rhs.second); + return node; + } + + static bool decode(const Node& node, std::pair& rhs) { + if(!node.IsSequence()) + return false; + if (node.size() != 2) + return false; + +#if defined(__GNUC__) && __GNUC__ < 4 +//workaround for GCC 3: + rhs.first = node[0].template as(); +#else + rhs.first = node[0].as(); +#endif +#if defined(__GNUC__) && __GNUC__ < 4 +//workaround for GCC 3: + rhs.second = node[1].template as(); +#else + rhs.second = node[1].as(); +#endif + return true; + } + }; + // binary template<> struct convert { diff --git a/test/new-api/nodetests.cpp b/test/new-api/nodetests.cpp index 394a04a..455709a 100644 --- a/test/new-api/nodetests.cpp +++ b/test/new-api/nodetests.cpp @@ -168,7 +168,19 @@ namespace Test return true; } - TEST SimpleAlias() + TEST StdPair() + { + std::pair p; + p.first = 5; + p.second = "five"; + + YAML::Node node; + node["pair"] = p; + YAML_ASSERT((node["pair"].as >() == p)); + return true; + } + + TEST SimpleAlias() { YAML::Node node; node["foo"] = "value"; @@ -463,8 +475,9 @@ namespace Test TEST ret; try { ret = test(); - } catch(...) { + } catch(const std::exception& e) { ret.ok = false; + ret.error = e.what(); } if(ret.ok) { passed++; @@ -492,6 +505,7 @@ namespace Test RunNodeTest(&Node::StdVector, "std::vector", passed, total); RunNodeTest(&Node::StdList, "std::list", passed, total); RunNodeTest(&Node::StdMap, "std::map", passed, total); + RunNodeTest(&Node::StdPair, "std::pair", passed, total); RunNodeTest(&Node::SimpleAlias, "simple alias", passed, total); RunNodeTest(&Node::AliasAsKey, "alias as key", passed, total); RunNodeTest(&Node::SelfReferenceSequence, "self reference sequence", passed, total); From 3b6b8d05fad39ee4363a7ea9da48abf81b0b893c Mon Sep 17 00:00:00 2001 From: Jesse Beder Date: Fri, 12 Apr 2013 23:41:02 -0500 Subject: [PATCH 23/43] Add better exception reporting when incorrectly dereferencing an iterator. --- include/yaml-cpp/exceptions.h | 9 +++- include/yaml-cpp/node/impl.h | 80 +++++++++++++++++++++++++++++--- include/yaml-cpp/node/iterator.h | 4 +- include/yaml-cpp/node/node.h | 4 ++ test/new-api/nodetests.cpp | 36 ++++++++++++-- 5 files changed, 121 insertions(+), 12 deletions(-) diff --git a/include/yaml-cpp/exceptions.h b/include/yaml-cpp/exceptions.h index 3a2bd22..ffbf7bd 100644 --- a/include/yaml-cpp/exceptions.h +++ b/include/yaml-cpp/exceptions.h @@ -55,6 +55,7 @@ namespace YAML const char * const AMBIGUOUS_ANCHOR = "cannot assign the same alias to multiple nodes"; const char * const UNKNOWN_ANCHOR = "the referenced anchor is not defined"; + const char * const INVALID_NODE = "invalid node; this may result from using a map iterator as a sequence iterator, or vice-versa"; const char * const INVALID_SCALAR = "invalid scalar"; const char * const KEY_NOT_FOUND = "key not found"; const char * const BAD_CONVERSION = "bad conversion"; @@ -149,7 +150,13 @@ namespace YAML return TypedKeyNotFound (mark, key); } - class BadConversion: public RepresentationException { + class InvalidNode: public RepresentationException { + public: + InvalidNode() + : RepresentationException(Mark::null_mark(), ErrorMsg::INVALID_NODE) {} + }; + + class BadConversion: public RepresentationException { public: BadConversion() : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_CONVERSION) {} diff --git a/include/yaml-cpp/node/impl.h b/include/yaml-cpp/node/impl.h index 803557c..41c2fcd 100644 --- a/include/yaml-cpp/node/impl.h +++ b/include/yaml-cpp/node/impl.h @@ -15,30 +15,34 @@ namespace YAML { - inline Node::Node(): m_pNode(NULL) + inline Node::Node(): m_isValid(true), m_pNode(NULL) { } - inline Node::Node(NodeType::value type): m_pMemory(new detail::memory_holder), m_pNode(&m_pMemory->create_node()) + inline Node::Node(NodeType::value type): m_isValid(true), m_pMemory(new detail::memory_holder), m_pNode(&m_pMemory->create_node()) { m_pNode->set_type(type); } template - inline Node::Node(const T& rhs): m_pMemory(new detail::memory_holder), m_pNode(&m_pMemory->create_node()) + inline Node::Node(const T& rhs): m_isValid(true), m_pMemory(new detail::memory_holder), m_pNode(&m_pMemory->create_node()) { Assign(rhs); } - inline Node::Node(const detail::iterator_value& rhs): m_pMemory(rhs.m_pMemory), m_pNode(rhs.m_pNode) + inline Node::Node(const detail::iterator_value& rhs): m_isValid(rhs.m_isValid), m_pMemory(rhs.m_pMemory), m_pNode(rhs.m_pNode) { } - inline Node::Node(const Node& rhs): m_pMemory(rhs.m_pMemory), m_pNode(rhs.m_pNode) + inline Node::Node(const Node& rhs): m_isValid(rhs.m_isValid), m_pMemory(rhs.m_pMemory), m_pNode(rhs.m_pNode) { } - inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory): m_pMemory(pMemory), m_pNode(&node) + inline Node::Node(Zombie): m_isValid(false), m_pNode(NULL) + { + } + + inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory): m_isValid(true), m_pMemory(pMemory), m_pNode(&node) { } @@ -48,6 +52,8 @@ namespace YAML inline void Node::EnsureNodeExists() const { + if(!m_isValid) + throw InvalidNode(); if(!m_pNode) { m_pMemory.reset(new detail::memory_holder); m_pNode = &m_pMemory->create_node(); @@ -57,11 +63,15 @@ namespace YAML inline bool Node::IsDefined() const { + if(!m_isValid) + throw InvalidNode(); return m_pNode ? m_pNode->is_defined() : true; } inline NodeType::value Node::Type() const { + if(!m_isValid) + throw InvalidNode(); return m_pNode ? m_pNode->type() : NodeType::Null; } @@ -128,27 +138,37 @@ namespace YAML template inline const T Node::as() const { + if(!m_isValid) + throw InvalidNode(); return as_if(*this)(); } template inline const T Node::as(const S& fallback) const { + if(!m_isValid) + throw InvalidNode(); return as_if(*this)(fallback); } inline const std::string& Node::Scalar() const { + if(!m_isValid) + throw InvalidNode(); return m_pNode ? m_pNode->scalar() : detail::node_data::empty_scalar; } inline const std::string& Node::Tag() const { + if(!m_isValid) + throw InvalidNode(); return m_pNode ? m_pNode->tag() : detail::node_data::empty_scalar; } inline void Node::SetTag(const std::string& tag) { + if(!m_isValid) + throw InvalidNode(); EnsureNodeExists(); m_pNode->set_tag(tag); } @@ -156,6 +176,8 @@ namespace YAML // assignment inline bool Node::is(const Node& rhs) const { + if(!m_isValid || !rhs.m_isValid) + throw InvalidNode(); if(!m_pNode || !rhs.m_pNode) return false; return m_pNode->is(*rhs.m_pNode); @@ -164,12 +186,16 @@ namespace YAML template inline Node& Node::operator=(const T& rhs) { + if(!m_isValid) + throw InvalidNode(); Assign(rhs); return *this; } inline void Node::reset(const YAML::Node& rhs) { + if(!m_isValid || !rhs.m_isValid) + throw InvalidNode(); m_pMemory = rhs.m_pMemory; m_pNode = rhs.m_pNode; } @@ -177,30 +203,40 @@ namespace YAML template inline void Node::Assign(const T& rhs) { + if(!m_isValid) + throw InvalidNode(); AssignData(convert::encode(rhs)); } template<> inline void Node::Assign(const std::string& rhs) { + if(!m_isValid) + throw InvalidNode(); EnsureNodeExists(); m_pNode->set_scalar(rhs); } inline void Node::Assign(const char *rhs) { + if(!m_isValid) + throw InvalidNode(); EnsureNodeExists(); m_pNode->set_scalar(rhs); } inline void Node::Assign(char *rhs) { + if(!m_isValid) + throw InvalidNode(); EnsureNodeExists(); m_pNode->set_scalar(rhs); } inline Node& Node::operator=(const Node& rhs) { + if(!m_isValid || !rhs.m_isValid) + throw InvalidNode(); if(is(rhs)) return *this; AssignNode(rhs); @@ -209,6 +245,8 @@ namespace YAML inline void Node::AssignData(const Node& rhs) { + if(!m_isValid || !rhs.m_isValid) + throw InvalidNode(); EnsureNodeExists(); rhs.EnsureNodeExists(); @@ -218,6 +256,8 @@ namespace YAML inline void Node::AssignNode(const Node& rhs) { + if(!m_isValid || !rhs.m_isValid) + throw InvalidNode(); rhs.EnsureNodeExists(); if(!m_pNode) { @@ -234,26 +274,36 @@ namespace YAML // size/iterator inline std::size_t Node::size() const { + if(!m_isValid) + throw InvalidNode(); return m_pNode ? m_pNode->size() : 0; } inline const_iterator Node::begin() const { + if(!m_isValid) + throw InvalidNode(); return m_pNode ? const_iterator(m_pNode->begin(), m_pMemory) : const_iterator(); } inline iterator Node::begin() { + if(!m_isValid) + throw InvalidNode(); return m_pNode ? iterator(m_pNode->begin(), m_pMemory) : iterator(); } inline const_iterator Node::end() const { + if(!m_isValid) + throw InvalidNode(); return m_pNode ? const_iterator(m_pNode->end(), m_pMemory) : const_iterator(); } inline iterator Node::end() { + if(!m_isValid) + throw InvalidNode(); return m_pNode ? iterator(m_pNode->end(), m_pMemory) : iterator(); } @@ -261,11 +311,15 @@ namespace YAML template inline void Node::push_back(const T& rhs) { + if(!m_isValid) + throw InvalidNode(); push_back(Node(rhs)); } inline void Node::push_back(const Node& rhs) { + if(!m_isValid || !rhs.m_isValid) + throw InvalidNode(); EnsureNodeExists(); rhs.EnsureNodeExists(); @@ -322,6 +376,8 @@ namespace YAML template inline const Node Node::operator[](const Key& key) const { + if(!m_isValid) + throw InvalidNode(); EnsureNodeExists(); detail::node& value = static_cast(*m_pNode).get(detail::to_value(key), m_pMemory); return Node(value, m_pMemory); @@ -330,6 +386,8 @@ namespace YAML template inline Node Node::operator[](const Key& key) { + if(!m_isValid) + throw InvalidNode(); EnsureNodeExists(); detail::node& value = m_pNode->get(detail::to_value(key), m_pMemory); return Node(value, m_pMemory); @@ -338,12 +396,16 @@ namespace YAML template inline bool Node::remove(const Key& key) { + if(!m_isValid) + throw InvalidNode(); EnsureNodeExists(); return m_pNode->remove(detail::to_value(key), m_pMemory); } inline const Node Node::operator[](const Node& key) const { + if(!m_isValid || !key.m_isValid) + throw InvalidNode(); EnsureNodeExists(); key.EnsureNodeExists(); detail::node& value = static_cast(*m_pNode).get(*key.m_pNode, m_pMemory); @@ -352,6 +414,8 @@ namespace YAML inline Node Node::operator[](const Node& key) { + if(!m_isValid || !key.m_isValid) + throw InvalidNode(); EnsureNodeExists(); key.EnsureNodeExists(); detail::node& value = m_pNode->get(*key.m_pNode, m_pMemory); @@ -360,6 +424,8 @@ namespace YAML inline bool Node::remove(const Node& key) { + if(!m_isValid || !key.m_isValid) + throw InvalidNode(); EnsureNodeExists(); key.EnsureNodeExists(); return m_pNode->remove(*key.m_pNode, m_pMemory); @@ -369,6 +435,8 @@ namespace YAML template inline void Node::force_insert(const Key& key, const Value& value) { + if(!m_isValid) + throw InvalidNode(); EnsureNodeExists(); m_pNode->force_insert(detail::to_value(key), detail::to_value(value), m_pMemory); } diff --git a/include/yaml-cpp/node/iterator.h b/include/yaml-cpp/node/iterator.h index 4cc4719..98c8851 100644 --- a/include/yaml-cpp/node/iterator.h +++ b/include/yaml-cpp/node/iterator.h @@ -19,8 +19,8 @@ namespace YAML namespace detail { struct iterator_value: public Node, std::pair { iterator_value() {} - explicit iterator_value(const Node& rhs): Node(rhs) {} - explicit iterator_value(const Node& key, const Node& value): std::pair(key, value) {} + explicit iterator_value(const Node& rhs): Node(rhs), std::pair(Node(Node::ZombieNode), Node(Node::ZombieNode)) {} + explicit iterator_value(const Node& key, const Node& value): Node(Node::ZombieNode), std::pair(key, value) {} }; } } diff --git a/include/yaml-cpp/node/node.h b/include/yaml-cpp/node/node.h index 179716c..b949850 100644 --- a/include/yaml-cpp/node/node.h +++ b/include/yaml-cpp/node/node.h @@ -20,6 +20,7 @@ namespace YAML public: friend class NodeBuilder; friend class NodeEvents; + friend struct detail::iterator_value; friend class detail::node_data; template friend class detail::iterator_base; template friend struct as_if; @@ -85,6 +86,8 @@ namespace YAML void force_insert(const Key& key, const Value& value); private: + enum Zombie { ZombieNode }; + explicit Node(Zombie); explicit Node(detail::node& node, detail::shared_memory_holder pMemory); void EnsureNodeExists() const; @@ -97,6 +100,7 @@ namespace YAML void AssignNode(const Node& rhs); private: + bool m_isValid; mutable detail::shared_memory_holder m_pMemory; mutable detail::node *m_pNode; }; diff --git a/test/new-api/nodetests.cpp b/test/new-api/nodetests.cpp index 455709a..4b2240c 100644 --- a/test/new-api/nodetests.cpp +++ b/test/new-api/nodetests.cpp @@ -8,15 +8,33 @@ namespace { TEST(): ok(false) {} TEST(bool ok_): ok(ok_) {} TEST(const char *error_): ok(false), error(error_) {} + TEST(const std::string& error_): ok(false), error(error_) {} bool ok; std::string error; }; } -#define YAML_ASSERT(cond) do { if(!(cond)) return " Assert failed: " #cond; } while(false) +#define YAML_ASSERT(cond)\ + do {\ + if(!(cond))\ + return " Assert failed: " #cond;\ + } while(false) -#define YAML_ASSERT_THROWS(cond, exc) do { try { (cond); return " Expression did not throw: " #cond; } catch(const exc&) {} catch(...) { return " Expression threw something other than " #exc ": " #cond; } } while(false) +#define YAML_ASSERT_THROWS(cond, exc)\ + do {\ + try {\ + (cond);\ + return " Expression did not throw: " #cond;\ + } catch(const exc&) {\ + } catch(const std::runtime_error& e) {\ + std::stringstream stream;\ + stream << " Expression threw runtime error ther than " #exc ":\n " #cond "\n " << e.what();\ + return stream.str();\ + } catch(...) {\ + return " Expression threw unknown exception, other than " #exc ":\n " #cond;\ + }\ + } while(false) namespace Test { @@ -319,7 +337,7 @@ namespace Test YAML::Node node = YAML::Load("[1.5, 1, .nan, .inf, -.inf, 0x15, 015]"); YAML_ASSERT(node[0].as() == 1.5f); YAML_ASSERT(node[0].as() == 1.5); - YAML_ASSERT_THROWS(node[0].as(), std::runtime_error); + YAML_ASSERT_THROWS(node[0].as(), YAML::TypedBadConversion); YAML_ASSERT(node[1].as() == 1); YAML_ASSERT(node[1].as() == 1.0f); YAML_ASSERT(node[2].as() != node[2].as()); @@ -469,6 +487,17 @@ namespace Test YAML_ASSERT(other == node); return true; } + + TEST DereferenceIteratorError() + { + YAML::Node node = YAML::Load("[{a: b}, 1, 2]"); + YAML_ASSERT_THROWS(node.begin()->first.as(), YAML::InvalidNode); + YAML_ASSERT((*node.begin()).IsMap() == true); + YAML_ASSERT(node.begin()->IsMap() == true); + YAML_ASSERT_THROWS((*node.begin()->begin()).IsDefined(), YAML::InvalidNode); + YAML_ASSERT_THROWS(node.begin()->begin()->IsDefined(), YAML::InvalidNode); + return true; + } } void RunNodeTest(TEST (*test)(), const std::string& name, int& passed, int& total) { @@ -530,6 +559,7 @@ namespace Test RunNodeTest(&Node::CloneAlias, "clone alias", passed, total); RunNodeTest(&Node::ForceInsertIntoMap, "force insert into map", passed, total); RunNodeTest(&Node::ResetNode, "reset node", passed, total); + RunNodeTest(&Node::DereferenceIteratorError, "dereference iterator error", passed, total); std::cout << "Node tests: " << passed << "/" << total << " passed\n"; return passed == total; From 21e8612136461a3b895e4d2659ed6540c7b2a3ff Mon Sep 17 00:00:00 2001 From: Jesse Beder Date: Sat, 13 Apr 2013 13:10:36 -0500 Subject: [PATCH 24/43] Fix floating point precision on input. --- include/yaml-cpp/node/convert.h | 1 + test/new-api/nodetests.cpp | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/include/yaml-cpp/node/convert.h b/include/yaml-cpp/node/convert.h index 1010d7e..d73f284 100644 --- a/include/yaml-cpp/node/convert.h +++ b/include/yaml-cpp/node/convert.h @@ -78,6 +78,7 @@ namespace YAML struct convert {\ static Node encode(const type& rhs) {\ std::stringstream stream;\ + stream.precision(std::numeric_limits::digits10 + 1);\ stream << rhs;\ return Node(stream.str());\ }\ diff --git a/test/new-api/nodetests.cpp b/test/new-api/nodetests.cpp index 4b2240c..e1140f8 100644 --- a/test/new-api/nodetests.cpp +++ b/test/new-api/nodetests.cpp @@ -498,6 +498,14 @@ namespace Test YAML_ASSERT_THROWS(node.begin()->begin()->IsDefined(), YAML::InvalidNode); return true; } + + TEST FloatingPrecision() + { + const double x = 0.123456789; + YAML::Node node = YAML::Node(x); + YAML_ASSERT(node.as() == x); + return true; + } } void RunNodeTest(TEST (*test)(), const std::string& name, int& passed, int& total) { @@ -560,6 +568,7 @@ namespace Test RunNodeTest(&Node::ForceInsertIntoMap, "force insert into map", passed, total); RunNodeTest(&Node::ResetNode, "reset node", passed, total); RunNodeTest(&Node::DereferenceIteratorError, "dereference iterator error", passed, total); + RunNodeTest(&Node::FloatingPrecision, "floating precision", passed, total); std::cout << "Node tests: " << passed << "/" << total << " passed\n"; return passed == total; From 967f7b5249768743153046980d15be36b015bca4 Mon Sep 17 00:00:00 2001 From: beder Date: Sat, 13 Apr 2013 18:37:33 -0500 Subject: [PATCH 25/43] Bumped version to 0.5.1 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c56c53..4cefdbf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ project(YAML_CPP) set(YAML_CPP_VERSION_MAJOR "0") set(YAML_CPP_VERSION_MINOR "5") -set(YAML_CPP_VERSION_PATCH "0") +set(YAML_CPP_VERSION_PATCH "1") set(YAML_CPP_VERSION "${YAML_CPP_VERSION_MAJOR}.${YAML_CPP_VERSION_MINOR}.${YAML_CPP_VERSION_PATCH}") enable_testing() From 2a3bfca31af8483b145e4f91281885fadbcbc040 Mon Sep 17 00:00:00 2001 From: beder Date: Sat, 13 Apr 2013 18:45:50 -0500 Subject: [PATCH 26/43] Added tag release-0.5.1 for changeset 98e9aefe6778 From 4242c39a9eadd85ea5d009ff2fdfbcc4b284fdbd Mon Sep 17 00:00:00 2001 From: beder Date: Wed, 10 Jul 2013 08:29:11 -0500 Subject: [PATCH 27/43] Fixed crash when emitting empty node --- src/nodeevents.cpp | 8 +++++--- src/nodeevents.h | 2 +- src/ostream_wrapper.cpp | 2 +- test/new-api/nodetests.cpp | 10 ++++++++++ 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/nodeevents.cpp b/src/nodeevents.cpp index 721f9c6..879c2ce 100644 --- a/src/nodeevents.cpp +++ b/src/nodeevents.cpp @@ -19,9 +19,10 @@ namespace YAML return it->second; } - NodeEvents::NodeEvents(const Node& node): m_pMemory(node.m_pMemory), m_root(*node.m_pNode) + NodeEvents::NodeEvents(const Node& node): m_pMemory(node.m_pMemory), m_root(node.m_pNode) { - Setup(m_root); + if(m_root) + Setup(*m_root); } void NodeEvents::Setup(const detail::node& node) @@ -47,7 +48,8 @@ namespace YAML AliasManager am; handler.OnDocumentStart(Mark()); - Emit(m_root, handler, am); + if(m_root) + Emit(*m_root, handler, am); handler.OnDocumentEnd(); } diff --git a/src/nodeevents.h b/src/nodeevents.h index d142115..ba31226 100644 --- a/src/nodeevents.h +++ b/src/nodeevents.h @@ -46,7 +46,7 @@ namespace YAML private: detail::shared_memory_holder m_pMemory; - detail::node& m_root; + detail::node* m_root; typedef std::map RefCount; RefCount m_refCount; diff --git a/src/ostream_wrapper.cpp b/src/ostream_wrapper.cpp index 15d9f0f..66cafda 100644 --- a/src/ostream_wrapper.cpp +++ b/src/ostream_wrapper.cpp @@ -4,7 +4,7 @@ namespace YAML { - ostream_wrapper::ostream_wrapper(): m_pStream(0), m_pos(0), m_row(0), m_col(0), m_comment(false) + ostream_wrapper::ostream_wrapper(): m_buffer(1), m_pStream(0), m_pos(0), m_row(0), m_col(0), m_comment(false) { } diff --git a/test/new-api/nodetests.cpp b/test/new-api/nodetests.cpp index e1140f8..cb53ad8 100644 --- a/test/new-api/nodetests.cpp +++ b/test/new-api/nodetests.cpp @@ -506,6 +506,15 @@ namespace Test YAML_ASSERT(node.as() == x); return true; } + + TEST EmitEmptyNode() + { + YAML::Node node; + YAML::Emitter emitter; + emitter << node; + YAML_ASSERT(std::string(emitter.c_str()) == ""); + return true; + } } void RunNodeTest(TEST (*test)(), const std::string& name, int& passed, int& total) { @@ -569,6 +578,7 @@ namespace Test RunNodeTest(&Node::ResetNode, "reset node", passed, total); RunNodeTest(&Node::DereferenceIteratorError, "dereference iterator error", passed, total); RunNodeTest(&Node::FloatingPrecision, "floating precision", passed, total); + RunNodeTest(&Node::EmitEmptyNode, "emit empty node", passed, total); std::cout << "Node tests: " << passed << "/" << total << " passed\n"; return passed == total; From b552fe0a96c47b1599a56f95f89b8ed52eb54d45 Mon Sep 17 00:00:00 2001 From: beder Date: Sun, 13 Oct 2013 11:14:34 -0500 Subject: [PATCH 28/43] Add ifdef to check if BOOST_FOREACH is defined, and disable tests that use it if it is not available --- test/new-api/nodetests.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/test/new-api/nodetests.cpp b/test/new-api/nodetests.cpp index cb53ad8..b002431 100644 --- a/test/new-api/nodetests.cpp +++ b/test/new-api/nodetests.cpp @@ -1,8 +1,13 @@ #include "nodetests.h" #include "yaml-cpp/yaml.h" -#include #include +#include + +#if BOOST_VERSION >= 103400 +#include +#endif + namespace { struct TEST { TEST(): ok(false) {} @@ -382,7 +387,8 @@ namespace Test YAML_ASSERT(i == 3); return true; } - + +#ifdef BOOST_FOREACH TEST ForEach() { YAML::Node node = YAML::Load("[1, 3, 5, 7]"); @@ -403,6 +409,7 @@ namespace Test } return true; } +#endif TEST CloneScalar() { @@ -568,8 +575,10 @@ namespace Test RunNodeTest(&Node::Binary, "binary", passed, total); RunNodeTest(&Node::IterateSequence, "iterate sequence", passed, total); RunNodeTest(&Node::IterateMap, "iterate map", passed, total); +#ifdef BOOST_FOREACH RunNodeTest(&Node::ForEach, "for each", passed, total); RunNodeTest(&Node::ForEachMap, "for each map", passed, total); +#endif RunNodeTest(&Node::CloneScalar, "clone scalar", passed, total); RunNodeTest(&Node::CloneSeq, "clone seq", passed, total); RunNodeTest(&Node::CloneMap, "clone map", passed, total); From 23a03d2d6ee85494e2ad3da9d3dadd7124e4e1e1 Mon Sep 17 00:00:00 2001 From: beder Date: Sun, 10 Nov 2013 14:50:35 -0600 Subject: [PATCH 29/43] Fixed bug while reading a single space char --- include/yaml-cpp/node/convert.h | 2 +- test/new-api/nodetests.cpp | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/yaml-cpp/node/convert.h b/include/yaml-cpp/node/convert.h index d73f284..63ab9d7 100644 --- a/include/yaml-cpp/node/convert.h +++ b/include/yaml-cpp/node/convert.h @@ -89,7 +89,7 @@ namespace YAML const std::string& input = node.Scalar();\ std::stringstream stream(input);\ stream.unsetf(std::ios::dec);\ - if((stream >> rhs) && (stream >> std::ws).eof())\ + if((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof())\ return true;\ if(std::numeric_limits::has_infinity) {\ if(conversion::IsInfinity(input)) {\ diff --git a/test/new-api/nodetests.cpp b/test/new-api/nodetests.cpp index b002431..cb6a0c5 100644 --- a/test/new-api/nodetests.cpp +++ b/test/new-api/nodetests.cpp @@ -522,6 +522,13 @@ namespace Test YAML_ASSERT(std::string(emitter.c_str()) == ""); return true; } + + TEST SpaceChar() + { + YAML::Node node = YAML::Node(' '); + YAML_ASSERT(node.as() == ' '); + return true; + } } void RunNodeTest(TEST (*test)(), const std::string& name, int& passed, int& total) { @@ -588,6 +595,7 @@ namespace Test RunNodeTest(&Node::DereferenceIteratorError, "dereference iterator error", passed, total); RunNodeTest(&Node::FloatingPrecision, "floating precision", passed, total); RunNodeTest(&Node::EmitEmptyNode, "emit empty node", passed, total); + RunNodeTest(&Node::SpaceChar, "space char", passed, total); std::cout << "Node tests: " << passed << "/" << total << " passed\n"; return passed == total; From 9d66a6c5617e0152303f992387edcfb061f8fdbe Mon Sep 17 00:00:00 2001 From: beder Date: Sat, 22 Mar 2014 13:05:03 -0500 Subject: [PATCH 30/43] Run clang-format --- include/yaml-cpp/dll.h | 2 +- include/yaml-cpp/exceptions.h | 401 +-- include/yaml-cpp/node/convert.h | 467 ++- include/yaml-cpp/node/detail/bool_type.h | 34 +- include/yaml-cpp/node/detail/impl.h | 308 +- include/yaml-cpp/node/detail/iterator.h | 98 +- include/yaml-cpp/node/detail/iterator_fwd.h | 27 +- include/yaml-cpp/node/detail/memory.h | 52 +- include/yaml-cpp/node/detail/node.h | 235 +- include/yaml-cpp/node/detail/node_data.h | 182 +- include/yaml-cpp/node/detail/node_iterator.h | 254 +- include/yaml-cpp/node/detail/node_ref.h | 130 +- include/yaml-cpp/node/emit.h | 24 +- include/yaml-cpp/node/impl.h | 838 +++--- include/yaml-cpp/node/iterator.h | 27 +- include/yaml-cpp/node/node.h | 202 +- include/yaml-cpp/node/parse.h | 30 +- include/yaml-cpp/node/ptr.h | 34 +- include/yaml-cpp/node/type.h | 20 +- include/yaml-cpp/parser.h | 57 +- include/yaml-cpp/yaml.h | 6 +- src/convert.cpp | 142 +- src/emit.cpp | 42 +- src/memory.cpp | 45 +- src/node.cpp | 16 +- src/node_data.cpp | 560 ++-- src/nodebuilder.cpp | 246 +- src/nodebuilder.h | 90 +- src/nodeevents.cpp | 186 +- src/nodeevents.h | 88 +- src/ostream_wrapper.cpp | 95 +- src/parse.cpp | 115 +- src/stream.cpp | 12 +- test/emittertests.cpp | 2347 +++++++-------- test/new-api/nodetests.cpp | 1166 ++++---- test/new-api/parsertests.cpp | 5 +- test/new-api/spectests.cpp | 2776 +++++++++--------- test/nodetests.h | 9 +- test/tests.cpp | 33 +- util/parse.cpp | 83 +- 40 files changed, 5797 insertions(+), 5687 deletions(-) diff --git a/include/yaml-cpp/dll.h b/include/yaml-cpp/dll.h index df04cc8..827e0f1 100644 --- a/include/yaml-cpp/dll.h +++ b/include/yaml-cpp/dll.h @@ -30,7 +30,7 @@ // #pragma message( "Defining YAML_CPP_API for DLL import" ) #define YAML_CPP_API __declspec(dllimport) #endif // yaml_cpp_EXPORTS -#else // YAML_CPP_DLL +#else // YAML_CPP_DLL #define YAML_CPP_API #endif // YAML_CPP_DLL diff --git a/include/yaml-cpp/exceptions.h b/include/yaml-cpp/exceptions.h index ffbf7bd..cdf766e 100644 --- a/include/yaml-cpp/exceptions.h +++ b/include/yaml-cpp/exceptions.h @@ -1,208 +1,227 @@ #ifndef EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif - #include "yaml-cpp/mark.h" #include "yaml-cpp/traits.h" #include #include #include -namespace YAML -{ - // error messages - namespace ErrorMsg - { - const char * const YAML_DIRECTIVE_ARGS = "YAML directives must have exactly one argument"; - const char * const YAML_VERSION = "bad YAML version: "; - const char * const YAML_MAJOR_VERSION = "YAML major version too large"; - const char * const REPEATED_YAML_DIRECTIVE= "repeated YAML directive"; - const char * const TAG_DIRECTIVE_ARGS = "TAG directives must have exactly two arguments"; - const char * const REPEATED_TAG_DIRECTIVE = "repeated TAG directive"; - const char * const CHAR_IN_TAG_HANDLE = "illegal character found while scanning tag handle"; - const char * const TAG_WITH_NO_SUFFIX = "tag handle with no suffix"; - const char * const END_OF_VERBATIM_TAG = "end of verbatim tag not found"; - const char * const END_OF_MAP = "end of map not found"; - const char * const END_OF_MAP_FLOW = "end of map flow not found"; - const char * const END_OF_SEQ = "end of sequence not found"; - const char * const END_OF_SEQ_FLOW = "end of sequence flow not found"; - const char * const MULTIPLE_TAGS = "cannot assign multiple tags to the same node"; - const char * const MULTIPLE_ANCHORS = "cannot assign multiple anchors to the same node"; - const char * const MULTIPLE_ALIASES = "cannot assign multiple aliases to the same node"; - const char * const ALIAS_CONTENT = "aliases can't have any content, *including* tags"; - const char * const INVALID_HEX = "bad character found while scanning hex number"; - const char * const INVALID_UNICODE = "invalid unicode: "; - const char * const INVALID_ESCAPE = "unknown escape character: "; - const char * const UNKNOWN_TOKEN = "unknown token"; - const char * const DOC_IN_SCALAR = "illegal document indicator in scalar"; - const char * const EOF_IN_SCALAR = "illegal EOF in scalar"; - const char * const CHAR_IN_SCALAR = "illegal character in scalar"; - const char * const TAB_IN_INDENTATION = "illegal tab when looking for indentation"; - const char * const FLOW_END = "illegal flow end"; - const char * const BLOCK_ENTRY = "illegal block entry"; - const char * const MAP_KEY = "illegal map key"; - const char * const MAP_VALUE = "illegal map value"; - const char * const ALIAS_NOT_FOUND = "alias not found after *"; - const char * const ANCHOR_NOT_FOUND = "anchor not found after &"; - const char * const CHAR_IN_ALIAS = "illegal character found while scanning alias"; - const char * const CHAR_IN_ANCHOR = "illegal character found while scanning anchor"; - const char * const ZERO_INDENT_IN_BLOCK = "cannot set zero indentation for a block scalar"; - const char * const CHAR_IN_BLOCK = "unexpected character in block scalar"; - const char * const AMBIGUOUS_ANCHOR = "cannot assign the same alias to multiple nodes"; - const char * const UNKNOWN_ANCHOR = "the referenced anchor is not defined"; +namespace YAML { +// error messages +namespace ErrorMsg { +const char* const YAML_DIRECTIVE_ARGS = + "YAML directives must have exactly one argument"; +const char* const YAML_VERSION = "bad YAML version: "; +const char* const YAML_MAJOR_VERSION = "YAML major version too large"; +const char* const REPEATED_YAML_DIRECTIVE = "repeated YAML directive"; +const char* const TAG_DIRECTIVE_ARGS = + "TAG directives must have exactly two arguments"; +const char* const REPEATED_TAG_DIRECTIVE = "repeated TAG directive"; +const char* const CHAR_IN_TAG_HANDLE = + "illegal character found while scanning tag handle"; +const char* const TAG_WITH_NO_SUFFIX = "tag handle with no suffix"; +const char* const END_OF_VERBATIM_TAG = "end of verbatim tag not found"; +const char* const END_OF_MAP = "end of map not found"; +const char* const END_OF_MAP_FLOW = "end of map flow not found"; +const char* const END_OF_SEQ = "end of sequence not found"; +const char* const END_OF_SEQ_FLOW = "end of sequence flow not found"; +const char* const MULTIPLE_TAGS = + "cannot assign multiple tags to the same node"; +const char* const MULTIPLE_ANCHORS = + "cannot assign multiple anchors to the same node"; +const char* const MULTIPLE_ALIASES = + "cannot assign multiple aliases to the same node"; +const char* const ALIAS_CONTENT = + "aliases can't have any content, *including* tags"; +const char* const INVALID_HEX = "bad character found while scanning hex number"; +const char* const INVALID_UNICODE = "invalid unicode: "; +const char* const INVALID_ESCAPE = "unknown escape character: "; +const char* const UNKNOWN_TOKEN = "unknown token"; +const char* const DOC_IN_SCALAR = "illegal document indicator in scalar"; +const char* const EOF_IN_SCALAR = "illegal EOF in scalar"; +const char* const CHAR_IN_SCALAR = "illegal character in scalar"; +const char* const TAB_IN_INDENTATION = + "illegal tab when looking for indentation"; +const char* const FLOW_END = "illegal flow end"; +const char* const BLOCK_ENTRY = "illegal block entry"; +const char* const MAP_KEY = "illegal map key"; +const char* const MAP_VALUE = "illegal map value"; +const char* const ALIAS_NOT_FOUND = "alias not found after *"; +const char* const ANCHOR_NOT_FOUND = "anchor not found after &"; +const char* const CHAR_IN_ALIAS = + "illegal character found while scanning alias"; +const char* const CHAR_IN_ANCHOR = + "illegal character found while scanning anchor"; +const char* const ZERO_INDENT_IN_BLOCK = + "cannot set zero indentation for a block scalar"; +const char* const CHAR_IN_BLOCK = "unexpected character in block scalar"; +const char* const AMBIGUOUS_ANCHOR = + "cannot assign the same alias to multiple nodes"; +const char* const UNKNOWN_ANCHOR = "the referenced anchor is not defined"; - const char * const INVALID_NODE = "invalid node; this may result from using a map iterator as a sequence iterator, or vice-versa"; - const char * const INVALID_SCALAR = "invalid scalar"; - const char * const KEY_NOT_FOUND = "key not found"; - const char * const BAD_CONVERSION = "bad conversion"; - const char * const BAD_DEREFERENCE = "bad dereference"; - const char * const BAD_SUBSCRIPT = "operator[] call on a scalar"; - const char * const BAD_PUSHBACK = "appending to a non-sequence"; - const char * const BAD_INSERT = "inserting in a non-convertible-to-map"; - - const char * const UNMATCHED_GROUP_TAG = "unmatched group tag"; - const char * const UNEXPECTED_END_SEQ = "unexpected end sequence token"; - const char * const UNEXPECTED_END_MAP = "unexpected end map token"; - const char * const SINGLE_QUOTED_CHAR = "invalid character in single-quoted string"; - const char * const INVALID_ANCHOR = "invalid anchor"; - const char * const INVALID_ALIAS = "invalid alias"; - const char * const INVALID_TAG = "invalid tag"; - const char * const BAD_FILE = "bad file"; +const char* const INVALID_NODE = + "invalid node; this may result from using a map iterator as a sequence " + "iterator, or vice-versa"; +const char* const INVALID_SCALAR = "invalid scalar"; +const char* const KEY_NOT_FOUND = "key not found"; +const char* const BAD_CONVERSION = "bad conversion"; +const char* const BAD_DEREFERENCE = "bad dereference"; +const char* const BAD_SUBSCRIPT = "operator[] call on a scalar"; +const char* const BAD_PUSHBACK = "appending to a non-sequence"; +const char* const BAD_INSERT = "inserting in a non-convertible-to-map"; - template - inline const std::string KEY_NOT_FOUND_WITH_KEY(const T&, typename disable_if >::type * = 0) { - return KEY_NOT_FOUND; - } +const char* const UNMATCHED_GROUP_TAG = "unmatched group tag"; +const char* const UNEXPECTED_END_SEQ = "unexpected end sequence token"; +const char* const UNEXPECTED_END_MAP = "unexpected end map token"; +const char* const SINGLE_QUOTED_CHAR = + "invalid character in single-quoted string"; +const char* const INVALID_ANCHOR = "invalid anchor"; +const char* const INVALID_ALIAS = "invalid alias"; +const char* const INVALID_TAG = "invalid tag"; +const char* const BAD_FILE = "bad file"; - inline const std::string KEY_NOT_FOUND_WITH_KEY(const std::string& key) { - std::stringstream stream; - stream << KEY_NOT_FOUND << ": " << key; - return stream.str(); - } - - template - inline const std::string KEY_NOT_FOUND_WITH_KEY(const T& key, typename enable_if >::type * = 0) { - std::stringstream stream; - stream << KEY_NOT_FOUND << ": " << key; - return stream.str(); - } - } - - class Exception: public std::runtime_error { - public: - Exception(const Mark& mark_, const std::string& msg_) - : std::runtime_error(build_what(mark_, msg_)), mark(mark_), msg(msg_) {} - virtual ~Exception() throw() {} - - Mark mark; - std::string msg; - - private: - static const std::string build_what(const Mark& mark, const std::string& msg) { - std::stringstream output; - output << "yaml-cpp: error at line " << mark.line+1 << ", column " << mark.column+1 << ": " << msg; - return output.str(); - } - }; - - class ParserException: public Exception { - public: - ParserException(const Mark& mark_, const std::string& msg_) - : Exception(mark_, msg_) {} - }; - - class RepresentationException: public Exception { - public: - RepresentationException(const Mark& mark_, const std::string& msg_) - : Exception(mark_, msg_) {} - }; - - // representation exceptions - class InvalidScalar: public RepresentationException { - public: - InvalidScalar(const Mark& mark_) - : RepresentationException(mark_, ErrorMsg::INVALID_SCALAR) {} - }; - - class KeyNotFound: public RepresentationException { - public: - template - KeyNotFound(const Mark& mark_, const T& key_) - : RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) {} - }; - - template - class TypedKeyNotFound: public KeyNotFound { - public: - TypedKeyNotFound(const Mark& mark_, const T& key_) - : KeyNotFound(mark_, key_), key(key_) {} - virtual ~TypedKeyNotFound() throw() {} - - T key; - }; - - template - inline TypedKeyNotFound MakeTypedKeyNotFound(const Mark& mark, const T& key) { - return TypedKeyNotFound (mark, key); - } - - class InvalidNode: public RepresentationException { - public: - InvalidNode() - : RepresentationException(Mark::null_mark(), ErrorMsg::INVALID_NODE) {} - }; - - class BadConversion: public RepresentationException { - public: - BadConversion() - : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_CONVERSION) {} - }; - - template - class TypedBadConversion: public BadConversion { - public: - TypedBadConversion() - : BadConversion() {} - }; - - class BadDereference: public RepresentationException { - public: - BadDereference() - : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_DEREFERENCE) {} - }; - - class BadSubscript: public RepresentationException { - public: - BadSubscript() - : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_SUBSCRIPT) {} - }; - - class BadPushback: public RepresentationException { - public: - BadPushback() - : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_PUSHBACK) {} - }; - - class BadInsert: public RepresentationException { - public: - BadInsert() - : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_INSERT) {} - }; - - class EmitterException: public Exception { - public: - EmitterException(const std::string& msg_) - : Exception(Mark::null_mark(), msg_) {} - }; - - class BadFile: public Exception { - public: - BadFile(): Exception(Mark::null_mark(), ErrorMsg::BAD_FILE) {} - }; +template +inline const std::string KEY_NOT_FOUND_WITH_KEY( + const T&, typename disable_if >::type* = 0) { + return KEY_NOT_FOUND; } -#endif // EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +inline const std::string KEY_NOT_FOUND_WITH_KEY(const std::string& key) { + std::stringstream stream; + stream << KEY_NOT_FOUND << ": " << key; + return stream.str(); +} + +template +inline const std::string KEY_NOT_FOUND_WITH_KEY( + const T& key, typename enable_if >::type* = 0) { + std::stringstream stream; + stream << KEY_NOT_FOUND << ": " << key; + return stream.str(); +} +} + +class Exception : public std::runtime_error { + public: + Exception(const Mark& mark_, const std::string& msg_) + : std::runtime_error(build_what(mark_, msg_)), mark(mark_), msg(msg_) {} + virtual ~Exception() throw() {} + + Mark mark; + std::string msg; + + private: + static const std::string build_what(const Mark& mark, + const std::string& msg) { + std::stringstream output; + output << "yaml-cpp: error at line " << mark.line + 1 << ", column " + << mark.column + 1 << ": " << msg; + return output.str(); + } +}; + +class ParserException : public Exception { + public: + ParserException(const Mark& mark_, const std::string& msg_) + : Exception(mark_, msg_) {} +}; + +class RepresentationException : public Exception { + public: + RepresentationException(const Mark& mark_, const std::string& msg_) + : Exception(mark_, msg_) {} +}; + +// representation exceptions +class InvalidScalar : public RepresentationException { + public: + InvalidScalar(const Mark& mark_) + : RepresentationException(mark_, ErrorMsg::INVALID_SCALAR) {} +}; + +class KeyNotFound : public RepresentationException { + public: + template + KeyNotFound(const Mark& mark_, const T& key_) + : RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) { + } +}; + +template +class TypedKeyNotFound : public KeyNotFound { + public: + TypedKeyNotFound(const Mark& mark_, const T& key_) + : KeyNotFound(mark_, key_), key(key_) {} + virtual ~TypedKeyNotFound() throw() {} + + T key; +}; + +template +inline TypedKeyNotFound MakeTypedKeyNotFound(const Mark& mark, + const T& key) { + return TypedKeyNotFound(mark, key); +} + +class InvalidNode : public RepresentationException { + public: + InvalidNode() + : RepresentationException(Mark::null_mark(), ErrorMsg::INVALID_NODE) {} +}; + +class BadConversion : public RepresentationException { + public: + BadConversion() + : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_CONVERSION) {} +}; + +template +class TypedBadConversion : public BadConversion { + public: + TypedBadConversion() : BadConversion() {} +}; + +class BadDereference : public RepresentationException { + public: + BadDereference() + : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_DEREFERENCE) {} +}; + +class BadSubscript : public RepresentationException { + public: + BadSubscript() + : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_SUBSCRIPT) {} +}; + +class BadPushback : public RepresentationException { + public: + BadPushback() + : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_PUSHBACK) {} +}; + +class BadInsert : public RepresentationException { + public: + BadInsert() + : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_INSERT) {} +}; + +class EmitterException : public Exception { + public: + EmitterException(const std::string& msg_) + : Exception(Mark::null_mark(), msg_) {} +}; + +class BadFile : public Exception { + public: + BadFile() : Exception(Mark::null_mark(), ErrorMsg::BAD_FILE) {} +}; +} + +#endif // EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/convert.h b/include/yaml-cpp/node/convert.h index 63ab9d7..76ceee5 100644 --- a/include/yaml-cpp/node/convert.h +++ b/include/yaml-cpp/node/convert.h @@ -1,11 +1,12 @@ #ifndef NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif - #include "yaml-cpp/binary.h" #include "yaml-cpp/node/node.h" #include "yaml-cpp/node/iterator.h" @@ -16,265 +17,259 @@ #include #include -namespace YAML -{ - namespace conversion { - inline bool IsInfinity(const std::string& input) { - return input == ".inf" || input == ".Inf" || input == ".INF" || input == "+.inf" || input == "+.Inf" || input == "+.INF"; - } - - inline bool IsNegativeInfinity(const std::string& input) { - return input == "-.inf" || input == "-.Inf" || input == "-.INF"; - } - - inline bool IsNaN(const std::string& input) { - return input == ".nan" || input == ".NaN" || input == ".NAN"; - } - } - - // std::string - template<> - struct convert { - static Node encode(const std::string& rhs) { - return Node(rhs); - } - - static bool decode(const Node& node, std::string& rhs) { - if(!node.IsScalar()) - return false; - rhs = node.Scalar(); - return true; - } - }; - - // C-strings can only be encoded - template<> - struct convert { - static Node encode(const char *&rhs) { - return Node(rhs); - } - }; +namespace YAML { +namespace conversion { +inline bool IsInfinity(const std::string& input) { + return input == ".inf" || input == ".Inf" || input == ".INF" || + input == "+.inf" || input == "+.Inf" || input == "+.INF"; +} - template - struct convert { - static Node encode(const char (&rhs)[N]) { - return Node(rhs); - } - }; +inline bool IsNegativeInfinity(const std::string& input) { + return input == "-.inf" || input == "-.Inf" || input == "-.INF"; +} - template<> - struct convert<_Null> { - static Node encode(const _Null& /* rhs */) { - return Node(); - } - - static bool decode(const Node& node, _Null& /* rhs */) { - return node.IsNull(); - } - }; - -#define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op)\ - template<>\ - struct convert {\ - static Node encode(const type& rhs) {\ - std::stringstream stream;\ - stream.precision(std::numeric_limits::digits10 + 1);\ - stream << rhs;\ - return Node(stream.str());\ - }\ - \ - static bool decode(const Node& node, type& rhs) {\ - if(node.Type() != NodeType::Scalar)\ - return false;\ - const std::string& input = node.Scalar();\ - std::stringstream stream(input);\ - stream.unsetf(std::ios::dec);\ - if((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof())\ - return true;\ - if(std::numeric_limits::has_infinity) {\ - if(conversion::IsInfinity(input)) {\ - rhs = std::numeric_limits::infinity();\ - return true;\ - } else if(conversion::IsNegativeInfinity(input)) {\ - rhs = negative_op std::numeric_limits::infinity();\ - return true;\ - }\ - }\ - \ - if(std::numeric_limits::has_quiet_NaN && conversion::IsNaN(input)) {\ - rhs = std::numeric_limits::quiet_NaN();\ - return true;\ - }\ - \ - return false;\ - }\ - } - -#define YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(type)\ - YAML_DEFINE_CONVERT_STREAMABLE(type, -) +inline bool IsNaN(const std::string& input) { + return input == ".nan" || input == ".NaN" || input == ".NAN"; +} +} -#define YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(type)\ - YAML_DEFINE_CONVERT_STREAMABLE(type, +) +// std::string +template <> +struct convert { + static Node encode(const std::string& rhs) { return Node(rhs); } + + static bool decode(const Node& node, std::string& rhs) { + if (!node.IsScalar()) + return false; + rhs = node.Scalar(); + return true; + } +}; + +// C-strings can only be encoded +template <> +struct convert { + static Node encode(const char*& rhs) { return Node(rhs); } +}; + +template +struct convert { + static Node encode(const char (&rhs)[N]) { return Node(rhs); } +}; + +template <> +struct convert<_Null> { + static Node encode(const _Null& /* rhs */) { return Node(); } + + static bool decode(const Node& node, _Null& /* rhs */) { + return node.IsNull(); + } +}; + +#define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op) \ + template <> \ + struct convert { \ + static Node encode(const type& rhs) { \ + std::stringstream stream; \ + stream.precision(std::numeric_limits::digits10 + 1); \ + stream << rhs; \ + return Node(stream.str()); \ + } \ + \ + static bool decode(const Node& node, type& rhs) { \ + if (node.Type() != NodeType::Scalar) \ + return false; \ + const std::string& input = node.Scalar(); \ + std::stringstream stream(input); \ + stream.unsetf(std::ios::dec); \ + if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) \ + return true; \ + if (std::numeric_limits::has_infinity) { \ + if (conversion::IsInfinity(input)) { \ + rhs = std::numeric_limits::infinity(); \ + return true; \ + } else if (conversion::IsNegativeInfinity(input)) { \ + rhs = negative_op std::numeric_limits::infinity(); \ + return true; \ + } \ + } \ + \ + if (std::numeric_limits::has_quiet_NaN && \ + conversion::IsNaN(input)) { \ + rhs = std::numeric_limits::quiet_NaN(); \ + return true; \ + } \ + \ + return false; \ + } \ + } + +#define YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(type) \ + YAML_DEFINE_CONVERT_STREAMABLE(type, -) + +#define YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(type) \ + YAML_DEFINE_CONVERT_STREAMABLE(type, +) + +YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(int); +YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(short); +YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long); +YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long long); +YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned); +YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned short); +YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long); +YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long long); + +YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(char); +YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned char); + +YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(float); +YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(double); +YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long double); - YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(int); - YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(short); - YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long); - YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long long); - YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned); - YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned short); - YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long); - YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long long); - - YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(char); - YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned char); - - YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(float); - YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(double); - YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(long double); - #undef YAML_DEFINE_CONVERT_STREAMABLE_SIGNED #undef YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED #undef YAML_DEFINE_CONVERT_STREAMABLE - - // bool - template<> - struct convert { - static Node encode(bool rhs) { - return rhs ? Node("true") : Node("false"); - } - - static bool decode(const Node& node, bool& rhs); - }; - // std::map - template - struct convert > { - static Node encode(const std::map& rhs) { - Node node(NodeType::Map); - for(typename std::map::const_iterator it=rhs.begin();it!=rhs.end();++it) - node.force_insert(it->first, it->second); - return node; - } - - static bool decode(const Node& node, std::map& rhs) { - if(!node.IsMap()) - return false; +// bool +template <> +struct convert { + static Node encode(bool rhs) { return rhs ? Node("true") : Node("false"); } - rhs.clear(); - for(const_iterator it=node.begin();it!=node.end();++it) + static bool decode(const Node& node, bool& rhs); +}; + +// std::map +template +struct convert > { + static Node encode(const std::map& rhs) { + Node node(NodeType::Map); + for (typename std::map::const_iterator it = rhs.begin(); + it != rhs.end(); ++it) + node.force_insert(it->first, it->second); + return node; + } + + static bool decode(const Node& node, std::map& rhs) { + if (!node.IsMap()) + return false; + + rhs.clear(); + for (const_iterator it = node.begin(); it != node.end(); ++it) #if defined(__GNUC__) && __GNUC__ < 4 -//workaround for GCC 3: - rhs[it->first.template as()] = it->second.template as(); + // workaround for GCC 3: + rhs[it->first.template as()] = it->second.template as(); #else - rhs[it->first.as()] = it->second.as(); + rhs[it->first.as()] = it->second.as(); #endif - return true; - } - }; - - // std::vector - template - struct convert > { - static Node encode(const std::vector& rhs) { - Node node(NodeType::Sequence); - for(typename std::vector::const_iterator it=rhs.begin();it!=rhs.end();++it) - node.push_back(*it); - return node; - } - - static bool decode(const Node& node, std::vector& rhs) { - if(!node.IsSequence()) - return false; - - rhs.clear(); - for(const_iterator it=node.begin();it!=node.end();++it) + return true; + } +}; + +// std::vector +template +struct convert > { + static Node encode(const std::vector& rhs) { + Node node(NodeType::Sequence); + for (typename std::vector::const_iterator it = rhs.begin(); + it != rhs.end(); ++it) + node.push_back(*it); + return node; + } + + static bool decode(const Node& node, std::vector& rhs) { + if (!node.IsSequence()) + return false; + + rhs.clear(); + for (const_iterator it = node.begin(); it != node.end(); ++it) #if defined(__GNUC__) && __GNUC__ < 4 -//workaround for GCC 3: - rhs.push_back(it->template as()); + // workaround for GCC 3: + rhs.push_back(it->template as()); #else - rhs.push_back(it->as()); + rhs.push_back(it->as()); #endif - return true; - } - }; - - // std::list - template - struct convert > { - static Node encode(const std::list& rhs) { - Node node(NodeType::Sequence); - for(typename std::list::const_iterator it=rhs.begin();it!=rhs.end();++it) - node.push_back(*it); - return node; - } - - static bool decode(const Node& node, std::list& rhs) { - if(!node.IsSequence()) - return false; - - rhs.clear(); - for(const_iterator it=node.begin();it!=node.end();++it) + return true; + } +}; + +// std::list +template +struct convert > { + static Node encode(const std::list& rhs) { + Node node(NodeType::Sequence); + for (typename std::list::const_iterator it = rhs.begin(); + it != rhs.end(); ++it) + node.push_back(*it); + return node; + } + + static bool decode(const Node& node, std::list& rhs) { + if (!node.IsSequence()) + return false; + + rhs.clear(); + for (const_iterator it = node.begin(); it != node.end(); ++it) #if defined(__GNUC__) && __GNUC__ < 4 -//workaround for GCC 3: - rhs.push_back(it->template as()); + // workaround for GCC 3: + rhs.push_back(it->template as()); #else - rhs.push_back(it->as()); + rhs.push_back(it->as()); #endif - return true; - } - }; - - // std::pair - template - struct convert > { - static Node encode(const std::pair& rhs) { - Node node(NodeType::Sequence); - node.push_back(rhs.first); - node.push_back(rhs.second); - return node; - } - - static bool decode(const Node& node, std::pair& rhs) { - if(!node.IsSequence()) - return false; - if (node.size() != 2) - return false; + return true; + } +}; + +// std::pair +template +struct convert > { + static Node encode(const std::pair& rhs) { + Node node(NodeType::Sequence); + node.push_back(rhs.first); + node.push_back(rhs.second); + return node; + } + + static bool decode(const Node& node, std::pair& rhs) { + if (!node.IsSequence()) + return false; + if (node.size() != 2) + return false; #if defined(__GNUC__) && __GNUC__ < 4 -//workaround for GCC 3: - rhs.first = node[0].template as(); + // workaround for GCC 3: + rhs.first = node[0].template as(); #else - rhs.first = node[0].as(); + rhs.first = node[0].as(); #endif #if defined(__GNUC__) && __GNUC__ < 4 -//workaround for GCC 3: - rhs.second = node[1].template as(); + // workaround for GCC 3: + rhs.second = node[1].template as(); #else - rhs.second = node[1].as(); + rhs.second = node[1].as(); #endif - return true; - } - }; + return true; + } +}; - // binary - template<> - struct convert { - static Node encode(const Binary& rhs) { - return Node(EncodeBase64(rhs.data(), rhs.size())); - } - - static bool decode(const Node& node, Binary& rhs) { - if(!node.IsScalar()) - return false; - - std::vector data = DecodeBase64(node.Scalar()); - if(data.empty() && !node.Scalar().empty()) - return false; - - rhs.swap(data); - return true; - } - }; +// binary +template <> +struct convert { + static Node encode(const Binary& rhs) { + return Node(EncodeBase64(rhs.data(), rhs.size())); + } + + static bool decode(const Node& node, Binary& rhs) { + if (!node.IsScalar()) + return false; + + std::vector data = DecodeBase64(node.Scalar()); + if (data.empty() && !node.Scalar().empty()) + return false; + + rhs.swap(data); + return true; + } +}; } -#endif // NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#endif // NODE_CONVERT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/detail/bool_type.h b/include/yaml-cpp/node/detail/bool_type.h index 80ed9a4..2c80705 100644 --- a/include/yaml-cpp/node/detail/bool_type.h +++ b/include/yaml-cpp/node/detail/bool_type.h @@ -1,26 +1,26 @@ #ifndef NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif -namespace YAML -{ - namespace detail - { - struct unspecified_bool { - struct NOT_ALLOWED; - static void true_value(NOT_ALLOWED*) {} - }; - typedef void (*unspecified_bool_type)(unspecified_bool::NOT_ALLOWED*); - } +namespace YAML { +namespace detail { +struct unspecified_bool { + struct NOT_ALLOWED; + static void true_value(NOT_ALLOWED*) {} +}; +typedef void (*unspecified_bool_type)(unspecified_bool::NOT_ALLOWED*); +} } -#define YAML_CPP_OPERATOR_BOOL()\ -operator YAML::detail::unspecified_bool_type() const\ -{\ - return this->operator!() ? 0 : &YAML::detail::unspecified_bool::true_value;\ -} +#define YAML_CPP_OPERATOR_BOOL() \ + operator YAML::detail::unspecified_bool_type() const { \ + return this->operator!() ? 0 \ + : &YAML::detail::unspecified_bool::true_value; \ + } -#endif // NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#endif // NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/detail/impl.h b/include/yaml-cpp/node/detail/impl.h index ce5fd57..43eaa38 100644 --- a/include/yaml-cpp/node/detail/impl.h +++ b/include/yaml-cpp/node/detail/impl.h @@ -1,168 +1,176 @@ #ifndef NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif - #include "yaml-cpp/node/detail/node.h" #include "yaml-cpp/node/detail/node_data.h" #include -namespace YAML -{ - namespace detail - { - template - struct get_idx { - static node *get(const std::vector& /* sequence */, const Key& /* key */, shared_memory_holder /* pMemory */) { - return 0; - } - }; +namespace YAML { +namespace detail { +template +struct get_idx { + static node* get(const std::vector& /* sequence */, + const Key& /* key */, shared_memory_holder /* pMemory */) { + return 0; + } +}; - template - struct get_idx::value && !boost::is_same::value>::type> { - static node *get(const std::vector& sequence, const Key& key, shared_memory_holder /* pMemory */) { - return key < sequence.size() ? sequence[key] : 0; - } +template +struct get_idx< + Key, typename boost::enable_if_c::value && + !boost::is_same::value>::type> { + static node* get(const std::vector& sequence, const Key& key, + shared_memory_holder /* pMemory */) { + return key < sequence.size() ? sequence[key] : 0; + } - static node *get(std::vector& sequence, const Key& key, shared_memory_holder pMemory) { - if(key > sequence.size()) - return 0; - if(key == sequence.size()) - sequence.push_back(&pMemory->create_node()); - return sequence[key]; - } - }; - - template - struct get_idx >::type> { - static node *get(const std::vector& sequence, const Key& key, shared_memory_holder pMemory) { - return key >= 0 ? get_idx::get(sequence, static_cast(key), pMemory) : 0; - } - static node *get(std::vector& sequence, const Key& key, shared_memory_holder pMemory) { - return key >= 0 ? get_idx::get(sequence, static_cast(key), pMemory) : 0; - } - }; + static node* get(std::vector& sequence, const Key& key, + shared_memory_holder pMemory) { + if (key > sequence.size()) + return 0; + if (key == sequence.size()) + sequence.push_back(&pMemory->create_node()); + return sequence[key]; + } +}; - // indexing - template - inline node& node_data::get(const Key& key, shared_memory_holder pMemory) const - { - switch(m_type) { - case NodeType::Map: - break; - case NodeType::Undefined: - case NodeType::Null: - return pMemory->create_node(); - case NodeType::Sequence: - if(node *pNode = get_idx::get(m_sequence, key, pMemory)) - return *pNode; - return pMemory->create_node(); - case NodeType::Scalar: - throw BadSubscript(); - } +template +struct get_idx >::type> { + static node* get(const std::vector& sequence, const Key& key, + shared_memory_holder pMemory) { + return key >= 0 ? get_idx::get( + sequence, static_cast(key), pMemory) + : 0; + } + static node* get(std::vector& sequence, const Key& key, + shared_memory_holder pMemory) { + return key >= 0 ? get_idx::get( + sequence, static_cast(key), pMemory) + : 0; + } +}; - for(node_map::const_iterator it=m_map.begin();it!=m_map.end();++it) { - if(equals(*it->first, key, pMemory)) - return *it->second; - } - - return pMemory->create_node(); - } - - template - inline node& node_data::get(const Key& key, shared_memory_holder pMemory) - { - switch(m_type) { - case NodeType::Map: - break; - case NodeType::Undefined: - case NodeType::Null: - case NodeType::Sequence: - if(node *pNode = get_idx::get(m_sequence, key, pMemory)) { - m_type = NodeType::Sequence; - return *pNode; - } - - convert_to_map(pMemory); - break; - case NodeType::Scalar: - throw BadSubscript(); - } - - for(node_map::const_iterator it=m_map.begin();it!=m_map.end();++it) { - if(equals(*it->first, key, pMemory)) - return *it->second; - } - - node& k = convert_to_node(key, pMemory); - node& v = pMemory->create_node(); - insert_map_pair(k, v); - return v; - } - - template - inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) - { - if(m_type != NodeType::Map) - return false; - - for(node_map::iterator it=m_map.begin();it!=m_map.end();++it) { - if(equals(*it->first, key, pMemory)) { - m_map.erase(it); - return true; - } - } - - return false; - } - - // map - template - inline void node_data::force_insert(const Key& key, const Value& value, shared_memory_holder pMemory) - { - switch(m_type) { - case NodeType::Map: - break; - case NodeType::Undefined: - case NodeType::Null: - case NodeType::Sequence: - convert_to_map(pMemory); - break; - case NodeType::Scalar: - throw BadInsert(); - } - - node& k = convert_to_node(key, pMemory); - node& v = convert_to_node(value, pMemory); - insert_map_pair(k, v); - } +// indexing +template +inline node& node_data::get(const Key& key, + shared_memory_holder pMemory) const { + switch (m_type) { + case NodeType::Map: + break; + case NodeType::Undefined: + case NodeType::Null: + return pMemory->create_node(); + case NodeType::Sequence: + if (node* pNode = get_idx::get(m_sequence, key, pMemory)) + return *pNode; + return pMemory->create_node(); + case NodeType::Scalar: + throw BadSubscript(); + } - template - inline bool node_data::equals(node& node, const T& rhs, shared_memory_holder pMemory) - { - T lhs; - if(convert::decode(Node(node, pMemory), lhs)) - return lhs == rhs; - return false; - } - - inline bool node_data::equals(node& node, const char *rhs, shared_memory_holder pMemory) - { - return equals(node, rhs, pMemory); - } + for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) { + if (equals(*it->first, key, pMemory)) + return *it->second; + } - template - inline node& node_data::convert_to_node(const T& rhs, shared_memory_holder pMemory) - { - Node value = convert::encode(rhs); - value.EnsureNodeExists(); - pMemory->merge(*value.m_pMemory); - return *value.m_pNode; - } - } + return pMemory->create_node(); } -#endif // NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +template +inline node& node_data::get(const Key& key, shared_memory_holder pMemory) { + switch (m_type) { + case NodeType::Map: + break; + case NodeType::Undefined: + case NodeType::Null: + case NodeType::Sequence: + if (node* pNode = get_idx::get(m_sequence, key, pMemory)) { + m_type = NodeType::Sequence; + return *pNode; + } + + convert_to_map(pMemory); + break; + case NodeType::Scalar: + throw BadSubscript(); + } + + for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) { + if (equals(*it->first, key, pMemory)) + return *it->second; + } + + node& k = convert_to_node(key, pMemory); + node& v = pMemory->create_node(); + insert_map_pair(k, v); + return v; +} + +template +inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) { + if (m_type != NodeType::Map) + return false; + + for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) { + if (equals(*it->first, key, pMemory)) { + m_map.erase(it); + return true; + } + } + + return false; +} + +// map +template +inline void node_data::force_insert(const Key& key, const Value& value, + shared_memory_holder pMemory) { + switch (m_type) { + case NodeType::Map: + break; + case NodeType::Undefined: + case NodeType::Null: + case NodeType::Sequence: + convert_to_map(pMemory); + break; + case NodeType::Scalar: + throw BadInsert(); + } + + node& k = convert_to_node(key, pMemory); + node& v = convert_to_node(value, pMemory); + insert_map_pair(k, v); +} + +template +inline bool node_data::equals(node& node, const T& rhs, + shared_memory_holder pMemory) { + T lhs; + if (convert::decode(Node(node, pMemory), lhs)) + return lhs == rhs; + return false; +} + +inline bool node_data::equals(node& node, const char* rhs, + shared_memory_holder pMemory) { + return equals(node, rhs, pMemory); +} + +template +inline node& node_data::convert_to_node(const T& rhs, + shared_memory_holder pMemory) { + Node value = convert::encode(rhs); + value.EnsureNodeExists(); + pMemory->merge(*value.m_pMemory); + return *value.m_pNode; +} +} +} + +#endif // NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/detail/iterator.h b/include/yaml-cpp/node/detail/iterator.h index dc699f4..6c0d4b6 100644 --- a/include/yaml-cpp/node/detail/iterator.h +++ b/include/yaml-cpp/node/detail/iterator.h @@ -1,64 +1,66 @@ #ifndef VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif - #include "yaml-cpp/dll.h" #include "yaml-cpp/node/ptr.h" #include "yaml-cpp/node/detail/node_iterator.h" #include #include -namespace YAML -{ - namespace detail - { - struct iterator_value; +namespace YAML { +namespace detail { +struct iterator_value; - template - class iterator_base: public boost::iterator_adaptor< - iterator_base, - node_iterator, - V, - std::forward_iterator_tag, - V> - { - private: - template friend class iterator_base; - struct enabler {}; - typedef typename iterator_base::base_type base_type; - - public: - typedef typename iterator_base::value_type value_type; - - public: - iterator_base() {} - explicit iterator_base(base_type rhs, shared_memory_holder pMemory): iterator_base::iterator_adaptor_(rhs), m_pMemory(pMemory) {} - - template - iterator_base(const iterator_base& rhs, typename boost::enable_if, enabler>::type = enabler()): iterator_base::iterator_adaptor_(rhs.base()), m_pMemory(rhs.m_pMemory) {} - - private: - friend class boost::iterator_core_access; +template +class iterator_base + : public boost::iterator_adaptor, node_iterator, V, + std::forward_iterator_tag, V> { + private: + template + friend class iterator_base; + struct enabler {}; + typedef typename iterator_base::base_type base_type; - void increment() { this->base_reference() = boost::next(this->base()); } - - value_type dereference() const { - const typename base_type::value_type& v = *this->base(); - if(v.pNode) - return value_type(Node(*v, m_pMemory)); - if(v.first && v.second) - return value_type(Node(*v.first, m_pMemory), Node(*v.second, m_pMemory)); - return value_type(); - } - - private: - shared_memory_holder m_pMemory; - }; - } + public: + typedef typename iterator_base::value_type value_type; + + public: + iterator_base() {} + explicit iterator_base(base_type rhs, shared_memory_holder pMemory) + : iterator_base::iterator_adaptor_(rhs), m_pMemory(pMemory) {} + + template + iterator_base( + const iterator_base& rhs, + typename boost::enable_if, enabler>::type = + enabler()) + : iterator_base::iterator_adaptor_(rhs.base()), + m_pMemory(rhs.m_pMemory) {} + + private: + friend class boost::iterator_core_access; + + void increment() { this->base_reference() = boost::next(this->base()); } + + value_type dereference() const { + const typename base_type::value_type& v = *this->base(); + if (v.pNode) + return value_type(Node(*v, m_pMemory)); + if (v.first && v.second) + return value_type(Node(*v.first, m_pMemory), Node(*v.second, m_pMemory)); + return value_type(); + } + + private: + shared_memory_holder m_pMemory; +}; +} } -#endif // VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#endif // VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/detail/iterator_fwd.h b/include/yaml-cpp/node/detail/iterator_fwd.h index c4efb2c..c54a258 100644 --- a/include/yaml-cpp/node/detail/iterator_fwd.h +++ b/include/yaml-cpp/node/detail/iterator_fwd.h @@ -1,27 +1,28 @@ #ifndef VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif - #include "yaml-cpp/dll.h" #include #include #include -namespace YAML -{ - class node; - - namespace detail { - struct iterator_value; - template class iterator_base; - } +namespace YAML { +class node; - typedef detail::iterator_base iterator; - typedef detail::iterator_base const_iterator; +namespace detail { +struct iterator_value; +template +class iterator_base; } -#endif // VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +typedef detail::iterator_base iterator; +typedef detail::iterator_base const_iterator; +} + +#endif // VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/detail/memory.h b/include/yaml-cpp/node/detail/memory.h index 243a81a..4584add 100644 --- a/include/yaml-cpp/node/detail/memory.h +++ b/include/yaml-cpp/node/detail/memory.h @@ -1,7 +1,9 @@ #ifndef VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif @@ -9,31 +11,29 @@ #include #include -namespace YAML -{ - namespace detail - { - class memory { - public: - node& create_node(); - void merge(const memory& rhs); - - private: - typedef std::set Nodes; - Nodes m_nodes; - }; +namespace YAML { +namespace detail { +class memory { + public: + node& create_node(); + void merge(const memory& rhs); - class memory_holder { - public: - memory_holder(): m_pMemory(new memory) {} - - node& create_node() { return m_pMemory->create_node(); } - void merge(memory_holder& rhs); - - private: - boost::shared_ptr m_pMemory; - }; - } + private: + typedef std::set Nodes; + Nodes m_nodes; +}; + +class memory_holder { + public: + memory_holder() : m_pMemory(new memory) {} + + node& create_node() { return m_pMemory->create_node(); } + void merge(memory_holder& rhs); + + private: + boost::shared_ptr m_pMemory; +}; +} } -#endif // VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#endif // VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/detail/node.h b/include/yaml-cpp/node/detail/node.h index ce3a76d..20be18c 100644 --- a/include/yaml-cpp/node/detail/node.h +++ b/include/yaml-cpp/node/detail/node.h @@ -1,11 +1,12 @@ #ifndef NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif - #include "yaml-cpp/dll.h" #include "yaml-cpp/node/type.h" #include "yaml-cpp/node/ptr.h" @@ -13,118 +14,134 @@ #include #include -namespace YAML -{ - namespace detail - { - class node: private boost::noncopyable - { - public: - node(): m_pRef(new node_ref) {} +namespace YAML { +namespace detail { +class node : private boost::noncopyable { + public: + node() : m_pRef(new node_ref) {} - bool is(const node& rhs) const { return m_pRef == rhs.m_pRef; } - const node_ref *ref() const { return m_pRef.get(); } - - bool is_defined() const { return m_pRef->is_defined(); } - NodeType::value type() const { return m_pRef->type(); } - - const std::string& scalar() const { return m_pRef->scalar(); } - const std::string& tag() const { return m_pRef->tag(); } - - void mark_defined() { - if(is_defined()) - return; - - m_pRef->mark_defined(); - for(nodes::iterator it=m_dependencies.begin();it!=m_dependencies.end();++it) - (*it)->mark_defined(); - m_dependencies.clear(); - } - - void add_dependency(node& rhs) { - if(is_defined()) - rhs.mark_defined(); - else - m_dependencies.insert(&rhs); - } - - void set_ref(const node& rhs) { - if(rhs.is_defined()) - mark_defined(); - m_pRef = rhs.m_pRef; - } - void set_data(const node& rhs) { - if(rhs.is_defined()) - mark_defined(); - m_pRef->set_data(*rhs.m_pRef); - } - - void set_type(NodeType::value type) { - if(type != NodeType::Undefined) - mark_defined(); - m_pRef->set_type(type); - } - void set_null() { - mark_defined(); - m_pRef->set_null(); - } - void set_scalar(const std::string& scalar) { - mark_defined(); - m_pRef->set_scalar(scalar); - } - void set_tag(const std::string& tag) { - mark_defined(); - m_pRef->set_tag(tag); - } + bool is(const node& rhs) const { return m_pRef == rhs.m_pRef; } + const node_ref* ref() const { return m_pRef.get(); } - // size/iterator - std::size_t size() const { return m_pRef->size(); } - - const_node_iterator begin() const { return static_cast(*m_pRef).begin(); } - node_iterator begin() { return m_pRef->begin(); } - - const_node_iterator end() const { return static_cast(*m_pRef).end(); } - node_iterator end() { return m_pRef->end(); } + bool is_defined() const { return m_pRef->is_defined(); } + NodeType::value type() const { return m_pRef->type(); } - // sequence - void push_back(node& node, shared_memory_holder pMemory) { - m_pRef->push_back(node, pMemory); - node.add_dependency(*this); - } - void insert(node& key, node& value, shared_memory_holder pMemory) { - m_pRef->insert(key, value, pMemory); - key.add_dependency(*this); - value.add_dependency(*this); - } + const std::string& scalar() const { return m_pRef->scalar(); } + const std::string& tag() const { return m_pRef->tag(); } - // indexing - template node& get(const Key& key, shared_memory_holder pMemory) const { return static_cast(*m_pRef).get(key, pMemory); } - template node& get(const Key& key, shared_memory_holder pMemory) { - node& value = m_pRef->get(key, pMemory); - value.add_dependency(*this); - return value; - } - template bool remove(const Key& key, shared_memory_holder pMemory) { return m_pRef->remove(key, pMemory); } - - node& get(node& key, shared_memory_holder pMemory) const { return static_cast(*m_pRef).get(key, pMemory); } - node& get(node& key, shared_memory_holder pMemory) { - node& value = m_pRef->get(key, pMemory); - key.add_dependency(*this); - value.add_dependency(*this); - return value; - } - bool remove(node& key, shared_memory_holder pMemory) { return m_pRef->remove(key, pMemory); } + void mark_defined() { + if (is_defined()) + return; - // map - template - void force_insert(const Key& key, const Value& value, shared_memory_holder pMemory){ m_pRef->force_insert(key, value, pMemory); } + m_pRef->mark_defined(); + for (nodes::iterator it = m_dependencies.begin(); + it != m_dependencies.end(); ++it) + (*it)->mark_defined(); + m_dependencies.clear(); + } - private: - shared_node_ref m_pRef; - typedef std::set nodes; - nodes m_dependencies; - }; - } + void add_dependency(node& rhs) { + if (is_defined()) + rhs.mark_defined(); + else + m_dependencies.insert(&rhs); + } + + void set_ref(const node& rhs) { + if (rhs.is_defined()) + mark_defined(); + m_pRef = rhs.m_pRef; + } + void set_data(const node& rhs) { + if (rhs.is_defined()) + mark_defined(); + m_pRef->set_data(*rhs.m_pRef); + } + + void set_type(NodeType::value type) { + if (type != NodeType::Undefined) + mark_defined(); + m_pRef->set_type(type); + } + void set_null() { + mark_defined(); + m_pRef->set_null(); + } + void set_scalar(const std::string& scalar) { + mark_defined(); + m_pRef->set_scalar(scalar); + } + void set_tag(const std::string& tag) { + mark_defined(); + m_pRef->set_tag(tag); + } + + // size/iterator + std::size_t size() const { return m_pRef->size(); } + + const_node_iterator begin() const { + return static_cast(*m_pRef).begin(); + } + node_iterator begin() { return m_pRef->begin(); } + + const_node_iterator end() const { + return static_cast(*m_pRef).end(); + } + node_iterator end() { return m_pRef->end(); } + + // sequence + void push_back(node& node, shared_memory_holder pMemory) { + m_pRef->push_back(node, pMemory); + node.add_dependency(*this); + } + void insert(node& key, node& value, shared_memory_holder pMemory) { + m_pRef->insert(key, value, pMemory); + key.add_dependency(*this); + value.add_dependency(*this); + } + + // indexing + template + node& get(const Key& key, shared_memory_holder pMemory) const { + return static_cast(*m_pRef).get(key, pMemory); + } + template + node& get(const Key& key, shared_memory_holder pMemory) { + node& value = m_pRef->get(key, pMemory); + value.add_dependency(*this); + return value; + } + template + bool remove(const Key& key, shared_memory_holder pMemory) { + return m_pRef->remove(key, pMemory); + } + + node& get(node& key, shared_memory_holder pMemory) const { + return static_cast(*m_pRef).get(key, pMemory); + } + node& get(node& key, shared_memory_holder pMemory) { + node& value = m_pRef->get(key, pMemory); + key.add_dependency(*this); + value.add_dependency(*this); + return value; + } + bool remove(node& key, shared_memory_holder pMemory) { + return m_pRef->remove(key, pMemory); + } + + // map + template + void force_insert(const Key& key, const Value& value, + shared_memory_holder pMemory) { + m_pRef->force_insert(key, value, pMemory); + } + + private: + shared_node_ref m_pRef; + typedef std::set nodes; + nodes m_dependencies; +}; +} } -#endif // NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#endif // NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/detail/node_data.h b/include/yaml-cpp/node/detail/node_data.h index 413da5f..50dd85a 100644 --- a/include/yaml-cpp/node/detail/node_data.h +++ b/include/yaml-cpp/node/detail/node_data.h @@ -1,11 +1,12 @@ #ifndef VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif - #include "yaml-cpp/dll.h" #include "yaml-cpp/node/iterator.h" #include "yaml-cpp/node/ptr.h" @@ -15,96 +16,99 @@ #include #include -namespace YAML -{ - namespace detail - { - class node_data: private boost::noncopyable - { - public: - node_data(); - - void mark_defined(); - void set_type(NodeType::value type); - void set_tag(const std::string& tag); - void set_null(); - void set_scalar(const std::string& scalar); - - bool is_defined() const { return m_isDefined; } - NodeType::value type() const { return m_isDefined ? m_type : NodeType::Undefined; } - const std::string& scalar() const { return m_scalar; } - const std::string& tag() const { return m_tag; } - - // size/iterator - std::size_t size() const; - - const_node_iterator begin() const; - node_iterator begin(); - - const_node_iterator end() const; - node_iterator end(); +namespace YAML { +namespace detail { +class node_data : private boost::noncopyable { + public: + node_data(); - // sequence - void push_back(node& node, shared_memory_holder pMemory); - void insert(node& key, node& value, shared_memory_holder pMemory); + void mark_defined(); + void set_type(NodeType::value type); + void set_tag(const std::string& tag); + void set_null(); + void set_scalar(const std::string& scalar); - // indexing - template node& get(const Key& key, shared_memory_holder pMemory) const; - template node& get(const Key& key, shared_memory_holder pMemory); - template bool remove(const Key& key, shared_memory_holder pMemory); - - node& get(node& key, shared_memory_holder pMemory) const; - node& get(node& key, shared_memory_holder pMemory); - bool remove(node& key, shared_memory_holder pMemory); - - // map - template - void force_insert(const Key& key, const Value& value, shared_memory_holder pMemory); - - public: - static std::string empty_scalar; - - private: - void compute_seq_size() const; - void compute_map_size() const; + bool is_defined() const { return m_isDefined; } + NodeType::value type() const { + return m_isDefined ? m_type : NodeType::Undefined; + } + const std::string& scalar() const { return m_scalar; } + const std::string& tag() const { return m_tag; } - void reset_sequence(); - void reset_map(); - - void insert_map_pair(node& key, node& value); - void convert_to_map(shared_memory_holder pMemory); - void convert_sequence_to_map(shared_memory_holder pMemory); - - template - static bool equals(node& node, const T& rhs, shared_memory_holder pMemory); - static bool equals(node& node, const char *rhs, shared_memory_holder pMemory); - - template - static node& convert_to_node(const T& rhs, shared_memory_holder pMemory); + // size/iterator + std::size_t size() const; - private: - bool m_isDefined; - NodeType::value m_type; - std::string m_tag; - - // scalar - std::string m_scalar; - - // sequence - typedef std::vector node_seq; - node_seq m_sequence; - - mutable std::size_t m_seqSize; - - // map - typedef std::map node_map; - node_map m_map; - - typedef std::pair kv_pair; - typedef std::list kv_pairs; - mutable kv_pairs m_undefinedPairs; - }; - } + const_node_iterator begin() const; + node_iterator begin(); + + const_node_iterator end() const; + node_iterator end(); + + // sequence + void push_back(node& node, shared_memory_holder pMemory); + void insert(node& key, node& value, shared_memory_holder pMemory); + + // indexing + template + node& get(const Key& key, shared_memory_holder pMemory) const; + template + node& get(const Key& key, shared_memory_holder pMemory); + template + bool remove(const Key& key, shared_memory_holder pMemory); + + node& get(node& key, shared_memory_holder pMemory) const; + node& get(node& key, shared_memory_holder pMemory); + bool remove(node& key, shared_memory_holder pMemory); + + // map + template + void force_insert(const Key& key, const Value& value, + shared_memory_holder pMemory); + + public: + static std::string empty_scalar; + + private: + void compute_seq_size() const; + void compute_map_size() const; + + void reset_sequence(); + void reset_map(); + + void insert_map_pair(node& key, node& value); + void convert_to_map(shared_memory_holder pMemory); + void convert_sequence_to_map(shared_memory_holder pMemory); + + template + static bool equals(node& node, const T& rhs, shared_memory_holder pMemory); + static bool equals(node& node, const char* rhs, shared_memory_holder pMemory); + + template + static node& convert_to_node(const T& rhs, shared_memory_holder pMemory); + + private: + bool m_isDefined; + NodeType::value m_type; + std::string m_tag; + + // scalar + std::string m_scalar; + + // sequence + typedef std::vector node_seq; + node_seq m_sequence; + + mutable std::size_t m_seqSize; + + // map + typedef std::map node_map; + node_map m_map; + + typedef std::pair kv_pair; + typedef std::list kv_pairs; + mutable kv_pairs m_undefinedPairs; +}; +} } -#endif // VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#endif // VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/detail/node_iterator.h b/include/yaml-cpp/node/detail/node_iterator.h index 294921b..6147f63 100644 --- a/include/yaml-cpp/node/detail/node_iterator.h +++ b/include/yaml-cpp/node/detail/node_iterator.h @@ -1,11 +1,12 @@ #ifndef VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif - #include "yaml-cpp/dll.h" #include "yaml-cpp/node/ptr.h" #include @@ -14,126 +15,143 @@ #include #include -namespace YAML -{ - namespace detail - { - struct iterator_type { enum value { None, Sequence, Map }; }; - - template - struct node_iterator_value: public std::pair { - typedef std::pair kv; - - node_iterator_value(): kv(), pNode(0) {} - explicit node_iterator_value(V& rhs): kv(), pNode(&rhs) {} - explicit node_iterator_value(V& key, V& value): kv(&key, &value), pNode(0) {} - - V& operator *() const { return *pNode; } - V& operator ->() const { return *pNode; } - - V *pNode; - }; - - typedef std::vector node_seq; - typedef std::map node_map; - - template - struct node_iterator_type { - typedef node_seq::iterator seq; - typedef node_map::iterator map; - }; - - template - struct node_iterator_type { - typedef node_seq::const_iterator seq; - typedef node_map::const_iterator map; - }; - +namespace YAML { +namespace detail { +struct iterator_type { + enum value { + None, + Sequence, + Map + }; +}; - template - class node_iterator_base: public boost::iterator_facade< - node_iterator_base, - node_iterator_value, - std::forward_iterator_tag, - node_iterator_value > - { - private: - struct enabler {}; - - public: - typedef typename node_iterator_type::seq SeqIter; - typedef typename node_iterator_type::map MapIter; - typedef node_iterator_value value_type; - - node_iterator_base(): m_type(iterator_type::None) {} - explicit node_iterator_base(SeqIter seqIt): m_type(iterator_type::Sequence), m_seqIt(seqIt) {} - explicit node_iterator_base(MapIter mapIt, MapIter mapEnd): m_type(iterator_type::Map), m_mapIt(mapIt), m_mapEnd(mapEnd) { - m_mapIt = increment_until_defined(m_mapIt); - } - - template - node_iterator_base(const node_iterator_base& rhs, typename boost::enable_if, enabler>::type = enabler()) - : m_type(rhs.m_type), m_seqIt(rhs.m_seqIt), m_mapIt(rhs.m_mapIt), m_mapEnd(rhs.m_mapEnd) {} - - private: - friend class boost::iterator_core_access; - template friend class node_iterator_base; - - template - bool equal(const node_iterator_base& rhs) const { - if(m_type != rhs.m_type) - return false; - - switch(m_type) { - case iterator_type::None: return true; - case iterator_type::Sequence: return m_seqIt == rhs.m_seqIt; - case iterator_type::Map: return m_mapIt == rhs.m_mapIt; - } - return true; - } - - void increment() { - switch(m_type) { - case iterator_type::None: break; - case iterator_type::Sequence: - ++m_seqIt; - break; - case iterator_type::Map: - ++m_mapIt; - m_mapIt = increment_until_defined(m_mapIt); - break; - } - } +template +struct node_iterator_value : public std::pair { + typedef std::pair kv; - value_type dereference() const { - switch(m_type) { - case iterator_type::None: return value_type(); - case iterator_type::Sequence: return value_type(**m_seqIt); - case iterator_type::Map: return value_type(*m_mapIt->first, *m_mapIt->second); - } - return value_type(); - } - - MapIter increment_until_defined(MapIter it) { - while(it != m_mapEnd && !is_defined(it)) - ++it; - return it; - } - - bool is_defined(MapIter it) const { - return it->first->is_defined() && it->second->is_defined(); - } + node_iterator_value() : kv(), pNode(0) {} + explicit node_iterator_value(V& rhs) : kv(), pNode(&rhs) {} + explicit node_iterator_value(V& key, V& value) : kv(&key, &value), pNode(0) {} - private: - typename iterator_type::value m_type; + V& operator*() const { return *pNode; } + V& operator->() const { return *pNode; } - SeqIter m_seqIt; - MapIter m_mapIt, m_mapEnd; - }; + V* pNode; +}; - typedef node_iterator_base node_iterator; - typedef node_iterator_base const_node_iterator; - } +typedef std::vector node_seq; +typedef std::map node_map; + +template +struct node_iterator_type { + typedef node_seq::iterator seq; + typedef node_map::iterator map; +}; + +template +struct node_iterator_type { + typedef node_seq::const_iterator seq; + typedef node_map::const_iterator map; +}; + +template +class node_iterator_base + : public boost::iterator_facade< + node_iterator_base, node_iterator_value, + std::forward_iterator_tag, node_iterator_value > { + private: + struct enabler {}; + + public: + typedef typename node_iterator_type::seq SeqIter; + typedef typename node_iterator_type::map MapIter; + typedef node_iterator_value value_type; + + node_iterator_base() : m_type(iterator_type::None) {} + explicit node_iterator_base(SeqIter seqIt) + : m_type(iterator_type::Sequence), m_seqIt(seqIt) {} + explicit node_iterator_base(MapIter mapIt, MapIter mapEnd) + : m_type(iterator_type::Map), m_mapIt(mapIt), m_mapEnd(mapEnd) { + m_mapIt = increment_until_defined(m_mapIt); + } + + template + node_iterator_base( + const node_iterator_base& rhs, + typename boost::enable_if, enabler>::type = + enabler()) + : m_type(rhs.m_type), + m_seqIt(rhs.m_seqIt), + m_mapIt(rhs.m_mapIt), + m_mapEnd(rhs.m_mapEnd) {} + + private: + friend class boost::iterator_core_access; + template + friend class node_iterator_base; + + template + bool equal(const node_iterator_base& rhs) const { + if (m_type != rhs.m_type) + return false; + + switch (m_type) { + case iterator_type::None: + return true; + case iterator_type::Sequence: + return m_seqIt == rhs.m_seqIt; + case iterator_type::Map: + return m_mapIt == rhs.m_mapIt; + } + return true; + } + + void increment() { + switch (m_type) { + case iterator_type::None: + break; + case iterator_type::Sequence: + ++m_seqIt; + break; + case iterator_type::Map: + ++m_mapIt; + m_mapIt = increment_until_defined(m_mapIt); + break; + } + } + + value_type dereference() const { + switch (m_type) { + case iterator_type::None: + return value_type(); + case iterator_type::Sequence: + return value_type(**m_seqIt); + case iterator_type::Map: + return value_type(*m_mapIt->first, *m_mapIt->second); + } + return value_type(); + } + + MapIter increment_until_defined(MapIter it) { + while (it != m_mapEnd && !is_defined(it)) + ++it; + return it; + } + + bool is_defined(MapIter it) const { + return it->first->is_defined() && it->second->is_defined(); + } + + private: + typename iterator_type::value m_type; + + SeqIter m_seqIt; + MapIter m_mapIt, m_mapEnd; +}; + +typedef node_iterator_base node_iterator; +typedef node_iterator_base const_node_iterator; +} } -#endif // VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#endif // VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/detail/node_ref.h b/include/yaml-cpp/node/detail/node_ref.h index 64cdb98..2b577a3 100644 --- a/include/yaml-cpp/node/detail/node_ref.h +++ b/include/yaml-cpp/node/detail/node_ref.h @@ -1,69 +1,93 @@ #ifndef VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif - #include "yaml-cpp/dll.h" #include "yaml-cpp/node/type.h" #include "yaml-cpp/node/ptr.h" #include "yaml-cpp/node/detail/node_data.h" #include -namespace YAML -{ - namespace detail - { - class node_ref: private boost::noncopyable - { - public: - node_ref(): m_pData(new node_data) {} - - bool is_defined() const { return m_pData->is_defined(); } - NodeType::value type() const { return m_pData->type(); } - const std::string& scalar() const { return m_pData->scalar(); } - const std::string& tag() const { return m_pData->tag(); } - - void mark_defined() { m_pData->mark_defined(); } - void set_data(const node_ref& rhs) { m_pData = rhs.m_pData; } - - void set_type(NodeType::value type) { m_pData->set_type(type); } - void set_tag(const std::string& tag) { m_pData->set_tag(tag); } - void set_null() { m_pData->set_null(); } - void set_scalar(const std::string& scalar) { m_pData->set_scalar(scalar); } - - // size/iterator - std::size_t size() const { return m_pData->size(); } - - const_node_iterator begin() const { return static_cast(*m_pData).begin(); } - node_iterator begin() {return m_pData->begin(); } - - const_node_iterator end() const { return static_cast(*m_pData).end(); } - node_iterator end() {return m_pData->end(); } +namespace YAML { +namespace detail { +class node_ref : private boost::noncopyable { + public: + node_ref() : m_pData(new node_data) {} - // sequence - void push_back(node& node, shared_memory_holder pMemory) { m_pData->push_back(node, pMemory); } - void insert(node& key, node& value, shared_memory_holder pMemory) { m_pData->insert(key, value, pMemory); } - - // indexing - template node& get(const Key& key, shared_memory_holder pMemory) const { return static_cast(*m_pData).get(key, pMemory); } - template node& get(const Key& key, shared_memory_holder pMemory) { return m_pData->get(key, pMemory); } - template bool remove(const Key& key, shared_memory_holder pMemory) { return m_pData->remove(key, pMemory); } - - node& get(node& key, shared_memory_holder pMemory) const { return static_cast(*m_pData).get(key, pMemory); } - node& get(node& key, shared_memory_holder pMemory) { return m_pData->get(key, pMemory); } - bool remove(node& key, shared_memory_holder pMemory) { return m_pData->remove(key, pMemory); } - - // map - template - void force_insert(const Key& key, const Value& value, shared_memory_holder pMemory) { m_pData->force_insert(key, value, pMemory); } + bool is_defined() const { return m_pData->is_defined(); } + NodeType::value type() const { return m_pData->type(); } + const std::string& scalar() const { return m_pData->scalar(); } + const std::string& tag() const { return m_pData->tag(); } - private: - shared_node_data m_pData; - }; - } + void mark_defined() { m_pData->mark_defined(); } + void set_data(const node_ref& rhs) { m_pData = rhs.m_pData; } + + void set_type(NodeType::value type) { m_pData->set_type(type); } + void set_tag(const std::string& tag) { m_pData->set_tag(tag); } + void set_null() { m_pData->set_null(); } + void set_scalar(const std::string& scalar) { m_pData->set_scalar(scalar); } + + // size/iterator + std::size_t size() const { return m_pData->size(); } + + const_node_iterator begin() const { + return static_cast(*m_pData).begin(); + } + node_iterator begin() { return m_pData->begin(); } + + const_node_iterator end() const { + return static_cast(*m_pData).end(); + } + node_iterator end() { return m_pData->end(); } + + // sequence + void push_back(node& node, shared_memory_holder pMemory) { + m_pData->push_back(node, pMemory); + } + void insert(node& key, node& value, shared_memory_holder pMemory) { + m_pData->insert(key, value, pMemory); + } + + // indexing + template + node& get(const Key& key, shared_memory_holder pMemory) const { + return static_cast(*m_pData).get(key, pMemory); + } + template + node& get(const Key& key, shared_memory_holder pMemory) { + return m_pData->get(key, pMemory); + } + template + bool remove(const Key& key, shared_memory_holder pMemory) { + return m_pData->remove(key, pMemory); + } + + node& get(node& key, shared_memory_holder pMemory) const { + return static_cast(*m_pData).get(key, pMemory); + } + node& get(node& key, shared_memory_holder pMemory) { + return m_pData->get(key, pMemory); + } + bool remove(node& key, shared_memory_holder pMemory) { + return m_pData->remove(key, pMemory); + } + + // map + template + void force_insert(const Key& key, const Value& value, + shared_memory_holder pMemory) { + m_pData->force_insert(key, value, pMemory); + } + + private: + shared_node_data m_pData; +}; +} } -#endif // VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#endif // VALUE_DETAIL_NODE_REF_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/emit.h b/include/yaml-cpp/node/emit.h index 7abf80b..2e4b98d 100644 --- a/include/yaml-cpp/node/emit.h +++ b/include/yaml-cpp/node/emit.h @@ -1,23 +1,23 @@ #ifndef NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif #include #include -namespace YAML -{ - class Emitter; - class Node; - - Emitter& operator << (Emitter& out, const Node& node); - std::ostream& operator << (std::ostream& out, const Node& node); - - std::string Dump(const Node& node); +namespace YAML { +class Emitter; +class Node; + +Emitter& operator<<(Emitter& out, const Node& node); +std::ostream& operator<<(std::ostream& out, const Node& node); + +std::string Dump(const Node& node); } -#endif // NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 - +#endif // NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/impl.h b/include/yaml-cpp/node/impl.h index 41c2fcd..425e37f 100644 --- a/include/yaml-cpp/node/impl.h +++ b/include/yaml-cpp/node/impl.h @@ -1,11 +1,12 @@ #ifndef NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif - #include "yaml-cpp/node/node.h" #include "yaml-cpp/node/iterator.h" #include "yaml-cpp/node/detail/memory.h" @@ -13,439 +14,406 @@ #include "yaml-cpp/exceptions.h" #include -namespace YAML -{ - inline Node::Node(): m_isValid(true), m_pNode(NULL) - { - } - - inline Node::Node(NodeType::value type): m_isValid(true), m_pMemory(new detail::memory_holder), m_pNode(&m_pMemory->create_node()) - { - m_pNode->set_type(type); - } - - template - inline Node::Node(const T& rhs): m_isValid(true), m_pMemory(new detail::memory_holder), m_pNode(&m_pMemory->create_node()) - { - Assign(rhs); - } - - inline Node::Node(const detail::iterator_value& rhs): m_isValid(rhs.m_isValid), m_pMemory(rhs.m_pMemory), m_pNode(rhs.m_pNode) - { - } +namespace YAML { +inline Node::Node() : m_isValid(true), m_pNode(NULL) {} - inline Node::Node(const Node& rhs): m_isValid(rhs.m_isValid), m_pMemory(rhs.m_pMemory), m_pNode(rhs.m_pNode) - { - } - - inline Node::Node(Zombie): m_isValid(false), m_pNode(NULL) - { - } - - inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory): m_isValid(true), m_pMemory(pMemory), m_pNode(&node) - { - } - - inline Node::~Node() - { - } - - inline void Node::EnsureNodeExists() const - { - if(!m_isValid) - throw InvalidNode(); - if(!m_pNode) { - m_pMemory.reset(new detail::memory_holder); - m_pNode = &m_pMemory->create_node(); - m_pNode->set_null(); - } - } - - inline bool Node::IsDefined() const - { - if(!m_isValid) - throw InvalidNode(); - return m_pNode ? m_pNode->is_defined() : true; - } - - inline NodeType::value Node::Type() const - { - if(!m_isValid) - throw InvalidNode(); - return m_pNode ? m_pNode->type() : NodeType::Null; - } - - // access - - // template helpers - template - struct as_if { - explicit as_if(const Node& node_): node(node_) {} - const Node& node; - - const T operator()(const S& fallback) const { - if(!node.m_pNode) - return fallback; - - T t; - if(convert::decode(node, t)) - return t; - return fallback; - } - }; - - template - struct as_if { - explicit as_if(const Node& node_): node(node_) {} - const Node& node; - - const std::string operator()(const S& fallback) const { - if(node.Type() != NodeType::Scalar) - return fallback; - return node.Scalar(); - } - }; - - template - struct as_if { - explicit as_if(const Node& node_): node(node_) {} - const Node& node; - - const T operator()() const { - if(!node.m_pNode) - throw TypedBadConversion(); - - T t; - if(convert::decode(node, t)) - return t; - throw TypedBadConversion(); - } - }; - - template<> - struct as_if { - explicit as_if(const Node& node_): node(node_) {} - const Node& node; - - const std::string operator()() const { - if(node.Type() != NodeType::Scalar) - throw TypedBadConversion(); - return node.Scalar(); - } - }; - - // access functions - template - inline const T Node::as() const - { - if(!m_isValid) - throw InvalidNode(); - return as_if(*this)(); - } - - template - inline const T Node::as(const S& fallback) const - { - if(!m_isValid) - throw InvalidNode(); - return as_if(*this)(fallback); - } - - inline const std::string& Node::Scalar() const - { - if(!m_isValid) - throw InvalidNode(); - return m_pNode ? m_pNode->scalar() : detail::node_data::empty_scalar; - } - - inline const std::string& Node::Tag() const - { - if(!m_isValid) - throw InvalidNode(); - return m_pNode ? m_pNode->tag() : detail::node_data::empty_scalar; - } - - inline void Node::SetTag(const std::string& tag) - { - if(!m_isValid) - throw InvalidNode(); - EnsureNodeExists(); - m_pNode->set_tag(tag); - } - - // assignment - inline bool Node::is(const Node& rhs) const - { - if(!m_isValid || !rhs.m_isValid) - throw InvalidNode(); - if(!m_pNode || !rhs.m_pNode) - return false; - return m_pNode->is(*rhs.m_pNode); - } - - template - inline Node& Node::operator=(const T& rhs) - { - if(!m_isValid) - throw InvalidNode(); - Assign(rhs); - return *this; - } - - inline void Node::reset(const YAML::Node& rhs) - { - if(!m_isValid || !rhs.m_isValid) - throw InvalidNode(); - m_pMemory = rhs.m_pMemory; - m_pNode = rhs.m_pNode; - } - - template - inline void Node::Assign(const T& rhs) - { - if(!m_isValid) - throw InvalidNode(); - AssignData(convert::encode(rhs)); - } - - template<> - inline void Node::Assign(const std::string& rhs) - { - if(!m_isValid) - throw InvalidNode(); - EnsureNodeExists(); - m_pNode->set_scalar(rhs); - } - - inline void Node::Assign(const char *rhs) - { - if(!m_isValid) - throw InvalidNode(); - EnsureNodeExists(); - m_pNode->set_scalar(rhs); - } - - inline void Node::Assign(char *rhs) - { - if(!m_isValid) - throw InvalidNode(); - EnsureNodeExists(); - m_pNode->set_scalar(rhs); - } - - inline Node& Node::operator=(const Node& rhs) - { - if(!m_isValid || !rhs.m_isValid) - throw InvalidNode(); - if(is(rhs)) - return *this; - AssignNode(rhs); - return *this; - } - - inline void Node::AssignData(const Node& rhs) - { - if(!m_isValid || !rhs.m_isValid) - throw InvalidNode(); - EnsureNodeExists(); - rhs.EnsureNodeExists(); - - m_pNode->set_data(*rhs.m_pNode); - m_pMemory->merge(*rhs.m_pMemory); - } - - inline void Node::AssignNode(const Node& rhs) - { - if(!m_isValid || !rhs.m_isValid) - throw InvalidNode(); - rhs.EnsureNodeExists(); - - if(!m_pNode) { - m_pNode = rhs.m_pNode; - m_pMemory = rhs.m_pMemory; - return; - } - - m_pNode->set_ref(*rhs.m_pNode); - m_pMemory->merge(*rhs.m_pMemory); - m_pNode = rhs.m_pNode; - } - - // size/iterator - inline std::size_t Node::size() const - { - if(!m_isValid) - throw InvalidNode(); - return m_pNode ? m_pNode->size() : 0; - } - - inline const_iterator Node::begin() const - { - if(!m_isValid) - throw InvalidNode(); - return m_pNode ? const_iterator(m_pNode->begin(), m_pMemory) : const_iterator(); - } - - inline iterator Node::begin() - { - if(!m_isValid) - throw InvalidNode(); - return m_pNode ? iterator(m_pNode->begin(), m_pMemory) : iterator(); - } - - inline const_iterator Node::end() const - { - if(!m_isValid) - throw InvalidNode(); - return m_pNode ? const_iterator(m_pNode->end(), m_pMemory) : const_iterator(); - } - - inline iterator Node::end() - { - if(!m_isValid) - throw InvalidNode(); - return m_pNode ? iterator(m_pNode->end(), m_pMemory) : iterator(); - } - - // sequence - template - inline void Node::push_back(const T& rhs) - { - if(!m_isValid) - throw InvalidNode(); - push_back(Node(rhs)); - } - - inline void Node::push_back(const Node& rhs) - { - if(!m_isValid || !rhs.m_isValid) - throw InvalidNode(); - EnsureNodeExists(); - rhs.EnsureNodeExists(); - - m_pNode->push_back(*rhs.m_pNode, m_pMemory); - m_pMemory->merge(*rhs.m_pMemory); - } - - // helpers for indexing - namespace detail { - template - struct to_value_t { - explicit to_value_t(const T& t_): t(t_) {} - const T& t; - typedef const T& return_type; - - const T& operator()() const { return t; } - }; - - template<> - struct to_value_t { - explicit to_value_t(const char *t_): t(t_) {} - const char *t; - typedef std::string return_type; - - const std::string operator()() const { return t; } - }; - - template<> - struct to_value_t { - explicit to_value_t(char *t_): t(t_) {} - const char *t; - typedef std::string return_type; - - const std::string operator()() const { return t; } - }; - - template - struct to_value_t { - explicit to_value_t(const char *t_): t(t_) {} - const char *t; - typedef std::string return_type; - - const std::string operator()() const { return t; } - }; - - // converts C-strings to std::strings so they can be copied - template - inline typename to_value_t::return_type to_value(const T& t) { - return to_value_t(t)(); - } - } - - // indexing - template - inline const Node Node::operator[](const Key& key) const - { - if(!m_isValid) - throw InvalidNode(); - EnsureNodeExists(); - detail::node& value = static_cast(*m_pNode).get(detail::to_value(key), m_pMemory); - return Node(value, m_pMemory); - } - - template - inline Node Node::operator[](const Key& key) - { - if(!m_isValid) - throw InvalidNode(); - EnsureNodeExists(); - detail::node& value = m_pNode->get(detail::to_value(key), m_pMemory); - return Node(value, m_pMemory); - } - - template - inline bool Node::remove(const Key& key) - { - if(!m_isValid) - throw InvalidNode(); - EnsureNodeExists(); - return m_pNode->remove(detail::to_value(key), m_pMemory); - } - - inline const Node Node::operator[](const Node& key) const - { - if(!m_isValid || !key.m_isValid) - throw InvalidNode(); - EnsureNodeExists(); - key.EnsureNodeExists(); - detail::node& value = static_cast(*m_pNode).get(*key.m_pNode, m_pMemory); - return Node(value, m_pMemory); - } - - inline Node Node::operator[](const Node& key) - { - if(!m_isValid || !key.m_isValid) - throw InvalidNode(); - EnsureNodeExists(); - key.EnsureNodeExists(); - detail::node& value = m_pNode->get(*key.m_pNode, m_pMemory); - return Node(value, m_pMemory); - } - - inline bool Node::remove(const Node& key) - { - if(!m_isValid || !key.m_isValid) - throw InvalidNode(); - EnsureNodeExists(); - key.EnsureNodeExists(); - return m_pNode->remove(*key.m_pNode, m_pMemory); - } - - // map - template - inline void Node::force_insert(const Key& key, const Value& value) - { - if(!m_isValid) - throw InvalidNode(); - EnsureNodeExists(); - m_pNode->force_insert(detail::to_value(key), detail::to_value(value), m_pMemory); - } - - // free functions - inline bool operator==(const Node& lhs, const Node& rhs) - { - return lhs.is(rhs); - } +inline Node::Node(NodeType::value type) + : m_isValid(true), + m_pMemory(new detail::memory_holder), + m_pNode(&m_pMemory->create_node()) { + m_pNode->set_type(type); } -#endif // NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +template +inline Node::Node(const T& rhs) + : m_isValid(true), + m_pMemory(new detail::memory_holder), + m_pNode(&m_pMemory->create_node()) { + Assign(rhs); +} + +inline Node::Node(const detail::iterator_value& rhs) + : m_isValid(rhs.m_isValid), + m_pMemory(rhs.m_pMemory), + m_pNode(rhs.m_pNode) {} + +inline Node::Node(const Node& rhs) + : m_isValid(rhs.m_isValid), + m_pMemory(rhs.m_pMemory), + m_pNode(rhs.m_pNode) {} + +inline Node::Node(Zombie) : m_isValid(false), m_pNode(NULL) {} + +inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory) + : m_isValid(true), m_pMemory(pMemory), m_pNode(&node) {} + +inline Node::~Node() {} + +inline void Node::EnsureNodeExists() const { + if (!m_isValid) + throw InvalidNode(); + if (!m_pNode) { + m_pMemory.reset(new detail::memory_holder); + m_pNode = &m_pMemory->create_node(); + m_pNode->set_null(); + } +} + +inline bool Node::IsDefined() const { + if (!m_isValid) + throw InvalidNode(); + return m_pNode ? m_pNode->is_defined() : true; +} + +inline NodeType::value Node::Type() const { + if (!m_isValid) + throw InvalidNode(); + return m_pNode ? m_pNode->type() : NodeType::Null; +} + +// access + +// template helpers +template +struct as_if { + explicit as_if(const Node& node_) : node(node_) {} + const Node& node; + + const T operator()(const S& fallback) const { + if (!node.m_pNode) + return fallback; + + T t; + if (convert::decode(node, t)) + return t; + return fallback; + } +}; + +template +struct as_if { + explicit as_if(const Node& node_) : node(node_) {} + const Node& node; + + const std::string operator()(const S& fallback) const { + if (node.Type() != NodeType::Scalar) + return fallback; + return node.Scalar(); + } +}; + +template +struct as_if { + explicit as_if(const Node& node_) : node(node_) {} + const Node& node; + + const T operator()() const { + if (!node.m_pNode) + throw TypedBadConversion(); + + T t; + if (convert::decode(node, t)) + return t; + throw TypedBadConversion(); + } +}; + +template <> +struct as_if { + explicit as_if(const Node& node_) : node(node_) {} + const Node& node; + + const std::string operator()() const { + if (node.Type() != NodeType::Scalar) + throw TypedBadConversion(); + return node.Scalar(); + } +}; + +// access functions +template +inline const T Node::as() const { + if (!m_isValid) + throw InvalidNode(); + return as_if(*this)(); +} + +template +inline const T Node::as(const S& fallback) const { + if (!m_isValid) + throw InvalidNode(); + return as_if(*this)(fallback); +} + +inline const std::string& Node::Scalar() const { + if (!m_isValid) + throw InvalidNode(); + return m_pNode ? m_pNode->scalar() : detail::node_data::empty_scalar; +} + +inline const std::string& Node::Tag() const { + if (!m_isValid) + throw InvalidNode(); + return m_pNode ? m_pNode->tag() : detail::node_data::empty_scalar; +} + +inline void Node::SetTag(const std::string& tag) { + if (!m_isValid) + throw InvalidNode(); + EnsureNodeExists(); + m_pNode->set_tag(tag); +} + +// assignment +inline bool Node::is(const Node& rhs) const { + if (!m_isValid || !rhs.m_isValid) + throw InvalidNode(); + if (!m_pNode || !rhs.m_pNode) + return false; + return m_pNode->is(*rhs.m_pNode); +} + +template +inline Node& Node::operator=(const T& rhs) { + if (!m_isValid) + throw InvalidNode(); + Assign(rhs); + return *this; +} + +inline void Node::reset(const YAML::Node& rhs) { + if (!m_isValid || !rhs.m_isValid) + throw InvalidNode(); + m_pMemory = rhs.m_pMemory; + m_pNode = rhs.m_pNode; +} + +template +inline void Node::Assign(const T& rhs) { + if (!m_isValid) + throw InvalidNode(); + AssignData(convert::encode(rhs)); +} + +template <> +inline void Node::Assign(const std::string& rhs) { + if (!m_isValid) + throw InvalidNode(); + EnsureNodeExists(); + m_pNode->set_scalar(rhs); +} + +inline void Node::Assign(const char* rhs) { + if (!m_isValid) + throw InvalidNode(); + EnsureNodeExists(); + m_pNode->set_scalar(rhs); +} + +inline void Node::Assign(char* rhs) { + if (!m_isValid) + throw InvalidNode(); + EnsureNodeExists(); + m_pNode->set_scalar(rhs); +} + +inline Node& Node::operator=(const Node& rhs) { + if (!m_isValid || !rhs.m_isValid) + throw InvalidNode(); + if (is(rhs)) + return *this; + AssignNode(rhs); + return *this; +} + +inline void Node::AssignData(const Node& rhs) { + if (!m_isValid || !rhs.m_isValid) + throw InvalidNode(); + EnsureNodeExists(); + rhs.EnsureNodeExists(); + + m_pNode->set_data(*rhs.m_pNode); + m_pMemory->merge(*rhs.m_pMemory); +} + +inline void Node::AssignNode(const Node& rhs) { + if (!m_isValid || !rhs.m_isValid) + throw InvalidNode(); + rhs.EnsureNodeExists(); + + if (!m_pNode) { + m_pNode = rhs.m_pNode; + m_pMemory = rhs.m_pMemory; + return; + } + + m_pNode->set_ref(*rhs.m_pNode); + m_pMemory->merge(*rhs.m_pMemory); + m_pNode = rhs.m_pNode; +} + +// size/iterator +inline std::size_t Node::size() const { + if (!m_isValid) + throw InvalidNode(); + return m_pNode ? m_pNode->size() : 0; +} + +inline const_iterator Node::begin() const { + if (!m_isValid) + throw InvalidNode(); + return m_pNode ? const_iterator(m_pNode->begin(), m_pMemory) + : const_iterator(); +} + +inline iterator Node::begin() { + if (!m_isValid) + throw InvalidNode(); + return m_pNode ? iterator(m_pNode->begin(), m_pMemory) : iterator(); +} + +inline const_iterator Node::end() const { + if (!m_isValid) + throw InvalidNode(); + return m_pNode ? const_iterator(m_pNode->end(), m_pMemory) : const_iterator(); +} + +inline iterator Node::end() { + if (!m_isValid) + throw InvalidNode(); + return m_pNode ? iterator(m_pNode->end(), m_pMemory) : iterator(); +} + +// sequence +template +inline void Node::push_back(const T& rhs) { + if (!m_isValid) + throw InvalidNode(); + push_back(Node(rhs)); +} + +inline void Node::push_back(const Node& rhs) { + if (!m_isValid || !rhs.m_isValid) + throw InvalidNode(); + EnsureNodeExists(); + rhs.EnsureNodeExists(); + + m_pNode->push_back(*rhs.m_pNode, m_pMemory); + m_pMemory->merge(*rhs.m_pMemory); +} + +// helpers for indexing +namespace detail { +template +struct to_value_t { + explicit to_value_t(const T& t_) : t(t_) {} + const T& t; + typedef const T& return_type; + + const T& operator()() const { return t; } +}; + +template <> +struct to_value_t { + explicit to_value_t(const char* t_) : t(t_) {} + const char* t; + typedef std::string return_type; + + const std::string operator()() const { return t; } +}; + +template <> +struct to_value_t { + explicit to_value_t(char* t_) : t(t_) {} + const char* t; + typedef std::string return_type; + + const std::string operator()() const { return t; } +}; + +template +struct to_value_t { + explicit to_value_t(const char* t_) : t(t_) {} + const char* t; + typedef std::string return_type; + + const std::string operator()() const { return t; } +}; + +// converts C-strings to std::strings so they can be copied +template +inline typename to_value_t::return_type to_value(const T& t) { + return to_value_t(t)(); +} +} + +// indexing +template +inline const Node Node::operator[](const Key& key) const { + if (!m_isValid) + throw InvalidNode(); + EnsureNodeExists(); + detail::node& value = static_cast(*m_pNode) + .get(detail::to_value(key), m_pMemory); + return Node(value, m_pMemory); +} + +template +inline Node Node::operator[](const Key& key) { + if (!m_isValid) + throw InvalidNode(); + EnsureNodeExists(); + detail::node& value = m_pNode->get(detail::to_value(key), m_pMemory); + return Node(value, m_pMemory); +} + +template +inline bool Node::remove(const Key& key) { + if (!m_isValid) + throw InvalidNode(); + EnsureNodeExists(); + return m_pNode->remove(detail::to_value(key), m_pMemory); +} + +inline const Node Node::operator[](const Node& key) const { + if (!m_isValid || !key.m_isValid) + throw InvalidNode(); + EnsureNodeExists(); + key.EnsureNodeExists(); + detail::node& value = + static_cast(*m_pNode).get(*key.m_pNode, m_pMemory); + return Node(value, m_pMemory); +} + +inline Node Node::operator[](const Node& key) { + if (!m_isValid || !key.m_isValid) + throw InvalidNode(); + EnsureNodeExists(); + key.EnsureNodeExists(); + detail::node& value = m_pNode->get(*key.m_pNode, m_pMemory); + return Node(value, m_pMemory); +} + +inline bool Node::remove(const Node& key) { + if (!m_isValid || !key.m_isValid) + throw InvalidNode(); + EnsureNodeExists(); + key.EnsureNodeExists(); + return m_pNode->remove(*key.m_pNode, m_pMemory); +} + +// map +template +inline void Node::force_insert(const Key& key, const Value& value) { + if (!m_isValid) + throw InvalidNode(); + EnsureNodeExists(); + m_pNode->force_insert(detail::to_value(key), detail::to_value(value), + m_pMemory); +} + +// free functions +inline bool operator==(const Node& lhs, const Node& rhs) { return lhs.is(rhs); } +} + +#endif // NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/iterator.h b/include/yaml-cpp/node/iterator.h index 98c8851..366a9c8 100644 --- a/include/yaml-cpp/node/iterator.h +++ b/include/yaml-cpp/node/iterator.h @@ -1,11 +1,12 @@ #ifndef VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif - #include "yaml-cpp/dll.h" #include "yaml-cpp/node/node.h" #include "yaml-cpp/node/detail/iterator_fwd.h" @@ -14,15 +15,17 @@ #include #include -namespace YAML -{ - namespace detail { - struct iterator_value: public Node, std::pair { - iterator_value() {} - explicit iterator_value(const Node& rhs): Node(rhs), std::pair(Node(Node::ZombieNode), Node(Node::ZombieNode)) {} - explicit iterator_value(const Node& key, const Node& value): Node(Node::ZombieNode), std::pair(key, value) {} - }; - } +namespace YAML { +namespace detail { +struct iterator_value : public Node, std::pair { + iterator_value() {} + explicit iterator_value(const Node& rhs) + : Node(rhs), + std::pair(Node(Node::ZombieNode), Node(Node::ZombieNode)) {} + explicit iterator_value(const Node& key, const Node& value) + : Node(Node::ZombieNode), std::pair(key, value) {} +}; +} } -#endif // VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#endif // VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/node.h b/include/yaml-cpp/node/node.h index b949850..75df149 100644 --- a/include/yaml-cpp/node/node.h +++ b/include/yaml-cpp/node/node.h @@ -1,11 +1,12 @@ #ifndef NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif - #include "yaml-cpp/dll.h" #include "yaml-cpp/node/ptr.h" #include "yaml-cpp/node/type.h" @@ -13,104 +14,115 @@ #include "yaml-cpp/node/detail/bool_type.h" #include -namespace YAML -{ - class Node - { - public: - friend class NodeBuilder; - friend class NodeEvents; - friend struct detail::iterator_value; - friend class detail::node_data; - template friend class detail::iterator_base; - template friend struct as_if; - - typedef YAML::iterator iterator; - typedef YAML::const_iterator const_iterator; - - Node(); - explicit Node(NodeType::value type); - template explicit Node(const T& rhs); - explicit Node(const detail::iterator_value& rhs); - Node(const Node& rhs); - ~Node(); - - NodeType::value Type() const; - bool IsDefined() const; - bool IsNull() const { return Type() == NodeType::Null; } - bool IsScalar() const { return Type() == NodeType::Scalar; } - bool IsSequence() const { return Type() == NodeType::Sequence; } - bool IsMap() const { return Type() == NodeType::Map; } - - // bool conversions - YAML_CPP_OPERATOR_BOOL(); - bool operator!() const { return !IsDefined(); } - - // access - template const T as() const; - template const T as(const S& fallback) const; - const std::string& Scalar() const; - const std::string& Tag() const; - void SetTag(const std::string& tag); +namespace YAML { +class Node { + public: + friend class NodeBuilder; + friend class NodeEvents; + friend struct detail::iterator_value; + friend class detail::node_data; + template + friend class detail::iterator_base; + template + friend struct as_if; - // assignment - bool is(const Node& rhs) const; - template Node& operator=(const T& rhs); - Node& operator=(const Node& rhs); - void reset(const Node& rhs = Node()); - - // size/iterator - std::size_t size() const; + typedef YAML::iterator iterator; + typedef YAML::const_iterator const_iterator; - const_iterator begin() const; - iterator begin(); - - const_iterator end() const; - iterator end(); - - // sequence - template void push_back(const T& rhs); - void push_back(const Node& rhs); - - // indexing - template const Node operator[](const Key& key) const; - template Node operator[](const Key& key); - template bool remove(const Key& key); + Node(); + explicit Node(NodeType::value type); + template + explicit Node(const T& rhs); + explicit Node(const detail::iterator_value& rhs); + Node(const Node& rhs); + ~Node(); - const Node operator[](const Node& key) const; - Node operator[](const Node& key); - bool remove(const Node& key); - - // map - template - void force_insert(const Key& key, const Value& value); + NodeType::value Type() const; + bool IsDefined() const; + bool IsNull() const { return Type() == NodeType::Null; } + bool IsScalar() const { return Type() == NodeType::Scalar; } + bool IsSequence() const { return Type() == NodeType::Sequence; } + bool IsMap() const { return Type() == NodeType::Map; } - private: - enum Zombie { ZombieNode }; - explicit Node(Zombie); - explicit Node(detail::node& node, detail::shared_memory_holder pMemory); - - void EnsureNodeExists() const; - - template void Assign(const T& rhs); - void Assign(const char *rhs); - void Assign(char *rhs); + // bool conversions + YAML_CPP_OPERATOR_BOOL(); + bool operator!() const { return !IsDefined(); } - void AssignData(const Node& rhs); - void AssignNode(const Node& rhs); - - private: - bool m_isValid; - mutable detail::shared_memory_holder m_pMemory; - mutable detail::node *m_pNode; - }; + // access + template + const T as() const; + template + const T as(const S& fallback) const; + const std::string& Scalar() const; + const std::string& Tag() const; + void SetTag(const std::string& tag); - bool operator==(const Node& lhs, const Node& rhs); - - Node Clone(const Node& node); - - template - struct convert; + // assignment + bool is(const Node& rhs) const; + template + Node& operator=(const T& rhs); + Node& operator=(const Node& rhs); + void reset(const Node& rhs = Node()); + + // size/iterator + std::size_t size() const; + + const_iterator begin() const; + iterator begin(); + + const_iterator end() const; + iterator end(); + + // sequence + template + void push_back(const T& rhs); + void push_back(const Node& rhs); + + // indexing + template + const Node operator[](const Key& key) const; + template + Node operator[](const Key& key); + template + bool remove(const Key& key); + + const Node operator[](const Node& key) const; + Node operator[](const Node& key); + bool remove(const Node& key); + + // map + template + void force_insert(const Key& key, const Value& value); + + private: + enum Zombie { + ZombieNode + }; + explicit Node(Zombie); + explicit Node(detail::node& node, detail::shared_memory_holder pMemory); + + void EnsureNodeExists() const; + + template + void Assign(const T& rhs); + void Assign(const char* rhs); + void Assign(char* rhs); + + void AssignData(const Node& rhs); + void AssignNode(const Node& rhs); + + private: + bool m_isValid; + mutable detail::shared_memory_holder m_pMemory; + mutable detail::node* m_pNode; +}; + +bool operator==(const Node& lhs, const Node& rhs); + +Node Clone(const Node& node); + +template +struct convert; } -#endif // NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#endif // NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/parse.h b/include/yaml-cpp/node/parse.h index 82dbdc1..4e3cb90 100644 --- a/include/yaml-cpp/node/parse.h +++ b/include/yaml-cpp/node/parse.h @@ -1,7 +1,9 @@ #ifndef VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif @@ -9,20 +11,18 @@ #include #include -namespace YAML -{ - class Node; - - Node Load(const std::string& input); - Node Load(const char *input); - Node Load(std::istream& input); - Node LoadFile(const std::string& filename); +namespace YAML { +class Node; - std::vector LoadAll(const std::string& input); - std::vector LoadAll(const char *input); - std::vector LoadAll(std::istream& input); - std::vector LoadAllFromFile(const std::string& filename); +Node Load(const std::string& input); +Node Load(const char* input); +Node Load(std::istream& input); +Node LoadFile(const std::string& filename); + +std::vector LoadAll(const std::string& input); +std::vector LoadAll(const char* input); +std::vector LoadAll(std::istream& input); +std::vector LoadAllFromFile(const std::string& filename); } -#endif // VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 - +#endif // VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/ptr.h b/include/yaml-cpp/node/ptr.h index 316dbd2..64c8689 100644 --- a/include/yaml-cpp/node/ptr.h +++ b/include/yaml-cpp/node/ptr.h @@ -1,29 +1,29 @@ #ifndef VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif - #include "yaml-cpp/dll.h" #include -namespace YAML -{ - namespace detail { - class node; - class node_ref; - class node_data; - class memory; - class memory_holder; +namespace YAML { +namespace detail { +class node; +class node_ref; +class node_data; +class memory; +class memory_holder; - typedef boost::shared_ptr shared_node; - typedef boost::shared_ptr shared_node_ref; - typedef boost::shared_ptr shared_node_data; - typedef boost::shared_ptr shared_memory_holder; - typedef boost::shared_ptr shared_memory; - } +typedef boost::shared_ptr shared_node; +typedef boost::shared_ptr shared_node_ref; +typedef boost::shared_ptr shared_node_data; +typedef boost::shared_ptr shared_memory_holder; +typedef boost::shared_ptr shared_memory; +} } -#endif // VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#endif // VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/node/type.h b/include/yaml-cpp/node/type.h index 5ac8041..da1bc11 100644 --- a/include/yaml-cpp/node/type.h +++ b/include/yaml-cpp/node/type.h @@ -1,14 +1,22 @@ #ifndef VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif - -namespace YAML -{ - struct NodeType { enum value { Undefined, Null, Scalar, Sequence, Map }; }; +namespace YAML { +struct NodeType { + enum value { + Undefined, + Null, + Scalar, + Sequence, + Map + }; +}; } -#endif // VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#endif // VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/parser.h b/include/yaml-cpp/parser.h index 8ec926b..18389bb 100644 --- a/include/yaml-cpp/parser.h +++ b/include/yaml-cpp/parser.h @@ -1,47 +1,46 @@ #ifndef PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif - #include "yaml-cpp/dll.h" #include "yaml-cpp/noncopyable.h" #include #include -namespace YAML -{ - struct Directives; - struct Token; - class EventHandler; - class Scanner; +namespace YAML { +struct Directives; +struct Token; +class EventHandler; +class Scanner; - class YAML_CPP_API Parser: private noncopyable - { - public: - Parser(); - Parser(std::istream& in); - ~Parser(); +class YAML_CPP_API Parser : private noncopyable { + public: + Parser(); + Parser(std::istream& in); + ~Parser(); - operator bool() const; + operator bool() const; - void Load(std::istream& in); - bool HandleNextDocument(EventHandler& eventHandler); + void Load(std::istream& in); + bool HandleNextDocument(EventHandler& eventHandler); - void PrintTokens(std::ostream& out); + void PrintTokens(std::ostream& out); - private: - void ParseDirectives(); - void HandleDirective(const Token& token); - void HandleYamlDirective(const Token& token); - void HandleTagDirective(const Token& token); - - private: - std::auto_ptr m_pScanner; - std::auto_ptr m_pDirectives; - }; + private: + void ParseDirectives(); + void HandleDirective(const Token& token); + void HandleYamlDirective(const Token& token); + void HandleTagDirective(const Token& token); + + private: + std::auto_ptr m_pScanner; + std::auto_ptr m_pDirectives; +}; } -#endif // PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#endif // PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/yaml.h b/include/yaml-cpp/yaml.h index 4e63408..4f09097 100644 --- a/include/yaml-cpp/yaml.h +++ b/include/yaml-cpp/yaml.h @@ -1,7 +1,9 @@ #ifndef YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif @@ -18,4 +20,4 @@ #include "yaml-cpp/node/parse.h" #include "yaml-cpp/node/emit.h" -#endif // YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#endif // YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/src/convert.cpp b/src/convert.cpp index dc715f7..50b15bc 100644 --- a/src/convert.cpp +++ b/src/convert.cpp @@ -2,82 +2,72 @@ #include "yaml-cpp/node/impl.h" #include -namespace -{ - // we're not gonna mess with the mess that is all the isupper/etc. functions - bool IsLower(char ch) { return 'a' <= ch && ch <= 'z'; } - bool IsUpper(char ch) { return 'A' <= ch && ch <= 'Z'; } - char ToLower(char ch) { return IsUpper(ch) ? ch + 'a' - 'A' : ch; } - - std::string tolower(const std::string& str) - { - std::string s(str); - std::transform(s.begin(), s.end(), s.begin(), ToLower); - return s; - } - - template - bool IsEntirely(const std::string& str, T func) - { - for(std::size_t i=0;i::decode(const Node& node, bool& rhs) { - if(!node.IsScalar()) - return false; - - // we can't use iostream bool extraction operators as they don't - // recognize all possible values in the table below (taken from - // http://yaml.org/type/bool.html) - static const struct { - std::string truename, falsename; - } names[] = { - { "y", "n" }, - { "yes", "no" }, - { "true", "false" }, - { "on", "off" }, - }; - - if(!IsFlexibleCase(node.Scalar())) - return false; - - for(unsigned i=0;i +bool IsEntirely(const std::string& str, T func) { + for (std::size_t i = 0; i < str.size(); i++) + if (!func(str[i])) + return false; + + return true; +} + +// IsFlexibleCase +// . Returns true if 'str' is: +// . UPPERCASE +// . lowercase +// . Capitalized +bool IsFlexibleCase(const std::string& str) { + if (str.empty()) + return true; + + if (IsEntirely(str, IsLower)) + return true; + + bool firstcaps = IsUpper(str[0]); + std::string rest = str.substr(1); + return firstcaps && (IsEntirely(rest, IsLower) || IsEntirely(rest, IsUpper)); +} +} + +namespace YAML { +bool convert::decode(const Node& node, bool& rhs) { + if (!node.IsScalar()) + return false; + + // we can't use iostream bool extraction operators as they don't + // recognize all possible values in the table below (taken from + // http://yaml.org/type/bool.html) + static const struct { + std::string truename, falsename; + } names[] = {{"y", "n"}, {"yes", "no"}, {"true", "false"}, {"on", "off"}, }; + + if (!IsFlexibleCase(node.Scalar())) + return false; + + for (unsigned i = 0; i < sizeof(names) / sizeof(names[0]); i++) { + if (names[i].truename == tolower(node.Scalar())) { + rhs = true; + return true; + } + + if (names[i].falsename == tolower(node.Scalar())) { + rhs = false; + return true; + } + } + + return false; +} } diff --git a/src/emit.cpp b/src/emit.cpp index 1f0a647..5fb593b 100644 --- a/src/emit.cpp +++ b/src/emit.cpp @@ -3,27 +3,23 @@ #include "yaml-cpp/emitter.h" #include "nodeevents.h" -namespace YAML -{ - Emitter& operator << (Emitter& out, const Node& node) - { - EmitFromEvents emitFromEvents(out); - NodeEvents events(node); - events.Emit(emitFromEvents); - return out; - } - - std::ostream& operator << (std::ostream& out, const Node& node) - { - Emitter emitter(out); - emitter << node; - return out; - } - - std::string Dump(const Node& node) - { - Emitter emitter; - emitter << node; - return emitter.c_str(); - } +namespace YAML { +Emitter& operator<<(Emitter& out, const Node& node) { + EmitFromEvents emitFromEvents(out); + NodeEvents events(node); + events.Emit(emitFromEvents); + return out; +} + +std::ostream& operator<<(std::ostream& out, const Node& node) { + Emitter emitter(out); + emitter << node; + return out; +} + +std::string Dump(const Node& node) { + Emitter emitter; + emitter << node; + return emitter.c_str(); +} } diff --git a/src/memory.cpp b/src/memory.cpp index 98d0dfb..1a02bf0 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -1,29 +1,24 @@ #include "yaml-cpp/node/detail/memory.h" #include "yaml-cpp/node/detail/node.h" -namespace YAML -{ - namespace detail - { - void memory_holder::merge(memory_holder& rhs) - { - if(m_pMemory == rhs.m_pMemory) - return; - - m_pMemory->merge(*rhs.m_pMemory); - rhs.m_pMemory = m_pMemory; - } - - node& memory::create_node() - { - shared_node pNode(new node); - m_nodes.insert(pNode); - return *pNode; - } - - void memory::merge(const memory& rhs) - { - m_nodes.insert(rhs.m_nodes.begin(), rhs.m_nodes.end()); - } - } +namespace YAML { +namespace detail { +void memory_holder::merge(memory_holder& rhs) { + if (m_pMemory == rhs.m_pMemory) + return; + + m_pMemory->merge(*rhs.m_pMemory); + rhs.m_pMemory = m_pMemory; +} + +node& memory::create_node() { + shared_node pNode(new node); + m_nodes.insert(pNode); + return *pNode; +} + +void memory::merge(const memory& rhs) { + m_nodes.insert(rhs.m_nodes.begin(), rhs.m_nodes.end()); +} +} } diff --git a/src/node.cpp b/src/node.cpp index 2d21aa9..2088e13 100644 --- a/src/node.cpp +++ b/src/node.cpp @@ -2,13 +2,11 @@ #include "nodebuilder.h" #include "nodeevents.h" -namespace YAML -{ - Node Clone(const Node& node) - { - NodeEvents events(node); - NodeBuilder builder; - events.Emit(builder); - return builder.Root(); - } +namespace YAML { +Node Clone(const Node& node) { + NodeEvents events(node); + NodeBuilder builder; + events.Emit(builder); + return builder.Root(); +} } diff --git a/src/node_data.cpp b/src/node_data.cpp index 6f82f7b..db80be9 100644 --- a/src/node_data.cpp +++ b/src/node_data.cpp @@ -4,292 +4,280 @@ #include "yaml-cpp/exceptions.h" #include -namespace YAML -{ - namespace detail - { - std::string node_data::empty_scalar; +namespace YAML { +namespace detail { +std::string node_data::empty_scalar; - node_data::node_data(): m_isDefined(false), m_type(NodeType::Null), m_seqSize(0) - { - } +node_data::node_data() + : m_isDefined(false), m_type(NodeType::Null), m_seqSize(0) {} - void node_data::mark_defined() - { - if(m_type == NodeType::Undefined) - m_type = NodeType::Null; - m_isDefined = true; - } - - void node_data::set_type(NodeType::value type) - { - if(type == NodeType::Undefined) { - m_type = type; - m_isDefined = false; - return; - } - - - m_isDefined = true; - if(type == m_type) - return; - - m_type = type; - - switch(m_type) { - case NodeType::Null: - break; - case NodeType::Scalar: - m_scalar.clear(); - break; - case NodeType::Sequence: - reset_sequence(); - break; - case NodeType::Map: - reset_map(); - break; - case NodeType::Undefined: - assert(false); - break; - } - } - - void node_data::set_tag(const std::string& tag) - { - m_tag = tag; - } - - void node_data::set_null() - { - m_isDefined = true; - m_type = NodeType::Null; - } - - void node_data::set_scalar(const std::string& scalar) - { - m_isDefined = true; - m_type = NodeType::Scalar; - m_scalar = scalar; - } - - // size/iterator - std::size_t node_data::size() const - { - if(!m_isDefined) - return 0; - - switch(m_type) { - case NodeType::Sequence: compute_seq_size(); return m_seqSize; - case NodeType::Map: compute_map_size(); return m_map.size() - m_undefinedPairs.size(); - default: - return 0; - } - return 0; - } - - void node_data::compute_seq_size() const - { - while(m_seqSize < m_sequence.size() && m_sequence[m_seqSize]->is_defined()) - m_seqSize++; - } - - void node_data::compute_map_size() const - { - kv_pairs::iterator it = m_undefinedPairs.begin(); - while(it != m_undefinedPairs.end()) { - kv_pairs::iterator jt = boost::next(it); - if(it->first->is_defined() && it->second->is_defined()) - m_undefinedPairs.erase(it); - it = jt; - } - } - - const_node_iterator node_data::begin() const - { - if(!m_isDefined) - return const_node_iterator(); - - switch(m_type) { - case NodeType::Sequence: return const_node_iterator(m_sequence.begin()); - case NodeType::Map: return const_node_iterator(m_map.begin(), m_map.end()); - default: return const_node_iterator(); - } - } - - node_iterator node_data::begin() - { - if(!m_isDefined) - return node_iterator(); - - switch(m_type) { - case NodeType::Sequence: return node_iterator(m_sequence.begin()); - case NodeType::Map: return node_iterator(m_map.begin(), m_map.end()); - default: return node_iterator(); - } - } - - const_node_iterator node_data::end() const - { - if(!m_isDefined) - return const_node_iterator(); - - switch(m_type) { - case NodeType::Sequence: return const_node_iterator(m_sequence.end()); - case NodeType::Map: return const_node_iterator(m_map.end(), m_map.end()); - default: return const_node_iterator(); - } - } - - node_iterator node_data::end() - { - if(!m_isDefined) - return node_iterator(); - - switch(m_type) { - case NodeType::Sequence: return node_iterator(m_sequence.end()); - case NodeType::Map: return node_iterator(m_map.end(), m_map.end()); - default: return node_iterator(); - } - } - - // sequence - void node_data::push_back(node& node, shared_memory_holder /* pMemory */) - { - if(m_type == NodeType::Undefined || m_type == NodeType::Null) { - m_type = NodeType::Sequence; - reset_sequence(); - } - - if(m_type != NodeType::Sequence) - throw BadPushback(); - - m_sequence.push_back(&node); - } - - void node_data::insert(node& key, node& value, shared_memory_holder pMemory) - { - switch(m_type) { - case NodeType::Map: - break; - case NodeType::Undefined: - case NodeType::Null: - case NodeType::Sequence: - convert_to_map(pMemory); - break; - case NodeType::Scalar: - throw BadSubscript(); - } - - insert_map_pair(key, value); - } - - // indexing - node& node_data::get(node& key, shared_memory_holder pMemory) const - { - if(m_type != NodeType::Map) - return pMemory->create_node(); - - for(node_map::const_iterator it=m_map.begin();it!=m_map.end();++it) { - if(it->first->is(key)) - return *it->second; - } - - return pMemory->create_node(); - } - - node& node_data::get(node& key, shared_memory_holder pMemory) - { - switch(m_type) { - case NodeType::Map: - break; - case NodeType::Undefined: - case NodeType::Null: - case NodeType::Sequence: - convert_to_map(pMemory); - break; - case NodeType::Scalar: - throw BadSubscript(); - } - - for(node_map::const_iterator it=m_map.begin();it!=m_map.end();++it) { - if(it->first->is(key)) - return *it->second; - } - - node& value = pMemory->create_node(); - insert_map_pair(key, value); - return value; - } - - bool node_data::remove(node& key, shared_memory_holder /* pMemory */) - { - if(m_type != NodeType::Map) - return false; - - for(node_map::iterator it=m_map.begin();it!=m_map.end();++it) { - if(it->first->is(key)) { - m_map.erase(it); - return true; - } - } - - return false; - } - - void node_data::reset_sequence() - { - m_sequence.clear(); - m_seqSize = 0; - } - - void node_data::reset_map() - { - m_map.clear(); - m_undefinedPairs.clear(); - } - - void node_data::insert_map_pair(node& key, node& value) - { - m_map[&key] = &value; - if(!key.is_defined() || !value.is_defined()) - m_undefinedPairs.push_back(kv_pair(&key, &value)); - } - - void node_data::convert_to_map(shared_memory_holder pMemory) - { - switch(m_type) { - case NodeType::Undefined: - case NodeType::Null: - reset_map(); - m_type = NodeType::Map; - break; - case NodeType::Sequence: - convert_sequence_to_map(pMemory); - break; - case NodeType::Map: - break; - case NodeType::Scalar: - assert(false); - break; - } - } - - void node_data::convert_sequence_to_map(shared_memory_holder pMemory) - { - assert(m_type == NodeType::Sequence); - - reset_map(); - for(std::size_t i=0;icreate_node(); - key.set_scalar(stream.str()); - insert_map_pair(key, *m_sequence[i]); - } - - reset_sequence(); - m_type = NodeType::Map; - } - } +void node_data::mark_defined() { + if (m_type == NodeType::Undefined) + m_type = NodeType::Null; + m_isDefined = true; +} + +void node_data::set_type(NodeType::value type) { + if (type == NodeType::Undefined) { + m_type = type; + m_isDefined = false; + return; + } + + m_isDefined = true; + if (type == m_type) + return; + + m_type = type; + + switch (m_type) { + case NodeType::Null: + break; + case NodeType::Scalar: + m_scalar.clear(); + break; + case NodeType::Sequence: + reset_sequence(); + break; + case NodeType::Map: + reset_map(); + break; + case NodeType::Undefined: + assert(false); + break; + } +} + +void node_data::set_tag(const std::string& tag) { m_tag = tag; } + +void node_data::set_null() { + m_isDefined = true; + m_type = NodeType::Null; +} + +void node_data::set_scalar(const std::string& scalar) { + m_isDefined = true; + m_type = NodeType::Scalar; + m_scalar = scalar; +} + +// size/iterator +std::size_t node_data::size() const { + if (!m_isDefined) + return 0; + + switch (m_type) { + case NodeType::Sequence: + compute_seq_size(); + return m_seqSize; + case NodeType::Map: + compute_map_size(); + return m_map.size() - m_undefinedPairs.size(); + default: + return 0; + } + return 0; +} + +void node_data::compute_seq_size() const { + while (m_seqSize < m_sequence.size() && m_sequence[m_seqSize]->is_defined()) + m_seqSize++; +} + +void node_data::compute_map_size() const { + kv_pairs::iterator it = m_undefinedPairs.begin(); + while (it != m_undefinedPairs.end()) { + kv_pairs::iterator jt = boost::next(it); + if (it->first->is_defined() && it->second->is_defined()) + m_undefinedPairs.erase(it); + it = jt; + } +} + +const_node_iterator node_data::begin() const { + if (!m_isDefined) + return const_node_iterator(); + + switch (m_type) { + case NodeType::Sequence: + return const_node_iterator(m_sequence.begin()); + case NodeType::Map: + return const_node_iterator(m_map.begin(), m_map.end()); + default: + return const_node_iterator(); + } +} + +node_iterator node_data::begin() { + if (!m_isDefined) + return node_iterator(); + + switch (m_type) { + case NodeType::Sequence: + return node_iterator(m_sequence.begin()); + case NodeType::Map: + return node_iterator(m_map.begin(), m_map.end()); + default: + return node_iterator(); + } +} + +const_node_iterator node_data::end() const { + if (!m_isDefined) + return const_node_iterator(); + + switch (m_type) { + case NodeType::Sequence: + return const_node_iterator(m_sequence.end()); + case NodeType::Map: + return const_node_iterator(m_map.end(), m_map.end()); + default: + return const_node_iterator(); + } +} + +node_iterator node_data::end() { + if (!m_isDefined) + return node_iterator(); + + switch (m_type) { + case NodeType::Sequence: + return node_iterator(m_sequence.end()); + case NodeType::Map: + return node_iterator(m_map.end(), m_map.end()); + default: + return node_iterator(); + } +} + +// sequence +void node_data::push_back(node& node, shared_memory_holder /* pMemory */) { + if (m_type == NodeType::Undefined || m_type == NodeType::Null) { + m_type = NodeType::Sequence; + reset_sequence(); + } + + if (m_type != NodeType::Sequence) + throw BadPushback(); + + m_sequence.push_back(&node); +} + +void node_data::insert(node& key, node& value, shared_memory_holder pMemory) { + switch (m_type) { + case NodeType::Map: + break; + case NodeType::Undefined: + case NodeType::Null: + case NodeType::Sequence: + convert_to_map(pMemory); + break; + case NodeType::Scalar: + throw BadSubscript(); + } + + insert_map_pair(key, value); +} + +// indexing +node& node_data::get(node& key, shared_memory_holder pMemory) const { + if (m_type != NodeType::Map) + return pMemory->create_node(); + + for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) { + if (it->first->is(key)) + return *it->second; + } + + return pMemory->create_node(); +} + +node& node_data::get(node& key, shared_memory_holder pMemory) { + switch (m_type) { + case NodeType::Map: + break; + case NodeType::Undefined: + case NodeType::Null: + case NodeType::Sequence: + convert_to_map(pMemory); + break; + case NodeType::Scalar: + throw BadSubscript(); + } + + for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) { + if (it->first->is(key)) + return *it->second; + } + + node& value = pMemory->create_node(); + insert_map_pair(key, value); + return value; +} + +bool node_data::remove(node& key, shared_memory_holder /* pMemory */) { + if (m_type != NodeType::Map) + return false; + + for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) { + if (it->first->is(key)) { + m_map.erase(it); + return true; + } + } + + return false; +} + +void node_data::reset_sequence() { + m_sequence.clear(); + m_seqSize = 0; +} + +void node_data::reset_map() { + m_map.clear(); + m_undefinedPairs.clear(); +} + +void node_data::insert_map_pair(node& key, node& value) { + m_map[&key] = &value; + if (!key.is_defined() || !value.is_defined()) + m_undefinedPairs.push_back(kv_pair(&key, &value)); +} + +void node_data::convert_to_map(shared_memory_holder pMemory) { + switch (m_type) { + case NodeType::Undefined: + case NodeType::Null: + reset_map(); + m_type = NodeType::Map; + break; + case NodeType::Sequence: + convert_sequence_to_map(pMemory); + break; + case NodeType::Map: + break; + case NodeType::Scalar: + assert(false); + break; + } +} + +void node_data::convert_sequence_to_map(shared_memory_holder pMemory) { + assert(m_type == NodeType::Sequence); + + reset_map(); + for (std::size_t i = 0; i < m_sequence.size(); i++) { + std::stringstream stream; + stream << i; + + node& key = pMemory->create_node(); + key.set_scalar(stream.str()); + insert_map_pair(key, *m_sequence[i]); + } + + reset_sequence(); + m_type = NodeType::Map; +} +} } diff --git a/src/nodebuilder.cpp b/src/nodebuilder.cpp index 6735f73..3ef2f7d 100644 --- a/src/nodebuilder.cpp +++ b/src/nodebuilder.cpp @@ -4,135 +4,119 @@ #include "yaml-cpp/node/impl.h" #include -namespace YAML -{ - NodeBuilder::NodeBuilder(): m_pMemory(new detail::memory_holder), m_pRoot(0), m_mapDepth(0) - { - m_anchors.push_back(0); // since the anchors start at 1 - } - - NodeBuilder::~NodeBuilder() - { - } - - Node NodeBuilder::Root() - { - if(!m_pRoot) - return Node(); - - return Node(*m_pRoot, m_pMemory); - } - - void NodeBuilder::OnDocumentStart(const Mark&) - { - } - - void NodeBuilder::OnDocumentEnd() - { - } - - void NodeBuilder::OnNull(const Mark& /* mark */, anchor_t anchor) - { - detail::node& node = Push(anchor); - node.set_null(); - Pop(); - } - - void NodeBuilder::OnAlias(const Mark& /* mark */, anchor_t anchor) - { - detail::node& node = *m_anchors[anchor]; - Push(node); - Pop(); - } - - void NodeBuilder::OnScalar(const Mark& /* mark */, const std::string& tag, anchor_t anchor, const std::string& value) - { - detail::node& node = Push(anchor); - node.set_scalar(value); - node.set_tag(tag); - Pop(); - } - - void NodeBuilder::OnSequenceStart(const Mark& /* mark */, const std::string& tag, anchor_t anchor) - { - detail::node& node = Push(anchor); - node.set_tag(tag); - node.set_type(NodeType::Sequence); - } - - void NodeBuilder::OnSequenceEnd() - { - Pop(); - } - - void NodeBuilder::OnMapStart(const Mark& /* mark */, const std::string& tag, anchor_t anchor) - { - detail::node& node = Push(anchor); - node.set_type(NodeType::Map); - node.set_tag(tag); - m_mapDepth++; - } - - void NodeBuilder::OnMapEnd() - { - assert(m_mapDepth > 0); - m_mapDepth--; - Pop(); - } - - detail::node& NodeBuilder::Push(anchor_t anchor) - { - detail::node& node = m_pMemory->create_node(); - RegisterAnchor(anchor, node); - Push(node); - return node; - } - - void NodeBuilder::Push(detail::node& node) - { - const bool needsKey = (!m_stack.empty() && m_stack.back()->type() == NodeType::Map && m_keys.size() < m_mapDepth); - - m_stack.push_back(&node); - if(needsKey) - m_keys.push_back(PushedKey(&node, false)); - } - - void NodeBuilder::Pop() - { - assert(!m_stack.empty()); - if(m_stack.size() == 1) { - m_pRoot = m_stack[0]; - m_stack.pop_back(); - return; - } - - detail::node& node = *m_stack.back(); - m_stack.pop_back(); - - detail::node& collection = *m_stack.back(); - - if(collection.type() == NodeType::Sequence) { - collection.push_back(node, m_pMemory); - } else if(collection.type() == NodeType::Map) { - assert(!m_keys.empty()); - PushedKey& key = m_keys.back(); - if(key.second) { - collection.insert(*key.first, node, m_pMemory); - m_keys.pop_back(); - } else { - key.second = true; - } - } else { - assert(false); - m_stack.clear(); - } - } - - void NodeBuilder::RegisterAnchor(anchor_t anchor, detail::node& node) - { - if(anchor) { - assert(anchor == m_anchors.size()); - m_anchors.push_back(&node); - } - } +namespace YAML { +NodeBuilder::NodeBuilder() + : m_pMemory(new detail::memory_holder), m_pRoot(0), m_mapDepth(0) { + m_anchors.push_back(0); // since the anchors start at 1 +} + +NodeBuilder::~NodeBuilder() {} + +Node NodeBuilder::Root() { + if (!m_pRoot) + return Node(); + + return Node(*m_pRoot, m_pMemory); +} + +void NodeBuilder::OnDocumentStart(const Mark&) {} + +void NodeBuilder::OnDocumentEnd() {} + +void NodeBuilder::OnNull(const Mark& /* mark */, anchor_t anchor) { + detail::node& node = Push(anchor); + node.set_null(); + Pop(); +} + +void NodeBuilder::OnAlias(const Mark& /* mark */, anchor_t anchor) { + detail::node& node = *m_anchors[anchor]; + Push(node); + Pop(); +} + +void NodeBuilder::OnScalar(const Mark& /* mark */, const std::string& tag, + anchor_t anchor, const std::string& value) { + detail::node& node = Push(anchor); + node.set_scalar(value); + node.set_tag(tag); + Pop(); +} + +void NodeBuilder::OnSequenceStart(const Mark& /* mark */, + const std::string& tag, anchor_t anchor) { + detail::node& node = Push(anchor); + node.set_tag(tag); + node.set_type(NodeType::Sequence); +} + +void NodeBuilder::OnSequenceEnd() { Pop(); } + +void NodeBuilder::OnMapStart(const Mark& /* mark */, const std::string& tag, + anchor_t anchor) { + detail::node& node = Push(anchor); + node.set_type(NodeType::Map); + node.set_tag(tag); + m_mapDepth++; +} + +void NodeBuilder::OnMapEnd() { + assert(m_mapDepth > 0); + m_mapDepth--; + Pop(); +} + +detail::node& NodeBuilder::Push(anchor_t anchor) { + detail::node& node = m_pMemory->create_node(); + RegisterAnchor(anchor, node); + Push(node); + return node; +} + +void NodeBuilder::Push(detail::node& node) { + const bool needsKey = + (!m_stack.empty() && m_stack.back()->type() == NodeType::Map && + m_keys.size() < m_mapDepth); + + m_stack.push_back(&node); + if (needsKey) + m_keys.push_back(PushedKey(&node, false)); +} + +void NodeBuilder::Pop() { + assert(!m_stack.empty()); + if (m_stack.size() == 1) { + m_pRoot = m_stack[0]; + m_stack.pop_back(); + return; + } + + detail::node& node = *m_stack.back(); + m_stack.pop_back(); + + detail::node& collection = *m_stack.back(); + + if (collection.type() == NodeType::Sequence) { + collection.push_back(node, m_pMemory); + } else if (collection.type() == NodeType::Map) { + assert(!m_keys.empty()); + PushedKey& key = m_keys.back(); + if (key.second) { + collection.insert(*key.first, node, m_pMemory); + m_keys.pop_back(); + } else { + key.second = true; + } + } else { + assert(false); + m_stack.clear(); + } +} + +void NodeBuilder::RegisterAnchor(anchor_t anchor, detail::node& node) { + if (anchor) { + assert(anchor == m_anchors.size()); + m_anchors.push_back(&node); + } +} } diff --git a/src/nodebuilder.h b/src/nodebuilder.h index cce91d3..3600561 100644 --- a/src/nodebuilder.h +++ b/src/nodebuilder.h @@ -1,7 +1,9 @@ #ifndef NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif @@ -9,50 +11,50 @@ #include "yaml-cpp/node/ptr.h" #include -namespace YAML -{ - class Node; +namespace YAML { +class Node; - class NodeBuilder: public EventHandler - { - public: - NodeBuilder(); - virtual ~NodeBuilder(); - - Node Root(); - - virtual void OnDocumentStart(const Mark& mark); - virtual void OnDocumentEnd(); - - virtual void OnNull(const Mark& mark, anchor_t anchor); - virtual void OnAlias(const Mark& mark, anchor_t anchor); - virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value); - - virtual void OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor); - virtual void OnSequenceEnd(); - - virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor); - virtual void OnMapEnd(); - - private: - detail::node& Push(anchor_t anchor); - void Push(detail::node& node); - void Pop(); - void RegisterAnchor(anchor_t anchor, detail::node& node); - - private: - detail::shared_memory_holder m_pMemory; - detail::node *m_pRoot; - - typedef std::vector Nodes; - Nodes m_stack; - Nodes m_anchors; +class NodeBuilder : public EventHandler { + public: + NodeBuilder(); + virtual ~NodeBuilder(); - typedef std::pair PushedKey; - std::vector m_keys; - std::size_t m_mapDepth; - }; + Node Root(); + + virtual void OnDocumentStart(const Mark& mark); + virtual void OnDocumentEnd(); + + virtual void OnNull(const Mark& mark, anchor_t anchor); + virtual void OnAlias(const Mark& mark, anchor_t anchor); + virtual void OnScalar(const Mark& mark, const std::string& tag, + anchor_t anchor, const std::string& value); + + virtual void OnSequenceStart(const Mark& mark, const std::string& tag, + anchor_t anchor); + virtual void OnSequenceEnd(); + + virtual void OnMapStart(const Mark& mark, const std::string& tag, + anchor_t anchor); + virtual void OnMapEnd(); + + private: + detail::node& Push(anchor_t anchor); + void Push(detail::node& node); + void Pop(); + void RegisterAnchor(anchor_t anchor, detail::node& node); + + private: + detail::shared_memory_holder m_pMemory; + detail::node* m_pRoot; + + typedef std::vector Nodes; + Nodes m_stack; + Nodes m_anchors; + + typedef std::pair PushedKey; + std::vector m_keys; + std::size_t m_mapDepth; +}; } -#endif // NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 - +#endif // NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/src/nodeevents.cpp b/src/nodeevents.cpp index 879c2ce..1f07482 100644 --- a/src/nodeevents.cpp +++ b/src/nodeevents.cpp @@ -4,98 +4,96 @@ #include "yaml-cpp/eventhandler.h" #include "yaml-cpp/mark.h" -namespace YAML -{ - void NodeEvents::AliasManager::RegisterReference(const detail::node& node) - { - m_anchorByIdentity.insert(std::make_pair(node.ref(), _CreateNewAnchor())); - } - - anchor_t NodeEvents::AliasManager::LookupAnchor(const detail::node& node) const - { - AnchorByIdentity::const_iterator it = m_anchorByIdentity.find(node.ref()); - if(it == m_anchorByIdentity.end()) - return 0; - return it->second; - } - - NodeEvents::NodeEvents(const Node& node): m_pMemory(node.m_pMemory), m_root(node.m_pNode) - { - if(m_root) - Setup(*m_root); - } - - void NodeEvents::Setup(const detail::node& node) - { - int& refCount = m_refCount[node.ref()]; - refCount++; - if(refCount > 1) - return; - - if(node.type() == NodeType::Sequence) { - for(detail::const_node_iterator it=node.begin();it!=node.end();++it) - Setup(**it); - } else if(node.type() == NodeType::Map) { - for(detail::const_node_iterator it=node.begin();it!=node.end();++it) { - Setup(*it->first); - Setup(*it->second); - } - } - } - - void NodeEvents::Emit(EventHandler& handler) - { - AliasManager am; - - handler.OnDocumentStart(Mark()); - if(m_root) - Emit(*m_root, handler, am); - handler.OnDocumentEnd(); - } - - void NodeEvents::Emit(const detail::node& node, EventHandler& handler, AliasManager& am) const - { - anchor_t anchor = NullAnchor; - if(IsAliased(node)) { - anchor = am.LookupAnchor(node); - if(anchor) { - handler.OnAlias(Mark(), anchor); - return; - } - - am.RegisterReference(node); - anchor = am.LookupAnchor(node); - } - - switch(node.type()) { - case NodeType::Undefined: - break; - case NodeType::Null: - handler.OnNull(Mark(), anchor); - break; - case NodeType::Scalar: - handler.OnScalar(Mark(), node.tag(), anchor, node.scalar()); - break; - case NodeType::Sequence: - handler.OnSequenceStart(Mark(), node.tag(), anchor); - for(detail::const_node_iterator it=node.begin();it!=node.end();++it) - Emit(**it, handler, am); - handler.OnSequenceEnd(); - break; - case NodeType::Map: - handler.OnMapStart(Mark(), node.tag(), anchor); - for(detail::const_node_iterator it=node.begin();it!=node.end();++it) { - Emit(*it->first, handler, am); - Emit(*it->second, handler, am); - } - handler.OnMapEnd(); - break; - } - } - - bool NodeEvents::IsAliased(const detail::node& node) const - { - RefCount::const_iterator it = m_refCount.find(node.ref()); - return it != m_refCount.end() && it->second > 1; - } +namespace YAML { +void NodeEvents::AliasManager::RegisterReference(const detail::node& node) { + m_anchorByIdentity.insert(std::make_pair(node.ref(), _CreateNewAnchor())); +} + +anchor_t NodeEvents::AliasManager::LookupAnchor(const detail::node& node) + const { + AnchorByIdentity::const_iterator it = m_anchorByIdentity.find(node.ref()); + if (it == m_anchorByIdentity.end()) + return 0; + return it->second; +} + +NodeEvents::NodeEvents(const Node& node) + : m_pMemory(node.m_pMemory), m_root(node.m_pNode) { + if (m_root) + Setup(*m_root); +} + +void NodeEvents::Setup(const detail::node& node) { + int& refCount = m_refCount[node.ref()]; + refCount++; + if (refCount > 1) + return; + + if (node.type() == NodeType::Sequence) { + for (detail::const_node_iterator it = node.begin(); it != node.end(); ++it) + Setup(**it); + } else if (node.type() == NodeType::Map) { + for (detail::const_node_iterator it = node.begin(); it != node.end(); + ++it) { + Setup(*it->first); + Setup(*it->second); + } + } +} + +void NodeEvents::Emit(EventHandler& handler) { + AliasManager am; + + handler.OnDocumentStart(Mark()); + if (m_root) + Emit(*m_root, handler, am); + handler.OnDocumentEnd(); +} + +void NodeEvents::Emit(const detail::node& node, EventHandler& handler, + AliasManager& am) const { + anchor_t anchor = NullAnchor; + if (IsAliased(node)) { + anchor = am.LookupAnchor(node); + if (anchor) { + handler.OnAlias(Mark(), anchor); + return; + } + + am.RegisterReference(node); + anchor = am.LookupAnchor(node); + } + + switch (node.type()) { + case NodeType::Undefined: + break; + case NodeType::Null: + handler.OnNull(Mark(), anchor); + break; + case NodeType::Scalar: + handler.OnScalar(Mark(), node.tag(), anchor, node.scalar()); + break; + case NodeType::Sequence: + handler.OnSequenceStart(Mark(), node.tag(), anchor); + for (detail::const_node_iterator it = node.begin(); it != node.end(); + ++it) + Emit(**it, handler, am); + handler.OnSequenceEnd(); + break; + case NodeType::Map: + handler.OnMapStart(Mark(), node.tag(), anchor); + for (detail::const_node_iterator it = node.begin(); it != node.end(); + ++it) { + Emit(*it->first, handler, am); + Emit(*it->second, handler, am); + } + handler.OnMapEnd(); + break; + } +} + +bool NodeEvents::IsAliased(const detail::node& node) const { + RefCount::const_iterator it = m_refCount.find(node.ref()); + return it != m_refCount.end() && it->second > 1; +} } diff --git a/src/nodeevents.h b/src/nodeevents.h index ba31226..98b26ba 100644 --- a/src/nodeevents.h +++ b/src/nodeevents.h @@ -1,7 +1,9 @@ #ifndef NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif @@ -10,48 +12,46 @@ #include #include -namespace YAML -{ - class EventHandler; - class Node; - - class NodeEvents - { - public: - explicit NodeEvents(const Node& node); - - void Emit(EventHandler& handler); - - private: - class AliasManager { - public: - AliasManager(): m_curAnchor(0) {} - - void RegisterReference(const detail::node& node); - anchor_t LookupAnchor(const detail::node& node) const; - - private: - anchor_t _CreateNewAnchor() { return ++m_curAnchor; } - - private: - typedef std::map AnchorByIdentity; - AnchorByIdentity m_anchorByIdentity; - - anchor_t m_curAnchor; - }; - - void Setup(const detail::node& node); - void Emit(const detail::node& node, EventHandler& handler, AliasManager& am) const; - bool IsAliased(const detail::node& node) const; - - private: - detail::shared_memory_holder m_pMemory; - detail::node* m_root; - - typedef std::map RefCount; - RefCount m_refCount; - }; +namespace YAML { +class EventHandler; +class Node; + +class NodeEvents { + public: + explicit NodeEvents(const Node& node); + + void Emit(EventHandler& handler); + + private: + class AliasManager { + public: + AliasManager() : m_curAnchor(0) {} + + void RegisterReference(const detail::node& node); + anchor_t LookupAnchor(const detail::node& node) const; + + private: + anchor_t _CreateNewAnchor() { return ++m_curAnchor; } + + private: + typedef std::map AnchorByIdentity; + AnchorByIdentity m_anchorByIdentity; + + anchor_t m_curAnchor; + }; + + void Setup(const detail::node& node); + void Emit(const detail::node& node, EventHandler& handler, + AliasManager& am) const; + bool IsAliased(const detail::node& node) const; + + private: + detail::shared_memory_holder m_pMemory; + detail::node* m_root; + + typedef std::map RefCount; + RefCount m_refCount; +}; } -#endif // NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 - +#endif // NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/src/ostream_wrapper.cpp b/src/ostream_wrapper.cpp index 66cafda..558bd7b 100644 --- a/src/ostream_wrapper.cpp +++ b/src/ostream_wrapper.cpp @@ -2,55 +2,52 @@ #include #include -namespace YAML -{ - ostream_wrapper::ostream_wrapper(): m_buffer(1), m_pStream(0), m_pos(0), m_row(0), m_col(0), m_comment(false) - { - } - - ostream_wrapper::ostream_wrapper(std::ostream& stream): m_pStream(&stream), m_pos(0), m_row(0), m_col(0), m_comment(false) - { - } +namespace YAML { +ostream_wrapper::ostream_wrapper() + : m_buffer(1), + m_pStream(0), + m_pos(0), + m_row(0), + m_col(0), + m_comment(false) {} - ostream_wrapper::~ostream_wrapper() - { - } - - void ostream_wrapper::write(const std::string& str) - { - if(m_pStream) { - m_pStream->write(str.c_str(), str.size()); - } else { - m_buffer.resize(std::max(m_buffer.size(), m_pos + str.size() + 1)); - std::copy(str.begin(), str.end(), &m_buffer[m_pos]); - } - - for(std::size_t i=0;iwrite(str, size); - } else { - m_buffer.resize(std::max(m_buffer.size(), m_pos + size + 1)); - std::copy(str, str + size, &m_buffer[m_pos]); - } - - for(std::size_t i=0;iwrite(str.c_str(), str.size()); + } else { + m_buffer.resize(std::max(m_buffer.size(), m_pos + str.size() + 1)); + std::copy(str.begin(), str.end(), &m_buffer[m_pos]); + } + + for (std::size_t i = 0; i < str.size(); i++) + update_pos(str[i]); +} + +void ostream_wrapper::write(const char* str, std::size_t size) { + if (m_pStream) { + m_pStream->write(str, size); + } else { + m_buffer.resize(std::max(m_buffer.size(), m_pos + size + 1)); + std::copy(str, str + size, &m_buffer[m_pos]); + } + + for (std::size_t i = 0; i < size; i++) + update_pos(str[i]); +} + +void ostream_wrapper::update_pos(char ch) { + m_pos++; + m_col++; + + if (ch == '\n') { + m_row++; + m_col = 0; + m_comment = false; + } +} } diff --git a/src/parse.cpp b/src/parse.cpp index 1537d55..06292ae 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -7,62 +7,61 @@ #include #include -namespace YAML -{ - Node Load(const std::string& input) { - std::stringstream stream(input); - return Load(stream); - } - - Node Load(const char *input) { - std::stringstream stream(input); - return Load(stream); - } - - Node Load(std::istream& input) { - Parser parser(input); - NodeBuilder builder; - if(!parser.HandleNextDocument(builder)) - return Node(); - - return builder.Root(); - } - - Node LoadFile(const std::string& filename) { - std::ifstream fin(filename.c_str()); - if(!fin) - throw BadFile(); - return Load(fin); - } - - std::vector LoadAll(const std::string& input) { - std::stringstream stream(input); - return LoadAll(stream); - } - - std::vector LoadAll(const char *input) { - std::stringstream stream(input); - return LoadAll(stream); - } - - std::vector LoadAll(std::istream& input) { - std::vector docs; - - Parser parser(input); - while(1) { - NodeBuilder builder; - if(!parser.HandleNextDocument(builder)) - break; - docs.push_back(builder.Root()); - } - - return docs; - } - - std::vector LoadAllFromFile(const std::string& filename) { - std::ifstream fin(filename.c_str()); - if(!fin) - throw BadFile(); - return LoadAll(fin); - } +namespace YAML { +Node Load(const std::string& input) { + std::stringstream stream(input); + return Load(stream); +} + +Node Load(const char* input) { + std::stringstream stream(input); + return Load(stream); +} + +Node Load(std::istream& input) { + Parser parser(input); + NodeBuilder builder; + if (!parser.HandleNextDocument(builder)) + return Node(); + + return builder.Root(); +} + +Node LoadFile(const std::string& filename) { + std::ifstream fin(filename.c_str()); + if (!fin) + throw BadFile(); + return Load(fin); +} + +std::vector LoadAll(const std::string& input) { + std::stringstream stream(input); + return LoadAll(stream); +} + +std::vector LoadAll(const char* input) { + std::stringstream stream(input); + return LoadAll(stream); +} + +std::vector LoadAll(std::istream& input) { + std::vector docs; + + Parser parser(input); + while (1) { + NodeBuilder builder; + if (!parser.HandleNextDocument(builder)) + break; + docs.push_back(builder.Root()); + } + + return docs; +} + +std::vector LoadAllFromFile(const std::string& filename) { + std::ifstream fin(filename.c_str()); + if (!fin) + throw BadFile(); + return LoadAll(fin); +} } diff --git a/src/stream.cpp b/src/stream.cpp index a79fc17..f285e0a 100644 --- a/src/stream.cpp +++ b/src/stream.cpp @@ -50,21 +50,21 @@ static bool s_introFinalState[] = {false, // uis_start false, // uis_utfbe_b1 false, // uis_utf32be_b2 false, // uis_utf32be_bom3 - true, // uis_utf32be - true, // uis_utf16be + true, // uis_utf32be + true, // uis_utf16be false, // uis_utf16be_bom1 false, // uis_utfle_bom1 false, // uis_utf16le_bom2 false, // uis_utf32le_bom3 - true, // uis_utf16le - true, // uis_utf32le + true, // uis_utf16le + true, // uis_utf32le false, // uis_utf8_imp false, // uis_utf16le_imp false, // uis_utf32le_imp3 false, // uis_utf8_bom1 false, // uis_utf8_bom2 - true, // uis_utf8 - true, // uis_error + true, // uis_utf8 + true, // uis_error }; static UtfIntroState s_introTransitions[][uictMax] = { diff --git a/test/emittertests.cpp b/test/emittertests.cpp index cee64f5..7dbb118 100644 --- a/test/emittertests.cpp +++ b/test/emittertests.cpp @@ -3,1162 +3,1197 @@ #include "yaml-cpp/yaml.h" #include -namespace Test -{ - namespace Emitter { - //////////////////////////////////////////////////////////////////////////////////////////////////////// - // correct emitting +namespace Test { +namespace Emitter { +//////////////////////////////////////////////////////////////////////////////////////////////////////// +// correct emitting - void SimpleScalar(YAML::Emitter& out, std::string& desiredOutput) { - out << "Hello, World!"; - desiredOutput = "Hello, World!"; - } - - void SimpleSeq(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - out << "eggs"; - out << "bread"; - out << "milk"; - out << YAML::EndSeq; - - desiredOutput = "- eggs\n- bread\n- milk"; - } - - void SimpleFlowSeq(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Flow; - out << YAML::BeginSeq; - out << "Larry"; - out << "Curly"; - out << "Moe"; - out << YAML::EndSeq; - - desiredOutput = "[Larry, Curly, Moe]"; - } - - void EmptyFlowSeq(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Flow; - out << YAML::BeginSeq; - out << YAML::EndSeq; - - desiredOutput = "[]"; - } - - void NestedBlockSeq(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - out << "item 1"; - out << YAML::BeginSeq << "subitem 1" << "subitem 2" << YAML::EndSeq; - out << YAML::EndSeq; - - desiredOutput = "- item 1\n-\n - subitem 1\n - subitem 2"; - } - - void NestedFlowSeq(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - out << "one"; - out << YAML::Flow << YAML::BeginSeq << "two" << "three" << YAML::EndSeq; - out << YAML::EndSeq; - - desiredOutput = "- one\n- [two, three]"; - } - - void SimpleMap(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginMap; - out << YAML::Key << "name"; - out << YAML::Value << "Ryan Braun"; - out << YAML::Key << "position"; - out << YAML::Value << "3B"; - out << YAML::EndMap; - - desiredOutput = "name: Ryan Braun\nposition: 3B"; - } - - void SimpleFlowMap(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Flow; - out << YAML::BeginMap; - out << YAML::Key << "shape"; - out << YAML::Value << "square"; - out << YAML::Key << "color"; - out << YAML::Value << "blue"; - out << YAML::EndMap; - - desiredOutput = "{shape: square, color: blue}"; - } - - void MapAndList(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginMap; - out << YAML::Key << "name"; - out << YAML::Value << "Barack Obama"; - out << YAML::Key << "children"; - out << YAML::Value << YAML::BeginSeq << "Sasha" << "Malia" << YAML::EndSeq; - out << YAML::EndMap; - - desiredOutput = "name: Barack Obama\nchildren:\n - Sasha\n - Malia"; - } - - void ListAndMap(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - out << "item 1"; - out << YAML::BeginMap; - out << YAML::Key << "pens" << YAML::Value << 8; - out << YAML::Key << "pencils" << YAML::Value << 14; - out << YAML::EndMap; - out << "item 2"; - out << YAML::EndSeq; - - desiredOutput = "- item 1\n- pens: 8\n pencils: 14\n- item 2"; - } - - void NestedBlockMap(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginMap; - out << YAML::Key << "name"; - out << YAML::Value << "Fred"; - out << YAML::Key << "grades"; - out << YAML::Value; - out << YAML::BeginMap; - out << YAML::Key << "algebra" << YAML::Value << "A"; - out << YAML::Key << "physics" << YAML::Value << "C+"; - out << YAML::Key << "literature" << YAML::Value << "B"; - out << YAML::EndMap; - out << YAML::EndMap; - - desiredOutput = "name: Fred\ngrades:\n algebra: A\n physics: C+\n literature: B"; - } - - void NestedFlowMap(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Flow; - out << YAML::BeginMap; - out << YAML::Key << "name"; - out << YAML::Value << "Fred"; - out << YAML::Key << "grades"; - out << YAML::Value; - out << YAML::BeginMap; - out << YAML::Key << "algebra" << YAML::Value << "A"; - out << YAML::Key << "physics" << YAML::Value << "C+"; - out << YAML::Key << "literature" << YAML::Value << "B"; - out << YAML::EndMap; - out << YAML::EndMap; - - desiredOutput = "{name: Fred, grades: {algebra: A, physics: C+, literature: B}}"; - } - - void MapListMix(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginMap; - out << YAML::Key << "name"; - out << YAML::Value << "Bob"; - out << YAML::Key << "position"; - out << YAML::Value; - out << YAML::Flow << YAML::BeginSeq << 2 << 4 << YAML::EndSeq; - out << YAML::Key << "invincible" << YAML::Value << YAML::OnOffBool << false; - out << YAML::EndMap; - - desiredOutput = "name: Bob\nposition: [2, 4]\ninvincible: off"; - } - - void SimpleLongKey(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::LongKey; - out << YAML::BeginMap; - out << YAML::Key << "height"; - out << YAML::Value << "5'9\""; - out << YAML::Key << "weight"; - out << YAML::Value << 145; - out << YAML::EndMap; - - desiredOutput = "? height\n: 5'9\"\n? weight\n: 145"; - } - - void SingleLongKey(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginMap; - out << YAML::Key << "age"; - out << YAML::Value << "24"; - out << YAML::LongKey << YAML::Key << "height"; - out << YAML::Value << "5'9\""; - out << YAML::Key << "weight"; - out << YAML::Value << 145; - out << YAML::EndMap; - - desiredOutput = "age: 24\n? height\n: 5'9\"\nweight: 145"; - } - - void ComplexLongKey(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::LongKey; - out << YAML::BeginMap; - out << YAML::Key << YAML::BeginSeq << 1 << 3 << YAML::EndSeq; - out << YAML::Value << "monster"; - out << YAML::Key << YAML::Flow << YAML::BeginSeq << 2 << 0 << YAML::EndSeq; - out << YAML::Value << "demon"; - out << YAML::EndMap; - - desiredOutput = "? - 1\n - 3\n: monster\n? [2, 0]\n: demon"; - } - - void AutoLongKey(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginMap; - out << YAML::Key << YAML::BeginSeq << 1 << 3 << YAML::EndSeq; - out << YAML::Value << "monster"; - out << YAML::Key << YAML::Flow << YAML::BeginSeq << 2 << 0 << YAML::EndSeq; - out << YAML::Value << "demon"; - out << YAML::Key << "the origin"; - out << YAML::Value << "angel"; - out << YAML::EndMap; - - desiredOutput = "? - 1\n - 3\n: monster\n[2, 0]: demon\nthe origin: angel"; - } - - void ScalarFormat(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginSeq; - out << "simple scalar"; - out << YAML::SingleQuoted << "explicit single-quoted scalar"; - out << YAML::DoubleQuoted << "explicit double-quoted scalar"; - out << "auto-detected\ndouble-quoted scalar"; - out << "a non-\"auto-detected\" double-quoted scalar"; - out << YAML::Literal << "literal scalar\nthat may span\nmany, many\nlines and have \"whatever\" crazy\tsymbols that we like"; - out << YAML::EndSeq; - - desiredOutput = "- simple scalar\n- 'explicit single-quoted scalar'\n- \"explicit double-quoted scalar\"\n- \"auto-detected\\ndouble-quoted scalar\"\n- a non-\"auto-detected\" double-quoted scalar\n- |\n literal scalar\n that may span\n many, many\n lines and have \"whatever\" crazy\tsymbols that we like"; - } - - void AutoLongKeyScalar(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginMap; - out << YAML::Key << YAML::Literal << "multi-line\nscalar"; - out << YAML::Value << "and its value"; - out << YAML::EndMap; - - desiredOutput = "? |\n multi-line\n scalar\n: and its value"; - } - - void LongKeyFlowMap(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::Flow; - out << YAML::BeginMap; - out << YAML::Key << "simple key"; - out << YAML::Value << "and value"; - out << YAML::LongKey << YAML::Key << "long key"; - out << YAML::Value << "and its value"; - out << YAML::EndMap; - - desiredOutput = "{simple key: and value, ? long key: and its value}"; - } - - void BlockMapAsKey(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginMap; - out << YAML::Key; - out << YAML::BeginMap; - out << YAML::Key << "key" << YAML::Value << "value"; - out << YAML::Key << "next key" << YAML::Value << "next value"; - out << YAML::EndMap; - out << YAML::Value; - out << "total value"; - out << YAML::EndMap; - - desiredOutput = "? key: value\n next key: next value\n: total value"; - } - - void AliasAndAnchor(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginSeq; - out << YAML::Anchor("fred"); - out << YAML::BeginMap; - out << YAML::Key << "name" << YAML::Value << "Fred"; - out << YAML::Key << "age" << YAML::Value << 42; - out << YAML::EndMap; - out << YAML::Alias("fred"); - out << YAML::EndSeq; - - desiredOutput = "- &fred\n name: Fred\n age: 42\n- *fred"; - } - - void AliasAndAnchorWithNull(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginSeq; - out << YAML::Anchor("fred") << YAML::Null; - out << YAML::Alias("fred"); - out << YAML::EndSeq; - - desiredOutput = "- &fred ~\n- *fred"; - } - - void AliasAndAnchorInFlow(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::Flow << YAML::BeginSeq; - out << YAML::Anchor("fred"); - out << YAML::BeginMap; - out << YAML::Key << "name" << YAML::Value << "Fred"; - out << YAML::Key << "age" << YAML::Value << 42; - out << YAML::EndMap; - out << YAML::Alias("fred"); - out << YAML::EndSeq; - - desiredOutput = "[&fred {name: Fred, age: 42}, *fred]"; - } - - void SimpleVerbatimTag(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::VerbatimTag("!foo") << "bar"; - - desiredOutput = "! bar"; - } - - void VerbatimTagInBlockSeq(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginSeq; - out << YAML::VerbatimTag("!foo") << "bar"; - out << "baz"; - out << YAML::EndSeq; - - desiredOutput = "- ! bar\n- baz"; - } - - void VerbatimTagInFlowSeq(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::Flow << YAML::BeginSeq; - out << YAML::VerbatimTag("!foo") << "bar"; - out << "baz"; - out << YAML::EndSeq; - - desiredOutput = "[! bar, baz]"; - } - - void VerbatimTagInFlowSeqWithNull(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::Flow << YAML::BeginSeq; - out << YAML::VerbatimTag("!foo") << YAML::Null; - out << "baz"; - out << YAML::EndSeq; - - desiredOutput = "[! ~, baz]"; - } - - void VerbatimTagInBlockMap(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginMap; - out << YAML::Key << YAML::VerbatimTag("!foo") << "bar"; - out << YAML::Value << YAML::VerbatimTag("!waz") << "baz"; - out << YAML::EndMap; - - desiredOutput = "! bar: ! baz"; - } - - void VerbatimTagInFlowMap(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::Flow << YAML::BeginMap; - out << YAML::Key << YAML::VerbatimTag("!foo") << "bar"; - out << YAML::Value << "baz"; - out << YAML::EndMap; - - desiredOutput = "{! bar: baz}"; - } - - void VerbatimTagInFlowMapWithNull(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::Flow << YAML::BeginMap; - out << YAML::Key << YAML::VerbatimTag("!foo") << YAML::Null; - out << YAML::Value << "baz"; - out << YAML::EndMap; - - desiredOutput = "{! ~: baz}"; - } - - void VerbatimTagWithEmptySeq(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::VerbatimTag("!foo") << YAML::BeginSeq << YAML::EndSeq; - - desiredOutput = "!\n[]"; - } - - void VerbatimTagWithEmptyMap(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::VerbatimTag("!bar") << YAML::BeginMap << YAML::EndMap; - - desiredOutput = "!\n{}"; - } - - void VerbatimTagWithEmptySeqAndMap(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginSeq; - out << YAML::VerbatimTag("!foo") << YAML::BeginSeq << YAML::EndSeq; - out << YAML::VerbatimTag("!bar") << YAML::BeginMap << YAML::EndMap; - out << YAML::EndSeq; - - desiredOutput = "- !\n []\n- !\n {}"; - } - - void ByKindTagWithScalar(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginSeq; - out << YAML::DoubleQuoted << "12"; - out << "12"; - out << YAML::TagByKind << "12"; - out << YAML::EndSeq; - - desiredOutput = "- \"12\"\n- 12\n- ! 12"; - } - - void LocalTagWithScalar(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::LocalTag("foo") << "bar"; - - desiredOutput = "!foo bar"; - } - - void BadLocalTag(YAML::Emitter& out, std::string& desiredError) - { - out << YAML::LocalTag("e!far") << "bar"; - - desiredError = "invalid tag"; - } - - void ComplexDoc(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginMap; - out << YAML::Key << "receipt"; - out << YAML::Value << "Oz-Ware Purchase Invoice"; - out << YAML::Key << "date"; - out << YAML::Value << "2007-08-06"; - out << YAML::Key << "customer"; - out << YAML::Value; - out << YAML::BeginMap; - out << YAML::Key << "given"; - out << YAML::Value << "Dorothy"; - out << YAML::Key << "family"; - out << YAML::Value << "Gale"; - out << YAML::EndMap; - out << YAML::Key << "items"; - out << YAML::Value; - out << YAML::BeginSeq; - out << YAML::BeginMap; - out << YAML::Key << "part_no"; - out << YAML::Value << "A4786"; - out << YAML::Key << "descrip"; - out << YAML::Value << "Water Bucket (Filled)"; - out << YAML::Key << "price"; - out << YAML::Value << 1.47; - out << YAML::Key << "quantity"; - out << YAML::Value << 4; - out << YAML::EndMap; - out << YAML::BeginMap; - out << YAML::Key << "part_no"; - out << YAML::Value << "E1628"; - out << YAML::Key << "descrip"; - out << YAML::Value << "High Heeled \"Ruby\" Slippers"; - out << YAML::Key << "price"; - out << YAML::Value << 100.27; - out << YAML::Key << "quantity"; - out << YAML::Value << 1; - out << YAML::EndMap; - out << YAML::EndSeq; - out << YAML::Key << "bill-to"; - out << YAML::Value << YAML::Anchor("id001"); - out << YAML::BeginMap; - out << YAML::Key << "street"; - out << YAML::Value << YAML::Literal << "123 Tornado Alley\nSuite 16"; - out << YAML::Key << "city"; - out << YAML::Value << "East Westville"; - out << YAML::Key << "state"; - out << YAML::Value << "KS"; - out << YAML::EndMap; - out << YAML::Key << "ship-to"; - out << YAML::Value << YAML::Alias("id001"); - out << YAML::EndMap; - - desiredOutput = "receipt: Oz-Ware Purchase Invoice\ndate: 2007-08-06\ncustomer:\n given: Dorothy\n family: Gale\nitems:\n - part_no: A4786\n descrip: Water Bucket (Filled)\n price: 1.47\n quantity: 4\n - part_no: E1628\n descrip: High Heeled \"Ruby\" Slippers\n price: 100.27\n quantity: 1\nbill-to: &id001\n street: |\n 123 Tornado Alley\n Suite 16\n city: East Westville\n state: KS\nship-to: *id001"; - } - - void STLContainers(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginSeq; - std::vector primes; - primes.push_back(2); - primes.push_back(3); - primes.push_back(5); - primes.push_back(7); - primes.push_back(11); - primes.push_back(13); - out << YAML::Flow << primes; - std::map ages; - ages["Daniel"] = 26; - ages["Jesse"] = 24; - out << ages; - out << YAML::EndSeq; - - desiredOutput = "- [2, 3, 5, 7, 11, 13]\n- Daniel: 26\n Jesse: 24"; - } - - void SimpleComment(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginMap; - out << YAML::Key << "method"; - out << YAML::Value << "least squares" << YAML::Comment("should we change this method?"); - out << YAML::EndMap; - - desiredOutput = "method: least squares # should we change this method?"; - } - - void MultiLineComment(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginSeq; - out << "item 1" << YAML::Comment("really really long\ncomment that couldn't possibly\nfit on one line"); - out << "item 2"; - out << YAML::EndSeq; - - desiredOutput = "- item 1 # really really long\n # comment that couldn't possibly\n # fit on one line\n- item 2"; - } - - void ComplexComments(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginMap; - out << YAML::LongKey << YAML::Key << "long key" << YAML::Comment("long key"); - out << YAML::Value << "value"; - out << YAML::EndMap; - - desiredOutput = "? long key # long key\n: value"; - } - - void InitialComment(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::Comment("A comment describing the purpose of the file."); - out << YAML::BeginMap << YAML::Key << "key" << YAML::Value << "value" << YAML::EndMap; - - desiredOutput = "# A comment describing the purpose of the file.\nkey: value"; - } - - void InitialCommentWithDocIndicator(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginDoc << YAML::Comment("A comment describing the purpose of the file."); - out << YAML::BeginMap << YAML::Key << "key" << YAML::Value << "value" << YAML::EndMap; - - desiredOutput = "---\n# A comment describing the purpose of the file.\nkey: value"; - } - - void CommentInFlowSeq(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::Flow << YAML::BeginSeq << "foo" << YAML::Comment("foo!") << "bar" << YAML::EndSeq; - - desiredOutput = "[foo, # foo!\nbar]"; - } - - void CommentInFlowMap(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::Flow << YAML::BeginMap; - out << YAML::Key << "foo" << YAML::Value << "foo value"; - out << YAML::Key << "bar" << YAML::Value << "bar value" << YAML::Comment("bar!"); - out << YAML::Key << "baz" << YAML::Value << "baz value" << YAML::Comment("baz!"); - out << YAML::EndMap; - - desiredOutput = "{foo: foo value, bar: bar value, # bar!\nbaz: baz value, # baz!\n}"; - } - - void Indentation(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::Indent(4); - out << YAML::BeginSeq; - out << YAML::BeginMap; - out << YAML::Key << "key 1" << YAML::Value << "value 1"; - out << YAML::Key << "key 2" << YAML::Value << YAML::BeginSeq << "a" << "b" << "c" << YAML::EndSeq; - out << YAML::EndMap; - out << YAML::EndSeq; - - desiredOutput = "- key 1: value 1\n key 2:\n - a\n - b\n - c"; - } - - void SimpleGlobalSettings(YAML::Emitter& out, std::string& desiredOutput) - { - out.SetIndent(4); - out.SetMapFormat(YAML::LongKey); - - out << YAML::BeginSeq; - out << YAML::BeginMap; - out << YAML::Key << "key 1" << YAML::Value << "value 1"; - out << YAML::Key << "key 2" << YAML::Value << YAML::Flow << YAML::BeginSeq << "a" << "b" << "c" << YAML::EndSeq; - out << YAML::EndMap; - out << YAML::EndSeq; - - desiredOutput = "- ? key 1\n : value 1\n ? key 2\n : [a, b, c]"; - } - - void ComplexGlobalSettings(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginSeq; - out << YAML::Block; - out << YAML::BeginMap; - out << YAML::Key << "key 1" << YAML::Value << "value 1"; - out << YAML::Key << "key 2" << YAML::Value; - out.SetSeqFormat(YAML::Flow); - out << YAML::BeginSeq << "a" << "b" << "c" << YAML::EndSeq; - out << YAML::EndMap; - out << YAML::BeginMap; - out << YAML::Key << YAML::BeginSeq << 1 << 2 << YAML::EndSeq; - out << YAML::Value << YAML::BeginMap << YAML::Key << "a" << YAML::Value << "b" << YAML::EndMap; - out << YAML::EndMap; - out << YAML::EndSeq; - - desiredOutput = "- key 1: value 1\n key 2: [a, b, c]\n- [1, 2]:\n a: b"; - } - - void Null(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginSeq; - out << YAML::Null; - out << YAML::BeginMap; - out << YAML::Key << "null value" << YAML::Value << YAML::Null; - out << YAML::Key << YAML::Null << YAML::Value << "null key"; - out << YAML::EndMap; - out << YAML::EndSeq; - - desiredOutput = "- ~\n- null value: ~\n ~: null key"; - } - - void EscapedUnicode(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::EscapeNonAscii << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2"; - - desiredOutput = "\"$ \\xa2 \\u20ac \\U00024b62\""; - } - - void Unicode(YAML::Emitter& out, std::string& desiredOutput) - { - out << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2"; - desiredOutput = "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2"; - } - - void DoubleQuotedUnicode(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::DoubleQuoted << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2"; - desiredOutput = "\"\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2\""; - } - - struct Foo { - Foo(): x(0) {} - Foo(int x_, const std::string& bar_): x(x_), bar(bar_) {} - - int x; - std::string bar; - }; - - YAML::Emitter& operator << (YAML::Emitter& out, const Foo& foo) { - out << YAML::BeginMap; - out << YAML::Key << "x" << YAML::Value << foo.x; - out << YAML::Key << "bar" << YAML::Value << foo.bar; - out << YAML::EndMap; - return out; - } - - void UserType(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginSeq; - out << Foo(5, "hello"); - out << Foo(3, "goodbye"); - out << YAML::EndSeq; - - desiredOutput = "- x: 5\n bar: hello\n- x: 3\n bar: goodbye"; - } - - void UserTypeInContainer(YAML::Emitter& out, std::string& desiredOutput) - { - std::vector fv; - fv.push_back(Foo(5, "hello")); - fv.push_back(Foo(3, "goodbye")); - out << fv; - - desiredOutput = "- x: 5\n bar: hello\n- x: 3\n bar: goodbye"; - } - - template - YAML::Emitter& operator << (YAML::Emitter& out, const T *v) { - if(v) - out << *v; - else - out << YAML::Null; - return out; - } - - void PointerToInt(YAML::Emitter& out, std::string& desiredOutput) - { - int foo = 5; - int *bar = &foo; - int *baz = 0; - out << YAML::BeginSeq; - out << bar << baz; - out << YAML::EndSeq; - - desiredOutput = "- 5\n- ~"; - } - - void PointerToUserType(YAML::Emitter& out, std::string& desiredOutput) - { - Foo foo(5, "hello"); - Foo *bar = &foo; - Foo *baz = 0; - out << YAML::BeginSeq; - out << bar << baz; - out << YAML::EndSeq; - - desiredOutput = "- x: 5\n bar: hello\n- ~"; - } - - void NewlineAtEnd(YAML::Emitter& out, std::string& desiredOutput) - { - out << "Hello" << YAML::Newline << YAML::Newline; - desiredOutput = "Hello\n\n"; - } - - void NewlineInBlockSequence(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginSeq; - out << "a" << YAML::Newline << "b" << "c" << YAML::Newline << "d"; - out << YAML::EndSeq; - desiredOutput = "- a\n\n- b\n- c\n\n- d"; - } - - void NewlineInFlowSequence(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::Flow << YAML::BeginSeq; - out << "a" << YAML::Newline << "b" << "c" << YAML::Newline << "d"; - out << YAML::EndSeq; - desiredOutput = "[a,\nb, c,\nd]"; - } - - void NewlineInBlockMap(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginMap; - out << YAML::Key << "a" << YAML::Value << "foo" << YAML::Newline; - out << YAML::Key << "b" << YAML::Newline << YAML::Value << "bar"; - out << YAML::LongKey << YAML::Key << "c" << YAML::Newline << YAML::Value << "car"; - out << YAML::EndMap; - desiredOutput = "a: foo\nb:\n bar\n? c\n\n: car"; - } - - void NewlineInFlowMap(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::Flow << YAML::BeginMap; - out << YAML::Key << "a" << YAML::Value << "foo" << YAML::Newline; - out << YAML::Key << "b" << YAML::Value << "bar"; - out << YAML::EndMap; - desiredOutput = "{a: foo,\nb: bar}"; - } - - void LotsOfNewlines(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginSeq; - out << "a" << YAML::Newline; - out << YAML::BeginSeq; - out << "b" << "c" << YAML::Newline; - out << YAML::EndSeq; - out << YAML::Newline; - out << YAML::BeginMap; - out << YAML::Newline << YAML::Key << "d" << YAML::Value << YAML::Newline << "e"; - out << YAML::LongKey << YAML::Key << "f" << YAML::Newline << YAML::Value << "foo"; - out << YAML::EndMap; - out << YAML::EndSeq; - desiredOutput = "- a\n\n-\n - b\n - c\n\n\n-\n d:\n e\n ? f\n\n : foo"; - } - - void Binary(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::Binary(reinterpret_cast("Hello, World!"), 13); - desiredOutput = "!!binary \"SGVsbG8sIFdvcmxkIQ==\""; - } - - void LongBinary(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::Binary(reinterpret_cast("Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.\n"), 270); - desiredOutput = "!!binary \"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4K\""; - } - - void EmptyBinary(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::Binary(reinterpret_cast(""), 0); - desiredOutput = "!!binary \"\""; - } - - void ColonAtEndOfScalar(YAML::Emitter& out, std::string& desiredOutput) - { - out << "a:"; - desiredOutput = "\"a:\""; - } - - void ColonAsScalar(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginMap; - out << YAML::Key << "apple" << YAML::Value << ":"; - out << YAML::Key << "banana" << YAML::Value << ":"; - out << YAML::EndMap; - desiredOutput = "apple: \":\"\nbanana: \":\""; - } - - void ColonAtEndOfScalarInFlow(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::Flow << YAML::BeginMap << YAML::Key << "C:" << YAML::Value << "C:" << YAML::EndMap; - desiredOutput = "{\"C:\": \"C:\"}"; - } - - void BoolFormatting(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginSeq; - out << YAML::TrueFalseBool << YAML::UpperCase << true; - out << YAML::TrueFalseBool << YAML::CamelCase << true; - out << YAML::TrueFalseBool << YAML::LowerCase << true; - out << YAML::TrueFalseBool << YAML::UpperCase << false; - out << YAML::TrueFalseBool << YAML::CamelCase << false; - out << YAML::TrueFalseBool << YAML::LowerCase << false; - out << YAML::YesNoBool << YAML::UpperCase << true; - out << YAML::YesNoBool << YAML::CamelCase << true; - out << YAML::YesNoBool << YAML::LowerCase << true; - out << YAML::YesNoBool << YAML::UpperCase << false; - out << YAML::YesNoBool << YAML::CamelCase << false; - out << YAML::YesNoBool << YAML::LowerCase << false; - out << YAML::OnOffBool << YAML::UpperCase << true; - out << YAML::OnOffBool << YAML::CamelCase << true; - out << YAML::OnOffBool << YAML::LowerCase << true; - out << YAML::OnOffBool << YAML::UpperCase << false; - out << YAML::OnOffBool << YAML::CamelCase << false; - out << YAML::OnOffBool << YAML::LowerCase << false; - out << YAML::ShortBool << YAML::UpperCase << true; - out << YAML::ShortBool << YAML::CamelCase << true; - out << YAML::ShortBool << YAML::LowerCase << true; - out << YAML::ShortBool << YAML::UpperCase << false; - out << YAML::ShortBool << YAML::CamelCase << false; - out << YAML::ShortBool << YAML::LowerCase << false; - out << YAML::EndSeq; - desiredOutput = - "- TRUE\n- True\n- true\n- FALSE\n- False\n- false\n" - "- YES\n- Yes\n- yes\n- NO\n- No\n- no\n" - "- ON\n- On\n- on\n- OFF\n- Off\n- off\n" - "- Y\n- Y\n- y\n- N\n- N\n- n"; - } - - void DocStartAndEnd(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginDoc; - out << YAML::BeginSeq << 1 << 2 << 3 << YAML::EndSeq; - out << YAML::BeginDoc; - out << "Hi there!"; - out << YAML::EndDoc; - out << YAML::EndDoc; - out << YAML::EndDoc; - out << YAML::BeginDoc; - out << YAML::VerbatimTag("foo") << "bar"; - desiredOutput = "---\n- 1\n- 2\n- 3\n---\nHi there!\n...\n...\n...\n---\n! bar"; - } - - void ImplicitDocStart(YAML::Emitter& out, std::string& desiredOutput) - { - out << "Hi"; - out << "Bye"; - out << "Oops"; - desiredOutput = "Hi\n---\nBye\n---\nOops"; - } - - void EmptyString(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginMap; - out << YAML::Key << "key" << YAML::Value << ""; - out << YAML::EndMap; - desiredOutput = "key: \"\""; - } - - void SingleChar(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginSeq; - out << 'a'; - out << ':'; - out << (char)0x10; - out << '\n'; - out << ' '; - out << '\t'; - out << YAML::EndSeq; - desiredOutput = "- a\n- \":\"\n- \"\\x10\"\n- \"\\n\"\n- \" \"\n- \"\\t\""; - } - - void DefaultPrecision(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginSeq; - out << 1.234f; - out << 3.14159265358979; - out << YAML::EndSeq; - desiredOutput = "- 1.234\n- 3.14159265358979"; - } - - void SetPrecision(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginSeq; - out << YAML::FloatPrecision(3) << 1.234f; - out << YAML::DoublePrecision(6) << 3.14159265358979; - out << YAML::EndSeq; - desiredOutput = "- 1.23\n- 3.14159"; - } - - void DashInBlockContext(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::BeginMap; - out << YAML::Key << "key" << YAML::Value << "-"; - out << YAML::EndMap; - desiredOutput = "key: \"-\""; - } - - void HexAndOct(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::Flow << YAML::BeginSeq; - out << 31; - out << YAML::Hex << 31; - out << YAML::Oct << 31; - out << YAML::EndSeq; - desiredOutput = "[31, 0x1f, 037]"; - } - - void CompactMapWithNewline(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::Comment("Characteristics"); - out << YAML::BeginSeq; - out << YAML::BeginMap; - out << YAML::Key << "color" << YAML::Value << "blue"; - out << YAML::Key << "height" << YAML::Value << 120; - out << YAML::EndMap; - out << YAML::Newline << YAML::Newline; - out << YAML::Comment("Skills"); - out << YAML::BeginMap; - out << YAML::Key << "attack" << YAML::Value << 23; - out << YAML::Key << "intelligence" << YAML::Value << 56; - out << YAML::EndMap; - out << YAML::EndSeq; - - desiredOutput = - "# Characteristics\n" - "- color: blue\n" - " height: 120\n" - "\n" - "# Skills\n" - "- attack: 23\n" - " intelligence: 56"; - } - - void ForceSingleQuotedToDouble(YAML::Emitter& out, std::string& desiredOutput) - { - out << YAML::SingleQuoted << "Hello\nWorld"; - - desiredOutput = "\"Hello\\nWorld\""; - } - - //////////////////////////////////////////////////////////////////////////////// - // incorrect emitting - - void ExtraEndSeq(YAML::Emitter& out, std::string& desiredError) - { - desiredError = YAML::ErrorMsg::UNEXPECTED_END_SEQ; - - out << YAML::BeginSeq; - out << "Hello"; - out << "World"; - out << YAML::EndSeq; - out << YAML::EndSeq; - } - - void ExtraEndMap(YAML::Emitter& out, std::string& desiredError) - { - desiredError = YAML::ErrorMsg::UNEXPECTED_END_MAP; - - out << YAML::BeginMap; - out << YAML::Key << "Hello" << YAML::Value << "World"; - out << YAML::EndMap; - out << YAML::EndMap; - } - - void InvalidAnchor(YAML::Emitter& out, std::string& desiredError) - { - desiredError = YAML::ErrorMsg::INVALID_ANCHOR; - - out << YAML::BeginSeq; - out << YAML::Anchor("new\nline") << "Test"; - out << YAML::EndSeq; - } - - void InvalidAlias(YAML::Emitter& out, std::string& desiredError) - { - desiredError = YAML::ErrorMsg::INVALID_ALIAS; - - out << YAML::BeginSeq; - out << YAML::Alias("new\nline"); - out << YAML::EndSeq; - } - } - - namespace { - void RunEmitterTest(void (*test)(YAML::Emitter&, std::string&), const std::string& name, int& passed, int& total) { - YAML::Emitter out; - std::string desiredOutput; - test(out, desiredOutput); - std::string output = out.c_str(); - std::string lastError = out.GetLastError(); - - if(output == desiredOutput) { - try { - YAML::Node node = YAML::Load(output); - passed++; - } catch(const YAML::Exception& e) { - std::cout << "Emitter test failed: " << name << "\n"; - std::cout << "Parsing output error: " << e.what() << "\n"; - } - } else { - std::cout << "Emitter test failed: " << name << "\n"; - std::cout << "Output:\n"; - std::cout << output << "<<<\n"; - std::cout << "Desired output:\n"; - std::cout << desiredOutput << "<<<\n"; - if(!out.good()) - std::cout << "Emitter error: " << lastError << "\n"; - } - total++; - } - - void RunEmitterErrorTest(void (*test)(YAML::Emitter&, std::string&), const std::string& name, int& passed, int& total) { - YAML::Emitter out; - std::string desiredError; - test(out, desiredError); - std::string lastError = out.GetLastError(); - if(!out.good() && lastError == desiredError) { - passed++; - } else { - std::cout << "Emitter test failed: " << name << "\n"; - if(out.good()) - std::cout << "No error detected\n"; - else - std::cout << "Detected error: " << lastError << "\n"; - std::cout << "Expected error: " << desiredError << "\n"; - } - total++; - } - - void RunGenEmitterTest(TEST (*test)(YAML::Emitter&), const std::string& name, int& passed, int& total) { - YAML::Emitter out; - TEST ret; - - try { - ret = test(out); - } catch(const YAML::Exception& e) { - ret.ok = false; - ret.error = std::string(" Exception caught: ") + e.what(); - } - - if(!out.good()) { - ret.ok = false; - ret.error = out.GetLastError(); - } - - if(!ret.ok) { - std::cout << "Generated emitter test failed: " << name << "\n"; - std::cout << "Output:\n"; - std::cout << out.c_str() << "<<<\n"; - std::cout << ret.error << "\n"; - } - - if(ret.ok) - passed++; - total++; - } - } - -#include "genemittertests.h" - - bool RunEmitterTests() - { - int passed = 0; - int total = 0; - RunEmitterTest(&Emitter::SimpleScalar, "simple scalar", passed, total); - RunEmitterTest(&Emitter::SimpleSeq, "simple seq", passed, total); - RunEmitterTest(&Emitter::SimpleFlowSeq, "simple flow seq", passed, total); - RunEmitterTest(&Emitter::EmptyFlowSeq, "empty flow seq", passed, total); - RunEmitterTest(&Emitter::NestedBlockSeq, "nested block seq", passed, total); - RunEmitterTest(&Emitter::NestedFlowSeq, "nested flow seq", passed, total); - RunEmitterTest(&Emitter::SimpleMap, "simple map", passed, total); - RunEmitterTest(&Emitter::SimpleFlowMap, "simple flow map", passed, total); - RunEmitterTest(&Emitter::MapAndList, "map and list", passed, total); - RunEmitterTest(&Emitter::ListAndMap, "list and map", passed, total); - RunEmitterTest(&Emitter::NestedBlockMap, "nested block map", passed, total); - RunEmitterTest(&Emitter::NestedFlowMap, "nested flow map", passed, total); - RunEmitterTest(&Emitter::MapListMix, "map list mix", passed, total); - RunEmitterTest(&Emitter::SimpleLongKey, "simple long key", passed, total); - RunEmitterTest(&Emitter::SingleLongKey, "single long key", passed, total); - RunEmitterTest(&Emitter::ComplexLongKey, "complex long key", passed, total); - RunEmitterTest(&Emitter::AutoLongKey, "auto long key", passed, total); - RunEmitterTest(&Emitter::ScalarFormat, "scalar format", passed, total); - RunEmitterTest(&Emitter::AutoLongKeyScalar, "auto long key scalar", passed, total); - RunEmitterTest(&Emitter::LongKeyFlowMap, "long key flow map", passed, total); - RunEmitterTest(&Emitter::BlockMapAsKey, "block map as key", passed, total); - RunEmitterTest(&Emitter::AliasAndAnchor, "alias and anchor", passed, total); - RunEmitterTest(&Emitter::AliasAndAnchorWithNull, "alias and anchor with null", passed, total); - RunEmitterTest(&Emitter::AliasAndAnchorInFlow, "alias and anchor in flow", passed, total); - RunEmitterTest(&Emitter::SimpleVerbatimTag, "simple verbatim tag", passed, total); - RunEmitterTest(&Emitter::VerbatimTagInBlockSeq, "verbatim tag in block seq", passed, total); - RunEmitterTest(&Emitter::VerbatimTagInFlowSeq, "verbatim tag in flow seq", passed, total); - RunEmitterTest(&Emitter::VerbatimTagInFlowSeqWithNull, "verbatim tag in flow seq with null", passed, total); - RunEmitterTest(&Emitter::VerbatimTagInBlockMap, "verbatim tag in block map", passed, total); - RunEmitterTest(&Emitter::VerbatimTagInFlowMap, "verbatim tag in flow map", passed, total); - RunEmitterTest(&Emitter::VerbatimTagInFlowMapWithNull, "verbatim tag in flow map with null", passed, total); - RunEmitterTest(&Emitter::VerbatimTagWithEmptySeq, "verbatim tag with empty seq", passed, total); - RunEmitterTest(&Emitter::VerbatimTagWithEmptyMap, "verbatim tag with empty map", passed, total); - RunEmitterTest(&Emitter::VerbatimTagWithEmptySeqAndMap, "verbatim tag with empty seq and map", passed, total); - RunEmitterTest(&Emitter::ByKindTagWithScalar, "by-kind tag with scalar", passed, total); - RunEmitterTest(&Emitter::LocalTagWithScalar, "local tag with scalar", passed, total); - RunEmitterTest(&Emitter::ComplexDoc, "complex doc", passed, total); - RunEmitterTest(&Emitter::STLContainers, "STL containers", passed, total); - RunEmitterTest(&Emitter::SimpleComment, "simple comment", passed, total); - RunEmitterTest(&Emitter::MultiLineComment, "multi-line comment", passed, total); - RunEmitterTest(&Emitter::ComplexComments, "complex comments", passed, total); - RunEmitterTest(&Emitter::InitialComment, "initial comment", passed, total); - RunEmitterTest(&Emitter::InitialCommentWithDocIndicator, "initial comment with doc indicator", passed, total); - RunEmitterTest(&Emitter::CommentInFlowSeq, "comment in flow seq", passed, total); - RunEmitterTest(&Emitter::CommentInFlowMap, "comment in flow map", passed, total); - RunEmitterTest(&Emitter::Indentation, "indentation", passed, total); - RunEmitterTest(&Emitter::SimpleGlobalSettings, "simple global settings", passed, total); - RunEmitterTest(&Emitter::ComplexGlobalSettings, "complex global settings", passed, total); - RunEmitterTest(&Emitter::Null, "null", passed, total); - RunEmitterTest(&Emitter::EscapedUnicode, "escaped unicode", passed, total); - RunEmitterTest(&Emitter::Unicode, "unicode", passed, total); - RunEmitterTest(&Emitter::DoubleQuotedUnicode, "double quoted unicode", passed, total); - RunEmitterTest(&Emitter::UserType, "user type", passed, total); - RunEmitterTest(&Emitter::UserTypeInContainer, "user type in container", passed, total); - RunEmitterTest(&Emitter::PointerToInt, "pointer to int", passed, total); - RunEmitterTest(&Emitter::PointerToUserType, "pointer to user type", passed, total); - RunEmitterTest(&Emitter::NewlineAtEnd, "newline at end", passed, total); - RunEmitterTest(&Emitter::NewlineInBlockSequence, "newline in block sequence", passed, total); - RunEmitterTest(&Emitter::NewlineInFlowSequence, "newline in flow sequence", passed, total); - RunEmitterTest(&Emitter::NewlineInBlockMap, "newline in block map", passed, total); - RunEmitterTest(&Emitter::NewlineInFlowMap, "newline in flow map", passed, total); - RunEmitterTest(&Emitter::LotsOfNewlines, "lots of newlines", passed, total); - RunEmitterTest(&Emitter::Binary, "binary", passed, total); - RunEmitterTest(&Emitter::LongBinary, "long binary", passed, total); - RunEmitterTest(&Emitter::EmptyBinary, "empty binary", passed, total); - RunEmitterTest(&Emitter::ColonAtEndOfScalar, "colon at end of scalar", passed, total); - RunEmitterTest(&Emitter::ColonAsScalar, "colon as scalar", passed, total); - RunEmitterTest(&Emitter::ColonAtEndOfScalarInFlow, "colon at end of scalar in flow", passed, total); - RunEmitterTest(&Emitter::BoolFormatting, "bool formatting", passed, total); - RunEmitterTest(&Emitter::DocStartAndEnd, "doc start and end", passed, total); - RunEmitterTest(&Emitter::ImplicitDocStart, "implicit doc start", passed, total); - RunEmitterTest(&Emitter::EmptyString, "empty string", passed, total); - RunEmitterTest(&Emitter::SingleChar, "single char", passed, total); - RunEmitterTest(&Emitter::DefaultPrecision, "default precision", passed, total); - RunEmitterTest(&Emitter::SetPrecision, "set precision", passed, total); - RunEmitterTest(&Emitter::DashInBlockContext, "dash in block context", passed, total); - RunEmitterTest(&Emitter::HexAndOct, "hex and oct", passed, total); - RunEmitterTest(&Emitter::CompactMapWithNewline, "compact map with newline", passed, total); - RunEmitterTest(&Emitter::ForceSingleQuotedToDouble, "force single quoted to double", passed, total); - - RunEmitterErrorTest(&Emitter::ExtraEndSeq, "extra EndSeq", passed, total); - RunEmitterErrorTest(&Emitter::ExtraEndMap, "extra EndMap", passed, total); - RunEmitterErrorTest(&Emitter::InvalidAnchor, "invalid anchor", passed, total); - RunEmitterErrorTest(&Emitter::InvalidAlias, "invalid alias", passed, total); - RunEmitterErrorTest(&Emitter::BadLocalTag, "bad local tag", passed, total); - - RunGenEmitterTests(passed, total); - - std::cout << "Emitter tests: " << passed << "/" << total << " passed\n"; - return passed == total; - } +void SimpleScalar(YAML::Emitter& out, std::string& desiredOutput) { + out << "Hello, World!"; + desiredOutput = "Hello, World!"; } +void SimpleSeq(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginSeq; + out << "eggs"; + out << "bread"; + out << "milk"; + out << YAML::EndSeq; + + desiredOutput = "- eggs\n- bread\n- milk"; +} + +void SimpleFlowSeq(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::Flow; + out << YAML::BeginSeq; + out << "Larry"; + out << "Curly"; + out << "Moe"; + out << YAML::EndSeq; + + desiredOutput = "[Larry, Curly, Moe]"; +} + +void EmptyFlowSeq(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::Flow; + out << YAML::BeginSeq; + out << YAML::EndSeq; + + desiredOutput = "[]"; +} + +void NestedBlockSeq(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginSeq; + out << "item 1"; + out << YAML::BeginSeq << "subitem 1" + << "subitem 2" << YAML::EndSeq; + out << YAML::EndSeq; + + desiredOutput = "- item 1\n-\n - subitem 1\n - subitem 2"; +} + +void NestedFlowSeq(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginSeq; + out << "one"; + out << YAML::Flow << YAML::BeginSeq << "two" + << "three" << YAML::EndSeq; + out << YAML::EndSeq; + + desiredOutput = "- one\n- [two, three]"; +} + +void SimpleMap(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginMap; + out << YAML::Key << "name"; + out << YAML::Value << "Ryan Braun"; + out << YAML::Key << "position"; + out << YAML::Value << "3B"; + out << YAML::EndMap; + + desiredOutput = "name: Ryan Braun\nposition: 3B"; +} + +void SimpleFlowMap(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::Flow; + out << YAML::BeginMap; + out << YAML::Key << "shape"; + out << YAML::Value << "square"; + out << YAML::Key << "color"; + out << YAML::Value << "blue"; + out << YAML::EndMap; + + desiredOutput = "{shape: square, color: blue}"; +} + +void MapAndList(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginMap; + out << YAML::Key << "name"; + out << YAML::Value << "Barack Obama"; + out << YAML::Key << "children"; + out << YAML::Value << YAML::BeginSeq << "Sasha" + << "Malia" << YAML::EndSeq; + out << YAML::EndMap; + + desiredOutput = "name: Barack Obama\nchildren:\n - Sasha\n - Malia"; +} + +void ListAndMap(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginSeq; + out << "item 1"; + out << YAML::BeginMap; + out << YAML::Key << "pens" << YAML::Value << 8; + out << YAML::Key << "pencils" << YAML::Value << 14; + out << YAML::EndMap; + out << "item 2"; + out << YAML::EndSeq; + + desiredOutput = "- item 1\n- pens: 8\n pencils: 14\n- item 2"; +} + +void NestedBlockMap(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginMap; + out << YAML::Key << "name"; + out << YAML::Value << "Fred"; + out << YAML::Key << "grades"; + out << YAML::Value; + out << YAML::BeginMap; + out << YAML::Key << "algebra" << YAML::Value << "A"; + out << YAML::Key << "physics" << YAML::Value << "C+"; + out << YAML::Key << "literature" << YAML::Value << "B"; + out << YAML::EndMap; + out << YAML::EndMap; + + desiredOutput = + "name: Fred\ngrades:\n algebra: A\n physics: C+\n literature: B"; +} + +void NestedFlowMap(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::Flow; + out << YAML::BeginMap; + out << YAML::Key << "name"; + out << YAML::Value << "Fred"; + out << YAML::Key << "grades"; + out << YAML::Value; + out << YAML::BeginMap; + out << YAML::Key << "algebra" << YAML::Value << "A"; + out << YAML::Key << "physics" << YAML::Value << "C+"; + out << YAML::Key << "literature" << YAML::Value << "B"; + out << YAML::EndMap; + out << YAML::EndMap; + + desiredOutput = + "{name: Fred, grades: {algebra: A, physics: C+, literature: B}}"; +} + +void MapListMix(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginMap; + out << YAML::Key << "name"; + out << YAML::Value << "Bob"; + out << YAML::Key << "position"; + out << YAML::Value; + out << YAML::Flow << YAML::BeginSeq << 2 << 4 << YAML::EndSeq; + out << YAML::Key << "invincible" << YAML::Value << YAML::OnOffBool << false; + out << YAML::EndMap; + + desiredOutput = "name: Bob\nposition: [2, 4]\ninvincible: off"; +} + +void SimpleLongKey(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::LongKey; + out << YAML::BeginMap; + out << YAML::Key << "height"; + out << YAML::Value << "5'9\""; + out << YAML::Key << "weight"; + out << YAML::Value << 145; + out << YAML::EndMap; + + desiredOutput = "? height\n: 5'9\"\n? weight\n: 145"; +} + +void SingleLongKey(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginMap; + out << YAML::Key << "age"; + out << YAML::Value << "24"; + out << YAML::LongKey << YAML::Key << "height"; + out << YAML::Value << "5'9\""; + out << YAML::Key << "weight"; + out << YAML::Value << 145; + out << YAML::EndMap; + + desiredOutput = "age: 24\n? height\n: 5'9\"\nweight: 145"; +} + +void ComplexLongKey(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::LongKey; + out << YAML::BeginMap; + out << YAML::Key << YAML::BeginSeq << 1 << 3 << YAML::EndSeq; + out << YAML::Value << "monster"; + out << YAML::Key << YAML::Flow << YAML::BeginSeq << 2 << 0 << YAML::EndSeq; + out << YAML::Value << "demon"; + out << YAML::EndMap; + + desiredOutput = "? - 1\n - 3\n: monster\n? [2, 0]\n: demon"; +} + +void AutoLongKey(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginMap; + out << YAML::Key << YAML::BeginSeq << 1 << 3 << YAML::EndSeq; + out << YAML::Value << "monster"; + out << YAML::Key << YAML::Flow << YAML::BeginSeq << 2 << 0 << YAML::EndSeq; + out << YAML::Value << "demon"; + out << YAML::Key << "the origin"; + out << YAML::Value << "angel"; + out << YAML::EndMap; + + desiredOutput = "? - 1\n - 3\n: monster\n[2, 0]: demon\nthe origin: angel"; +} + +void ScalarFormat(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginSeq; + out << "simple scalar"; + out << YAML::SingleQuoted << "explicit single-quoted scalar"; + out << YAML::DoubleQuoted << "explicit double-quoted scalar"; + out << "auto-detected\ndouble-quoted scalar"; + out << "a non-\"auto-detected\" double-quoted scalar"; + out << YAML::Literal << "literal scalar\nthat may span\nmany, many\nlines " + "and have \"whatever\" crazy\tsymbols that we like"; + out << YAML::EndSeq; + + desiredOutput = + "- simple scalar\n- 'explicit single-quoted scalar'\n- \"explicit " + "double-quoted scalar\"\n- \"auto-detected\\ndouble-quoted scalar\"\n- a " + "non-\"auto-detected\" double-quoted scalar\n- |\n literal scalar\n " + "that may span\n many, many\n lines and have \"whatever\" " + "crazy\tsymbols that we like"; +} + +void AutoLongKeyScalar(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginMap; + out << YAML::Key << YAML::Literal << "multi-line\nscalar"; + out << YAML::Value << "and its value"; + out << YAML::EndMap; + + desiredOutput = "? |\n multi-line\n scalar\n: and its value"; +} + +void LongKeyFlowMap(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::Flow; + out << YAML::BeginMap; + out << YAML::Key << "simple key"; + out << YAML::Value << "and value"; + out << YAML::LongKey << YAML::Key << "long key"; + out << YAML::Value << "and its value"; + out << YAML::EndMap; + + desiredOutput = "{simple key: and value, ? long key: and its value}"; +} + +void BlockMapAsKey(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginMap; + out << YAML::Key; + out << YAML::BeginMap; + out << YAML::Key << "key" << YAML::Value << "value"; + out << YAML::Key << "next key" << YAML::Value << "next value"; + out << YAML::EndMap; + out << YAML::Value; + out << "total value"; + out << YAML::EndMap; + + desiredOutput = "? key: value\n next key: next value\n: total value"; +} + +void AliasAndAnchor(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginSeq; + out << YAML::Anchor("fred"); + out << YAML::BeginMap; + out << YAML::Key << "name" << YAML::Value << "Fred"; + out << YAML::Key << "age" << YAML::Value << 42; + out << YAML::EndMap; + out << YAML::Alias("fred"); + out << YAML::EndSeq; + + desiredOutput = "- &fred\n name: Fred\n age: 42\n- *fred"; +} + +void AliasAndAnchorWithNull(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginSeq; + out << YAML::Anchor("fred") << YAML::Null; + out << YAML::Alias("fred"); + out << YAML::EndSeq; + + desiredOutput = "- &fred ~\n- *fred"; +} + +void AliasAndAnchorInFlow(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::Flow << YAML::BeginSeq; + out << YAML::Anchor("fred"); + out << YAML::BeginMap; + out << YAML::Key << "name" << YAML::Value << "Fred"; + out << YAML::Key << "age" << YAML::Value << 42; + out << YAML::EndMap; + out << YAML::Alias("fred"); + out << YAML::EndSeq; + + desiredOutput = "[&fred {name: Fred, age: 42}, *fred]"; +} + +void SimpleVerbatimTag(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::VerbatimTag("!foo") << "bar"; + + desiredOutput = "! bar"; +} + +void VerbatimTagInBlockSeq(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginSeq; + out << YAML::VerbatimTag("!foo") << "bar"; + out << "baz"; + out << YAML::EndSeq; + + desiredOutput = "- ! bar\n- baz"; +} + +void VerbatimTagInFlowSeq(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::Flow << YAML::BeginSeq; + out << YAML::VerbatimTag("!foo") << "bar"; + out << "baz"; + out << YAML::EndSeq; + + desiredOutput = "[! bar, baz]"; +} + +void VerbatimTagInFlowSeqWithNull(YAML::Emitter& out, + std::string& desiredOutput) { + out << YAML::Flow << YAML::BeginSeq; + out << YAML::VerbatimTag("!foo") << YAML::Null; + out << "baz"; + out << YAML::EndSeq; + + desiredOutput = "[! ~, baz]"; +} + +void VerbatimTagInBlockMap(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginMap; + out << YAML::Key << YAML::VerbatimTag("!foo") << "bar"; + out << YAML::Value << YAML::VerbatimTag("!waz") << "baz"; + out << YAML::EndMap; + + desiredOutput = "! bar: ! baz"; +} + +void VerbatimTagInFlowMap(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::Flow << YAML::BeginMap; + out << YAML::Key << YAML::VerbatimTag("!foo") << "bar"; + out << YAML::Value << "baz"; + out << YAML::EndMap; + + desiredOutput = "{! bar: baz}"; +} + +void VerbatimTagInFlowMapWithNull(YAML::Emitter& out, + std::string& desiredOutput) { + out << YAML::Flow << YAML::BeginMap; + out << YAML::Key << YAML::VerbatimTag("!foo") << YAML::Null; + out << YAML::Value << "baz"; + out << YAML::EndMap; + + desiredOutput = "{! ~: baz}"; +} + +void VerbatimTagWithEmptySeq(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::VerbatimTag("!foo") << YAML::BeginSeq << YAML::EndSeq; + + desiredOutput = "!\n[]"; +} + +void VerbatimTagWithEmptyMap(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::VerbatimTag("!bar") << YAML::BeginMap << YAML::EndMap; + + desiredOutput = "!\n{}"; +} + +void VerbatimTagWithEmptySeqAndMap(YAML::Emitter& out, + std::string& desiredOutput) { + out << YAML::BeginSeq; + out << YAML::VerbatimTag("!foo") << YAML::BeginSeq << YAML::EndSeq; + out << YAML::VerbatimTag("!bar") << YAML::BeginMap << YAML::EndMap; + out << YAML::EndSeq; + + desiredOutput = "- !\n []\n- !\n {}"; +} + +void ByKindTagWithScalar(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginSeq; + out << YAML::DoubleQuoted << "12"; + out << "12"; + out << YAML::TagByKind << "12"; + out << YAML::EndSeq; + + desiredOutput = "- \"12\"\n- 12\n- ! 12"; +} + +void LocalTagWithScalar(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::LocalTag("foo") << "bar"; + + desiredOutput = "!foo bar"; +} + +void BadLocalTag(YAML::Emitter& out, std::string& desiredError) { + out << YAML::LocalTag("e!far") << "bar"; + + desiredError = "invalid tag"; +} + +void ComplexDoc(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginMap; + out << YAML::Key << "receipt"; + out << YAML::Value << "Oz-Ware Purchase Invoice"; + out << YAML::Key << "date"; + out << YAML::Value << "2007-08-06"; + out << YAML::Key << "customer"; + out << YAML::Value; + out << YAML::BeginMap; + out << YAML::Key << "given"; + out << YAML::Value << "Dorothy"; + out << YAML::Key << "family"; + out << YAML::Value << "Gale"; + out << YAML::EndMap; + out << YAML::Key << "items"; + out << YAML::Value; + out << YAML::BeginSeq; + out << YAML::BeginMap; + out << YAML::Key << "part_no"; + out << YAML::Value << "A4786"; + out << YAML::Key << "descrip"; + out << YAML::Value << "Water Bucket (Filled)"; + out << YAML::Key << "price"; + out << YAML::Value << 1.47; + out << YAML::Key << "quantity"; + out << YAML::Value << 4; + out << YAML::EndMap; + out << YAML::BeginMap; + out << YAML::Key << "part_no"; + out << YAML::Value << "E1628"; + out << YAML::Key << "descrip"; + out << YAML::Value << "High Heeled \"Ruby\" Slippers"; + out << YAML::Key << "price"; + out << YAML::Value << 100.27; + out << YAML::Key << "quantity"; + out << YAML::Value << 1; + out << YAML::EndMap; + out << YAML::EndSeq; + out << YAML::Key << "bill-to"; + out << YAML::Value << YAML::Anchor("id001"); + out << YAML::BeginMap; + out << YAML::Key << "street"; + out << YAML::Value << YAML::Literal << "123 Tornado Alley\nSuite 16"; + out << YAML::Key << "city"; + out << YAML::Value << "East Westville"; + out << YAML::Key << "state"; + out << YAML::Value << "KS"; + out << YAML::EndMap; + out << YAML::Key << "ship-to"; + out << YAML::Value << YAML::Alias("id001"); + out << YAML::EndMap; + + desiredOutput = + "receipt: Oz-Ware Purchase Invoice\ndate: 2007-08-06\ncustomer:\n " + "given: Dorothy\n family: Gale\nitems:\n - part_no: A4786\n " + "descrip: Water Bucket (Filled)\n price: 1.47\n quantity: 4\n - " + "part_no: E1628\n descrip: High Heeled \"Ruby\" Slippers\n price: " + "100.27\n quantity: 1\nbill-to: &id001\n street: |\n 123 Tornado " + "Alley\n Suite 16\n city: East Westville\n state: KS\nship-to: " + "*id001"; +} + +void STLContainers(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginSeq; + std::vector primes; + primes.push_back(2); + primes.push_back(3); + primes.push_back(5); + primes.push_back(7); + primes.push_back(11); + primes.push_back(13); + out << YAML::Flow << primes; + std::map ages; + ages["Daniel"] = 26; + ages["Jesse"] = 24; + out << ages; + out << YAML::EndSeq; + + desiredOutput = "- [2, 3, 5, 7, 11, 13]\n- Daniel: 26\n Jesse: 24"; +} + +void SimpleComment(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginMap; + out << YAML::Key << "method"; + out << YAML::Value << "least squares" + << YAML::Comment("should we change this method?"); + out << YAML::EndMap; + + desiredOutput = "method: least squares # should we change this method?"; +} + +void MultiLineComment(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginSeq; + out << "item 1" << YAML::Comment( + "really really long\ncomment that couldn't " + "possibly\nfit on one line"); + out << "item 2"; + out << YAML::EndSeq; + + desiredOutput = + "- item 1 # really really long\n # comment that couldn't " + "possibly\n # fit on one line\n- item 2"; +} + +void ComplexComments(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginMap; + out << YAML::LongKey << YAML::Key << "long key" << YAML::Comment("long key"); + out << YAML::Value << "value"; + out << YAML::EndMap; + + desiredOutput = "? long key # long key\n: value"; +} + +void InitialComment(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::Comment("A comment describing the purpose of the file."); + out << YAML::BeginMap << YAML::Key << "key" << YAML::Value << "value" + << YAML::EndMap; + + desiredOutput = "# A comment describing the purpose of the file.\nkey: value"; +} + +void InitialCommentWithDocIndicator(YAML::Emitter& out, + std::string& desiredOutput) { + out << YAML::BeginDoc + << YAML::Comment("A comment describing the purpose of the file."); + out << YAML::BeginMap << YAML::Key << "key" << YAML::Value << "value" + << YAML::EndMap; + + desiredOutput = + "---\n# A comment describing the purpose of the file.\nkey: value"; +} + +void CommentInFlowSeq(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::Flow << YAML::BeginSeq << "foo" << YAML::Comment("foo!") << "bar" + << YAML::EndSeq; + + desiredOutput = "[foo, # foo!\nbar]"; +} + +void CommentInFlowMap(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::Flow << YAML::BeginMap; + out << YAML::Key << "foo" << YAML::Value << "foo value"; + out << YAML::Key << "bar" << YAML::Value << "bar value" + << YAML::Comment("bar!"); + out << YAML::Key << "baz" << YAML::Value << "baz value" + << YAML::Comment("baz!"); + out << YAML::EndMap; + + desiredOutput = + "{foo: foo value, bar: bar value, # bar!\nbaz: baz value, # baz!\n}"; +} + +void Indentation(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::Indent(4); + out << YAML::BeginSeq; + out << YAML::BeginMap; + out << YAML::Key << "key 1" << YAML::Value << "value 1"; + out << YAML::Key << "key 2" << YAML::Value << YAML::BeginSeq << "a" + << "b" + << "c" << YAML::EndSeq; + out << YAML::EndMap; + out << YAML::EndSeq; + + desiredOutput = + "- key 1: value 1\n key 2:\n - a\n - b\n - " + " c"; +} + +void SimpleGlobalSettings(YAML::Emitter& out, std::string& desiredOutput) { + out.SetIndent(4); + out.SetMapFormat(YAML::LongKey); + + out << YAML::BeginSeq; + out << YAML::BeginMap; + out << YAML::Key << "key 1" << YAML::Value << "value 1"; + out << YAML::Key << "key 2" << YAML::Value << YAML::Flow << YAML::BeginSeq + << "a" + << "b" + << "c" << YAML::EndSeq; + out << YAML::EndMap; + out << YAML::EndSeq; + + desiredOutput = "- ? key 1\n : value 1\n ? key 2\n : [a, b, c]"; +} + +void ComplexGlobalSettings(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginSeq; + out << YAML::Block; + out << YAML::BeginMap; + out << YAML::Key << "key 1" << YAML::Value << "value 1"; + out << YAML::Key << "key 2" << YAML::Value; + out.SetSeqFormat(YAML::Flow); + out << YAML::BeginSeq << "a" + << "b" + << "c" << YAML::EndSeq; + out << YAML::EndMap; + out << YAML::BeginMap; + out << YAML::Key << YAML::BeginSeq << 1 << 2 << YAML::EndSeq; + out << YAML::Value << YAML::BeginMap << YAML::Key << "a" << YAML::Value << "b" + << YAML::EndMap; + out << YAML::EndMap; + out << YAML::EndSeq; + + desiredOutput = "- key 1: value 1\n key 2: [a, b, c]\n- [1, 2]:\n a: b"; +} + +void Null(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginSeq; + out << YAML::Null; + out << YAML::BeginMap; + out << YAML::Key << "null value" << YAML::Value << YAML::Null; + out << YAML::Key << YAML::Null << YAML::Value << "null key"; + out << YAML::EndMap; + out << YAML::EndSeq; + + desiredOutput = "- ~\n- null value: ~\n ~: null key"; +} + +void EscapedUnicode(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::EscapeNonAscii << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2"; + + desiredOutput = "\"$ \\xa2 \\u20ac \\U00024b62\""; +} + +void Unicode(YAML::Emitter& out, std::string& desiredOutput) { + out << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2"; + desiredOutput = "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2"; +} + +void DoubleQuotedUnicode(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::DoubleQuoted << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2"; + desiredOutput = "\"\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2\""; +} + +struct Foo { + Foo() : x(0) {} + Foo(int x_, const std::string& bar_) : x(x_), bar(bar_) {} + + int x; + std::string bar; +}; + +YAML::Emitter& operator<<(YAML::Emitter& out, const Foo& foo) { + out << YAML::BeginMap; + out << YAML::Key << "x" << YAML::Value << foo.x; + out << YAML::Key << "bar" << YAML::Value << foo.bar; + out << YAML::EndMap; + return out; +} + +void UserType(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginSeq; + out << Foo(5, "hello"); + out << Foo(3, "goodbye"); + out << YAML::EndSeq; + + desiredOutput = "- x: 5\n bar: hello\n- x: 3\n bar: goodbye"; +} + +void UserTypeInContainer(YAML::Emitter& out, std::string& desiredOutput) { + std::vector fv; + fv.push_back(Foo(5, "hello")); + fv.push_back(Foo(3, "goodbye")); + out << fv; + + desiredOutput = "- x: 5\n bar: hello\n- x: 3\n bar: goodbye"; +} + +template +YAML::Emitter& operator<<(YAML::Emitter& out, const T* v) { + if (v) + out << *v; + else + out << YAML::Null; + return out; +} + +void PointerToInt(YAML::Emitter& out, std::string& desiredOutput) { + int foo = 5; + int* bar = &foo; + int* baz = 0; + out << YAML::BeginSeq; + out << bar << baz; + out << YAML::EndSeq; + + desiredOutput = "- 5\n- ~"; +} + +void PointerToUserType(YAML::Emitter& out, std::string& desiredOutput) { + Foo foo(5, "hello"); + Foo* bar = &foo; + Foo* baz = 0; + out << YAML::BeginSeq; + out << bar << baz; + out << YAML::EndSeq; + + desiredOutput = "- x: 5\n bar: hello\n- ~"; +} + +void NewlineAtEnd(YAML::Emitter& out, std::string& desiredOutput) { + out << "Hello" << YAML::Newline << YAML::Newline; + desiredOutput = "Hello\n\n"; +} + +void NewlineInBlockSequence(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginSeq; + out << "a" << YAML::Newline << "b" + << "c" << YAML::Newline << "d"; + out << YAML::EndSeq; + desiredOutput = "- a\n\n- b\n- c\n\n- d"; +} + +void NewlineInFlowSequence(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::Flow << YAML::BeginSeq; + out << "a" << YAML::Newline << "b" + << "c" << YAML::Newline << "d"; + out << YAML::EndSeq; + desiredOutput = "[a,\nb, c,\nd]"; +} + +void NewlineInBlockMap(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginMap; + out << YAML::Key << "a" << YAML::Value << "foo" << YAML::Newline; + out << YAML::Key << "b" << YAML::Newline << YAML::Value << "bar"; + out << YAML::LongKey << YAML::Key << "c" << YAML::Newline << YAML::Value + << "car"; + out << YAML::EndMap; + desiredOutput = "a: foo\nb:\n bar\n? c\n\n: car"; +} + +void NewlineInFlowMap(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::Flow << YAML::BeginMap; + out << YAML::Key << "a" << YAML::Value << "foo" << YAML::Newline; + out << YAML::Key << "b" << YAML::Value << "bar"; + out << YAML::EndMap; + desiredOutput = "{a: foo,\nb: bar}"; +} + +void LotsOfNewlines(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginSeq; + out << "a" << YAML::Newline; + out << YAML::BeginSeq; + out << "b" + << "c" << YAML::Newline; + out << YAML::EndSeq; + out << YAML::Newline; + out << YAML::BeginMap; + out << YAML::Newline << YAML::Key << "d" << YAML::Value << YAML::Newline + << "e"; + out << YAML::LongKey << YAML::Key << "f" << YAML::Newline << YAML::Value + << "foo"; + out << YAML::EndMap; + out << YAML::EndSeq; + desiredOutput = + "- a\n\n-\n - b\n - c\n\n\n-\n d:\n e\n ? f\n\n : foo"; +} + +void Binary(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::Binary(reinterpret_cast("Hello, World!"), + 13); + desiredOutput = "!!binary \"SGVsbG8sIFdvcmxkIQ==\""; +} + +void LongBinary(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::Binary( + reinterpret_cast( + "Man is distinguished, not only by his reason, but by this " + "singular passion from other animals, which is a lust of the " + "mind, that by a perseverance of delight in the continued and " + "indefatigable generation of knowledge, exceeds the short " + "vehemence of any carnal pleasure.\n"), + 270); + desiredOutput = + "!!binary " + "\"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieS" + "B0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIG" + "x1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbi" + "B0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZG" + "dlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS" + "4K\""; +} + +void EmptyBinary(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::Binary(reinterpret_cast(""), 0); + desiredOutput = "!!binary \"\""; +} + +void ColonAtEndOfScalar(YAML::Emitter& out, std::string& desiredOutput) { + out << "a:"; + desiredOutput = "\"a:\""; +} + +void ColonAsScalar(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginMap; + out << YAML::Key << "apple" << YAML::Value << ":"; + out << YAML::Key << "banana" << YAML::Value << ":"; + out << YAML::EndMap; + desiredOutput = "apple: \":\"\nbanana: \":\""; +} + +void ColonAtEndOfScalarInFlow(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::Flow << YAML::BeginMap << YAML::Key << "C:" << YAML::Value + << "C:" << YAML::EndMap; + desiredOutput = "{\"C:\": \"C:\"}"; +} + +void BoolFormatting(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginSeq; + out << YAML::TrueFalseBool << YAML::UpperCase << true; + out << YAML::TrueFalseBool << YAML::CamelCase << true; + out << YAML::TrueFalseBool << YAML::LowerCase << true; + out << YAML::TrueFalseBool << YAML::UpperCase << false; + out << YAML::TrueFalseBool << YAML::CamelCase << false; + out << YAML::TrueFalseBool << YAML::LowerCase << false; + out << YAML::YesNoBool << YAML::UpperCase << true; + out << YAML::YesNoBool << YAML::CamelCase << true; + out << YAML::YesNoBool << YAML::LowerCase << true; + out << YAML::YesNoBool << YAML::UpperCase << false; + out << YAML::YesNoBool << YAML::CamelCase << false; + out << YAML::YesNoBool << YAML::LowerCase << false; + out << YAML::OnOffBool << YAML::UpperCase << true; + out << YAML::OnOffBool << YAML::CamelCase << true; + out << YAML::OnOffBool << YAML::LowerCase << true; + out << YAML::OnOffBool << YAML::UpperCase << false; + out << YAML::OnOffBool << YAML::CamelCase << false; + out << YAML::OnOffBool << YAML::LowerCase << false; + out << YAML::ShortBool << YAML::UpperCase << true; + out << YAML::ShortBool << YAML::CamelCase << true; + out << YAML::ShortBool << YAML::LowerCase << true; + out << YAML::ShortBool << YAML::UpperCase << false; + out << YAML::ShortBool << YAML::CamelCase << false; + out << YAML::ShortBool << YAML::LowerCase << false; + out << YAML::EndSeq; + desiredOutput = + "- TRUE\n- True\n- true\n- FALSE\n- False\n- false\n" + "- YES\n- Yes\n- yes\n- NO\n- No\n- no\n" + "- ON\n- On\n- on\n- OFF\n- Off\n- off\n" + "- Y\n- Y\n- y\n- N\n- N\n- n"; +} + +void DocStartAndEnd(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginDoc; + out << YAML::BeginSeq << 1 << 2 << 3 << YAML::EndSeq; + out << YAML::BeginDoc; + out << "Hi there!"; + out << YAML::EndDoc; + out << YAML::EndDoc; + out << YAML::EndDoc; + out << YAML::BeginDoc; + out << YAML::VerbatimTag("foo") << "bar"; + desiredOutput = + "---\n- 1\n- 2\n- 3\n---\nHi there!\n...\n...\n...\n---\n! bar"; +} + +void ImplicitDocStart(YAML::Emitter& out, std::string& desiredOutput) { + out << "Hi"; + out << "Bye"; + out << "Oops"; + desiredOutput = "Hi\n---\nBye\n---\nOops"; +} + +void EmptyString(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginMap; + out << YAML::Key << "key" << YAML::Value << ""; + out << YAML::EndMap; + desiredOutput = "key: \"\""; +} + +void SingleChar(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginSeq; + out << 'a'; + out << ':'; + out << (char)0x10; + out << '\n'; + out << ' '; + out << '\t'; + out << YAML::EndSeq; + desiredOutput = "- a\n- \":\"\n- \"\\x10\"\n- \"\\n\"\n- \" \"\n- \"\\t\""; +} + +void DefaultPrecision(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginSeq; + out << 1.234f; + out << 3.14159265358979; + out << YAML::EndSeq; + desiredOutput = "- 1.234\n- 3.14159265358979"; +} + +void SetPrecision(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginSeq; + out << YAML::FloatPrecision(3) << 1.234f; + out << YAML::DoublePrecision(6) << 3.14159265358979; + out << YAML::EndSeq; + desiredOutput = "- 1.23\n- 3.14159"; +} + +void DashInBlockContext(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::BeginMap; + out << YAML::Key << "key" << YAML::Value << "-"; + out << YAML::EndMap; + desiredOutput = "key: \"-\""; +} + +void HexAndOct(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::Flow << YAML::BeginSeq; + out << 31; + out << YAML::Hex << 31; + out << YAML::Oct << 31; + out << YAML::EndSeq; + desiredOutput = "[31, 0x1f, 037]"; +} + +void CompactMapWithNewline(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::Comment("Characteristics"); + out << YAML::BeginSeq; + out << YAML::BeginMap; + out << YAML::Key << "color" << YAML::Value << "blue"; + out << YAML::Key << "height" << YAML::Value << 120; + out << YAML::EndMap; + out << YAML::Newline << YAML::Newline; + out << YAML::Comment("Skills"); + out << YAML::BeginMap; + out << YAML::Key << "attack" << YAML::Value << 23; + out << YAML::Key << "intelligence" << YAML::Value << 56; + out << YAML::EndMap; + out << YAML::EndSeq; + + desiredOutput = + "# Characteristics\n" + "- color: blue\n" + " height: 120\n" + "\n" + "# Skills\n" + "- attack: 23\n" + " intelligence: 56"; +} + +void ForceSingleQuotedToDouble(YAML::Emitter& out, std::string& desiredOutput) { + out << YAML::SingleQuoted << "Hello\nWorld"; + + desiredOutput = "\"Hello\\nWorld\""; +} + +//////////////////////////////////////////////////////////////////////////////// +// incorrect emitting + +void ExtraEndSeq(YAML::Emitter& out, std::string& desiredError) { + desiredError = YAML::ErrorMsg::UNEXPECTED_END_SEQ; + + out << YAML::BeginSeq; + out << "Hello"; + out << "World"; + out << YAML::EndSeq; + out << YAML::EndSeq; +} + +void ExtraEndMap(YAML::Emitter& out, std::string& desiredError) { + desiredError = YAML::ErrorMsg::UNEXPECTED_END_MAP; + + out << YAML::BeginMap; + out << YAML::Key << "Hello" << YAML::Value << "World"; + out << YAML::EndMap; + out << YAML::EndMap; +} + +void InvalidAnchor(YAML::Emitter& out, std::string& desiredError) { + desiredError = YAML::ErrorMsg::INVALID_ANCHOR; + + out << YAML::BeginSeq; + out << YAML::Anchor("new\nline") << "Test"; + out << YAML::EndSeq; +} + +void InvalidAlias(YAML::Emitter& out, std::string& desiredError) { + desiredError = YAML::ErrorMsg::INVALID_ALIAS; + + out << YAML::BeginSeq; + out << YAML::Alias("new\nline"); + out << YAML::EndSeq; +} +} + +namespace { +void RunEmitterTest(void (*test)(YAML::Emitter&, std::string&), + const std::string& name, int& passed, int& total) { + YAML::Emitter out; + std::string desiredOutput; + test(out, desiredOutput); + std::string output = out.c_str(); + std::string lastError = out.GetLastError(); + + if (output == desiredOutput) { + try { + YAML::Node node = YAML::Load(output); + passed++; + } + catch (const YAML::Exception& e) { + std::cout << "Emitter test failed: " << name << "\n"; + std::cout << "Parsing output error: " << e.what() << "\n"; + } + } else { + std::cout << "Emitter test failed: " << name << "\n"; + std::cout << "Output:\n"; + std::cout << output << "<<<\n"; + std::cout << "Desired output:\n"; + std::cout << desiredOutput << "<<<\n"; + if (!out.good()) + std::cout << "Emitter error: " << lastError << "\n"; + } + total++; +} + +void RunEmitterErrorTest(void (*test)(YAML::Emitter&, std::string&), + const std::string& name, int& passed, int& total) { + YAML::Emitter out; + std::string desiredError; + test(out, desiredError); + std::string lastError = out.GetLastError(); + if (!out.good() && lastError == desiredError) { + passed++; + } else { + std::cout << "Emitter test failed: " << name << "\n"; + if (out.good()) + std::cout << "No error detected\n"; + else + std::cout << "Detected error: " << lastError << "\n"; + std::cout << "Expected error: " << desiredError << "\n"; + } + total++; +} + +void RunGenEmitterTest(TEST (*test)(YAML::Emitter&), const std::string& name, + int& passed, int& total) { + YAML::Emitter out; + TEST ret; + + try { + ret = test(out); + } + catch (const YAML::Exception& e) { + ret.ok = false; + ret.error = std::string(" Exception caught: ") + e.what(); + } + + if (!out.good()) { + ret.ok = false; + ret.error = out.GetLastError(); + } + + if (!ret.ok) { + std::cout << "Generated emitter test failed: " << name << "\n"; + std::cout << "Output:\n"; + std::cout << out.c_str() << "<<<\n"; + std::cout << ret.error << "\n"; + } + + if (ret.ok) + passed++; + total++; +} +} + +#include "genemittertests.h" + +bool RunEmitterTests() { + int passed = 0; + int total = 0; + RunEmitterTest(&Emitter::SimpleScalar, "simple scalar", passed, total); + RunEmitterTest(&Emitter::SimpleSeq, "simple seq", passed, total); + RunEmitterTest(&Emitter::SimpleFlowSeq, "simple flow seq", passed, total); + RunEmitterTest(&Emitter::EmptyFlowSeq, "empty flow seq", passed, total); + RunEmitterTest(&Emitter::NestedBlockSeq, "nested block seq", passed, total); + RunEmitterTest(&Emitter::NestedFlowSeq, "nested flow seq", passed, total); + RunEmitterTest(&Emitter::SimpleMap, "simple map", passed, total); + RunEmitterTest(&Emitter::SimpleFlowMap, "simple flow map", passed, total); + RunEmitterTest(&Emitter::MapAndList, "map and list", passed, total); + RunEmitterTest(&Emitter::ListAndMap, "list and map", passed, total); + RunEmitterTest(&Emitter::NestedBlockMap, "nested block map", passed, total); + RunEmitterTest(&Emitter::NestedFlowMap, "nested flow map", passed, total); + RunEmitterTest(&Emitter::MapListMix, "map list mix", passed, total); + RunEmitterTest(&Emitter::SimpleLongKey, "simple long key", passed, total); + RunEmitterTest(&Emitter::SingleLongKey, "single long key", passed, total); + RunEmitterTest(&Emitter::ComplexLongKey, "complex long key", passed, total); + RunEmitterTest(&Emitter::AutoLongKey, "auto long key", passed, total); + RunEmitterTest(&Emitter::ScalarFormat, "scalar format", passed, total); + RunEmitterTest(&Emitter::AutoLongKeyScalar, "auto long key scalar", passed, + total); + RunEmitterTest(&Emitter::LongKeyFlowMap, "long key flow map", passed, total); + RunEmitterTest(&Emitter::BlockMapAsKey, "block map as key", passed, total); + RunEmitterTest(&Emitter::AliasAndAnchor, "alias and anchor", passed, total); + RunEmitterTest(&Emitter::AliasAndAnchorWithNull, "alias and anchor with null", + passed, total); + RunEmitterTest(&Emitter::AliasAndAnchorInFlow, "alias and anchor in flow", + passed, total); + RunEmitterTest(&Emitter::SimpleVerbatimTag, "simple verbatim tag", passed, + total); + RunEmitterTest(&Emitter::VerbatimTagInBlockSeq, "verbatim tag in block seq", + passed, total); + RunEmitterTest(&Emitter::VerbatimTagInFlowSeq, "verbatim tag in flow seq", + passed, total); + RunEmitterTest(&Emitter::VerbatimTagInFlowSeqWithNull, + "verbatim tag in flow seq with null", passed, total); + RunEmitterTest(&Emitter::VerbatimTagInBlockMap, "verbatim tag in block map", + passed, total); + RunEmitterTest(&Emitter::VerbatimTagInFlowMap, "verbatim tag in flow map", + passed, total); + RunEmitterTest(&Emitter::VerbatimTagInFlowMapWithNull, + "verbatim tag in flow map with null", passed, total); + RunEmitterTest(&Emitter::VerbatimTagWithEmptySeq, + "verbatim tag with empty seq", passed, total); + RunEmitterTest(&Emitter::VerbatimTagWithEmptyMap, + "verbatim tag with empty map", passed, total); + RunEmitterTest(&Emitter::VerbatimTagWithEmptySeqAndMap, + "verbatim tag with empty seq and map", passed, total); + RunEmitterTest(&Emitter::ByKindTagWithScalar, "by-kind tag with scalar", + passed, total); + RunEmitterTest(&Emitter::LocalTagWithScalar, "local tag with scalar", passed, + total); + RunEmitterTest(&Emitter::ComplexDoc, "complex doc", passed, total); + RunEmitterTest(&Emitter::STLContainers, "STL containers", passed, total); + RunEmitterTest(&Emitter::SimpleComment, "simple comment", passed, total); + RunEmitterTest(&Emitter::MultiLineComment, "multi-line comment", passed, + total); + RunEmitterTest(&Emitter::ComplexComments, "complex comments", passed, total); + RunEmitterTest(&Emitter::InitialComment, "initial comment", passed, total); + RunEmitterTest(&Emitter::InitialCommentWithDocIndicator, + "initial comment with doc indicator", passed, total); + RunEmitterTest(&Emitter::CommentInFlowSeq, "comment in flow seq", passed, + total); + RunEmitterTest(&Emitter::CommentInFlowMap, "comment in flow map", passed, + total); + RunEmitterTest(&Emitter::Indentation, "indentation", passed, total); + RunEmitterTest(&Emitter::SimpleGlobalSettings, "simple global settings", + passed, total); + RunEmitterTest(&Emitter::ComplexGlobalSettings, "complex global settings", + passed, total); + RunEmitterTest(&Emitter::Null, "null", passed, total); + RunEmitterTest(&Emitter::EscapedUnicode, "escaped unicode", passed, total); + RunEmitterTest(&Emitter::Unicode, "unicode", passed, total); + RunEmitterTest(&Emitter::DoubleQuotedUnicode, "double quoted unicode", passed, + total); + RunEmitterTest(&Emitter::UserType, "user type", passed, total); + RunEmitterTest(&Emitter::UserTypeInContainer, "user type in container", + passed, total); + RunEmitterTest(&Emitter::PointerToInt, "pointer to int", passed, total); + RunEmitterTest(&Emitter::PointerToUserType, "pointer to user type", passed, + total); + RunEmitterTest(&Emitter::NewlineAtEnd, "newline at end", passed, total); + RunEmitterTest(&Emitter::NewlineInBlockSequence, "newline in block sequence", + passed, total); + RunEmitterTest(&Emitter::NewlineInFlowSequence, "newline in flow sequence", + passed, total); + RunEmitterTest(&Emitter::NewlineInBlockMap, "newline in block map", passed, + total); + RunEmitterTest(&Emitter::NewlineInFlowMap, "newline in flow map", passed, + total); + RunEmitterTest(&Emitter::LotsOfNewlines, "lots of newlines", passed, total); + RunEmitterTest(&Emitter::Binary, "binary", passed, total); + RunEmitterTest(&Emitter::LongBinary, "long binary", passed, total); + RunEmitterTest(&Emitter::EmptyBinary, "empty binary", passed, total); + RunEmitterTest(&Emitter::ColonAtEndOfScalar, "colon at end of scalar", passed, + total); + RunEmitterTest(&Emitter::ColonAsScalar, "colon as scalar", passed, total); + RunEmitterTest(&Emitter::ColonAtEndOfScalarInFlow, + "colon at end of scalar in flow", passed, total); + RunEmitterTest(&Emitter::BoolFormatting, "bool formatting", passed, total); + RunEmitterTest(&Emitter::DocStartAndEnd, "doc start and end", passed, total); + RunEmitterTest(&Emitter::ImplicitDocStart, "implicit doc start", passed, + total); + RunEmitterTest(&Emitter::EmptyString, "empty string", passed, total); + RunEmitterTest(&Emitter::SingleChar, "single char", passed, total); + RunEmitterTest(&Emitter::DefaultPrecision, "default precision", passed, + total); + RunEmitterTest(&Emitter::SetPrecision, "set precision", passed, total); + RunEmitterTest(&Emitter::DashInBlockContext, "dash in block context", passed, + total); + RunEmitterTest(&Emitter::HexAndOct, "hex and oct", passed, total); + RunEmitterTest(&Emitter::CompactMapWithNewline, "compact map with newline", + passed, total); + RunEmitterTest(&Emitter::ForceSingleQuotedToDouble, + "force single quoted to double", passed, total); + + RunEmitterErrorTest(&Emitter::ExtraEndSeq, "extra EndSeq", passed, total); + RunEmitterErrorTest(&Emitter::ExtraEndMap, "extra EndMap", passed, total); + RunEmitterErrorTest(&Emitter::InvalidAnchor, "invalid anchor", passed, total); + RunEmitterErrorTest(&Emitter::InvalidAlias, "invalid alias", passed, total); + RunEmitterErrorTest(&Emitter::BadLocalTag, "bad local tag", passed, total); + + RunGenEmitterTests(passed, total); + + std::cout << "Emitter tests: " << passed << "/" << total << " passed\n"; + return passed == total; +} +} diff --git a/test/new-api/nodetests.cpp b/test/new-api/nodetests.cpp index cb6a0c5..8d77c6f 100644 --- a/test/new-api/nodetests.cpp +++ b/test/new-api/nodetests.cpp @@ -9,595 +9,587 @@ #endif namespace { - struct TEST { - TEST(): ok(false) {} - TEST(bool ok_): ok(ok_) {} - TEST(const char *error_): ok(false), error(error_) {} - TEST(const std::string& error_): ok(false), error(error_) {} - - bool ok; - std::string error; - }; +struct TEST { + TEST() : ok(false) {} + TEST(bool ok_) : ok(ok_) {} + TEST(const char* error_) : ok(false), error(error_) {} + TEST(const std::string& error_) : ok(false), error(error_) {} + + bool ok; + std::string error; +}; } -#define YAML_ASSERT(cond)\ - do {\ - if(!(cond))\ - return " Assert failed: " #cond;\ - } while(false) +#define YAML_ASSERT(cond) \ + do { \ + if (!(cond)) \ + return " Assert failed: " #cond; \ + } while (false) -#define YAML_ASSERT_THROWS(cond, exc)\ - do {\ - try {\ - (cond);\ - return " Expression did not throw: " #cond;\ - } catch(const exc&) {\ - } catch(const std::runtime_error& e) {\ - std::stringstream stream;\ - stream << " Expression threw runtime error ther than " #exc ":\n " #cond "\n " << e.what();\ - return stream.str();\ - } catch(...) {\ - return " Expression threw unknown exception, other than " #exc ":\n " #cond;\ - }\ - } while(false) +#define YAML_ASSERT_THROWS(cond, exc) \ + do { \ + try { \ + (cond); \ + return " Expression did not throw: " #cond; \ + } \ + catch (const exc&) { \ + } \ + catch (const std::runtime_error& e) { \ + std::stringstream stream; \ + stream << " Expression threw runtime error ther than " #exc \ + ":\n " #cond "\n " << e.what(); \ + return stream.str(); \ + } \ + catch (...) { \ + return " Expression threw unknown exception, other than " #exc \ + ":\n " #cond; \ + } \ + } while (false) -namespace Test -{ - namespace Node - { - TEST SimpleScalar() - { - YAML::Node node = YAML::Node("Hello, World!"); - YAML_ASSERT(node.IsScalar()); - YAML_ASSERT(node.as() == "Hello, World!"); - return true; - } - - TEST IntScalar() - { - YAML::Node node = YAML::Node(15); - YAML_ASSERT(node.IsScalar()); - YAML_ASSERT(node.as() == 15); - return true; - } - - TEST SimpleAppendSequence() - { - YAML::Node node; - node.push_back(10); - node.push_back("foo"); - node.push_back("monkey"); - YAML_ASSERT(node.IsSequence()); - YAML_ASSERT(node.size() == 3); - YAML_ASSERT(node[0].as() == 10); - YAML_ASSERT(node[1].as() == "foo"); - YAML_ASSERT(node[2].as() == "monkey"); - YAML_ASSERT(node.IsSequence()); - return true; - } - - TEST SimpleAssignSequence() - { - YAML::Node node; - node[0] = 10; - node[1] = "foo"; - node[2] = "monkey"; - YAML_ASSERT(node.IsSequence()); - YAML_ASSERT(node.size() == 3); - YAML_ASSERT(node[0].as() == 10); - YAML_ASSERT(node[1].as() == "foo"); - YAML_ASSERT(node[2].as() == "monkey"); - YAML_ASSERT(node.IsSequence()); - return true; - } - - TEST SimpleMap() - { - YAML::Node node; - node["key"] = "value"; - YAML_ASSERT(node.IsMap()); - YAML_ASSERT(node["key"].as() == "value"); - YAML_ASSERT(node.size() == 1); - return true; - } - - TEST MapWithUndefinedValues() - { - YAML::Node node; - node["key"] = "value"; - node["undefined"]; - YAML_ASSERT(node.IsMap()); - YAML_ASSERT(node["key"].as() == "value"); - YAML_ASSERT(node.size() == 1); - - node["undefined"] = "monkey"; - YAML_ASSERT(node["undefined"].as() == "monkey"); - YAML_ASSERT(node.size() == 2); - - return true; - } - - TEST MapIteratorWithUndefinedValues() - { - YAML::Node node; - node["key"] = "value"; - node["undefined"]; - - std::size_t count = 0; - for(YAML::const_iterator it=node.begin();it!=node.end();++it) - count++; - YAML_ASSERT(count == 1); - return true; - } - - TEST SimpleSubkeys() - { - YAML::Node node; - node["device"]["udid"] = "12345"; - node["device"]["name"] = "iPhone"; - node["device"]["os"] = "4.0"; - node["username"] = "monkey"; - YAML_ASSERT(node["device"]["udid"].as() == "12345"); - YAML_ASSERT(node["device"]["name"].as() == "iPhone"); - YAML_ASSERT(node["device"]["os"].as() == "4.0"); - YAML_ASSERT(node["username"].as() == "monkey"); - return true; - } - - TEST StdVector() - { - std::vector primes; - primes.push_back(2); - primes.push_back(3); - primes.push_back(5); - primes.push_back(7); - primes.push_back(11); - primes.push_back(13); - - YAML::Node node; - node["primes"] = primes; - YAML_ASSERT(node["primes"].as >() == primes); - return true; - } - - TEST StdList() - { - std::list primes; - primes.push_back(2); - primes.push_back(3); - primes.push_back(5); - primes.push_back(7); - primes.push_back(11); - primes.push_back(13); - - YAML::Node node; - node["primes"] = primes; - YAML_ASSERT(node["primes"].as >() == primes); - return true; - } - - TEST StdMap() - { - std::map squares; - squares[0] = 0; - squares[1] = 1; - squares[2] = 4; - squares[3] = 9; - squares[4] = 16; - - YAML::Node node; - node["squares"] = squares; - YAML_ASSERT((node["squares"].as >() == squares)); - return true; - } - - TEST StdPair() - { - std::pair p; - p.first = 5; - p.second = "five"; - - YAML::Node node; - node["pair"] = p; - YAML_ASSERT((node["pair"].as >() == p)); - return true; - } - - TEST SimpleAlias() - { - YAML::Node node; - node["foo"] = "value"; - node["bar"] = node["foo"]; - YAML_ASSERT(node["foo"].as() == "value"); - YAML_ASSERT(node["bar"].as() == "value"); - YAML_ASSERT(node["foo"] == node["bar"]); - YAML_ASSERT(node.size() == 2); - return true; - } - - TEST AliasAsKey() - { - YAML::Node node; - node["foo"] = "value"; - YAML::Node value = node["foo"]; - node[value] = "foo"; - YAML_ASSERT(node["foo"].as() == "value"); - YAML_ASSERT(node[value].as() == "foo"); - YAML_ASSERT(node["value"].as() == "foo"); - YAML_ASSERT(node.size() == 2); - return true; - } - - TEST SelfReferenceSequence() - { - YAML::Node node; - node[0] = node; - YAML_ASSERT(node.IsSequence()); - YAML_ASSERT(node.size() == 1); - YAML_ASSERT(node[0] == node); - YAML_ASSERT(node[0][0] == node); - YAML_ASSERT(node[0][0] == node[0]); - return true; - } - - TEST ValueSelfReferenceMap() - { - YAML::Node node; - node["key"] = node; - YAML_ASSERT(node.IsMap()); - YAML_ASSERT(node.size() == 1); - YAML_ASSERT(node["key"] == node); - YAML_ASSERT(node["key"]["key"] == node); - YAML_ASSERT(node["key"]["key"] == node["key"]); - return true; - } - - TEST KeySelfReferenceMap() - { - YAML::Node node; - node[node] = "value"; - YAML_ASSERT(node.IsMap()); - YAML_ASSERT(node.size() == 1); - YAML_ASSERT(node[node].as() == "value"); - return true; - } - - TEST SelfReferenceMap() - { - YAML::Node node; - node[node] = node; - YAML_ASSERT(node.IsMap()); - YAML_ASSERT(node.size() == 1); - YAML_ASSERT(node[node] == node); - YAML_ASSERT(node[node][node] == node); - YAML_ASSERT(node[node][node] == node[node]); - return true; - } - - TEST TempMapVariable() - { - YAML::Node node; - YAML::Node tmp = node["key"]; - tmp = "value"; - YAML_ASSERT(node.IsMap()); - YAML_ASSERT(node.size() == 1); - YAML_ASSERT(node["key"].as() == "value"); - return true; - } - - TEST TempMapVariableAlias() - { - YAML::Node node; - YAML::Node tmp = node["key"]; - tmp = node["other"]; - node["other"] = "value"; - YAML_ASSERT(node.IsMap()); - YAML_ASSERT(node.size() == 2); - YAML_ASSERT(node["key"].as() == "value"); - YAML_ASSERT(node["other"].as() == "value"); - YAML_ASSERT(node["other"] == node["key"]); - return true; - } - - TEST Bool() - { - YAML::Node node; - node[true] = false; - YAML_ASSERT(node.IsMap()); - YAML_ASSERT(node[true].as() == false); - return true; - } - - TEST AutoBoolConversion() - { - YAML::Node node; - node["foo"] = "bar"; - YAML_ASSERT(static_cast(node["foo"])); - YAML_ASSERT(!node["monkey"]); - YAML_ASSERT(!!node["foo"]); - return true; - } - - TEST Reassign() - { - YAML::Node node = YAML::Load("foo"); - node = YAML::Node(); - return true; - } - - TEST FallbackValues() - { - YAML::Node node = YAML::Load("foo: bar\nx: 2"); - YAML_ASSERT(node["foo"].as() == "bar"); - YAML_ASSERT(node["foo"].as("hello") == "bar"); - YAML_ASSERT(node["baz"].as("hello") == "hello"); - YAML_ASSERT(node["x"].as() == 2); - YAML_ASSERT(node["x"].as(5) == 2); - YAML_ASSERT(node["y"].as(5) == 5); - return true; - } - - TEST NumericConversion() - { - YAML::Node node = YAML::Load("[1.5, 1, .nan, .inf, -.inf, 0x15, 015]"); - YAML_ASSERT(node[0].as() == 1.5f); - YAML_ASSERT(node[0].as() == 1.5); - YAML_ASSERT_THROWS(node[0].as(), YAML::TypedBadConversion); - YAML_ASSERT(node[1].as() == 1); - YAML_ASSERT(node[1].as() == 1.0f); - YAML_ASSERT(node[2].as() != node[2].as()); - YAML_ASSERT(node[3].as() == std::numeric_limits::infinity()); - YAML_ASSERT(node[4].as() == -std::numeric_limits::infinity()); - YAML_ASSERT(node[5].as() == 21); - YAML_ASSERT(node[6].as() == 13); - return true; - } - - TEST Binary() - { - YAML::Node node = YAML::Load("[!!binary \"SGVsbG8sIFdvcmxkIQ==\", !!binary \"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4K\"]"); - YAML_ASSERT(node[0].as() == YAML::Binary(reinterpret_cast("Hello, World!"), 13)); - YAML_ASSERT(node[1].as() == YAML::Binary(reinterpret_cast("Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.\n"), 270)); - return true; - } - - TEST IterateSequence() - { - YAML::Node node = YAML::Load("[1, 3, 5, 7]"); - int seq[] = {1, 3, 5, 7}; - int i=0; - for(YAML::const_iterator it=node.begin();it!=node.end();++it) { - YAML_ASSERT(i < 4); - int x = seq[i++]; - YAML_ASSERT(it->as() == x); - } - YAML_ASSERT(i == 4); - return true; - } - - TEST IterateMap() - { - YAML::Node node = YAML::Load("{a: A, b: B, c: C}"); - int i=0; - for(YAML::const_iterator it=node.begin();it!=node.end();++it) { - YAML_ASSERT(i < 3); - i++; - YAML_ASSERT(it->first.as() + 'A' - 'a' == it->second.as()); - } - YAML_ASSERT(i == 3); - return true; - } - -#ifdef BOOST_FOREACH - TEST ForEach() - { - YAML::Node node = YAML::Load("[1, 3, 5, 7]"); - int seq[] = {1, 3, 5, 7}; - int i = 0; - BOOST_FOREACH(const YAML::Node &item, node) { - int x = seq[i++]; - YAML_ASSERT(item.as() == x); - } - return true; - } - - TEST ForEachMap() - { - YAML::Node node = YAML::Load("{a: A, b: B, c: C}"); - BOOST_FOREACH(const YAML::const_iterator::value_type &p, node) { - YAML_ASSERT(p.first.as() + 'A' - 'a' == p.second.as()); - } - return true; - } -#endif - - TEST CloneScalar() - { - YAML::Node node = YAML::Load("!foo monkey"); - YAML::Node clone = Clone(node); - YAML_ASSERT(!(node == clone)); - YAML_ASSERT(node.as() == clone.as()); - YAML_ASSERT(node.Tag() == clone.Tag()); - return true; - } - - TEST CloneSeq() - { - YAML::Node node = YAML::Load("[1, 3, 5, 7]"); - YAML::Node clone = Clone(node); - YAML_ASSERT(!(node == clone)); - YAML_ASSERT(clone.Type() == YAML::NodeType::Sequence); - YAML_ASSERT(node.size() == clone.size()); - for(std::size_t i=0;i() == clone[i].as()); - return true; - } - - TEST CloneMap() - { - YAML::Node node = YAML::Load("{foo: bar}"); - YAML::Node clone = Clone(node); - YAML_ASSERT(!(node == clone)); - YAML_ASSERT(clone.Type() == YAML::NodeType::Map); - YAML_ASSERT(node.size() == clone.size()); - YAML_ASSERT(node["foo"].as() == clone["foo"].as()); - return true; - } - - TEST CloneAlias() - { - YAML::Node node = YAML::Load("&foo [*foo]"); - YAML::Node clone = Clone(node); - YAML_ASSERT(!(node == clone)); - YAML_ASSERT(clone.Type() == YAML::NodeType::Sequence); - YAML_ASSERT(node.size() == clone.size()); - YAML_ASSERT(clone == clone[0]); - return true; - } - - TEST ForceInsertIntoMap() - { - YAML::Node node; - node["a"] = "b"; - node.force_insert("x", "y"); - node.force_insert("a", 5); - YAML_ASSERT(node.size() == 3); - YAML_ASSERT(node.Type() == YAML::NodeType::Map); - bool ab = false; - bool a5 = false; - bool xy = false; - for(YAML::const_iterator it=node.begin();it!=node.end();++it) { - if(it->first.as() == "a") { - if(it->second.as() == "b") - ab = true; - else if(it->second.as() == "5") - a5 = true; - } else if(it->first.as() == "x" && it->second.as() == "y") - xy = true; - } - YAML_ASSERT(ab); - YAML_ASSERT(a5); - YAML_ASSERT(xy); - return true; - } - - TEST ResetNode() - { - YAML::Node node = YAML::Load("[1, 2, 3]"); - YAML_ASSERT(!node.IsNull()); - YAML::Node other = node; - node.reset(); - YAML_ASSERT(node.IsNull()); - YAML_ASSERT(!other.IsNull()); - node.reset(other); - YAML_ASSERT(!node.IsNull()); - YAML_ASSERT(other == node); - return true; - } - - TEST DereferenceIteratorError() - { - YAML::Node node = YAML::Load("[{a: b}, 1, 2]"); - YAML_ASSERT_THROWS(node.begin()->first.as(), YAML::InvalidNode); - YAML_ASSERT((*node.begin()).IsMap() == true); - YAML_ASSERT(node.begin()->IsMap() == true); - YAML_ASSERT_THROWS((*node.begin()->begin()).IsDefined(), YAML::InvalidNode); - YAML_ASSERT_THROWS(node.begin()->begin()->IsDefined(), YAML::InvalidNode); - return true; - } - - TEST FloatingPrecision() - { - const double x = 0.123456789; - YAML::Node node = YAML::Node(x); - YAML_ASSERT(node.as() == x); - return true; - } - - TEST EmitEmptyNode() - { - YAML::Node node; - YAML::Emitter emitter; - emitter << node; - YAML_ASSERT(std::string(emitter.c_str()) == ""); - return true; - } - - TEST SpaceChar() - { - YAML::Node node = YAML::Node(' '); - YAML_ASSERT(node.as() == ' '); - return true; - } - } - - void RunNodeTest(TEST (*test)(), const std::string& name, int& passed, int& total) { - TEST ret; - try { - ret = test(); - } catch(const std::exception& e) { - ret.ok = false; - ret.error = e.what(); - } - if(ret.ok) { - passed++; - } else { - std::cout << "Node test failed: " << name << "\n"; - if(ret.error != "") - std::cout << ret.error << "\n"; - } - total++; - } - - bool RunNodeTests() - { - int passed = 0; - int total = 0; - - RunNodeTest(&Node::SimpleScalar, "simple scalar", passed, total); - RunNodeTest(&Node::IntScalar, "int scalar", passed, total); - RunNodeTest(&Node::SimpleAppendSequence, "simple append sequence", passed, total); - RunNodeTest(&Node::SimpleAssignSequence, "simple assign sequence", passed, total); - RunNodeTest(&Node::SimpleMap, "simple map", passed, total); - RunNodeTest(&Node::MapWithUndefinedValues, "map with undefined values", passed, total); - RunNodeTest(&Node::MapIteratorWithUndefinedValues, "map iterator with undefined values", passed, total); - RunNodeTest(&Node::SimpleSubkeys, "simple subkey", passed, total); - RunNodeTest(&Node::StdVector, "std::vector", passed, total); - RunNodeTest(&Node::StdList, "std::list", passed, total); - RunNodeTest(&Node::StdMap, "std::map", passed, total); - RunNodeTest(&Node::StdPair, "std::pair", passed, total); - RunNodeTest(&Node::SimpleAlias, "simple alias", passed, total); - RunNodeTest(&Node::AliasAsKey, "alias as key", passed, total); - RunNodeTest(&Node::SelfReferenceSequence, "self reference sequence", passed, total); - RunNodeTest(&Node::ValueSelfReferenceMap, "value self reference map", passed, total); - RunNodeTest(&Node::KeySelfReferenceMap, "key self reference map", passed, total); - RunNodeTest(&Node::SelfReferenceMap, "self reference map", passed, total); - RunNodeTest(&Node::TempMapVariable, "temp map variable", passed, total); - RunNodeTest(&Node::TempMapVariableAlias, "temp map variable alias", passed, total); - RunNodeTest(&Node::Bool, "bool", passed, total); - RunNodeTest(&Node::AutoBoolConversion, "auto bool conversion", passed, total); - RunNodeTest(&Node::Reassign, "reassign", passed, total); - RunNodeTest(&Node::FallbackValues, "fallback values", passed, total); - RunNodeTest(&Node::NumericConversion, "numeric conversion", passed, total); - RunNodeTest(&Node::Binary, "binary", passed, total); - RunNodeTest(&Node::IterateSequence, "iterate sequence", passed, total); - RunNodeTest(&Node::IterateMap, "iterate map", passed, total); -#ifdef BOOST_FOREACH - RunNodeTest(&Node::ForEach, "for each", passed, total); - RunNodeTest(&Node::ForEachMap, "for each map", passed, total); -#endif - RunNodeTest(&Node::CloneScalar, "clone scalar", passed, total); - RunNodeTest(&Node::CloneSeq, "clone seq", passed, total); - RunNodeTest(&Node::CloneMap, "clone map", passed, total); - RunNodeTest(&Node::CloneAlias, "clone alias", passed, total); - RunNodeTest(&Node::ForceInsertIntoMap, "force insert into map", passed, total); - RunNodeTest(&Node::ResetNode, "reset node", passed, total); - RunNodeTest(&Node::DereferenceIteratorError, "dereference iterator error", passed, total); - RunNodeTest(&Node::FloatingPrecision, "floating precision", passed, total); - RunNodeTest(&Node::EmitEmptyNode, "emit empty node", passed, total); - RunNodeTest(&Node::SpaceChar, "space char", passed, total); - - std::cout << "Node tests: " << passed << "/" << total << " passed\n"; - return passed == total; - } +namespace Test { +namespace Node { +TEST SimpleScalar() { + YAML::Node node = YAML::Node("Hello, World!"); + YAML_ASSERT(node.IsScalar()); + YAML_ASSERT(node.as() == "Hello, World!"); + return true; +} + +TEST IntScalar() { + YAML::Node node = YAML::Node(15); + YAML_ASSERT(node.IsScalar()); + YAML_ASSERT(node.as() == 15); + return true; +} + +TEST SimpleAppendSequence() { + YAML::Node node; + node.push_back(10); + node.push_back("foo"); + node.push_back("monkey"); + YAML_ASSERT(node.IsSequence()); + YAML_ASSERT(node.size() == 3); + YAML_ASSERT(node[0].as() == 10); + YAML_ASSERT(node[1].as() == "foo"); + YAML_ASSERT(node[2].as() == "monkey"); + YAML_ASSERT(node.IsSequence()); + return true; +} + +TEST SimpleAssignSequence() { + YAML::Node node; + node[0] = 10; + node[1] = "foo"; + node[2] = "monkey"; + YAML_ASSERT(node.IsSequence()); + YAML_ASSERT(node.size() == 3); + YAML_ASSERT(node[0].as() == 10); + YAML_ASSERT(node[1].as() == "foo"); + YAML_ASSERT(node[2].as() == "monkey"); + YAML_ASSERT(node.IsSequence()); + return true; +} + +TEST SimpleMap() { + YAML::Node node; + node["key"] = "value"; + YAML_ASSERT(node.IsMap()); + YAML_ASSERT(node["key"].as() == "value"); + YAML_ASSERT(node.size() == 1); + return true; +} + +TEST MapWithUndefinedValues() { + YAML::Node node; + node["key"] = "value"; + node["undefined"]; + YAML_ASSERT(node.IsMap()); + YAML_ASSERT(node["key"].as() == "value"); + YAML_ASSERT(node.size() == 1); + + node["undefined"] = "monkey"; + YAML_ASSERT(node["undefined"].as() == "monkey"); + YAML_ASSERT(node.size() == 2); + + return true; +} + +TEST MapIteratorWithUndefinedValues() { + YAML::Node node; + node["key"] = "value"; + node["undefined"]; + + std::size_t count = 0; + for (YAML::const_iterator it = node.begin(); it != node.end(); ++it) + count++; + YAML_ASSERT(count == 1); + return true; +} + +TEST SimpleSubkeys() { + YAML::Node node; + node["device"]["udid"] = "12345"; + node["device"]["name"] = "iPhone"; + node["device"]["os"] = "4.0"; + node["username"] = "monkey"; + YAML_ASSERT(node["device"]["udid"].as() == "12345"); + YAML_ASSERT(node["device"]["name"].as() == "iPhone"); + YAML_ASSERT(node["device"]["os"].as() == "4.0"); + YAML_ASSERT(node["username"].as() == "monkey"); + return true; +} + +TEST StdVector() { + std::vector primes; + primes.push_back(2); + primes.push_back(3); + primes.push_back(5); + primes.push_back(7); + primes.push_back(11); + primes.push_back(13); + + YAML::Node node; + node["primes"] = primes; + YAML_ASSERT(node["primes"].as >() == primes); + return true; +} + +TEST StdList() { + std::list primes; + primes.push_back(2); + primes.push_back(3); + primes.push_back(5); + primes.push_back(7); + primes.push_back(11); + primes.push_back(13); + + YAML::Node node; + node["primes"] = primes; + YAML_ASSERT(node["primes"].as >() == primes); + return true; +} + +TEST StdMap() { + std::map squares; + squares[0] = 0; + squares[1] = 1; + squares[2] = 4; + squares[3] = 9; + squares[4] = 16; + + YAML::Node node; + node["squares"] = squares; + YAML_ASSERT((node["squares"].as >() == squares)); + return true; +} + +TEST StdPair() { + std::pair p; + p.first = 5; + p.second = "five"; + + YAML::Node node; + node["pair"] = p; + YAML_ASSERT((node["pair"].as >() == p)); + return true; +} + +TEST SimpleAlias() { + YAML::Node node; + node["foo"] = "value"; + node["bar"] = node["foo"]; + YAML_ASSERT(node["foo"].as() == "value"); + YAML_ASSERT(node["bar"].as() == "value"); + YAML_ASSERT(node["foo"] == node["bar"]); + YAML_ASSERT(node.size() == 2); + return true; +} + +TEST AliasAsKey() { + YAML::Node node; + node["foo"] = "value"; + YAML::Node value = node["foo"]; + node[value] = "foo"; + YAML_ASSERT(node["foo"].as() == "value"); + YAML_ASSERT(node[value].as() == "foo"); + YAML_ASSERT(node["value"].as() == "foo"); + YAML_ASSERT(node.size() == 2); + return true; +} + +TEST SelfReferenceSequence() { + YAML::Node node; + node[0] = node; + YAML_ASSERT(node.IsSequence()); + YAML_ASSERT(node.size() == 1); + YAML_ASSERT(node[0] == node); + YAML_ASSERT(node[0][0] == node); + YAML_ASSERT(node[0][0] == node[0]); + return true; +} + +TEST ValueSelfReferenceMap() { + YAML::Node node; + node["key"] = node; + YAML_ASSERT(node.IsMap()); + YAML_ASSERT(node.size() == 1); + YAML_ASSERT(node["key"] == node); + YAML_ASSERT(node["key"]["key"] == node); + YAML_ASSERT(node["key"]["key"] == node["key"]); + return true; +} + +TEST KeySelfReferenceMap() { + YAML::Node node; + node[node] = "value"; + YAML_ASSERT(node.IsMap()); + YAML_ASSERT(node.size() == 1); + YAML_ASSERT(node[node].as() == "value"); + return true; +} + +TEST SelfReferenceMap() { + YAML::Node node; + node[node] = node; + YAML_ASSERT(node.IsMap()); + YAML_ASSERT(node.size() == 1); + YAML_ASSERT(node[node] == node); + YAML_ASSERT(node[node][node] == node); + YAML_ASSERT(node[node][node] == node[node]); + return true; +} + +TEST TempMapVariable() { + YAML::Node node; + YAML::Node tmp = node["key"]; + tmp = "value"; + YAML_ASSERT(node.IsMap()); + YAML_ASSERT(node.size() == 1); + YAML_ASSERT(node["key"].as() == "value"); + return true; +} + +TEST TempMapVariableAlias() { + YAML::Node node; + YAML::Node tmp = node["key"]; + tmp = node["other"]; + node["other"] = "value"; + YAML_ASSERT(node.IsMap()); + YAML_ASSERT(node.size() == 2); + YAML_ASSERT(node["key"].as() == "value"); + YAML_ASSERT(node["other"].as() == "value"); + YAML_ASSERT(node["other"] == node["key"]); + return true; +} + +TEST Bool() { + YAML::Node node; + node[true] = false; + YAML_ASSERT(node.IsMap()); + YAML_ASSERT(node[true].as() == false); + return true; +} + +TEST AutoBoolConversion() { + YAML::Node node; + node["foo"] = "bar"; + YAML_ASSERT(static_cast(node["foo"])); + YAML_ASSERT(!node["monkey"]); + YAML_ASSERT(!!node["foo"]); + return true; +} + +TEST Reassign() { + YAML::Node node = YAML::Load("foo"); + node = YAML::Node(); + return true; +} + +TEST FallbackValues() { + YAML::Node node = YAML::Load("foo: bar\nx: 2"); + YAML_ASSERT(node["foo"].as() == "bar"); + YAML_ASSERT(node["foo"].as("hello") == "bar"); + YAML_ASSERT(node["baz"].as("hello") == "hello"); + YAML_ASSERT(node["x"].as() == 2); + YAML_ASSERT(node["x"].as(5) == 2); + YAML_ASSERT(node["y"].as(5) == 5); + return true; +} + +TEST NumericConversion() { + YAML::Node node = YAML::Load("[1.5, 1, .nan, .inf, -.inf, 0x15, 015]"); + YAML_ASSERT(node[0].as() == 1.5f); + YAML_ASSERT(node[0].as() == 1.5); + YAML_ASSERT_THROWS(node[0].as(), YAML::TypedBadConversion); + YAML_ASSERT(node[1].as() == 1); + YAML_ASSERT(node[1].as() == 1.0f); + YAML_ASSERT(node[2].as() != node[2].as()); + YAML_ASSERT(node[3].as() == std::numeric_limits::infinity()); + YAML_ASSERT(node[4].as() == -std::numeric_limits::infinity()); + YAML_ASSERT(node[5].as() == 21); + YAML_ASSERT(node[6].as() == 13); + return true; +} + +TEST Binary() { + YAML::Node node = YAML::Load( + "[!!binary \"SGVsbG8sIFdvcmxkIQ==\", !!binary " + "\"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieS" + "B0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIG" + "x1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbi" + "B0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZG" + "dlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS" + "4K\"]"); + YAML_ASSERT(node[0].as() == + YAML::Binary( + reinterpret_cast("Hello, World!"), 13)); + YAML_ASSERT(node[1].as() == + YAML::Binary(reinterpret_cast( + "Man is distinguished, not only by his reason, " + "but by this singular passion from other " + "animals, which is a lust of the mind, that by " + "a perseverance of delight in the continued and " + "indefatigable generation of knowledge, exceeds " + "the short vehemence of any carnal pleasure.\n"), + 270)); + return true; +} + +TEST IterateSequence() { + YAML::Node node = YAML::Load("[1, 3, 5, 7]"); + int seq[] = {1, 3, 5, 7}; + int i = 0; + for (YAML::const_iterator it = node.begin(); it != node.end(); ++it) { + YAML_ASSERT(i < 4); + int x = seq[i++]; + YAML_ASSERT(it->as() == x); + } + YAML_ASSERT(i == 4); + return true; +} + +TEST IterateMap() { + YAML::Node node = YAML::Load("{a: A, b: B, c: C}"); + int i = 0; + for (YAML::const_iterator it = node.begin(); it != node.end(); ++it) { + YAML_ASSERT(i < 3); + i++; + YAML_ASSERT(it->first.as() + 'A' - 'a' == it->second.as()); + } + YAML_ASSERT(i == 3); + return true; +} + +#ifdef BOOST_FOREACH +TEST ForEach() { + YAML::Node node = YAML::Load("[1, 3, 5, 7]"); + int seq[] = {1, 3, 5, 7}; + int i = 0; + BOOST_FOREACH(const YAML::Node & item, node) { + int x = seq[i++]; + YAML_ASSERT(item.as() == x); + } + return true; +} + +TEST ForEachMap() { + YAML::Node node = YAML::Load("{a: A, b: B, c: C}"); + BOOST_FOREACH(const YAML::const_iterator::value_type & p, node) { + YAML_ASSERT(p.first.as() + 'A' - 'a' == p.second.as()); + } + return true; +} +#endif + +TEST CloneScalar() { + YAML::Node node = YAML::Load("!foo monkey"); + YAML::Node clone = Clone(node); + YAML_ASSERT(!(node == clone)); + YAML_ASSERT(node.as() == clone.as()); + YAML_ASSERT(node.Tag() == clone.Tag()); + return true; +} + +TEST CloneSeq() { + YAML::Node node = YAML::Load("[1, 3, 5, 7]"); + YAML::Node clone = Clone(node); + YAML_ASSERT(!(node == clone)); + YAML_ASSERT(clone.Type() == YAML::NodeType::Sequence); + YAML_ASSERT(node.size() == clone.size()); + for (std::size_t i = 0; i < node.size(); i++) + YAML_ASSERT(node[i].as() == clone[i].as()); + return true; +} + +TEST CloneMap() { + YAML::Node node = YAML::Load("{foo: bar}"); + YAML::Node clone = Clone(node); + YAML_ASSERT(!(node == clone)); + YAML_ASSERT(clone.Type() == YAML::NodeType::Map); + YAML_ASSERT(node.size() == clone.size()); + YAML_ASSERT(node["foo"].as() == clone["foo"].as()); + return true; +} + +TEST CloneAlias() { + YAML::Node node = YAML::Load("&foo [*foo]"); + YAML::Node clone = Clone(node); + YAML_ASSERT(!(node == clone)); + YAML_ASSERT(clone.Type() == YAML::NodeType::Sequence); + YAML_ASSERT(node.size() == clone.size()); + YAML_ASSERT(clone == clone[0]); + return true; +} + +TEST ForceInsertIntoMap() { + YAML::Node node; + node["a"] = "b"; + node.force_insert("x", "y"); + node.force_insert("a", 5); + YAML_ASSERT(node.size() == 3); + YAML_ASSERT(node.Type() == YAML::NodeType::Map); + bool ab = false; + bool a5 = false; + bool xy = false; + for (YAML::const_iterator it = node.begin(); it != node.end(); ++it) { + if (it->first.as() == "a") { + if (it->second.as() == "b") + ab = true; + else if (it->second.as() == "5") + a5 = true; + } else if (it->first.as() == "x" && + it->second.as() == "y") + xy = true; + } + YAML_ASSERT(ab); + YAML_ASSERT(a5); + YAML_ASSERT(xy); + return true; +} + +TEST ResetNode() { + YAML::Node node = YAML::Load("[1, 2, 3]"); + YAML_ASSERT(!node.IsNull()); + YAML::Node other = node; + node.reset(); + YAML_ASSERT(node.IsNull()); + YAML_ASSERT(!other.IsNull()); + node.reset(other); + YAML_ASSERT(!node.IsNull()); + YAML_ASSERT(other == node); + return true; +} + +TEST DereferenceIteratorError() { + YAML::Node node = YAML::Load("[{a: b}, 1, 2]"); + YAML_ASSERT_THROWS(node.begin()->first.as(), YAML::InvalidNode); + YAML_ASSERT((*node.begin()).IsMap() == true); + YAML_ASSERT(node.begin()->IsMap() == true); + YAML_ASSERT_THROWS((*node.begin()->begin()).IsDefined(), YAML::InvalidNode); + YAML_ASSERT_THROWS(node.begin()->begin()->IsDefined(), YAML::InvalidNode); + return true; +} + +TEST FloatingPrecision() { + const double x = 0.123456789; + YAML::Node node = YAML::Node(x); + YAML_ASSERT(node.as() == x); + return true; +} + +TEST EmitEmptyNode() { + YAML::Node node; + YAML::Emitter emitter; + emitter << node; + YAML_ASSERT(std::string(emitter.c_str()) == ""); + return true; +} + +TEST SpaceChar() { + YAML::Node node = YAML::Node(' '); + YAML_ASSERT(node.as() == ' '); + return true; +} +} + +void RunNodeTest(TEST (*test)(), const std::string& name, int& passed, + int& total) { + TEST ret; + try { + ret = test(); + } + catch (const std::exception& e) { + ret.ok = false; + ret.error = e.what(); + } + if (ret.ok) { + passed++; + } else { + std::cout << "Node test failed: " << name << "\n"; + if (ret.error != "") + std::cout << ret.error << "\n"; + } + total++; +} + +bool RunNodeTests() { + int passed = 0; + int total = 0; + + RunNodeTest(&Node::SimpleScalar, "simple scalar", passed, total); + RunNodeTest(&Node::IntScalar, "int scalar", passed, total); + RunNodeTest(&Node::SimpleAppendSequence, "simple append sequence", passed, + total); + RunNodeTest(&Node::SimpleAssignSequence, "simple assign sequence", passed, + total); + RunNodeTest(&Node::SimpleMap, "simple map", passed, total); + RunNodeTest(&Node::MapWithUndefinedValues, "map with undefined values", + passed, total); + RunNodeTest(&Node::MapIteratorWithUndefinedValues, + "map iterator with undefined values", passed, total); + RunNodeTest(&Node::SimpleSubkeys, "simple subkey", passed, total); + RunNodeTest(&Node::StdVector, "std::vector", passed, total); + RunNodeTest(&Node::StdList, "std::list", passed, total); + RunNodeTest(&Node::StdMap, "std::map", passed, total); + RunNodeTest(&Node::StdPair, "std::pair", passed, total); + RunNodeTest(&Node::SimpleAlias, "simple alias", passed, total); + RunNodeTest(&Node::AliasAsKey, "alias as key", passed, total); + RunNodeTest(&Node::SelfReferenceSequence, "self reference sequence", passed, + total); + RunNodeTest(&Node::ValueSelfReferenceMap, "value self reference map", passed, + total); + RunNodeTest(&Node::KeySelfReferenceMap, "key self reference map", passed, + total); + RunNodeTest(&Node::SelfReferenceMap, "self reference map", passed, total); + RunNodeTest(&Node::TempMapVariable, "temp map variable", passed, total); + RunNodeTest(&Node::TempMapVariableAlias, "temp map variable alias", passed, + total); + RunNodeTest(&Node::Bool, "bool", passed, total); + RunNodeTest(&Node::AutoBoolConversion, "auto bool conversion", passed, total); + RunNodeTest(&Node::Reassign, "reassign", passed, total); + RunNodeTest(&Node::FallbackValues, "fallback values", passed, total); + RunNodeTest(&Node::NumericConversion, "numeric conversion", passed, total); + RunNodeTest(&Node::Binary, "binary", passed, total); + RunNodeTest(&Node::IterateSequence, "iterate sequence", passed, total); + RunNodeTest(&Node::IterateMap, "iterate map", passed, total); +#ifdef BOOST_FOREACH + RunNodeTest(&Node::ForEach, "for each", passed, total); + RunNodeTest(&Node::ForEachMap, "for each map", passed, total); +#endif + RunNodeTest(&Node::CloneScalar, "clone scalar", passed, total); + RunNodeTest(&Node::CloneSeq, "clone seq", passed, total); + RunNodeTest(&Node::CloneMap, "clone map", passed, total); + RunNodeTest(&Node::CloneAlias, "clone alias", passed, total); + RunNodeTest(&Node::ForceInsertIntoMap, "force insert into map", passed, + total); + RunNodeTest(&Node::ResetNode, "reset node", passed, total); + RunNodeTest(&Node::DereferenceIteratorError, "dereference iterator error", + passed, total); + RunNodeTest(&Node::FloatingPrecision, "floating precision", passed, total); + RunNodeTest(&Node::EmitEmptyNode, "emit empty node", passed, total); + RunNodeTest(&Node::SpaceChar, "space char", passed, total); + + std::cout << "Node tests: " << passed << "/" << total << " passed\n"; + return passed == total; +} } diff --git a/test/new-api/parsertests.cpp b/test/new-api/parsertests.cpp index 1d50ca6..2662ab4 100644 --- a/test/new-api/parsertests.cpp +++ b/test/new-api/parsertests.cpp @@ -1,8 +1,5 @@ #include "parsertests.h" namespace Test { - bool RunParserTests() - { - return true; - } +bool RunParserTests() { return true; } } diff --git a/test/new-api/spectests.cpp b/test/new-api/spectests.cpp index 328ae7a..52b4e7e 100644 --- a/test/new-api/spectests.cpp +++ b/test/new-api/spectests.cpp @@ -3,1363 +3,1423 @@ #include "yaml-cpp/yaml.h" #include -#define YAML_ASSERT(cond) do { if(!(cond)) return " Assert failed: " #cond; } while(false) +#define YAML_ASSERT(cond) \ + do { \ + if (!(cond)) \ + return " Assert failed: " #cond; \ + } while (false) -namespace Test -{ - namespace Spec - { - // 2.1 - TEST SeqScalars() { - YAML::Node doc = YAML::Load(ex2_1); - YAML_ASSERT(doc.IsSequence()); - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc[0].as() == "Mark McGwire"); - YAML_ASSERT(doc[1].as() == "Sammy Sosa"); - YAML_ASSERT(doc[2].as() == "Ken Griffey"); - return true; - } - - // 2.2 - TEST MappingScalarsToScalars() { - YAML::Node doc = YAML::Load(ex2_2); - YAML_ASSERT(doc.IsMap()); - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc["hr"].as() == "65"); - YAML_ASSERT(doc["avg"].as() == "0.278"); - YAML_ASSERT(doc["rbi"].as() == "147"); - return true; - } - - // 2.3 - TEST MappingScalarsToSequences() { - YAML::Node doc = YAML::Load(ex2_3); - YAML_ASSERT(doc.IsMap()); - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc["american"].size() == 3); - YAML_ASSERT(doc["american"][0].as() == "Boston Red Sox"); - YAML_ASSERT(doc["american"][1].as() == "Detroit Tigers"); - YAML_ASSERT(doc["american"][2].as() == "New York Yankees"); - YAML_ASSERT(doc["national"].size() == 3); - YAML_ASSERT(doc["national"][0].as() == "New York Mets"); - YAML_ASSERT(doc["national"][1].as() == "Chicago Cubs"); - YAML_ASSERT(doc["national"][2].as() == "Atlanta Braves"); - return true; - } - - // 2.4 - TEST SequenceOfMappings() { - YAML::Node doc = YAML::Load(ex2_4); - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc[0].size() == 3); - YAML_ASSERT(doc[0]["name"].as() == "Mark McGwire"); - YAML_ASSERT(doc[0]["hr"].as() == "65"); - YAML_ASSERT(doc[0]["avg"].as() == "0.278"); - YAML_ASSERT(doc[1].size() == 3); - YAML_ASSERT(doc[1]["name"].as() == "Sammy Sosa"); - YAML_ASSERT(doc[1]["hr"].as() == "63"); - YAML_ASSERT(doc[1]["avg"].as() == "0.288"); - return true; - } - - // 2.5 - TEST SequenceOfSequences() { - YAML::Node doc = YAML::Load(ex2_5); - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc[0].size() == 3); - YAML_ASSERT(doc[0][0].as() == "name"); - YAML_ASSERT(doc[0][1].as() == "hr"); - YAML_ASSERT(doc[0][2].as() == "avg"); - YAML_ASSERT(doc[1].size() == 3); - YAML_ASSERT(doc[1][0].as() == "Mark McGwire"); - YAML_ASSERT(doc[1][1].as() == "65"); - YAML_ASSERT(doc[1][2].as() == "0.278"); - YAML_ASSERT(doc[2].size() == 3); - YAML_ASSERT(doc[2][0].as() == "Sammy Sosa"); - YAML_ASSERT(doc[2][1].as() == "63"); - YAML_ASSERT(doc[2][2].as() == "0.288"); - return true; - } - - // 2.6 - TEST MappingOfMappings() { - YAML::Node doc = YAML::Load(ex2_6); - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc["Mark McGwire"].size() == 2); - YAML_ASSERT(doc["Mark McGwire"]["hr"].as() == "65"); - YAML_ASSERT(doc["Mark McGwire"]["avg"].as() == "0.278"); - YAML_ASSERT(doc["Sammy Sosa"].size() == 2); - YAML_ASSERT(doc["Sammy Sosa"]["hr"].as() == "63"); - YAML_ASSERT(doc["Sammy Sosa"]["avg"].as() == "0.288"); - return true; - } - - // 2.7 - TEST TwoDocumentsInAStream() { - std::vector docs = YAML::LoadAll(ex2_7); - YAML_ASSERT(docs.size() == 2); - - { - YAML::Node doc = docs[0]; - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc[0].as() == "Mark McGwire"); - YAML_ASSERT(doc[1].as() == "Sammy Sosa"); - YAML_ASSERT(doc[2].as() == "Ken Griffey"); - } - - { - YAML::Node doc = docs[1]; - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc[0].as() == "Chicago Cubs"); - YAML_ASSERT(doc[1].as() == "St Louis Cardinals"); - } - return true; - } - - // 2.8 - TEST PlayByPlayFeed() { - std::vector docs = YAML::LoadAll(ex2_8); - YAML_ASSERT(docs.size() == 2); - - { - YAML::Node doc = docs[0]; - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc["time"].as() == "20:03:20"); - YAML_ASSERT(doc["player"].as() == "Sammy Sosa"); - YAML_ASSERT(doc["action"].as() == "strike (miss)"); - } - - { - YAML::Node doc = docs[1]; - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc["time"].as() == "20:03:47"); - YAML_ASSERT(doc["player"].as() == "Sammy Sosa"); - YAML_ASSERT(doc["action"].as() == "grand slam"); - } - return true; - } - - // 2.9 - TEST SingleDocumentWithTwoComments() { - YAML::Node doc = YAML::Load(ex2_9); - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc["hr"].size() == 2); - YAML_ASSERT(doc["hr"][0].as() == "Mark McGwire"); - YAML_ASSERT(doc["hr"][1].as() == "Sammy Sosa"); - YAML_ASSERT(doc["rbi"].size() == 2); - YAML_ASSERT(doc["rbi"][0].as() == "Sammy Sosa"); - YAML_ASSERT(doc["rbi"][1].as() == "Ken Griffey"); - return true; - } - - // 2.10 - TEST SimpleAnchor() { - YAML::Node doc = YAML::Load(ex2_10); - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc["hr"].size() == 2); - YAML_ASSERT(doc["hr"][0].as() == "Mark McGwire"); - YAML_ASSERT(doc["hr"][1].as() == "Sammy Sosa"); - YAML_ASSERT(doc["rbi"].size() == 2); - YAML_ASSERT(doc["rbi"][0].as() == "Sammy Sosa"); - YAML_ASSERT(doc["rbi"][1].as() == "Ken Griffey"); - return true; - } - - // 2.11 - TEST MappingBetweenSequences() { - YAML::Node doc = YAML::Load(ex2_11); - - std::vector tigers_cubs; - tigers_cubs.push_back("Detroit Tigers"); - tigers_cubs.push_back("Chicago cubs"); - - std::vector yankees_braves; - yankees_braves.push_back("New York Yankees"); - yankees_braves.push_back("Atlanta Braves"); - - - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc[tigers_cubs].size() == 1); - YAML_ASSERT(doc[tigers_cubs][0].as() == "2001-07-23"); - YAML_ASSERT(doc[yankees_braves].size() == 3); - YAML_ASSERT(doc[yankees_braves][0].as() == "2001-07-02"); - YAML_ASSERT(doc[yankees_braves][1].as() == "2001-08-12"); - YAML_ASSERT(doc[yankees_braves][2].as() == "2001-08-14"); - return true; - } - - // 2.12 - TEST CompactNestedMapping() { - YAML::Node doc = YAML::Load(ex2_12); - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc[0].size() == 2); - YAML_ASSERT(doc[0]["item"].as() == "Super Hoop"); - YAML_ASSERT(doc[0]["quantity"].as() == 1); - YAML_ASSERT(doc[1].size() == 2); - YAML_ASSERT(doc[1]["item"].as() == "Basketball"); - YAML_ASSERT(doc[1]["quantity"].as() == 4); - YAML_ASSERT(doc[2].size() == 2); - YAML_ASSERT(doc[2]["item"].as() == "Big Shoes"); - YAML_ASSERT(doc[2]["quantity"].as() == 1); - return true; - } - - // 2.13 - TEST InLiteralsNewlinesArePreserved() { - YAML::Node doc = YAML::Load(ex2_13); - YAML_ASSERT(doc.as() == - "\\//||\\/||\n" - "// || ||__"); - return true; - } - - // 2.14 - TEST InFoldedScalarsNewlinesBecomeSpaces() { - YAML::Node doc = YAML::Load(ex2_14); - YAML_ASSERT(doc.as() == "Mark McGwire's year was crippled by a knee injury."); - return true; - } - - // 2.15 - TEST FoldedNewlinesArePreservedForMoreIndentedAndBlankLines() { - YAML::Node doc = YAML::Load(ex2_15); - YAML_ASSERT(doc.as() == - "Sammy Sosa completed another fine season with great stats.\n\n" - " 63 Home Runs\n" - " 0.288 Batting Average\n\n" - "What a year!"); - return true; - } - - // 2.16 - TEST IndentationDeterminesScope() { - YAML::Node doc = YAML::Load(ex2_16); - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc["name"].as() == "Mark McGwire"); - YAML_ASSERT(doc["accomplishment"].as() == "Mark set a major league home run record in 1998.\n"); - YAML_ASSERT(doc["stats"].as() == "65 Home Runs\n0.278 Batting Average\n"); - return true; - } - - // 2.17 - TEST QuotedScalars() { - YAML::Node doc = YAML::Load(ex2_17); - YAML_ASSERT(doc.size() == 6); - YAML_ASSERT(doc["unicode"].as() == "Sosa did fine.\xe2\x98\xba"); - YAML_ASSERT(doc["control"].as() == "\b1998\t1999\t2000\n"); - YAML_ASSERT(doc["hex esc"].as() == "\x0d\x0a is \r\n"); - YAML_ASSERT(doc["single"].as() == "\"Howdy!\" he cried."); - YAML_ASSERT(doc["quoted"].as() == " # Not a 'comment'."); - YAML_ASSERT(doc["tie-fighter"].as() == "|\\-*-/|"); - return true; - } - - // 2.18 - TEST MultiLineFlowScalars() { - YAML::Node doc = YAML::Load(ex2_18); - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc["plain"].as() == "This unquoted scalar spans many lines."); - YAML_ASSERT(doc["quoted"].as() == "So does this quoted scalar.\n"); - return true; - } - - // TODO: 2.19 - 2.22 schema tags - - // 2.23 - TEST VariousExplicitTags() { - YAML::Node doc = YAML::Load(ex2_23); - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc["not-date"].Tag() == "tag:yaml.org,2002:str"); - YAML_ASSERT(doc["not-date"].as() == "2002-04-28"); - YAML_ASSERT(doc["picture"].Tag() == "tag:yaml.org,2002:binary"); - YAML_ASSERT(doc["picture"].as() == - "R0lGODlhDAAMAIQAAP//9/X\n" - "17unp5WZmZgAAAOfn515eXv\n" - "Pz7Y6OjuDg4J+fn5OTk6enp\n" - "56enmleECcgggoBADs=\n" - ); - YAML_ASSERT(doc["application specific tag"].Tag() == "!something"); - YAML_ASSERT(doc["application specific tag"].as() == - "The semantics of the tag\n" - "above may be different for\n" - "different documents." - ); - return true; - } - - // 2.24 - TEST GlobalTags() { - YAML::Node doc = YAML::Load(ex2_24); - YAML_ASSERT(doc.Tag() == "tag:clarkevans.com,2002:shape"); - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc[0].Tag() == "tag:clarkevans.com,2002:circle"); - YAML_ASSERT(doc[0].size() == 2); - YAML_ASSERT(doc[0]["center"].size() == 2); - YAML_ASSERT(doc[0]["center"]["x"].as() == 73); - YAML_ASSERT(doc[0]["center"]["y"].as() == 129); - YAML_ASSERT(doc[0]["radius"].as() == 7); - YAML_ASSERT(doc[1].Tag() == "tag:clarkevans.com,2002:line"); - YAML_ASSERT(doc[1].size() == 2); - YAML_ASSERT(doc[1]["start"].size() == 2); - YAML_ASSERT(doc[1]["start"]["x"].as() == 73); - YAML_ASSERT(doc[1]["start"]["y"].as() == 129); - YAML_ASSERT(doc[1]["finish"].size() == 2); - YAML_ASSERT(doc[1]["finish"]["x"].as() == 89); - YAML_ASSERT(doc[1]["finish"]["y"].as() == 102); - YAML_ASSERT(doc[2].Tag() == "tag:clarkevans.com,2002:label"); - YAML_ASSERT(doc[2].size() == 3); - YAML_ASSERT(doc[2]["start"].size() == 2); - YAML_ASSERT(doc[2]["start"]["x"].as() == 73); - YAML_ASSERT(doc[2]["start"]["y"].as() == 129); - YAML_ASSERT(doc[2]["color"].as() == "0xFFEEBB"); - YAML_ASSERT(doc[2]["text"].as() == "Pretty vector drawing."); - return true; - } - - // 2.25 - TEST UnorderedSets() { - YAML::Node doc = YAML::Load(ex2_25); - YAML_ASSERT(doc.Tag() == "tag:yaml.org,2002:set"); - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc["Mark McGwire"].IsNull()); - YAML_ASSERT(doc["Sammy Sosa"].IsNull()); - YAML_ASSERT(doc["Ken Griffey"].IsNull()); - return true; - } - - // 2.26 - TEST OrderedMappings() { - YAML::Node doc = YAML::Load(ex2_26); - YAML_ASSERT(doc.Tag() == "tag:yaml.org,2002:omap"); - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc[0].size() == 1); - YAML_ASSERT(doc[0]["Mark McGwire"].as() == 65); - YAML_ASSERT(doc[1].size() == 1); - YAML_ASSERT(doc[1]["Sammy Sosa"].as() == 63); - YAML_ASSERT(doc[2].size() == 1); - YAML_ASSERT(doc[2]["Ken Griffey"].as() == 58); - return true; - } - - // 2.27 - TEST Invoice() { - YAML::Node doc = YAML::Load(ex2_27); - YAML_ASSERT(doc.Tag() == "tag:clarkevans.com,2002:invoice"); - YAML_ASSERT(doc.size() == 8); - YAML_ASSERT(doc["invoice"].as() == 34843); - YAML_ASSERT(doc["date"].as() == "2001-01-23"); - YAML_ASSERT(doc["bill-to"].size() == 3); - YAML_ASSERT(doc["bill-to"]["given"].as() == "Chris"); - YAML_ASSERT(doc["bill-to"]["family"].as() == "Dumars"); - YAML_ASSERT(doc["bill-to"]["address"].size() == 4); - YAML_ASSERT(doc["bill-to"]["address"]["lines"].as() == "458 Walkman Dr.\nSuite #292\n"); - YAML_ASSERT(doc["bill-to"]["address"]["city"].as() == "Royal Oak"); - YAML_ASSERT(doc["bill-to"]["address"]["state"].as() == "MI"); - YAML_ASSERT(doc["bill-to"]["address"]["postal"].as() == "48046"); - YAML_ASSERT(doc["ship-to"].size() == 3); - YAML_ASSERT(doc["ship-to"]["given"].as() == "Chris"); - YAML_ASSERT(doc["ship-to"]["family"].as() == "Dumars"); - YAML_ASSERT(doc["ship-to"]["address"].size() == 4); - YAML_ASSERT(doc["ship-to"]["address"]["lines"].as() == "458 Walkman Dr.\nSuite #292\n"); - YAML_ASSERT(doc["ship-to"]["address"]["city"].as() == "Royal Oak"); - YAML_ASSERT(doc["ship-to"]["address"]["state"].as() == "MI"); - YAML_ASSERT(doc["ship-to"]["address"]["postal"].as() == "48046"); - YAML_ASSERT(doc["product"].size() == 2); - YAML_ASSERT(doc["product"][0].size() == 4); - YAML_ASSERT(doc["product"][0]["sku"].as() == "BL394D"); - YAML_ASSERT(doc["product"][0]["quantity"].as() == 4); - YAML_ASSERT(doc["product"][0]["description"].as() == "Basketball"); - YAML_ASSERT(doc["product"][0]["price"].as() == "450.00"); - YAML_ASSERT(doc["product"][1].size() == 4); - YAML_ASSERT(doc["product"][1]["sku"].as() == "BL4438H"); - YAML_ASSERT(doc["product"][1]["quantity"].as() == 1); - YAML_ASSERT(doc["product"][1]["description"].as() == "Super Hoop"); - YAML_ASSERT(doc["product"][1]["price"].as() == "2392.00"); - YAML_ASSERT(doc["tax"].as() == "251.42"); - YAML_ASSERT(doc["total"].as() == "4443.52"); - YAML_ASSERT(doc["comments"].as() == "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338."); - return true; - } - - // 2.28 - TEST LogFile() { - std::vector docs = YAML::LoadAll(ex2_28); - YAML_ASSERT(docs.size() == 3); - - { - YAML::Node doc = docs[0]; - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc["Time"].as() == "2001-11-23 15:01:42 -5"); - YAML_ASSERT(doc["User"].as() == "ed"); - YAML_ASSERT(doc["Warning"].as() == "This is an error message for the log file"); - } - - { - YAML::Node doc = docs[1]; - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc["Time"].as() == "2001-11-23 15:02:31 -5"); - YAML_ASSERT(doc["User"].as() == "ed"); - YAML_ASSERT(doc["Warning"].as() == "A slightly different error message."); - } - - { - YAML::Node doc = docs[2]; - YAML_ASSERT(doc.size() == 4); - YAML_ASSERT(doc["Date"].as() == "2001-11-23 15:03:17 -5"); - YAML_ASSERT(doc["User"].as() == "ed"); - YAML_ASSERT(doc["Fatal"].as() == "Unknown variable \"bar\""); - YAML_ASSERT(doc["Stack"].size() == 2); - YAML_ASSERT(doc["Stack"][0].size() == 3); - YAML_ASSERT(doc["Stack"][0]["file"].as() == "TopClass.py"); - YAML_ASSERT(doc["Stack"][0]["line"].as() == "23"); - YAML_ASSERT(doc["Stack"][0]["code"].as() == "x = MoreObject(\"345\\n\")\n"); - YAML_ASSERT(doc["Stack"][1].size() == 3); - YAML_ASSERT(doc["Stack"][1]["file"].as() == "MoreClass.py"); - YAML_ASSERT(doc["Stack"][1]["line"].as() == "58"); - YAML_ASSERT(doc["Stack"][1]["code"].as() == "foo = bar"); - } - return true; - } - - // TODO: 5.1 - 5.2 BOM - - // 5.3 - TEST BlockStructureIndicators() { - YAML::Node doc = YAML::Load(ex5_3); - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc["sequence"].size() == 2); - YAML_ASSERT(doc["sequence"][0].as() == "one"); - YAML_ASSERT(doc["sequence"][1].as() == "two"); - YAML_ASSERT(doc["mapping"].size() == 2); - YAML_ASSERT(doc["mapping"]["sky"].as() == "blue"); - YAML_ASSERT(doc["mapping"]["sea"].as() == "green"); - return true; - } - - // 5.4 - TEST FlowStructureIndicators() { - YAML::Node doc = YAML::Load(ex5_4); - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc["sequence"].size() == 2); - YAML_ASSERT(doc["sequence"][0].as() == "one"); - YAML_ASSERT(doc["sequence"][1].as() == "two"); - YAML_ASSERT(doc["mapping"].size() == 2); - YAML_ASSERT(doc["mapping"]["sky"].as() == "blue"); - YAML_ASSERT(doc["mapping"]["sea"].as() == "green"); - return true; - } - - // 5.5 - TEST CommentIndicator() { - YAML::Node doc = YAML::Load(ex5_5); - YAML_ASSERT(doc.IsNull()); - return true; - } - - // 5.6 - TEST NodePropertyIndicators() { - YAML::Node doc = YAML::Load(ex5_6); - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc["anchored"].as() == "value"); // TODO: assert tag - YAML_ASSERT(doc["alias"].as() == "value"); - return true; - } - - // 5.7 - TEST BlockScalarIndicators() { - YAML::Node doc = YAML::Load(ex5_7); - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc["literal"].as() == "some\ntext\n"); - YAML_ASSERT(doc["folded"].as() == "some text\n"); - return true; - } - - // 5.8 - TEST QuotedScalarIndicators() { - YAML::Node doc = YAML::Load(ex5_8); - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc["single"].as() == "text"); - YAML_ASSERT(doc["double"].as() == "text"); - return true; - } - - // TODO: 5.9 directive - // TODO: 5.10 reserved indicator - - // 5.11 - TEST LineBreakCharacters() { - YAML::Node doc = YAML::Load(ex5_11); - YAML_ASSERT(doc.as() == "Line break (no glyph)\nLine break (glyphed)\n"); - return true; - } - - // 5.12 - TEST TabsAndSpaces() { - YAML::Node doc = YAML::Load(ex5_12); - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc["quoted"].as() == "Quoted\t"); - YAML_ASSERT(doc["block"].as() == - "void main() {\n" - "\tprintf(\"Hello, world!\\n\");\n" - "}"); - return true; - } - - // 5.13 - TEST EscapedCharacters() { - YAML::Node doc = YAML::Load(ex5_13); - YAML_ASSERT(doc.as() == "Fun with \x5C \x22 \x07 \x08 \x1B \x0C \x0A \x0D \x09 \x0B " + std::string("\x00", 1) + " \x20 \xA0 \x85 \xe2\x80\xa8 \xe2\x80\xa9 A A A"); - return true; - } - - // 5.14 - TEST InvalidEscapedCharacters() { - try { - YAML::Load(ex5_14); - } catch(const YAML::ParserException& e) { - YAML_ASSERT(e.msg == std::string(YAML::ErrorMsg::INVALID_ESCAPE) + "c"); - return true; - } - - return false; - } - - // 6.1 - TEST IndentationSpaces() { - YAML::Node doc = YAML::Load(ex6_1); - YAML_ASSERT(doc.size() == 1); - YAML_ASSERT(doc["Not indented"].size() == 2); - YAML_ASSERT(doc["Not indented"]["By one space"].as() == "By four\n spaces\n"); - YAML_ASSERT(doc["Not indented"]["Flow style"].size() == 3); - YAML_ASSERT(doc["Not indented"]["Flow style"][0].as() == "By two"); - YAML_ASSERT(doc["Not indented"]["Flow style"][1].as() == "Also by two"); - YAML_ASSERT(doc["Not indented"]["Flow style"][2].as() == "Still by two"); - return true; - } - - // 6.2 - TEST IndentationIndicators() { - YAML::Node doc = YAML::Load(ex6_2); - YAML_ASSERT(doc.size() == 1); - YAML_ASSERT(doc["a"].size() == 2); - YAML_ASSERT(doc["a"][0].as() == "b"); - YAML_ASSERT(doc["a"][1].size() == 2); - YAML_ASSERT(doc["a"][1][0].as() == "c"); - YAML_ASSERT(doc["a"][1][1].as() == "d"); - return true; - } - - // 6.3 - TEST SeparationSpaces() { - YAML::Node doc = YAML::Load(ex6_3); - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc[0].size() == 1); - YAML_ASSERT(doc[0]["foo"].as() == "bar"); - YAML_ASSERT(doc[1].size() == 2); - YAML_ASSERT(doc[1][0].as() == "baz"); - YAML_ASSERT(doc[1][1].as() == "baz"); - return true; - } - - // 6.4 - TEST LinePrefixes() { - YAML::Node doc = YAML::Load(ex6_4); - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc["plain"].as() == "text lines"); - YAML_ASSERT(doc["quoted"].as() == "text lines"); - YAML_ASSERT(doc["block"].as() == "text\n \tlines\n"); - return true; - } - - // 6.5 - TEST EmptyLines() { - YAML::Node doc = YAML::Load(ex6_5); - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc["Folding"].as() == "Empty line\nas a line feed"); - YAML_ASSERT(doc["Chomping"].as() == "Clipped empty lines\n"); - return true; - } - - // 6.6 - TEST LineFolding() { - YAML::Node doc = YAML::Load(ex6_6); - YAML_ASSERT(doc.as() == "trimmed\n\n\nas space"); - return true; - } - - // 6.7 - TEST BlockFolding() { - YAML::Node doc = YAML::Load(ex6_7); - YAML_ASSERT(doc.as() == "foo \n\n\t bar\n\nbaz\n"); - return true; - } - - // 6.8 - TEST FlowFolding() { - YAML::Node doc = YAML::Load(ex6_8); - YAML_ASSERT(doc.as() == " foo\nbar\nbaz "); - return true; - } - - // 6.9 - TEST SeparatedComment() { - YAML::Node doc = YAML::Load(ex6_9); - YAML_ASSERT(doc.size() == 1); - YAML_ASSERT(doc["key"].as() == "value"); - return true; - } - - // 6.10 - TEST CommentLines() { - YAML::Node doc = YAML::Load(ex6_10); - YAML_ASSERT(doc.IsNull()); - return true; - } - - // 6.11 - TEST MultiLineComments() { - YAML::Node doc = YAML::Load(ex6_11); - YAML_ASSERT(doc.size() == 1); - YAML_ASSERT(doc["key"].as() == "value"); - return true; - } - - // 6.12 - TEST SeparationSpacesII() { - YAML::Node doc = YAML::Load(ex6_12); - - std::map sammy; - sammy["first"] = "Sammy"; - sammy["last"] = "Sosa"; - - YAML_ASSERT(doc.size() == 1); - YAML_ASSERT(doc[sammy].size() == 2); - YAML_ASSERT(doc[sammy]["hr"].as() == 65); - YAML_ASSERT(doc[sammy]["avg"].as() == "0.278"); - return true; - } - - // 6.13 - TEST ReservedDirectives() { - YAML::Node doc = YAML::Load(ex6_13); - YAML_ASSERT(doc.as() == "foo"); - return true; - } - - // 6.14 - TEST YAMLDirective() { - YAML::Node doc = YAML::Load(ex6_14); - YAML_ASSERT(doc.as() == "foo"); - return true; - } - - // 6.15 - TEST InvalidRepeatedYAMLDirective() { - try { - YAML::Load(ex6_15); - } catch(const YAML::ParserException& e) { - YAML_ASSERT(e.msg == YAML::ErrorMsg::REPEATED_YAML_DIRECTIVE); - return true; - } - - return " No exception was thrown"; - } - - // 6.16 - TEST TagDirective() { - YAML::Node doc = YAML::Load(ex6_16); - YAML_ASSERT(doc.Tag() == "tag:yaml.org,2002:str"); - YAML_ASSERT(doc.as() == "foo"); - return true; - } - - // 6.17 - TEST InvalidRepeatedTagDirective() { - try { - YAML::Load(ex6_17); - } catch(const YAML::ParserException& e) { - if(e.msg == YAML::ErrorMsg::REPEATED_TAG_DIRECTIVE) - return true; - - throw; - } - - return " No exception was thrown"; - } - - // 6.18 - TEST PrimaryTagHandle() { - std::vector docs = YAML::LoadAll(ex6_18); - YAML_ASSERT(docs.size() == 2); - - { - YAML::Node doc = docs[0]; - YAML_ASSERT(doc.Tag() == "!foo"); - YAML_ASSERT(doc.as() == "bar"); - } - - { - YAML::Node doc = docs[1]; - YAML_ASSERT(doc.Tag() == "tag:example.com,2000:app/foo"); - YAML_ASSERT(doc.as() == "bar"); - } - return true; - } - - // 6.19 - TEST SecondaryTagHandle() { - YAML::Node doc = YAML::Load(ex6_19); - YAML_ASSERT(doc.Tag() == "tag:example.com,2000:app/int"); - YAML_ASSERT(doc.as() == "1 - 3"); - return true; - } - - // 6.20 - TEST TagHandles() { - YAML::Node doc = YAML::Load(ex6_20); - YAML_ASSERT(doc.Tag() == "tag:example.com,2000:app/foo"); - YAML_ASSERT(doc.as() == "bar"); - return true; - } - - // 6.21 - TEST LocalTagPrefix() { - std::vector docs = YAML::LoadAll(ex6_21); - YAML_ASSERT(docs.size() == 2); - - { - YAML::Node doc = docs[0]; - YAML_ASSERT(doc.Tag() == "!my-light"); - YAML_ASSERT(doc.as() == "fluorescent"); - } - - { - YAML::Node doc = docs[1]; - YAML_ASSERT(doc.Tag() == "!my-light"); - YAML_ASSERT(doc.as() == "green"); - } - return true; - } - - // 6.22 - TEST GlobalTagPrefix() { - YAML::Node doc = YAML::Load(ex6_22); - YAML_ASSERT(doc.size() == 1); - YAML_ASSERT(doc[0].Tag() == "tag:example.com,2000:app/foo"); - YAML_ASSERT(doc[0].as() == "bar"); - return true; - } - - // 6.23 - TEST NodeProperties() { - YAML::Node doc = YAML::Load(ex6_23); - YAML_ASSERT(doc.size() == 2); - for(YAML::const_iterator it=doc.begin();it!=doc.end();++it) { - if(it->first.as() == "foo") { - YAML_ASSERT(it->first.Tag() == "tag:yaml.org,2002:str"); - YAML_ASSERT(it->second.Tag() == "tag:yaml.org,2002:str"); - YAML_ASSERT(it->second.as() == "bar"); - } else if(it->first.as() == "baz") { - YAML_ASSERT(it->second.as() == "foo"); - } else - return " unknown key"; - } - - return true; - } - - // 6.24 - TEST VerbatimTags() { - YAML::Node doc = YAML::Load(ex6_24); - YAML_ASSERT(doc.size() == 1); - for(YAML::const_iterator it=doc.begin();it!=doc.end();++it) { - YAML_ASSERT(it->first.Tag() == "tag:yaml.org,2002:str"); - YAML_ASSERT(it->first.as() == "foo"); - YAML_ASSERT(it->second.Tag() == "!bar"); - YAML_ASSERT(it->second.as() == "baz"); - } - return true; - } - - // 6.25 - TEST InvalidVerbatimTags() { - YAML::Node doc = YAML::Load(ex6_25); - return " not implemented yet"; // TODO: check tags (but we probably will say these are valid, I think) - } - - // 6.26 - TEST TagShorthands() { - YAML::Node doc = YAML::Load(ex6_26); - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc[0].Tag() == "!local"); - YAML_ASSERT(doc[0].as() == "foo"); - YAML_ASSERT(doc[1].Tag() == "tag:yaml.org,2002:str"); - YAML_ASSERT(doc[1].as() == "bar"); - YAML_ASSERT(doc[2].Tag() == "tag:example.com,2000:app/tag%21"); - YAML_ASSERT(doc[2].as() == "baz"); - return true; - } - - // 6.27 - TEST InvalidTagShorthands() { - bool threw = false; - try { - YAML::Load(ex6_27a); - } catch(const YAML::ParserException& e) { - threw = true; - if(e.msg != YAML::ErrorMsg::TAG_WITH_NO_SUFFIX) - throw; - } - - if(!threw) - return " No exception was thrown for a tag with no suffix"; - - YAML::Load(ex6_27b); // TODO: should we reject this one (since !h! is not declared)? - return " not implemented yet"; - } - - // 6.28 - TEST NonSpecificTags() { - YAML::Node doc = YAML::Load(ex6_28); - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc[0].as() == "12"); // TODO: check tags. How? - YAML_ASSERT(doc[1].as() == 12); - YAML_ASSERT(doc[2].as() == "12"); - return true; - } - - // 6.29 - TEST NodeAnchors() { - YAML::Node doc = YAML::Load(ex6_29); - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc["First occurrence"].as() == "Value"); - YAML_ASSERT(doc["Second occurrence"].as() == "Value"); - return true; - } - - // 7.1 - TEST AliasNodes() { - YAML::Node doc = YAML::Load(ex7_1); - YAML_ASSERT(doc.size() == 4); - YAML_ASSERT(doc["First occurrence"].as() == "Foo"); - YAML_ASSERT(doc["Second occurrence"].as() == "Foo"); - YAML_ASSERT(doc["Override anchor"].as() == "Bar"); - YAML_ASSERT(doc["Reuse anchor"].as() == "Bar"); - return true; - } - - // 7.2 - TEST EmptyNodes() { - YAML::Node doc = YAML::Load(ex7_2); - YAML_ASSERT(doc.size() == 2); - for(YAML::const_iterator it=doc.begin();it!=doc.end();++it) { - if(it->first.as() == "foo") { - YAML_ASSERT(it->second.Tag() == "tag:yaml.org,2002:str"); - YAML_ASSERT(it->second.as() == ""); - } else if(it->first.as() == "") { - YAML_ASSERT(it->first.Tag() == "tag:yaml.org,2002:str"); - YAML_ASSERT(it->second.as() == "bar"); - } else - return " unexpected key"; - } - return true; - } - - // 7.3 - TEST CompletelyEmptyNodes() { - YAML::Node doc = YAML::Load(ex7_3); - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc["foo"].IsNull()); - YAML_ASSERT(doc[YAML::Null].as() == "bar"); - return true; - } - - // 7.4 - TEST DoubleQuotedImplicitKeys() { - YAML::Node doc = YAML::Load(ex7_4); - YAML_ASSERT(doc.size() == 1); - YAML_ASSERT(doc["implicit block key"].size() == 1); - YAML_ASSERT(doc["implicit block key"][0].size() == 1); - YAML_ASSERT(doc["implicit block key"][0]["implicit flow key"].as() == "value"); - return true; - } - - // 7.5 - TEST DoubleQuotedLineBreaks() { - YAML::Node doc = YAML::Load(ex7_5); - YAML_ASSERT(doc.as() == "folded to a space,\nto a line feed, or \t \tnon-content"); - return true; - } - - // 7.6 - TEST DoubleQuotedLines() { - YAML::Node doc = YAML::Load(ex7_6); - YAML_ASSERT(doc.as() == " 1st non-empty\n2nd non-empty 3rd non-empty "); - return true; - } - - // 7.7 - TEST SingleQuotedCharacters() { - YAML::Node doc = YAML::Load(ex7_7); - YAML_ASSERT(doc.as() == "here's to \"quotes\""); - return true; - } - - // 7.8 - TEST SingleQuotedImplicitKeys() { - YAML::Node doc = YAML::Load(ex7_8); - YAML_ASSERT(doc.size() == 1); - YAML_ASSERT(doc["implicit block key"].size() == 1); - YAML_ASSERT(doc["implicit block key"][0].size() == 1); - YAML_ASSERT(doc["implicit block key"][0]["implicit flow key"].as() == "value"); - return true; - } - - // 7.9 - TEST SingleQuotedLines() { - YAML::Node doc = YAML::Load(ex7_9); - YAML_ASSERT(doc.as() == " 1st non-empty\n2nd non-empty 3rd non-empty "); - return true; - } - - // 7.10 - TEST PlainCharacters() { - YAML::Node doc = YAML::Load(ex7_10); - YAML_ASSERT(doc.size() == 6); - YAML_ASSERT(doc[0].as() == "::vector"); - YAML_ASSERT(doc[1].as() == ": - ()"); - YAML_ASSERT(doc[2].as() == "Up, up, and away!"); - YAML_ASSERT(doc[3].as() == -123); - YAML_ASSERT(doc[4].as() == "http://example.com/foo#bar"); - YAML_ASSERT(doc[5].size() == 5); - YAML_ASSERT(doc[5][0].as() == "::vector"); - YAML_ASSERT(doc[5][1].as() == ": - ()"); - YAML_ASSERT(doc[5][2].as() == "Up, up, and away!"); - YAML_ASSERT(doc[5][3].as() == -123); - YAML_ASSERT(doc[5][4].as() == "http://example.com/foo#bar"); - return true; - } - - // 7.11 - TEST PlainImplicitKeys() { - YAML::Node doc = YAML::Load(ex7_11); - YAML_ASSERT(doc.size() == 1); - YAML_ASSERT(doc["implicit block key"].size() == 1); - YAML_ASSERT(doc["implicit block key"][0].size() == 1); - YAML_ASSERT(doc["implicit block key"][0]["implicit flow key"].as() == "value"); - return true; - } - - // 7.12 - TEST PlainLines() { - YAML::Node doc = YAML::Load(ex7_12); - YAML_ASSERT(doc.as() == "1st non-empty\n2nd non-empty 3rd non-empty"); - return true; - } - - // 7.13 - TEST FlowSequence() { - YAML::Node doc = YAML::Load(ex7_13); - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc[0].size() == 2); - YAML_ASSERT(doc[0][0].as() == "one"); - YAML_ASSERT(doc[0][1].as() == "two"); - YAML_ASSERT(doc[1].size() == 2); - YAML_ASSERT(doc[1][0].as() == "three"); - YAML_ASSERT(doc[1][1].as() == "four"); - return true; - } - - // 7.14 - TEST FlowSequenceEntries() { - YAML::Node doc = YAML::Load(ex7_14); - YAML_ASSERT(doc.size() == 5); - YAML_ASSERT(doc[0].as() == "double quoted"); - YAML_ASSERT(doc[1].as() == "single quoted"); - YAML_ASSERT(doc[2].as() == "plain text"); - YAML_ASSERT(doc[3].size() == 1); - YAML_ASSERT(doc[3][0].as() == "nested"); - YAML_ASSERT(doc[4].size() == 1); - YAML_ASSERT(doc[4]["single"].as() == "pair"); - return true; - } - - // 7.15 - TEST FlowMappings() { - YAML::Node doc = YAML::Load(ex7_15); - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc[0].size() == 2); - YAML_ASSERT(doc[0]["one"].as() == "two"); - YAML_ASSERT(doc[0]["three"].as() == "four"); - YAML_ASSERT(doc[1].size() == 2); - YAML_ASSERT(doc[1]["five"].as() == "six"); - YAML_ASSERT(doc[1]["seven"].as() == "eight"); - return true; - } - - // 7.16 - TEST FlowMappingEntries() { - YAML::Node doc = YAML::Load(ex7_16); - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc["explicit"].as() == "entry"); - YAML_ASSERT(doc["implicit"].as() == "entry"); - YAML_ASSERT(doc[YAML::Null].IsNull()); - return true; - } - - // 7.17 - TEST FlowMappingSeparateValues() { - YAML::Node doc = YAML::Load(ex7_17); - YAML_ASSERT(doc.size() == 4); - YAML_ASSERT(doc["unquoted"].as() == "separate"); - YAML_ASSERT(doc["http://foo.com"].IsNull()); - YAML_ASSERT(doc["omitted value"].IsNull()); - YAML_ASSERT(doc[YAML::Null].as() == "omitted key"); - return true; - } - - // 7.18 - TEST FlowMappingAdjacentValues() { - YAML::Node doc = YAML::Load(ex7_18); - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc["adjacent"].as() == "value"); - YAML_ASSERT(doc["readable"].as() == "value"); - YAML_ASSERT(doc["empty"].IsNull()); - return true; - } - - // 7.19 - TEST SinglePairFlowMappings() { - YAML::Node doc = YAML::Load(ex7_19); - YAML_ASSERT(doc.size() == 1); - YAML_ASSERT(doc[0].size() == 1); - YAML_ASSERT(doc[0]["foo"].as() == "bar"); - return true; - } - - // 7.20 - TEST SinglePairExplicitEntry() { - YAML::Node doc = YAML::Load(ex7_20); - YAML_ASSERT(doc.size() == 1); - YAML_ASSERT(doc[0].size() == 1); - YAML_ASSERT(doc[0]["foo bar"].as() == "baz"); - return true; - } - - // 7.21 - TEST SinglePairImplicitEntries() { - YAML::Node doc = YAML::Load(ex7_21); - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc[0].size() == 1); - YAML_ASSERT(doc[0][0].size() == 1); - YAML_ASSERT(doc[0][0]["YAML"].as() == "separate"); - YAML_ASSERT(doc[1].size() == 1); - YAML_ASSERT(doc[1][0].size() == 1); - YAML_ASSERT(doc[1][0][YAML::Null].as() == "empty key entry"); - YAML_ASSERT(doc[2].size() == 1); - YAML_ASSERT(doc[2][0].size() == 1); - - std::map key; - key["JSON"] = "like"; - YAML_ASSERT(doc[2][0][key].as() == "adjacent"); - return true; - } - - // 7.22 - TEST InvalidImplicitKeys() { - try { - YAML::Load(ex7_22); - } catch(const YAML::Exception& e) { - if(e.msg == YAML::ErrorMsg::END_OF_SEQ_FLOW) - return true; - - throw; - } - return " no exception thrown"; - } - - // 7.23 - TEST FlowContent() { - YAML::Node doc = YAML::Load(ex7_23); - YAML_ASSERT(doc.size() == 5); - YAML_ASSERT(doc[0].size() == 2); - YAML_ASSERT(doc[0][0].as() == "a"); - YAML_ASSERT(doc[0][1].as() == "b"); - YAML_ASSERT(doc[1].size() == 1); - YAML_ASSERT(doc[1]["a"].as() == "b"); - YAML_ASSERT(doc[2].as() == "a"); - YAML_ASSERT(doc[3].as() == 'b'); - YAML_ASSERT(doc[4].as() == "c"); - return true; - } - - // 7.24 - TEST FlowNodes() { - YAML::Node doc = YAML::Load(ex7_24); - YAML_ASSERT(doc.size() == 5); - YAML_ASSERT(doc[0].Tag() == "tag:yaml.org,2002:str"); - YAML_ASSERT(doc[0].as() == "a"); - YAML_ASSERT(doc[1].as() == 'b'); - YAML_ASSERT(doc[2].as() == "c"); - YAML_ASSERT(doc[3].as() == "c"); - YAML_ASSERT(doc[4].Tag() == "tag:yaml.org,2002:str"); - YAML_ASSERT(doc[4].as() == ""); - return true; - } - - // 8.1 - TEST BlockScalarHeader() { - YAML::Node doc = YAML::Load(ex8_1); - YAML_ASSERT(doc.size() == 4); - YAML_ASSERT(doc[0].as() == "literal\n"); - YAML_ASSERT(doc[1].as() == " folded\n"); - YAML_ASSERT(doc[2].as() == "keep\n\n"); - YAML_ASSERT(doc[3].as() == " strip"); - return true; - } - - // 8.2 - TEST BlockIndentationHeader() { - YAML::Node doc = YAML::Load(ex8_2); - YAML_ASSERT(doc.size() == 4); - YAML_ASSERT(doc[0].as() == "detected\n"); - YAML_ASSERT(doc[1].as() == "\n\n# detected\n"); - YAML_ASSERT(doc[2].as() == " explicit\n"); - YAML_ASSERT(doc[3].as() == "\t\ndetected\n"); - return true; - } - - // 8.3 - TEST InvalidBlockScalarIndentationIndicators() { - { - bool threw = false; - try { - YAML::Load(ex8_3a); - } catch(const YAML::Exception& e) { - if(e.msg != YAML::ErrorMsg::END_OF_SEQ) - throw; - - threw = true; - } - - if(!threw) - return " no exception thrown for less indented auto-detecting indentation for a literal block scalar"; - } - - { - bool threw = false; - try { - YAML::Load(ex8_3b); - } catch(const YAML::Exception& e) { - if(e.msg != YAML::ErrorMsg::END_OF_SEQ) - throw; - - threw = true; - } - - if(!threw) - return " no exception thrown for less indented auto-detecting indentation for a folded block scalar"; - } - - { - bool threw = false; - try { - YAML::Load(ex8_3c); - } catch(const YAML::Exception& e) { - if(e.msg != YAML::ErrorMsg::END_OF_SEQ) - throw; - - threw = true; - } - - if(!threw) - return " no exception thrown for less indented explicit indentation for a literal block scalar"; - } - - return true; - } - - // 8.4 - TEST ChompingFinalLineBreak() { - YAML::Node doc = YAML::Load(ex8_4); - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc["strip"].as() == "text"); - YAML_ASSERT(doc["clip"].as() == "text\n"); - YAML_ASSERT(doc["keep"].as() == "text\n"); - return true; - } - - // 8.5 - TEST ChompingTrailingLines() { - YAML::Node doc = YAML::Load(ex8_5); - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc["strip"].as() == "# text"); - YAML_ASSERT(doc["clip"].as() == "# text\n"); - YAML_ASSERT(doc["keep"].as() == "# text\n"); // Note: I believe this is a bug in the YAML spec - it should be "# text\n\n" - return true; - } - - // 8.6 - TEST EmptyScalarChomping() { - YAML::Node doc = YAML::Load(ex8_6); - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc["strip"].as() == ""); - YAML_ASSERT(doc["clip"].as() == ""); - YAML_ASSERT(doc["keep"].as() == "\n"); - return true; - } - - // 8.7 - TEST LiteralScalar() { - YAML::Node doc = YAML::Load(ex8_7); - YAML_ASSERT(doc.as() == "literal\n\ttext\n"); - return true; - } - - // 8.8 - TEST LiteralContent() { - YAML::Node doc = YAML::Load(ex8_8); - YAML_ASSERT(doc.as() == "\n\nliteral\n \n\ntext\n"); - return true; - } - - // 8.9 - TEST FoldedScalar() { - YAML::Node doc = YAML::Load(ex8_9); - YAML_ASSERT(doc.as() == "folded text\n"); - return true; - } - - // 8.10 - TEST FoldedLines() { - YAML::Node doc = YAML::Load(ex8_10); - YAML_ASSERT(doc.as() == "\nfolded line\nnext line\n * bullet\n\n * list\n * lines\n\nlast line\n"); - return true; - } - - // 8.11 - TEST MoreIndentedLines() { - YAML::Node doc = YAML::Load(ex8_11); - YAML_ASSERT(doc.as() == "\nfolded line\nnext line\n * bullet\n\n * list\n * lines\n\nlast line\n"); - return true; - } - - // 8.12 - TEST EmptySeparationLines() { - YAML::Node doc = YAML::Load(ex8_12); - YAML_ASSERT(doc.as() == "\nfolded line\nnext line\n * bullet\n\n * list\n * lines\n\nlast line\n"); - return true; - } - - // 8.13 - TEST FinalEmptyLines() { - YAML::Node doc = YAML::Load(ex8_13); - YAML_ASSERT(doc.as() == "\nfolded line\nnext line\n * bullet\n\n * list\n * lines\n\nlast line\n"); - return true; - } - - // 8.14 - TEST BlockSequence() { - YAML::Node doc = YAML::Load(ex8_14); - YAML_ASSERT(doc.size() == 1); - YAML_ASSERT(doc["block sequence"].size() == 2); - YAML_ASSERT(doc["block sequence"][0].as() == "one"); - YAML_ASSERT(doc["block sequence"][1].size() == 1); - YAML_ASSERT(doc["block sequence"][1]["two"].as() == "three"); - return true; - } - - // 8.15 - TEST BlockSequenceEntryTypes() { - YAML::Node doc = YAML::Load(ex8_15); - YAML_ASSERT(doc.size() == 4); - YAML_ASSERT(doc[0].IsNull()); - YAML_ASSERT(doc[1].as() == "block node\n"); - YAML_ASSERT(doc[2].size() == 2); - YAML_ASSERT(doc[2][0].as() == "one"); - YAML_ASSERT(doc[2][1].as() == "two"); - YAML_ASSERT(doc[3].size() == 1); - YAML_ASSERT(doc[3]["one"].as() == "two"); - return true; - } - - // 8.16 - TEST BlockMappings() { - YAML::Node doc = YAML::Load(ex8_16); - YAML_ASSERT(doc.size() == 1); - YAML_ASSERT(doc["block mapping"].size() == 1); - YAML_ASSERT(doc["block mapping"]["key"].as() == "value"); - return true; - } - - // 8.17 - TEST ExplicitBlockMappingEntries() { - YAML::Node doc = YAML::Load(ex8_17); - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc["explicit key"].IsNull()); - YAML_ASSERT(doc["block key\n"].size() == 2); - YAML_ASSERT(doc["block key\n"][0].as() == "one"); - YAML_ASSERT(doc["block key\n"][1].as() == "two"); - return true; - } - - // 8.18 - TEST ImplicitBlockMappingEntries() { - YAML::Node doc = YAML::Load(ex8_18); - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc["plain key"].as() == "in-line value"); - YAML_ASSERT(doc[YAML::Null].IsNull()); - YAML_ASSERT(doc["quoted key"].size() == 1); - YAML_ASSERT(doc["quoted key"][0].as() == "entry"); - return true; - } - - // 8.19 - TEST CompactBlockMappings() { - YAML::Node doc = YAML::Load(ex8_19); - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc[0].size() == 1); - YAML_ASSERT(doc[0]["sun"].as() == "yellow"); - YAML_ASSERT(doc[1].size() == 1); - std::map key; - key["earth"] = "blue"; - YAML_ASSERT(doc[1][key].size() == 1); - YAML_ASSERT(doc[1][key]["moon"].as() == "white"); - return true; - } - - // 8.20 - TEST BlockNodeTypes() { - YAML::Node doc = YAML::Load(ex8_20); - YAML_ASSERT(doc.size() == 3); - YAML_ASSERT(doc[0].as() == "flow in block"); - YAML_ASSERT(doc[1].as() == "Block scalar\n"); - YAML_ASSERT(doc[2].size() == 1); - YAML_ASSERT(doc[2]["foo"].as() == "bar"); - return true; - } - - // 8.21 - TEST BlockScalarNodes() { - YAML::Node doc = YAML::Load(ex8_21); - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc["literal"].as() == "value"); // Note: I believe this is a bug in the YAML spec - it should be "value\n" - YAML_ASSERT(doc["folded"].as() == "value"); - YAML_ASSERT(doc["folded"].Tag() == "!foo"); - return true; - } - - // 8.22 - TEST BlockCollectionNodes() { - YAML::Node doc = YAML::Load(ex8_22); - YAML_ASSERT(doc.size() == 2); - YAML_ASSERT(doc["sequence"].size() == 2); - YAML_ASSERT(doc["sequence"][0].as() == "entry"); - YAML_ASSERT(doc["sequence"][1].size() == 1); - YAML_ASSERT(doc["sequence"][1][0].as() == "nested"); - YAML_ASSERT(doc["mapping"].size() == 1); - YAML_ASSERT(doc["mapping"]["foo"].as() == "bar"); - return true; - } - } +namespace Test { +namespace Spec { +// 2.1 +TEST SeqScalars() { + YAML::Node doc = YAML::Load(ex2_1); + YAML_ASSERT(doc.IsSequence()); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc[0].as() == "Mark McGwire"); + YAML_ASSERT(doc[1].as() == "Sammy Sosa"); + YAML_ASSERT(doc[2].as() == "Ken Griffey"); + return true; +} + +// 2.2 +TEST MappingScalarsToScalars() { + YAML::Node doc = YAML::Load(ex2_2); + YAML_ASSERT(doc.IsMap()); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["hr"].as() == "65"); + YAML_ASSERT(doc["avg"].as() == "0.278"); + YAML_ASSERT(doc["rbi"].as() == "147"); + return true; +} + +// 2.3 +TEST MappingScalarsToSequences() { + YAML::Node doc = YAML::Load(ex2_3); + YAML_ASSERT(doc.IsMap()); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["american"].size() == 3); + YAML_ASSERT(doc["american"][0].as() == "Boston Red Sox"); + YAML_ASSERT(doc["american"][1].as() == "Detroit Tigers"); + YAML_ASSERT(doc["american"][2].as() == "New York Yankees"); + YAML_ASSERT(doc["national"].size() == 3); + YAML_ASSERT(doc["national"][0].as() == "New York Mets"); + YAML_ASSERT(doc["national"][1].as() == "Chicago Cubs"); + YAML_ASSERT(doc["national"][2].as() == "Atlanta Braves"); + return true; +} + +// 2.4 +TEST SequenceOfMappings() { + YAML::Node doc = YAML::Load(ex2_4); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc[0].size() == 3); + YAML_ASSERT(doc[0]["name"].as() == "Mark McGwire"); + YAML_ASSERT(doc[0]["hr"].as() == "65"); + YAML_ASSERT(doc[0]["avg"].as() == "0.278"); + YAML_ASSERT(doc[1].size() == 3); + YAML_ASSERT(doc[1]["name"].as() == "Sammy Sosa"); + YAML_ASSERT(doc[1]["hr"].as() == "63"); + YAML_ASSERT(doc[1]["avg"].as() == "0.288"); + return true; +} + +// 2.5 +TEST SequenceOfSequences() { + YAML::Node doc = YAML::Load(ex2_5); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc[0].size() == 3); + YAML_ASSERT(doc[0][0].as() == "name"); + YAML_ASSERT(doc[0][1].as() == "hr"); + YAML_ASSERT(doc[0][2].as() == "avg"); + YAML_ASSERT(doc[1].size() == 3); + YAML_ASSERT(doc[1][0].as() == "Mark McGwire"); + YAML_ASSERT(doc[1][1].as() == "65"); + YAML_ASSERT(doc[1][2].as() == "0.278"); + YAML_ASSERT(doc[2].size() == 3); + YAML_ASSERT(doc[2][0].as() == "Sammy Sosa"); + YAML_ASSERT(doc[2][1].as() == "63"); + YAML_ASSERT(doc[2][2].as() == "0.288"); + return true; +} + +// 2.6 +TEST MappingOfMappings() { + YAML::Node doc = YAML::Load(ex2_6); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["Mark McGwire"].size() == 2); + YAML_ASSERT(doc["Mark McGwire"]["hr"].as() == "65"); + YAML_ASSERT(doc["Mark McGwire"]["avg"].as() == "0.278"); + YAML_ASSERT(doc["Sammy Sosa"].size() == 2); + YAML_ASSERT(doc["Sammy Sosa"]["hr"].as() == "63"); + YAML_ASSERT(doc["Sammy Sosa"]["avg"].as() == "0.288"); + return true; +} + +// 2.7 +TEST TwoDocumentsInAStream() { + std::vector docs = YAML::LoadAll(ex2_7); + YAML_ASSERT(docs.size() == 2); + + { + YAML::Node doc = docs[0]; + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc[0].as() == "Mark McGwire"); + YAML_ASSERT(doc[1].as() == "Sammy Sosa"); + YAML_ASSERT(doc[2].as() == "Ken Griffey"); + } + + { + YAML::Node doc = docs[1]; + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc[0].as() == "Chicago Cubs"); + YAML_ASSERT(doc[1].as() == "St Louis Cardinals"); + } + return true; +} + +// 2.8 +TEST PlayByPlayFeed() { + std::vector docs = YAML::LoadAll(ex2_8); + YAML_ASSERT(docs.size() == 2); + + { + YAML::Node doc = docs[0]; + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["time"].as() == "20:03:20"); + YAML_ASSERT(doc["player"].as() == "Sammy Sosa"); + YAML_ASSERT(doc["action"].as() == "strike (miss)"); + } + + { + YAML::Node doc = docs[1]; + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["time"].as() == "20:03:47"); + YAML_ASSERT(doc["player"].as() == "Sammy Sosa"); + YAML_ASSERT(doc["action"].as() == "grand slam"); + } + return true; +} + +// 2.9 +TEST SingleDocumentWithTwoComments() { + YAML::Node doc = YAML::Load(ex2_9); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["hr"].size() == 2); + YAML_ASSERT(doc["hr"][0].as() == "Mark McGwire"); + YAML_ASSERT(doc["hr"][1].as() == "Sammy Sosa"); + YAML_ASSERT(doc["rbi"].size() == 2); + YAML_ASSERT(doc["rbi"][0].as() == "Sammy Sosa"); + YAML_ASSERT(doc["rbi"][1].as() == "Ken Griffey"); + return true; +} + +// 2.10 +TEST SimpleAnchor() { + YAML::Node doc = YAML::Load(ex2_10); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["hr"].size() == 2); + YAML_ASSERT(doc["hr"][0].as() == "Mark McGwire"); + YAML_ASSERT(doc["hr"][1].as() == "Sammy Sosa"); + YAML_ASSERT(doc["rbi"].size() == 2); + YAML_ASSERT(doc["rbi"][0].as() == "Sammy Sosa"); + YAML_ASSERT(doc["rbi"][1].as() == "Ken Griffey"); + return true; +} + +// 2.11 +TEST MappingBetweenSequences() { + YAML::Node doc = YAML::Load(ex2_11); + + std::vector tigers_cubs; + tigers_cubs.push_back("Detroit Tigers"); + tigers_cubs.push_back("Chicago cubs"); + + std::vector yankees_braves; + yankees_braves.push_back("New York Yankees"); + yankees_braves.push_back("Atlanta Braves"); + + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc[tigers_cubs].size() == 1); + YAML_ASSERT(doc[tigers_cubs][0].as() == "2001-07-23"); + YAML_ASSERT(doc[yankees_braves].size() == 3); + YAML_ASSERT(doc[yankees_braves][0].as() == "2001-07-02"); + YAML_ASSERT(doc[yankees_braves][1].as() == "2001-08-12"); + YAML_ASSERT(doc[yankees_braves][2].as() == "2001-08-14"); + return true; +} + +// 2.12 +TEST CompactNestedMapping() { + YAML::Node doc = YAML::Load(ex2_12); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc[0].size() == 2); + YAML_ASSERT(doc[0]["item"].as() == "Super Hoop"); + YAML_ASSERT(doc[0]["quantity"].as() == 1); + YAML_ASSERT(doc[1].size() == 2); + YAML_ASSERT(doc[1]["item"].as() == "Basketball"); + YAML_ASSERT(doc[1]["quantity"].as() == 4); + YAML_ASSERT(doc[2].size() == 2); + YAML_ASSERT(doc[2]["item"].as() == "Big Shoes"); + YAML_ASSERT(doc[2]["quantity"].as() == 1); + return true; +} + +// 2.13 +TEST InLiteralsNewlinesArePreserved() { + YAML::Node doc = YAML::Load(ex2_13); + YAML_ASSERT(doc.as() == + "\\//||\\/||\n" + "// || ||__"); + return true; +} + +// 2.14 +TEST InFoldedScalarsNewlinesBecomeSpaces() { + YAML::Node doc = YAML::Load(ex2_14); + YAML_ASSERT(doc.as() == + "Mark McGwire's year was crippled by a knee injury."); + return true; +} + +// 2.15 +TEST FoldedNewlinesArePreservedForMoreIndentedAndBlankLines() { + YAML::Node doc = YAML::Load(ex2_15); + YAML_ASSERT(doc.as() == + "Sammy Sosa completed another fine season with great stats.\n\n" + " 63 Home Runs\n" + " 0.288 Batting Average\n\n" + "What a year!"); + return true; +} + +// 2.16 +TEST IndentationDeterminesScope() { + YAML::Node doc = YAML::Load(ex2_16); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["name"].as() == "Mark McGwire"); + YAML_ASSERT(doc["accomplishment"].as() == + "Mark set a major league home run record in 1998.\n"); + YAML_ASSERT(doc["stats"].as() == + "65 Home Runs\n0.278 Batting Average\n"); + return true; +} + +// 2.17 +TEST QuotedScalars() { + YAML::Node doc = YAML::Load(ex2_17); + YAML_ASSERT(doc.size() == 6); + YAML_ASSERT(doc["unicode"].as() == "Sosa did fine.\xe2\x98\xba"); + YAML_ASSERT(doc["control"].as() == "\b1998\t1999\t2000\n"); + YAML_ASSERT(doc["hex esc"].as() == "\x0d\x0a is \r\n"); + YAML_ASSERT(doc["single"].as() == "\"Howdy!\" he cried."); + YAML_ASSERT(doc["quoted"].as() == " # Not a 'comment'."); + YAML_ASSERT(doc["tie-fighter"].as() == "|\\-*-/|"); + return true; +} + +// 2.18 +TEST MultiLineFlowScalars() { + YAML::Node doc = YAML::Load(ex2_18); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["plain"].as() == + "This unquoted scalar spans many lines."); + YAML_ASSERT(doc["quoted"].as() == + "So does this quoted scalar.\n"); + return true; +} + +// TODO: 2.19 - 2.22 schema tags + +// 2.23 +TEST VariousExplicitTags() { + YAML::Node doc = YAML::Load(ex2_23); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["not-date"].Tag() == "tag:yaml.org,2002:str"); + YAML_ASSERT(doc["not-date"].as() == "2002-04-28"); + YAML_ASSERT(doc["picture"].Tag() == "tag:yaml.org,2002:binary"); + YAML_ASSERT(doc["picture"].as() == + "R0lGODlhDAAMAIQAAP//9/X\n" + "17unp5WZmZgAAAOfn515eXv\n" + "Pz7Y6OjuDg4J+fn5OTk6enp\n" + "56enmleECcgggoBADs=\n"); + YAML_ASSERT(doc["application specific tag"].Tag() == "!something"); + YAML_ASSERT(doc["application specific tag"].as() == + "The semantics of the tag\n" + "above may be different for\n" + "different documents."); + return true; +} + +// 2.24 +TEST GlobalTags() { + YAML::Node doc = YAML::Load(ex2_24); + YAML_ASSERT(doc.Tag() == "tag:clarkevans.com,2002:shape"); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc[0].Tag() == "tag:clarkevans.com,2002:circle"); + YAML_ASSERT(doc[0].size() == 2); + YAML_ASSERT(doc[0]["center"].size() == 2); + YAML_ASSERT(doc[0]["center"]["x"].as() == 73); + YAML_ASSERT(doc[0]["center"]["y"].as() == 129); + YAML_ASSERT(doc[0]["radius"].as() == 7); + YAML_ASSERT(doc[1].Tag() == "tag:clarkevans.com,2002:line"); + YAML_ASSERT(doc[1].size() == 2); + YAML_ASSERT(doc[1]["start"].size() == 2); + YAML_ASSERT(doc[1]["start"]["x"].as() == 73); + YAML_ASSERT(doc[1]["start"]["y"].as() == 129); + YAML_ASSERT(doc[1]["finish"].size() == 2); + YAML_ASSERT(doc[1]["finish"]["x"].as() == 89); + YAML_ASSERT(doc[1]["finish"]["y"].as() == 102); + YAML_ASSERT(doc[2].Tag() == "tag:clarkevans.com,2002:label"); + YAML_ASSERT(doc[2].size() == 3); + YAML_ASSERT(doc[2]["start"].size() == 2); + YAML_ASSERT(doc[2]["start"]["x"].as() == 73); + YAML_ASSERT(doc[2]["start"]["y"].as() == 129); + YAML_ASSERT(doc[2]["color"].as() == "0xFFEEBB"); + YAML_ASSERT(doc[2]["text"].as() == "Pretty vector drawing."); + return true; +} + +// 2.25 +TEST UnorderedSets() { + YAML::Node doc = YAML::Load(ex2_25); + YAML_ASSERT(doc.Tag() == "tag:yaml.org,2002:set"); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["Mark McGwire"].IsNull()); + YAML_ASSERT(doc["Sammy Sosa"].IsNull()); + YAML_ASSERT(doc["Ken Griffey"].IsNull()); + return true; +} + +// 2.26 +TEST OrderedMappings() { + YAML::Node doc = YAML::Load(ex2_26); + YAML_ASSERT(doc.Tag() == "tag:yaml.org,2002:omap"); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc[0].size() == 1); + YAML_ASSERT(doc[0]["Mark McGwire"].as() == 65); + YAML_ASSERT(doc[1].size() == 1); + YAML_ASSERT(doc[1]["Sammy Sosa"].as() == 63); + YAML_ASSERT(doc[2].size() == 1); + YAML_ASSERT(doc[2]["Ken Griffey"].as() == 58); + return true; +} + +// 2.27 +TEST Invoice() { + YAML::Node doc = YAML::Load(ex2_27); + YAML_ASSERT(doc.Tag() == "tag:clarkevans.com,2002:invoice"); + YAML_ASSERT(doc.size() == 8); + YAML_ASSERT(doc["invoice"].as() == 34843); + YAML_ASSERT(doc["date"].as() == "2001-01-23"); + YAML_ASSERT(doc["bill-to"].size() == 3); + YAML_ASSERT(doc["bill-to"]["given"].as() == "Chris"); + YAML_ASSERT(doc["bill-to"]["family"].as() == "Dumars"); + YAML_ASSERT(doc["bill-to"]["address"].size() == 4); + YAML_ASSERT(doc["bill-to"]["address"]["lines"].as() == + "458 Walkman Dr.\nSuite #292\n"); + YAML_ASSERT(doc["bill-to"]["address"]["city"].as() == + "Royal Oak"); + YAML_ASSERT(doc["bill-to"]["address"]["state"].as() == "MI"); + YAML_ASSERT(doc["bill-to"]["address"]["postal"].as() == "48046"); + YAML_ASSERT(doc["ship-to"].size() == 3); + YAML_ASSERT(doc["ship-to"]["given"].as() == "Chris"); + YAML_ASSERT(doc["ship-to"]["family"].as() == "Dumars"); + YAML_ASSERT(doc["ship-to"]["address"].size() == 4); + YAML_ASSERT(doc["ship-to"]["address"]["lines"].as() == + "458 Walkman Dr.\nSuite #292\n"); + YAML_ASSERT(doc["ship-to"]["address"]["city"].as() == + "Royal Oak"); + YAML_ASSERT(doc["ship-to"]["address"]["state"].as() == "MI"); + YAML_ASSERT(doc["ship-to"]["address"]["postal"].as() == "48046"); + YAML_ASSERT(doc["product"].size() == 2); + YAML_ASSERT(doc["product"][0].size() == 4); + YAML_ASSERT(doc["product"][0]["sku"].as() == "BL394D"); + YAML_ASSERT(doc["product"][0]["quantity"].as() == 4); + YAML_ASSERT(doc["product"][0]["description"].as() == + "Basketball"); + YAML_ASSERT(doc["product"][0]["price"].as() == "450.00"); + YAML_ASSERT(doc["product"][1].size() == 4); + YAML_ASSERT(doc["product"][1]["sku"].as() == "BL4438H"); + YAML_ASSERT(doc["product"][1]["quantity"].as() == 1); + YAML_ASSERT(doc["product"][1]["description"].as() == + "Super Hoop"); + YAML_ASSERT(doc["product"][1]["price"].as() == "2392.00"); + YAML_ASSERT(doc["tax"].as() == "251.42"); + YAML_ASSERT(doc["total"].as() == "4443.52"); + YAML_ASSERT( + doc["comments"].as() == + "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338."); + return true; +} + +// 2.28 +TEST LogFile() { + std::vector docs = YAML::LoadAll(ex2_28); + YAML_ASSERT(docs.size() == 3); + + { + YAML::Node doc = docs[0]; + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["Time"].as() == "2001-11-23 15:01:42 -5"); + YAML_ASSERT(doc["User"].as() == "ed"); + YAML_ASSERT(doc["Warning"].as() == + "This is an error message for the log file"); + } + + { + YAML::Node doc = docs[1]; + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["Time"].as() == "2001-11-23 15:02:31 -5"); + YAML_ASSERT(doc["User"].as() == "ed"); + YAML_ASSERT(doc["Warning"].as() == + "A slightly different error message."); + } + + { + YAML::Node doc = docs[2]; + YAML_ASSERT(doc.size() == 4); + YAML_ASSERT(doc["Date"].as() == "2001-11-23 15:03:17 -5"); + YAML_ASSERT(doc["User"].as() == "ed"); + YAML_ASSERT(doc["Fatal"].as() == "Unknown variable \"bar\""); + YAML_ASSERT(doc["Stack"].size() == 2); + YAML_ASSERT(doc["Stack"][0].size() == 3); + YAML_ASSERT(doc["Stack"][0]["file"].as() == "TopClass.py"); + YAML_ASSERT(doc["Stack"][0]["line"].as() == "23"); + YAML_ASSERT(doc["Stack"][0]["code"].as() == + "x = MoreObject(\"345\\n\")\n"); + YAML_ASSERT(doc["Stack"][1].size() == 3); + YAML_ASSERT(doc["Stack"][1]["file"].as() == "MoreClass.py"); + YAML_ASSERT(doc["Stack"][1]["line"].as() == "58"); + YAML_ASSERT(doc["Stack"][1]["code"].as() == "foo = bar"); + } + return true; +} + +// TODO: 5.1 - 5.2 BOM + +// 5.3 +TEST BlockStructureIndicators() { + YAML::Node doc = YAML::Load(ex5_3); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["sequence"].size() == 2); + YAML_ASSERT(doc["sequence"][0].as() == "one"); + YAML_ASSERT(doc["sequence"][1].as() == "two"); + YAML_ASSERT(doc["mapping"].size() == 2); + YAML_ASSERT(doc["mapping"]["sky"].as() == "blue"); + YAML_ASSERT(doc["mapping"]["sea"].as() == "green"); + return true; +} + +// 5.4 +TEST FlowStructureIndicators() { + YAML::Node doc = YAML::Load(ex5_4); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["sequence"].size() == 2); + YAML_ASSERT(doc["sequence"][0].as() == "one"); + YAML_ASSERT(doc["sequence"][1].as() == "two"); + YAML_ASSERT(doc["mapping"].size() == 2); + YAML_ASSERT(doc["mapping"]["sky"].as() == "blue"); + YAML_ASSERT(doc["mapping"]["sea"].as() == "green"); + return true; +} + +// 5.5 +TEST CommentIndicator() { + YAML::Node doc = YAML::Load(ex5_5); + YAML_ASSERT(doc.IsNull()); + return true; +} + +// 5.6 +TEST NodePropertyIndicators() { + YAML::Node doc = YAML::Load(ex5_6); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["anchored"].as() == + "value"); // TODO: assert tag + YAML_ASSERT(doc["alias"].as() == "value"); + return true; +} + +// 5.7 +TEST BlockScalarIndicators() { + YAML::Node doc = YAML::Load(ex5_7); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["literal"].as() == "some\ntext\n"); + YAML_ASSERT(doc["folded"].as() == "some text\n"); + return true; +} + +// 5.8 +TEST QuotedScalarIndicators() { + YAML::Node doc = YAML::Load(ex5_8); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["single"].as() == "text"); + YAML_ASSERT(doc["double"].as() == "text"); + return true; +} + +// TODO: 5.9 directive +// TODO: 5.10 reserved indicator + +// 5.11 +TEST LineBreakCharacters() { + YAML::Node doc = YAML::Load(ex5_11); + YAML_ASSERT(doc.as() == + "Line break (no glyph)\nLine break (glyphed)\n"); + return true; +} + +// 5.12 +TEST TabsAndSpaces() { + YAML::Node doc = YAML::Load(ex5_12); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["quoted"].as() == "Quoted\t"); + YAML_ASSERT(doc["block"].as() == + "void main() {\n" + "\tprintf(\"Hello, world!\\n\");\n" + "}"); + return true; +} + +// 5.13 +TEST EscapedCharacters() { + YAML::Node doc = YAML::Load(ex5_13); + YAML_ASSERT(doc.as() == + "Fun with \x5C \x22 \x07 \x08 \x1B \x0C \x0A \x0D \x09 \x0B " + + std::string("\x00", 1) + + " \x20 \xA0 \x85 \xe2\x80\xa8 \xe2\x80\xa9 A A A"); + return true; +} + +// 5.14 +TEST InvalidEscapedCharacters() { + try { + YAML::Load(ex5_14); + } + catch (const YAML::ParserException& e) { + YAML_ASSERT(e.msg == std::string(YAML::ErrorMsg::INVALID_ESCAPE) + "c"); + return true; + } + + return false; +} + +// 6.1 +TEST IndentationSpaces() { + YAML::Node doc = YAML::Load(ex6_1); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc["Not indented"].size() == 2); + YAML_ASSERT(doc["Not indented"]["By one space"].as() == + "By four\n spaces\n"); + YAML_ASSERT(doc["Not indented"]["Flow style"].size() == 3); + YAML_ASSERT(doc["Not indented"]["Flow style"][0].as() == + "By two"); + YAML_ASSERT(doc["Not indented"]["Flow style"][1].as() == + "Also by two"); + YAML_ASSERT(doc["Not indented"]["Flow style"][2].as() == + "Still by two"); + return true; +} + +// 6.2 +TEST IndentationIndicators() { + YAML::Node doc = YAML::Load(ex6_2); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc["a"].size() == 2); + YAML_ASSERT(doc["a"][0].as() == "b"); + YAML_ASSERT(doc["a"][1].size() == 2); + YAML_ASSERT(doc["a"][1][0].as() == "c"); + YAML_ASSERT(doc["a"][1][1].as() == "d"); + return true; +} + +// 6.3 +TEST SeparationSpaces() { + YAML::Node doc = YAML::Load(ex6_3); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc[0].size() == 1); + YAML_ASSERT(doc[0]["foo"].as() == "bar"); + YAML_ASSERT(doc[1].size() == 2); + YAML_ASSERT(doc[1][0].as() == "baz"); + YAML_ASSERT(doc[1][1].as() == "baz"); + return true; +} + +// 6.4 +TEST LinePrefixes() { + YAML::Node doc = YAML::Load(ex6_4); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["plain"].as() == "text lines"); + YAML_ASSERT(doc["quoted"].as() == "text lines"); + YAML_ASSERT(doc["block"].as() == "text\n \tlines\n"); + return true; +} + +// 6.5 +TEST EmptyLines() { + YAML::Node doc = YAML::Load(ex6_5); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["Folding"].as() == "Empty line\nas a line feed"); + YAML_ASSERT(doc["Chomping"].as() == "Clipped empty lines\n"); + return true; +} + +// 6.6 +TEST LineFolding() { + YAML::Node doc = YAML::Load(ex6_6); + YAML_ASSERT(doc.as() == "trimmed\n\n\nas space"); + return true; +} + +// 6.7 +TEST BlockFolding() { + YAML::Node doc = YAML::Load(ex6_7); + YAML_ASSERT(doc.as() == "foo \n\n\t bar\n\nbaz\n"); + return true; +} + +// 6.8 +TEST FlowFolding() { + YAML::Node doc = YAML::Load(ex6_8); + YAML_ASSERT(doc.as() == " foo\nbar\nbaz "); + return true; +} + +// 6.9 +TEST SeparatedComment() { + YAML::Node doc = YAML::Load(ex6_9); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc["key"].as() == "value"); + return true; +} + +// 6.10 +TEST CommentLines() { + YAML::Node doc = YAML::Load(ex6_10); + YAML_ASSERT(doc.IsNull()); + return true; +} + +// 6.11 +TEST MultiLineComments() { + YAML::Node doc = YAML::Load(ex6_11); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc["key"].as() == "value"); + return true; +} + +// 6.12 +TEST SeparationSpacesII() { + YAML::Node doc = YAML::Load(ex6_12); + + std::map sammy; + sammy["first"] = "Sammy"; + sammy["last"] = "Sosa"; + + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc[sammy].size() == 2); + YAML_ASSERT(doc[sammy]["hr"].as() == 65); + YAML_ASSERT(doc[sammy]["avg"].as() == "0.278"); + return true; +} + +// 6.13 +TEST ReservedDirectives() { + YAML::Node doc = YAML::Load(ex6_13); + YAML_ASSERT(doc.as() == "foo"); + return true; +} + +// 6.14 +TEST YAMLDirective() { + YAML::Node doc = YAML::Load(ex6_14); + YAML_ASSERT(doc.as() == "foo"); + return true; +} + +// 6.15 +TEST InvalidRepeatedYAMLDirective() { + try { + YAML::Load(ex6_15); + } + catch (const YAML::ParserException& e) { + YAML_ASSERT(e.msg == YAML::ErrorMsg::REPEATED_YAML_DIRECTIVE); + return true; + } + + return " No exception was thrown"; +} + +// 6.16 +TEST TagDirective() { + YAML::Node doc = YAML::Load(ex6_16); + YAML_ASSERT(doc.Tag() == "tag:yaml.org,2002:str"); + YAML_ASSERT(doc.as() == "foo"); + return true; +} + +// 6.17 +TEST InvalidRepeatedTagDirective() { + try { + YAML::Load(ex6_17); + } + catch (const YAML::ParserException& e) { + if (e.msg == YAML::ErrorMsg::REPEATED_TAG_DIRECTIVE) + return true; + + throw; + } + + return " No exception was thrown"; +} + +// 6.18 +TEST PrimaryTagHandle() { + std::vector docs = YAML::LoadAll(ex6_18); + YAML_ASSERT(docs.size() == 2); + + { + YAML::Node doc = docs[0]; + YAML_ASSERT(doc.Tag() == "!foo"); + YAML_ASSERT(doc.as() == "bar"); + } + + { + YAML::Node doc = docs[1]; + YAML_ASSERT(doc.Tag() == "tag:example.com,2000:app/foo"); + YAML_ASSERT(doc.as() == "bar"); + } + return true; +} + +// 6.19 +TEST SecondaryTagHandle() { + YAML::Node doc = YAML::Load(ex6_19); + YAML_ASSERT(doc.Tag() == "tag:example.com,2000:app/int"); + YAML_ASSERT(doc.as() == "1 - 3"); + return true; +} + +// 6.20 +TEST TagHandles() { + YAML::Node doc = YAML::Load(ex6_20); + YAML_ASSERT(doc.Tag() == "tag:example.com,2000:app/foo"); + YAML_ASSERT(doc.as() == "bar"); + return true; +} + +// 6.21 +TEST LocalTagPrefix() { + std::vector docs = YAML::LoadAll(ex6_21); + YAML_ASSERT(docs.size() == 2); + + { + YAML::Node doc = docs[0]; + YAML_ASSERT(doc.Tag() == "!my-light"); + YAML_ASSERT(doc.as() == "fluorescent"); + } + + { + YAML::Node doc = docs[1]; + YAML_ASSERT(doc.Tag() == "!my-light"); + YAML_ASSERT(doc.as() == "green"); + } + return true; +} + +// 6.22 +TEST GlobalTagPrefix() { + YAML::Node doc = YAML::Load(ex6_22); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc[0].Tag() == "tag:example.com,2000:app/foo"); + YAML_ASSERT(doc[0].as() == "bar"); + return true; +} + +// 6.23 +TEST NodeProperties() { + YAML::Node doc = YAML::Load(ex6_23); + YAML_ASSERT(doc.size() == 2); + for (YAML::const_iterator it = doc.begin(); it != doc.end(); ++it) { + if (it->first.as() == "foo") { + YAML_ASSERT(it->first.Tag() == "tag:yaml.org,2002:str"); + YAML_ASSERT(it->second.Tag() == "tag:yaml.org,2002:str"); + YAML_ASSERT(it->second.as() == "bar"); + } else if (it->first.as() == "baz") { + YAML_ASSERT(it->second.as() == "foo"); + } else + return " unknown key"; + } + + return true; +} + +// 6.24 +TEST VerbatimTags() { + YAML::Node doc = YAML::Load(ex6_24); + YAML_ASSERT(doc.size() == 1); + for (YAML::const_iterator it = doc.begin(); it != doc.end(); ++it) { + YAML_ASSERT(it->first.Tag() == "tag:yaml.org,2002:str"); + YAML_ASSERT(it->first.as() == "foo"); + YAML_ASSERT(it->second.Tag() == "!bar"); + YAML_ASSERT(it->second.as() == "baz"); + } + return true; +} + +// 6.25 +TEST InvalidVerbatimTags() { + YAML::Node doc = YAML::Load(ex6_25); + return " not implemented yet"; // TODO: check tags (but we probably will say + // these are valid, I think) +} + +// 6.26 +TEST TagShorthands() { + YAML::Node doc = YAML::Load(ex6_26); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc[0].Tag() == "!local"); + YAML_ASSERT(doc[0].as() == "foo"); + YAML_ASSERT(doc[1].Tag() == "tag:yaml.org,2002:str"); + YAML_ASSERT(doc[1].as() == "bar"); + YAML_ASSERT(doc[2].Tag() == "tag:example.com,2000:app/tag%21"); + YAML_ASSERT(doc[2].as() == "baz"); + return true; +} + +// 6.27 +TEST InvalidTagShorthands() { + bool threw = false; + try { + YAML::Load(ex6_27a); + } + catch (const YAML::ParserException& e) { + threw = true; + if (e.msg != YAML::ErrorMsg::TAG_WITH_NO_SUFFIX) + throw; + } + + if (!threw) + return " No exception was thrown for a tag with no suffix"; + + YAML::Load( + ex6_27b); // TODO: should we reject this one (since !h! is not declared)? + return " not implemented yet"; +} + +// 6.28 +TEST NonSpecificTags() { + YAML::Node doc = YAML::Load(ex6_28); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc[0].as() == "12"); // TODO: check tags. How? + YAML_ASSERT(doc[1].as() == 12); + YAML_ASSERT(doc[2].as() == "12"); + return true; +} + +// 6.29 +TEST NodeAnchors() { + YAML::Node doc = YAML::Load(ex6_29); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["First occurrence"].as() == "Value"); + YAML_ASSERT(doc["Second occurrence"].as() == "Value"); + return true; +} + +// 7.1 +TEST AliasNodes() { + YAML::Node doc = YAML::Load(ex7_1); + YAML_ASSERT(doc.size() == 4); + YAML_ASSERT(doc["First occurrence"].as() == "Foo"); + YAML_ASSERT(doc["Second occurrence"].as() == "Foo"); + YAML_ASSERT(doc["Override anchor"].as() == "Bar"); + YAML_ASSERT(doc["Reuse anchor"].as() == "Bar"); + return true; +} + +// 7.2 +TEST EmptyNodes() { + YAML::Node doc = YAML::Load(ex7_2); + YAML_ASSERT(doc.size() == 2); + for (YAML::const_iterator it = doc.begin(); it != doc.end(); ++it) { + if (it->first.as() == "foo") { + YAML_ASSERT(it->second.Tag() == "tag:yaml.org,2002:str"); + YAML_ASSERT(it->second.as() == ""); + } else if (it->first.as() == "") { + YAML_ASSERT(it->first.Tag() == "tag:yaml.org,2002:str"); + YAML_ASSERT(it->second.as() == "bar"); + } else + return " unexpected key"; + } + return true; +} + +// 7.3 +TEST CompletelyEmptyNodes() { + YAML::Node doc = YAML::Load(ex7_3); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["foo"].IsNull()); + YAML_ASSERT(doc[YAML::Null].as() == "bar"); + return true; +} + +// 7.4 +TEST DoubleQuotedImplicitKeys() { + YAML::Node doc = YAML::Load(ex7_4); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc["implicit block key"].size() == 1); + YAML_ASSERT(doc["implicit block key"][0].size() == 1); + YAML_ASSERT(doc["implicit block key"][0]["implicit flow key"] + .as() == "value"); + return true; +} + +// 7.5 +TEST DoubleQuotedLineBreaks() { + YAML::Node doc = YAML::Load(ex7_5); + YAML_ASSERT(doc.as() == + "folded to a space,\nto a line feed, or \t \tnon-content"); + return true; +} + +// 7.6 +TEST DoubleQuotedLines() { + YAML::Node doc = YAML::Load(ex7_6); + YAML_ASSERT(doc.as() == + " 1st non-empty\n2nd non-empty 3rd non-empty "); + return true; +} + +// 7.7 +TEST SingleQuotedCharacters() { + YAML::Node doc = YAML::Load(ex7_7); + YAML_ASSERT(doc.as() == "here's to \"quotes\""); + return true; +} + +// 7.8 +TEST SingleQuotedImplicitKeys() { + YAML::Node doc = YAML::Load(ex7_8); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc["implicit block key"].size() == 1); + YAML_ASSERT(doc["implicit block key"][0].size() == 1); + YAML_ASSERT(doc["implicit block key"][0]["implicit flow key"] + .as() == "value"); + return true; +} + +// 7.9 +TEST SingleQuotedLines() { + YAML::Node doc = YAML::Load(ex7_9); + YAML_ASSERT(doc.as() == + " 1st non-empty\n2nd non-empty 3rd non-empty "); + return true; +} + +// 7.10 +TEST PlainCharacters() { + YAML::Node doc = YAML::Load(ex7_10); + YAML_ASSERT(doc.size() == 6); + YAML_ASSERT(doc[0].as() == "::vector"); + YAML_ASSERT(doc[1].as() == ": - ()"); + YAML_ASSERT(doc[2].as() == "Up, up, and away!"); + YAML_ASSERT(doc[3].as() == -123); + YAML_ASSERT(doc[4].as() == "http://example.com/foo#bar"); + YAML_ASSERT(doc[5].size() == 5); + YAML_ASSERT(doc[5][0].as() == "::vector"); + YAML_ASSERT(doc[5][1].as() == ": - ()"); + YAML_ASSERT(doc[5][2].as() == "Up, up, and away!"); + YAML_ASSERT(doc[5][3].as() == -123); + YAML_ASSERT(doc[5][4].as() == "http://example.com/foo#bar"); + return true; +} + +// 7.11 +TEST PlainImplicitKeys() { + YAML::Node doc = YAML::Load(ex7_11); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc["implicit block key"].size() == 1); + YAML_ASSERT(doc["implicit block key"][0].size() == 1); + YAML_ASSERT(doc["implicit block key"][0]["implicit flow key"] + .as() == "value"); + return true; +} + +// 7.12 +TEST PlainLines() { + YAML::Node doc = YAML::Load(ex7_12); + YAML_ASSERT(doc.as() == + "1st non-empty\n2nd non-empty 3rd non-empty"); + return true; +} + +// 7.13 +TEST FlowSequence() { + YAML::Node doc = YAML::Load(ex7_13); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc[0].size() == 2); + YAML_ASSERT(doc[0][0].as() == "one"); + YAML_ASSERT(doc[0][1].as() == "two"); + YAML_ASSERT(doc[1].size() == 2); + YAML_ASSERT(doc[1][0].as() == "three"); + YAML_ASSERT(doc[1][1].as() == "four"); + return true; +} + +// 7.14 +TEST FlowSequenceEntries() { + YAML::Node doc = YAML::Load(ex7_14); + YAML_ASSERT(doc.size() == 5); + YAML_ASSERT(doc[0].as() == "double quoted"); + YAML_ASSERT(doc[1].as() == "single quoted"); + YAML_ASSERT(doc[2].as() == "plain text"); + YAML_ASSERT(doc[3].size() == 1); + YAML_ASSERT(doc[3][0].as() == "nested"); + YAML_ASSERT(doc[4].size() == 1); + YAML_ASSERT(doc[4]["single"].as() == "pair"); + return true; +} + +// 7.15 +TEST FlowMappings() { + YAML::Node doc = YAML::Load(ex7_15); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc[0].size() == 2); + YAML_ASSERT(doc[0]["one"].as() == "two"); + YAML_ASSERT(doc[0]["three"].as() == "four"); + YAML_ASSERT(doc[1].size() == 2); + YAML_ASSERT(doc[1]["five"].as() == "six"); + YAML_ASSERT(doc[1]["seven"].as() == "eight"); + return true; +} + +// 7.16 +TEST FlowMappingEntries() { + YAML::Node doc = YAML::Load(ex7_16); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["explicit"].as() == "entry"); + YAML_ASSERT(doc["implicit"].as() == "entry"); + YAML_ASSERT(doc[YAML::Null].IsNull()); + return true; +} + +// 7.17 +TEST FlowMappingSeparateValues() { + YAML::Node doc = YAML::Load(ex7_17); + YAML_ASSERT(doc.size() == 4); + YAML_ASSERT(doc["unquoted"].as() == "separate"); + YAML_ASSERT(doc["http://foo.com"].IsNull()); + YAML_ASSERT(doc["omitted value"].IsNull()); + YAML_ASSERT(doc[YAML::Null].as() == "omitted key"); + return true; +} + +// 7.18 +TEST FlowMappingAdjacentValues() { + YAML::Node doc = YAML::Load(ex7_18); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["adjacent"].as() == "value"); + YAML_ASSERT(doc["readable"].as() == "value"); + YAML_ASSERT(doc["empty"].IsNull()); + return true; +} + +// 7.19 +TEST SinglePairFlowMappings() { + YAML::Node doc = YAML::Load(ex7_19); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc[0].size() == 1); + YAML_ASSERT(doc[0]["foo"].as() == "bar"); + return true; +} + +// 7.20 +TEST SinglePairExplicitEntry() { + YAML::Node doc = YAML::Load(ex7_20); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc[0].size() == 1); + YAML_ASSERT(doc[0]["foo bar"].as() == "baz"); + return true; +} + +// 7.21 +TEST SinglePairImplicitEntries() { + YAML::Node doc = YAML::Load(ex7_21); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc[0].size() == 1); + YAML_ASSERT(doc[0][0].size() == 1); + YAML_ASSERT(doc[0][0]["YAML"].as() == "separate"); + YAML_ASSERT(doc[1].size() == 1); + YAML_ASSERT(doc[1][0].size() == 1); + YAML_ASSERT(doc[1][0][YAML::Null].as() == "empty key entry"); + YAML_ASSERT(doc[2].size() == 1); + YAML_ASSERT(doc[2][0].size() == 1); + + std::map key; + key["JSON"] = "like"; + YAML_ASSERT(doc[2][0][key].as() == "adjacent"); + return true; +} + +// 7.22 +TEST InvalidImplicitKeys() { + try { + YAML::Load(ex7_22); + } + catch (const YAML::Exception& e) { + if (e.msg == YAML::ErrorMsg::END_OF_SEQ_FLOW) + return true; + + throw; + } + return " no exception thrown"; +} + +// 7.23 +TEST FlowContent() { + YAML::Node doc = YAML::Load(ex7_23); + YAML_ASSERT(doc.size() == 5); + YAML_ASSERT(doc[0].size() == 2); + YAML_ASSERT(doc[0][0].as() == "a"); + YAML_ASSERT(doc[0][1].as() == "b"); + YAML_ASSERT(doc[1].size() == 1); + YAML_ASSERT(doc[1]["a"].as() == "b"); + YAML_ASSERT(doc[2].as() == "a"); + YAML_ASSERT(doc[3].as() == 'b'); + YAML_ASSERT(doc[4].as() == "c"); + return true; +} + +// 7.24 +TEST FlowNodes() { + YAML::Node doc = YAML::Load(ex7_24); + YAML_ASSERT(doc.size() == 5); + YAML_ASSERT(doc[0].Tag() == "tag:yaml.org,2002:str"); + YAML_ASSERT(doc[0].as() == "a"); + YAML_ASSERT(doc[1].as() == 'b'); + YAML_ASSERT(doc[2].as() == "c"); + YAML_ASSERT(doc[3].as() == "c"); + YAML_ASSERT(doc[4].Tag() == "tag:yaml.org,2002:str"); + YAML_ASSERT(doc[4].as() == ""); + return true; +} + +// 8.1 +TEST BlockScalarHeader() { + YAML::Node doc = YAML::Load(ex8_1); + YAML_ASSERT(doc.size() == 4); + YAML_ASSERT(doc[0].as() == "literal\n"); + YAML_ASSERT(doc[1].as() == " folded\n"); + YAML_ASSERT(doc[2].as() == "keep\n\n"); + YAML_ASSERT(doc[3].as() == " strip"); + return true; +} + +// 8.2 +TEST BlockIndentationHeader() { + YAML::Node doc = YAML::Load(ex8_2); + YAML_ASSERT(doc.size() == 4); + YAML_ASSERT(doc[0].as() == "detected\n"); + YAML_ASSERT(doc[1].as() == "\n\n# detected\n"); + YAML_ASSERT(doc[2].as() == " explicit\n"); + YAML_ASSERT(doc[3].as() == "\t\ndetected\n"); + return true; +} + +// 8.3 +TEST InvalidBlockScalarIndentationIndicators() { + { + bool threw = false; + try { + YAML::Load(ex8_3a); + } + catch (const YAML::Exception& e) { + if (e.msg != YAML::ErrorMsg::END_OF_SEQ) + throw; + + threw = true; + } + + if (!threw) + return " no exception thrown for less indented auto-detecting " + "indentation for a literal block scalar"; + } + + { + bool threw = false; + try { + YAML::Load(ex8_3b); + } + catch (const YAML::Exception& e) { + if (e.msg != YAML::ErrorMsg::END_OF_SEQ) + throw; + + threw = true; + } + + if (!threw) + return " no exception thrown for less indented auto-detecting " + "indentation for a folded block scalar"; + } + + { + bool threw = false; + try { + YAML::Load(ex8_3c); + } + catch (const YAML::Exception& e) { + if (e.msg != YAML::ErrorMsg::END_OF_SEQ) + throw; + + threw = true; + } + + if (!threw) + return " no exception thrown for less indented explicit indentation for " + "a literal block scalar"; + } + + return true; +} + +// 8.4 +TEST ChompingFinalLineBreak() { + YAML::Node doc = YAML::Load(ex8_4); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["strip"].as() == "text"); + YAML_ASSERT(doc["clip"].as() == "text\n"); + YAML_ASSERT(doc["keep"].as() == "text\n"); + return true; +} + +// 8.5 +TEST ChompingTrailingLines() { + YAML::Node doc = YAML::Load(ex8_5); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["strip"].as() == "# text"); + YAML_ASSERT(doc["clip"].as() == "# text\n"); + YAML_ASSERT(doc["keep"].as() == "# text\n"); // Note: I believe + // this is a bug in + // the YAML spec - + // it should be "# + // text\n\n" + return true; +} + +// 8.6 +TEST EmptyScalarChomping() { + YAML::Node doc = YAML::Load(ex8_6); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["strip"].as() == ""); + YAML_ASSERT(doc["clip"].as() == ""); + YAML_ASSERT(doc["keep"].as() == "\n"); + return true; +} + +// 8.7 +TEST LiteralScalar() { + YAML::Node doc = YAML::Load(ex8_7); + YAML_ASSERT(doc.as() == "literal\n\ttext\n"); + return true; +} + +// 8.8 +TEST LiteralContent() { + YAML::Node doc = YAML::Load(ex8_8); + YAML_ASSERT(doc.as() == "\n\nliteral\n \n\ntext\n"); + return true; +} + +// 8.9 +TEST FoldedScalar() { + YAML::Node doc = YAML::Load(ex8_9); + YAML_ASSERT(doc.as() == "folded text\n"); + return true; +} + +// 8.10 +TEST FoldedLines() { + YAML::Node doc = YAML::Load(ex8_10); + YAML_ASSERT(doc.as() == + "\nfolded line\nnext line\n * bullet\n\n * list\n * " + "lines\n\nlast line\n"); + return true; +} + +// 8.11 +TEST MoreIndentedLines() { + YAML::Node doc = YAML::Load(ex8_11); + YAML_ASSERT(doc.as() == + "\nfolded line\nnext line\n * bullet\n\n * list\n * " + "lines\n\nlast line\n"); + return true; +} + +// 8.12 +TEST EmptySeparationLines() { + YAML::Node doc = YAML::Load(ex8_12); + YAML_ASSERT(doc.as() == + "\nfolded line\nnext line\n * bullet\n\n * list\n * " + "lines\n\nlast line\n"); + return true; +} + +// 8.13 +TEST FinalEmptyLines() { + YAML::Node doc = YAML::Load(ex8_13); + YAML_ASSERT(doc.as() == + "\nfolded line\nnext line\n * bullet\n\n * list\n * " + "lines\n\nlast line\n"); + return true; +} + +// 8.14 +TEST BlockSequence() { + YAML::Node doc = YAML::Load(ex8_14); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc["block sequence"].size() == 2); + YAML_ASSERT(doc["block sequence"][0].as() == "one"); + YAML_ASSERT(doc["block sequence"][1].size() == 1); + YAML_ASSERT(doc["block sequence"][1]["two"].as() == "three"); + return true; +} + +// 8.15 +TEST BlockSequenceEntryTypes() { + YAML::Node doc = YAML::Load(ex8_15); + YAML_ASSERT(doc.size() == 4); + YAML_ASSERT(doc[0].IsNull()); + YAML_ASSERT(doc[1].as() == "block node\n"); + YAML_ASSERT(doc[2].size() == 2); + YAML_ASSERT(doc[2][0].as() == "one"); + YAML_ASSERT(doc[2][1].as() == "two"); + YAML_ASSERT(doc[3].size() == 1); + YAML_ASSERT(doc[3]["one"].as() == "two"); + return true; +} + +// 8.16 +TEST BlockMappings() { + YAML::Node doc = YAML::Load(ex8_16); + YAML_ASSERT(doc.size() == 1); + YAML_ASSERT(doc["block mapping"].size() == 1); + YAML_ASSERT(doc["block mapping"]["key"].as() == "value"); + return true; +} + +// 8.17 +TEST ExplicitBlockMappingEntries() { + YAML::Node doc = YAML::Load(ex8_17); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["explicit key"].IsNull()); + YAML_ASSERT(doc["block key\n"].size() == 2); + YAML_ASSERT(doc["block key\n"][0].as() == "one"); + YAML_ASSERT(doc["block key\n"][1].as() == "two"); + return true; +} + +// 8.18 +TEST ImplicitBlockMappingEntries() { + YAML::Node doc = YAML::Load(ex8_18); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc["plain key"].as() == "in-line value"); + YAML_ASSERT(doc[YAML::Null].IsNull()); + YAML_ASSERT(doc["quoted key"].size() == 1); + YAML_ASSERT(doc["quoted key"][0].as() == "entry"); + return true; +} + +// 8.19 +TEST CompactBlockMappings() { + YAML::Node doc = YAML::Load(ex8_19); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc[0].size() == 1); + YAML_ASSERT(doc[0]["sun"].as() == "yellow"); + YAML_ASSERT(doc[1].size() == 1); + std::map key; + key["earth"] = "blue"; + YAML_ASSERT(doc[1][key].size() == 1); + YAML_ASSERT(doc[1][key]["moon"].as() == "white"); + return true; +} + +// 8.20 +TEST BlockNodeTypes() { + YAML::Node doc = YAML::Load(ex8_20); + YAML_ASSERT(doc.size() == 3); + YAML_ASSERT(doc[0].as() == "flow in block"); + YAML_ASSERT(doc[1].as() == "Block scalar\n"); + YAML_ASSERT(doc[2].size() == 1); + YAML_ASSERT(doc[2]["foo"].as() == "bar"); + return true; +} + +// 8.21 +TEST BlockScalarNodes() { + YAML::Node doc = YAML::Load(ex8_21); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["literal"].as() == "value"); // Note: I believe + // this is a bug in + // the YAML spec - + // it should be + // "value\n" + YAML_ASSERT(doc["folded"].as() == "value"); + YAML_ASSERT(doc["folded"].Tag() == "!foo"); + return true; +} + +// 8.22 +TEST BlockCollectionNodes() { + YAML::Node doc = YAML::Load(ex8_22); + YAML_ASSERT(doc.size() == 2); + YAML_ASSERT(doc["sequence"].size() == 2); + YAML_ASSERT(doc["sequence"][0].as() == "entry"); + YAML_ASSERT(doc["sequence"][1].size() == 1); + YAML_ASSERT(doc["sequence"][1][0].as() == "nested"); + YAML_ASSERT(doc["mapping"].size() == 1); + YAML_ASSERT(doc["mapping"]["foo"].as() == "bar"); + return true; +} +} } diff --git a/test/nodetests.h b/test/nodetests.h index 733e782..6728758 100644 --- a/test/nodetests.h +++ b/test/nodetests.h @@ -1,13 +1,14 @@ #ifndef NODETESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define NODETESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#if defined(_MSC_VER) || \ + (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ + (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 #pragma once #endif namespace Test { - bool RunNodeTests(); +bool RunNodeTests(); } -#endif // NODETESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A6666 - +#endif // NODETESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A6666 diff --git a/test/tests.cpp b/test/tests.cpp index efe82fc..3c20995 100644 --- a/test/tests.cpp +++ b/test/tests.cpp @@ -9,25 +9,22 @@ #include #include -namespace Test -{ - void RunAll() - { - bool passed = true; - if(!RunParserTests()) - passed = false; - - if(!RunEmitterTests()) - passed = false; +namespace Test { +void RunAll() { + bool passed = true; + if (!RunParserTests()) + passed = false; - if(!RunSpecTests()) - passed = false; + if (!RunEmitterTests()) + passed = false; - if(!RunNodeTests()) - passed = false; + if (!RunSpecTests()) + passed = false; - if(passed) - std::cout << "All tests passed!\n"; - } + if (!RunNodeTests()) + passed = false; + + if (passed) + std::cout << "All tests passed!\n"; +} } - diff --git a/util/parse.cpp b/util/parse.cpp index ca112e0..7794177 100644 --- a/util/parse.cpp +++ b/util/parse.cpp @@ -5,56 +5,57 @@ #include struct Params { - bool hasFile; - std::string fileName; + bool hasFile; + std::string fileName; }; -Params ParseArgs(int argc, char **argv) { - Params p; +Params ParseArgs(int argc, char** argv) { + Params p; - std::vector args(argv + 1, argv + argc); - - return p; + std::vector args(argv + 1, argv + argc); + + return p; } -class NullEventHandler: public YAML::EventHandler -{ -public: - virtual void OnDocumentStart(const YAML::Mark&) {} - virtual void OnDocumentEnd() {} - - virtual void OnNull(const YAML::Mark&, YAML::anchor_t) {} - virtual void OnAlias(const YAML::Mark&, YAML::anchor_t) {} - virtual void OnScalar(const YAML::Mark&, const std::string&, YAML::anchor_t, const std::string&) {} - - virtual void OnSequenceStart(const YAML::Mark&, const std::string&, YAML::anchor_t) {} - virtual void OnSequenceEnd() {} - - virtual void OnMapStart(const YAML::Mark&, const std::string&, YAML::anchor_t) {} - virtual void OnMapEnd() {} +class NullEventHandler : public YAML::EventHandler { + public: + virtual void OnDocumentStart(const YAML::Mark&) {} + virtual void OnDocumentEnd() {} + + virtual void OnNull(const YAML::Mark&, YAML::anchor_t) {} + virtual void OnAlias(const YAML::Mark&, YAML::anchor_t) {} + virtual void OnScalar(const YAML::Mark&, const std::string&, YAML::anchor_t, + const std::string&) {} + + virtual void OnSequenceStart(const YAML::Mark&, const std::string&, + YAML::anchor_t) {} + virtual void OnSequenceEnd() {} + + virtual void OnMapStart(const YAML::Mark&, const std::string&, + YAML::anchor_t) {} + virtual void OnMapEnd() {} }; -void parse(std::istream& input) -{ - try { - YAML::Node doc = YAML::Load(input); - std::cout << doc << "\n"; - } catch(const YAML::Exception& e) { - std::cerr << e.what() << "\n"; - } +void parse(std::istream& input) { + try { + YAML::Node doc = YAML::Load(input); + std::cout << doc << "\n"; + } + catch (const YAML::Exception& e) { + std::cerr << e.what() << "\n"; + } } -int main(int argc, char **argv) -{ - Params p = ParseArgs(argc, argv); +int main(int argc, char** argv) { + Params p = ParseArgs(argc, argv); - if(argc > 1) { - std::ifstream fin; - fin.open(argv[1]); - parse(fin); - } else { - parse(std::cin); - } + if (argc > 1) { + std::ifstream fin; + fin.open(argv[1]); + parse(fin); + } else { + parse(std::cin); + } - return 0; + return 0; } From 97e3765ced43165376f4e4df5ed2ada360c3d662 Mon Sep 17 00:00:00 2001 From: beder Date: Sat, 22 Mar 2014 19:32:53 -0500 Subject: [PATCH 31/43] Add missing includes to node_data.h --- include/yaml-cpp/node/detail/node_data.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/yaml-cpp/node/detail/node_data.h b/include/yaml-cpp/node/detail/node_data.h index 50dd85a..2892610 100644 --- a/include/yaml-cpp/node/detail/node_data.h +++ b/include/yaml-cpp/node/detail/node_data.h @@ -13,6 +13,8 @@ #include "yaml-cpp/node/type.h" #include #include +#include +#include #include #include From a5260a1154a8d70294763f5ec2049a71261e6dce Mon Sep 17 00:00:00 2001 From: beder Date: Sat, 22 Mar 2014 23:14:48 -0500 Subject: [PATCH 32/43] Run IWYU --- include/yaml-cpp/node/convert.h | 17 +++++++++++++---- include/yaml-cpp/node/detail/memory.h | 12 ++++++++++-- include/yaml-cpp/node/detail/node_data.h | 17 +++++++++++++---- include/yaml-cpp/node/node.h | 15 ++++++++++++--- src/convert.cpp | 4 ++-- src/memory.cpp | 4 +++- src/node_data.cpp | 15 +++++++++++---- src/nodebuilder.cpp | 13 +++++++++---- src/nodebuilder.h | 11 ++++++++++- src/nodeevents.cpp | 6 ++++-- src/nodeevents.h | 11 +++++++++-- src/parse.cpp | 7 ++++--- test/emittertests.cpp | 1 - test/new-api/nodetests.cpp | 11 ++++++++--- test/new-api/spectests.cpp | 7 ++++--- test/spectests.cpp | 4 ---- util/parse.cpp | 5 +++-- 17 files changed, 115 insertions(+), 45 deletions(-) diff --git a/include/yaml-cpp/node/convert.h b/include/yaml-cpp/node/convert.h index 76ceee5..2c7a40a 100644 --- a/include/yaml-cpp/node/convert.h +++ b/include/yaml-cpp/node/convert.h @@ -7,16 +7,25 @@ #pragma once #endif -#include "yaml-cpp/binary.h" -#include "yaml-cpp/node/node.h" -#include "yaml-cpp/node/iterator.h" -#include "yaml-cpp/null.h" #include #include #include #include #include +#include "yaml-cpp/binary.h" +#include "yaml-cpp/node/impl.h" +#include "yaml-cpp/node/iterator.h" +#include "yaml-cpp/node/node.h" +#include "yaml-cpp/node/type.h" +#include "yaml-cpp/null.h" + +namespace YAML { +class Binary; +struct _Null; +template struct convert; +} // namespace YAML + namespace YAML { namespace conversion { inline bool IsInfinity(const std::string& input) { diff --git a/include/yaml-cpp/node/detail/memory.h b/include/yaml-cpp/node/detail/memory.h index 4584add..b5f257f 100644 --- a/include/yaml-cpp/node/detail/memory.h +++ b/include/yaml-cpp/node/detail/memory.h @@ -7,9 +7,17 @@ #pragma once #endif -#include "yaml-cpp/node/ptr.h" -#include #include +#include +#include + +#include "yaml-cpp/node/ptr.h" + +namespace YAML { +namespace detail { +class node; +} // namespace detail +} // namespace YAML namespace YAML { namespace detail { diff --git a/include/yaml-cpp/node/detail/node_data.h b/include/yaml-cpp/node/detail/node_data.h index 2892610..f82e332 100644 --- a/include/yaml-cpp/node/detail/node_data.h +++ b/include/yaml-cpp/node/detail/node_data.h @@ -7,10 +7,7 @@ #pragma once #endif -#include "yaml-cpp/dll.h" -#include "yaml-cpp/node/iterator.h" -#include "yaml-cpp/node/ptr.h" -#include "yaml-cpp/node/type.h" +#include #include #include #include @@ -18,6 +15,18 @@ #include #include +#include "yaml-cpp/dll.h" +#include "yaml-cpp/node/detail/node_iterator.h" +#include "yaml-cpp/node/iterator.h" +#include "yaml-cpp/node/ptr.h" +#include "yaml-cpp/node/type.h" + +namespace YAML { +namespace detail { +class node; +} // namespace detail +} // namespace YAML + namespace YAML { namespace detail { class node_data : private boost::noncopyable { diff --git a/include/yaml-cpp/node/node.h b/include/yaml-cpp/node/node.h index 75df149..394750f 100644 --- a/include/yaml-cpp/node/node.h +++ b/include/yaml-cpp/node/node.h @@ -7,12 +7,21 @@ #pragma once #endif +#include + #include "yaml-cpp/dll.h" +#include "yaml-cpp/node/detail/bool_type.h" +#include "yaml-cpp/node/detail/iterator_fwd.h" #include "yaml-cpp/node/ptr.h" #include "yaml-cpp/node/type.h" -#include "yaml-cpp/node/detail/iterator_fwd.h" -#include "yaml-cpp/node/detail/bool_type.h" -#include + +namespace YAML { +namespace detail { +class node; +class node_data; +struct iterator_value; +} // namespace detail +} // namespace YAML namespace YAML { class Node { diff --git a/src/convert.cpp b/src/convert.cpp index 50b15bc..349e2f7 100644 --- a/src/convert.cpp +++ b/src/convert.cpp @@ -1,7 +1,7 @@ -#include "yaml-cpp/node/convert.h" -#include "yaml-cpp/node/impl.h" #include +#include "yaml-cpp/node/convert.h" + namespace { // we're not gonna mess with the mess that is all the isupper/etc. functions bool IsLower(char ch) { return 'a' <= ch && ch <= 'z'; } diff --git a/src/memory.cpp b/src/memory.cpp index 1a02bf0..e5f8a9d 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -1,8 +1,10 @@ #include "yaml-cpp/node/detail/memory.h" -#include "yaml-cpp/node/detail/node.h" +#include "yaml-cpp/node/detail/node.h" // IWYU pragma: keep +#include "yaml-cpp/node/ptr.h" namespace YAML { namespace detail { + void memory_holder::merge(memory_holder& rhs) { if (m_pMemory == rhs.m_pMemory) return; diff --git a/src/node_data.cpp b/src/node_data.cpp index db80be9..90be9b9 100644 --- a/src/node_data.cpp +++ b/src/node_data.cpp @@ -1,11 +1,18 @@ -#include "yaml-cpp/node/detail/node_data.h" -#include "yaml-cpp/node/detail/memory.h" -#include "yaml-cpp/node/detail/node.h" -#include "yaml-cpp/exceptions.h" +#include +#include #include +#include "yaml-cpp/exceptions.h" +#include "yaml-cpp/node/detail/memory.h" +#include "yaml-cpp/node/detail/node.h" // IWYU pragma: keep +#include "yaml-cpp/node/detail/node_data.h" +#include "yaml-cpp/node/detail/node_iterator.h" +#include "yaml-cpp/node/ptr.h" +#include "yaml-cpp/node/type.h" + namespace YAML { namespace detail { + std::string node_data::empty_scalar; node_data::node_data() diff --git a/src/nodebuilder.cpp b/src/nodebuilder.cpp index 3ef2f7d..c69effa 100644 --- a/src/nodebuilder.cpp +++ b/src/nodebuilder.cpp @@ -1,10 +1,15 @@ -#include "nodebuilder.h" -#include "yaml-cpp/mark.h" -#include "yaml-cpp/node/node.h" -#include "yaml-cpp/node/impl.h" +#include #include +#include "nodebuilder.h" +#include "yaml-cpp/node/detail/node.h" +#include "yaml-cpp/node/impl.h" +#include "yaml-cpp/node/node.h" +#include "yaml-cpp/node/type.h" + namespace YAML { +struct Mark; + NodeBuilder::NodeBuilder() : m_pMemory(new detail::memory_holder), m_pRoot(0), m_mapDepth(0) { m_anchors.push_back(0); // since the anchors start at 1 diff --git a/src/nodebuilder.h b/src/nodebuilder.h index 3600561..5006023 100644 --- a/src/nodebuilder.h +++ b/src/nodebuilder.h @@ -7,9 +7,18 @@ #pragma once #endif +#include + +#include "yaml-cpp/anchor.h" #include "yaml-cpp/eventhandler.h" #include "yaml-cpp/node/ptr.h" -#include + +namespace YAML { +namespace detail { +class node; +} // namespace detail +struct Mark; +} // namespace YAML namespace YAML { class Node; diff --git a/src/nodeevents.cpp b/src/nodeevents.cpp index 1f07482..38fa4d7 100644 --- a/src/nodeevents.cpp +++ b/src/nodeevents.cpp @@ -1,8 +1,10 @@ #include "nodeevents.h" -#include "yaml-cpp/node/node.h" -#include "yaml-cpp/node/impl.h" #include "yaml-cpp/eventhandler.h" #include "yaml-cpp/mark.h" +#include "yaml-cpp/node/detail/node.h" +#include "yaml-cpp/node/detail/node_iterator.h" +#include "yaml-cpp/node/node.h" +#include "yaml-cpp/node/type.h" namespace YAML { void NodeEvents::AliasManager::RegisterReference(const detail::node& node) { diff --git a/src/nodeevents.h b/src/nodeevents.h index 98b26ba..49c18eb 100644 --- a/src/nodeevents.h +++ b/src/nodeevents.h @@ -7,11 +7,18 @@ #pragma once #endif -#include "yaml-cpp/anchor.h" -#include "yaml-cpp/node/ptr.h" #include #include +#include "yaml-cpp/anchor.h" +#include "yaml-cpp/node/ptr.h" + +namespace YAML { +namespace detail { +class node; +} // namespace detail +} // namespace YAML + namespace YAML { class EventHandler; class Node; diff --git a/src/parse.cpp b/src/parse.cpp index 06292ae..1ef474d 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -1,12 +1,13 @@ #include "yaml-cpp/node/parse.h" + +#include +#include + #include "yaml-cpp/node/node.h" #include "yaml-cpp/node/impl.h" #include "yaml-cpp/parser.h" #include "nodebuilder.h" -#include -#include - namespace YAML { Node Load(const std::string& input) { std::stringstream stream(input); diff --git a/test/emittertests.cpp b/test/emittertests.cpp index 1cade03..8ba4937 100644 --- a/test/emittertests.cpp +++ b/test/emittertests.cpp @@ -1,7 +1,6 @@ #include #include "teststruct.h" -#include "yaml-cpp/eventhandler.h" #include "yaml-cpp/yaml.h" // IWYU pragma: keep namespace Test { diff --git a/test/new-api/nodetests.cpp b/test/new-api/nodetests.cpp index 8d77c6f..7c47674 100644 --- a/test/new-api/nodetests.cpp +++ b/test/new-api/nodetests.cpp @@ -1,8 +1,13 @@ -#include "nodetests.h" -#include "yaml-cpp/yaml.h" +#include #include -#include +#include "nodetests.h" +#include "yaml-cpp/yaml.h" // IWYU pragma: keep + +namespace YAML { +class InvalidNode; +template class TypedBadConversion; +} // namespace YAML #if BOOST_VERSION >= 103400 #include diff --git a/test/new-api/spectests.cpp b/test/new-api/spectests.cpp index 52b4e7e..eda2867 100644 --- a/test/new-api/spectests.cpp +++ b/test/new-api/spectests.cpp @@ -1,8 +1,9 @@ -#include "spectests.h" -#include "specexamples.h" -#include "yaml-cpp/yaml.h" #include +#include "specexamples.h" +#include "spectests.h" +#include "yaml-cpp/yaml.h" // IWYU pragma: keep + #define YAML_ASSERT(cond) \ do { \ if (!(cond)) \ diff --git a/test/spectests.cpp b/test/spectests.cpp index 156501f..907e161 100644 --- a/test/spectests.cpp +++ b/test/spectests.cpp @@ -3,10 +3,6 @@ #include "spectests.h" #include "yaml-cpp/yaml.h" // IWYU pragma: keep -namespace YAML { -class Exception; -} // namespace YAML - namespace Test { namespace { void RunSpecTest(TEST (*test)(), const std::string& index, diff --git a/util/parse.cpp b/util/parse.cpp index 7794177..6596db8 100644 --- a/util/parse.cpp +++ b/util/parse.cpp @@ -1,9 +1,10 @@ -#include "yaml-cpp/yaml.h" -#include "yaml-cpp/eventhandler.h" #include #include #include +#include "yaml-cpp/eventhandler.h" +#include "yaml-cpp/yaml.h" // IWYU pragma: keep + struct Params { bool hasFile; std::string fileName; From 5ff32c0efe11eb9bd55058ea6af769cf09381b9f Mon Sep 17 00:00:00 2001 From: beder Date: Sat, 22 Mar 2014 23:29:14 -0500 Subject: [PATCH 33/43] Add test for cloning a null node --- test/CMakeLists.txt | 2 +- test/node/node_test.cpp | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 test/node/node_test.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 1f2df7c..aeacac9 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -2,7 +2,7 @@ add_subdirectory(gtest-1.7.0) include_directories(gtest-1.7.0/include) file(GLOB test_headers [a-z_]*.h) -file(GLOB test_sources [a-z_]*.cpp) +file(GLOB test_sources [a-z_]*.cpp node/[a-z_]*.cpp) file(GLOB test_new_api_sources new-api/[a-z]*.cpp) list(APPEND test_sources ${test_new_api_sources}) diff --git a/test/node/node_test.cpp b/test/node/node_test.cpp new file mode 100644 index 0000000..0830e0e --- /dev/null +++ b/test/node/node_test.cpp @@ -0,0 +1,12 @@ +#include "gtest/gtest.h" +#include "yaml-cpp/node/node.h" + +namespace YAML { +namespace { +TEST(NodeTest, CloneNull) { + Node node; + Node clone = Clone(node); + EXPECT_EQ(NodeType::Null, clone.Type()); +} +} +} From e683a2bb6814898c9e9ef2d1e05c5e416e59065b Mon Sep 17 00:00:00 2001 From: beder Date: Sun, 23 Mar 2014 19:21:13 -0500 Subject: [PATCH 34/43] Convert node tests to gtest --- test/integration/load_node_test.cpp | 191 +++++++++ test/main.cpp | 3 - test/new-api/nodetests.cpp | 600 ---------------------------- test/node/node_test.cpp | 249 +++++++++++- test/nodetests.h | 14 - test/tests.cpp | 18 - test/tests.h | 56 --- test/teststruct.h | 20 - 8 files changed, 439 insertions(+), 712 deletions(-) create mode 100644 test/integration/load_node_test.cpp delete mode 100644 test/new-api/nodetests.cpp delete mode 100644 test/nodetests.h delete mode 100644 test/tests.cpp delete mode 100644 test/tests.h delete mode 100644 test/teststruct.h diff --git a/test/integration/load_node_test.cpp b/test/integration/load_node_test.cpp new file mode 100644 index 0000000..4c4c826 --- /dev/null +++ b/test/integration/load_node_test.cpp @@ -0,0 +1,191 @@ +#include "yaml-cpp/yaml.h" // IWYU pragma: keep + +#include "gtest/gtest.h" + +namespace YAML { +namespace { +TEST(LoadNodeTest, Reassign) { + YAML::Node node = YAML::Load("foo"); + node = YAML::Node(); +} + +TEST(LoadNodeTest, FallbackValues) { + YAML::Node node = YAML::Load("foo: bar\nx: 2"); + EXPECT_EQ("bar", node["foo"].as()); + EXPECT_EQ("bar", node["foo"].as("hello")); + EXPECT_EQ("hello", node["baz"].as("hello")); + EXPECT_EQ(2, node["x"].as()); + EXPECT_EQ(2, node["x"].as(5)); + EXPECT_EQ(5, node["y"].as(5)); +} + +TEST(LoadNodeTest, NumericConversion) { + YAML::Node node = YAML::Load("[1.5, 1, .nan, .inf, -.inf, 0x15, 015]"); + EXPECT_EQ(1.5f, node[0].as()); + EXPECT_EQ(1.5, node[0].as()); + EXPECT_THROW(node[0].as(), YAML::TypedBadConversion); + EXPECT_EQ(1, node[1].as()); + EXPECT_EQ(1.0f, node[1].as()); + EXPECT_NE(node[2].as(), node[2].as()); + EXPECT_EQ(std::numeric_limits::infinity(), node[3].as()); + EXPECT_EQ(-std::numeric_limits::infinity(), node[4].as()); + EXPECT_EQ(21, node[5].as()); + EXPECT_EQ(13, node[6].as()); +} + +TEST(LoadNodeTest, Binary) { + YAML::Node node = YAML::Load( + "[!!binary \"SGVsbG8sIFdvcmxkIQ==\", !!binary " + "\"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieS" + "B0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIG" + "x1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbi" + "B0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZG" + "dlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS" + "4K\"]"); + EXPECT_EQ( + YAML::Binary(reinterpret_cast("Hello, World!"), 13), + node[0].as()); + EXPECT_EQ(YAML::Binary(reinterpret_cast( + "Man is distinguished, not only by his reason, " + "but by this singular passion from other " + "animals, which is a lust of the mind, that by " + "a perseverance of delight in the continued and " + "indefatigable generation of knowledge, exceeds " + "the short vehemence of any carnal pleasure.\n"), + 270), + node[1].as()); +} + +TEST(LoadNodeTest, IterateSequence) { + YAML::Node node = YAML::Load("[1, 3, 5, 7]"); + int seq[] = {1, 3, 5, 7}; + int i = 0; + for (YAML::const_iterator it = node.begin(); it != node.end(); ++it) { + EXPECT_TRUE(i < 4); + int x = seq[i++]; + EXPECT_EQ(x, it->as()); + } + EXPECT_EQ(4, i); +} + +TEST(LoadNodeTest, IterateMap) { + YAML::Node node = YAML::Load("{a: A, b: B, c: C}"); + int i = 0; + for (YAML::const_iterator it = node.begin(); it != node.end(); ++it) { + EXPECT_TRUE(i < 3); + i++; + EXPECT_EQ(it->second.as(), it->first.as() + 'A' - 'a'); + } + EXPECT_EQ(3, i); +} + +#ifdef BOOST_FOREACH +TEST(LoadNodeTest, ForEach) { + YAML::Node node = YAML::Load("[1, 3, 5, 7]"); + int seq[] = {1, 3, 5, 7}; + int i = 0; + BOOST_FOREACH(const YAML::Node & item, node) { + int x = seq[i++]; + EXPECT_EQ(x, item.as()); + } +} + +TEST(LoadNodeTest, ForEachMap) { + YAML::Node node = YAML::Load("{a: A, b: B, c: C}"); + BOOST_FOREACH(const YAML::const_iterator::value_type & p, node) { + EXPECT_EQ(p.second.as(), p.first.as() + 'A' - 'a'); + } +} +#endif + +TEST(LoadNodeTest, CloneScalar) { + YAML::Node node = YAML::Load("!foo monkey"); + YAML::Node clone = Clone(node); + EXPECT_FALSE(clone == node); + EXPECT_EQ(clone.as(), node.as()); + EXPECT_EQ(clone.Tag(), node.Tag()); +} + +TEST(LoadNodeTest, CloneSeq) { + YAML::Node node = YAML::Load("[1, 3, 5, 7]"); + YAML::Node clone = Clone(node); + EXPECT_FALSE(clone == node); + EXPECT_EQ(YAML::NodeType::Sequence, clone.Type()); + EXPECT_EQ(clone.size(), node.size()); + for (std::size_t i = 0; i < node.size(); i++) { + EXPECT_EQ(clone[i].as(), node[i].as()); + } +} + +TEST(LoadNodeTest, CloneMap) { + YAML::Node node = YAML::Load("{foo: bar}"); + YAML::Node clone = Clone(node); + EXPECT_FALSE(clone == node); + EXPECT_EQ(YAML::NodeType::Map, clone.Type()); + EXPECT_EQ(clone.size(), node.size()); + EXPECT_EQ(clone["foo"].as(), node["foo"].as()); +} + +TEST(LoadNodeTest, CloneAlias) { + YAML::Node node = YAML::Load("&foo [*foo]"); + YAML::Node clone = Clone(node); + EXPECT_FALSE(clone == node); + EXPECT_EQ(YAML::NodeType::Sequence, clone.Type()); + EXPECT_EQ(clone.size(), node.size()); + EXPECT_EQ(clone[0], clone); +} + +TEST(LoadNodeTest, ForceInsertIntoMap) { + YAML::Node node; + node["a"] = "b"; + node.force_insert("x", "y"); + node.force_insert("a", 5); + EXPECT_EQ(3, node.size()); + EXPECT_EQ(YAML::NodeType::Map, node.Type()); + bool ab = false; + bool a5 = false; + bool xy = false; + for (YAML::const_iterator it = node.begin(); it != node.end(); ++it) { + if (it->first.as() == "a") { + if (it->second.as() == "b") + ab = true; + else if (it->second.as() == "5") + a5 = true; + } else if (it->first.as() == "x" && + it->second.as() == "y") + xy = true; + } + EXPECT_TRUE(ab); + EXPECT_TRUE(a5); + EXPECT_TRUE(xy); +} + +TEST(LoadNodeTest, ResetNode) { + YAML::Node node = YAML::Load("[1, 2, 3]"); + EXPECT_TRUE(!node.IsNull()); + YAML::Node other = node; + node.reset(); + EXPECT_TRUE(node.IsNull()); + EXPECT_TRUE(!other.IsNull()); + node.reset(other); + EXPECT_TRUE(!node.IsNull()); + EXPECT_EQ(node, other); +} + +TEST(LoadNodeTest, DereferenceIteratorError) { + YAML::Node node = YAML::Load("[{a: b}, 1, 2]"); + EXPECT_THROW(node.begin()->first.as(), YAML::InvalidNode); + EXPECT_EQ(true, (*node.begin()).IsMap()); + EXPECT_EQ(true, node.begin()->IsMap()); + EXPECT_THROW((*node.begin()->begin()).IsDefined(), YAML::InvalidNode); + EXPECT_THROW(node.begin()->begin()->IsDefined(), YAML::InvalidNode); +} + +TEST(NodeTest, EmitEmptyNode) { + YAML::Node node; + YAML::Emitter emitter; + emitter << node; + EXPECT_EQ("", std::string(emitter.c_str())); +} +} +} diff --git a/test/main.cpp b/test/main.cpp index dd65123..443e2db 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -1,9 +1,6 @@ -#include "tests.h" - #include "gtest/gtest.h" int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); - Test::RunAll(); return RUN_ALL_TESTS(); } diff --git a/test/new-api/nodetests.cpp b/test/new-api/nodetests.cpp deleted file mode 100644 index 7c47674..0000000 --- a/test/new-api/nodetests.cpp +++ /dev/null @@ -1,600 +0,0 @@ -#include -#include - -#include "nodetests.h" -#include "yaml-cpp/yaml.h" // IWYU pragma: keep - -namespace YAML { -class InvalidNode; -template class TypedBadConversion; -} // namespace YAML - -#if BOOST_VERSION >= 103400 -#include -#endif - -namespace { -struct TEST { - TEST() : ok(false) {} - TEST(bool ok_) : ok(ok_) {} - TEST(const char* error_) : ok(false), error(error_) {} - TEST(const std::string& error_) : ok(false), error(error_) {} - - bool ok; - std::string error; -}; -} - -#define YAML_ASSERT(cond) \ - do { \ - if (!(cond)) \ - return " Assert failed: " #cond; \ - } while (false) - -#define YAML_ASSERT_THROWS(cond, exc) \ - do { \ - try { \ - (cond); \ - return " Expression did not throw: " #cond; \ - } \ - catch (const exc&) { \ - } \ - catch (const std::runtime_error& e) { \ - std::stringstream stream; \ - stream << " Expression threw runtime error ther than " #exc \ - ":\n " #cond "\n " << e.what(); \ - return stream.str(); \ - } \ - catch (...) { \ - return " Expression threw unknown exception, other than " #exc \ - ":\n " #cond; \ - } \ - } while (false) - -namespace Test { -namespace Node { -TEST SimpleScalar() { - YAML::Node node = YAML::Node("Hello, World!"); - YAML_ASSERT(node.IsScalar()); - YAML_ASSERT(node.as() == "Hello, World!"); - return true; -} - -TEST IntScalar() { - YAML::Node node = YAML::Node(15); - YAML_ASSERT(node.IsScalar()); - YAML_ASSERT(node.as() == 15); - return true; -} - -TEST SimpleAppendSequence() { - YAML::Node node; - node.push_back(10); - node.push_back("foo"); - node.push_back("monkey"); - YAML_ASSERT(node.IsSequence()); - YAML_ASSERT(node.size() == 3); - YAML_ASSERT(node[0].as() == 10); - YAML_ASSERT(node[1].as() == "foo"); - YAML_ASSERT(node[2].as() == "monkey"); - YAML_ASSERT(node.IsSequence()); - return true; -} - -TEST SimpleAssignSequence() { - YAML::Node node; - node[0] = 10; - node[1] = "foo"; - node[2] = "monkey"; - YAML_ASSERT(node.IsSequence()); - YAML_ASSERT(node.size() == 3); - YAML_ASSERT(node[0].as() == 10); - YAML_ASSERT(node[1].as() == "foo"); - YAML_ASSERT(node[2].as() == "monkey"); - YAML_ASSERT(node.IsSequence()); - return true; -} - -TEST SimpleMap() { - YAML::Node node; - node["key"] = "value"; - YAML_ASSERT(node.IsMap()); - YAML_ASSERT(node["key"].as() == "value"); - YAML_ASSERT(node.size() == 1); - return true; -} - -TEST MapWithUndefinedValues() { - YAML::Node node; - node["key"] = "value"; - node["undefined"]; - YAML_ASSERT(node.IsMap()); - YAML_ASSERT(node["key"].as() == "value"); - YAML_ASSERT(node.size() == 1); - - node["undefined"] = "monkey"; - YAML_ASSERT(node["undefined"].as() == "monkey"); - YAML_ASSERT(node.size() == 2); - - return true; -} - -TEST MapIteratorWithUndefinedValues() { - YAML::Node node; - node["key"] = "value"; - node["undefined"]; - - std::size_t count = 0; - for (YAML::const_iterator it = node.begin(); it != node.end(); ++it) - count++; - YAML_ASSERT(count == 1); - return true; -} - -TEST SimpleSubkeys() { - YAML::Node node; - node["device"]["udid"] = "12345"; - node["device"]["name"] = "iPhone"; - node["device"]["os"] = "4.0"; - node["username"] = "monkey"; - YAML_ASSERT(node["device"]["udid"].as() == "12345"); - YAML_ASSERT(node["device"]["name"].as() == "iPhone"); - YAML_ASSERT(node["device"]["os"].as() == "4.0"); - YAML_ASSERT(node["username"].as() == "monkey"); - return true; -} - -TEST StdVector() { - std::vector primes; - primes.push_back(2); - primes.push_back(3); - primes.push_back(5); - primes.push_back(7); - primes.push_back(11); - primes.push_back(13); - - YAML::Node node; - node["primes"] = primes; - YAML_ASSERT(node["primes"].as >() == primes); - return true; -} - -TEST StdList() { - std::list primes; - primes.push_back(2); - primes.push_back(3); - primes.push_back(5); - primes.push_back(7); - primes.push_back(11); - primes.push_back(13); - - YAML::Node node; - node["primes"] = primes; - YAML_ASSERT(node["primes"].as >() == primes); - return true; -} - -TEST StdMap() { - std::map squares; - squares[0] = 0; - squares[1] = 1; - squares[2] = 4; - squares[3] = 9; - squares[4] = 16; - - YAML::Node node; - node["squares"] = squares; - YAML_ASSERT((node["squares"].as >() == squares)); - return true; -} - -TEST StdPair() { - std::pair p; - p.first = 5; - p.second = "five"; - - YAML::Node node; - node["pair"] = p; - YAML_ASSERT((node["pair"].as >() == p)); - return true; -} - -TEST SimpleAlias() { - YAML::Node node; - node["foo"] = "value"; - node["bar"] = node["foo"]; - YAML_ASSERT(node["foo"].as() == "value"); - YAML_ASSERT(node["bar"].as() == "value"); - YAML_ASSERT(node["foo"] == node["bar"]); - YAML_ASSERT(node.size() == 2); - return true; -} - -TEST AliasAsKey() { - YAML::Node node; - node["foo"] = "value"; - YAML::Node value = node["foo"]; - node[value] = "foo"; - YAML_ASSERT(node["foo"].as() == "value"); - YAML_ASSERT(node[value].as() == "foo"); - YAML_ASSERT(node["value"].as() == "foo"); - YAML_ASSERT(node.size() == 2); - return true; -} - -TEST SelfReferenceSequence() { - YAML::Node node; - node[0] = node; - YAML_ASSERT(node.IsSequence()); - YAML_ASSERT(node.size() == 1); - YAML_ASSERT(node[0] == node); - YAML_ASSERT(node[0][0] == node); - YAML_ASSERT(node[0][0] == node[0]); - return true; -} - -TEST ValueSelfReferenceMap() { - YAML::Node node; - node["key"] = node; - YAML_ASSERT(node.IsMap()); - YAML_ASSERT(node.size() == 1); - YAML_ASSERT(node["key"] == node); - YAML_ASSERT(node["key"]["key"] == node); - YAML_ASSERT(node["key"]["key"] == node["key"]); - return true; -} - -TEST KeySelfReferenceMap() { - YAML::Node node; - node[node] = "value"; - YAML_ASSERT(node.IsMap()); - YAML_ASSERT(node.size() == 1); - YAML_ASSERT(node[node].as() == "value"); - return true; -} - -TEST SelfReferenceMap() { - YAML::Node node; - node[node] = node; - YAML_ASSERT(node.IsMap()); - YAML_ASSERT(node.size() == 1); - YAML_ASSERT(node[node] == node); - YAML_ASSERT(node[node][node] == node); - YAML_ASSERT(node[node][node] == node[node]); - return true; -} - -TEST TempMapVariable() { - YAML::Node node; - YAML::Node tmp = node["key"]; - tmp = "value"; - YAML_ASSERT(node.IsMap()); - YAML_ASSERT(node.size() == 1); - YAML_ASSERT(node["key"].as() == "value"); - return true; -} - -TEST TempMapVariableAlias() { - YAML::Node node; - YAML::Node tmp = node["key"]; - tmp = node["other"]; - node["other"] = "value"; - YAML_ASSERT(node.IsMap()); - YAML_ASSERT(node.size() == 2); - YAML_ASSERT(node["key"].as() == "value"); - YAML_ASSERT(node["other"].as() == "value"); - YAML_ASSERT(node["other"] == node["key"]); - return true; -} - -TEST Bool() { - YAML::Node node; - node[true] = false; - YAML_ASSERT(node.IsMap()); - YAML_ASSERT(node[true].as() == false); - return true; -} - -TEST AutoBoolConversion() { - YAML::Node node; - node["foo"] = "bar"; - YAML_ASSERT(static_cast(node["foo"])); - YAML_ASSERT(!node["monkey"]); - YAML_ASSERT(!!node["foo"]); - return true; -} - -TEST Reassign() { - YAML::Node node = YAML::Load("foo"); - node = YAML::Node(); - return true; -} - -TEST FallbackValues() { - YAML::Node node = YAML::Load("foo: bar\nx: 2"); - YAML_ASSERT(node["foo"].as() == "bar"); - YAML_ASSERT(node["foo"].as("hello") == "bar"); - YAML_ASSERT(node["baz"].as("hello") == "hello"); - YAML_ASSERT(node["x"].as() == 2); - YAML_ASSERT(node["x"].as(5) == 2); - YAML_ASSERT(node["y"].as(5) == 5); - return true; -} - -TEST NumericConversion() { - YAML::Node node = YAML::Load("[1.5, 1, .nan, .inf, -.inf, 0x15, 015]"); - YAML_ASSERT(node[0].as() == 1.5f); - YAML_ASSERT(node[0].as() == 1.5); - YAML_ASSERT_THROWS(node[0].as(), YAML::TypedBadConversion); - YAML_ASSERT(node[1].as() == 1); - YAML_ASSERT(node[1].as() == 1.0f); - YAML_ASSERT(node[2].as() != node[2].as()); - YAML_ASSERT(node[3].as() == std::numeric_limits::infinity()); - YAML_ASSERT(node[4].as() == -std::numeric_limits::infinity()); - YAML_ASSERT(node[5].as() == 21); - YAML_ASSERT(node[6].as() == 13); - return true; -} - -TEST Binary() { - YAML::Node node = YAML::Load( - "[!!binary \"SGVsbG8sIFdvcmxkIQ==\", !!binary " - "\"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieS" - "B0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIG" - "x1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbi" - "B0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZG" - "dlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS" - "4K\"]"); - YAML_ASSERT(node[0].as() == - YAML::Binary( - reinterpret_cast("Hello, World!"), 13)); - YAML_ASSERT(node[1].as() == - YAML::Binary(reinterpret_cast( - "Man is distinguished, not only by his reason, " - "but by this singular passion from other " - "animals, which is a lust of the mind, that by " - "a perseverance of delight in the continued and " - "indefatigable generation of knowledge, exceeds " - "the short vehemence of any carnal pleasure.\n"), - 270)); - return true; -} - -TEST IterateSequence() { - YAML::Node node = YAML::Load("[1, 3, 5, 7]"); - int seq[] = {1, 3, 5, 7}; - int i = 0; - for (YAML::const_iterator it = node.begin(); it != node.end(); ++it) { - YAML_ASSERT(i < 4); - int x = seq[i++]; - YAML_ASSERT(it->as() == x); - } - YAML_ASSERT(i == 4); - return true; -} - -TEST IterateMap() { - YAML::Node node = YAML::Load("{a: A, b: B, c: C}"); - int i = 0; - for (YAML::const_iterator it = node.begin(); it != node.end(); ++it) { - YAML_ASSERT(i < 3); - i++; - YAML_ASSERT(it->first.as() + 'A' - 'a' == it->second.as()); - } - YAML_ASSERT(i == 3); - return true; -} - -#ifdef BOOST_FOREACH -TEST ForEach() { - YAML::Node node = YAML::Load("[1, 3, 5, 7]"); - int seq[] = {1, 3, 5, 7}; - int i = 0; - BOOST_FOREACH(const YAML::Node & item, node) { - int x = seq[i++]; - YAML_ASSERT(item.as() == x); - } - return true; -} - -TEST ForEachMap() { - YAML::Node node = YAML::Load("{a: A, b: B, c: C}"); - BOOST_FOREACH(const YAML::const_iterator::value_type & p, node) { - YAML_ASSERT(p.first.as() + 'A' - 'a' == p.second.as()); - } - return true; -} -#endif - -TEST CloneScalar() { - YAML::Node node = YAML::Load("!foo monkey"); - YAML::Node clone = Clone(node); - YAML_ASSERT(!(node == clone)); - YAML_ASSERT(node.as() == clone.as()); - YAML_ASSERT(node.Tag() == clone.Tag()); - return true; -} - -TEST CloneSeq() { - YAML::Node node = YAML::Load("[1, 3, 5, 7]"); - YAML::Node clone = Clone(node); - YAML_ASSERT(!(node == clone)); - YAML_ASSERT(clone.Type() == YAML::NodeType::Sequence); - YAML_ASSERT(node.size() == clone.size()); - for (std::size_t i = 0; i < node.size(); i++) - YAML_ASSERT(node[i].as() == clone[i].as()); - return true; -} - -TEST CloneMap() { - YAML::Node node = YAML::Load("{foo: bar}"); - YAML::Node clone = Clone(node); - YAML_ASSERT(!(node == clone)); - YAML_ASSERT(clone.Type() == YAML::NodeType::Map); - YAML_ASSERT(node.size() == clone.size()); - YAML_ASSERT(node["foo"].as() == clone["foo"].as()); - return true; -} - -TEST CloneAlias() { - YAML::Node node = YAML::Load("&foo [*foo]"); - YAML::Node clone = Clone(node); - YAML_ASSERT(!(node == clone)); - YAML_ASSERT(clone.Type() == YAML::NodeType::Sequence); - YAML_ASSERT(node.size() == clone.size()); - YAML_ASSERT(clone == clone[0]); - return true; -} - -TEST ForceInsertIntoMap() { - YAML::Node node; - node["a"] = "b"; - node.force_insert("x", "y"); - node.force_insert("a", 5); - YAML_ASSERT(node.size() == 3); - YAML_ASSERT(node.Type() == YAML::NodeType::Map); - bool ab = false; - bool a5 = false; - bool xy = false; - for (YAML::const_iterator it = node.begin(); it != node.end(); ++it) { - if (it->first.as() == "a") { - if (it->second.as() == "b") - ab = true; - else if (it->second.as() == "5") - a5 = true; - } else if (it->first.as() == "x" && - it->second.as() == "y") - xy = true; - } - YAML_ASSERT(ab); - YAML_ASSERT(a5); - YAML_ASSERT(xy); - return true; -} - -TEST ResetNode() { - YAML::Node node = YAML::Load("[1, 2, 3]"); - YAML_ASSERT(!node.IsNull()); - YAML::Node other = node; - node.reset(); - YAML_ASSERT(node.IsNull()); - YAML_ASSERT(!other.IsNull()); - node.reset(other); - YAML_ASSERT(!node.IsNull()); - YAML_ASSERT(other == node); - return true; -} - -TEST DereferenceIteratorError() { - YAML::Node node = YAML::Load("[{a: b}, 1, 2]"); - YAML_ASSERT_THROWS(node.begin()->first.as(), YAML::InvalidNode); - YAML_ASSERT((*node.begin()).IsMap() == true); - YAML_ASSERT(node.begin()->IsMap() == true); - YAML_ASSERT_THROWS((*node.begin()->begin()).IsDefined(), YAML::InvalidNode); - YAML_ASSERT_THROWS(node.begin()->begin()->IsDefined(), YAML::InvalidNode); - return true; -} - -TEST FloatingPrecision() { - const double x = 0.123456789; - YAML::Node node = YAML::Node(x); - YAML_ASSERT(node.as() == x); - return true; -} - -TEST EmitEmptyNode() { - YAML::Node node; - YAML::Emitter emitter; - emitter << node; - YAML_ASSERT(std::string(emitter.c_str()) == ""); - return true; -} - -TEST SpaceChar() { - YAML::Node node = YAML::Node(' '); - YAML_ASSERT(node.as() == ' '); - return true; -} -} - -void RunNodeTest(TEST (*test)(), const std::string& name, int& passed, - int& total) { - TEST ret; - try { - ret = test(); - } - catch (const std::exception& e) { - ret.ok = false; - ret.error = e.what(); - } - if (ret.ok) { - passed++; - } else { - std::cout << "Node test failed: " << name << "\n"; - if (ret.error != "") - std::cout << ret.error << "\n"; - } - total++; -} - -bool RunNodeTests() { - int passed = 0; - int total = 0; - - RunNodeTest(&Node::SimpleScalar, "simple scalar", passed, total); - RunNodeTest(&Node::IntScalar, "int scalar", passed, total); - RunNodeTest(&Node::SimpleAppendSequence, "simple append sequence", passed, - total); - RunNodeTest(&Node::SimpleAssignSequence, "simple assign sequence", passed, - total); - RunNodeTest(&Node::SimpleMap, "simple map", passed, total); - RunNodeTest(&Node::MapWithUndefinedValues, "map with undefined values", - passed, total); - RunNodeTest(&Node::MapIteratorWithUndefinedValues, - "map iterator with undefined values", passed, total); - RunNodeTest(&Node::SimpleSubkeys, "simple subkey", passed, total); - RunNodeTest(&Node::StdVector, "std::vector", passed, total); - RunNodeTest(&Node::StdList, "std::list", passed, total); - RunNodeTest(&Node::StdMap, "std::map", passed, total); - RunNodeTest(&Node::StdPair, "std::pair", passed, total); - RunNodeTest(&Node::SimpleAlias, "simple alias", passed, total); - RunNodeTest(&Node::AliasAsKey, "alias as key", passed, total); - RunNodeTest(&Node::SelfReferenceSequence, "self reference sequence", passed, - total); - RunNodeTest(&Node::ValueSelfReferenceMap, "value self reference map", passed, - total); - RunNodeTest(&Node::KeySelfReferenceMap, "key self reference map", passed, - total); - RunNodeTest(&Node::SelfReferenceMap, "self reference map", passed, total); - RunNodeTest(&Node::TempMapVariable, "temp map variable", passed, total); - RunNodeTest(&Node::TempMapVariableAlias, "temp map variable alias", passed, - total); - RunNodeTest(&Node::Bool, "bool", passed, total); - RunNodeTest(&Node::AutoBoolConversion, "auto bool conversion", passed, total); - RunNodeTest(&Node::Reassign, "reassign", passed, total); - RunNodeTest(&Node::FallbackValues, "fallback values", passed, total); - RunNodeTest(&Node::NumericConversion, "numeric conversion", passed, total); - RunNodeTest(&Node::Binary, "binary", passed, total); - RunNodeTest(&Node::IterateSequence, "iterate sequence", passed, total); - RunNodeTest(&Node::IterateMap, "iterate map", passed, total); -#ifdef BOOST_FOREACH - RunNodeTest(&Node::ForEach, "for each", passed, total); - RunNodeTest(&Node::ForEachMap, "for each map", passed, total); -#endif - RunNodeTest(&Node::CloneScalar, "clone scalar", passed, total); - RunNodeTest(&Node::CloneSeq, "clone seq", passed, total); - RunNodeTest(&Node::CloneMap, "clone map", passed, total); - RunNodeTest(&Node::CloneAlias, "clone alias", passed, total); - RunNodeTest(&Node::ForceInsertIntoMap, "force insert into map", passed, - total); - RunNodeTest(&Node::ResetNode, "reset node", passed, total); - RunNodeTest(&Node::DereferenceIteratorError, "dereference iterator error", - passed, total); - RunNodeTest(&Node::FloatingPrecision, "floating precision", passed, total); - RunNodeTest(&Node::EmitEmptyNode, "emit empty node", passed, total); - RunNodeTest(&Node::SpaceChar, "space char", passed, total); - - std::cout << "Node tests: " << passed << "/" << total << " passed\n"; - return passed == total; -} -} diff --git a/test/node/node_test.cpp b/test/node/node_test.cpp index 0830e0e..830ddd7 100644 --- a/test/node/node_test.cpp +++ b/test/node/node_test.cpp @@ -1,8 +1,255 @@ -#include "gtest/gtest.h" #include "yaml-cpp/node/node.h" +#include "yaml-cpp/node/impl.h" +#include "yaml-cpp/node/convert.h" +#include "yaml-cpp/node/iterator.h" +#include "yaml-cpp/node/detail/impl.h" + +#include "gtest/gtest.h" namespace YAML { namespace { +TEST(NodeTest, SimpleScalar) { + YAML::Node node = YAML::Node("Hello, World!"); + EXPECT_TRUE(node.IsScalar()); + EXPECT_EQ("Hello, World!", node.as()); +} + +TEST(NodeTest, IntScalar) { + YAML::Node node = YAML::Node(15); + EXPECT_TRUE(node.IsScalar()); + EXPECT_EQ(15, node.as()); +} + +TEST(NodeTest, SimpleAppendSequence) { + YAML::Node node; + node.push_back(10); + node.push_back("foo"); + node.push_back("monkey"); + EXPECT_TRUE(node.IsSequence()); + EXPECT_EQ(3, node.size()); + EXPECT_EQ(10, node[0].as()); + EXPECT_EQ("foo", node[1].as()); + EXPECT_EQ("monkey", node[2].as()); + EXPECT_TRUE(node.IsSequence()); +} + +TEST(NodeTest, SimpleAssignSequence) { + YAML::Node node; + node[0] = 10; + node[1] = "foo"; + node[2] = "monkey"; + EXPECT_TRUE(node.IsSequence()); + EXPECT_EQ(3, node.size()); + EXPECT_EQ(10, node[0].as()); + EXPECT_EQ("foo", node[1].as()); + EXPECT_EQ("monkey", node[2].as()); + EXPECT_TRUE(node.IsSequence()); +} + +TEST(NodeTest, SimpleMap) { + YAML::Node node; + node["key"] = "value"; + EXPECT_TRUE(node.IsMap()); + EXPECT_EQ("value", node["key"].as()); + EXPECT_EQ(1, node.size()); +} + +TEST(NodeTest, MapWithUndefinedValues) { + YAML::Node node; + node["key"] = "value"; + node["undefined"]; + EXPECT_TRUE(node.IsMap()); + EXPECT_EQ("value", node["key"].as()); + EXPECT_EQ(1, node.size()); + + node["undefined"] = "monkey"; + EXPECT_EQ("monkey", node["undefined"].as()); + EXPECT_EQ(2, node.size()); +} + +TEST(NodeTest, MapIteratorWithUndefinedValues) { + YAML::Node node; + node["key"] = "value"; + node["undefined"]; + + std::size_t count = 0; + for (const_iterator it = node.begin(); it != node.end(); ++it) + count++; + EXPECT_EQ(1, count); +} + +TEST(NodeTest, SimpleSubkeys) { + YAML::Node node; + node["device"]["udid"] = "12345"; + node["device"]["name"] = "iPhone"; + node["device"]["os"] = "4.0"; + node["username"] = "monkey"; + EXPECT_EQ("12345", node["device"]["udid"].as()); + EXPECT_EQ("iPhone", node["device"]["name"].as()); + EXPECT_EQ("4.0", node["device"]["os"].as()); + EXPECT_EQ("monkey", node["username"].as()); +} + +TEST(NodeTest, StdVector) { + std::vector primes; + primes.push_back(2); + primes.push_back(3); + primes.push_back(5); + primes.push_back(7); + primes.push_back(11); + primes.push_back(13); + + YAML::Node node; + node["primes"] = primes; + EXPECT_EQ(primes, node["primes"].as >()); +} + +TEST(NodeTest, StdList) { + std::list primes; + primes.push_back(2); + primes.push_back(3); + primes.push_back(5); + primes.push_back(7); + primes.push_back(11); + primes.push_back(13); + + YAML::Node node; + node["primes"] = primes; + EXPECT_EQ(primes, node["primes"].as >()); +} + +TEST(NodeTest, StdMap) { + std::map squares; + squares[0] = 0; + squares[1] = 1; + squares[2] = 4; + squares[3] = 9; + squares[4] = 16; + + YAML::Node node; + node["squares"] = squares; + std::map actualSquares = node["squares"].as >(); + EXPECT_EQ(squares, actualSquares); +} + +TEST(NodeTest, StdPair) { + std::pair p; + p.first = 5; + p.second = "five"; + + YAML::Node node; + node["pair"] = p; + std::pair actualP = + node["pair"].as >(); + EXPECT_EQ(p, actualP); +} + +TEST(NodeTest, SimpleAlias) { + YAML::Node node; + node["foo"] = "value"; + node["bar"] = node["foo"]; + EXPECT_EQ("value", node["foo"].as()); + EXPECT_EQ("value", node["bar"].as()); + EXPECT_EQ(node["bar"], node["foo"]); + EXPECT_EQ(2, node.size()); +} + +TEST(NodeTest, AliasAsKey) { + YAML::Node node; + node["foo"] = "value"; + YAML::Node value = node["foo"]; + node[value] = "foo"; + EXPECT_EQ("value", node["foo"].as()); + EXPECT_EQ("foo", node[value].as()); + EXPECT_EQ("foo", node["value"].as()); + EXPECT_EQ(2, node.size()); +} + +TEST(NodeTest, SelfReferenceSequence) { + YAML::Node node; + node[0] = node; + EXPECT_TRUE(node.IsSequence()); + EXPECT_EQ(1, node.size()); + EXPECT_EQ(node, node[0]); + EXPECT_EQ(node, node[0][0]); + EXPECT_EQ(node[0], node[0][0]); +} + +TEST(NodeTest, ValueSelfReferenceMap) { + YAML::Node node; + node["key"] = node; + EXPECT_TRUE(node.IsMap()); + EXPECT_EQ(1, node.size()); + EXPECT_EQ(node, node["key"]); + EXPECT_EQ(node, node["key"]["key"]); + EXPECT_EQ(node["key"], node["key"]["key"]); +} + +TEST(NodeTest, KeySelfReferenceMap) { + YAML::Node node; + node[node] = "value"; + EXPECT_TRUE(node.IsMap()); + EXPECT_EQ(1, node.size()); + EXPECT_EQ("value", node[node].as()); +} + +TEST(NodeTest, SelfReferenceMap) { + YAML::Node node; + node[node] = node; + EXPECT_TRUE(node.IsMap()); + EXPECT_EQ(1, node.size()); + EXPECT_EQ(node, node[node]); + EXPECT_EQ(node, node[node][node]); + EXPECT_EQ(node[node], node[node][node]); +} + +TEST(NodeTest, TempMapVariable) { + YAML::Node node; + YAML::Node tmp = node["key"]; + tmp = "value"; + EXPECT_TRUE(node.IsMap()); + EXPECT_EQ(1, node.size()); + EXPECT_EQ("value", node["key"].as()); +} + +TEST(NodeTest, TempMapVariableAlias) { + YAML::Node node; + YAML::Node tmp = node["key"]; + tmp = node["other"]; + node["other"] = "value"; + EXPECT_TRUE(node.IsMap()); + EXPECT_EQ(2, node.size()); + EXPECT_EQ("value", node["key"].as()); + EXPECT_EQ("value", node["other"].as()); + EXPECT_EQ(node["key"], node["other"]); +} + +TEST(NodeTest, Bool) { + YAML::Node node; + node[true] = false; + EXPECT_TRUE(node.IsMap()); + EXPECT_EQ(false, node[true].as()); +} + +TEST(NodeTest, AutoBoolConversion) { + YAML::Node node; + node["foo"] = "bar"; + EXPECT_TRUE(static_cast(node["foo"])); + EXPECT_TRUE(!node["monkey"]); + EXPECT_TRUE(!!node["foo"]); +} + +TEST(NodeTest, FloatingPrecision) { + const double x = 0.123456789; + YAML::Node node = YAML::Node(x); + EXPECT_EQ(x, node.as()); +} + +TEST(NodeTest, SpaceChar) { + YAML::Node node = YAML::Node(' '); + EXPECT_EQ(' ', node.as()); +} + TEST(NodeTest, CloneNull) { Node node; Node clone = Clone(node); diff --git a/test/nodetests.h b/test/nodetests.h deleted file mode 100644 index 6728758..0000000 --- a/test/nodetests.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef NODETESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#define NODETESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 - -#if defined(_MSC_VER) || \ - (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ - (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 -#pragma once -#endif - -namespace Test { -bool RunNodeTests(); -} - -#endif // NODETESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A6666 diff --git a/test/tests.cpp b/test/tests.cpp deleted file mode 100644 index b675941..0000000 --- a/test/tests.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include -#include -#include - -#include "nodetests.h" -#include "tests.h" - -namespace Test { -void RunAll() { - bool passed = true; - if (!RunNodeTests()) - passed = false; - - if (passed) - std::cout << "All tests passed!\n"; -} -} diff --git a/test/tests.h b/test/tests.h deleted file mode 100644 index 72c87c1..0000000 --- a/test/tests.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef TESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#define TESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 - -#if defined(_MSC_VER) || \ - (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ - (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 -#pragma once -#endif - -#include - -namespace Test { -void RunAll(); - -namespace Parser { -// scalar tests -void SimpleScalar(std::string& inputScalar, std::string& desiredOutput); -void MultiLineScalar(std::string& inputScalar, std::string& desiredOutput); -void LiteralScalar(std::string& inputScalar, std::string& desiredOutput); -void FoldedScalar(std::string& inputScalar, std::string& desiredOutput); -void ChompedFoldedScalar(std::string& inputScalar, std::string& desiredOutput); -void ChompedLiteralScalar(std::string& inputScalar, std::string& desiredOutput); -void FoldedScalarWithIndent(std::string& inputScalar, - std::string& desiredOutput); -void ColonScalar(std::string& inputScalar, std::string& desiredOutput); -void QuotedScalar(std::string& inputScalar, std::string& desiredOutput); -void CommaScalar(std::string& inputScalar, std::string& desiredOutput); -void DashScalar(std::string& inputScalar, std::string& desiredOutput); -void URLScalar(std::string& inputScalar, std::string& desiredOutput); - -// misc tests -bool SimpleSeq(); -bool SimpleMap(); -bool FlowSeq(); -bool FlowMap(); -bool FlowMapWithOmittedKey(); -bool FlowMapWithOmittedValue(); -bool FlowMapWithSoloEntry(); -bool FlowMapEndingWithSoloEntry(); -bool QuotedSimpleKeys(); -bool CompressedMapAndSeq(); -bool NullBlockSeqEntry(); -bool NullBlockMapKey(); -bool NullBlockMapValue(); -bool SimpleAlias(); -bool AliasWithNull(); -bool AnchorInSimpleKey(); -bool AliasAsSimpleKey(); -bool ExplicitDoc(); -bool MultipleDocs(); -bool ExplicitEndDoc(); -bool MultipleDocsWithSomeExplicitIndicators(); -} -} - -#endif // TESTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/test/teststruct.h b/test/teststruct.h deleted file mode 100644 index 60596cf..0000000 --- a/test/teststruct.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include - -#define YAML_ASSERT(cond) \ - do { \ - if (!(cond)) \ - return " Assert failed: " #cond; \ - } while (false) - -namespace Test { -struct TEST { - TEST() : ok(false) {} - TEST(bool ok_) : ok(ok_) {} - TEST(const char *error_) : ok(false), error(error_) {} - - bool ok; - std::string error; -}; -} From dfb20686fd88d6a85eb3baf6282d1610fc67945e Mon Sep 17 00:00:00 2001 From: Jesse Beder Date: Sun, 23 Mar 2014 22:42:06 -0500 Subject: [PATCH 35/43] Disable warning: warning C4800: forcing value to bool 'true' or 'false' (performance warning) for the node test, since it really doesn't make any sense in this context. (It's exactly what we intended with the "unspecified bool type".) --- test/node/node_test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/node/node_test.cpp b/test/node/node_test.cpp index 830ddd7..5d66e75 100644 --- a/test/node/node_test.cpp +++ b/test/node/node_test.cpp @@ -232,6 +232,7 @@ TEST(NodeTest, Bool) { } TEST(NodeTest, AutoBoolConversion) { +#pragma warning(disable:4800) YAML::Node node; node["foo"] = "bar"; EXPECT_TRUE(static_cast(node["foo"])); From b6edf3d772951735b2f1c3aa2916897a51079a7f Mon Sep 17 00:00:00 2001 From: beder Date: Tue, 25 Mar 2014 00:11:17 -0500 Subject: [PATCH 36/43] clang-format --- include/yaml-cpp/binary.h | 3 ++- include/yaml-cpp/node/convert.h | 3 ++- include/yaml-cpp/node/detail/iterator.h | 7 +++---- include/yaml-cpp/node/detail/node_iterator.h | 13 ++++--------- include/yaml-cpp/node/node.h | 4 +--- include/yaml-cpp/node/type.h | 8 +------- src/nodeevents.cpp | 4 ++-- test/node/node_test.cpp | 2 +- 8 files changed, 16 insertions(+), 28 deletions(-) diff --git a/include/yaml-cpp/binary.h b/include/yaml-cpp/binary.h index adb2b36..d236a0c 100644 --- a/include/yaml-cpp/binary.h +++ b/include/yaml-cpp/binary.h @@ -13,7 +13,8 @@ #include "yaml-cpp/dll.h" namespace YAML { -YAML_CPP_API std::string EncodeBase64(const unsigned char *data, std::size_t size); +YAML_CPP_API std::string EncodeBase64(const unsigned char *data, + std::size_t size); YAML_CPP_API std::vector DecodeBase64(const std::string &input); class YAML_CPP_API Binary { diff --git a/include/yaml-cpp/node/convert.h b/include/yaml-cpp/node/convert.h index 65d5c6c..c942533 100644 --- a/include/yaml-cpp/node/convert.h +++ b/include/yaml-cpp/node/convert.h @@ -23,7 +23,8 @@ namespace YAML { class Binary; struct _Null; -template struct convert; +template +struct convert; } // namespace YAML namespace YAML { diff --git a/include/yaml-cpp/node/detail/iterator.h b/include/yaml-cpp/node/detail/iterator.h index 6c0d4b6..2c701af 100644 --- a/include/yaml-cpp/node/detail/iterator.h +++ b/include/yaml-cpp/node/detail/iterator.h @@ -36,10 +36,9 @@ class iterator_base : iterator_base::iterator_adaptor_(rhs), m_pMemory(pMemory) {} template - iterator_base( - const iterator_base& rhs, - typename boost::enable_if, enabler>::type = - enabler()) + iterator_base(const iterator_base& rhs, + typename boost::enable_if, + enabler>::type = enabler()) : iterator_base::iterator_adaptor_(rhs.base()), m_pMemory(rhs.m_pMemory) {} diff --git a/include/yaml-cpp/node/detail/node_iterator.h b/include/yaml-cpp/node/detail/node_iterator.h index 6147f63..2382d4a 100644 --- a/include/yaml-cpp/node/detail/node_iterator.h +++ b/include/yaml-cpp/node/detail/node_iterator.h @@ -18,11 +18,7 @@ namespace YAML { namespace detail { struct iterator_type { - enum value { - None, - Sequence, - Map - }; + enum value { None, Sequence, Map }; }; template @@ -76,10 +72,9 @@ class node_iterator_base } template - node_iterator_base( - const node_iterator_base& rhs, - typename boost::enable_if, enabler>::type = - enabler()) + node_iterator_base(const node_iterator_base& rhs, + typename boost::enable_if, + enabler>::type = enabler()) : m_type(rhs.m_type), m_seqIt(rhs.m_seqIt), m_mapIt(rhs.m_mapIt), diff --git a/include/yaml-cpp/node/node.h b/include/yaml-cpp/node/node.h index 8942aa5..a7e7ff8 100644 --- a/include/yaml-cpp/node/node.h +++ b/include/yaml-cpp/node/node.h @@ -104,9 +104,7 @@ class YAML_CPP_API Node { void force_insert(const Key& key, const Value& value); private: - enum Zombie { - ZombieNode - }; + enum Zombie { ZombieNode }; explicit Node(Zombie); explicit Node(detail::node& node, detail::shared_memory_holder pMemory); diff --git a/include/yaml-cpp/node/type.h b/include/yaml-cpp/node/type.h index da1bc11..9d55ca9 100644 --- a/include/yaml-cpp/node/type.h +++ b/include/yaml-cpp/node/type.h @@ -9,13 +9,7 @@ namespace YAML { struct NodeType { - enum value { - Undefined, - Null, - Scalar, - Sequence, - Map - }; + enum value { Undefined, Null, Scalar, Sequence, Map }; }; } diff --git a/src/nodeevents.cpp b/src/nodeevents.cpp index 38fa4d7..f70199d 100644 --- a/src/nodeevents.cpp +++ b/src/nodeevents.cpp @@ -11,8 +11,8 @@ void NodeEvents::AliasManager::RegisterReference(const detail::node& node) { m_anchorByIdentity.insert(std::make_pair(node.ref(), _CreateNewAnchor())); } -anchor_t NodeEvents::AliasManager::LookupAnchor(const detail::node& node) - const { +anchor_t NodeEvents::AliasManager::LookupAnchor( + const detail::node& node) const { AnchorByIdentity::const_iterator it = m_anchorByIdentity.find(node.ref()); if (it == m_anchorByIdentity.end()) return 0; diff --git a/test/node/node_test.cpp b/test/node/node_test.cpp index 5d66e75..b9d1aa8 100644 --- a/test/node/node_test.cpp +++ b/test/node/node_test.cpp @@ -232,7 +232,7 @@ TEST(NodeTest, Bool) { } TEST(NodeTest, AutoBoolConversion) { -#pragma warning(disable:4800) +#pragma warning(disable : 4800) YAML::Node node; node["foo"] = "bar"; EXPECT_TRUE(static_cast(node["foo"])); From 715b769650298e9262e08b9e829de15e3c5c40f3 Mon Sep 17 00:00:00 2001 From: beder Date: Tue, 25 Mar 2014 22:08:34 -0500 Subject: [PATCH 37/43] Wrap the #pragma warning for msvc in an ifdef --- test/node/node_test.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/node/node_test.cpp b/test/node/node_test.cpp index b9d1aa8..0c16a57 100644 --- a/test/node/node_test.cpp +++ b/test/node/node_test.cpp @@ -232,7 +232,9 @@ TEST(NodeTest, Bool) { } TEST(NodeTest, AutoBoolConversion) { +#ifdef _MSC_VER #pragma warning(disable : 4800) +#endif YAML::Node node; node["foo"] = "bar"; EXPECT_TRUE(static_cast(node["foo"])); From d2aabfe2866112dbd73fbcc29d6a6a980639d980 Mon Sep 17 00:00:00 2001 From: beder Date: Sat, 16 Aug 2014 10:52:51 -0500 Subject: [PATCH 38/43] Fixed memory corruption when using a node as a key --- include/yaml-cpp/node/impl.h | 2 ++ test/node/node_test.cpp | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/include/yaml-cpp/node/impl.h b/include/yaml-cpp/node/impl.h index 425e37f..e79d562 100644 --- a/include/yaml-cpp/node/impl.h +++ b/include/yaml-cpp/node/impl.h @@ -380,6 +380,7 @@ inline const Node Node::operator[](const Node& key) const { throw InvalidNode(); EnsureNodeExists(); key.EnsureNodeExists(); + m_pMemory->merge(*key.m_pMemory); detail::node& value = static_cast(*m_pNode).get(*key.m_pNode, m_pMemory); return Node(value, m_pMemory); @@ -390,6 +391,7 @@ inline Node Node::operator[](const Node& key) { throw InvalidNode(); EnsureNodeExists(); key.EnsureNodeExists(); + m_pMemory->merge(*key.m_pMemory); detail::node& value = m_pNode->get(*key.m_pNode, m_pMemory); return Node(value, m_pMemory); } diff --git a/test/node/node_test.cpp b/test/node/node_test.cpp index 0c16a57..736a068 100644 --- a/test/node/node_test.cpp +++ b/test/node/node_test.cpp @@ -258,5 +258,16 @@ TEST(NodeTest, CloneNull) { Node clone = Clone(node); EXPECT_EQ(NodeType::Null, clone.Type()); } + +TEST(NodeTest, KeyNodeExitsScope) { + Node node; + { + Node temp("Hello, world"); + node[temp] = 0; + } + for (const auto &kv : node) { + (void)kv; + } +} } } From b47ea9a243aab2f67f999c39f48b0a62d9f0be58 Mon Sep 17 00:00:00 2001 From: Jesse Beder Date: Sat, 24 Jan 2015 13:11:43 -0600 Subject: [PATCH 39/43] Add flow/block style setting on Nodes --- include/yaml-cpp/node/detail/node.h | 8 + include/yaml-cpp/node/detail/node_data.h | 3 + include/yaml-cpp/node/detail/node_ref.h | 2 + include/yaml-cpp/node/impl.h | 13 ++ include/yaml-cpp/node/node.h | 7 + src/convert.cpp | 4 +- src/node_data.cpp | 7 +- src/nodebuilder.cpp | 2 + src/nodeevents.cpp | 5 +- test/integration/load_node_test.cpp | 102 +++++++------ test/integration/node_spec_test.cpp | 3 +- test/node/node_test.cpp | 177 +++++++++++++++++++---- util/parse.cpp | 3 +- 13 files changed, 252 insertions(+), 84 deletions(-) diff --git a/include/yaml-cpp/node/detail/node.h b/include/yaml-cpp/node/detail/node.h index 20be18c..29605dd 100644 --- a/include/yaml-cpp/node/detail/node.h +++ b/include/yaml-cpp/node/detail/node.h @@ -7,6 +7,7 @@ #pragma once #endif +#include "yaml-cpp/emitterstyle.h" #include "yaml-cpp/dll.h" #include "yaml-cpp/node/type.h" #include "yaml-cpp/node/ptr.h" @@ -28,6 +29,7 @@ class node : private boost::noncopyable { const std::string& scalar() const { return m_pRef->scalar(); } const std::string& tag() const { return m_pRef->tag(); } + EmitterStyle::value style() const { return m_pRef->style(); } void mark_defined() { if (is_defined()) @@ -76,6 +78,12 @@ class node : private boost::noncopyable { m_pRef->set_tag(tag); } + // style + void set_style(EmitterStyle::value style) { + mark_defined(); + m_pRef->set_style(style); + } + // size/iterator std::size_t size() const { return m_pRef->size(); } diff --git a/include/yaml-cpp/node/detail/node_data.h b/include/yaml-cpp/node/detail/node_data.h index c1696f4..b6c12b3 100644 --- a/include/yaml-cpp/node/detail/node_data.h +++ b/include/yaml-cpp/node/detail/node_data.h @@ -38,6 +38,7 @@ class YAML_CPP_API node_data : private boost::noncopyable { void set_tag(const std::string& tag); void set_null(); void set_scalar(const std::string& scalar); + void set_style(EmitterStyle::value style); bool is_defined() const { return m_isDefined; } NodeType::value type() const { @@ -45,6 +46,7 @@ class YAML_CPP_API node_data : private boost::noncopyable { } const std::string& scalar() const { return m_scalar; } const std::string& tag() const { return m_tag; } + EmitterStyle::value style() const { return m_style; } // size/iterator std::size_t size() const; @@ -101,6 +103,7 @@ class YAML_CPP_API node_data : private boost::noncopyable { bool m_isDefined; NodeType::value m_type; std::string m_tag; + EmitterStyle::value m_style; // scalar std::string m_scalar; diff --git a/include/yaml-cpp/node/detail/node_ref.h b/include/yaml-cpp/node/detail/node_ref.h index 2b577a3..4530cf8 100644 --- a/include/yaml-cpp/node/detail/node_ref.h +++ b/include/yaml-cpp/node/detail/node_ref.h @@ -23,6 +23,7 @@ class node_ref : private boost::noncopyable { NodeType::value type() const { return m_pData->type(); } const std::string& scalar() const { return m_pData->scalar(); } const std::string& tag() const { return m_pData->tag(); } + EmitterStyle::value style() const { return m_pData->style(); } void mark_defined() { m_pData->mark_defined(); } void set_data(const node_ref& rhs) { m_pData = rhs.m_pData; } @@ -31,6 +32,7 @@ class node_ref : private boost::noncopyable { void set_tag(const std::string& tag) { m_pData->set_tag(tag); } void set_null() { m_pData->set_null(); } void set_scalar(const std::string& scalar) { m_pData->set_scalar(scalar); } + void set_style(EmitterStyle::value style) { m_pData->set_style(style); } // size/iterator std::size_t size() const { return m_pData->size(); } diff --git a/include/yaml-cpp/node/impl.h b/include/yaml-cpp/node/impl.h index 425e37f..9b367ab 100644 --- a/include/yaml-cpp/node/impl.h +++ b/include/yaml-cpp/node/impl.h @@ -164,6 +164,19 @@ inline void Node::SetTag(const std::string& tag) { m_pNode->set_tag(tag); } +inline EmitterStyle::value Node::Style() const { + if (!m_isValid) + throw InvalidNode(); + return m_pNode ? m_pNode->style() : EmitterStyle::Default; +} + +inline void Node::SetStyle(EmitterStyle::value style) { + if (!m_isValid) + throw InvalidNode(); + EnsureNodeExists(); + m_pNode->set_style(style); +} + // assignment inline bool Node::is(const Node& rhs) const { if (!m_isValid || !rhs.m_isValid) diff --git a/include/yaml-cpp/node/node.h b/include/yaml-cpp/node/node.h index a7e7ff8..15de6f0 100644 --- a/include/yaml-cpp/node/node.h +++ b/include/yaml-cpp/node/node.h @@ -10,6 +10,7 @@ #include #include "yaml-cpp/dll.h" +#include "yaml-cpp/emitterstyle.h" #include "yaml-cpp/node/detail/bool_type.h" #include "yaml-cpp/node/detail/iterator_fwd.h" #include "yaml-cpp/node/ptr.h" @@ -63,9 +64,15 @@ class YAML_CPP_API Node { template const T as(const S& fallback) const; const std::string& Scalar() const; + const std::string& Tag() const; void SetTag(const std::string& tag); + // style + // WARNING: This API might change in future releases. + EmitterStyle::value Style() const; + void SetStyle(EmitterStyle::value style); + // assignment bool is(const Node& rhs) const; template diff --git a/src/convert.cpp b/src/convert.cpp index 349e2f7..da3bc2f 100644 --- a/src/convert.cpp +++ b/src/convert.cpp @@ -51,7 +51,9 @@ bool convert::decode(const Node& node, bool& rhs) { // http://yaml.org/type/bool.html) static const struct { std::string truename, falsename; - } names[] = {{"y", "n"}, {"yes", "no"}, {"true", "false"}, {"on", "off"}, }; + } names[] = { + {"y", "n"}, {"yes", "no"}, {"true", "false"}, {"on", "off"}, + }; if (!IsFlexibleCase(node.Scalar())) return false; diff --git a/src/node_data.cpp b/src/node_data.cpp index 90be9b9..b8cf43c 100644 --- a/src/node_data.cpp +++ b/src/node_data.cpp @@ -16,7 +16,10 @@ namespace detail { std::string node_data::empty_scalar; node_data::node_data() - : m_isDefined(false), m_type(NodeType::Null), m_seqSize(0) {} + : m_isDefined(false), + m_type(NodeType::Null), + m_seqSize(0), + m_style(EmitterStyle::Default) {} void node_data::mark_defined() { if (m_type == NodeType::Undefined) @@ -57,6 +60,8 @@ void node_data::set_type(NodeType::value type) { void node_data::set_tag(const std::string& tag) { m_tag = tag; } +void node_data::set_style(EmitterStyle::value style) { m_style = style; } + void node_data::set_null() { m_isDefined = true; m_type = NodeType::Null; diff --git a/src/nodebuilder.cpp b/src/nodebuilder.cpp index 7c4307c..69f9702 100644 --- a/src/nodebuilder.cpp +++ b/src/nodebuilder.cpp @@ -54,6 +54,7 @@ void NodeBuilder::OnSequenceStart(const Mark& /* mark */, detail::node& node = Push(anchor); node.set_tag(tag); node.set_type(NodeType::Sequence); + node.set_style(style); } void NodeBuilder::OnSequenceEnd() { Pop(); } @@ -63,6 +64,7 @@ void NodeBuilder::OnMapStart(const Mark& /* mark */, const std::string& tag, detail::node& node = Push(anchor); node.set_type(NodeType::Map); node.set_tag(tag); + node.set_style(style); m_mapDepth++; } diff --git a/src/nodeevents.cpp b/src/nodeevents.cpp index 2848511..82261fe 100644 --- a/src/nodeevents.cpp +++ b/src/nodeevents.cpp @@ -76,15 +76,14 @@ void NodeEvents::Emit(const detail::node& node, EventHandler& handler, handler.OnScalar(Mark(), node.tag(), anchor, node.scalar()); break; case NodeType::Sequence: - handler.OnSequenceStart(Mark(), node.tag(), anchor, - EmitterStyle::Default); + handler.OnSequenceStart(Mark(), node.tag(), anchor, node.style()); for (detail::const_node_iterator it = node.begin(); it != node.end(); ++it) Emit(**it, handler, am); handler.OnSequenceEnd(); break; case NodeType::Map: - handler.OnMapStart(Mark(), node.tag(), anchor, EmitterStyle::Default); + handler.OnMapStart(Mark(), node.tag(), anchor, node.style()); for (detail::const_node_iterator it = node.begin(); it != node.end(); ++it) { Emit(*it->first, handler, am); diff --git a/test/integration/load_node_test.cpp b/test/integration/load_node_test.cpp index 4c4c826..0083a2b 100644 --- a/test/integration/load_node_test.cpp +++ b/test/integration/load_node_test.cpp @@ -5,12 +5,12 @@ namespace YAML { namespace { TEST(LoadNodeTest, Reassign) { - YAML::Node node = YAML::Load("foo"); - node = YAML::Node(); + Node node = Load("foo"); + node = Node(); } TEST(LoadNodeTest, FallbackValues) { - YAML::Node node = YAML::Load("foo: bar\nx: 2"); + Node node = Load("foo: bar\nx: 2"); EXPECT_EQ("bar", node["foo"].as()); EXPECT_EQ("bar", node["foo"].as("hello")); EXPECT_EQ("hello", node["baz"].as("hello")); @@ -20,10 +20,10 @@ TEST(LoadNodeTest, FallbackValues) { } TEST(LoadNodeTest, NumericConversion) { - YAML::Node node = YAML::Load("[1.5, 1, .nan, .inf, -.inf, 0x15, 015]"); + Node node = Load("[1.5, 1, .nan, .inf, -.inf, 0x15, 015]"); EXPECT_EQ(1.5f, node[0].as()); EXPECT_EQ(1.5, node[0].as()); - EXPECT_THROW(node[0].as(), YAML::TypedBadConversion); + EXPECT_THROW(node[0].as(), TypedBadConversion); EXPECT_EQ(1, node[1].as()); EXPECT_EQ(1.0f, node[1].as()); EXPECT_NE(node[2].as(), node[2].as()); @@ -34,7 +34,7 @@ TEST(LoadNodeTest, NumericConversion) { } TEST(LoadNodeTest, Binary) { - YAML::Node node = YAML::Load( + Node node = Load( "[!!binary \"SGVsbG8sIFdvcmxkIQ==\", !!binary " "\"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieS" "B0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIG" @@ -42,25 +42,24 @@ TEST(LoadNodeTest, Binary) { "B0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZG" "dlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS" "4K\"]"); - EXPECT_EQ( - YAML::Binary(reinterpret_cast("Hello, World!"), 13), - node[0].as()); - EXPECT_EQ(YAML::Binary(reinterpret_cast( - "Man is distinguished, not only by his reason, " - "but by this singular passion from other " - "animals, which is a lust of the mind, that by " - "a perseverance of delight in the continued and " - "indefatigable generation of knowledge, exceeds " - "the short vehemence of any carnal pleasure.\n"), - 270), - node[1].as()); + EXPECT_EQ(Binary(reinterpret_cast("Hello, World!"), 13), + node[0].as()); + EXPECT_EQ(Binary(reinterpret_cast( + "Man is distinguished, not only by his reason, " + "but by this singular passion from other " + "animals, which is a lust of the mind, that by " + "a perseverance of delight in the continued and " + "indefatigable generation of knowledge, exceeds " + "the short vehemence of any carnal pleasure.\n"), + 270), + node[1].as()); } TEST(LoadNodeTest, IterateSequence) { - YAML::Node node = YAML::Load("[1, 3, 5, 7]"); + Node node = Load("[1, 3, 5, 7]"); int seq[] = {1, 3, 5, 7}; int i = 0; - for (YAML::const_iterator it = node.begin(); it != node.end(); ++it) { + for (const_iterator it = node.begin(); it != node.end(); ++it) { EXPECT_TRUE(i < 4); int x = seq[i++]; EXPECT_EQ(x, it->as()); @@ -69,9 +68,9 @@ TEST(LoadNodeTest, IterateSequence) { } TEST(LoadNodeTest, IterateMap) { - YAML::Node node = YAML::Load("{a: A, b: B, c: C}"); + Node node = Load("{a: A, b: B, c: C}"); int i = 0; - for (YAML::const_iterator it = node.begin(); it != node.end(); ++it) { + for (const_iterator it = node.begin(); it != node.end(); ++it) { EXPECT_TRUE(i < 3); i++; EXPECT_EQ(it->second.as(), it->first.as() + 'A' - 'a'); @@ -81,36 +80,36 @@ TEST(LoadNodeTest, IterateMap) { #ifdef BOOST_FOREACH TEST(LoadNodeTest, ForEach) { - YAML::Node node = YAML::Load("[1, 3, 5, 7]"); + Node node = Load("[1, 3, 5, 7]"); int seq[] = {1, 3, 5, 7}; int i = 0; - BOOST_FOREACH(const YAML::Node & item, node) { + BOOST_FOREACH (const Node& item, node) { int x = seq[i++]; EXPECT_EQ(x, item.as()); } } TEST(LoadNodeTest, ForEachMap) { - YAML::Node node = YAML::Load("{a: A, b: B, c: C}"); - BOOST_FOREACH(const YAML::const_iterator::value_type & p, node) { + Node node = Load("{a: A, b: B, c: C}"); + BOOST_FOREACH (const const_iterator::value_type& p, node) { EXPECT_EQ(p.second.as(), p.first.as() + 'A' - 'a'); } } #endif TEST(LoadNodeTest, CloneScalar) { - YAML::Node node = YAML::Load("!foo monkey"); - YAML::Node clone = Clone(node); + Node node = Load("!foo monkey"); + Node clone = Clone(node); EXPECT_FALSE(clone == node); EXPECT_EQ(clone.as(), node.as()); EXPECT_EQ(clone.Tag(), node.Tag()); } TEST(LoadNodeTest, CloneSeq) { - YAML::Node node = YAML::Load("[1, 3, 5, 7]"); - YAML::Node clone = Clone(node); + Node node = Load("[1, 3, 5, 7]"); + Node clone = Clone(node); EXPECT_FALSE(clone == node); - EXPECT_EQ(YAML::NodeType::Sequence, clone.Type()); + EXPECT_EQ(NodeType::Sequence, clone.Type()); EXPECT_EQ(clone.size(), node.size()); for (std::size_t i = 0; i < node.size(); i++) { EXPECT_EQ(clone[i].as(), node[i].as()); @@ -118,34 +117,34 @@ TEST(LoadNodeTest, CloneSeq) { } TEST(LoadNodeTest, CloneMap) { - YAML::Node node = YAML::Load("{foo: bar}"); - YAML::Node clone = Clone(node); + Node node = Load("{foo: bar}"); + Node clone = Clone(node); EXPECT_FALSE(clone == node); - EXPECT_EQ(YAML::NodeType::Map, clone.Type()); + EXPECT_EQ(NodeType::Map, clone.Type()); EXPECT_EQ(clone.size(), node.size()); EXPECT_EQ(clone["foo"].as(), node["foo"].as()); } TEST(LoadNodeTest, CloneAlias) { - YAML::Node node = YAML::Load("&foo [*foo]"); - YAML::Node clone = Clone(node); + Node node = Load("&foo [*foo]"); + Node clone = Clone(node); EXPECT_FALSE(clone == node); - EXPECT_EQ(YAML::NodeType::Sequence, clone.Type()); + EXPECT_EQ(NodeType::Sequence, clone.Type()); EXPECT_EQ(clone.size(), node.size()); EXPECT_EQ(clone[0], clone); } TEST(LoadNodeTest, ForceInsertIntoMap) { - YAML::Node node; + Node node; node["a"] = "b"; node.force_insert("x", "y"); node.force_insert("a", 5); EXPECT_EQ(3, node.size()); - EXPECT_EQ(YAML::NodeType::Map, node.Type()); + EXPECT_EQ(NodeType::Map, node.Type()); bool ab = false; bool a5 = false; bool xy = false; - for (YAML::const_iterator it = node.begin(); it != node.end(); ++it) { + for (const_iterator it = node.begin(); it != node.end(); ++it) { if (it->first.as() == "a") { if (it->second.as() == "b") ab = true; @@ -161,9 +160,9 @@ TEST(LoadNodeTest, ForceInsertIntoMap) { } TEST(LoadNodeTest, ResetNode) { - YAML::Node node = YAML::Load("[1, 2, 3]"); + Node node = Load("[1, 2, 3]"); EXPECT_TRUE(!node.IsNull()); - YAML::Node other = node; + Node other = node; node.reset(); EXPECT_TRUE(node.IsNull()); EXPECT_TRUE(!other.IsNull()); @@ -173,19 +172,26 @@ TEST(LoadNodeTest, ResetNode) { } TEST(LoadNodeTest, DereferenceIteratorError) { - YAML::Node node = YAML::Load("[{a: b}, 1, 2]"); - EXPECT_THROW(node.begin()->first.as(), YAML::InvalidNode); + Node node = Load("[{a: b}, 1, 2]"); + EXPECT_THROW(node.begin()->first.as(), InvalidNode); EXPECT_EQ(true, (*node.begin()).IsMap()); EXPECT_EQ(true, node.begin()->IsMap()); - EXPECT_THROW((*node.begin()->begin()).IsDefined(), YAML::InvalidNode); - EXPECT_THROW(node.begin()->begin()->IsDefined(), YAML::InvalidNode); + EXPECT_THROW((*node.begin()->begin()).IsDefined(), InvalidNode); + EXPECT_THROW(node.begin()->begin()->IsDefined(), InvalidNode); } TEST(NodeTest, EmitEmptyNode) { - YAML::Node node; - YAML::Emitter emitter; + Node node; + Emitter emitter; emitter << node; EXPECT_EQ("", std::string(emitter.c_str())); } + +TEST(NodeTest, ParseNodeStyle) { + EXPECT_EQ(EmitterStyle::Flow, Load("[1, 2, 3]").Style()); + EXPECT_EQ(EmitterStyle::Flow, Load("{foo: bar}").Style()); + EXPECT_EQ(EmitterStyle::Block, Load("- foo\n- bar").Style()); + EXPECT_EQ(EmitterStyle::Block, Load("foo: bar").Style()); +} } } diff --git a/test/integration/node_spec_test.cpp b/test/integration/node_spec_test.cpp index ea6d6bd..aedf38b 100644 --- a/test/integration/node_spec_test.cpp +++ b/test/integration/node_spec_test.cpp @@ -7,8 +7,7 @@ ASSERT_THROW(statement, ParserException); \ try { \ statement; \ - } \ - catch (const ParserException& e) { \ + } catch (const ParserException& e) { \ EXPECT_EQ(e.msg, message); \ } diff --git a/test/node/node_test.cpp b/test/node/node_test.cpp index 0c16a57..265d6f3 100644 --- a/test/node/node_test.cpp +++ b/test/node/node_test.cpp @@ -1,3 +1,5 @@ +#include "yaml-cpp/emitter.h" +#include "yaml-cpp/node/emit.h" #include "yaml-cpp/node/node.h" #include "yaml-cpp/node/impl.h" #include "yaml-cpp/node/convert.h" @@ -9,19 +11,19 @@ namespace YAML { namespace { TEST(NodeTest, SimpleScalar) { - YAML::Node node = YAML::Node("Hello, World!"); + Node node = Node("Hello, World!"); EXPECT_TRUE(node.IsScalar()); EXPECT_EQ("Hello, World!", node.as()); } TEST(NodeTest, IntScalar) { - YAML::Node node = YAML::Node(15); + Node node = Node(15); EXPECT_TRUE(node.IsScalar()); EXPECT_EQ(15, node.as()); } TEST(NodeTest, SimpleAppendSequence) { - YAML::Node node; + Node node; node.push_back(10); node.push_back("foo"); node.push_back("monkey"); @@ -34,7 +36,7 @@ TEST(NodeTest, SimpleAppendSequence) { } TEST(NodeTest, SimpleAssignSequence) { - YAML::Node node; + Node node; node[0] = 10; node[1] = "foo"; node[2] = "monkey"; @@ -47,7 +49,7 @@ TEST(NodeTest, SimpleAssignSequence) { } TEST(NodeTest, SimpleMap) { - YAML::Node node; + Node node; node["key"] = "value"; EXPECT_TRUE(node.IsMap()); EXPECT_EQ("value", node["key"].as()); @@ -55,7 +57,7 @@ TEST(NodeTest, SimpleMap) { } TEST(NodeTest, MapWithUndefinedValues) { - YAML::Node node; + Node node; node["key"] = "value"; node["undefined"]; EXPECT_TRUE(node.IsMap()); @@ -68,7 +70,7 @@ TEST(NodeTest, MapWithUndefinedValues) { } TEST(NodeTest, MapIteratorWithUndefinedValues) { - YAML::Node node; + Node node; node["key"] = "value"; node["undefined"]; @@ -79,7 +81,7 @@ TEST(NodeTest, MapIteratorWithUndefinedValues) { } TEST(NodeTest, SimpleSubkeys) { - YAML::Node node; + Node node; node["device"]["udid"] = "12345"; node["device"]["name"] = "iPhone"; node["device"]["os"] = "4.0"; @@ -99,7 +101,7 @@ TEST(NodeTest, StdVector) { primes.push_back(11); primes.push_back(13); - YAML::Node node; + Node node; node["primes"] = primes; EXPECT_EQ(primes, node["primes"].as >()); } @@ -113,7 +115,7 @@ TEST(NodeTest, StdList) { primes.push_back(11); primes.push_back(13); - YAML::Node node; + Node node; node["primes"] = primes; EXPECT_EQ(primes, node["primes"].as >()); } @@ -126,7 +128,7 @@ TEST(NodeTest, StdMap) { squares[3] = 9; squares[4] = 16; - YAML::Node node; + Node node; node["squares"] = squares; std::map actualSquares = node["squares"].as >(); EXPECT_EQ(squares, actualSquares); @@ -137,7 +139,7 @@ TEST(NodeTest, StdPair) { p.first = 5; p.second = "five"; - YAML::Node node; + Node node; node["pair"] = p; std::pair actualP = node["pair"].as >(); @@ -145,7 +147,7 @@ TEST(NodeTest, StdPair) { } TEST(NodeTest, SimpleAlias) { - YAML::Node node; + Node node; node["foo"] = "value"; node["bar"] = node["foo"]; EXPECT_EQ("value", node["foo"].as()); @@ -155,9 +157,9 @@ TEST(NodeTest, SimpleAlias) { } TEST(NodeTest, AliasAsKey) { - YAML::Node node; + Node node; node["foo"] = "value"; - YAML::Node value = node["foo"]; + Node value = node["foo"]; node[value] = "foo"; EXPECT_EQ("value", node["foo"].as()); EXPECT_EQ("foo", node[value].as()); @@ -166,7 +168,7 @@ TEST(NodeTest, AliasAsKey) { } TEST(NodeTest, SelfReferenceSequence) { - YAML::Node node; + Node node; node[0] = node; EXPECT_TRUE(node.IsSequence()); EXPECT_EQ(1, node.size()); @@ -176,7 +178,7 @@ TEST(NodeTest, SelfReferenceSequence) { } TEST(NodeTest, ValueSelfReferenceMap) { - YAML::Node node; + Node node; node["key"] = node; EXPECT_TRUE(node.IsMap()); EXPECT_EQ(1, node.size()); @@ -186,7 +188,7 @@ TEST(NodeTest, ValueSelfReferenceMap) { } TEST(NodeTest, KeySelfReferenceMap) { - YAML::Node node; + Node node; node[node] = "value"; EXPECT_TRUE(node.IsMap()); EXPECT_EQ(1, node.size()); @@ -194,7 +196,7 @@ TEST(NodeTest, KeySelfReferenceMap) { } TEST(NodeTest, SelfReferenceMap) { - YAML::Node node; + Node node; node[node] = node; EXPECT_TRUE(node.IsMap()); EXPECT_EQ(1, node.size()); @@ -204,8 +206,8 @@ TEST(NodeTest, SelfReferenceMap) { } TEST(NodeTest, TempMapVariable) { - YAML::Node node; - YAML::Node tmp = node["key"]; + Node node; + Node tmp = node["key"]; tmp = "value"; EXPECT_TRUE(node.IsMap()); EXPECT_EQ(1, node.size()); @@ -213,8 +215,8 @@ TEST(NodeTest, TempMapVariable) { } TEST(NodeTest, TempMapVariableAlias) { - YAML::Node node; - YAML::Node tmp = node["key"]; + Node node; + Node tmp = node["key"]; tmp = node["other"]; node["other"] = "value"; EXPECT_TRUE(node.IsMap()); @@ -225,7 +227,7 @@ TEST(NodeTest, TempMapVariableAlias) { } TEST(NodeTest, Bool) { - YAML::Node node; + Node node; node[true] = false; EXPECT_TRUE(node.IsMap()); EXPECT_EQ(false, node[true].as()); @@ -235,7 +237,7 @@ TEST(NodeTest, AutoBoolConversion) { #ifdef _MSC_VER #pragma warning(disable : 4800) #endif - YAML::Node node; + Node node; node["foo"] = "bar"; EXPECT_TRUE(static_cast(node["foo"])); EXPECT_TRUE(!node["monkey"]); @@ -244,12 +246,12 @@ TEST(NodeTest, AutoBoolConversion) { TEST(NodeTest, FloatingPrecision) { const double x = 0.123456789; - YAML::Node node = YAML::Node(x); + Node node = Node(x); EXPECT_EQ(x, node.as()); } TEST(NodeTest, SpaceChar) { - YAML::Node node = YAML::Node(' '); + Node node = Node(' '); EXPECT_EQ(' ', node.as()); } @@ -258,5 +260,126 @@ TEST(NodeTest, CloneNull) { Node clone = Clone(node); EXPECT_EQ(NodeType::Null, clone.Type()); } + +TEST(NodeTest, DefaultNodeStyle) { + Node node; + EXPECT_EQ(EmitterStyle::Default, node.Style()); +} + +class NodeEmitterTest : public ::testing::Test { + protected: + void ExpectOutput(const std::string& output, const Node& node) { + Emitter emitter; + emitter << node; + ASSERT_TRUE(emitter.good()); + EXPECT_EQ(output, emitter.c_str()); + } +}; + +TEST_F(NodeEmitterTest, SimpleFlowSeqNode) { + Node node; + node.SetStyle(EmitterStyle::Flow); + node.push_back(1.01); + node.push_back(2.01); + node.push_back(3.01); + + ExpectOutput("[1.01, 2.01, 3.01]", node); +} + +TEST_F(NodeEmitterTest, NestFlowSeqNode) { + Node node, cell0, cell1; + + cell0.push_back(1.01); + cell0.push_back(2.01); + cell0.push_back(3.01); + + cell1.push_back(4.01); + cell1.push_back(5.01); + cell1.push_back(6.01); + + node.SetStyle(EmitterStyle::Flow); + node.push_back(cell0); + node.push_back(cell1); + + ExpectOutput("[[1.01, 2.01, 3.01], [4.01, 5.01, 6.01]]", node); +} + +TEST_F(NodeEmitterTest, MixBlockFlowSeqNode) { + Node node, cell0, cell1; + + cell0.SetStyle(EmitterStyle::Flow); + cell0.push_back(1.01); + cell0.push_back(2.01); + cell0.push_back(3.01); + + cell1.push_back(4.01); + cell1.push_back(5.01); + cell1.push_back(6.01); + + node.SetStyle(EmitterStyle::Block); + node.push_back(cell0); + node.push_back(cell1); + + ExpectOutput("- [1.01, 2.01, 3.01]\n-\n - 4.01\n - 5.01\n - 6.01", node); +} + +TEST_F(NodeEmitterTest, NestBlockFlowMapListNode) { + Node node, mapNode, blockNode; + + node.push_back(1.01); + node.push_back(2.01); + node.push_back(3.01); + + mapNode.SetStyle(EmitterStyle::Flow); + mapNode["position"] = node; + + blockNode.push_back(1.01); + blockNode.push_back(mapNode); + + ExpectOutput("- 1.01\n- {position: [1.01, 2.01, 3.01]}", blockNode); +} + +TEST_F(NodeEmitterTest, NestBlockMixMapListNode) { + Node node, mapNode, blockNode; + + node.push_back(1.01); + node.push_back(2.01); + node.push_back(3.01); + + mapNode.SetStyle(EmitterStyle::Flow); + mapNode["position"] = node; + + blockNode["scalar"] = 1.01; + blockNode["object"] = mapNode; + + ExpectOutput("scalar: 1.01\nobject: {position: [1.01, 2.01, 3.01]}", + blockNode); +} + +TEST_F(NodeEmitterTest, NestBlockMapListNode) { + Node node, mapNode; + + node.push_back(1.01); + node.push_back(2.01); + node.push_back(3.01); + + mapNode.SetStyle(EmitterStyle::Block); + mapNode["position"] = node; + + ExpectOutput("position:\n - 1.01\n - 2.01\n - 3.01", mapNode); +} + +TEST_F(NodeEmitterTest, NestFlowMapListNode) { + Node node, mapNode; + + node.push_back(1.01); + node.push_back(2.01); + node.push_back(3.01); + + mapNode.SetStyle(EmitterStyle::Flow); + mapNode["position"] = node; + + ExpectOutput("{position: [1.01, 2.01, 3.01]}", mapNode); +} } } diff --git a/util/parse.cpp b/util/parse.cpp index 6596db8..ed9db4b 100644 --- a/util/parse.cpp +++ b/util/parse.cpp @@ -41,8 +41,7 @@ void parse(std::istream& input) { try { YAML::Node doc = YAML::Load(input); std::cout << doc << "\n"; - } - catch (const YAML::Exception& e) { + } catch (const YAML::Exception& e) { std::cerr << e.what() << "\n"; } } From 72ff3abdde106969a201ec7d5e9fec12daad5480 Mon Sep 17 00:00:00 2001 From: Jesse Beder Date: Sat, 24 Jan 2015 15:19:49 -0600 Subject: [PATCH 40/43] Add conversion for signed char --- include/yaml-cpp/node/convert.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/yaml-cpp/node/convert.h b/include/yaml-cpp/node/convert.h index c942533..dd74514 100644 --- a/include/yaml-cpp/node/convert.h +++ b/include/yaml-cpp/node/convert.h @@ -130,6 +130,7 @@ YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long); YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned long long); YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(char); +YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(signed char); YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED(unsigned char); YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(float); From 700027833b1f92c184416cb8a0765fdc14e6f3cf Mon Sep 17 00:00:00 2001 From: Jesse Beder Date: Sat, 24 Jan 2015 15:32:04 -0600 Subject: [PATCH 41/43] Fix initialize ordering warning --- src/node_data.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/node_data.cpp b/src/node_data.cpp index b8cf43c..379c1ef 100644 --- a/src/node_data.cpp +++ b/src/node_data.cpp @@ -18,8 +18,8 @@ std::string node_data::empty_scalar; node_data::node_data() : m_isDefined(false), m_type(NodeType::Null), - m_seqSize(0), - m_style(EmitterStyle::Default) {} + m_style(EmitterStyle::Default), + m_seqSize(0) {} void node_data::mark_defined() { if (m_type == NodeType::Undefined) From 2911aebcf7b90fba35dadb5f3852320b1311c4cf Mon Sep 17 00:00:00 2001 From: Jesse Beder Date: Sat, 24 Jan 2015 15:34:39 -0600 Subject: [PATCH 42/43] Remove stray 'auto' that leaked in without C++11 --- test/node/node_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/node/node_test.cpp b/test/node/node_test.cpp index f0f7b9d..430d142 100644 --- a/test/node/node_test.cpp +++ b/test/node/node_test.cpp @@ -267,8 +267,8 @@ TEST(NodeTest, KeyNodeExitsScope) { Node temp("Hello, world"); node[temp] = 0; } - for (const auto& kv : node) { - (void)kv; + for (Node::const_iterator it = node.begin(); it != node.end(); ++it) { + (void)it; } } From 5bd2736cde91acc85261cd8f0e36ab1a48e5d3b0 Mon Sep 17 00:00:00 2001 From: Jesse Beder Date: Sat, 24 Jan 2015 16:23:35 -0600 Subject: [PATCH 43/43] Default-initialize all sub-iterators in node_iterator_base --- include/yaml-cpp/node/detail/node_iterator.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/include/yaml-cpp/node/detail/node_iterator.h b/include/yaml-cpp/node/detail/node_iterator.h index 2382d4a..9669c81 100644 --- a/include/yaml-cpp/node/detail/node_iterator.h +++ b/include/yaml-cpp/node/detail/node_iterator.h @@ -63,11 +63,18 @@ class node_iterator_base typedef typename node_iterator_type::map MapIter; typedef node_iterator_value value_type; - node_iterator_base() : m_type(iterator_type::None) {} + node_iterator_base() + : m_type(iterator_type::None), m_seqIt(), m_mapIt(), m_mapEnd() {} explicit node_iterator_base(SeqIter seqIt) - : m_type(iterator_type::Sequence), m_seqIt(seqIt) {} + : m_type(iterator_type::Sequence), + m_seqIt(seqIt), + m_mapIt(), + m_mapEnd() {} explicit node_iterator_base(MapIter mapIt, MapIter mapEnd) - : m_type(iterator_type::Map), m_mapIt(mapIt), m_mapEnd(mapEnd) { + : m_type(iterator_type::Map), + m_seqIt(), + m_mapIt(mapIt), + m_mapEnd(mapEnd) { m_mapIt = increment_until_defined(m_mapIt); }