diff --git a/CMakeLists.txt b/CMakeLists.txt index 214e7c3..eccee43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,11 @@ endif() if(POLICY CMP0015) cmake_policy(SET CMP0015 OLD) endif() +# see https://cmake.org/cmake/help/latest/policy/CMP0042.html +if(POLICY CMP0042) + # Enable MACOSX_RPATH by default. + cmake_policy(SET CMP0042 NEW) +endif() include(CheckCXXCompilerFlag) @@ -149,9 +154,11 @@ if(WIN32) endif() endif() -# GCC or Clang specialities +# GCC or Clang or Intel Compiler specialities if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR - CMAKE_CXX_COMPILER_ID MATCHES "Clang") + CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR + CMAKE_CXX_COMPILER_ID MATCHES "Intel") + ### General stuff if(WIN32) set(CMAKE_SHARED_LIBRARY_PREFIX "") # DLLs do not have a "lib" prefix @@ -219,13 +226,14 @@ if(MSVC) endif() # correct linker options - foreach(flag_var yaml_c_flags yaml_cxx_flags) + foreach(flag_var CMAKE_C_FLAGS CMAKE_CXX_FLAGS) foreach(config_name "" DEBUG RELEASE MINSIZEREL RELWITHDEBINFO) set(var_name "${flag_var}") if(NOT "${config_name}" STREQUAL "") set(var_name "${var_name}_${config_name}") endif() string(REPLACE "/MD" "${LIB_RT_OPTION}" ${var_name} "${${var_name}}") + set(${var_name} "${${var_name}}" CACHE STRING "" FORCE) endforeach() endforeach() endif() diff --git a/README.md b/README.md index c597667..bf94de7 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ yaml-cpp uses [CMake](http://www.cmake.org) to support cross-platform building. * The `generator` is whatever type of build system you'd like to use. To see a full list of generators on your platform, just run `cmake` (with no arguments). For example: - * On Windows, you might use "Visual Studio 12 2013" to generate a Visual Studio 2013 solution + * On Windows, you might use "Visual Studio 12 2013" to generate a Visual Studio 2013 solution or "Visual Studio 14 2015 Win64" to generate a 64-bit Visual Studio 2015 solution. * On OS X, you might use "Xcode" to generate an Xcode project * On a UNIX-y system, simply omit the option to generate a makefile diff --git a/include/yaml-cpp/emitter.h b/include/yaml-cpp/emitter.h index 5bffc25..ef92cc4 100644 --- a/include/yaml-cpp/emitter.h +++ b/include/yaml-cpp/emitter.h @@ -162,12 +162,12 @@ inline Emitter& Emitter::WriteStreamable(T value) { template <> inline void Emitter::SetStreamablePrecision(std::stringstream& stream) { - stream.precision(GetFloatPrecision()); + stream.precision(static_cast(GetFloatPrecision())); } template <> inline void Emitter::SetStreamablePrecision(std::stringstream& stream) { - stream.precision(GetDoublePrecision()); + stream.precision(static_cast(GetDoublePrecision())); } // overloads of insertion diff --git a/include/yaml-cpp/exceptions.h b/include/yaml-cpp/exceptions.h index 285fc33..8e67c36 100644 --- a/include/yaml-cpp/exceptions.h +++ b/include/yaml-cpp/exceptions.h @@ -9,9 +9,9 @@ #include "yaml-cpp/mark.h" #include "yaml-cpp/traits.h" +#include #include #include -#include namespace YAML { // error messages @@ -89,7 +89,7 @@ const char* const BAD_FILE = "bad file"; template inline const std::string KEY_NOT_FOUND_WITH_KEY( - const T&, typename disable_if >::type* = 0) { + const T&, typename disable_if>::type* = 0) { return KEY_NOT_FOUND; } @@ -101,7 +101,7 @@ inline const std::string KEY_NOT_FOUND_WITH_KEY(const std::string& key) { template inline const std::string KEY_NOT_FOUND_WITH_KEY( - const T& key, typename enable_if >::type* = 0) { + const T& key, typename enable_if>::type* = 0) { std::stringstream stream; stream << KEY_NOT_FOUND << ": " << key; return stream.str(); @@ -112,7 +112,9 @@ 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() {} + virtual ~Exception() noexcept; + + Exception(const Exception&) = default; Mark mark; std::string msg; @@ -135,12 +137,16 @@ class ParserException : public Exception { public: ParserException(const Mark& mark_, const std::string& msg_) : Exception(mark_, msg_) {} + ParserException(const ParserException&) = default; + virtual ~ParserException() noexcept; }; class RepresentationException : public Exception { public: RepresentationException(const Mark& mark_, const std::string& msg_) : Exception(mark_, msg_) {} + RepresentationException(const RepresentationException&) = default; + virtual ~RepresentationException() noexcept; }; // representation exceptions @@ -148,6 +154,8 @@ class InvalidScalar : public RepresentationException { public: InvalidScalar(const Mark& mark_) : RepresentationException(mark_, ErrorMsg::INVALID_SCALAR) {} + InvalidScalar(const InvalidScalar&) = default; + virtual ~InvalidScalar() noexcept; }; class KeyNotFound : public RepresentationException { @@ -156,6 +164,8 @@ class KeyNotFound : public RepresentationException { KeyNotFound(const Mark& mark_, const T& key_) : RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) { } + KeyNotFound(const KeyNotFound&) = default; + virtual ~KeyNotFound() noexcept; }; template @@ -163,7 +173,7 @@ class TypedKeyNotFound : public KeyNotFound { public: TypedKeyNotFound(const Mark& mark_, const T& key_) : KeyNotFound(mark_, key_), key(key_) {} - virtual ~TypedKeyNotFound() throw() {} + virtual ~TypedKeyNotFound() noexcept {} T key; }; @@ -178,12 +188,16 @@ class InvalidNode : public RepresentationException { public: InvalidNode() : RepresentationException(Mark::null_mark(), ErrorMsg::INVALID_NODE) {} + InvalidNode(const InvalidNode&) = default; + virtual ~InvalidNode() noexcept; }; class BadConversion : public RepresentationException { public: explicit BadConversion(const Mark& mark_) : RepresentationException(mark_, ErrorMsg::BAD_CONVERSION) {} + BadConversion(const BadConversion&) = default; + virtual ~BadConversion() noexcept; }; template @@ -196,35 +210,47 @@ class BadDereference : public RepresentationException { public: BadDereference() : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_DEREFERENCE) {} + BadDereference(const BadDereference&) = default; + virtual ~BadDereference() noexcept; }; class BadSubscript : public RepresentationException { public: BadSubscript() : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_SUBSCRIPT) {} + BadSubscript(const BadSubscript&) = default; + virtual ~BadSubscript() noexcept; }; class BadPushback : public RepresentationException { public: BadPushback() : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_PUSHBACK) {} + BadPushback(const BadPushback&) = default; + virtual ~BadPushback() noexcept; }; class BadInsert : public RepresentationException { public: BadInsert() : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_INSERT) {} + BadInsert(const BadInsert&) = default; + virtual ~BadInsert() noexcept; }; class EmitterException : public Exception { public: EmitterException(const std::string& msg_) : Exception(Mark::null_mark(), msg_) {} + EmitterException(const EmitterException&) = default; + virtual ~EmitterException() noexcept; }; class BadFile : public Exception { public: BadFile() : Exception(Mark::null_mark(), ErrorMsg::BAD_FILE) {} + BadFile(const BadFile&) = default; + virtual ~BadFile() noexcept; }; } diff --git a/include/yaml-cpp/node/convert.h b/include/yaml-cpp/node/convert.h index f388a67..45a878a 100644 --- a/include/yaml-cpp/node/convert.h +++ b/include/yaml-cpp/node/convert.h @@ -7,6 +7,7 @@ #pragma once #endif +#include #include #include #include @@ -162,7 +163,7 @@ struct convert { // std::map template -struct convert > { +struct convert> { static Node encode(const std::map& rhs) { Node node(NodeType::Map); for (typename std::map::const_iterator it = rhs.begin(); @@ -189,7 +190,7 @@ struct convert > { // std::vector template -struct convert > { +struct convert> { static Node encode(const std::vector& rhs) { Node node(NodeType::Sequence); for (typename std::vector::const_iterator it = rhs.begin(); @@ -216,7 +217,7 @@ struct convert > { // std::list template -struct convert > { +struct convert> { static Node encode(const std::list& rhs) { Node node(NodeType::Sequence); for (typename std::list::const_iterator it = rhs.begin(); @@ -241,9 +242,42 @@ struct convert > { } }; +// std::array +template +struct convert> { + static Node encode(const std::array& rhs) { + Node node(NodeType::Sequence); + for (const auto& element : rhs) { + node.push_back(element); + } + return node; + } + + static bool decode(const Node& node, std::array& rhs) { + if (!isNodeValid(node)) { + return false; + } + + for (auto i = 0u; i < node.size(); ++i) { +#if defined(__GNUC__) && __GNUC__ < 4 + // workaround for GCC 3: + rhs[i] = node[i].template as(); +#else + rhs[i] = node[i].as(); +#endif + } + return true; + } + + private: + static bool isNodeValid(const Node& node) { + return node.IsSequence() && node.size() == N; + } +}; + // std::pair template -struct convert > { +struct convert> { static Node encode(const std::pair& rhs) { Node node(NodeType::Sequence); node.push_back(rhs.first); diff --git a/include/yaml-cpp/node/detail/impl.h b/include/yaml-cpp/node/detail/impl.h index 69f4476..5931826 100644 --- a/include/yaml-cpp/node/detail/impl.h +++ b/include/yaml-cpp/node/detail/impl.h @@ -32,7 +32,7 @@ struct get_idx& sequence, const Key& key, shared_memory_holder pMemory) { - if (key > sequence.size()) + if (key > sequence.size() || (key > 0 && !sequence[key-1]->is_defined())) return 0; if (key == sequence.size()) sequence.push_back(&pMemory->create_node()); @@ -132,6 +132,14 @@ inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) { if (m_type != NodeType::Map) return false; + kv_pairs::iterator it = m_undefinedPairs.begin(); + while (it != m_undefinedPairs.end()) { + kv_pairs::iterator jt = std::next(it); + if (it->first->equals(key, pMemory)) + m_undefinedPairs.erase(it); + it = jt; + } + for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) { if (it->first->equals(key, pMemory)) { m_map.erase(it); diff --git a/include/yaml-cpp/node/detail/node_data.h b/include/yaml-cpp/node/detail/node_data.h index 64bbc05..50bcd74 100644 --- a/include/yaml-cpp/node/detail/node_data.h +++ b/include/yaml-cpp/node/detail/node_data.h @@ -114,7 +114,7 @@ class YAML_CPP_API node_data { mutable std::size_t m_seqSize; // map - typedef std::map node_map; + typedef std::vector> node_map; node_map m_map; typedef std::pair kv_pair; diff --git a/include/yaml-cpp/node/detail/node_iterator.h b/include/yaml-cpp/node/detail/node_iterator.h index a33049a..4337df4 100644 --- a/include/yaml-cpp/node/detail/node_iterator.h +++ b/include/yaml-cpp/node/detail/node_iterator.h @@ -37,7 +37,7 @@ struct node_iterator_value : public std::pair { }; typedef std::vector node_seq; -typedef std::map node_map; +typedef std::vector> node_map; template struct node_iterator_type { @@ -55,7 +55,7 @@ template class node_iterator_base : public std::iterator, std::ptrdiff_t, node_iterator_value*, - node_iterator_value > { + node_iterator_value> { private: struct enabler {}; diff --git a/include/yaml-cpp/node/emit.h b/include/yaml-cpp/node/emit.h index 9154b51..032268c 100644 --- a/include/yaml-cpp/node/emit.h +++ b/include/yaml-cpp/node/emit.h @@ -27,6 +27,6 @@ YAML_CPP_API std::ostream& operator<<(std::ostream& out, const Node& node); /** Converts the node to a YAML string. */ YAML_CPP_API std::string Dump(const Node& node); -} // namespace YAML +} // namespace YAML #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 50af6b6..20c487a 100644 --- a/include/yaml-cpp/node/impl.h +++ b/include/yaml-cpp/node/impl.h @@ -103,7 +103,7 @@ struct as_if { explicit as_if(const Node& node_) : node(node_) {} const Node& node; - const std::string operator()(const S& fallback) const { + std::string operator()(const S& fallback) const { if (node.Type() != NodeType::Scalar) return fallback; return node.Scalar(); @@ -115,7 +115,7 @@ struct as_if { explicit as_if(const Node& node_) : node(node_) {} const Node& node; - const T operator()() const { + T operator()() const { if (!node.m_pNode) throw TypedBadConversion(node.Mark()); @@ -131,7 +131,7 @@ struct as_if { explicit as_if(const Node& node_) : node(node_) {} const Node& node; - const std::string operator()() const { + std::string operator()() const { if (node.Type() != NodeType::Scalar) throw TypedBadConversion(node.Mark()); return node.Scalar(); diff --git a/include/yaml-cpp/node/node.h b/include/yaml-cpp/node/node.h index 1207f6e..1ded7d2 100644 --- a/include/yaml-cpp/node/node.h +++ b/include/yaml-cpp/node/node.h @@ -58,7 +58,7 @@ class YAML_CPP_API Node { bool IsMap() const { return Type() == NodeType::Map; } // bool conversions - YAML_CPP_OPERATOR_BOOL(); + YAML_CPP_OPERATOR_BOOL() bool operator!() const { return !IsDefined(); } // access diff --git a/include/yaml-cpp/parser.h b/include/yaml-cpp/parser.h index 0e8a73e..ceac22d 100644 --- a/include/yaml-cpp/parser.h +++ b/include/yaml-cpp/parser.h @@ -47,7 +47,7 @@ class YAML_CPP_API Parser : private noncopyable { void Load(std::istream& in); /** - * Handles the next document by calling events on the {@param eventHandler}. + * Handles the next document by calling events on the {@code eventHandler}. * * @throw a ParserException on error. * @return false if there are no more documents diff --git a/src/emit.cpp b/src/emit.cpp index 67f68a9..51bc791 100644 --- a/src/emit.cpp +++ b/src/emit.cpp @@ -22,4 +22,4 @@ std::string Dump(const Node& node) { emitter << node; return emitter.c_str(); } -} // namespace YAML +} // namespace YAML diff --git a/src/emitfromevents.cpp b/src/emitfromevents.cpp index 45c5b99..4832649 100644 --- a/src/emitfromevents.cpp +++ b/src/emitfromevents.cpp @@ -111,7 +111,7 @@ void EmitFromEvents::BeginNode() { } void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor) { - if (!tag.empty() && tag != "?") + if (!tag.empty() && tag != "?" && tag != "!") m_emitter << VerbatimTag(tag); if (anchor) m_emitter << Anchor(ToString(anchor)); diff --git a/src/emitterstate.cpp b/src/emitterstate.cpp index e5555e6..3542aaf 100644 --- a/src/emitterstate.cpp +++ b/src/emitterstate.cpp @@ -124,7 +124,8 @@ void EmitterState::StartedScalar() { void EmitterState::StartedGroup(GroupType::value type) { StartedNode(); - const int lastGroupIndent = (m_groups.empty() ? 0 : m_groups.back()->indent); + const std::size_t lastGroupIndent = + (m_groups.empty() ? 0 : m_groups.back()->indent); m_curIndent += lastGroupIndent; // TODO: Create move constructors for settings types to simplify transfer @@ -193,7 +194,7 @@ FlowType::value EmitterState::CurGroupFlowType() const { return m_groups.empty() ? FlowType::NoType : m_groups.back()->flowType; } -int EmitterState::CurGroupIndent() const { +std::size_t EmitterState::CurGroupIndent() const { return m_groups.empty() ? 0 : m_groups.back()->indent; } @@ -205,7 +206,7 @@ bool EmitterState::CurGroupLongKey() const { return m_groups.empty() ? false : m_groups.back()->longKey; } -int EmitterState::LastIndent() const { +std::size_t EmitterState::LastIndent() const { if (m_groups.size() <= 1) { return 0; } @@ -347,15 +348,16 @@ bool EmitterState::SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope) { } } -bool EmitterState::SetFloatPrecision(int value, FmtScope::value scope) { - if (value < 0 || value > std::numeric_limits::digits10 + 1) +bool EmitterState::SetFloatPrecision(std::size_t value, FmtScope::value scope) { + if (value > std::numeric_limits::digits10 + 1) return false; _Set(m_floatPrecision, value, scope); return true; } -bool EmitterState::SetDoublePrecision(int value, FmtScope::value scope) { - if (value < 0 || value > std::numeric_limits::digits10 + 1) +bool EmitterState::SetDoublePrecision(std::size_t value, + FmtScope::value scope) { + if (value > std::numeric_limits::digits10 + 1) return false; _Set(m_doublePrecision, value, scope); return true; diff --git a/src/emitterstate.h b/src/emitterstate.h index aba390c..0937f00 100644 --- a/src/emitterstate.h +++ b/src/emitterstate.h @@ -58,12 +58,12 @@ class EmitterState { GroupType::value CurGroupType() const; FlowType::value CurGroupFlowType() const; - int CurGroupIndent() const; + std::size_t CurGroupIndent() const; std::size_t CurGroupChildCount() const; bool CurGroupLongKey() const; - int LastIndent() const; - int CurIndent() const { return m_curIndent; } + std::size_t LastIndent() const; + std::size_t CurIndent() const { return m_curIndent; } bool HasAnchor() const { return m_hasAnchor; } bool HasTag() const { return m_hasTag; } bool HasBegunNode() const { @@ -95,12 +95,12 @@ class EmitterState { EMITTER_MANIP GetIntFormat() const { return m_intFmt.get(); } bool SetIndent(std::size_t value, FmtScope::value scope); - int GetIndent() const { return m_indent.get(); } + std::size_t GetIndent() const { return m_indent.get(); } bool SetPreCommentIndent(std::size_t value, FmtScope::value scope); - int GetPreCommentIndent() const { return m_preCommentIndent.get(); } + std::size_t GetPreCommentIndent() const { return m_preCommentIndent.get(); } bool SetPostCommentIndent(std::size_t value, FmtScope::value scope); - int GetPostCommentIndent() const { return m_postCommentIndent.get(); } + std::size_t GetPostCommentIndent() const { return m_postCommentIndent.get(); } bool SetFlowType(GroupType::value groupType, EMITTER_MANIP value, FmtScope::value scope); @@ -109,9 +109,9 @@ class EmitterState { bool SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope); EMITTER_MANIP GetMapKeyFormat() const { return m_mapKeyFmt.get(); } - bool SetFloatPrecision(int value, FmtScope::value scope); + bool SetFloatPrecision(std::size_t value, FmtScope::value scope); std::size_t GetFloatPrecision() const { return m_floatPrecision.get(); } - bool SetDoublePrecision(int value, FmtScope::value scope); + bool SetDoublePrecision(std::size_t value, FmtScope::value scope); std::size_t GetDoublePrecision() const { return m_doublePrecision.get(); } private: @@ -137,8 +137,8 @@ class EmitterState { Setting m_seqFmt; Setting m_mapFmt; Setting m_mapKeyFmt; - Setting m_floatPrecision; - Setting m_doublePrecision; + Setting m_floatPrecision; + Setting m_doublePrecision; SettingChanges m_modifiedSettings; SettingChanges m_globalModifiedSettings; @@ -149,7 +149,7 @@ class EmitterState { GroupType::value type; FlowType::value flowType; - int indent; + std::size_t indent; std::size_t childCount; bool longKey; diff --git a/src/emitterutils.cpp b/src/emitterutils.cpp index 42c2a39..147738a 100644 --- a/src/emitterutils.cpp +++ b/src/emitterutils.cpp @@ -354,7 +354,7 @@ bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str, } bool WriteLiteralString(ostream_wrapper& out, const std::string& str, - int indent) { + std::size_t indent) { out << "|\n"; out << IndentTo(indent); int codePoint; @@ -380,6 +380,8 @@ bool WriteChar(ostream_wrapper& out, char ch) { out << "\"\\n\""; } else if (ch == '\b') { out << "\"\\b\""; + } else if (ch == '\\') { + out << "\"\\\\\""; } else if ((0x20 <= ch && ch <= 0x7e) || ch == ' ') { out << "\"" << ch << "\""; } else { @@ -391,7 +393,7 @@ bool WriteChar(ostream_wrapper& out, char ch) { } bool WriteComment(ostream_wrapper& out, const std::string& str, - int postCommentIndent) { + std::size_t postCommentIndent) { const std::size_t curIndent = out.col(); out << "#" << Indentation(postCommentIndent); out.set_comment(); diff --git a/src/emitterutils.h b/src/emitterutils.h index 3a9c2f8..6cc7319 100644 --- a/src/emitterutils.h +++ b/src/emitterutils.h @@ -34,10 +34,10 @@ bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str); bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str, bool escapeNonAscii); bool WriteLiteralString(ostream_wrapper& out, const std::string& str, - int indent); + std::size_t indent); bool WriteChar(ostream_wrapper& out, char ch); bool WriteComment(ostream_wrapper& out, const std::string& str, - int postCommentIndent); + std::size_t postCommentIndent); bool WriteAlias(ostream_wrapper& out, const std::string& str); bool WriteAnchor(ostream_wrapper& out, const std::string& str); bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim); diff --git a/src/exceptions.cpp b/src/exceptions.cpp new file mode 100644 index 0000000..8b5dfa2 --- /dev/null +++ b/src/exceptions.cpp @@ -0,0 +1,19 @@ +#include "yaml-cpp/exceptions.h" + +namespace YAML { + +// These destructors are defined out-of-line so the vtable is only emitted once. +Exception::~Exception() noexcept {} +ParserException::~ParserException() noexcept {} +RepresentationException::~RepresentationException() noexcept {} +InvalidScalar::~InvalidScalar() noexcept {} +KeyNotFound::~KeyNotFound() noexcept {} +InvalidNode::~InvalidNode() noexcept {} +BadConversion::~BadConversion() noexcept {} +BadDereference::~BadDereference() noexcept {} +BadSubscript::~BadSubscript() noexcept {} +BadPushback::~BadPushback() noexcept {} +BadInsert::~BadInsert() noexcept {} +EmitterException::~EmitterException() noexcept {} +BadFile::~BadFile() noexcept {} +} diff --git a/src/node_data.cpp b/src/node_data.cpp index a862946..77cd465 100644 --- a/src/node_data.cpp +++ b/src/node_data.cpp @@ -256,9 +256,10 @@ void node_data::reset_map() { } void node_data::insert_map_pair(node& key, node& value) { - m_map[&key] = &value; + m_map.emplace_back(&key, &value); + if (!key.is_defined() || !value.is_defined()) - m_undefinedPairs.push_back(kv_pair(&key, &value)); + m_undefinedPairs.emplace_back(&key, &value); } void node_data::convert_to_map(shared_memory_holder pMemory) { diff --git a/src/nodebuilder.cpp b/src/nodebuilder.cpp index 20ec3ac..093d2ef 100644 --- a/src/nodebuilder.cpp +++ b/src/nodebuilder.cpp @@ -48,9 +48,8 @@ void NodeBuilder::OnScalar(const Mark& mark, const std::string& tag, Pop(); } -void NodeBuilder::OnSequenceStart(const Mark& mark, - const std::string& tag, anchor_t anchor, - EmitterStyle::value style) { +void NodeBuilder::OnSequenceStart(const Mark& mark, const std::string& tag, + anchor_t anchor, EmitterStyle::value style) { detail::node& node = Push(mark, anchor); node.set_tag(tag); node.set_type(NodeType::Sequence); diff --git a/src/null.cpp b/src/null.cpp index 7158bd4..d12dd08 100644 --- a/src/null.cpp +++ b/src/null.cpp @@ -4,6 +4,7 @@ namespace YAML { _Null Null; bool IsNullString(const std::string& str) { - return str.empty() || str == "~" || str == "null" || str == "Null" || str == "NULL"; + return str.empty() || str == "~" || str == "null" || str == "Null" || + str == "NULL"; } } diff --git a/src/ptr_vector.h b/src/ptr_vector.h index 3ebed28..955aebd 100644 --- a/src/ptr_vector.h +++ b/src/ptr_vector.h @@ -22,29 +22,21 @@ class ptr_vector : private YAML::noncopyable { public: ptr_vector() {} - void clear() { - m_data.clear(); - } + void clear() { m_data.clear(); } std::size_t size() const { return m_data.size(); } bool empty() const { return m_data.empty(); } - void push_back(std::unique_ptr&& t) { - m_data.push_back(std::move(t)); - } + void push_back(std::unique_ptr&& t) { m_data.push_back(std::move(t)); } T& operator[](std::size_t i) { return *m_data[i]; } const T& operator[](std::size_t i) const { return *m_data[i]; } - T& back() { - return *(m_data.back().get()); - } + T& back() { return *(m_data.back().get()); } - const T& back() const { - return *(m_data.back().get()); - } + const T& back() const { return *(m_data.back().get()); } private: - std::vector> m_data; + std::vector> m_data; }; } diff --git a/src/regex_yaml.h b/src/regex_yaml.h index 3fa7327..8f28b85 100644 --- a/src/regex_yaml.h +++ b/src/regex_yaml.h @@ -10,6 +10,8 @@ #include #include +#include "yaml-cpp/dll.h" + namespace YAML { class Stream; @@ -26,7 +28,7 @@ enum REGEX_OP { // simplified regular expressions // . Only straightforward matches (no repeated characters) // . Only matches from start of string -class RegEx { +class YAML_CPP_API RegEx { public: RegEx(); RegEx(char ch); @@ -34,10 +36,10 @@ class RegEx { RegEx(const std::string& str, REGEX_OP op = REGEX_SEQ); ~RegEx() {} - friend RegEx operator!(const RegEx& ex); - friend RegEx operator||(const RegEx& ex1, const RegEx& ex2); - friend RegEx operator&&(const RegEx& ex1, const RegEx& ex2); - friend RegEx operator+(const RegEx& ex1, const RegEx& ex2); + friend YAML_CPP_API RegEx operator!(const RegEx& ex); + friend YAML_CPP_API RegEx operator||(const RegEx& ex1, const RegEx& ex2); + friend YAML_CPP_API RegEx operator&&(const RegEx& ex1, const RegEx& ex2); + friend YAML_CPP_API RegEx operator+(const RegEx& ex1, const RegEx& ex2); bool Matches(char ch) const; bool Matches(const std::string& str) const; diff --git a/src/scanner.cpp b/src/scanner.cpp index 3c9e7af..b5cfcc1 100644 --- a/src/scanner.cpp +++ b/src/scanner.cpp @@ -65,9 +65,9 @@ void Scanner::EnsureTokensInQueue() { } // no token? maybe we've actually finished - if (m_endedStream) { + if (m_endedStream) { return; - } + } // no? then scan... ScanNextToken(); diff --git a/test/integration/emitter_test.cpp b/test/integration/emitter_test.cpp index e65ed85..2780838 100644 --- a/test/integration/emitter_test.cpp +++ b/test/integration/emitter_test.cpp @@ -46,6 +46,12 @@ TEST_F(EmitterTest, SimpleScalar) { ExpectEmit("Hello, World!"); } +TEST_F(EmitterTest, SimpleQuotedScalar) { + Node n(Load("\"test\"")); + out << n; + ExpectEmit("test"); +} + TEST_F(EmitterTest, SimpleSeq) { out << BeginSeq; out << "eggs"; @@ -970,6 +976,14 @@ TEST_F(EmitterTest, ValueOfDoubleQuote) { ExpectEmit("foo: \"\\\"\""); } +TEST_F(EmitterTest, ValueOfBackslash) { + out << YAML::BeginMap; + out << YAML::Key << "foo" << YAML::Value << '\\'; + out << YAML::EndMap; + + ExpectEmit("foo: \"\\\\\""); +} + class EmitterErrorTest : public ::testing::Test { protected: void ExpectEmitError(const std::string& expectedError) { diff --git a/test/node/node_test.cpp b/test/node/node_test.cpp index 4105e72..485ad09 100644 --- a/test/node/node_test.cpp +++ b/test/node/node_test.cpp @@ -12,6 +12,14 @@ using ::testing::AnyOf; using ::testing::Eq; +#define EXPECT_THROW_REPRESENTATION_EXCEPTION(statement, message) \ + ASSERT_THROW(statement, RepresentationException); \ + try { \ + statement; \ + } catch (const RepresentationException& e) { \ + EXPECT_EQ(e.msg, message); \ + } + namespace YAML { namespace { TEST(NodeTest, SimpleScalar) { @@ -80,6 +88,24 @@ TEST(NodeTest, MapWithUndefinedValues) { EXPECT_EQ(2, node.size()); } +TEST(NodeTest, SeqIntoMap) { + Node node; + node[0] = "test"; + node[1]; + node[2] = "value"; + EXPECT_TRUE(node.IsMap()); + EXPECT_EQ("test", node[0].as()); + EXPECT_EQ("value", node[2].as()); + EXPECT_EQ(2, node.size()); +} + +TEST(NodeTest, RemoveUnassignedNode) { + Node node(NodeType::Map); + node["key"]; + node.remove("key"); + EXPECT_EQ(0, node.size()); +} + TEST(NodeTest, MapForceInsert) { Node node; Node k1("k1"); @@ -95,8 +121,8 @@ TEST(NodeTest, MapForceInsert) { node.force_insert(k2, v2); EXPECT_EQ("v1", node["k1"].as()); - EXPECT_EQ("v2", node["k2"].as()); - EXPECT_EQ(2, node.size()); + EXPECT_EQ("v1", node["k2"].as()); + EXPECT_EQ(3, node.size()); } TEST(NodeTest, UndefinedConstNodeWithFallback) { @@ -124,7 +150,7 @@ TEST(NodeTest, ConstIteratorOnConstUndefinedNode) { std::size_t count = 0; for (const_iterator it = undefinedCn.begin(); it != undefinedCn.end(); ++it) { count++; - } + } EXPECT_EQ(0, count); } @@ -136,7 +162,8 @@ TEST(NodeTest, IteratorOnConstUndefinedNode) { Node& nonConstUndefinedNode = const_cast(undefinedCn); std::size_t count = 0; - for (iterator it = nonConstUndefinedNode.begin(); it != nonConstUndefinedNode.end(); ++it) { + for (iterator it = nonConstUndefinedNode.begin(); + it != nonConstUndefinedNode.end(); ++it) { count++; } EXPECT_EQ(0, count); @@ -154,6 +181,22 @@ TEST(NodeTest, SimpleSubkeys) { EXPECT_EQ("monkey", node["username"].as()); } +TEST(NodeTest, StdArray) { + std::array evens{{2, 4, 6, 8, 10}}; + Node node; + node["evens"] = evens; + std::array actualEvens = node["evens"].as>(); + EXPECT_EQ(evens, actualEvens); +} + +TEST(NodeTest, StdArrayWrongSize) { + std::array evens{{2, 4, 6}}; + Node node; + node["evens"] = evens; + EXPECT_THROW_REPRESENTATION_EXCEPTION( + (node["evens"].as>()), ErrorMsg::BAD_CONVERSION); +} + TEST(NodeTest, StdVector) { std::vector primes; primes.push_back(2); @@ -165,7 +208,7 @@ TEST(NodeTest, StdVector) { Node node; node["primes"] = primes; - EXPECT_EQ(primes, node["primes"].as >()); + EXPECT_EQ(primes, node["primes"].as>()); } TEST(NodeTest, StdList) { @@ -179,7 +222,7 @@ TEST(NodeTest, StdList) { Node node; node["primes"] = primes; - EXPECT_EQ(primes, node["primes"].as >()); + EXPECT_EQ(primes, node["primes"].as>()); } TEST(NodeTest, StdMap) { @@ -192,7 +235,7 @@ TEST(NodeTest, StdMap) { Node node; node["squares"] = squares; - std::map actualSquares = node["squares"].as >(); + std::map actualSquares = node["squares"].as>(); EXPECT_EQ(squares, actualSquares); } @@ -204,7 +247,7 @@ TEST(NodeTest, StdPair) { Node node; node["pair"] = p; std::pair actualP = - node["pair"].as >(); + node["pair"].as>(); EXPECT_EQ(p, actualP); } diff --git a/util/read.cpp b/util/read.cpp index b1f787e..fc88f1f 100644 --- a/util/read.cpp +++ b/util/read.cpp @@ -1,10 +1,11 @@ -#include -#include - #include "yaml-cpp/emitterstyle.h" #include "yaml-cpp/eventhandler.h" #include "yaml-cpp/yaml.h" // IWYU pragma: keep +#include +#include +#include + class NullEventHandler : public YAML::EventHandler { public: typedef YAML::Mark Mark; diff --git a/yaml-cpp.pc.cmake b/yaml-cpp.pc.cmake index 04d343f..044ef78 100644 --- a/yaml-cpp.pc.cmake +++ b/yaml-cpp.pc.cmake @@ -1,7 +1,5 @@ -prefix=@CMAKE_INSTALL_PREFIX@ -exec_prefix=@CMAKE_INSTALL_PREFIX@ -libdir=${prefix}/@LIB_INSTALL_DIR@ -includedir=${prefix}/@INCLUDE_INSTALL_ROOT_DIR@ +libdir=@LIB_INSTALL_DIR@ +includedir=@INCLUDE_INSTALL_ROOT_DIR@ Name: Yaml-cpp Description: A YAML parser and emitter for C++