Commit 3d091871 authored by Andreas Tille's avatar Andreas Tille

Update upstream source from tag 'upstream/0.5.3'

Update to upstream version '0.5.3'
with Debian dir bc2cc3021db7ebe616264ee78da7f18f4bb1b2ed
parents 56d05874 10d9bea3
**.h = native
**.c = native
**.cpp = native
**.txt = native
......@@ -23,7 +23,7 @@ project(YAML_CPP)
set(YAML_CPP_VERSION_MAJOR "0")
set(YAML_CPP_VERSION_MINOR "5")
set(YAML_CPP_VERSION_PATCH "2")
set(YAML_CPP_VERSION_PATCH "3")
set(YAML_CPP_VERSION "${YAML_CPP_VERSION_MAJOR}.${YAML_CPP_VERSION_MINOR}.${YAML_CPP_VERSION_PATCH}")
enable_testing()
......
# Style
This project is formatted with [clang-format][fmt] using the style file at the root of the repository. Please run clang-format before sending a pull request.
In general, try to follow the style of surrounding code.
[fmt]: http://clang.llvm.org/docs/ClangFormat.html
# Tests
Please verify the tests pass by running the target `tests/run_tests`.
If you are adding functionality, add tests accordingly.
# Pull request process
Every pull request undergoes a code review. Unfortunately, github's code review process isn't great, but we'll manage. During the code review, if you make changes, add new commits to the pull request for each change. Once the code review is complete, rebase against the master branch and squash into a single commit.
Copyright (c) 2008 Jesse Beder.
Copyright (c) 2008-2015 Jesse Beder.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
......
# yaml-cpp
yaml-cpp is a [YAML](http://www.yaml.org/) parser and emitter in C++ matching the [YAML 1.2 spec](http://www.yaml.org/spec/1.2/spec.html).
To get a feel for how it can be used, see the [Tutorial](https://github.com/jbeder/yaml-cpp/wiki/Tutorial) or [How to Emit YAML](https://github.com/jbeder/yaml-cpp/wiki/How-To-Emit-YAML). For the old API (version < 0.5.0), see [How To Parse A Document](https://github.com/jbeder/yaml-cpp/wiki/How-To-Parse-A-Document-(Old-API)).
# Problems? #
If you find a bug, post an [issue](https://github.com/jbeder/yaml-cpp/issues)! If you have questions about how to use yaml-cpp, please post it on http://stackoverflow.com and tag it `yaml-cpp`.
# How to Build #
yaml-cpp uses [CMake](http://www.cmake.org) to support cross-platform building. The basic steps to build are:
1. Download and install [CMake](http://www.cmake.org) (Resources -> Download).
**Note:** If you don't use the provided installer for your platform, make sure that you add CMake's bin folder to your path.
2. Navigate into the source directory, and type:
```
mkdir build
cd build
```
3. Run CMake. The basic syntax is:
```
cmake [-G generator] [-DBUILD_SHARED_LIBS=ON|OFF] ..
```
* 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 OS X, you might use "Xcode" to generate an Xcode project
* On a UNIX-y system, simply omit the option to generate a makefile
* yaml-cpp defaults to building a static library, but you may build a shared library by specifying `-DBUILD_SHARED_LIBS=ON`.
* For more options on customizing the build, see the [CMakeLists.txt](https://github.com/jbeder/yaml-cpp/blob/master/CMakeLists.txt) file.
4. Build it!
5. To clean up, just remove the `build` directory.
# Recent Release #
[yaml-cpp 0.5.2](https://github.com/jbeder/yaml-cpp/releases/tag/release-0.5.2) has been released! This is a bug fix release.
[yaml-cpp 0.3.0](https://github.com/jbeder/yaml-cpp/releases/tag/release-0.3.0) is still available if you want the old API.
**The old API will continue to be supported, and will still receive bugfixes!** The 0.3.x and 0.4.x versions will be old API releases, and 0.5.x and above will all be new API releases.
......@@ -120,6 +120,10 @@ class Exception : public std::runtime_error {
private:
static const std::string build_what(const Mark& mark,
const std::string& msg) {
if (mark.is_null()) {
return msg.c_str();
}
std::stringstream output;
output << "yaml-cpp: error at line " << mark.line + 1 << ", column "
<< mark.column + 1 << ": " << msg;
......@@ -178,14 +182,14 @@ class InvalidNode : public RepresentationException {
class BadConversion : public RepresentationException {
public:
BadConversion()
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_CONVERSION) {}
explicit BadConversion(const Mark& mark_)
: RepresentationException(mark_, ErrorMsg::BAD_CONVERSION) {}
};
template <typename T>
class TypedBadConversion : public BadConversion {
public:
TypedBadConversion() : BadConversion() {}
explicit TypedBadConversion(const Mark& mark_) : BadConversion(mark_) {}
};
class BadDereference : public RepresentationException {
......
......@@ -15,6 +15,8 @@ struct YAML_CPP_API Mark {
static const Mark null_mark() { return Mark(-1, -1, -1); }
bool is_null() const { return pos == -1 && line == -1 && column == -1; }
int pos;
int line, column;
......
......@@ -43,6 +43,17 @@ inline bool IsNaN(const std::string& input) {
}
}
// Node
template <>
struct convert<Node> {
static Node encode(const Node& rhs) { return rhs; }
static bool decode(const Node& node, Node& rhs) {
rhs.reset(node);
return true;
}
};
// std::string
template <>
struct convert<std::string> {
......
......@@ -133,7 +133,7 @@ inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) {
return false;
for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) {
if (equals(*it->first, key, pMemory)) {
if (it->first->equals(key, pMemory)) {
m_map.erase(it);
return true;
}
......
......@@ -7,8 +7,6 @@
#pragma once
#endif
#include <boost/shared_ptr.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <set>
#include "yaml-cpp/dll.h"
......@@ -40,7 +38,7 @@ class YAML_CPP_API memory_holder {
void merge(memory_holder& rhs);
private:
boost::shared_ptr<memory> m_pMemory;
shared_memory m_pMemory;
};
}
}
......
......@@ -25,6 +25,7 @@ class node : private boost::noncopyable {
const node_ref* ref() const { return m_pRef.get(); }
bool is_defined() const { return m_pRef->is_defined(); }
const Mark& mark() const { return m_pRef->mark(); }
NodeType::value type() const { return m_pRef->type(); }
const std::string& scalar() const { return m_pRef->scalar(); }
......@@ -64,6 +65,10 @@ class node : private boost::noncopyable {
m_pRef->set_data(*rhs.m_pRef);
}
void set_mark(const Mark& mark) {
m_pRef->set_mark(mark);
}
void set_type(NodeType::value type) {
if (type != NodeType::Undefined)
mark_defined();
......
......@@ -34,6 +34,7 @@ class YAML_CPP_API node_data : private boost::noncopyable {
node_data();
void mark_defined();
void set_mark(const Mark& mark);
void set_type(NodeType::value type);
void set_tag(const std::string& tag);
void set_null();
......@@ -41,6 +42,7 @@ class YAML_CPP_API node_data : private boost::noncopyable {
void set_style(EmitterStyle::value style);
bool is_defined() const { return m_isDefined; }
const Mark& mark() const { return m_mark; }
NodeType::value type() const {
return m_isDefined ? m_type : NodeType::Undefined;
}
......@@ -97,6 +99,7 @@ class YAML_CPP_API node_data : private boost::noncopyable {
private:
bool m_isDefined;
Mark m_mark;
NodeType::value m_type;
std::string m_tag;
EmitterStyle::value m_style;
......
......@@ -20,6 +20,7 @@ class node_ref : private boost::noncopyable {
node_ref() : m_pData(new node_data) {}
bool is_defined() const { return m_pData->is_defined(); }
const Mark& mark() const { return m_pData->mark(); }
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(); }
......@@ -28,6 +29,7 @@ class node_ref : private boost::noncopyable {
void mark_defined() { m_pData->mark_defined(); }
void set_data(const node_ref& rhs) { m_pData = rhs.m_pData; }
void set_mark(const Mark& mark) { m_pData->set_mark(mark); }
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(); }
......
......@@ -66,6 +66,13 @@ inline bool Node::IsDefined() const {
return m_pNode ? m_pNode->is_defined() : true;
}
inline Mark Node::Mark() const {
if (!m_isValid) {
throw InvalidNode();
}
return m_pNode ? m_pNode->mark() : Mark::null_mark();
}
inline NodeType::value Node::Type() const {
if (!m_isValid)
throw InvalidNode();
......@@ -80,7 +87,7 @@ struct as_if {
explicit as_if(const Node& node_) : node(node_) {}
const Node& node;
const T operator()(const S& fallback) const {
T operator()(const S& fallback) const {
if (!node.m_pNode)
return fallback;
......@@ -110,12 +117,12 @@ struct as_if<T, void> {
const T operator()() const {
if (!node.m_pNode)
throw TypedBadConversion<T>();
throw TypedBadConversion<T>(node.Mark());
T t;
if (convert<T>::decode(node, t))
return t;
throw TypedBadConversion<T>();
throw TypedBadConversion<T>(node.Mark());
}
};
......@@ -126,23 +133,23 @@ struct as_if<std::string, void> {
const std::string operator()() const {
if (node.Type() != NodeType::Scalar)
throw TypedBadConversion<std::string>();
throw TypedBadConversion<std::string>(node.Mark());
return node.Scalar();
}
};
// access functions
template <typename T>
inline const T Node::as() const {
inline T Node::as() const {
if (!m_isValid)
throw InvalidNode();
return as_if<T, void>(*this)();
}
template <typename T, typename S>
inline const T Node::as(const S& fallback) const {
inline T Node::as(const S& fallback) const {
if (!m_isValid)
throw InvalidNode();
return fallback;
return as_if<T, S>(*this)(fallback);
}
......@@ -275,26 +282,26 @@ inline std::size_t Node::size() const {
inline const_iterator Node::begin() const {
if (!m_isValid)
throw InvalidNode();
return const_iterator();
return m_pNode ? const_iterator(m_pNode->begin(), m_pMemory)
: const_iterator();
}
inline iterator Node::begin() {
if (!m_isValid)
throw InvalidNode();
return iterator();
return m_pNode ? iterator(m_pNode->begin(), m_pMemory) : iterator();
}
inline const_iterator Node::end() const {
if (!m_isValid)
throw InvalidNode();
return const_iterator();
return m_pNode ? const_iterator(m_pNode->end(), m_pMemory) : const_iterator();
}
inline iterator Node::end() {
if (!m_isValid)
throw InvalidNode();
return iterator();
return m_pNode ? iterator(m_pNode->end(), m_pMemory) : iterator();
}
......
......@@ -11,6 +11,7 @@
#include "yaml-cpp/dll.h"
#include "yaml-cpp/emitterstyle.h"
#include "yaml-cpp/mark.h"
#include "yaml-cpp/node/detail/bool_type.h"
#include "yaml-cpp/node/detail/iterator_fwd.h"
#include "yaml-cpp/node/ptr.h"
......@@ -48,6 +49,7 @@ class YAML_CPP_API Node {
Node(const Node& rhs);
~Node();
YAML::Mark Mark() const;
NodeType::value Type() const;
bool IsDefined() const;
bool IsNull() const { return Type() == NodeType::Null; }
......@@ -61,9 +63,9 @@ class YAML_CPP_API Node {
// access
template <typename T>
const T as() const;
T as() const;
template <typename T, typename S>
const T as(const S& fallback) const;
T as(const S& fallback) const;
const std::string& Scalar() const;
const std::string& Tag() const;
......
......@@ -375,14 +375,16 @@ bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
bool WriteChar(ostream_wrapper& out, char ch) {
if (('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')) {
out << ch;
} else if ((0x20 <= ch && ch <= 0x7e) || ch == ' ') {
out << "\"" << ch << "\"";
} else if (ch == '\"') {
out << "\"\\\"\"";
} else if (ch == '\t') {
out << "\"\\t\"";
} else if (ch == '\n') {
out << "\"\\n\"";
} else if (ch == '\b') {
out << "\"\\b\"";
} else if ((0x20 <= ch && ch <= 0x7e) || ch == ' ') {
out << "\"" << ch << "\"";
} else {
out << "\"";
WriteDoubleQuoteEscapeSequence(out, ch);
......
......@@ -17,6 +17,7 @@ std::string node_data::empty_scalar;
node_data::node_data()
: m_isDefined(false),
m_mark(Mark::null_mark()),
m_type(NodeType::Null),
m_style(EmitterStyle::Default),
m_seqSize(0) {}
......@@ -27,6 +28,10 @@ void node_data::mark_defined() {
m_isDefined = true;
}
void node_data::set_mark(const Mark& mark) {
m_mark = mark;
}
void node_data::set_type(NodeType::value type) {
if (type == NodeType::Undefined) {
m_type = type;
......
......@@ -28,8 +28,8 @@ void NodeBuilder::OnDocumentStart(const Mark&) {}
void NodeBuilder::OnDocumentEnd() {}
void NodeBuilder::OnNull(const Mark& /* mark */, anchor_t anchor) {
detail::node& node = Push(anchor);
void NodeBuilder::OnNull(const Mark& mark, anchor_t anchor) {
detail::node& node = Push(mark, anchor);
node.set_null();
Pop();
}
......@@ -40,18 +40,18 @@ void NodeBuilder::OnAlias(const Mark& /* mark */, anchor_t anchor) {
Pop();
}
void NodeBuilder::OnScalar(const Mark& /* mark */, const std::string& tag,
void NodeBuilder::OnScalar(const Mark& mark, const std::string& tag,
anchor_t anchor, const std::string& value) {
detail::node& node = Push(anchor);
detail::node& node = Push(mark, anchor);
node.set_scalar(value);
node.set_tag(tag);
Pop();
}
void NodeBuilder::OnSequenceStart(const Mark& /* mark */,
void NodeBuilder::OnSequenceStart(const Mark& mark,
const std::string& tag, anchor_t anchor,
EmitterStyle::value style) {
detail::node& node = Push(anchor);
detail::node& node = Push(mark, anchor);
node.set_tag(tag);
node.set_type(NodeType::Sequence);
node.set_style(style);
......@@ -59,9 +59,9 @@ void NodeBuilder::OnSequenceStart(const Mark& /* mark */,
void NodeBuilder::OnSequenceEnd() { Pop(); }
void NodeBuilder::OnMapStart(const Mark& /* mark */, const std::string& tag,
void NodeBuilder::OnMapStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style) {
detail::node& node = Push(anchor);
detail::node& node = Push(mark, anchor);
node.set_type(NodeType::Map);
node.set_tag(tag);
node.set_style(style);
......@@ -74,8 +74,9 @@ void NodeBuilder::OnMapEnd() {
Pop();
}
detail::node& NodeBuilder::Push(anchor_t anchor) {
detail::node& NodeBuilder::Push(const Mark& mark, anchor_t anchor) {
detail::node& node = m_pMemory->create_node();
node.set_mark(mark);
RegisterAnchor(anchor, node);
Push(node);
return node;
......
......@@ -48,7 +48,7 @@ class NodeBuilder : public EventHandler {
virtual void OnMapEnd();
private:
detail::node& Push(anchor_t anchor);
detail::node& Push(const Mark& mark, anchor_t anchor);
void Push(detail::node& node);
void Pop();
void RegisterAnchor(anchor_t anchor, detail::node& node);
......
......@@ -962,6 +962,14 @@ TEST_F(EmitterTest, QuoteNull) {
ExpectEmit("\"null\"");
}
TEST_F(EmitterTest, ValueOfDoubleQuote) {
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) {
......
......@@ -39,6 +39,13 @@ TEST(NodeTest, SimpleAppendSequence) {
EXPECT_TRUE(node.IsSequence());
}
TEST(NodeTest, MapElementRemoval) {
Node node;
node["foo"] = "bar";
node.remove("foo");
EXPECT_TRUE(!node["foo"]);
}
TEST(NodeTest, SimpleAssignSequence) {
Node node;
node[0] = 10;
......@@ -73,6 +80,31 @@ TEST(NodeTest, MapWithUndefinedValues) {
EXPECT_EQ(2, node.size());
}
TEST(NodeTest, MapForceInsert) {
Node node;
Node k1("k1");
Node k2("k2");
Node v1("v1");
Node v2("v2");
node[k1] = v1;
node[k2] = v1;
EXPECT_TRUE(node.IsMap());
EXPECT_EQ("v1", node["k1"].as<std::string>());
EXPECT_EQ("v1", node["k2"].as<std::string>());
EXPECT_EQ(2, node.size());
node.force_insert(k2, v2);
EXPECT_EQ("v1", node["k1"].as<std::string>());
EXPECT_EQ("v2", node["k2"].as<std::string>());
EXPECT_EQ(2, node.size());
}
TEST(NodeTest, UndefinedConstNodeWithFallback) {
Node node;
const Node& cn = node;
EXPECT_EQ(cn["undefined"].as<int>(3), 3);
}
TEST(NodeTest, MapIteratorWithUndefinedValues) {
Node node;
node["key"] = "value";
......@@ -84,6 +116,32 @@ TEST(NodeTest, MapIteratorWithUndefinedValues) {
EXPECT_EQ(1, count);
}
TEST(NodeTest, ConstIteratorOnConstUndefinedNode) {
Node node;
const Node& cn = node;
const Node& undefinedCn = cn["undefined"];
std::size_t count = 0;
for (const_iterator it = undefinedCn.begin(); it != undefinedCn.end(); ++it) {
count++;
}
EXPECT_EQ(0, count);
}
TEST(NodeTest, IteratorOnConstUndefinedNode) {
Node node;
const Node& cn = node;
const Node& undefinedCn = cn["undefined"];
Node& nonConstUndefinedNode = const_cast<Node&>(undefinedCn);
std::size_t count = 0;
for (iterator it = nonConstUndefinedNode.begin(); it != nonConstUndefinedNode.end(); ++it) {
count++;
}
EXPECT_EQ(0, count);
}
TEST(NodeTest, SimpleSubkeys) {
Node node;
node["device"]["udid"] = "12345";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment