Compare commits

..

140 Commits

Author SHA1 Message Date
Jesse Beder
fa6a71e37f Bumped version to 0.5.1 2013-04-13 18:37:33 -05:00
Jesse Beder
e5aa599b27 Merge null string bug fix from core, plus bug fix regarding use-after-delete for a token that seems to have been ignored. 2013-04-13 18:25:37 -05:00
Jesse Beder
2375f2c66b Fix bug where the string "null" (without quotes) is deserialized as a string, instead of null. 2013-04-13 18:21:06 -05:00
Jesse Beder
895af26226 Fix floating point precision on input. 2013-04-13 13:10:36 -05:00
Jesse Beder
ae42def6cf Merge to fix default precision for floats. 2013-04-13 00:09:40 -05:00
Jesse Beder
e0ae477b8f Switch default precision to one more than the number of digits allows.
See, e.g., http://stackoverflow.com/questions/4738768/printing-double-without-losing-precision.
2013-04-13 00:00:58 -05:00
Jesse Beder
434c6a5697 Add better exception reporting when incorrectly dereferencing an iterator. 2013-04-12 23:41:02 -05:00
Jesse Beder
097ac171c6 Add std::pair conversion specialization. 2013-04-02 21:04:17 -05:00
Jesse Beder
0482463569 Rename clear() to reset(), and it now takes an optional node parameter. 2013-04-02 20:39:54 -05:00
Jesse Beder
5dbcf7eeb1 Fix conversion for C-strings (both literals and normal C-strings) so it compiles on Visual Studio. 2013-04-01 22:25:53 -05:00
Jesse Beder
f5418306d6 Explicity disallow get_idx for boolean type, to avoid ambiguity with a map. 2013-04-01 22:06:09 -05:00
Jesse Beder
04937649b7 Add missing line from previous fix. 2013-04-01 21:52:32 -05:00
Jesse Beder
71f35b1104 Fix warning in Visual Studio:
warning C4146: unary minus operator applied to unsigned type, result still unsigned
2013-04-01 21:43:09 -05:00
Jesse Beder
c335c8dd75 Added tag release-0.5.0 for changeset d042aa2fa32d 2012-12-28 18:59:29 -06:00
Jesse Beder
6276189716 Merged ? fix from core 2012-11-08 19:12:22 -06:00
Jesse Beder
8c517bf0fd Fixed parsing ? when attached to a scalar 2012-11-08 19:11:41 -06:00
Jesse Beder
15b60e2a3b Added failing test for parsing a ? at the start of a value 2012-11-08 19:00:46 -06:00
Jesse Beder
4e1bdd08d3 Removed that failing test - I don't think the parser is correct here 2012-11-08 18:54:53 -06:00
Jesse Beder
490265cf22 Added failing tests for emitter ? at the start of a value 2012-11-08 18:52:54 -06:00
Jesse Beder
bcdda4027f Added Node::clear() function 2012-11-08 18:47:22 -06:00
Jesse Beder
eb02dd8dc3 Fixed typo from null fix 2012-11-08 18:40:44 -06:00
Jesse Beder
5721ac6194 Pulled 'null' renaming fix 2012-11-08 18:39:06 -06:00
Jesse Beder
0c72825303 Renamed all variables named 'null' (for real now, and only that) 2012-11-08 18:38:20 -06:00
Jesse Beder
6539648dac Merge from core + revert 2012-11-08 18:34:09 -06:00
Jesse Beder
b12e4b0781 Merged from core, rfaef276b1f6e 2012-11-08 18:33:12 -06:00
Jesse Beder
16f05e73b9 Reverted last change 2012-11-08 18:24:00 -06:00
Jesse Beder
06e09d1d64 Renamed all variables named 'null' 2012-11-08 18:21:00 -06:00
Jesse Beder
0c772c4c3f Set LoadFile and LoadAllFromFile to throw an exception if we can't load the file 2012-11-08 18:14:26 -06:00
Jesse Beder
a03e861d8c Switched map's convert<> specialization to use the new force_insert 2012-10-31 19:10:45 -05:00
Jesse Beder
09b4706faf Added force_insert for mapping nodes that doesn't check to see if the key exists already (so it could duplicate keys) 2012-10-31 19:08:09 -05:00
Jesse Beder
a645866ffa Simplified Node::operator[] interface by removing the C-string overloads, using a helper to_value 2012-10-31 18:55:07 -05:00
Jesse Beder
979a91692f Added small 'read' program to test reading a single doc (from stdin) 2012-09-15 16:29:07 -07:00
Jesse Beder
1d1d6886cc Fixed typo in the core parser tests 2012-09-15 15:50:44 -07:00
Jeff Wang
d770a7dc97 workaround for gcc 3 2012-07-17 11:55:45 -05:00
Jesse Beder
823311384f Added free Clone() function for Nodes 2012-07-04 15:26:37 -05:00
Jesse Beder
f29ea4b070 Merged end of map/seq flow fix from core 2012-06-09 14:42:00 -05:00
Jesse Beder
68dd9b5d18 Fixed bug where the parser doesn't find the end of a map or seq flow 2012-06-09 14:39:00 -05:00
Jesse Beder
2d815c5d6a Added extra parser tests for the core; in particular, one that asserts instead of throwing 2012-06-09 14:26:44 -05:00
Jesse Beder
c722684f0d Removed unnecessary forward declarations 2012-06-08 10:26:49 -05:00
Jesse Beder
5c097d417a Removed stray GetNextDocument declaration from the parser (it's from the old API, and not the new one) 2012-06-08 10:25:42 -05:00
Jesse Beder
ab36ca930f Updated from core (emitter) 2012-05-25 19:39:15 -05:00
Jesse Beder
d5130a4109 Changed Emitter::size() to return std::size_t instead of unsigned 2012-05-25 19:38:58 -05:00
Jesse Beder
6c690e8294 Updated the ostream emitting overload to user the new ostream-handling emitters 2012-05-25 19:38:20 -05:00
Jesse Beder
a78069a6e2 Merged ostreams for the emitter change from the core 2012-05-25 19:35:24 -05:00
Jesse Beder
bc3f72b565 Switched the stream << for c-strings to take a templated array param (since we never stream user-built c-strings, only string literals). For this, refactored the escape character display 2012-05-25 19:33:34 -05:00
Jesse Beder
772969270d Refactored stream overloads 2012-05-25 18:24:07 -05:00
Jesse Beder
2ffdc5b4d1 Added constructor to the Emitter with a stream, so you can write directly to a stream instead of our temp 2012-05-25 18:22:33 -05:00
Jesse Beder
e6d4a915dc Switched the ostream wrapper to wrap a std::vector<char> instead of our manually managed memory 2012-05-25 18:17:14 -05:00
Jesse Beder
7c85e9d5de Updated ostream wrapper with a write() and update_pos 2012-05-25 17:39:14 -05:00
Jesse Beder
1602f78974 Renamed ostream -> ostream_wrapper 2012-05-25 17:28:35 -05:00
Jesse Beder
4116d89f2c Merged emitter refactor from core 2012-05-23 15:30:03 -05:00
Jesse Beder
2dd1cf4596 Added compiler flag to compile the generated tests, since gcc takes *forever* to compile them 2012-05-23 15:16:34 -05:00
Jesse Beder
f011975769 Fixed handler macros to remove warnings in gcc 2012-05-23 15:12:36 -05:00
Jesse Beder
288c7e51f2 Added seq/map gen emitter tests 2012-05-23 11:20:36 -05:00
Jesse Beder
52813050d2 Fixed map/comment/seq emitting 2012-05-23 11:18:53 -05:00
Jesse Beder
1ab9469f10 Added map/seq gen emitter tests, including some failing ones 2012-05-23 11:16:32 -05:00
Jesse Beder
3ddfeff4f5 Added seq gen emitter tests 2012-05-23 11:11:50 -05:00
Jesse Beder
fdfffb0916 Added gen emitter tests 2012-05-23 11:02:42 -05:00
Jesse Beder
52d01ff154 Fixed top-level comment emitting 2012-05-23 11:02:17 -05:00
Jesse Beder
c197d822c1 Updated gen emitter tests 2012-05-23 11:00:33 -05:00
Jesse Beder
277132a21f Refactored emitter test template code 2012-05-23 10:56:16 -05:00
Jesse Beder
5af3fc04c6 Registered all the generated emitter tests 2012-05-22 22:17:50 -05:00
Jesse Beder
0fb59c18dd Split test struct and handler macros out for the emitter/spec tests 2012-05-22 22:10:47 -05:00
Jesse Beder
115101d25d Updated emitter test script, and moved handler macros to own include file 2012-05-22 21:59:12 -05:00
Jesse Beder
8d529cbcf2 Started emitting test generator 2012-05-22 19:31:23 -05:00
Jesse Beder
7d7075fdf9 Set indentation to be at least 2 2012-05-22 18:01:48 -05:00
Jesse Beder
8aabc0766b Fixed indentation test - all emitter tests now pass 2012-05-22 17:56:07 -05:00
Jesse Beder
abd49d8bca Added null 2012-05-22 17:55:17 -05:00
Jesse Beder
8b3778a639 Fixed warnings 2012-05-22 17:50:40 -05:00
Jesse Beder
0abbf650b5 Fixed char output 2012-05-22 17:50:10 -05:00
Jesse Beder
c664d50d5c Fixed double quote escapes (e.g., \n is now that instead of \x0a) 2012-05-22 17:45:31 -05:00
Jesse Beder
ad275901b2 Switched single quoted test to positive test (since we just convert to double quoted) 2012-05-22 16:59:39 -05:00
Jesse Beder
a6fe313d32 Removed key/value error checks (since we don't require asking them) 2012-05-22 16:57:30 -05:00
Jesse Beder
4123583159 Fixed end seq/map error msg 2012-05-22 16:56:10 -05:00
Jesse Beder
2c2b788391 Fixed doc start/end 2012-05-22 16:53:40 -05:00
Jesse Beder
bc884061e2 Fixed some newline/comma tests 2012-05-22 16:49:09 -05:00
Jesse Beder
611d243b84 Fixed global setting indentation 2012-05-22 16:47:08 -05:00
Jesse Beder
b2f9a61c46 Fixed emitter tests with newlines 2012-05-22 16:44:49 -05:00
Jesse Beder
f4278fe39f Added long key flow map 2012-05-22 16:41:03 -05:00
Jesse Beder
676e0b94ac Fixed flow seq/map indentation 2012-05-22 16:39:03 -05:00
Jesse Beder
0e3e6791ff Added flow map, simple key/value 2012-05-22 16:36:07 -05:00
Jesse Beder
b8a87c43bc Added flow seq 2012-05-22 15:42:45 -05:00
Jesse Beder
2670ce8aaf Fixed bool formatting 2012-05-22 15:08:21 -05:00
Jesse Beder
faa2e50605 Forced literal scalars to use long keys 2012-05-22 15:07:11 -05:00
Jesse Beder
cdfbac1fd7 Fixed some tests with the new compact long keys 2012-05-22 15:02:36 -05:00
Jesse Beder
944ebb7d1e Fixed settings reverting properly 2012-05-22 15:00:10 -05:00
Jesse Beder
bf07af52ff Added long key 2012-05-22 14:26:34 -05:00
Jesse Beder
41e4cd3308 Split block map simple/long key for both key/value 2012-05-22 14:20:50 -05:00
Jesse Beder
952fe51c73 Added writing float/double 2012-05-22 13:59:31 -05:00
Jesse Beder
c95bcae49f Added writing integral types 2012-05-22 13:57:44 -05:00
Jesse Beder
cc559956a0 Added bool, char, binary 2012-05-22 13:53:03 -05:00
Jesse Beder
879f96d2f6 Tweak sandbox 2012-05-22 12:59:58 -05:00
Jesse Beder
5e0886db87 Fixed block map prepare value (where the colon goes) 2012-05-22 12:59:07 -05:00
Jesse Beder
a626424baa Split the block map prepare into key/value 2012-05-22 12:56:40 -05:00
Jesse Beder
80823583a0 Tweaked spacing for comments 2012-05-22 12:54:54 -05:00
Jesse Beder
eef692d7b2 Fixed when we emit the doc start (only if there already is a document in the stream, and we're about to emit a new node) 2012-05-22 12:37:00 -05:00
Jesse Beder
0814813302 Added comments, not entirely correct 2012-05-22 12:29:36 -05:00
Jesse Beder
0f3f1e26a7 Fixed map/value 2012-05-21 23:47:57 -05:00
Jesse Beder
f72e325c40 Renamed begin/end scalar/group to started/ended scalar/group 2012-05-21 23:39:45 -05:00
Jesse Beder
07e88a78cb Added alias 2012-05-21 23:37:49 -05:00
Jesse Beder
c5e4bdee94 Fixed newline 2012-05-21 23:34:42 -05:00
Jesse Beder
d3801b7482 Added newlines, fixed map/map 2012-05-21 23:29:59 -05:00
Jesse Beder
b0dd0f862a Fixed anchor/tag in seq > map 2012-05-21 23:23:53 -05:00
Jesse Beder
3cae26a75e Added tags and anchors 2012-05-21 23:19:29 -05:00
Jesse Beder
91eac5d93d Implemented block seq and block map indentation/newlines 2012-05-21 22:14:26 -05:00
Jesse Beder
35d827f187 Structured emitter node handling better 2012-05-21 21:57:25 -05:00
Jesse Beder
23fb2dc811 Fixed basic block seq indentation 2012-05-21 21:11:03 -05:00
Jesse Beder
b5d8241dfa Added block seq indentation 2012-05-21 21:04:10 -05:00
Jesse Beder
d86cfc1c63 Implemented the Write for scalars (including checking which type of scalar it should be) 2012-05-21 19:07:56 -05:00
Jesse Beder
65d80ebc11 Started prepare node 2012-05-21 17:06:12 -05:00
Jesse Beder
923ccc8fed Implemented begin/end doc 2012-05-21 16:54:45 -05:00
Jesse Beder
5a2183f55b Removed old emitter state machine 2012-05-21 16:31:07 -05:00
Jesse Beder
41c2ddc03e Switched the emitter state enums to scoped enums 2012-05-21 15:05:17 -05:00
Jesse Beder
39165338e0 Added sandbox to play with 2012-05-20 01:46:08 -05:00
Jesse Beder
d8bdeb5b51 Added failing test for compact map with newline 2012-05-20 01:31:57 -05:00
Jesse Beder
16fd111a6b Fixed formatting for spec tests 2012-05-20 01:19:27 -05:00
Jesse Beder
f17cfacdbb Updated from core 2012-05-19 22:39:36 -05:00
Jesse Beder
030f48583a Fixed tag for implicit map 2012-05-19 22:38:12 -05:00
Jesse Beder
729ac991c7 Added 8.x tests 2012-05-19 22:24:20 -05:00
Jesse Beder
7d57209033 Added 7.x tests 2012-05-19 21:43:22 -05:00
Jesse Beder
4086c285fa Added 6.x tests 2012-05-19 21:08:58 -05:00
Jesse Beder
4245c36a84 Added 5.x tests 2012-05-19 20:40:42 -05:00
Jesse Beder
84b68c3868 Added all the 2.x tests 2012-05-19 18:43:02 -05:00
Jesse Beder
c2b22d6129 Added framework for spectests with event handling 2012-05-19 17:53:43 -05:00
Jesse Beder
58d4fedfc3 Backed out of removing parse 2012-05-19 15:55:13 -05:00
Jesse Beder
55fc800989 Updated from core 2012-05-19 15:54:52 -05:00
Jesse Beder
1f4d8ee3b4 Removed parse 2012-05-19 15:52:43 -05:00
Jesse Beder
e09fbacd35 Updated from core 2012-05-19 15:40:30 -05:00
Jesse Beder
06cb65c6b3 Removed stl node, which was from the old-api but never deleted 2012-05-19 15:37:39 -05:00
Jesse Beder
6c8b369312 Updated CMakeLists from new-api 2012-05-19 15:36:22 -05:00
Jesse Beder
be92547264 Added old parse utility 2012-05-19 15:34:49 -05:00
Jesse Beder
c22512649e Copied all files from new-api branch of old repo 2012-05-19 15:34:02 -05:00
Jesse Beder
c8a539f4f4 Removed old api exceptions 2012-05-19 01:32:10 -05:00
Jesse Beder
683c60f490 Removed traces of old-api Node 2012-05-19 01:19:03 -05:00
Jesse Beder
a183293ff0 Removed old-api tests, added (empty) core spec tests 2012-05-19 01:16:54 -05:00
Jesse Beder
0d32d19ed8 First pass at spearating out a 'core' library from the old api (default) branch 2012-05-19 01:04:43 -05:00
Jesse Beder
fca7b7e190 Fixed reading bad memory error 2012-05-14 23:09:25 -05:00
Jesse Beder
4ca9269e24 Patched signed -> unsigned warning (issue 98) 2012-02-14 10:11:44 -06:00
Jesse Beder
d6a0fc6f01 Fixed warning about binary's shadowing members functions 2012-01-25 17:40:16 -06:00
Jesse Beder
5d6e09d699 Added tag release-0.3.0 for changeset 6d37925fb440 2012-01-21 02:52:18 -06:00
87 changed files with 18481 additions and 4959 deletions

View File

@@ -22,8 +22,8 @@ include(CheckCXXCompilerFlag)
project(YAML_CPP)
set(YAML_CPP_VERSION_MAJOR "0")
set(YAML_CPP_VERSION_MINOR "3")
set(YAML_CPP_VERSION_PATCH "0")
set(YAML_CPP_VERSION_MINOR "5")
set(YAML_CPP_VERSION_PATCH "1")
set(YAML_CPP_VERSION "${YAML_CPP_VERSION_MAJOR}.${YAML_CPP_VERSION_MINOR}.${YAML_CPP_VERSION_PATCH}")
enable_testing()
@@ -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})
###

View File

@@ -1,34 +0,0 @@
#ifndef ALIASMANAGER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define ALIASMANAGER_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 <map>
namespace YAML
{
class Node;
class AliasManager
{
public:
AliasManager();
void RegisterReference(const Node& node);
anchor_t LookupAnchor(const Node& node) const;
private:
anchor_t _CreateNewAnchor();
private:
typedef std::map<const Node*, anchor_t> AnchorByIdentity;
AnchorByIdentity m_anchorByIdentity;
anchor_t m_curAnchor;
};
}
#endif // ALIASMANAGER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -10,15 +10,13 @@
namespace YAML
{
class Node;
std::string EncodeBase64(const unsigned char *data, std::size_t size);
std::vector<unsigned char> DecodeBase64(const std::string& input);
class Binary {
public:
Binary(): m_unownedData(0), m_unownedSize(0) {}
Binary(const unsigned char *data, std::size_t size): m_unownedData(data), m_unownedSize(size) {}
Binary(const unsigned char *data_, std::size_t size_): m_unownedData(data_), m_unownedSize(size_) {}
bool owned() const { return !m_unownedData; }
std::size_t size() const { return owned() ? m_data.size() : m_unownedSize; }
@@ -59,8 +57,6 @@ namespace YAML
const unsigned char *m_unownedData;
std::size_t m_unownedSize;
};
void operator >> (const Node& node, Binary& binary);
}
#endif // BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,75 +0,0 @@
#ifndef CONVERSION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define CONVERSION_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/null.h"
#include "yaml-cpp/traits.h"
#include <limits>
#include <string>
#include <sstream>
namespace YAML
{
// traits for conversion
template<typename T>
struct is_scalar_convertible { enum { value = is_numeric<T>::value }; };
template<> struct is_scalar_convertible<std::string> { enum { value = true }; };
template<> struct is_scalar_convertible<bool> { enum { value = true }; };
template<> struct is_scalar_convertible<_Null> { enum { value = true }; };
// actual conversion
inline bool Convert(const std::string& input, std::string& output) {
output = input;
return true;
}
YAML_CPP_API bool Convert(const std::string& input, bool& output);
YAML_CPP_API bool Convert(const std::string& input, _Null& output);
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";
}
template <typename T>
inline bool Convert(const std::string& input, T& output, typename enable_if<is_numeric<T> >::type * = 0) {
std::stringstream stream(input);
stream.unsetf(std::ios::dec);
if((stream >> output) && (stream >> std::ws).eof())
return true;
if(std::numeric_limits<T>::has_infinity) {
if(IsInfinity(input)) {
output = std::numeric_limits<T>::infinity();
return true;
} else if(IsNegativeInfinity(input)) {
output = -std::numeric_limits<T>::infinity();
return true;
}
}
if(std::numeric_limits<T>::has_quiet_NaN && IsNaN(input)) {
output = std::numeric_limits<T>::quiet_NaN();
return true;
}
return false;
}
}
#endif // CONVERSION_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -8,10 +8,11 @@
#include "yaml-cpp/dll.h"
#include "yaml-cpp/binary.h"
#include "yaml-cpp/emitterdef.h"
#include "yaml-cpp/emittermanip.h"
#include "yaml-cpp/ostream.h"
#include "yaml-cpp/noncopyable.h"
#include "yaml-cpp/null.h"
#include "yaml-cpp/ostream_wrapper.h"
#include <memory>
#include <string>
#include <sstream>
@@ -24,11 +25,12 @@ namespace YAML
{
public:
Emitter();
explicit Emitter(std::ostream& stream);
~Emitter();
// output
const char *c_str() const;
unsigned size() const;
std::size_t size() const;
// state checking
bool good() const;
@@ -60,7 +62,7 @@ namespace YAML
Emitter& Write(const _Anchor& anchor);
Emitter& Write(const _Tag& tag);
Emitter& Write(const _Comment& comment);
Emitter& Write(const _Null& null);
Emitter& Write(const _Null& n);
Emitter& Write(const Binary& binary);
template <typename T>
@@ -70,39 +72,51 @@ namespace YAML
Emitter& WriteStreamable(T value);
private:
void PreWriteIntegralType(std::stringstream& str);
void PreWriteStreamable(std::stringstream& str);
void PostWriteIntegralType(const std::stringstream& str);
void PostWriteStreamable(const std::stringstream& str);
template<typename T> void SetStreamablePrecision(std::stringstream&) {}
unsigned GetFloatPrecision() const;
unsigned GetDoublePrecision() const;
void PrepareIntegralStream(std::stringstream& stream) const;
void StartedScalar();
private:
void PreAtomicWrite();
bool GotoNextPreAtomicState();
void PostAtomicWrite();
void EmitSeparationIfNecessary();
void EmitBeginDoc();
void EmitEndDoc();
void EmitBeginSeq();
void EmitEndSeq();
void EmitBeginMap();
void EmitEndMap();
void EmitKey();
void EmitValue();
void EmitNewline();
void EmitKindTag();
void EmitTag(bool verbatim, const _Tag& tag);
void PrepareNode(EmitterNodeType::value child);
void PrepareTopNode(EmitterNodeType::value child);
void FlowSeqPrepareNode(EmitterNodeType::value child);
void BlockSeqPrepareNode(EmitterNodeType::value child);
void FlowMapPrepareNode(EmitterNodeType::value child);
void FlowMapPrepareLongKey(EmitterNodeType::value child);
void FlowMapPrepareLongKeyValue(EmitterNodeType::value child);
void FlowMapPrepareSimpleKey(EmitterNodeType::value child);
void FlowMapPrepareSimpleKeyValue(EmitterNodeType::value child);
void BlockMapPrepareNode(EmitterNodeType::value child);
void BlockMapPrepareLongKey(EmitterNodeType::value child);
void BlockMapPrepareLongKeyValue(EmitterNodeType::value child);
void BlockMapPrepareSimpleKey(EmitterNodeType::value child);
void BlockMapPrepareSimpleKeyValue(EmitterNodeType::value child);
void SpaceOrIndentTo(bool requireSpace, unsigned indent);
const char *ComputeFullBoolName(bool b) const;
bool CanEmitNewline() const;
private:
ostream m_stream;
std::auto_ptr <EmitterState> m_pState;
std::auto_ptr<EmitterState> m_pState;
ostream_wrapper m_stream;
};
template <typename T>
@@ -111,10 +125,15 @@ namespace YAML
if(!good())
return *this;
std::stringstream str;
PreWriteIntegralType(str);
str << value;
PostWriteIntegralType(str);
PrepareNode(EmitterNodeType::Scalar);
std::stringstream stream;
PrepareIntegralStream(stream);
stream << value;
m_stream << stream.str();
StartedScalar();
return *this;
}
@@ -124,24 +143,28 @@ namespace YAML
if(!good())
return *this;
std::stringstream str;
PreWriteStreamable(str);
SetStreamablePrecision<T>(str);
str << value;
PostWriteStreamable(str);
PrepareNode(EmitterNodeType::Scalar);
std::stringstream stream;
SetStreamablePrecision<T>(stream);
stream << value;
m_stream << stream.str();
StartedScalar();
return *this;
}
template<>
inline void Emitter::SetStreamablePrecision<float>(std::stringstream& str)
inline void Emitter::SetStreamablePrecision<float>(std::stringstream& stream)
{
str.precision(GetFloatPrecision());
stream.precision(GetFloatPrecision());
}
template<>
inline void Emitter::SetStreamablePrecision<double>(std::stringstream& str)
inline void Emitter::SetStreamablePrecision<double>(std::stringstream& stream)
{
str.precision(GetDoublePrecision());
stream.precision(GetDoublePrecision());
}
// overloads of insertion

View File

@@ -0,0 +1,13 @@
#ifndef EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITTERDEF_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 EmitterNodeType { enum value { None, Property, Scalar, FlowSeq, BlockSeq, FlowMap, BlockMap }; };
}
#endif // EMITTERDEF_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -55,9 +55,14 @@ 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";
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";
@@ -66,10 +71,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 EXPECTED_KEY_TOKEN = "expected key token";
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";
const char * const BAD_FILE = "bad file";
template <typename T>
inline const std::string KEY_NOT_FOUND_WITH_KEY(const T&, typename disable_if<is_numeric<T> >::type * = 0) {
@@ -148,17 +150,59 @@ namespace YAML
return TypedKeyNotFound <T> (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<typename T>
class TypedBadConversion: public BadConversion {
public:
TypedBadConversion()
: BadConversion() {}
};
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_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(), 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

View File

@@ -1,40 +0,0 @@
#ifndef ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define 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 <memory>
namespace YAML
{
class Node;
struct IterPriv;
class YAML_CPP_API Iterator
{
public:
Iterator();
Iterator(std::auto_ptr<IterPriv> pData);
Iterator(const Iterator& rhs);
~Iterator();
Iterator& operator = (const Iterator& rhs);
Iterator& operator ++ ();
Iterator operator ++ (int);
const Node& operator * () const;
const Node *operator -> () const;
const Node& first() const;
const Node& second() const;
friend YAML_CPP_API bool operator == (const Iterator& it, const Iterator& jt);
friend YAML_CPP_API bool operator != (const Iterator& it, const Iterator& jt);
private:
std::auto_ptr<IterPriv> m_pData;
};
}
#endif // ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,18 +0,0 @@
#ifndef LTNODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define LTNODE_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
{
class Node;
struct ltnode {
bool operator()(const Node *pNode1, const Node *pNode2) const;
};
}
#endif // LTNODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -13,7 +13,7 @@ namespace YAML
struct YAML_CPP_API Mark {
Mark(): pos(0), line(0), column(0) {}
static const Mark null() { return Mark(-1, -1, -1); }
static const Mark null_mark() { return Mark(-1, -1, -1); }
int pos;
int line, column;

View File

@@ -1,135 +0,0 @@
#ifndef NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define 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/exceptions.h"
#include "yaml-cpp/mark.h"
#include "yaml-cpp/noncopyable.h"
#include "yaml-cpp/conversion.h"
#include "yaml-cpp/iterator.h"
#include "yaml-cpp/ltnode.h"
#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <vector>
namespace YAML
{
class AliasManager;
class Content;
class NodeOwnership;
class Scanner;
class Emitter;
class EventHandler;
struct NodeType { enum value { Null, Scalar, Sequence, Map }; };
class YAML_CPP_API Node: private noncopyable
{
public:
friend class NodeOwnership;
friend class NodeBuilder;
Node();
~Node();
void Clear();
std::auto_ptr<Node> Clone() const;
void EmitEvents(EventHandler& eventHandler) const;
void EmitEvents(AliasManager& am, EventHandler& eventHandler) const;
NodeType::value Type() const { return m_type; }
bool IsAliased() const;
// file location of start of this node
const Mark GetMark() const { return m_mark; }
// accessors
Iterator begin() const;
Iterator end() const;
std::size_t size() const;
// extraction of scalars
bool GetScalar(std::string& s) const;
// we can specialize this for other values
template <typename T>
bool Read(T& value) const;
template <typename T>
const T to() const;
template <typename T>
friend YAML_CPP_API typename enable_if<is_scalar_convertible<T> >::type operator >> (const Node& node, T& value);
// retrieval for maps and sequences
template <typename T>
const Node *FindValue(const T& key) const;
template <typename T>
const Node& operator [] (const T& key) const;
// specific to maps
const Node *FindValue(const char *key) const;
const Node *FindValue(char *key) const;
const Node& operator [] (const char *key) const;
const Node& operator [] (char *key) const;
// for tags
const std::string& Tag() const { return m_tag; }
// emitting
friend YAML_CPP_API Emitter& operator << (Emitter& out, const Node& node);
// ordering
int Compare(const Node& rhs) const;
friend bool operator < (const Node& n1, const Node& n2);
private:
explicit Node(NodeOwnership& owner);
Node& CreateNode();
void Init(NodeType::value type, const Mark& mark, const std::string& tag);
void MarkAsAliased();
void SetScalarData(const std::string& data);
void Append(Node& node);
void Insert(Node& key, Node& value);
// helper for sequences
template <typename, bool> friend struct _FindFromNodeAtIndex;
const Node *FindAtIndex(std::size_t i) const;
// helper for maps
template <typename T>
const Node& GetValue(const T& key) const;
template <typename T>
const Node *FindValueForKey(const T& key) const;
private:
std::auto_ptr<NodeOwnership> m_pOwnership;
Mark m_mark;
std::string m_tag;
typedef std::vector<Node *> node_seq;
typedef std::map<Node *, Node *, ltnode> node_map;
NodeType::value m_type;
std::string m_scalarData;
node_seq m_seqData;
node_map m_mapData;
};
}
#include "yaml-cpp/nodeimpl.h"
#include "yaml-cpp/nodereadimpl.h"
#endif // NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,280 @@
#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 <limits>
#include <list>
#include <map>
#include <sstream>
#include <vector>
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<std::string> {
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<const char *> {
static Node encode(const char *&rhs) {
return Node(rhs);
}
};
template<std::size_t N>
struct convert<const char[N]> {
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<type> {\
static Node encode(const type& rhs) {\
std::stringstream stream;\
stream.precision(std::numeric_limits<type>::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 >> rhs) && (stream >> std::ws).eof())\
return true;\
if(std::numeric_limits<type>::has_infinity) {\
if(conversion::IsInfinity(input)) {\
rhs = std::numeric_limits<type>::infinity();\
return true;\
} else if(conversion::IsNegativeInfinity(input)) {\
rhs = negative_op std::numeric_limits<type>::infinity();\
return true;\
}\
}\
\
if(std::numeric_limits<type>::has_quiet_NaN && conversion::IsNaN(input)) {\
rhs = std::numeric_limits<type>::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);
#undef YAML_DEFINE_CONVERT_STREAMABLE_SIGNED
#undef YAML_DEFINE_CONVERT_STREAMABLE_UNSIGNED
#undef YAML_DEFINE_CONVERT_STREAMABLE
// bool
template<>
struct convert<bool> {
static Node encode(bool rhs) {
return rhs ? Node("true") : Node("false");
}
static bool decode(const Node& node, bool& rhs);
};
// std::map
template<typename K, typename V>
struct convert<std::map<K, V> > {
static Node encode(const std::map<K, V>& rhs) {
Node node(NodeType::Map);
for(typename std::map<K, V>::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<K, V>& 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<K>()] = it->second.template as<V>();
#else
rhs[it->first.as<K>()] = it->second.as<V>();
#endif
return true;
}
};
// std::vector
template<typename T>
struct convert<std::vector<T> > {
static Node encode(const std::vector<T>& rhs) {
Node node(NodeType::Sequence);
for(typename std::vector<T>::const_iterator it=rhs.begin();it!=rhs.end();++it)
node.push_back(*it);
return node;
}
static bool decode(const Node& node, std::vector<T>& 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<T>());
#else
rhs.push_back(it->as<T>());
#endif
return true;
}
};
// std::list
template<typename T>
struct convert<std::list<T> > {
static Node encode(const std::list<T>& rhs) {
Node node(NodeType::Sequence);
for(typename std::list<T>::const_iterator it=rhs.begin();it!=rhs.end();++it)
node.push_back(*it);
return node;
}
static bool decode(const Node& node, std::list<T>& 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<T>());
#else
rhs.push_back(it->as<T>());
#endif
return true;
}
};
// std::pair
template<typename T, typename U>
struct convert<std::pair<T, U> > {
static Node encode(const std::pair<T, U>& 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<T, U>& 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<T>();
#else
rhs.first = node[0].as<T>();
#endif
#if defined(__GNUC__) && __GNUC__ < 4
//workaround for GCC 3:
rhs.second = node[1].template as<U>();
#else
rhs.second = node[1].as<U>();
#endif
return true;
}
};
// binary
template<>
struct convert<Binary> {
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<unsigned char> 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

View File

@@ -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

View File

@@ -0,0 +1,168 @@
#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 <boost/type_traits.hpp>
namespace YAML
{
namespace detail
{
template<typename Key, typename Enable = void>
struct get_idx {
static node *get(const std::vector<node *>& /* sequence */, const Key& /* key */, shared_memory_holder /* pMemory */) {
return 0;
}
};
template<typename Key>
struct get_idx<Key, typename boost::enable_if_c<boost::is_unsigned<Key>::value && !boost::is_same<Key, bool>::value>::type> {
static node *get(const std::vector<node *>& sequence, const Key& key, shared_memory_holder /* pMemory */) {
return key < sequence.size() ? sequence[key] : 0;
}
static node *get(std::vector<node *>& 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<typename Key>
struct get_idx<Key, typename boost::enable_if<boost::is_signed<Key> >::type> {
static node *get(const std::vector<node *>& sequence, const Key& key, shared_memory_holder pMemory) {
return key >= 0 ? get_idx<std::size_t>::get(sequence, static_cast<std::size_t>(key), pMemory) : 0;
}
static node *get(std::vector<node *>& sequence, const Key& key, shared_memory_holder pMemory) {
return key >= 0 ? get_idx<std::size_t>::get(sequence, static_cast<std::size_t>(key), pMemory) : 0;
}
};
// indexing
template<typename Key>
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<Key>::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<typename Key>
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<Key>::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<typename Key>
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<typename Key, typename Value>
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<typename T>
inline bool node_data::equals(node& node, const T& rhs, shared_memory_holder pMemory)
{
T lhs;
if(convert<T>::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<std::string>(node, rhs, pMemory);
}
template<typename T>
inline node& node_data::convert_to_node(const T& rhs, shared_memory_holder pMemory)
{
Node value = convert<T>::encode(rhs);
value.EnsureNodeExists();
pMemory->merge(*value.m_pMemory);
return *value.m_pNode;
}
}
}
#endif // NODE_DETAIL_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -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 <boost/iterator/iterator_adaptor.hpp>
#include <boost/utility.hpp>
namespace YAML
{
namespace detail
{
struct iterator_value;
template<typename V>
class iterator_base: public boost::iterator_adaptor<
iterator_base<V>,
node_iterator,
V,
std::forward_iterator_tag,
V>
{
private:
template<typename> 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<class W>
iterator_base(const iterator_base<W>& rhs, typename boost::enable_if<boost::is_convertible<W*, V*>, 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

View File

@@ -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 <list>
#include <utility>
#include <vector>
namespace YAML
{
class node;
namespace detail {
struct iterator_value;
template<typename V> class iterator_base;
}
typedef detail::iterator_base<detail::iterator_value> iterator;
typedef detail::iterator_base<const detail::iterator_value> const_iterator;
}
#endif // VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -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 <set>
#include <boost/shared_ptr.hpp>
namespace YAML
{
namespace detail
{
class memory {
public:
node& create_node();
void merge(const memory& rhs);
private:
typedef std::set<shared_node> 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<memory> m_pMemory;
};
}
}
#endif // VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,130 @@
#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 <set>
#include <boost/utility.hpp>
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<const node_ref&>(*m_pRef).begin(); }
node_iterator begin() { return m_pRef->begin(); }
const_node_iterator end() const { return static_cast<const node_ref&>(*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<typename Key> node& get(const Key& key, shared_memory_holder pMemory) const { return static_cast<const node_ref&>(*m_pRef).get(key, pMemory); }
template<typename Key> node& get(const Key& key, shared_memory_holder pMemory) {
node& value = m_pRef->get(key, pMemory);
value.add_dependency(*this);
return value;
}
template<typename Key> 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<const node_ref&>(*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<typename Key, typename Value>
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<node *> nodes;
nodes m_dependencies;
};
}
}
#endif // NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,110 @@
#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 <boost/utility.hpp>
#include <list>
#include <utility>
#include <vector>
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<typename Key> node& get(const Key& key, shared_memory_holder pMemory) const;
template<typename Key> node& get(const Key& key, shared_memory_holder pMemory);
template<typename Key> 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<typename Key, typename Value>
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<typename T>
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<typename T>
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 *> node_seq;
node_seq m_sequence;
mutable std::size_t m_seqSize;
// map
typedef std::map<node *, node *> node_map;
node_map m_map;
typedef std::pair<node *, node *> kv_pair;
typedef std::list<kv_pair> kv_pairs;
mutable kv_pairs m_undefinedPairs;
};
}
}
#endif // VALUE_DETAIL_NODE_DATA_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -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 <boost/iterator/iterator_facade.hpp>
#include <boost/utility/enable_if.hpp>
#include <map>
#include <utility>
#include <vector>
namespace YAML
{
namespace detail
{
struct iterator_type { enum value { None, Sequence, Map }; };
template<typename V>
struct node_iterator_value: public std::pair<V*, V*> {
typedef std::pair<V*, V*> 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 *> node_seq;
typedef std::map<node *, node *> node_map;
template<typename V>
struct node_iterator_type {
typedef node_seq::iterator seq;
typedef node_map::iterator map;
};
template<typename V>
struct node_iterator_type<const V> {
typedef node_seq::const_iterator seq;
typedef node_map::const_iterator map;
};
template<typename V>
class node_iterator_base: public boost::iterator_facade<
node_iterator_base<V>,
node_iterator_value<V>,
std::forward_iterator_tag,
node_iterator_value<V> >
{
private:
struct enabler {};
public:
typedef typename node_iterator_type<V>::seq SeqIter;
typedef typename node_iterator_type<V>::map MapIter;
typedef node_iterator_value<V> 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<typename W>
node_iterator_base(const node_iterator_base<W>& rhs, typename boost::enable_if<boost::is_convertible<W*, V*>, 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<typename> friend class node_iterator_base;
template<typename W>
bool equal(const node_iterator_base<W>& 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> node_iterator;
typedef node_iterator_base<const node> const_node_iterator;
}
}
#endif // VALUE_DETAIL_NODE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,69 @@
#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 <boost/utility.hpp>
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<const node_data&>(*m_pData).begin(); }
node_iterator begin() {return m_pData->begin(); }
const_node_iterator end() const { return static_cast<const node_data&>(*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<typename Key> node& get(const Key& key, shared_memory_holder pMemory) const { return static_cast<const node_data&>(*m_pData).get(key, pMemory); }
template<typename Key> node& get(const Key& key, shared_memory_holder pMemory) { return m_pData->get(key, pMemory); }
template<typename Key> 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<const node_data&>(*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<typename Key, typename Value>
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

View File

@@ -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 <string>
#include <iosfwd>
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

View File

@@ -0,0 +1,451 @@
#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 <string>
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<typename T>
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<typename T, typename S>
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<T>::decode(node, t))
return t;
return fallback;
}
};
template<typename S>
struct as_if<std::string, S> {
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<typename T>
struct as_if<T, void> {
explicit as_if(const Node& node_): node(node_) {}
const Node& node;
const T operator()() const {
if(!node.m_pNode)
throw TypedBadConversion<T>();
T t;
if(convert<T>::decode(node, t))
return t;
throw TypedBadConversion<T>();
}
};
template<>
struct as_if<std::string, void> {
explicit as_if(const Node& node_): node(node_) {}
const Node& node;
const std::string operator()() const {
if(node.Type() != NodeType::Scalar)
throw TypedBadConversion<std::string>();
return node.Scalar();
}
};
// access functions
template<typename T>
inline const 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
{
if(!m_isValid)
throw InvalidNode();
return as_if<T, S>(*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<typename T>
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<typename T>
inline void Node::Assign(const T& rhs)
{
if(!m_isValid)
throw InvalidNode();
AssignData(convert<T>::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<typename T>
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<typename T>
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<const char*> {
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<char*> {
explicit to_value_t(char *t_): t(t_) {}
const char *t;
typedef std::string return_type;
const std::string operator()() const { return t; }
};
template<std::size_t N>
struct to_value_t<char [N]> {
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<typename T>
inline typename to_value_t<T>::return_type to_value(const T& t) {
return to_value_t<T>(t)();
}
}
// indexing
template<typename Key>
inline const Node Node::operator[](const Key& key) const
{
if(!m_isValid)
throw InvalidNode();
EnsureNodeExists();
detail::node& value = static_cast<const detail::node&>(*m_pNode).get(detail::to_value(key), m_pMemory);
return Node(value, m_pMemory);
}
template<typename Key>
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<typename Key>
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<const detail::node&>(*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<typename Key, typename Value>
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

View File

@@ -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 <list>
#include <utility>
#include <vector>
namespace YAML
{
namespace detail {
struct iterator_value: public Node, std::pair<Node, Node> {
iterator_value() {}
explicit iterator_value(const Node& rhs): Node(rhs), std::pair<Node, Node>(Node(Node::ZombieNode), Node(Node::ZombieNode)) {}
explicit iterator_value(const Node& key, const Node& value): Node(Node::ZombieNode), std::pair<Node, Node>(key, value) {}
};
}
}
#endif // VALUE_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,116 @@
#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 <stdexcept>
namespace YAML
{
class Node
{
public:
friend class NodeBuilder;
friend class NodeEvents;
friend struct detail::iterator_value;
friend class detail::node_data;
template<typename> friend class detail::iterator_base;
template<typename T, typename S> friend struct as_if;
typedef YAML::iterator iterator;
typedef YAML::const_iterator const_iterator;
Node();
explicit Node(NodeType::value type);
template<typename T> 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<typename T> const T as() const;
template<typename T, typename S> 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<typename T> 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<typename T> void push_back(const T& rhs);
void push_back(const Node& rhs);
// indexing
template<typename Key> const Node operator[](const Key& key) const;
template<typename Key> Node operator[](const Key& key);
template<typename Key> bool remove(const Key& key);
const Node operator[](const Node& key) const;
Node operator[](const Node& key);
bool remove(const Node& key);
// map
template<typename Key, typename Value>
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<typename T> 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<typename T>
struct convert;
}
#endif // NODE_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -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 <iosfwd>
#include <string>
#include <vector>
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<Node> LoadAll(const std::string& input);
std::vector<Node> LoadAll(const char *input);
std::vector<Node> LoadAll(std::istream& input);
std::vector<Node> LoadAllFromFile(const std::string& filename);
}
#endif // VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -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 <boost/shared_ptr.hpp>
namespace YAML
{
namespace detail {
class node;
class node_ref;
class node_data;
class memory;
class memory_holder;
typedef boost::shared_ptr<node> shared_node;
typedef boost::shared_ptr<node_ref> shared_node_ref;
typedef boost::shared_ptr<node_data> shared_node_data;
typedef boost::shared_ptr<memory_holder> shared_memory_holder;
typedef boost::shared_ptr<memory> shared_memory;
}
}
#endif // VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -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

View File

@@ -1,85 +0,0 @@
#ifndef NODEIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODEIMPL_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/nodeutil.h"
#include <cassert>
namespace YAML
{
// implementation of templated things
template <typename T>
inline const T Node::to() const {
T value;
*this >> value;
return value;
}
template <typename T>
inline typename enable_if<is_scalar_convertible<T> >::type operator >> (const Node& node, T& value) {
if(!ConvertScalar(node, value))
throw InvalidScalar(node.m_mark);
}
template <typename T>
inline const Node *Node::FindValue(const T& key) const {
switch(m_type) {
case NodeType::Null:
case NodeType::Scalar:
throw BadDereference();
case NodeType::Sequence:
return FindFromNodeAtIndex(*this, key);
case NodeType::Map:
return FindValueForKey(key);
}
assert(false);
throw BadDereference();
}
template <typename T>
inline const Node *Node::FindValueForKey(const T& key) const {
for(Iterator it=begin();it!=end();++it) {
T t;
if(it.first().Read(t)) {
if(key == t)
return &it.second();
}
}
return 0;
}
template <typename T>
inline const Node& Node::GetValue(const T& key) const {
if(const Node *pValue = FindValue(key))
return *pValue;
throw MakeTypedKeyNotFound(m_mark, key);
}
template <typename T>
inline const Node& Node::operator [] (const T& key) const {
return GetValue(key);
}
inline const Node *Node::FindValue(const char *key) const {
return FindValue(std::string(key));
}
inline const Node *Node::FindValue(char *key) const {
return FindValue(std::string(key));
}
inline const Node& Node::operator [] (const char *key) const {
return GetValue(std::string(key));
}
inline const Node& Node::operator [] (char *key) const {
return GetValue(std::string(key));
}
}
#endif // NODEIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,86 +0,0 @@
#ifndef NODEREADIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODEREADIMPL_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
{
// implementation for Node::Read
// (the goal is to call ConvertScalar if we can, and fall back to operator >> if not)
// thanks to litb from stackoverflow.com
// http://stackoverflow.com/questions/1386183/how-to-call-a-templated-function-if-it-exists-and-something-else-otherwise/1386390#1386390
// Note: this doesn't work on gcc 3.2, but does on gcc 3.4 and above. I'm not sure about 3.3.
#if __GNUC__ && (__GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ <= 3))
// trick doesn't work? Just fall back to ConvertScalar.
// This means that we can't use any user-defined types as keys in a map
template <typename T>
inline bool Node::Read(T& value) const {
return ConvertScalar(*this, value);
}
#else
// usual case: the trick!
template<bool>
struct read_impl;
// ConvertScalar available
template<>
struct read_impl<true> {
template<typename T>
static bool read(const Node& node, T& value) {
return ConvertScalar(node, value);
}
};
// ConvertScalar not available
template<>
struct read_impl<false> {
template<typename T>
static bool read(const Node& node, T& value) {
try {
node >> value;
} catch(const Exception&) {
return false;
}
return true;
}
};
namespace fallback {
// sizeof > 1
struct flag { char c[2]; };
flag Convert(...);
int operator,(flag, flag);
template<typename T>
char operator,(flag, T const&);
char operator,(int, flag);
int operator,(char, flag);
}
template <typename T>
inline bool Node::Read(T& value) const {
using namespace fallback;
return read_impl<sizeof (fallback::flag(), Convert(std::string(), value), fallback::flag()) != 1>::read(*this, value);
}
#endif // done with trick
// the main conversion function
template <typename T>
inline bool ConvertScalar(const Node& node, T& value) {
std::string scalar;
if(!node.GetScalar(scalar))
return false;
return Convert(scalar, value);
}
}
#endif // NODEREADIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,62 +0,0 @@
#ifndef NODEUTIL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODEUTIL_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
{
template <typename T, typename U>
struct is_same_type {
enum { value = false };
};
template <typename T>
struct is_same_type<T, T> {
enum { value = true };
};
template <typename T, bool check>
struct is_index_type_with_check {
enum { value = false };
};
template <> struct is_index_type_with_check<std::size_t, false> { enum { value = true }; };
#define MAKE_INDEX_TYPE(Type) \
template <> struct is_index_type_with_check<Type, is_same_type<Type, std::size_t>::value> { enum { value = true }; }
MAKE_INDEX_TYPE(int);
MAKE_INDEX_TYPE(unsigned);
MAKE_INDEX_TYPE(short);
MAKE_INDEX_TYPE(unsigned short);
MAKE_INDEX_TYPE(long);
MAKE_INDEX_TYPE(unsigned long);
#undef MAKE_INDEX_TYPE
template <typename T>
struct is_index_type: public is_index_type_with_check<T, false> {};
// messing around with template stuff to get the right overload for operator [] for a sequence
template <typename T, bool b>
struct _FindFromNodeAtIndex {
const Node *pRet;
_FindFromNodeAtIndex(const Node&, const T&): pRet(0) {}
};
template <typename T>
struct _FindFromNodeAtIndex<T, true> {
const Node *pRet;
_FindFromNodeAtIndex(const Node& node, const T& key): pRet(node.FindAtIndex(static_cast<std::size_t>(key))) {}
};
template <typename T>
inline const Node *FindFromNodeAtIndex(const Node& node, const T& key) {
return _FindFromNodeAtIndex<T, is_index_type<T>::value>(node, key).pRet;
}
}
#endif // NODEUTIL_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,40 +0,0 @@
#ifndef OSTREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define OSTREAM_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 <string>
namespace YAML
{
class ostream
{
public:
ostream();
~ostream();
void reserve(unsigned size);
void put(char ch);
const char *str() const { return m_buffer; }
unsigned row() const { return m_row; }
unsigned col() const { return m_col; }
unsigned pos() const { return m_pos; }
private:
char *m_buffer;
unsigned m_pos;
unsigned m_size;
unsigned m_row, m_col;
};
ostream& operator << (ostream& out, const char *str);
ostream& operator << (ostream& out, const std::string& str);
ostream& operator << (ostream& out, char ch);
}
#endif // OSTREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -0,0 +1,69 @@
#ifndef OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define OSTREAM_WRAPPER_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 <string>
#include <vector>
namespace YAML
{
class ostream_wrapper
{
public:
ostream_wrapper();
explicit ostream_wrapper(std::ostream& stream);
~ostream_wrapper();
void write(const std::string& str);
void write(const char *str, std::size_t size);
void set_comment() { m_comment = true; }
const char *str() const {
if(m_pStream) {
return 0;
} else {
m_buffer[m_pos] = '\0';
return &m_buffer[0];
}
}
std::size_t row() const { return m_row; }
std::size_t col() const { return m_col; }
std::size_t pos() const { return m_pos; }
bool comment() const { return m_comment; }
private:
void update_pos(char ch);
private:
mutable std::vector<char> m_buffer;
std::ostream *m_pStream;
std::size_t m_pos;
std::size_t m_row, m_col;
bool m_comment;
};
template<std::size_t N>
inline ostream_wrapper& operator << (ostream_wrapper& stream, const char (&str)[N]) {
stream.write(str, N-1);
return stream;
}
inline ostream_wrapper& operator << (ostream_wrapper& stream, const std::string& str) {
stream.write(str);
return stream;
}
inline ostream_wrapper& operator << (ostream_wrapper& stream, char ch) {
stream.write(&ch, 1);
return stream;
}
}
#endif // OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -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
@@ -31,9 +29,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:

View File

@@ -1,38 +0,0 @@
#ifndef STLNODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define STLNODE_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 <vector>
#include <map>
namespace YAML
{
template <typename T>
void operator >> (const Node& node, std::vector<T>& v)
{
v.clear();
v.resize(node.size());
for(unsigned i=0;i<node.size();++i)
node[i] >> v[i];
}
template <typename K, typename V>
void operator >> (const Node& node, std::map<K, V>& m)
{
m.clear();
for(Iterator it=node.begin();it!=node.end();++it) {
K k;
V v;
it.first() >> k;
it.second() >> v;
m[k] = v;
}
}
}
#endif // STLNODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -10,8 +10,12 @@
#include "yaml-cpp/stlemitter.h"
#include "yaml-cpp/exceptions.h"
#include "yaml-cpp/node.h"
#include "yaml-cpp/stlnode.h"
#include "yaml-cpp/iterator.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

View File

@@ -1,29 +0,0 @@
#include "yaml-cpp/aliasmanager.h"
#include "yaml-cpp/node.h"
#include <cassert>
#include <sstream>
namespace YAML
{
AliasManager::AliasManager(): m_curAnchor(0)
{
}
void AliasManager::RegisterReference(const Node& node)
{
m_anchorByIdentity.insert(std::make_pair(&node, _CreateNewAnchor()));
}
anchor_t AliasManager::LookupAnchor(const Node& node) const
{
AnchorByIdentity::const_iterator it = m_anchorByIdentity.find(&node);
if(it == m_anchorByIdentity.end())
return 0;
return it->second;
}
anchor_t AliasManager::_CreateNewAnchor()
{
return ++m_curAnchor;
}
}

View File

@@ -1,5 +1,4 @@
#include "yaml-cpp/binary.h"
#include "yaml-cpp/node.h"
namespace YAML
{
@@ -91,12 +90,4 @@ namespace YAML
ret.resize(out - &ret[0]);
return ret;
}
void operator >> (const Node& node, Binary& binary)
{
std::string scalar;
node.GetScalar(scalar);
std::vector<unsigned char> data = DecodeBase64(scalar);
binary.swap(data);
}
}

View File

@@ -1,33 +1,31 @@
#include "yaml-cpp/conversion.h"
#include "yaml-cpp/node/convert.h"
#include "yaml-cpp/node/impl.h"
#include <algorithm>
////////////////////////////////////////////////////////////////
// Specializations for converting a string to specific types
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 <typename T>
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
@@ -37,10 +35,10 @@ namespace
{
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));
@@ -49,8 +47,10 @@ namespace
namespace YAML
{
bool Convert(const std::string& input, bool& b)
{
bool convert<bool>::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)
@@ -62,28 +62,22 @@ namespace YAML
{ "true", "false" },
{ "on", "off" },
};
if(!IsFlexibleCase(input))
if(!IsFlexibleCase(node.Scalar()))
return false;
for(unsigned i=0;i<sizeof(names)/sizeof(names[0]);i++) {
if(names[i].truename == tolower(input)) {
b = true;
if(names[i].truename == tolower(node.Scalar())) {
rhs = true;
return true;
}
if(names[i].falsename == tolower(input)) {
b = false;
if(names[i].falsename == tolower(node.Scalar())) {
rhs = false;
return true;
}
}
return false;
}
bool Convert(const std::string& input, _Null& /*output*/)
{
return input.empty() || input == "~" || input == "null" || input == "Null" || input == "NULL";
}
}

29
src/emit.cpp Normal file
View File

@@ -0,0 +1,29 @@
#include "yaml-cpp/node/emit.h"
#include "yaml-cpp/emitfromevents.h"
#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();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -4,11 +4,8 @@
namespace YAML
{
EmitterState::EmitterState(): m_isGood(true), m_curIndent(0), m_requiresSoftSeparation(false), m_requiresHardSeparation(false)
EmitterState::EmitterState(): m_isGood(true), m_curIndent(0), m_hasAnchor(false), m_hasTag(false), m_hasNonContent(false), m_docCount(0)
{
// start up
m_stateStack.push(ES_WAITING_FOR_DOC);
// set default global manipulators
m_charset.set(EmitNonAscii);
m_strFmt.set(Auto);
@@ -22,8 +19,8 @@ namespace YAML
m_seqFmt.set(Block);
m_mapFmt.set(Block);
m_mapKeyFmt.set(Auto);
m_floatPrecision.set(6);
m_doublePrecision.set(15);
m_floatPrecision.set(std::numeric_limits<float>::digits10 + 1);
m_doublePrecision.set(std::numeric_limits<double>::digits10 + 1);
}
EmitterState::~EmitterState()
@@ -35,21 +32,111 @@ namespace YAML
// . Only the ones that make sense will be accepted
void EmitterState::SetLocalValue(EMITTER_MANIP value)
{
SetOutputCharset(value, LOCAL);
SetStringFormat(value, LOCAL);
SetBoolFormat(value, LOCAL);
SetBoolCaseFormat(value, LOCAL);
SetBoolLengthFormat(value, LOCAL);
SetIntFormat(value, LOCAL);
SetFlowType(GT_SEQ, value, LOCAL);
SetFlowType(GT_MAP, value, LOCAL);
SetMapKeyFormat(value, LOCAL);
SetOutputCharset(value, FmtScope::Local);
SetStringFormat(value, FmtScope::Local);
SetBoolFormat(value, FmtScope::Local);
SetBoolCaseFormat(value, FmtScope::Local);
SetBoolLengthFormat(value, FmtScope::Local);
SetIntFormat(value, FmtScope::Local);
SetFlowType(GroupType::Seq, value, FmtScope::Local);
SetFlowType(GroupType::Map, value, FmtScope::Local);
SetMapKeyFormat(value, FmtScope::Local);
}
void EmitterState::BeginGroup(GROUP_TYPE type)
void EmitterState::SetAnchor()
{
m_hasAnchor = true;
}
void EmitterState::SetTag()
{
m_hasTag = true;
}
void EmitterState::SetNonContent()
{
m_hasNonContent = true;
}
void EmitterState::SetLongKey()
{
assert(!m_groups.empty());
if(m_groups.empty())
return;
assert(m_groups.top().type == GroupType::Map);
m_groups.top().longKey = true;
}
void EmitterState::ForceFlow()
{
assert(!m_groups.empty());
if(m_groups.empty())
return;
m_groups.top().flowType = FlowType::Flow;
}
void EmitterState::StartedNode()
{
if(m_groups.empty()) {
m_docCount++;
} else {
m_groups.top().childCount++;
if(m_groups.top().childCount % 2 == 0)
m_groups.top().longKey = false;
}
m_hasAnchor = false;
m_hasTag = false;
m_hasNonContent = false;
}
EmitterNodeType::value EmitterState::NextGroupType(GroupType::value type) const
{
if(type == GroupType::Seq) {
if(GetFlowType(type) == Block)
return EmitterNodeType::BlockSeq;
else
return EmitterNodeType::FlowSeq;
} else {
if(GetFlowType(type) == Block)
return EmitterNodeType::BlockMap;
else
return EmitterNodeType::FlowMap;
}
// can't happen
assert(false);
return EmitterNodeType::None;
}
void EmitterState::StartedDoc()
{
m_hasAnchor = false;
m_hasTag = false;
m_hasNonContent = false;
}
void EmitterState::EndedDoc()
{
m_hasAnchor = false;
m_hasTag = false;
m_hasNonContent = false;
}
void EmitterState::StartedScalar()
{
StartedNode();
ClearModifiedSettings();
}
void EmitterState::StartedGroup(GroupType::value type)
{
unsigned lastIndent = (m_groups.empty() ? 0 : m_groups.top().indent);
m_curIndent += lastIndent;
StartedNode();
const int lastGroupIndent = (m_groups.empty() ? 0 : m_groups.top().indent);
m_curIndent += lastGroupIndent;
std::auto_ptr<Group> pGroup(new Group(type));
@@ -57,17 +144,23 @@ namespace YAML
pGroup->modifiedSettings = m_modifiedSettings;
// set up group
pGroup->flow = GetFlowType(type);
if(GetFlowType(type) == Block)
pGroup->flowType = FlowType::Block;
else
pGroup->flowType = FlowType::Flow;
pGroup->indent = GetIndent();
pGroup->usingLongKey = (GetMapKeyFormat() == LongKey ? true : false);
m_groups.push(pGroup);
}
void EmitterState::EndGroup(GROUP_TYPE type)
void EmitterState::EndedGroup(GroupType::value type)
{
if(m_groups.empty())
return SetError(ErrorMsg::UNMATCHED_GROUP_TAG);
if(m_groups.empty()) {
if(type == GroupType::Seq)
return SetError(ErrorMsg::UNEXPECTED_END_SEQ);
else
return SetError(ErrorMsg::UNEXPECTED_END_MAP);
}
// get rid of the current group
{
@@ -84,49 +177,57 @@ namespace YAML
// some global settings that we changed may have been overridden
// by a local setting we just popped, so we need to restore them
m_globalModifiedSettings.restore();
ClearModifiedSettings();
}
GROUP_TYPE EmitterState::GetCurGroupType() const
EmitterNodeType::value EmitterState::CurGroupNodeType() const
{
if(m_groups.empty())
return EmitterNodeType::None;
return m_groups.top().NodeType();
}
GroupType::value EmitterState::CurGroupType() const
{
if(m_groups.empty())
return GT_NONE;
return m_groups.top().type;
return m_groups.empty() ? GroupType::None : m_groups.top().type;
}
FLOW_TYPE EmitterState::GetCurGroupFlowType() const
FlowType::value EmitterState::CurGroupFlowType() const
{
if(m_groups.empty())
return FT_NONE;
return (m_groups.top().flow == Flow ? FT_FLOW : FT_BLOCK);
}
bool EmitterState::CurrentlyInLongKey()
{
if(m_groups.empty())
return false;
return m_groups.top().usingLongKey;
}
void EmitterState::StartLongKey()
{
if(!m_groups.empty())
m_groups.top().usingLongKey = true;
}
void EmitterState::StartSimpleKey()
{
if(!m_groups.empty())
m_groups.top().usingLongKey = false;
return m_groups.empty() ? FlowType::None : m_groups.top().flowType;
}
int EmitterState::CurGroupIndent() const
{
return m_groups.empty() ? 0 : m_groups.top().indent;
}
std::size_t EmitterState::CurGroupChildCount() const
{
return m_groups.empty() ? m_docCount : m_groups.top().childCount;
}
bool EmitterState::CurGroupLongKey() const
{
return m_groups.empty() ? false : m_groups.top().longKey;
}
int EmitterState::LastIndent() const
{
if(m_groups.size() <= 1)
return 0;
return m_curIndent - m_groups.top(-1).indent;
}
void EmitterState::ClearModifiedSettings()
{
m_modifiedSettings.clear();
}
bool EmitterState::SetOutputCharset(EMITTER_MANIP value, FMT_SCOPE scope)
bool EmitterState::SetOutputCharset(EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case EmitNonAscii:
@@ -138,7 +239,7 @@ namespace YAML
}
}
bool EmitterState::SetStringFormat(EMITTER_MANIP value, FMT_SCOPE scope)
bool EmitterState::SetStringFormat(EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case Auto:
@@ -152,7 +253,7 @@ namespace YAML
}
}
bool EmitterState::SetBoolFormat(EMITTER_MANIP value, FMT_SCOPE scope)
bool EmitterState::SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case OnOffBool:
@@ -165,7 +266,7 @@ namespace YAML
}
}
bool EmitterState::SetBoolLengthFormat(EMITTER_MANIP value, FMT_SCOPE scope)
bool EmitterState::SetBoolLengthFormat(EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case LongBool:
@@ -177,7 +278,7 @@ namespace YAML
}
}
bool EmitterState::SetBoolCaseFormat(EMITTER_MANIP value, FMT_SCOPE scope)
bool EmitterState::SetBoolCaseFormat(EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case UpperCase:
@@ -190,7 +291,7 @@ namespace YAML
}
}
bool EmitterState::SetIntFormat(EMITTER_MANIP value, FMT_SCOPE scope)
bool EmitterState::SetIntFormat(EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case Dec:
@@ -203,16 +304,16 @@ namespace YAML
}
}
bool EmitterState::SetIndent(unsigned value, FMT_SCOPE scope)
bool EmitterState::SetIndent(unsigned value, FmtScope::value scope)
{
if(value == 0)
if(value <= 1)
return false;
_Set(m_indent, value, scope);
return true;
}
bool EmitterState::SetPreCommentIndent(unsigned value, FMT_SCOPE scope)
bool EmitterState::SetPreCommentIndent(unsigned value, FmtScope::value scope)
{
if(value == 0)
return false;
@@ -221,7 +322,7 @@ namespace YAML
return true;
}
bool EmitterState::SetPostCommentIndent(unsigned value, FMT_SCOPE scope)
bool EmitterState::SetPostCommentIndent(unsigned value, FmtScope::value scope)
{
if(value == 0)
return false;
@@ -230,30 +331,29 @@ namespace YAML
return true;
}
bool EmitterState::SetFlowType(GROUP_TYPE groupType, EMITTER_MANIP value, FMT_SCOPE scope)
bool EmitterState::SetFlowType(GroupType::value groupType, EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case Block:
case Flow:
_Set(groupType == GT_SEQ ? m_seqFmt : m_mapFmt, value, scope);
_Set(groupType == GroupType::Seq ? m_seqFmt : m_mapFmt, value, scope);
return true;
default:
return false;
}
}
EMITTER_MANIP EmitterState::GetFlowType(GROUP_TYPE groupType) const
EMITTER_MANIP EmitterState::GetFlowType(GroupType::value groupType) const
{
// force flow style if we're currently in a flow
FLOW_TYPE flowType = GetCurGroupFlowType();
if(flowType == FT_FLOW)
if(CurGroupFlowType() == FlowType::Flow)
return Flow;
// otherwise, go with what's asked of use
return (groupType == GT_SEQ ? m_seqFmt.get() : m_mapFmt.get());
// otherwise, go with what's asked of us
return (groupType == GroupType::Seq ? m_seqFmt.get() : m_mapFmt.get());
}
bool EmitterState::SetMapKeyFormat(EMITTER_MANIP value, FMT_SCOPE scope)
bool EmitterState::SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope)
{
switch(value) {
case Auto:
@@ -265,17 +365,17 @@ namespace YAML
}
}
bool EmitterState::SetFloatPrecision(int value, FMT_SCOPE scope)
bool EmitterState::SetFloatPrecision(int value, FmtScope::value scope)
{
if(value < 0 || value > std::numeric_limits<float>::digits10)
if(value < 0 || value > std::numeric_limits<float>::digits10 + 1)
return false;
_Set(m_floatPrecision, value, scope);
return true;
}
bool EmitterState::SetDoublePrecision(int value, FMT_SCOPE scope)
bool EmitterState::SetDoublePrecision(int value, FmtScope::value scope)
{
if(value < 0 || value > std::numeric_limits<double>::digits10)
if(value < 0 || value > std::numeric_limits<double>::digits10 + 1)
return false;
_Set(m_doublePrecision, value, scope);
return true;

View File

@@ -8,71 +8,20 @@
#include "ptr_stack.h"
#include "setting.h"
#include "yaml-cpp/emitterdef.h"
#include "yaml-cpp/emittermanip.h"
#include <cassert>
#include <vector>
#include <stack>
#include <memory>
#include <stdexcept>
namespace YAML
{
enum FMT_SCOPE {
LOCAL,
GLOBAL
};
enum GROUP_TYPE {
GT_NONE,
GT_SEQ,
GT_MAP
};
enum FLOW_TYPE {
FT_NONE,
FT_FLOW,
FT_BLOCK
};
enum NODE_STATE {
NS_START,
NS_READY_FOR_ATOM,
NS_END
};
enum EMITTER_STATE {
ES_WAITING_FOR_DOC,
ES_WRITING_DOC,
ES_DONE_WITH_DOC,
// block seq
ES_WAITING_FOR_BLOCK_SEQ_ENTRY,
ES_WRITING_BLOCK_SEQ_ENTRY,
ES_DONE_WITH_BLOCK_SEQ_ENTRY,
// flow seq
ES_WAITING_FOR_FLOW_SEQ_ENTRY,
ES_WRITING_FLOW_SEQ_ENTRY,
ES_DONE_WITH_FLOW_SEQ_ENTRY,
// block map
ES_WAITING_FOR_BLOCK_MAP_ENTRY,
ES_WAITING_FOR_BLOCK_MAP_KEY,
ES_WRITING_BLOCK_MAP_KEY,
ES_DONE_WITH_BLOCK_MAP_KEY,
ES_WAITING_FOR_BLOCK_MAP_VALUE,
ES_WRITING_BLOCK_MAP_VALUE,
ES_DONE_WITH_BLOCK_MAP_VALUE,
// flow map
ES_WAITING_FOR_FLOW_MAP_ENTRY,
ES_WAITING_FOR_FLOW_MAP_KEY,
ES_WRITING_FLOW_MAP_KEY,
ES_DONE_WITH_FLOW_MAP_KEY,
ES_WAITING_FOR_FLOW_MAP_VALUE,
ES_WRITING_FLOW_MAP_VALUE,
ES_DONE_WITH_FLOW_MAP_VALUE
};
struct FmtScope { enum value { Local, Global }; };
struct GroupType { enum value { None, Seq, Map }; };
struct FlowType { enum value { None, Flow, Block }; };
class EmitterState
{
public:
@@ -84,76 +33,81 @@ namespace YAML
const std::string GetLastError() const { return m_lastError; }
void SetError(const std::string& error) { m_isGood = false; m_lastError = error; }
// main state of the machine
EMITTER_STATE GetCurState() const { return m_stateStack.top(); }
void SwitchState(EMITTER_STATE state) { PopState(); PushState(state); }
void PushState(EMITTER_STATE state) { m_stateStack.push(state); }
void PopState() { m_stateStack.pop(); }
void SetLocalValue(EMITTER_MANIP value);
// group handling
void BeginGroup(GROUP_TYPE type);
void EndGroup(GROUP_TYPE type);
GROUP_TYPE GetCurGroupType() const;
FLOW_TYPE GetCurGroupFlowType() const;
int GetCurIndent() const { return m_curIndent; }
bool CurrentlyInLongKey();
void StartLongKey();
void StartSimpleKey();
// node handling
void SetAnchor();
void SetTag();
void SetNonContent();
void SetLongKey();
void ForceFlow();
void StartedDoc();
void EndedDoc();
void StartedScalar();
void StartedGroup(GroupType::value type);
void EndedGroup(GroupType::value type);
bool RequiresSoftSeparation() const { return m_requiresSoftSeparation; }
bool RequiresHardSeparation() const { return m_requiresHardSeparation; }
void RequireSoftSeparation() { m_requiresSoftSeparation = true; }
void RequireHardSeparation() { m_requiresSoftSeparation = true; m_requiresHardSeparation = true; }
void ForceHardSeparation() { m_requiresSoftSeparation = false; }
void UnsetSeparation() { m_requiresSoftSeparation = false; m_requiresHardSeparation = false; }
EmitterNodeType::value NextGroupType(GroupType::value type) const;
EmitterNodeType::value CurGroupNodeType() const;
GroupType::value CurGroupType() const;
FlowType::value CurGroupFlowType() const;
int CurGroupIndent() const;
std::size_t CurGroupChildCount() const;
bool CurGroupLongKey() const;
int LastIndent() const;
int CurIndent() const { return m_curIndent; }
bool HasAnchor() const { return m_hasAnchor; }
bool HasTag() const { return m_hasTag; }
bool HasBegunNode() const { return m_hasAnchor || m_hasTag || m_hasNonContent; }
bool HasBegunContent() const { return m_hasAnchor || m_hasTag; }
void ClearModifiedSettings();
// formatters
bool SetOutputCharset(EMITTER_MANIP value, FMT_SCOPE scope);
void SetLocalValue(EMITTER_MANIP value);
bool SetOutputCharset(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetOutputCharset() const { return m_charset.get(); }
bool SetStringFormat(EMITTER_MANIP value, FMT_SCOPE scope);
bool SetStringFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetStringFormat() const { return m_strFmt.get(); }
bool SetBoolFormat(EMITTER_MANIP value, FMT_SCOPE scope);
bool SetBoolFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetBoolFormat() const { return m_boolFmt.get(); }
bool SetBoolLengthFormat(EMITTER_MANIP value, FMT_SCOPE scope);
bool SetBoolLengthFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetBoolLengthFormat() const { return m_boolLengthFmt.get(); }
bool SetBoolCaseFormat(EMITTER_MANIP value, FMT_SCOPE scope);
bool SetBoolCaseFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetBoolCaseFormat() const { return m_boolCaseFmt.get(); }
bool SetIntFormat(EMITTER_MANIP value, FMT_SCOPE scope);
bool SetIntFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetIntFormat() const { return m_intFmt.get(); }
bool SetIndent(unsigned value, FMT_SCOPE scope);
bool SetIndent(unsigned value, FmtScope::value scope);
int GetIndent() const { return m_indent.get(); }
bool SetPreCommentIndent(unsigned value, FMT_SCOPE scope);
bool SetPreCommentIndent(unsigned value, FmtScope::value scope);
int GetPreCommentIndent() const { return m_preCommentIndent.get(); }
bool SetPostCommentIndent(unsigned value, FMT_SCOPE scope);
bool SetPostCommentIndent(unsigned value, FmtScope::value scope);
int GetPostCommentIndent() const { return m_postCommentIndent.get(); }
bool SetFlowType(GROUP_TYPE groupType, EMITTER_MANIP value, FMT_SCOPE scope);
EMITTER_MANIP GetFlowType(GROUP_TYPE groupType) const;
bool SetFlowType(GroupType::value groupType, EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetFlowType(GroupType::value groupType) const;
bool SetMapKeyFormat(EMITTER_MANIP value, FMT_SCOPE scope);
bool SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetMapKeyFormat() const { return m_mapKeyFmt.get(); }
bool SetFloatPrecision(int value, FMT_SCOPE scope);
bool SetFloatPrecision(int value, FmtScope::value scope);
unsigned GetFloatPrecision() const { return m_floatPrecision.get(); }
bool SetDoublePrecision(int value, FMT_SCOPE scope);
bool SetDoublePrecision(int value, FmtScope::value scope);
unsigned GetDoublePrecision() const { return m_doublePrecision.get(); }
private:
template <typename T>
void _Set(Setting<T>& fmt, T value, FMT_SCOPE scope);
void _Set(Setting<T>& fmt, T value, FmtScope::value scope);
void StartedNode();
private:
// basic state ok?
@@ -161,8 +115,6 @@ namespace YAML
std::string m_lastError;
// other state
std::stack<EMITTER_STATE> m_stateStack;
Setting<EMITTER_MANIP> m_charset;
Setting<EMITTER_MANIP> m_strFmt;
Setting<EMITTER_MANIP> m_boolFmt;
@@ -181,29 +133,50 @@ namespace YAML
SettingChanges m_globalModifiedSettings;
struct Group {
Group(GROUP_TYPE type_): type(type_), usingLongKey(false), indent(0) {}
explicit Group(GroupType::value type_): type(type_), indent(0), childCount(0), longKey(false) {}
GROUP_TYPE type;
EMITTER_MANIP flow;
bool usingLongKey;
GroupType::value type;
FlowType::value flowType;
int indent;
std::size_t childCount;
bool longKey;
SettingChanges modifiedSettings;
EmitterNodeType::value NodeType() const {
if(type == GroupType::Seq) {
if(flowType == FlowType::Flow)
return EmitterNodeType::FlowSeq;
else
return EmitterNodeType::BlockSeq;
} else {
if(flowType == FlowType::Flow)
return EmitterNodeType::FlowMap;
else
return EmitterNodeType::BlockMap;
}
// can't get here
assert(false);
return EmitterNodeType::None;
}
};
ptr_stack<Group> m_groups;
unsigned m_curIndent;
bool m_requiresSoftSeparation;
bool m_requiresHardSeparation;
bool m_hasAnchor;
bool m_hasTag;
bool m_hasNonContent;
std::size_t m_docCount;
};
template <typename T>
void EmitterState::_Set(Setting<T>& fmt, T value, FMT_SCOPE scope) {
void EmitterState::_Set(Setting<T>& fmt, T value, FmtScope::value scope) {
switch(scope) {
case LOCAL:
case FmtScope::Local:
m_modifiedSettings.push(fmt.set(value));
break;
case GLOBAL:
case FmtScope::Global:
fmt.set(value);
m_globalModifiedSettings.push(fmt.set(value)); // this pushes an identity set, so when we restore,
// it restores to the value here, and not the previous one

View File

@@ -107,7 +107,7 @@ namespace YAML
return true;
}
void WriteCodePoint(ostream& out, int codePoint) {
void WriteCodePoint(ostream_wrapper& out, int codePoint) {
if (codePoint < 0 || codePoint > 0x10FFFF) {
codePoint = REPLACEMENT_CHARACTER;
}
@@ -128,12 +128,12 @@ namespace YAML
}
}
bool IsValidPlainScalar(const std::string& str, bool inFlow, bool allowOnlyAscii) {
bool IsValidPlainScalar(const std::string& str, FlowType::value flowType, bool allowOnlyAscii) {
if(str.empty())
return false;
// first check the start
const RegEx& start = (inFlow ? Exp::PlainScalarInFlow() : Exp::PlainScalar());
const RegEx& start = (flowType == FlowType::Flow ? Exp::PlainScalarInFlow() : Exp::PlainScalar());
if(!start.Matches(str))
return false;
@@ -142,7 +142,7 @@ namespace YAML
return false;
// then check until something is disallowed
const RegEx& disallowed = (inFlow ? Exp::EndScalarInFlow() : Exp::EndScalar())
const RegEx& disallowed = (flowType == FlowType::Flow ? Exp::EndScalarInFlow() : Exp::EndScalar())
|| (Exp::BlankOrBreak() + Exp::Comment())
|| Exp::NotPrintable()
|| Exp::Utf8_ByteOrderMark()
@@ -152,7 +152,7 @@ namespace YAML
while(buffer) {
if(disallowed.Matches(buffer))
return false;
if(allowOnlyAscii && (0x7F < static_cast<unsigned char>(buffer[0])))
if(allowOnlyAscii && (0x80 <= static_cast<unsigned char>(buffer[0])))
return false;
++buffer;
}
@@ -160,30 +160,53 @@ namespace YAML
return true;
}
void WriteDoubleQuoteEscapeSequence(ostream& out, int codePoint) {
bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii)
{
// TODO: check for non-printable characters?
for(std::size_t i=0;i<str.size();i++) {
if(escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i])))
return false;
if(str[i] == '\n')
return false;
}
return true;
}
bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType, bool escapeNonAscii)
{
if(flowType == FlowType::Flow)
return false;
// TODO: check for non-printable characters?
for(std::size_t i=0;i<str.size();i++) {
if(escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i])))
return false;
}
return true;
}
void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint) {
static const char hexDigits[] = "0123456789abcdef";
char escSeq[] = "\\U00000000";
out << "\\";
int digits = 8;
if (codePoint < 0xFF) {
escSeq[1] = 'x';
if(codePoint < 0xFF) {
out << "x";
digits = 2;
} else if (codePoint < 0xFFFF) {
escSeq[1] = 'u';
} else if(codePoint < 0xFFFF) {
out << "u";
digits = 4;
}
} else {
out << "U";
digits = 8;
}
// Write digits into the escape sequence
int i = 2;
for (; digits > 0; --digits, ++i) {
escSeq[i] = hexDigits[(codePoint >> (4 * (digits - 1))) & 0xF];
}
escSeq[i] = 0; // terminate with NUL character
out << escSeq;
for (; digits > 0; --digits)
out << hexDigits[(codePoint >> (4 * (digits - 1))) & 0xF];
}
bool WriteAliasName(ostream& out, const std::string& str) {
bool WriteAliasName(ostream_wrapper& out, const std::string& str) {
int codePoint;
for(std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());
@@ -198,16 +221,31 @@ namespace YAML
}
}
bool WriteString(ostream& out, const std::string& str, bool inFlow, bool escapeNonAscii)
{
if(IsValidPlainScalar(str, inFlow, escapeNonAscii)) {
out << str;
return true;
} else
return WriteDoubleQuotedString(out, str, escapeNonAscii);
}
bool WriteSingleQuotedString(ostream& out, const std::string& str)
StringFormat::value ComputeStringFormat(const std::string& str, EMITTER_MANIP strFormat, FlowType::value flowType, bool escapeNonAscii)
{
switch(strFormat) {
case Auto:
if(IsValidPlainScalar(str, flowType, escapeNonAscii))
return StringFormat::Plain;
return StringFormat::DoubleQuoted;
case SingleQuoted:
if(IsValidSingleQuotedScalar(str, escapeNonAscii))
return StringFormat::SingleQuoted;
return StringFormat::DoubleQuoted;
case DoubleQuoted:
return StringFormat::DoubleQuoted;
case Literal:
if(IsValidLiteralScalar(str, flowType, escapeNonAscii))
return StringFormat::Literal;
return StringFormat::DoubleQuoted;
default:
break;
}
return StringFormat::DoubleQuoted;
}
bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str)
{
out << "'";
int codePoint;
@@ -227,7 +265,7 @@ namespace YAML
return true;
}
bool WriteDoubleQuotedString(ostream& out, const std::string& str, bool escapeNonAscii)
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str, bool escapeNonAscii)
{
out << "\"";
int codePoint;
@@ -235,24 +273,29 @@ namespace YAML
GetNextCodePointAndAdvance(codePoint, i, str.end());
)
{
if (codePoint == '\"')
out << "\\\"";
else if (codePoint == '\\')
out << "\\\\";
else if (codePoint < 0x20 || (codePoint >= 0x80 && codePoint <= 0xA0)) // Control characters and non-breaking space
WriteDoubleQuoteEscapeSequence(out, codePoint);
else if (codePoint == 0xFEFF) // Byte order marks (ZWNS) should be escaped (YAML 1.2, sec. 5.2)
WriteDoubleQuoteEscapeSequence(out, codePoint);
else if (escapeNonAscii && codePoint > 0x7E)
WriteDoubleQuoteEscapeSequence(out, codePoint);
else
WriteCodePoint(out, codePoint);
switch(codePoint) {
case '\"': out << "\\\""; break;
case '\\': out << "\\\\"; break;
case '\n': out << "\\n"; break;
case '\t': out << "\\t"; break;
case '\r': out << "\\r"; break;
case '\b': out << "\\b"; break;
default:
if(codePoint < 0x20 || (codePoint >= 0x80 && codePoint <= 0xA0)) // Control characters and non-breaking space
WriteDoubleQuoteEscapeSequence(out, codePoint);
else if (codePoint == 0xFEFF) // Byte order marks (ZWNS) should be escaped (YAML 1.2, sec. 5.2)
WriteDoubleQuoteEscapeSequence(out, codePoint);
else if (escapeNonAscii && codePoint > 0x7E)
WriteDoubleQuoteEscapeSequence(out, codePoint);
else
WriteCodePoint(out, codePoint);
}
}
out << "\"";
return true;
}
bool WriteLiteralString(ostream& out, const std::string& str, int indent)
bool WriteLiteralString(ostream_wrapper& out, const std::string& str, int indent)
{
out << "|\n";
out << IndentTo(indent);
@@ -269,7 +312,7 @@ namespace YAML
return true;
}
bool WriteChar(ostream& out, char ch)
bool WriteChar(ostream_wrapper& out, char ch)
{
if(('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z'))
out << ch;
@@ -289,36 +332,39 @@ namespace YAML
return true;
}
bool WriteComment(ostream& out, const std::string& str, int postCommentIndent)
bool WriteComment(ostream_wrapper& out, const std::string& str, int postCommentIndent)
{
const unsigned curIndent = out.col();
out << "#" << Indentation(postCommentIndent);
out.set_comment();
int codePoint;
for(std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());
)
{
if(codePoint == '\n')
if(codePoint == '\n') {
out << "\n" << IndentTo(curIndent) << "#" << Indentation(postCommentIndent);
else
out.set_comment();
} else {
WriteCodePoint(out, codePoint);
}
}
return true;
}
bool WriteAlias(ostream& out, const std::string& str)
bool WriteAlias(ostream_wrapper& out, const std::string& str)
{
out << "*";
return WriteAliasName(out, str);
}
bool WriteAnchor(ostream& out, const std::string& str)
bool WriteAnchor(ostream_wrapper& out, const std::string& str)
{
out << "&";
return WriteAliasName(out, str);
}
bool WriteTag(ostream& out, const std::string& str, bool verbatim)
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim)
{
out << (verbatim ? "!<" : "!");
StringCharSource buffer(str.c_str(), str.size());
@@ -338,7 +384,7 @@ namespace YAML
return true;
}
bool WriteTagWithPrefix(ostream& out, const std::string& prefix, const std::string& tag)
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix, const std::string& tag)
{
out << "!";
StringCharSource prefixBuffer(prefix.c_str(), prefix.size());
@@ -368,7 +414,7 @@ namespace YAML
return true;
}
bool WriteBinary(ostream& out, const Binary& binary)
bool WriteBinary(ostream_wrapper& out, const Binary& binary)
{
WriteDoubleQuotedString(out, EncodeBase64(binary.data(), binary.size()), false);
return true;

View File

@@ -6,26 +6,30 @@
#endif
#include "yaml-cpp/ostream.h"
#include "emitterstate.h"
#include "yaml-cpp/ostream_wrapper.h"
#include <string>
namespace YAML
{
class Binary;
struct StringFormat { enum value { Plain, SingleQuoted, DoubleQuoted, Literal }; };
namespace Utils
{
bool WriteString(ostream& out, const std::string& str, bool inFlow, bool escapeNonAscii);
bool WriteSingleQuotedString(ostream& out, const std::string& str);
bool WriteDoubleQuotedString(ostream& out, const std::string& str, bool escapeNonAscii);
bool WriteLiteralString(ostream& out, const std::string& str, int indent);
bool WriteChar(ostream& out, char ch);
bool WriteComment(ostream& out, const std::string& str, int postCommentIndent);
bool WriteAlias(ostream& out, const std::string& str);
bool WriteAnchor(ostream& out, const std::string& str);
bool WriteTag(ostream& out, const std::string& str, bool verbatim);
bool WriteTagWithPrefix(ostream& out, const std::string& prefix, const std::string& tag);
bool WriteBinary(ostream& out, const Binary& binary);
StringFormat::value ComputeStringFormat(const std::string& str, EMITTER_MANIP strFormat, FlowType::value flowType, bool escapeNonAscii);
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);
bool WriteChar(ostream_wrapper& out, char ch);
bool WriteComment(ostream_wrapper& out, const std::string& str, int 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);
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix, const std::string& tag);
bool WriteBinary(ostream_wrapper& out, const Binary& binary);
}
}

View File

@@ -91,7 +91,7 @@ namespace YAML
return e;
}
inline const RegEx& Key() {
static const RegEx e = RegEx('?');
static const RegEx e = RegEx('?') + BlankOrBreak();
return e;
}
inline const RegEx& KeyInFlow() {

View File

@@ -6,7 +6,7 @@
#endif
#include "yaml-cpp/ostream.h"
#include "yaml-cpp/ostream_wrapper.h"
#include <iostream>
namespace YAML
@@ -16,7 +16,7 @@ namespace YAML
unsigned n;
};
inline ostream& operator << (ostream& out, const Indentation& indent) {
inline ostream_wrapper& operator << (ostream_wrapper& out, const Indentation& indent) {
for(unsigned i=0;i<indent.n;i++)
out << ' ';
return out;
@@ -27,7 +27,7 @@ namespace YAML
unsigned n;
};
inline ostream& operator << (ostream& out, const IndentTo& indent) {
inline ostream_wrapper& operator << (ostream_wrapper& out, const IndentTo& indent) {
while(out.col() < indent.n)
out << ' ';
return out;

View File

@@ -1,103 +0,0 @@
#include "yaml-cpp/node.h"
#include "yaml-cpp/exceptions.h"
#include "iterpriv.h"
namespace YAML
{
Iterator::Iterator(): m_pData(new IterPriv)
{
}
Iterator::Iterator(std::auto_ptr<IterPriv> pData): m_pData(pData)
{
}
Iterator::Iterator(const Iterator& rhs): m_pData(new IterPriv(*rhs.m_pData))
{
}
Iterator& Iterator::operator = (const Iterator& rhs)
{
if(this == &rhs)
return *this;
m_pData.reset(new IterPriv(*rhs.m_pData));
return *this;
}
Iterator::~Iterator()
{
}
Iterator& Iterator::operator ++ ()
{
if(m_pData->type == IterPriv::IT_SEQ)
++m_pData->seqIter;
else if(m_pData->type == IterPriv::IT_MAP)
++m_pData->mapIter;
return *this;
}
Iterator Iterator::operator ++ (int)
{
Iterator temp = *this;
if(m_pData->type == IterPriv::IT_SEQ)
++m_pData->seqIter;
else if(m_pData->type == IterPriv::IT_MAP)
++m_pData->mapIter;
return temp;
}
const Node& Iterator::operator * () const
{
if(m_pData->type == IterPriv::IT_SEQ)
return **m_pData->seqIter;
throw BadDereference();
}
const Node *Iterator::operator -> () const
{
if(m_pData->type == IterPriv::IT_SEQ)
return *m_pData->seqIter;
throw BadDereference();
}
const Node& Iterator::first() const
{
if(m_pData->type == IterPriv::IT_MAP)
return *m_pData->mapIter->first;
throw BadDereference();
}
const Node& Iterator::second() const
{
if(m_pData->type == IterPriv::IT_MAP)
return *m_pData->mapIter->second;
throw BadDereference();
}
bool operator == (const Iterator& it, const Iterator& jt)
{
if(it.m_pData->type != jt.m_pData->type)
return false;
if(it.m_pData->type == IterPriv::IT_SEQ)
return it.m_pData->seqIter == jt.m_pData->seqIter;
else if(it.m_pData->type == IterPriv::IT_MAP)
return it.m_pData->mapIter == jt.m_pData->mapIter;
return true;
}
bool operator != (const Iterator& it, const Iterator& jt)
{
return !(it == jt);
}
}

View File

@@ -1,33 +0,0 @@
#ifndef ITERPRIV_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define ITERPRIV_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/ltnode.h"
#include <vector>
#include <map>
namespace YAML
{
class Node;
// IterPriv
// . The implementation for iterators - essentially a union of sequence and map iterators.
struct IterPriv
{
IterPriv(): type(IT_NONE) {}
IterPriv(std::vector <Node *>::const_iterator it): type(IT_SEQ), seqIter(it) {}
IterPriv(std::map <Node *, Node *, ltnode>::const_iterator it): type(IT_MAP), mapIter(it) {}
enum ITER_TYPE { IT_NONE, IT_SEQ, IT_MAP };
ITER_TYPE type;
std::vector <Node *>::const_iterator seqIter;
std::map <Node *, Node *, ltnode>::const_iterator mapIter;
};
}
#endif // ITERPRIV_H_62B23520_7C8E_11DE_8A39_0800200C9A66

29
src/memory.cpp Normal file
View File

@@ -0,0 +1,29 @@
#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());
}
}
}

View File

@@ -1,269 +1,14 @@
#include "yaml-cpp/node.h"
#include "yaml-cpp/aliasmanager.h"
#include "yaml-cpp/emitfromevents.h"
#include "yaml-cpp/emitter.h"
#include "yaml-cpp/eventhandler.h"
#include "iterpriv.h"
#include "yaml-cpp/node/node.h"
#include "nodebuilder.h"
#include "nodeownership.h"
#include "scanner.h"
#include "tag.h"
#include "token.h"
#include <cassert>
#include <stdexcept>
#include "nodeevents.h"
namespace YAML
{
bool ltnode::operator()(const Node *pNode1, const Node *pNode2) const {
return *pNode1 < *pNode2;
}
Node::Node(): m_pOwnership(new NodeOwnership), m_type(NodeType::Null)
{
}
Node::Node(NodeOwnership& owner): m_pOwnership(new NodeOwnership(&owner)), m_type(NodeType::Null)
{
}
Node::~Node()
{
Clear();
}
void Node::Clear()
{
m_pOwnership.reset(new NodeOwnership);
m_type = NodeType::Null;
m_tag.clear();
m_scalarData.clear();
m_seqData.clear();
m_mapData.clear();
}
bool Node::IsAliased() const
{
return m_pOwnership->IsAliased(*this);
}
Node& Node::CreateNode()
{
return m_pOwnership->Create();
}
std::auto_ptr<Node> Node::Clone() const
{
std::auto_ptr<Node> pNode(new Node);
NodeBuilder nodeBuilder(*pNode);
EmitEvents(nodeBuilder);
return pNode;
}
void Node::EmitEvents(EventHandler& eventHandler) const
{
eventHandler.OnDocumentStart(m_mark);
AliasManager am;
EmitEvents(am, eventHandler);
eventHandler.OnDocumentEnd();
}
void Node::EmitEvents(AliasManager& am, EventHandler& eventHandler) const
{
anchor_t anchor = NullAnchor;
if(IsAliased()) {
anchor = am.LookupAnchor(*this);
if(anchor) {
eventHandler.OnAlias(m_mark, anchor);
return;
}
am.RegisterReference(*this);
anchor = am.LookupAnchor(*this);
}
switch(m_type) {
case NodeType::Null:
eventHandler.OnNull(m_mark, anchor);
break;
case NodeType::Scalar:
eventHandler.OnScalar(m_mark, m_tag, anchor, m_scalarData);
break;
case NodeType::Sequence:
eventHandler.OnSequenceStart(m_mark, m_tag, anchor);
for(std::size_t i=0;i<m_seqData.size();i++)
m_seqData[i]->EmitEvents(am, eventHandler);
eventHandler.OnSequenceEnd();
break;
case NodeType::Map:
eventHandler.OnMapStart(m_mark, m_tag, anchor);
for(node_map::const_iterator it=m_mapData.begin();it!=m_mapData.end();++it) {
it->first->EmitEvents(am, eventHandler);
it->second->EmitEvents(am, eventHandler);
}
eventHandler.OnMapEnd();
break;
}
}
void Node::Init(NodeType::value type, const Mark& mark, const std::string& tag)
{
Clear();
m_mark = mark;
m_type = type;
m_tag = tag;
}
void Node::MarkAsAliased()
{
m_pOwnership->MarkAsAliased(*this);
}
void Node::SetScalarData(const std::string& data)
{
assert(m_type == NodeType::Scalar); // TODO: throw?
m_scalarData = data;
}
void Node::Append(Node& node)
{
assert(m_type == NodeType::Sequence); // TODO: throw?
m_seqData.push_back(&node);
}
void Node::Insert(Node& key, Node& value)
{
assert(m_type == NodeType::Map); // TODO: throw?
m_mapData[&key] = &value;
}
// begin
// Returns an iterator to the beginning of this (sequence or map).
Iterator Node::begin() const
{
switch(m_type) {
case NodeType::Null:
case NodeType::Scalar:
return Iterator();
case NodeType::Sequence:
return Iterator(std::auto_ptr<IterPriv>(new IterPriv(m_seqData.begin())));
case NodeType::Map:
return Iterator(std::auto_ptr<IterPriv>(new IterPriv(m_mapData.begin())));
}
assert(false);
return Iterator();
}
// end
// . Returns an iterator to the end of this (sequence or map).
Iterator Node::end() const
{
switch(m_type) {
case NodeType::Null:
case NodeType::Scalar:
return Iterator();
case NodeType::Sequence:
return Iterator(std::auto_ptr<IterPriv>(new IterPriv(m_seqData.end())));
case NodeType::Map:
return Iterator(std::auto_ptr<IterPriv>(new IterPriv(m_mapData.end())));
}
assert(false);
return Iterator();
}
// size
// . Returns the size of a sequence or map node
// . Otherwise, returns zero.
std::size_t Node::size() const
{
switch(m_type) {
case NodeType::Null:
case NodeType::Scalar:
return 0;
case NodeType::Sequence:
return m_seqData.size();
case NodeType::Map:
return m_mapData.size();
}
assert(false);
return 0;
}
const Node *Node::FindAtIndex(std::size_t i) const
{
if(m_type == NodeType::Sequence)
return m_seqData[i];
return 0;
}
bool Node::GetScalar(std::string& s) const
{
switch(m_type) {
case NodeType::Null:
s = "~";
return true;
case NodeType::Scalar:
s = m_scalarData;
return true;
case NodeType::Sequence:
case NodeType::Map:
return false;
}
assert(false);
return false;
}
Emitter& operator << (Emitter& out, const Node& node)
{
EmitFromEvents emitFromEvents(out);
node.EmitEvents(emitFromEvents);
return out;
}
int Node::Compare(const Node& rhs) const
{
if(m_type != rhs.m_type)
return rhs.m_type - m_type;
switch(m_type) {
case NodeType::Null:
return 0;
case NodeType::Scalar:
return m_scalarData.compare(rhs.m_scalarData);
case NodeType::Sequence:
if(m_seqData.size() < rhs.m_seqData.size())
return 1;
else if(m_seqData.size() > rhs.m_seqData.size())
return -1;
for(std::size_t i=0;i<m_seqData.size();i++)
if(int cmp = m_seqData[i]->Compare(*rhs.m_seqData[i]))
return cmp;
return 0;
case NodeType::Map:
if(m_mapData.size() < rhs.m_mapData.size())
return 1;
else if(m_mapData.size() > rhs.m_mapData.size())
return -1;
node_map::const_iterator it = m_mapData.begin();
node_map::const_iterator jt = rhs.m_mapData.begin();
for(;it!=m_mapData.end() && jt!=rhs.m_mapData.end();it++, jt++) {
if(int cmp = it->first->Compare(*jt->first))
return cmp;
if(int cmp = it->second->Compare(*jt->second))
return cmp;
}
return 0;
}
assert(false);
return 0;
}
bool operator < (const Node& n1, const Node& n2)
{
return n1.Compare(n2) < 0;
}
Node Clone(const Node& node)
{
NodeEvents events(node);
NodeBuilder builder;
events.Emit(builder);
return builder.Root();
}
}

295
src/node_data.cpp Normal file
View File

@@ -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 <sstream>
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;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;
}
}
}

View File

@@ -1,141 +1,134 @@
#include "nodebuilder.h"
#include "yaml-cpp/mark.h"
#include "yaml-cpp/node.h"
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/impl.h"
#include <cassert>
namespace YAML
{
NodeBuilder::NodeBuilder(Node& root): m_root(root), m_initializedRoot(false), m_finished(false)
NodeBuilder::NodeBuilder(): m_pMemory(new detail::memory_holder), m_pRoot(0), m_mapDepth(0)
{
m_root.Clear();
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()
{
assert(m_finished);
}
void NodeBuilder::OnNull(const Mark& mark, anchor_t anchor)
void NodeBuilder::OnNull(const Mark& /* mark */, anchor_t anchor)
{
Node& node = Push(anchor);
node.Init(NodeType::Null, mark, "");
detail::node& node = Push(anchor);
node.set_null();
Pop();
}
void NodeBuilder::OnAlias(const Mark& /*mark*/, anchor_t anchor)
void NodeBuilder::OnAlias(const Mark& /* mark */, anchor_t anchor)
{
Node& node = *m_anchors[anchor];
Insert(node);
node.MarkAsAliased();
}
void NodeBuilder::OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value)
{
Node& node = Push(anchor);
node.Init(NodeType::Scalar, mark, tag);
node.SetScalarData(value);
detail::node& node = *m_anchors[anchor];
Push(node);
Pop();
}
void NodeBuilder::OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor)
void NodeBuilder::OnScalar(const Mark& /* mark */, const std::string& tag, anchor_t anchor, const std::string& value)
{
Node& node = Push(anchor);
node.Init(NodeType::Sequence, mark, tag);
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)
void NodeBuilder::OnMapStart(const Mark& /* mark */, const std::string& tag, anchor_t anchor)
{
Node& node = Push(anchor);
node.Init(NodeType::Map, mark, tag);
m_didPushKey.push(false);
detail::node& node = Push(anchor);
node.set_type(NodeType::Map);
node.set_tag(tag);
m_mapDepth++;
}
void NodeBuilder::OnMapEnd()
{
m_didPushKey.pop();
assert(m_mapDepth > 0);
m_mapDepth--;
Pop();
}
Node& NodeBuilder::Push(anchor_t anchor)
detail::node& NodeBuilder::Push(anchor_t anchor)
{
Node& node = Push();
detail::node& node = m_pMemory->create_node();
RegisterAnchor(anchor, node);
Push(node);
return node;
}
Node& NodeBuilder::Push()
void NodeBuilder::Push(detail::node& node)
{
if(!m_initializedRoot) {
m_initializedRoot = true;
return m_root;
}
const bool needsKey = (!m_stack.empty() && m_stack.back()->type() == NodeType::Map && m_keys.size() < m_mapDepth);
Node& node = m_root.CreateNode();
m_stack.push(&node);
return node;
}
Node& NodeBuilder::Top()
{
return m_stack.empty() ? m_root : *m_stack.top();
m_stack.push_back(&node);
if(needsKey)
m_keys.push_back(PushedKey(&node, false));
}
void NodeBuilder::Pop()
{
assert(!m_finished);
if(m_stack.empty()) {
m_finished = true;
assert(!m_stack.empty());
if(m_stack.size() == 1) {
m_pRoot = m_stack[0];
m_stack.pop_back();
return;
}
Node& node = *m_stack.top();
m_stack.pop();
Insert(node);
}
void NodeBuilder::Insert(Node& node)
{
Node& curTop = Top();
switch(curTop.Type()) {
case NodeType::Null:
case NodeType::Scalar:
assert(false);
break;
case NodeType::Sequence:
curTop.Append(node);
break;
case NodeType::Map:
assert(!m_didPushKey.empty());
if(m_didPushKey.top()) {
assert(!m_pendingKeys.empty());
detail::node& node = *m_stack.back();
m_stack.pop_back();
Node& key = *m_pendingKeys.top();
m_pendingKeys.pop();
curTop.Insert(key, node);
m_didPushKey.top() = false;
} else {
m_pendingKeys.push(&node);
m_didPushKey.top() = true;
}
break;
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, Node& node)
void NodeBuilder::RegisterAnchor(anchor_t anchor, detail::node& node)
{
if(anchor) {
assert(anchor == m_anchors.size());

View File

@@ -1,26 +1,26 @@
#ifndef NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#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 <map>
#include <memory>
#include <stack>
#include "yaml-cpp/node/ptr.h"
#include <vector>
namespace YAML
{
class Node;
class NodeBuilder: public EventHandler
{
public:
explicit NodeBuilder(Node& root);
NodeBuilder();
virtual ~NodeBuilder();
Node Root();
virtual void OnDocumentStart(const Mark& mark);
virtual void OnDocumentEnd();
@@ -35,27 +35,24 @@ namespace YAML
virtual void OnMapEnd();
private:
Node& Push(anchor_t anchor);
Node& Push();
Node& Top();
detail::node& Push(anchor_t anchor);
void Push(detail::node& node);
void Pop();
void Insert(Node& node);
void RegisterAnchor(anchor_t anchor, Node& node);
void RegisterAnchor(anchor_t anchor, detail::node& node);
private:
Node& m_root;
bool m_initializedRoot;
bool m_finished;
detail::shared_memory_holder m_pMemory;
detail::node *m_pRoot;
std::stack<Node *> m_stack;
std::stack<Node *> m_pendingKeys;
std::stack<bool> m_didPushKey;
typedef std::vector<detail::node *> Nodes;
Nodes m_stack;
Nodes m_anchors;
typedef std::vector<Node *> Anchors;
Anchors m_anchors;
typedef std::pair<detail::node *, bool> PushedKey;
std::vector<PushedKey> m_keys;
std::size_t m_mapDepth;
};
}
#endif // NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#endif // NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66

99
src/nodeevents.cpp Normal file
View File

@@ -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;
}
}

57
src/nodeevents.h Normal file
View File

@@ -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 <map>
#include <vector>
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<const detail::node_ref*, anchor_t> 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<const detail::node_ref *, int> RefCount;
RefCount m_refCount;
};
}
#endif // NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,31 +0,0 @@
#include "nodeownership.h"
#include "yaml-cpp/node.h"
namespace YAML
{
NodeOwnership::NodeOwnership(NodeOwnership *pOwner): m_pOwner(pOwner)
{
if(!m_pOwner)
m_pOwner = this;
}
NodeOwnership::~NodeOwnership()
{
}
Node& NodeOwnership::_Create()
{
m_nodes.push_back(std::auto_ptr<Node>(new Node));
return m_nodes.back();
}
void NodeOwnership::_MarkAsAliased(const Node& node)
{
m_aliasedNodes.insert(&node);
}
bool NodeOwnership::_IsAliased(const Node& node) const
{
return m_aliasedNodes.count(&node) > 0;
}
}

View File

@@ -1,39 +0,0 @@
#ifndef NODE_OWNERSHIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODE_OWNERSHIP_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/noncopyable.h"
#include "ptr_vector.h"
#include <set>
namespace YAML
{
class Node;
class NodeOwnership: private noncopyable
{
public:
explicit NodeOwnership(NodeOwnership *pOwner = 0);
~NodeOwnership();
Node& Create() { return m_pOwner->_Create(); }
void MarkAsAliased(const Node& node) { m_pOwner->_MarkAsAliased(node); }
bool IsAliased(const Node& node) const { return m_pOwner->_IsAliased(node); }
private:
Node& _Create();
void _MarkAsAliased(const Node& node);
bool _IsAliased(const Node& node) const;
private:
ptr_vector<Node> m_nodes;
std::set<const Node *> m_aliasedNodes;
NodeOwnership *m_pOwner;
};
}
#endif // NODE_OWNERSHIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -1,12 +1,6 @@
#include "yaml-cpp/null.h"
#include "yaml-cpp/node.h"
namespace YAML
{
_Null Null;
bool IsNull(const Node& node)
{
return node.Read(Null);
}
}

View File

@@ -1,63 +0,0 @@
#include "yaml-cpp/ostream.h"
#include <cstring>
namespace YAML
{
ostream::ostream(): m_buffer(0), m_pos(0), m_size(0), m_row(0), m_col(0)
{
reserve(1024);
}
ostream::~ostream()
{
delete [] m_buffer;
}
void ostream::reserve(unsigned size)
{
if(size <= m_size)
return;
char *newBuffer = new char[size];
std::memset(newBuffer, 0, size * sizeof(char));
std::memcpy(newBuffer, m_buffer, m_size * sizeof(char));
delete [] m_buffer;
m_buffer = newBuffer;
m_size = size;
}
void ostream::put(char ch)
{
if(m_pos >= m_size - 1) // an extra space for the NULL terminator
reserve(m_size * 2);
m_buffer[m_pos] = ch;
m_pos++;
if(ch == '\n') {
m_row++;
m_col = 0;
} else
m_col++;
}
ostream& operator << (ostream& out, const char *str)
{
std::size_t length = std::strlen(str);
for(std::size_t i=0;i<length;i++)
out.put(str[i]);
return out;
}
ostream& operator << (ostream& out, const std::string& str)
{
out << str.c_str();
return out;
}
ostream& operator << (ostream& out, char ch)
{
out.put(ch);
return out;
}
}

56
src/ostream_wrapper.cpp Normal file
View File

@@ -0,0 +1,56 @@
#include "yaml-cpp/ostream_wrapper.h"
#include <cstring>
#include <iostream>
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(std::ostream& stream): m_pStream(&stream), 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;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;
}
}
}

68
src/parse.cpp Normal file
View File

@@ -0,0 +1,68 @@
#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 <fstream>
#include <sstream>
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<Node> LoadAll(const std::string& input) {
std::stringstream stream(input);
return LoadAll(stream);
}
std::vector<Node> LoadAll(const char *input) {
std::stringstream stream(input);
return LoadAll(stream);
}
std::vector<Node> LoadAll(std::istream& input) {
std::vector<Node> docs;
Parser parser(input);
while(1) {
NodeBuilder builder;
if(!parser.HandleNextDocument(builder))
break;
docs.push_back(builder.Root());
}
return docs;
}
std::vector<Node> LoadAllFromFile(const std::string& filename) {
std::ifstream fin(filename.c_str());
if(!fin)
throw BadFile();
return LoadAll(fin);
}
}

View File

@@ -1,9 +1,7 @@
#include "yaml-cpp/parser.h"
#include "yaml-cpp/eventhandler.h"
#include "yaml-cpp/exceptions.h"
#include "yaml-cpp/node.h"
#include "directives.h"
#include "nodebuilder.h"
#include "scanner.h"
#include "singledocparser.h"
#include "tag.h"
@@ -55,15 +53,6 @@ namespace YAML
return true;
}
// GetNextDocument
// . Reads the next document in the queue (of tokens).
// . Throws a ParserException on error.
bool Parser::GetNextDocument(Node& document)
{
NodeBuilder builder(document);
return HandleNextDocument(builder);
}
// ParseDirectives
// . Reads any directives that are next in the queue.
void Parser::ParseDirectives()

View File

@@ -38,7 +38,10 @@ public:
}
T& top() { return *m_data.back(); }
const T& top() const { return *m_data.back(); }
T& top(std::ptrdiff_t diff) { return **(m_data.end() - 1 + diff); }
const T& top(std::ptrdiff_t diff) const { return **(m_data.end() - 1 + diff); }
private:
std::vector<T*> m_data;
};

View File

@@ -51,6 +51,13 @@ namespace YAML
return m_tokens.front();
}
// mark
// . Returns the current mark in the stream
Mark Scanner::mark() const
{
return INPUT.mark();
}
// EnsureTokensInQueue
// . Scan until there's a valid token at the front of the queue,
// or we're sure the queue is empty.
@@ -376,7 +383,7 @@ namespace YAML
// . Does not parse any more tokens.
void Scanner::ThrowParserException(const std::string& msg) const
{
Mark mark = Mark::null();
Mark mark = Mark::null_mark();
if(!m_tokens.empty()) {
const Token& token = m_tokens.front();
mark = token.mark;

View File

@@ -31,6 +31,7 @@ namespace YAML
bool empty();
void pop();
Token& peek();
Mark mark() const;
private:
struct IndentMarker {

View File

@@ -48,7 +48,7 @@ namespace YAML
{
// an empty node *is* a possibility
if(m_scanner.empty()) {
eventHandler.OnNull(Mark::null(), NullAnchor);
eventHandler.OnNull(m_scanner.mark(), NullAnchor);
return;
}
@@ -57,7 +57,7 @@ namespace YAML
// special case: a value node by itself must be a map, with no header
if(m_scanner.peek().type == Token::VALUE) {
eventHandler.OnMapStart(mark, "", NullAnchor);
eventHandler.OnMapStart(mark, "?", NullAnchor);
HandleMap(eventHandler);
eventHandler.OnMapEnd();
return;
@@ -75,6 +75,12 @@ namespace YAML
ParseProperties(tag, anchor);
const Token& token = m_scanner.peek();
if(token.type == Token::PLAIN_SCALAR && token.value == "null") {
eventHandler.OnNull(mark, anchor);
m_scanner.pop();
return;
}
// add non-specific tags
if(tag.empty())
@@ -136,7 +142,7 @@ namespace YAML
while(1) {
if(m_scanner.empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ);
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ);
Token token = m_scanner.peek();
if(token.type != Token::BLOCK_ENTRY && token.type != Token::BLOCK_SEQ_END)
@@ -169,7 +175,7 @@ namespace YAML
while(1) {
if(m_scanner.empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ_FLOW);
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);
// first check for end
if(m_scanner.peek().type == Token::FLOW_SEQ_END) {
@@ -179,6 +185,9 @@ namespace YAML
// then read the node
HandleNode(eventHandler);
if(m_scanner.empty())
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);
// now eat the separator (or could be a sequence end, which we ignore - but if it's neither, then it's a bad node)
Token& token = m_scanner.peek();
@@ -211,7 +220,7 @@ namespace YAML
while(1) {
if(m_scanner.empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP);
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP);
Token token = m_scanner.peek();
if(token.type != Token::KEY && token.type != Token::VALUE && token.type != Token::BLOCK_MAP_END)
@@ -250,9 +259,10 @@ namespace YAML
while(1) {
if(m_scanner.empty())
throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP_FLOW);
throw ParserException(m_scanner.mark(), 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();
@@ -264,7 +274,7 @@ namespace YAML
m_scanner.pop();
HandleNode(eventHandler);
} else {
eventHandler.OnNull(token.mark, NullAnchor);
eventHandler.OnNull(mark, NullAnchor);
}
// now grab value (optional)
@@ -272,8 +282,11 @@ namespace YAML
m_scanner.pop();
HandleNode(eventHandler);
} else {
eventHandler.OnNull(token.mark, NullAnchor);
eventHandler.OnNull(mark, NullAnchor);
}
if(m_scanner.empty())
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);
// now eat the separator (or could be a map end, which we ignore - but if it's neither, then it's a bad node)
Token& nextToken = m_scanner.peek();

View File

@@ -400,8 +400,7 @@ namespace YAML
if (m_nPrefetchedUsed >= m_nPrefetchedAvailable)
{
std::streambuf *pBuf = m_input.rdbuf();
m_nPrefetchedAvailable = pBuf->sgetn(ReadBuffer(m_pPrefetched),
YAML_PREFETCH_SIZE);
m_nPrefetchedAvailable = static_cast<std::size_t>(pBuf->sgetn(ReadBuffer(m_pPrefetched), YAML_PREFETCH_SIZE));
m_nPrefetchedUsed = 0;
if (!m_nPrefetchedAvailable)
{

View File

@@ -1,8 +1,8 @@
file(GLOB test_headers [a-z]*.h)
file(GLOB test_sources [a-z]*.cpp)
file(GLOB test_old_api_sources old-api/[a-z]*.cpp)
file(GLOB test_new_api_sources new-api/[a-z]*.cpp)
list(APPEND test_sources ${test_old_api_sources})
list(APPEND test_sources ${test_new_api_sources})
include_directories(${YAML_CPP_SOURCE_DIR}/test)

77
test/core/parsertests.cpp Normal file
View File

@@ -0,0 +1,77 @@
#include "parsertests.h"
#include "handlermacros.h"
#include "yaml-cpp/yaml.h"
#include <iostream>
namespace Test
{
namespace Parser {
TEST NoEndOfMapFlow()
{
try {
HANDLE("---{header: {id: 1");
} catch(const YAML::ParserException& e) {
YAML_ASSERT(e.msg == std::string(YAML::ErrorMsg::END_OF_MAP_FLOW));
return true;
}
return " no exception caught";
}
TEST PlainScalarStartingWithQuestionMark()
{
HANDLE("foo: ?bar");
EXPECT_DOC_START();
EXPECT_MAP_START("?", 0);
EXPECT_SCALAR("?", 0, "foo");
EXPECT_SCALAR("?", 0, "?bar");
EXPECT_MAP_END();
EXPECT_DOC_END();
DONE();
}
TEST NullStringScalar()
{
HANDLE("foo: null");
EXPECT_DOC_START();
EXPECT_MAP_START("?", 0);
EXPECT_SCALAR("?", 0, "foo");
EXPECT_NULL(0);
EXPECT_MAP_END();
EXPECT_DOC_END();
DONE();
}
}
namespace {
void RunParserTest(TEST (*test)(), const std::string& name, int& passed, int& total) {
TEST ret;
try {
ret = test();
} catch(const YAML::Exception& e) {
ret.ok = false;
ret.error = std::string(" Exception caught: ") + e.what();
}
if(!ret.ok) {
std::cout << "Parser test failed: " << name << "\n";
std::cout << ret.error << "\n";
}
if(ret.ok)
passed++;
total++;
}
}
bool RunParserTests()
{
int passed = 0;
int total = 0;
RunParserTest(&Parser::NoEndOfMapFlow, "No end of map flow", passed, total);
RunParserTest(&Parser::PlainScalarStartingWithQuestionMark, "Plain scalar starting with question mark", passed, total);
RunParserTest(&Parser::NullStringScalar, "Null string scalar", passed, total);
std::cout << "Parser tests: " << passed << "/" << total << " passed\n";
return passed == total;
}
}

1939
test/core/spectests.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,184 @@
import sys
import yaml
import hashlib
NS = 'Emitter'
DEFINE = 'YAML_GEN_TESTS'
EVENT_COUNT = 5
def encode_stream(line):
for c in line:
if c == '\n':
yield '\\n'
elif c == '"':
yield '\\"'
elif c == '\t':
yield '\\t'
elif ord(c) < 0x20:
yield '\\x' + hex(ord(c))
else:
yield c
def encode(line):
return ''.join(encode_stream(line))
def doc_start(implicit=False):
if implicit:
return {'emit': '', 'handle': 'DOC_START()'}
else:
return {'emit': 'YAML::BeginDoc', 'handle': 'DOC_START()'}
def doc_end(implicit=False):
if implicit:
return {'emit': '', 'handle': 'DOC_END()'}
else:
return {'emit': 'YAML::EndDoc', 'handle': 'DOC_END()'}
def scalar(value, tag='', anchor='', anchor_id=0):
emit = []
if tag:
emit += ['YAML::VerbatimTag("%s")' % encode(tag)]
if anchor:
emit += ['YAML::Anchor("%s")' % encode(anchor)]
if tag:
out_tag = encode(tag)
else:
if value == encode(value):
out_tag = '?'
else:
out_tag = '!'
emit += ['"%s"' % encode(value)]
return {'emit': emit, 'handle': 'SCALAR("%s", %s, "%s")' % (out_tag, anchor_id, encode(value))}
def comment(value):
return {'emit': 'YAML::Comment("%s")' % value, 'handle': ''}
def seq_start(tag='', anchor='', anchor_id=0):
emit = []
if tag:
emit += ['YAML::VerbatimTag("%s")' % encode(tag)]
if anchor:
emit += ['YAML::Anchor("%s")' % encode(anchor)]
if tag:
out_tag = encode(tag)
else:
out_tag = '?'
emit += ['YAML::BeginSeq']
return {'emit': emit, 'handle': 'SEQ_START("%s", %s)' % (out_tag, anchor_id)}
def seq_end():
return {'emit': 'YAML::EndSeq', 'handle': 'SEQ_END()'}
def map_start(tag='', anchor='', anchor_id=0):
emit = []
if tag:
emit += ['YAML::VerbatimTag("%s")' % encode(tag)]
if anchor:
emit += ['YAML::Anchor("%s")' % encode(anchor)]
if tag:
out_tag = encode(tag)
else:
out_tag = '?'
emit += ['YAML::BeginMap']
return {'emit': emit, 'handle': 'MAP_START("%s", %s)' % (out_tag, anchor_id)}
def map_end():
return {'emit': 'YAML::EndMap', 'handle': 'MAP_END()'}
def gen_templates():
yield [[doc_start(), doc_start(True)],
[scalar('foo'), scalar('foo\n'), scalar('foo', 'tag'), scalar('foo', '', 'anchor', 1)],
[doc_end(), doc_end(True)]]
yield [[doc_start(), doc_start(True)],
[seq_start()],
[[], [scalar('foo')], [scalar('foo', 'tag')], [scalar('foo', '', 'anchor', 1)], [scalar('foo', 'tag', 'anchor', 1)], [scalar('foo'), scalar('bar')], [scalar('foo', 'tag', 'anchor', 1), scalar('bar', 'tag', 'other', 2)]],
[seq_end()],
[doc_end(), doc_end(True)]]
yield [[doc_start(), doc_start(True)],
[map_start()],
[[], [scalar('foo'), scalar('bar')], [scalar('foo', 'tag', 'anchor', 1), scalar('bar', 'tag', 'other', 2)]],
[map_end()],
[doc_end(), doc_end(True)]]
yield [[doc_start(True)],
[map_start()],
[[scalar('foo')], [seq_start(), scalar('foo'), seq_end()], [map_start(), scalar('foo'), scalar('bar'), map_end()]],
[[scalar('foo')], [seq_start(), scalar('foo'), seq_end()], [map_start(), scalar('foo'), scalar('bar'), map_end()]],
[map_end()],
[doc_end(True)]]
yield [[doc_start(True)],
[seq_start()],
[[scalar('foo')], [seq_start(), scalar('foo'), seq_end()], [map_start(), scalar('foo'), scalar('bar'), map_end()]],
[[scalar('foo')], [seq_start(), scalar('foo'), seq_end()], [map_start(), scalar('foo'), scalar('bar'), map_end()]],
[seq_end()],
[doc_end(True)]]
def expand(template):
if len(template) == 0:
pass
elif len(template) == 1:
for item in template[0]:
if isinstance(item, list):
yield item
else:
yield [item]
else:
for car in expand(template[:1]):
for cdr in expand(template[1:]):
yield car + cdr
def gen_events():
for template in gen_templates():
for events in expand(template):
base = list(events)
for i in range(0, len(base)+1):
cpy = list(base)
cpy.insert(i, comment('comment'))
yield cpy
def gen_tests():
for events in gen_events():
name = 'test' + hashlib.sha1(''.join(yaml.dump(event) for event in events)).hexdigest()[:20]
yield {'name': name, 'events': events}
def create_emitter_tests(out):
out.write('#ifdef %s\n' % DEFINE)
out.write('namespace %s {\n' % NS)
tests = list(gen_tests())
for test in tests:
out.write('TEST %s(YAML::Emitter& out)\n' % test['name'])
out.write('{\n')
for event in test['events']:
emit = event['emit']
if isinstance(emit, list):
for e in emit:
out.write(' out << %s;\n' % e)
elif emit:
out.write(' out << %s;\n' % emit)
out.write('\n')
out.write(' HANDLE(out.c_str());\n')
for event in test['events']:
handle = event['handle']
if handle:
out.write(' EXPECT_%s;\n' % handle)
out.write(' DONE();\n')
out.write('}\n')
out.write('}\n')
out.write('#endif // %s\n\n' % DEFINE)
out.write('void RunGenEmitterTests(int& passed, int& total)\n')
out.write('{\n')
out.write('#ifdef %s\n' % DEFINE)
for test in tests:
out.write(' RunGenEmitterTest(&Emitter::%s, "%s", passed, total);\n' % (test['name'], encode(test['name'])))
out.write('#else // %s\n' % DEFINE)
out.write(' (void)passed; (void)total;\n')
out.write('#endif // %s\n' % DEFINE)
out.write('}\n')
if __name__ == '__main__':
create_emitter_tests(sys.stdout)

View File

@@ -1,4 +1,5 @@
#include "tests.h"
#include "handlermacros.h"
#include "yaml-cpp/yaml.h"
#include <iostream>
@@ -190,7 +191,7 @@ namespace Test
out << YAML::Value << "demon";
out << YAML::EndMap;
desiredOutput = "?\n - 1\n - 3\n: monster\n? [2, 0]\n: demon";
desiredOutput = "? - 1\n - 3\n: monster\n? [2, 0]\n: demon";
}
void AutoLongKey(YAML::Emitter& out, std::string& desiredOutput)
@@ -204,7 +205,7 @@ namespace Test
out << YAML::Value << "angel";
out << YAML::EndMap;
desiredOutput = "?\n - 1\n - 3\n: monster\n? [2, 0]\n: demon\nthe origin: angel";
desiredOutput = "? - 1\n - 3\n: monster\n[2, 0]: demon\nthe origin: angel";
}
void ScalarFormat(YAML::Emitter& out, std::string& desiredOutput)
@@ -218,7 +219,7 @@ namespace Test
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\\x0adouble-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";
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)
@@ -256,7 +257,7 @@ namespace Test
out << "total value";
out << YAML::EndMap;
desiredOutput = "?\n key: value\n next key: next value\n: total value";
desiredOutput = "? key: value\n next key: next value\n: total value";
}
void AliasAndAnchor(YAML::Emitter& out, std::string& desiredOutput)
@@ -539,7 +540,7 @@ namespace Test
{
out << YAML::Flow << YAML::BeginSeq << "foo" << YAML::Comment("foo!") << "bar" << YAML::EndSeq;
desiredOutput = "[foo # foo!\n, bar]";
desiredOutput = "[foo, # foo!\nbar]";
}
void CommentInFlowMap(YAML::Emitter& out, std::string& desiredOutput)
@@ -550,7 +551,7 @@ namespace Test
out << YAML::Key << "baz" << YAML::Value << "baz value" << YAML::Comment("baz!");
out << YAML::EndMap;
desiredOutput = "{foo: foo value, bar: bar value # bar!\n, baz: baz value # baz!\n}";
desiredOutput = "{foo: foo value, bar: bar value, # bar!\nbaz: baz value, # baz!\n}";
}
void Indentation(YAML::Emitter& out, std::string& desiredOutput)
@@ -563,7 +564,7 @@ namespace Test
out << YAML::EndMap;
out << YAML::EndSeq;
desiredOutput = "- key 1: value 1\n key 2:\n - a\n - b\n - c";
desiredOutput = "- key 1: value 1\n key 2:\n - a\n - b\n - c";
}
void SimpleGlobalSettings(YAML::Emitter& out, std::string& desiredOutput)
@@ -597,7 +598,7 @@ namespace Test
out << YAML::EndMap;
out << YAML::EndSeq;
desiredOutput = "- key 1: value 1\n key 2: [a, b, c]\n- ? [1, 2]\n :\n a: b";
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)
@@ -720,7 +721,7 @@ namespace Test
out << YAML::Flow << YAML::BeginSeq;
out << "a" << YAML::Newline << "b" << "c" << YAML::Newline << "d";
out << YAML::EndSeq;
desiredOutput = "[a\n, b, c\n, d]";
desiredOutput = "[a,\nb, c,\nd]";
}
void NewlineInBlockMap(YAML::Emitter& out, std::string& desiredOutput)
@@ -730,7 +731,7 @@ namespace Test
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\n\nb: bar\n? c\n\n: car";
desiredOutput = "a: foo\nb:\n bar\n? c\n\n: car";
}
void NewlineInFlowMap(YAML::Emitter& out, std::string& desiredOutput)
@@ -739,7 +740,7 @@ namespace Test
out << YAML::Key << "a" << YAML::Value << "foo" << YAML::Newline;
out << YAML::Key << "b" << YAML::Value << "bar";
out << YAML::EndMap;
desiredOutput = "{a: foo\n, b: bar}";
desiredOutput = "{a: foo,\nb: bar}";
}
void LotsOfNewlines(YAML::Emitter& out, std::string& desiredOutput)
@@ -755,7 +756,7 @@ namespace Test
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: e\n ? f\n\n : foo";
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)
@@ -911,7 +912,40 @@ namespace Test
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)
@@ -935,13 +969,6 @@ namespace Test
out << YAML::EndMap;
}
void BadSingleQuoted(YAML::Emitter& out, std::string& desiredError)
{
desiredError = YAML::ErrorMsg::SINGLE_QUOTED_CHAR;
out << YAML::SingleQuoted << "Hello\nWorld";
}
void InvalidAnchor(YAML::Emitter& out, std::string& desiredError)
{
desiredError = YAML::ErrorMsg::INVALID_ANCHOR;
@@ -959,43 +986,6 @@ namespace Test
out << YAML::Alias("new\nline");
out << YAML::EndSeq;
}
void MissingKey(YAML::Emitter& out, std::string& desiredError)
{
desiredError = YAML::ErrorMsg::EXPECTED_KEY_TOKEN;
out << YAML::BeginMap;
out << YAML::Key << "key" << YAML::Value << "value";
out << "missing key" << YAML::Value << "value";
out << YAML::EndMap;
}
void MissingValue(YAML::Emitter& out, std::string& desiredError)
{
desiredError = YAML::ErrorMsg::EXPECTED_VALUE_TOKEN;
out << YAML::BeginMap;
out << YAML::Key << "key" << "value";
out << YAML::EndMap;
}
void UnexpectedKey(YAML::Emitter& out, std::string& desiredError)
{
desiredError = YAML::ErrorMsg::UNEXPECTED_KEY_TOKEN;
out << YAML::BeginSeq;
out << YAML::Key << "hi";
out << YAML::EndSeq;
}
void UnexpectedValue(YAML::Emitter& out, std::string& desiredError)
{
desiredError = YAML::ErrorMsg::UNEXPECTED_VALUE_TOKEN;
out << YAML::BeginSeq;
out << YAML::Value << "hi";
out << YAML::EndSeq;
}
}
namespace {
@@ -1008,10 +998,7 @@ namespace Test
if(output == desiredOutput) {
try {
std::stringstream stream(output);
YAML::Parser parser;
YAML::Node node;
parser.GetNextDocument(node);
YAML::Node node = YAML::Load(output);
passed++;
} catch(const YAML::Exception& e) {
std::cout << "Emitter test failed: " << name << "\n";
@@ -1046,7 +1033,37 @@ namespace Test
}
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()
{
@@ -1129,17 +1146,16 @@ namespace Test
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::BadSingleQuoted, "bad single quoted string", passed, total);
RunEmitterErrorTest(&Emitter::InvalidAnchor, "invalid anchor", passed, total);
RunEmitterErrorTest(&Emitter::InvalidAlias, "invalid alias", passed, total);
RunEmitterErrorTest(&Emitter::MissingKey, "missing key", passed, total);
RunEmitterErrorTest(&Emitter::MissingValue, "missing value", passed, total);
RunEmitterErrorTest(&Emitter::UnexpectedKey, "unexpected key", passed, total);
RunEmitterErrorTest(&Emitter::UnexpectedValue, "unexpected value", passed, total);
RunEmitterErrorTest(&Emitter::BadLocalTag, "bad local tag", passed, total);
RunGenEmitterTests(passed, total);
std::cout << "Emitter tests: " << passed << "/" << total << " passed\n";
return passed == total;

10256
test/genemittertests.h Normal file

File diff suppressed because it is too large Load Diff

190
test/handlermacros.h Normal file
View File

@@ -0,0 +1,190 @@
#include "teststruct.h"
#pragma once
#include "yaml-cpp/yaml.h"
#include "yaml-cpp/eventhandler.h"
#include <string>
#include <cassert>
namespace Test {
inline std::string Quote(const std::string& text) {
YAML::Emitter out;
out << YAML::DoubleQuoted << text;
return out.c_str();
}
struct Event {
enum Type { DocStart, DocEnd, Null, Alias, Scalar, SeqStart, SeqEnd, MapStart, MapEnd };
typedef YAML::Mark Mark;
typedef YAML::anchor_t anchor_t;
Event(Type type_, const std::string& tag_, anchor_t anchor_, const std::string& scalar_): type(type_), tag(tag_), anchor(anchor_), scalar(scalar_) {}
Type type;
std::string tag;
anchor_t anchor;
std::string scalar;
std::ostream& write(std::ostream& out) const {
switch(type) {
case DocStart:
return out << "DocStart";
case DocEnd:
return out << "DocEnd";
case Null:
return out << "Null(" << anchor << ")";
case Alias:
return out << "Alias(" << anchor << ")";
case Scalar:
return out << "Scalar(" << Quote(tag) << ", " << anchor << ", " << Quote(scalar) << ")";
case SeqStart:
return out << "SeqStart(" << Quote(tag) << ", " << anchor << ")";
case SeqEnd:
return out << "SeqEnd";
case MapStart:
return out << "MapStart(" << Quote(tag) << ", " << anchor << ")";
case MapEnd:
return out << "MapEnd";
}
assert(false);
return out;
}
};
inline std::ostream& operator << (std::ostream& out, const Event& event) {
return event.write(out);
}
inline bool operator == (const Event& a, const Event& b) {
return a.type == b.type && a.tag == b.tag && a.anchor == b.anchor && a.scalar == b.scalar;
}
inline bool operator != (const Event& a, const Event& b) {
return !(a == b);
}
class MockEventHandler: public YAML::EventHandler
{
public:
typedef YAML::Mark Mark;
typedef YAML::anchor_t anchor_t;
MockEventHandler() {}
virtual void OnDocumentStart(const Mark&) {
m_actualEvents.push_back(Event(Event::DocStart, "", 0, ""));
}
virtual void OnDocumentEnd() {
m_actualEvents.push_back(Event(Event::DocEnd, "", 0, ""));
}
virtual void OnNull(const Mark&, anchor_t anchor) {
m_actualEvents.push_back(Event(Event::Null, "", anchor, ""));
}
virtual void OnAlias(const Mark&, anchor_t anchor) {
m_actualEvents.push_back(Event(Event::Alias, "", anchor, ""));
}
virtual void OnScalar(const Mark&, const std::string& tag, anchor_t anchor, const std::string& value) {
m_actualEvents.push_back(Event(Event::Scalar, tag, anchor, value));
}
virtual void OnSequenceStart(const Mark&, const std::string& tag, anchor_t anchor) {
m_actualEvents.push_back(Event(Event::SeqStart, tag, anchor, ""));
}
virtual void OnSequenceEnd() {
m_actualEvents.push_back(Event(Event::SeqEnd, "", 0, ""));
}
virtual void OnMapStart(const Mark&, const std::string& tag, anchor_t anchor) {
m_actualEvents.push_back(Event(Event::MapStart, tag, anchor, ""));
}
virtual void OnMapEnd() {
m_actualEvents.push_back(Event(Event::MapEnd, "", 0, ""));
}
void Expect(const Event& event) { m_expectedEvents.push_back(event); }
Test::TEST Check() const {
std::size_t N = std::max(m_expectedEvents.size(), m_actualEvents.size());
for(std::size_t i=0;i<N;i++) {
if(i >= m_expectedEvents.size()) {
std::stringstream out;
for(std::size_t j=0;j<i;j++) {
out << " " << m_expectedEvents[j] << "\n";
}
out << " EXPECTED: (no event expected)\n";
out << " ACTUAL : " << m_actualEvents[i] << "\n";
return out.str().c_str();
}
if(i >= m_actualEvents.size()) {
std::stringstream out;
for(std::size_t j=0;j<i;j++) {
out << " " << m_expectedEvents[j] << "\n";
}
out << " EXPECTED: " << m_expectedEvents[i] << "\n";
out << " ACTUAL : (no event recorded)\n";
return out.str().c_str();
}
if(m_expectedEvents[i] != m_actualEvents[i]) {
std::stringstream out;
for(std::size_t j=0;j<i;j++) {
out << " " << m_expectedEvents[j] << "\n";
}
out << " EXPECTED: " << m_expectedEvents[i] << "\n";
out << " ACTUAL : " << m_actualEvents[i] << "\n";
return out.str().c_str();
}
}
return true;
}
std::vector<Event> m_expectedEvents;
std::vector<Event> m_actualEvents;
};
#define HANDLE(ex)\
MockEventHandler handler;\
std::stringstream stream(ex);\
YAML::Parser parser(stream);\
while(parser.HandleNextDocument(handler)) {}
#define EXPECT_DOC_START()\
handler.Expect(Event(Event::DocStart, "", 0, ""))
#define EXPECT_DOC_END()\
handler.Expect(Event(Event::DocEnd, "", 0, ""))
#define EXPECT_NULL(anchor)\
handler.Expect(Event(Event::Null, "", anchor, ""))
#define EXPECT_ALIAS(anchor)\
handler.Expect(Event(Event::Alias, "", anchor, ""))
#define EXPECT_SCALAR(tag, anchor, value)\
handler.Expect(Event(Event::Scalar, tag, anchor, value))
#define EXPECT_SEQ_START(tag, anchor)\
handler.Expect(Event(Event::SeqStart, tag, anchor, ""))
#define EXPECT_SEQ_END()\
handler.Expect(Event(Event::SeqEnd, "", 0, ""))
#define EXPECT_MAP_START(tag, anchor)\
handler.Expect(Event(Event::MapStart, tag, anchor, ""))
#define EXPECT_MAP_END()\
handler.Expect(Event(Event::MapEnd, "", 0, ""))
#define DONE()\
return handler.Check()
}

576
test/new-api/nodetests.cpp Normal file
View File

@@ -0,0 +1,576 @@
#include "nodetests.h"
#include "yaml-cpp/yaml.h"
#include <boost/foreach.hpp>
#include <iostream>
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<std::string>() == "Hello, World!");
return true;
}
TEST IntScalar()
{
YAML::Node node = YAML::Node(15);
YAML_ASSERT(node.IsScalar());
YAML_ASSERT(node.as<int>() == 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<int>() == 10);
YAML_ASSERT(node[1].as<std::string>() == "foo");
YAML_ASSERT(node[2].as<std::string>() == "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<int>() == 10);
YAML_ASSERT(node[1].as<std::string>() == "foo");
YAML_ASSERT(node[2].as<std::string>() == "monkey");
YAML_ASSERT(node.IsSequence());
return true;
}
TEST SimpleMap()
{
YAML::Node node;
node["key"] = "value";
YAML_ASSERT(node.IsMap());
YAML_ASSERT(node["key"].as<std::string>() == "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<std::string>() == "value");
YAML_ASSERT(node.size() == 1);
node["undefined"] = "monkey";
YAML_ASSERT(node["undefined"].as<std::string>() == "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<std::string>() == "12345");
YAML_ASSERT(node["device"]["name"].as<std::string>() == "iPhone");
YAML_ASSERT(node["device"]["os"].as<std::string>() == "4.0");
YAML_ASSERT(node["username"].as<std::string>() == "monkey");
return true;
}
TEST StdVector()
{
std::vector<int> 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<std::vector<int> >() == primes);
return true;
}
TEST StdList()
{
std::list<int> 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<std::list<int> >() == primes);
return true;
}
TEST StdMap()
{
std::map<int, int> 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<std::map<int, int> >() == squares));
return true;
}
TEST StdPair()
{
std::pair<int, std::string> p;
p.first = 5;
p.second = "five";
YAML::Node node;
node["pair"] = p;
YAML_ASSERT((node["pair"].as<std::pair<int, std::string> >() == p));
return true;
}
TEST SimpleAlias()
{
YAML::Node node;
node["foo"] = "value";
node["bar"] = node["foo"];
YAML_ASSERT(node["foo"].as<std::string>() == "value");
YAML_ASSERT(node["bar"].as<std::string>() == "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<std::string>() == "value");
YAML_ASSERT(node[value].as<std::string>() == "foo");
YAML_ASSERT(node["value"].as<std::string>() == "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<std::string>() == "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<std::string>() == "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<std::string>() == "value");
YAML_ASSERT(node["other"].as<std::string>() == "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<bool>() == false);
return true;
}
TEST AutoBoolConversion()
{
YAML::Node node;
node["foo"] = "bar";
YAML_ASSERT(static_cast<bool>(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<std::string>() == "bar");
YAML_ASSERT(node["foo"].as<std::string>("hello") == "bar");
YAML_ASSERT(node["baz"].as<std::string>("hello") == "hello");
YAML_ASSERT(node["x"].as<int>() == 2);
YAML_ASSERT(node["x"].as<int>(5) == 2);
YAML_ASSERT(node["y"].as<int>(5) == 5);
return true;
}
TEST NumericConversion()
{
YAML::Node node = YAML::Load("[1.5, 1, .nan, .inf, -.inf, 0x15, 015]");
YAML_ASSERT(node[0].as<float>() == 1.5f);
YAML_ASSERT(node[0].as<double>() == 1.5);
YAML_ASSERT_THROWS(node[0].as<int>(), YAML::TypedBadConversion<int>);
YAML_ASSERT(node[1].as<int>() == 1);
YAML_ASSERT(node[1].as<float>() == 1.0f);
YAML_ASSERT(node[2].as<float>() != node[2].as<float>());
YAML_ASSERT(node[3].as<float>() == std::numeric_limits<float>::infinity());
YAML_ASSERT(node[4].as<float>() == -std::numeric_limits<float>::infinity());
YAML_ASSERT(node[5].as<int>() == 21);
YAML_ASSERT(node[6].as<int>() == 13);
return true;
}
TEST Binary()
{
YAML::Node node = YAML::Load("[!!binary \"SGVsbG8sIFdvcmxkIQ==\", !!binary \"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4K\"]");
YAML_ASSERT(node[0].as<YAML::Binary>() == YAML::Binary(reinterpret_cast<const unsigned char*>("Hello, World!"), 13));
YAML_ASSERT(node[1].as<YAML::Binary>() == YAML::Binary(reinterpret_cast<const unsigned char*>("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<int>() == 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<char>() + 'A' - 'a' == it->second.as<char>());
}
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<int>() == 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<char>() + 'A' - 'a' == p.second.as<char>());
}
return true;
}
TEST CloneScalar()
{
YAML::Node node = YAML::Load("!foo monkey");
YAML::Node clone = Clone(node);
YAML_ASSERT(!(node == clone));
YAML_ASSERT(node.as<std::string>() == clone.as<std::string>());
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<int>() == clone[i].as<int>());
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<std::string>() == clone["foo"].as<std::string>());
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<std::string>() == "a") {
if(it->second.as<std::string>() == "b")
ab = true;
else if(it->second.as<std::string>() == "5")
a5 = true;
} else if(it->first.as<std::string>() == "x" && it->second.as<std::string>() == "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<int>(), 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<double>() == x);
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);
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);
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;
}
}

View File

@@ -0,0 +1,8 @@
#include "parsertests.h"
namespace Test {
bool RunParserTests()
{
return true;
}
}

1365
test/new-api/spectests.cpp Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -5,18 +5,9 @@
#pragma once
#endif
#include <string>
#include "teststruct.h"
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;
};
namespace Spec {
// 2.1
TEST SeqScalars();

View File

@@ -22,7 +22,10 @@ namespace Test
if(!RunSpecTests())
passed = false;
if(!RunNodeTests())
passed = false;
if(passed)
std::cout << "All tests passed!\n";
}

18
test/teststruct.h Normal file
View File

@@ -0,0 +1,18 @@
#pragma once
#include <string>
#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;
};
}

View File

@@ -1,2 +1,8 @@
add_executable(parse parse.cpp)
target_link_libraries(parse yaml-cpp)
add_executable(sandbox sandbox.cpp)
target_link_libraries(sandbox yaml-cpp)
add_executable(read read.cpp)
target_link_libraries(read yaml-cpp)

View File

@@ -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";
}

30
util/read.cpp Normal file
View File

@@ -0,0 +1,30 @@
#include "yaml-cpp/yaml.h"
#include "yaml-cpp/eventhandler.h"
#include <iostream>
class NullEventHandler: public YAML::EventHandler
{
public:
typedef YAML::Mark Mark;
typedef YAML::anchor_t anchor_t;
NullEventHandler() {}
virtual void OnDocumentStart(const Mark&) {}
virtual void OnDocumentEnd() {}
virtual void OnNull(const Mark&, anchor_t) {}
virtual void OnAlias(const Mark&, anchor_t) {}
virtual void OnScalar(const Mark&, const std::string&, anchor_t, const std::string&) {}
virtual void OnSequenceStart(const Mark&, const std::string&, anchor_t) {}
virtual void OnSequenceEnd() {}
virtual void OnMapStart(const Mark&, const std::string&, anchor_t) {}
virtual void OnMapEnd() {}
};
int main()
{
YAML::Parser parser(std::cin);
NullEventHandler handler;
parser.HandleNextDocument(handler);
return 0;
}

32
util/sandbox.cpp Normal file
View File

@@ -0,0 +1,32 @@
#include "yaml-cpp/yaml.h"
#include "yaml-cpp/eventhandler.h"
#include <iostream>
class NullEventHandler: public YAML::EventHandler
{
public:
typedef YAML::Mark Mark;
typedef YAML::anchor_t anchor_t;
NullEventHandler() {}
virtual void OnDocumentStart(const Mark&) {}
virtual void OnDocumentEnd() {}
virtual void OnNull(const Mark&, anchor_t) {}
virtual void OnAlias(const Mark&, anchor_t) {}
virtual void OnScalar(const Mark&, const std::string&, anchor_t, const std::string&) {}
virtual void OnSequenceStart(const Mark&, const std::string&, anchor_t) {}
virtual void OnSequenceEnd() {}
virtual void OnMapStart(const Mark&, const std::string&, anchor_t) {}
virtual void OnMapEnd() {}
};
int main()
{
std::stringstream stream("---{header: {id: 1");
YAML::Parser parser(stream);
// parser.PrintTokens(std::cout);
NullEventHandler handler;
parser.HandleNextDocument(handler);
return 0;
}