mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2025-09-09 20:51:16 +00:00
Compare commits
53 Commits
release-0.
...
release-0.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
326899815f | ||
![]() |
083a97b171 | ||
![]() |
2226987442 | ||
![]() |
bca7737463 | ||
![]() |
6f40b09525 | ||
![]() |
3a755de572 | ||
![]() |
9718e58120 | ||
![]() |
8723b8f358 | ||
![]() |
03df73a7b0 | ||
![]() |
3307f0941c | ||
![]() |
54b68230ae | ||
![]() |
32491166ac | ||
![]() |
6f94f954bb | ||
![]() |
90fd24d149 | ||
![]() |
9a21a3ec8d | ||
![]() |
3779e4255d | ||
![]() |
ec62dc547e | ||
![]() |
a9b9e1ccec | ||
![]() |
e04be7890a | ||
![]() |
ecb30132e9 | ||
![]() |
52be1ccfb9 | ||
![]() |
3405a6fe01 | ||
![]() |
d372729b92 | ||
![]() |
fadc2ad39f | ||
![]() |
a5607f82a3 | ||
![]() |
f4c683ac22 | ||
![]() |
8c9c9d90da | ||
![]() |
a372bfdc60 | ||
![]() |
fe57829aca | ||
![]() |
b5c53d9e3a | ||
![]() |
f2a2d25ec0 | ||
![]() |
a706ffaf62 | ||
![]() |
8f48e693fe | ||
![]() |
a0bf12e7a1 | ||
![]() |
2314c04d5d | ||
![]() |
22410f46f5 | ||
![]() |
9559a661aa | ||
![]() |
beb524489c | ||
![]() |
4ffb93c12b | ||
![]() |
ae06a40fe6 | ||
![]() |
315b00065b | ||
![]() |
6f02f7556e | ||
![]() |
fa0af88dfe | ||
![]() |
bce845bb1f | ||
![]() |
ed570b9f7c | ||
![]() |
59b0e986bf | ||
![]() |
cffb98d15b | ||
![]() |
3e1ba0f3b4 | ||
![]() |
d0b5bf4b7b | ||
![]() |
7db39e66b8 | ||
![]() |
94eb7f1dbd | ||
![]() |
5733b77b84 | ||
![]() |
98bebfb628 |
@@ -10,16 +10,23 @@ if(IPHONE)
|
|||||||
endif(IPHONE)
|
endif(IPHONE)
|
||||||
|
|
||||||
if(CMAKE_COMPILER_IS_GNUCC)
|
if(CMAKE_COMPILER_IS_GNUCC)
|
||||||
set(CMAKE_CXX_FLAGS "-O2 -Wall -pedantic -Wextra")
|
set(CMAKE_CXX_FLAGS "-O2 -Wall -Wextra -pedantic -Wno-long-long ${CMAKE_CXX_FLAGS}")
|
||||||
endif(CMAKE_COMPILER_IS_GNUCC)
|
endif(CMAKE_COMPILER_IS_GNUCC)
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
set(LIB_TYPE) # I can't figure out how CMake handles Windows shared libraries
|
||||||
|
set(CMAKE_CXX_FLAGS "/W3 /wd4127 /wd4355 /D_SCL_SECURE_NO_WARNINGS ${CMAKE_CXX_FLAGS}")
|
||||||
|
endif(MSVC)
|
||||||
|
|
||||||
set(YAML_CPP_VERSION_MAJOR "0")
|
set(YAML_CPP_VERSION_MAJOR "0")
|
||||||
set(YAML_CPP_VERSION_MINOR "2")
|
set(YAML_CPP_VERSION_MINOR "2")
|
||||||
set(YAML_CPP_VERSION_PATCH "1")
|
set(YAML_CPP_VERSION_PATCH "4")
|
||||||
set(YAML_CPP_VERSION "${YAML_CPP_VERSION_MAJOR}.${YAML_CPP_VERSION_MINOR}.${YAML_CPP_VERSION_PATCH}")
|
set(YAML_CPP_VERSION "${YAML_CPP_VERSION_MAJOR}.${YAML_CPP_VERSION_MINOR}.${YAML_CPP_VERSION_PATCH}")
|
||||||
|
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
|
||||||
|
option(YAML_CPP_BUILD_TOOLS "Enables or disables testing and parse tools" true)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(_library_dir bin) # .dll are in PATH, like executables
|
set(_library_dir bin) # .dll are in PATH, like executables
|
||||||
else(WIN32)
|
else(WIN32)
|
||||||
@@ -36,9 +43,9 @@ set(_INSTALL_DESTINATIONS
|
|||||||
ARCHIVE DESTINATION lib${LIB_SUFFIX}
|
ARCHIVE DESTINATION lib${LIB_SUFFIX}
|
||||||
)
|
)
|
||||||
#
|
#
|
||||||
file(GLOB public_headers include/*.h)
|
file(GLOB public_headers include/[a-z]*.h)
|
||||||
file(GLOB private_headers src/*.h)
|
file(GLOB private_headers src/[a-z]*.h)
|
||||||
file(GLOB sources src/*.cpp)
|
file(GLOB sources src/[a-z]*.cpp)
|
||||||
|
|
||||||
include_directories(${YAML_CPP_SOURCE_DIR}/include)
|
include_directories(${YAML_CPP_SOURCE_DIR}/include)
|
||||||
add_library(yaml-cpp
|
add_library(yaml-cpp
|
||||||
@@ -64,5 +71,7 @@ if(UNIX)
|
|||||||
install(FILES ${PC_FILE} DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
|
install(FILES ${PC_FILE} DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
|
||||||
endif(UNIX)
|
endif(UNIX)
|
||||||
|
|
||||||
add_subdirectory (yaml-reader)
|
if(YAML_CPP_BUILD_TOOLS)
|
||||||
add_subdirectory (util)
|
add_subdirectory (test)
|
||||||
|
add_subdirectory (util)
|
||||||
|
endif(YAML_CPP_BUILD_TOOLS)
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "null.h"
|
#include "null.h"
|
||||||
|
#include "traits.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
@@ -18,26 +19,13 @@ namespace YAML
|
|||||||
bool Convert(const std::string& input, bool& output);
|
bool Convert(const std::string& input, bool& output);
|
||||||
bool Convert(const std::string& input, _Null& output);
|
bool Convert(const std::string& input, _Null& output);
|
||||||
|
|
||||||
#define YAML_MAKE_STREAM_CONVERT(type) \
|
template <typename T>
|
||||||
inline bool Convert(const std::string& input, type& output) { \
|
inline bool Convert(const std::string& input, T& output, typename enable_if<is_numeric<T> >::type * = 0) {
|
||||||
std::stringstream stream(input); \
|
std::stringstream stream(input);
|
||||||
stream >> output; \
|
stream.unsetf(std::ios::dec);
|
||||||
return !stream.fail(); \
|
stream >> output;
|
||||||
|
return !!stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
YAML_MAKE_STREAM_CONVERT(char)
|
|
||||||
YAML_MAKE_STREAM_CONVERT(unsigned char)
|
|
||||||
YAML_MAKE_STREAM_CONVERT(int)
|
|
||||||
YAML_MAKE_STREAM_CONVERT(unsigned int)
|
|
||||||
YAML_MAKE_STREAM_CONVERT(short)
|
|
||||||
YAML_MAKE_STREAM_CONVERT(unsigned short)
|
|
||||||
YAML_MAKE_STREAM_CONVERT(long)
|
|
||||||
YAML_MAKE_STREAM_CONVERT(unsigned long)
|
|
||||||
YAML_MAKE_STREAM_CONVERT(float)
|
|
||||||
YAML_MAKE_STREAM_CONVERT(double)
|
|
||||||
YAML_MAKE_STREAM_CONVERT(long double)
|
|
||||||
|
|
||||||
#undef YAML_MAKE_STREAM_CONVERT
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // CONVERSION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // CONVERSION_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
@@ -1,17 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#ifndef CRT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
|
||||||
#define CRT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
|
||||||
|
|
||||||
|
|
||||||
// for detecting memory leaks
|
|
||||||
#ifdef _DEBUG
|
|
||||||
|
|
||||||
#define _CRTDBG_MAP_ALLOC
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <crtdbg.h>
|
|
||||||
|
|
||||||
#endif // _DEBUG
|
|
||||||
|
|
||||||
|
|
||||||
#endif // CRT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
|
@@ -9,6 +9,7 @@
|
|||||||
#include "null.h"
|
#include "null.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
{
|
{
|
||||||
@@ -29,6 +30,7 @@ namespace YAML
|
|||||||
const std::string GetLastError() const;
|
const std::string GetLastError() const;
|
||||||
|
|
||||||
// global setters
|
// global setters
|
||||||
|
bool SetOutputCharset(EMITTER_MANIP value);
|
||||||
bool SetStringFormat(EMITTER_MANIP value);
|
bool SetStringFormat(EMITTER_MANIP value);
|
||||||
bool SetBoolFormat(EMITTER_MANIP value);
|
bool SetBoolFormat(EMITTER_MANIP value);
|
||||||
bool SetIntBase(EMITTER_MANIP value);
|
bool SetIntBase(EMITTER_MANIP value);
|
||||||
@@ -44,16 +46,23 @@ namespace YAML
|
|||||||
|
|
||||||
// overloads of write
|
// overloads of write
|
||||||
Emitter& Write(const std::string& str);
|
Emitter& Write(const std::string& str);
|
||||||
Emitter& Write(const char *str);
|
|
||||||
Emitter& Write(int i);
|
|
||||||
Emitter& Write(bool b);
|
Emitter& Write(bool b);
|
||||||
Emitter& Write(float f);
|
|
||||||
Emitter& Write(double d);
|
|
||||||
Emitter& Write(const _Alias& alias);
|
Emitter& Write(const _Alias& alias);
|
||||||
Emitter& Write(const _Anchor& anchor);
|
Emitter& Write(const _Anchor& anchor);
|
||||||
|
Emitter& Write(const _Tag& tag);
|
||||||
Emitter& Write(const _Comment& comment);
|
Emitter& Write(const _Comment& comment);
|
||||||
Emitter& Write(const _Null& null);
|
Emitter& Write(const _Null& null);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Emitter& WriteIntegralType(T value);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Emitter& WriteStreamable(T value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void PreWriteIntegralType(std::stringstream& str);
|
||||||
|
void PostWriteIntegralType(const std::stringstream& str);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum ATOMIC_TYPE { AT_SCALAR, AT_SEQ, AT_BLOCK_SEQ, AT_FLOW_SEQ, AT_MAP, AT_BLOCK_MAP, AT_FLOW_MAP };
|
enum ATOMIC_TYPE { AT_SCALAR, AT_SEQ, AT_BLOCK_SEQ, AT_FLOW_SEQ, AT_MAP, AT_BLOCK_MAP, AT_FLOW_MAP };
|
||||||
|
|
||||||
@@ -74,18 +83,61 @@ namespace YAML
|
|||||||
std::auto_ptr <EmitterState> m_pState;
|
std::auto_ptr <EmitterState> m_pState;
|
||||||
};
|
};
|
||||||
|
|
||||||
// overloads of insertion
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline Emitter& operator << (Emitter& emitter, T v) {
|
inline Emitter& Emitter::WriteIntegralType(T value)
|
||||||
return emitter.Write(v);
|
{
|
||||||
|
if(!good())
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
std::stringstream str;
|
||||||
|
PreWriteIntegralType(str);
|
||||||
|
str << value;
|
||||||
|
PostWriteIntegralType(str);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <typename T>
|
||||||
|
inline Emitter& Emitter::WriteStreamable(T value)
|
||||||
|
{
|
||||||
|
if(!good())
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
PreAtomicWrite();
|
||||||
|
EmitSeparationIfNecessary();
|
||||||
|
|
||||||
|
std::stringstream str;
|
||||||
|
str << value;
|
||||||
|
m_stream << str.str();
|
||||||
|
|
||||||
|
PostAtomicWrite();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// overloads of insertion
|
||||||
|
inline Emitter& operator << (Emitter& emitter, const std::string& v) { return emitter.Write(v); }
|
||||||
|
inline Emitter& operator << (Emitter& emitter, bool v) { return emitter.Write(v); }
|
||||||
|
inline Emitter& operator << (Emitter& emitter, const _Alias& v) { return emitter.Write(v); }
|
||||||
|
inline Emitter& operator << (Emitter& emitter, const _Anchor& v) { return emitter.Write(v); }
|
||||||
|
inline Emitter& operator << (Emitter& emitter, const _Tag& v) { return emitter.Write(v); }
|
||||||
|
inline Emitter& operator << (Emitter& emitter, const _Comment& v) { return emitter.Write(v); }
|
||||||
|
inline Emitter& operator << (Emitter& emitter, const _Null& v) { return emitter.Write(v); }
|
||||||
|
|
||||||
|
inline Emitter& operator << (Emitter& emitter, const char *v) { return emitter.Write(std::string(v)); }
|
||||||
|
|
||||||
|
inline Emitter& operator << (Emitter& emitter, int v) { return emitter.WriteIntegralType(v); }
|
||||||
|
inline Emitter& operator << (Emitter& emitter, unsigned int v) { return emitter.WriteIntegralType(v); }
|
||||||
|
inline Emitter& operator << (Emitter& emitter, short v) { return emitter.WriteIntegralType(v); }
|
||||||
|
inline Emitter& operator << (Emitter& emitter, unsigned short v) { return emitter.WriteIntegralType(v); }
|
||||||
|
inline Emitter& operator << (Emitter& emitter, long v) { return emitter.WriteIntegralType(v); }
|
||||||
|
inline Emitter& operator << (Emitter& emitter, unsigned long v) { return emitter.WriteIntegralType(v); }
|
||||||
|
|
||||||
|
inline Emitter& operator << (Emitter& emitter, float v) { return emitter.WriteStreamable(v); }
|
||||||
|
inline Emitter& operator << (Emitter& emitter, double v) { return emitter.WriteStreamable(v); }
|
||||||
|
|
||||||
inline Emitter& operator << (Emitter& emitter, EMITTER_MANIP value) {
|
inline Emitter& operator << (Emitter& emitter, EMITTER_MANIP value) {
|
||||||
return emitter.SetLocalValue(value);
|
return emitter.SetLocalValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
|
||||||
inline Emitter& operator << (Emitter& emitter, _Indent indent) {
|
inline Emitter& operator << (Emitter& emitter, _Indent indent) {
|
||||||
return emitter.SetLocalIndent(indent);
|
return emitter.SetLocalIndent(indent);
|
||||||
}
|
}
|
||||||
|
@@ -12,6 +12,10 @@ namespace YAML
|
|||||||
// general manipulators
|
// general manipulators
|
||||||
Auto,
|
Auto,
|
||||||
|
|
||||||
|
// output character set
|
||||||
|
EmitNonAscii,
|
||||||
|
EscapeNonAscii,
|
||||||
|
|
||||||
// string manipulators
|
// string manipulators
|
||||||
// Auto, // duplicate
|
// Auto, // duplicate
|
||||||
SingleQuoted,
|
SingleQuoted,
|
||||||
@@ -77,6 +81,16 @@ namespace YAML
|
|||||||
return _Anchor(content);
|
return _Anchor(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct _Tag {
|
||||||
|
_Tag(const std::string& content_): content(content_), verbatim(true) {}
|
||||||
|
std::string content;
|
||||||
|
bool verbatim;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline _Tag VerbatimTag(const std::string& content) {
|
||||||
|
return _Tag(content);
|
||||||
|
}
|
||||||
|
|
||||||
struct _Comment {
|
struct _Comment {
|
||||||
_Comment(const std::string& content_): content(content_) {}
|
_Comment(const std::string& content_): content(content_) {}
|
||||||
std::string content;
|
std::string content;
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "mark.h"
|
#include "mark.h"
|
||||||
|
#include "traits.h"
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@@ -17,7 +18,12 @@ namespace YAML
|
|||||||
const std::string YAML_DIRECTIVE_ARGS = "YAML directives must have exactly one argument";
|
const std::string YAML_DIRECTIVE_ARGS = "YAML directives must have exactly one argument";
|
||||||
const std::string YAML_VERSION = "bad YAML version: ";
|
const std::string YAML_VERSION = "bad YAML version: ";
|
||||||
const std::string YAML_MAJOR_VERSION = "YAML major version too large";
|
const std::string YAML_MAJOR_VERSION = "YAML major version too large";
|
||||||
|
const std::string REPEATED_YAML_DIRECTIVE= "repeated YAML directive";
|
||||||
const std::string TAG_DIRECTIVE_ARGS = "TAG directives must have exactly two arguments";
|
const std::string TAG_DIRECTIVE_ARGS = "TAG directives must have exactly two arguments";
|
||||||
|
const std::string REPEATED_TAG_DIRECTIVE = "repeated TAG directive";
|
||||||
|
const std::string CHAR_IN_TAG_HANDLE = "illegal character found while scanning tag handle";
|
||||||
|
const std::string TAG_WITH_NO_SUFFIX = "tag handle with no suffix";
|
||||||
|
const std::string END_OF_VERBATIM_TAG = "end of verbatim tag not found";
|
||||||
const std::string END_OF_MAP = "end of map not found";
|
const std::string END_OF_MAP = "end of map not found";
|
||||||
const std::string END_OF_MAP_FLOW = "end of map flow not found";
|
const std::string END_OF_MAP_FLOW = "end of map flow not found";
|
||||||
const std::string END_OF_SEQ = "end of sequence not found";
|
const std::string END_OF_SEQ = "end of sequence not found";
|
||||||
@@ -57,10 +63,27 @@ namespace YAML
|
|||||||
const std::string SINGLE_QUOTED_CHAR = "invalid character in single-quoted string";
|
const std::string SINGLE_QUOTED_CHAR = "invalid character in single-quoted string";
|
||||||
const std::string INVALID_ANCHOR = "invalid anchor";
|
const std::string INVALID_ANCHOR = "invalid anchor";
|
||||||
const std::string INVALID_ALIAS = "invalid alias";
|
const std::string INVALID_ALIAS = "invalid alias";
|
||||||
|
const std::string INVALID_TAG = "invalid tag";
|
||||||
const std::string EXPECTED_KEY_TOKEN = "expected key token";
|
const std::string EXPECTED_KEY_TOKEN = "expected key token";
|
||||||
const std::string EXPECTED_VALUE_TOKEN = "expected value token";
|
const std::string EXPECTED_VALUE_TOKEN = "expected value token";
|
||||||
const std::string UNEXPECTED_KEY_TOKEN = "unexpected key token";
|
const std::string UNEXPECTED_KEY_TOKEN = "unexpected key token";
|
||||||
const std::string UNEXPECTED_VALUE_TOKEN = "unexpected value token";
|
const std::string UNEXPECTED_VALUE_TOKEN = "unexpected value token";
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline const std::string KEY_NOT_FOUND_WITH_KEY(const T&, typename disable_if<is_numeric<T> >::type * = 0) {
|
||||||
|
return KEY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const std::string KEY_NOT_FOUND_WITH_KEY(const std::string& key) {
|
||||||
|
return KEY_NOT_FOUND + ": " + key;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline const std::string KEY_NOT_FOUND_WITH_KEY(const T& key, typename enable_if<is_numeric<T> >::type * = 0) {
|
||||||
|
std::stringstream stream;
|
||||||
|
stream << KEY_NOT_FOUND << ": " << key;
|
||||||
|
return stream.str();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Exception: public std::exception {
|
class Exception: public std::exception {
|
||||||
@@ -102,22 +125,23 @@ namespace YAML
|
|||||||
|
|
||||||
class KeyNotFound: public RepresentationException {
|
class KeyNotFound: public RepresentationException {
|
||||||
public:
|
public:
|
||||||
KeyNotFound(const Mark& mark_)
|
template <typename T>
|
||||||
: RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND) {}
|
KeyNotFound(const Mark& mark_, const T& key_)
|
||||||
|
: RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class TypedKeyNotFound: public KeyNotFound {
|
class TypedKeyNotFound: public KeyNotFound {
|
||||||
public:
|
public:
|
||||||
TypedKeyNotFound(const Mark& mark_, const T& key_)
|
TypedKeyNotFound(const Mark& mark_, const T& key_)
|
||||||
: KeyNotFound(mark_), key(key_) {}
|
: KeyNotFound(mark_, key_), key(key_) {}
|
||||||
~TypedKeyNotFound() throw() {}
|
virtual ~TypedKeyNotFound() throw() {}
|
||||||
|
|
||||||
T key;
|
T key;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
TypedKeyNotFound <T> MakeTypedKeyNotFound(const Mark& mark, const T& key) {
|
inline TypedKeyNotFound <T> MakeTypedKeyNotFound(const Mark& mark, const T& key) {
|
||||||
return TypedKeyNotFound <T> (mark, key);
|
return TypedKeyNotFound <T> (mark, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -9,7 +9,6 @@
|
|||||||
#include "iterator.h"
|
#include "iterator.h"
|
||||||
#include "mark.h"
|
#include "mark.h"
|
||||||
#include "noncopyable.h"
|
#include "noncopyable.h"
|
||||||
#include "parserstate.h"
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -21,6 +20,7 @@ namespace YAML
|
|||||||
class Content;
|
class Content;
|
||||||
class Scanner;
|
class Scanner;
|
||||||
class Emitter;
|
class Emitter;
|
||||||
|
struct ParserState;
|
||||||
|
|
||||||
enum CONTENT_TYPE { CT_NONE, CT_SCALAR, CT_SEQUENCE, CT_MAP };
|
enum CONTENT_TYPE { CT_NONE, CT_SCALAR, CT_SEQUENCE, CT_MAP };
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ namespace YAML
|
|||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
std::auto_ptr<Node> Clone() const;
|
std::auto_ptr<Node> Clone() const;
|
||||||
void Parse(Scanner *pScanner, const ParserState& state);
|
void Parse(Scanner *pScanner, ParserState& state);
|
||||||
|
|
||||||
CONTENT_TYPE GetType() const;
|
CONTENT_TYPE GetType() const;
|
||||||
|
|
||||||
@@ -76,6 +76,9 @@ namespace YAML
|
|||||||
bool IsAlias() const { return m_alias; }
|
bool IsAlias() const { return m_alias; }
|
||||||
bool IsReferenced() const { return m_referenced; }
|
bool IsReferenced() const { return m_referenced; }
|
||||||
|
|
||||||
|
// for tags
|
||||||
|
const std::string GetTag() const { return IsAlias() ? m_pIdentity->GetTag() : m_tag; }
|
||||||
|
|
||||||
// emitting
|
// emitting
|
||||||
friend Emitter& operator << (Emitter& out, const Node& node);
|
friend Emitter& operator << (Emitter& out, const Node& node);
|
||||||
|
|
||||||
@@ -99,10 +102,10 @@ namespace YAML
|
|||||||
Node(const Mark& mark, const std::string& anchor, const std::string& tag, const Content *pContent);
|
Node(const Mark& mark, const std::string& anchor, const std::string& tag, const Content *pContent);
|
||||||
|
|
||||||
// helpers for parsing
|
// helpers for parsing
|
||||||
void ParseHeader(Scanner *pScanner, const ParserState& state);
|
void ParseHeader(Scanner *pScanner, ParserState& state);
|
||||||
void ParseTag(Scanner *pScanner, const ParserState& state);
|
void ParseTag(Scanner *pScanner, ParserState& state);
|
||||||
void ParseAnchor(Scanner *pScanner, const ParserState& state);
|
void ParseAnchor(Scanner *pScanner, ParserState& state);
|
||||||
void ParseAlias(Scanner *pScanner, const ParserState& state);
|
void ParseAlias(Scanner *pScanner, ParserState& state);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Mark m_mark;
|
Mark m_mark;
|
||||||
|
@@ -79,22 +79,22 @@ namespace YAML
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool operator == (const T& value, const Node& node) {
|
inline bool operator == (const T& value, const Node& node) {
|
||||||
return value == node.Read<T>();
|
return value == node.operator T();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool operator == (const Node& node, const T& value) {
|
inline bool operator == (const Node& node, const T& value) {
|
||||||
return value == node.Read<T>();
|
return value == node.operator T();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool operator != (const T& value, const Node& node) {
|
inline bool operator != (const T& value, const Node& node) {
|
||||||
return value != node.Read<T>();
|
return value != node.operator T();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool operator != (const Node& node, const T& value) {
|
inline bool operator != (const Node& node, const T& value) {
|
||||||
return value != node.Read<T>();
|
return value != node.operator T();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator == (const char *value, const Node& node) {
|
inline bool operator == (const char *value, const Node& node) {
|
||||||
|
@@ -7,6 +7,17 @@ namespace YAML
|
|||||||
// thanks to litb from stackoverflow.com
|
// 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
|
// 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>
|
template<bool>
|
||||||
struct read_impl;
|
struct read_impl;
|
||||||
|
|
||||||
@@ -41,9 +52,10 @@ namespace YAML
|
|||||||
int operator,(flag, flag);
|
int operator,(flag, flag);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void operator,(flag, T const&);
|
char operator,(flag, T const&);
|
||||||
|
|
||||||
char operator,(int, flag);
|
char operator,(int, flag);
|
||||||
|
int operator,(char, flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -52,6 +64,7 @@ namespace YAML
|
|||||||
|
|
||||||
return read_impl<sizeof (fallback::flag(), Convert(std::string(), value), fallback::flag()) != 1>::read(*this, value);
|
return read_impl<sizeof (fallback::flag(), Convert(std::string(), value), fallback::flag()) != 1>::read(*this, value);
|
||||||
}
|
}
|
||||||
|
#endif // done with trick
|
||||||
|
|
||||||
// the main conversion function
|
// the main conversion function
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@@ -4,44 +4,42 @@
|
|||||||
#define PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
|
||||||
|
#include "node.h"
|
||||||
|
#include "noncopyable.h"
|
||||||
#include <ios>
|
#include <ios>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "node.h"
|
#include <memory>
|
||||||
#include "parserstate.h"
|
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
{
|
{
|
||||||
class Scanner;
|
class Scanner;
|
||||||
|
struct ParserState;
|
||||||
struct Token;
|
struct Token;
|
||||||
|
|
||||||
class Parser
|
class Parser: private noncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
Parser();
|
||||||
Parser(std::istream& in);
|
Parser(std::istream& in);
|
||||||
~Parser();
|
~Parser();
|
||||||
|
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
|
|
||||||
void Load(std::istream& in);
|
void Load(std::istream& in);
|
||||||
void GetNextDocument(Node& document);
|
bool GetNextDocument(Node& document);
|
||||||
void PrintTokens(std::ostream& out);
|
void PrintTokens(std::ostream& out);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ParseDirectives();
|
void ParseDirectives();
|
||||||
void HandleDirective(Token *pToken);
|
void HandleDirective(const Token& token);
|
||||||
void HandleYamlDirective(Token *pToken);
|
void HandleYamlDirective(const Token& token);
|
||||||
void HandleTagDirective(Token *pToken);
|
void HandleTagDirective(const Token& token);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// can't copy this
|
std::auto_ptr<Scanner> m_pScanner;
|
||||||
Parser(const Parser&) {}
|
std::auto_ptr<ParserState> m_pState;
|
||||||
Parser& operator = (const Parser&) { return *this; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
Scanner *m_pScanner;
|
|
||||||
ParserState m_state;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,26 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#ifndef PARSERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
|
||||||
#define PARSERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
|
||||||
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
namespace YAML
|
|
||||||
{
|
|
||||||
struct Version {
|
|
||||||
int major, minor;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ParserState
|
|
||||||
{
|
|
||||||
Version version;
|
|
||||||
std::map <std::string, std::string> tags;
|
|
||||||
|
|
||||||
void Reset();
|
|
||||||
std::string TranslateTag(const std::string& handle) const;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // PARSERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
|
36
include/stlnode.h
Normal file
36
include/stlnode.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef STLNODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
#define STLNODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
|
||||||
|
#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
|
50
include/traits.h
Normal file
50
include/traits.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
#define TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
|
||||||
|
namespace YAML
|
||||||
|
{
|
||||||
|
template <typename>
|
||||||
|
struct is_numeric { enum { value = false }; };
|
||||||
|
|
||||||
|
template <> struct is_numeric <char> { enum { value = true }; };
|
||||||
|
template <> struct is_numeric <unsigned char> { enum { value = true }; };
|
||||||
|
template <> struct is_numeric <int> { enum { value = true }; };
|
||||||
|
template <> struct is_numeric <unsigned int> { enum { value = true }; };
|
||||||
|
template <> struct is_numeric <long int> { enum { value = true }; };
|
||||||
|
template <> struct is_numeric <unsigned long int> { enum { value = true }; };
|
||||||
|
template <> struct is_numeric <short int> { enum { value = true }; };
|
||||||
|
template <> struct is_numeric <unsigned short int> { enum { value = true }; };
|
||||||
|
template <> struct is_numeric <long long> { enum { value = true }; };
|
||||||
|
template <> struct is_numeric <unsigned long long> { enum { value = true }; };
|
||||||
|
template <> struct is_numeric <float> { enum { value = true }; };
|
||||||
|
template <> struct is_numeric <double> { enum { value = true }; };
|
||||||
|
template <> struct is_numeric <long double> { enum { value = true }; };
|
||||||
|
|
||||||
|
template <bool, class T = void>
|
||||||
|
struct enable_if_c {
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct enable_if_c<false, T> {};
|
||||||
|
|
||||||
|
template <class Cond, class T = void>
|
||||||
|
struct enable_if : public enable_if_c<Cond::value, T> {};
|
||||||
|
|
||||||
|
template <bool, class T = void>
|
||||||
|
struct disable_if_c {
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct disable_if_c<true, T> {};
|
||||||
|
|
||||||
|
template <class Cond, class T = void>
|
||||||
|
struct disable_if : public disable_if_c<Cond::value, T> {};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
@@ -4,9 +4,9 @@
|
|||||||
#define YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
|
||||||
#include "crt.h"
|
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
|
#include "stlnode.h"
|
||||||
#include "iterator.h"
|
#include "iterator.h"
|
||||||
#include "emitter.h"
|
#include "emitter.h"
|
||||||
#include "stlemitter.h"
|
#include "stlemitter.h"
|
||||||
|
@@ -2,9 +2,9 @@
|
|||||||
<VisualStudioProject
|
<VisualStudioProject
|
||||||
ProjectType="Visual C++"
|
ProjectType="Visual C++"
|
||||||
Version="9.00"
|
Version="9.00"
|
||||||
Name="yaml-reader"
|
Name="parse"
|
||||||
ProjectGUID="{E8CC0D8A-D784-4A6B-B78B-ACEA13F9FB0B}"
|
ProjectGUID="{CD007B57-7812-4930-A5E2-6E5E56338814}"
|
||||||
RootNamespace="yamlreader"
|
RootNamespace="parse"
|
||||||
TargetFrameworkVersion="196613"
|
TargetFrameworkVersion="196613"
|
||||||
>
|
>
|
||||||
<Platforms>
|
<Platforms>
|
||||||
@@ -39,13 +39,15 @@
|
|||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
|
AdditionalOptions="/D_SCL_SECURE_NO_WARNINGS"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
AdditionalIncludeDirectories="include"
|
AdditionalIncludeDirectories="include"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
RuntimeLibrary="3"
|
RuntimeLibrary="3"
|
||||||
WarningLevel="3"
|
WarningLevel="3"
|
||||||
DebugInformationFormat="3"
|
DebugInformationFormat="4"
|
||||||
|
DisableSpecificWarnings="4127;4355"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCManagedResourceCompilerTool"
|
Name="VCManagedResourceCompilerTool"
|
||||||
@@ -110,13 +112,15 @@
|
|||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
|
AdditionalOptions="/D_SCL_SECURE_NO_WARNINGS"
|
||||||
Optimization="2"
|
Optimization="2"
|
||||||
EnableIntrinsicFunctions="true"
|
EnableIntrinsicFunctions="true"
|
||||||
AdditionalIncludeDirectories="include"
|
AdditionalIncludeDirectories="include"
|
||||||
RuntimeLibrary="2"
|
RuntimeLibrary="2"
|
||||||
EnableFunctionLevelLinking="true"
|
EnableFunctionLevelLinking="true"
|
||||||
WarningLevel="4"
|
WarningLevel="3"
|
||||||
DebugInformationFormat="3"
|
DebugInformationFormat="3"
|
||||||
|
DisableSpecificWarnings="4127;4355"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCManagedResourceCompilerTool"
|
Name="VCManagedResourceCompilerTool"
|
||||||
@@ -168,23 +172,7 @@
|
|||||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
>
|
>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\yaml-reader\emittertests.cpp"
|
RelativePath=".\util\parse.cpp"
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\yaml-reader\main.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\yaml-reader\parsertests.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\yaml-reader\spectests.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\yaml-reader\tests.cpp"
|
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
@@ -193,22 +181,12 @@
|
|||||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||||
>
|
>
|
||||||
<File
|
</Filter>
|
||||||
RelativePath=".\yaml-reader\emittertests.h"
|
<Filter
|
||||||
>
|
Name="Resource Files"
|
||||||
</File>
|
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||||
<File
|
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||||
RelativePath=".\yaml-reader\parsertests.h"
|
>
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\yaml-reader\spectests.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\yaml-reader\tests.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
</Filter>
|
</Filter>
|
||||||
</Files>
|
</Files>
|
||||||
<Globals>
|
<Globals>
|
@@ -1,4 +1,3 @@
|
|||||||
#include "crt.h"
|
|
||||||
#include "aliascontent.h"
|
#include "aliascontent.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
@@ -13,7 +12,7 @@ namespace YAML
|
|||||||
return 0; // TODO: how to clone an alias?
|
return 0; // TODO: how to clone an alias?
|
||||||
}
|
}
|
||||||
|
|
||||||
void AliasContent::Parse(Scanner * /*pScanner*/, const ParserState& /*state*/)
|
void AliasContent::Parse(Scanner * /*pScanner*/, ParserState& /*state*/)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -15,7 +15,7 @@ namespace YAML
|
|||||||
|
|
||||||
virtual Content *Clone() const;
|
virtual Content *Clone() const;
|
||||||
|
|
||||||
virtual void Parse(Scanner* pScanner, const ParserState& state);
|
virtual void Parse(Scanner* pScanner, ParserState& state);
|
||||||
virtual void Write(Emitter&) const;
|
virtual void Write(Emitter&) const;
|
||||||
|
|
||||||
virtual bool GetBegin(std::vector <Node *>::const_iterator&) const;
|
virtual bool GetBegin(std::vector <Node *>::const_iterator&) const;
|
||||||
|
@@ -1,13 +0,0 @@
|
|||||||
#include "crt.h"
|
|
||||||
#include "content.h"
|
|
||||||
|
|
||||||
namespace YAML
|
|
||||||
{
|
|
||||||
Content::Content()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Content::~Content()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
@@ -23,12 +23,12 @@ namespace YAML
|
|||||||
class Content
|
class Content
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Content();
|
Content() {}
|
||||||
virtual ~Content();
|
virtual ~Content() {}
|
||||||
|
|
||||||
virtual Content *Clone() const = 0;
|
virtual Content *Clone() const = 0;
|
||||||
|
|
||||||
virtual void Parse(Scanner *pScanner, const ParserState& state) = 0;
|
virtual void Parse(Scanner *pScanner, ParserState& state) = 0;
|
||||||
virtual void Write(Emitter& out) const = 0;
|
virtual void Write(Emitter& out) const = 0;
|
||||||
|
|
||||||
virtual bool GetBegin(std::vector <Node *>::const_iterator&) const { return false; }
|
virtual bool GetBegin(std::vector <Node *>::const_iterator&) const { return false; }
|
||||||
|
130
src/emitter.cpp
130
src/emitter.cpp
@@ -37,6 +37,11 @@ namespace YAML
|
|||||||
}
|
}
|
||||||
|
|
||||||
// global setters
|
// global setters
|
||||||
|
bool Emitter::SetOutputCharset(EMITTER_MANIP value)
|
||||||
|
{
|
||||||
|
return m_pState->SetOutputCharset(value, GLOBAL);
|
||||||
|
}
|
||||||
|
|
||||||
bool Emitter::SetStringFormat(EMITTER_MANIP value)
|
bool Emitter::SetStringFormat(EMITTER_MANIP value)
|
||||||
{
|
{
|
||||||
return m_pState->SetStringFormat(value, GLOBAL);
|
return m_pState->SetStringFormat(value, GLOBAL);
|
||||||
@@ -141,6 +146,8 @@ namespace YAML
|
|||||||
switch(curState) {
|
switch(curState) {
|
||||||
// document-level
|
// document-level
|
||||||
case ES_WAITING_FOR_DOC:
|
case ES_WAITING_FOR_DOC:
|
||||||
|
m_stream << "---";
|
||||||
|
m_pState->RequireSeparation();
|
||||||
m_pState->SwitchState(ES_WRITING_DOC);
|
m_pState->SwitchState(ES_WRITING_DOC);
|
||||||
return true;
|
return true;
|
||||||
case ES_WRITING_DOC:
|
case ES_WRITING_DOC:
|
||||||
@@ -318,7 +325,10 @@ namespace YAML
|
|||||||
EMITTER_STATE curState = m_pState->GetCurState();
|
EMITTER_STATE curState = m_pState->GetCurState();
|
||||||
EMITTER_MANIP flowType = m_pState->GetFlowType(GT_SEQ);
|
EMITTER_MANIP flowType = m_pState->GetFlowType(GT_SEQ);
|
||||||
if(flowType == Block) {
|
if(flowType == Block) {
|
||||||
if(curState == ES_WRITING_BLOCK_SEQ_ENTRY || curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE) {
|
if(curState == ES_WRITING_BLOCK_SEQ_ENTRY ||
|
||||||
|
curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE ||
|
||||||
|
curState == ES_WRITING_DOC
|
||||||
|
) {
|
||||||
m_stream << "\n";
|
m_stream << "\n";
|
||||||
m_pState->UnsetSeparation();
|
m_pState->UnsetSeparation();
|
||||||
}
|
}
|
||||||
@@ -344,12 +354,22 @@ namespace YAML
|
|||||||
|
|
||||||
EMITTER_STATE curState = m_pState->GetCurState();
|
EMITTER_STATE curState = m_pState->GetCurState();
|
||||||
FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
|
FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
|
||||||
if(flowType == FT_BLOCK)
|
if(flowType == FT_BLOCK) {
|
||||||
assert(curState == ES_DONE_WITH_BLOCK_SEQ_ENTRY);
|
// Note: block sequences are *not* allowed to be empty, but we convert it
|
||||||
else if(flowType == FT_FLOW) {
|
// to a flow sequence if it is
|
||||||
m_stream << "]";
|
assert(curState == ES_DONE_WITH_BLOCK_SEQ_ENTRY || curState == ES_WAITING_FOR_BLOCK_SEQ_ENTRY);
|
||||||
|
if(curState == ES_WAITING_FOR_BLOCK_SEQ_ENTRY) {
|
||||||
|
// Note: only one of these will actually output anything for a given situation
|
||||||
|
EmitSeparationIfNecessary();
|
||||||
|
unsigned curIndent = m_pState->GetCurIndent();
|
||||||
|
m_stream << IndentTo(curIndent);
|
||||||
|
|
||||||
|
m_stream << "[]";
|
||||||
|
}
|
||||||
|
} else if(flowType == FT_FLOW) {
|
||||||
// Note: flow sequences are allowed to be empty
|
// Note: flow sequences are allowed to be empty
|
||||||
assert(curState == ES_DONE_WITH_FLOW_SEQ_ENTRY || curState == ES_WAITING_FOR_FLOW_SEQ_ENTRY);
|
assert(curState == ES_DONE_WITH_FLOW_SEQ_ENTRY || curState == ES_WAITING_FOR_FLOW_SEQ_ENTRY);
|
||||||
|
m_stream << "]";
|
||||||
} else
|
} else
|
||||||
assert(false);
|
assert(false);
|
||||||
|
|
||||||
@@ -373,7 +393,10 @@ namespace YAML
|
|||||||
EMITTER_STATE curState = m_pState->GetCurState();
|
EMITTER_STATE curState = m_pState->GetCurState();
|
||||||
EMITTER_MANIP flowType = m_pState->GetFlowType(GT_MAP);
|
EMITTER_MANIP flowType = m_pState->GetFlowType(GT_MAP);
|
||||||
if(flowType == Block) {
|
if(flowType == Block) {
|
||||||
if(curState == ES_WRITING_BLOCK_SEQ_ENTRY || curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE) {
|
if(curState == ES_WRITING_BLOCK_SEQ_ENTRY ||
|
||||||
|
curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE ||
|
||||||
|
curState == ES_WRITING_DOC
|
||||||
|
) {
|
||||||
m_stream << "\n";
|
m_stream << "\n";
|
||||||
m_pState->UnsetSeparation();
|
m_pState->UnsetSeparation();
|
||||||
}
|
}
|
||||||
@@ -399,12 +422,21 @@ namespace YAML
|
|||||||
|
|
||||||
EMITTER_STATE curState = m_pState->GetCurState();
|
EMITTER_STATE curState = m_pState->GetCurState();
|
||||||
FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
|
FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
|
||||||
if(flowType == FT_BLOCK)
|
if(flowType == FT_BLOCK) {
|
||||||
assert(curState == ES_DONE_WITH_BLOCK_MAP_VALUE);
|
// Note: block sequences are *not* allowed to be empty, but we convert it
|
||||||
else if(flowType == FT_FLOW) {
|
// to a flow sequence if it is
|
||||||
m_stream << "}";
|
assert(curState == ES_DONE_WITH_BLOCK_MAP_VALUE || curState == ES_WAITING_FOR_BLOCK_MAP_ENTRY);
|
||||||
|
if(curState == ES_WAITING_FOR_BLOCK_MAP_ENTRY) {
|
||||||
|
// Note: only one of these will actually output anything for a given situation
|
||||||
|
EmitSeparationIfNecessary();
|
||||||
|
unsigned curIndent = m_pState->GetCurIndent();
|
||||||
|
m_stream << IndentTo(curIndent);
|
||||||
|
m_stream << "{}";
|
||||||
|
}
|
||||||
|
} else if(flowType == FT_FLOW) {
|
||||||
// Note: flow maps are allowed to be empty
|
// Note: flow maps are allowed to be empty
|
||||||
assert(curState == ES_DONE_WITH_FLOW_MAP_VALUE || curState == ES_WAITING_FOR_FLOW_MAP_ENTRY);
|
assert(curState == ES_DONE_WITH_FLOW_MAP_VALUE || curState == ES_WAITING_FOR_FLOW_MAP_ENTRY);
|
||||||
|
m_stream << "}";
|
||||||
} else
|
} else
|
||||||
assert(false);
|
assert(false);
|
||||||
|
|
||||||
@@ -485,13 +517,14 @@ namespace YAML
|
|||||||
PreAtomicWrite();
|
PreAtomicWrite();
|
||||||
EmitSeparationIfNecessary();
|
EmitSeparationIfNecessary();
|
||||||
|
|
||||||
|
bool escapeNonAscii = m_pState->GetOutputCharset() == EscapeNonAscii;
|
||||||
EMITTER_MANIP strFmt = m_pState->GetStringFormat();
|
EMITTER_MANIP strFmt = m_pState->GetStringFormat();
|
||||||
FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
|
FLOW_TYPE flowType = m_pState->GetCurGroupFlowType();
|
||||||
unsigned curIndent = m_pState->GetCurIndent();
|
unsigned curIndent = m_pState->GetCurIndent();
|
||||||
|
|
||||||
switch(strFmt) {
|
switch(strFmt) {
|
||||||
case Auto:
|
case Auto:
|
||||||
Utils::WriteString(m_stream, str, flowType == FT_FLOW);
|
Utils::WriteString(m_stream, str, flowType == FT_FLOW, escapeNonAscii);
|
||||||
break;
|
break;
|
||||||
case SingleQuoted:
|
case SingleQuoted:
|
||||||
if(!Utils::WriteSingleQuotedString(m_stream, str)) {
|
if(!Utils::WriteSingleQuotedString(m_stream, str)) {
|
||||||
@@ -500,11 +533,11 @@ namespace YAML
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DoubleQuoted:
|
case DoubleQuoted:
|
||||||
Utils::WriteDoubleQuotedString(m_stream, str);
|
Utils::WriteDoubleQuotedString(m_stream, str, escapeNonAscii);
|
||||||
break;
|
break;
|
||||||
case Literal:
|
case Literal:
|
||||||
if(flowType == FT_FLOW)
|
if(flowType == FT_FLOW)
|
||||||
Utils::WriteString(m_stream, str, flowType == FT_FLOW);
|
Utils::WriteString(m_stream, str, flowType == FT_FLOW, escapeNonAscii);
|
||||||
else
|
else
|
||||||
Utils::WriteLiteralString(m_stream, str, curIndent + m_pState->GetIndent());
|
Utils::WriteLiteralString(m_stream, str, curIndent + m_pState->GetIndent());
|
||||||
break;
|
break;
|
||||||
@@ -516,24 +549,12 @@ namespace YAML
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Emitter& Emitter::Write(const char *str)
|
void Emitter::PreWriteIntegralType(std::stringstream& str)
|
||||||
{
|
{
|
||||||
if(!good())
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
return Write(std::string(str));
|
|
||||||
}
|
|
||||||
|
|
||||||
Emitter& Emitter::Write(int i)
|
|
||||||
{
|
|
||||||
if(!good())
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
PreAtomicWrite();
|
PreAtomicWrite();
|
||||||
EmitSeparationIfNecessary();
|
EmitSeparationIfNecessary();
|
||||||
|
|
||||||
EMITTER_MANIP intFmt = m_pState->GetIntFormat();
|
EMITTER_MANIP intFmt = m_pState->GetIntFormat();
|
||||||
std::stringstream str;
|
|
||||||
switch(intFmt) {
|
switch(intFmt) {
|
||||||
case Dec:
|
case Dec:
|
||||||
str << std::dec;
|
str << std::dec;
|
||||||
@@ -541,18 +562,18 @@ namespace YAML
|
|||||||
case Hex:
|
case Hex:
|
||||||
str << std::hex;
|
str << std::hex;
|
||||||
break;
|
break;
|
||||||
case Oct:
|
case Oct:
|
||||||
str << std::oct;
|
str << std::oct;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
str << i;
|
void Emitter::PostWriteIntegralType(const std::stringstream& str)
|
||||||
|
{
|
||||||
m_stream << str.str();
|
m_stream << str.str();
|
||||||
|
|
||||||
PostAtomicWrite();
|
PostAtomicWrite();
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Emitter& Emitter::Write(bool b)
|
Emitter& Emitter::Write(bool b)
|
||||||
@@ -594,38 +615,6 @@ namespace YAML
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Emitter& Emitter::Write(float f)
|
|
||||||
{
|
|
||||||
if(!good())
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
PreAtomicWrite();
|
|
||||||
EmitSeparationIfNecessary();
|
|
||||||
|
|
||||||
std::stringstream str;
|
|
||||||
str << f;
|
|
||||||
m_stream << str.str();
|
|
||||||
|
|
||||||
PostAtomicWrite();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Emitter& Emitter::Write(double d)
|
|
||||||
{
|
|
||||||
if(!good())
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
PreAtomicWrite();
|
|
||||||
EmitSeparationIfNecessary();
|
|
||||||
|
|
||||||
std::stringstream str;
|
|
||||||
str << d;
|
|
||||||
m_stream << str.str();
|
|
||||||
|
|
||||||
PostAtomicWrite();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Emitter& Emitter::Write(const _Alias& alias)
|
Emitter& Emitter::Write(const _Alias& alias)
|
||||||
{
|
{
|
||||||
if(!good())
|
if(!good())
|
||||||
@@ -657,6 +646,22 @@ namespace YAML
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Emitter& Emitter::Write(const _Tag& tag)
|
||||||
|
{
|
||||||
|
if(!good())
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
PreAtomicWrite();
|
||||||
|
EmitSeparationIfNecessary();
|
||||||
|
if(!Utils::WriteTag(m_stream, tag.content)) {
|
||||||
|
m_pState->SetError(ErrorMsg::INVALID_TAG);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
m_pState->RequireSeparation();
|
||||||
|
// Note: no PostAtomicWrite() because we need another value for this node
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
Emitter& Emitter::Write(const _Comment& comment)
|
Emitter& Emitter::Write(const _Comment& comment)
|
||||||
{
|
{
|
||||||
if(!good())
|
if(!good())
|
||||||
@@ -679,3 +684,4 @@ namespace YAML
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -9,6 +9,7 @@ namespace YAML
|
|||||||
m_stateStack.push(ES_WAITING_FOR_DOC);
|
m_stateStack.push(ES_WAITING_FOR_DOC);
|
||||||
|
|
||||||
// set default global manipulators
|
// set default global manipulators
|
||||||
|
m_charset.set(EmitNonAscii);
|
||||||
m_strFmt.set(Auto);
|
m_strFmt.set(Auto);
|
||||||
m_boolFmt.set(TrueFalseBool);
|
m_boolFmt.set(TrueFalseBool);
|
||||||
m_boolLengthFmt.set(LongBool);
|
m_boolLengthFmt.set(LongBool);
|
||||||
@@ -43,6 +44,7 @@ namespace YAML
|
|||||||
// . Only the ones that make sense will be accepted
|
// . Only the ones that make sense will be accepted
|
||||||
void EmitterState::SetLocalValue(EMITTER_MANIP value)
|
void EmitterState::SetLocalValue(EMITTER_MANIP value)
|
||||||
{
|
{
|
||||||
|
SetOutputCharset(value, LOCAL);
|
||||||
SetStringFormat(value, LOCAL);
|
SetStringFormat(value, LOCAL);
|
||||||
SetBoolFormat(value, LOCAL);
|
SetBoolFormat(value, LOCAL);
|
||||||
SetBoolCaseFormat(value, LOCAL);
|
SetBoolCaseFormat(value, LOCAL);
|
||||||
@@ -133,6 +135,18 @@ namespace YAML
|
|||||||
m_modifiedSettings.clear();
|
m_modifiedSettings.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EmitterState::SetOutputCharset(EMITTER_MANIP value, FMT_SCOPE scope)
|
||||||
|
{
|
||||||
|
switch(value) {
|
||||||
|
case EmitNonAscii:
|
||||||
|
case EscapeNonAscii:
|
||||||
|
_Set(m_charset, value, scope);
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool EmitterState::SetStringFormat(EMITTER_MANIP value, FMT_SCOPE scope)
|
bool EmitterState::SetStringFormat(EMITTER_MANIP value, FMT_SCOPE scope)
|
||||||
{
|
{
|
||||||
switch(value) {
|
switch(value) {
|
||||||
|
@@ -108,6 +108,9 @@ namespace YAML
|
|||||||
void ClearModifiedSettings();
|
void ClearModifiedSettings();
|
||||||
|
|
||||||
// formatters
|
// formatters
|
||||||
|
bool SetOutputCharset(EMITTER_MANIP value, FMT_SCOPE scope);
|
||||||
|
EMITTER_MANIP GetOutputCharset() const { return m_charset.get(); }
|
||||||
|
|
||||||
bool SetStringFormat(EMITTER_MANIP value, FMT_SCOPE scope);
|
bool SetStringFormat(EMITTER_MANIP value, FMT_SCOPE scope);
|
||||||
EMITTER_MANIP GetStringFormat() const { return m_strFmt.get(); }
|
EMITTER_MANIP GetStringFormat() const { return m_strFmt.get(); }
|
||||||
|
|
||||||
@@ -149,6 +152,7 @@ namespace YAML
|
|||||||
// other state
|
// other state
|
||||||
std::stack <EMITTER_STATE> m_stateStack;
|
std::stack <EMITTER_STATE> m_stateStack;
|
||||||
|
|
||||||
|
Setting <EMITTER_MANIP> m_charset;
|
||||||
Setting <EMITTER_MANIP> m_strFmt;
|
Setting <EMITTER_MANIP> m_strFmt;
|
||||||
Setting <EMITTER_MANIP> m_boolFmt;
|
Setting <EMITTER_MANIP> m_boolFmt;
|
||||||
Setting <EMITTER_MANIP> m_boolLengthFmt;
|
Setting <EMITTER_MANIP> m_boolLengthFmt;
|
||||||
|
@@ -11,13 +11,125 @@ namespace YAML
|
|||||||
namespace Utils
|
namespace Utils
|
||||||
{
|
{
|
||||||
namespace {
|
namespace {
|
||||||
bool IsPrintable(char ch) {
|
enum {REPLACEMENT_CHARACTER = 0xFFFD};
|
||||||
return (0x20 <= ch && ch <= 0x7E);
|
|
||||||
|
bool IsAnchorChar(int ch) { // test for ns-anchor-char
|
||||||
|
switch (ch) {
|
||||||
|
case ',': case '[': case ']': case '{': case '}': // c-flow-indicator
|
||||||
|
case ' ': case '\t': // s-white
|
||||||
|
case 0xFEFF: // c-byte-order-mark
|
||||||
|
case 0xA: case 0xD: // b-char
|
||||||
|
return false;
|
||||||
|
case 0x85:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch < 0x20)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ch < 0x7E)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (ch < 0xA0)
|
||||||
|
return false;
|
||||||
|
if (ch >= 0xD800 && ch <= 0xDFFF)
|
||||||
|
return false;
|
||||||
|
if ((ch & 0xFFFE) == 0xFFFE)
|
||||||
|
return false;
|
||||||
|
if ((ch >= 0xFDD0) && (ch <= 0xFDEF))
|
||||||
|
return false;
|
||||||
|
if (ch > 0x10FFFF)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsValidPlainScalar(const std::string& str, bool inFlow) {
|
int Utf8BytesIndicated(char ch) {
|
||||||
|
int byteVal = static_cast<unsigned char>(ch);
|
||||||
|
switch (byteVal >> 4) {
|
||||||
|
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
|
||||||
|
return 1;
|
||||||
|
case 12: case 13:
|
||||||
|
return 2;
|
||||||
|
case 14:
|
||||||
|
return 3;
|
||||||
|
case 15:
|
||||||
|
return 4;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsTrailingByte(char ch) {
|
||||||
|
return (ch & 0xC0) == 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetNextCodePointAndAdvance(int& codePoint, std::string::const_iterator& first, std::string::const_iterator last) {
|
||||||
|
if (first == last)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int nBytes = Utf8BytesIndicated(*first);
|
||||||
|
if (nBytes < 1) {
|
||||||
|
// Bad lead byte
|
||||||
|
++first;
|
||||||
|
codePoint = REPLACEMENT_CHARACTER;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nBytes == 1) {
|
||||||
|
codePoint = *first++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gather bits from trailing bytes
|
||||||
|
codePoint = static_cast<unsigned char>(*first) & ~(0xFF << (7 - nBytes));
|
||||||
|
++first;
|
||||||
|
--nBytes;
|
||||||
|
for (; nBytes > 0; ++first, --nBytes) {
|
||||||
|
if ((first == last) || !IsTrailingByte(*first)) {
|
||||||
|
codePoint = REPLACEMENT_CHARACTER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
codePoint <<= 6;
|
||||||
|
codePoint |= *first & 0x3F;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for illegal code points
|
||||||
|
if (codePoint > 0x10FFFF)
|
||||||
|
codePoint = REPLACEMENT_CHARACTER;
|
||||||
|
else if (codePoint >= 0xD800 && codePoint <= 0xDFFF)
|
||||||
|
codePoint = REPLACEMENT_CHARACTER;
|
||||||
|
else if ((codePoint & 0xFFFE) == 0xFFFE)
|
||||||
|
codePoint = REPLACEMENT_CHARACTER;
|
||||||
|
else if (codePoint >= 0xFDD0 && codePoint <= 0xFDEF)
|
||||||
|
codePoint = REPLACEMENT_CHARACTER;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteCodePoint(ostream& out, int codePoint) {
|
||||||
|
if (codePoint < 0 || codePoint > 0x10FFFF) {
|
||||||
|
codePoint = REPLACEMENT_CHARACTER;
|
||||||
|
}
|
||||||
|
if (codePoint < 0x7F) {
|
||||||
|
out << static_cast<char>(codePoint);
|
||||||
|
} else if (codePoint < 0x7FF) {
|
||||||
|
out << static_cast<char>(0xC0 | (codePoint >> 6))
|
||||||
|
<< static_cast<char>(0x80 | (codePoint & 0x3F));
|
||||||
|
} else if (codePoint < 0xFFFF) {
|
||||||
|
out << static_cast<char>(0xE0 | (codePoint >> 12))
|
||||||
|
<< static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F))
|
||||||
|
<< static_cast<char>(0x80 | (codePoint & 0x3F));
|
||||||
|
} else {
|
||||||
|
out << static_cast<char>(0xF0 | (codePoint >> 18))
|
||||||
|
<< static_cast<char>(0x80 | ((codePoint >> 12) & 0x3F))
|
||||||
|
<< static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F))
|
||||||
|
<< static_cast<char>(0x80 | (codePoint & 0x3F));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsValidPlainScalar(const std::string& str, bool inFlow, bool allowOnlyAscii) {
|
||||||
// first check the start
|
// first check the start
|
||||||
const RegEx& start = (inFlow ? Exp::PlainScalarInFlow : Exp::PlainScalar);
|
const RegEx& start = (inFlow ? Exp::PlainScalarInFlow() : Exp::PlainScalar());
|
||||||
if(!start.Matches(str))
|
if(!start.Matches(str))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -26,66 +138,111 @@ namespace YAML
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// then check until something is disallowed
|
// then check until something is disallowed
|
||||||
const RegEx& disallowed = (inFlow ? Exp::EndScalarInFlow : Exp::EndScalar)
|
const RegEx& disallowed = (inFlow ? Exp::EndScalarInFlow() : Exp::EndScalar())
|
||||||
|| (Exp::BlankOrBreak + Exp::Comment)
|
|| (Exp::BlankOrBreak() + Exp::Comment())
|
||||||
|| (!Exp::Printable)
|
|| Exp::NotPrintable()
|
||||||
|| Exp::Break
|
|| Exp::Utf8_ByteOrderMark()
|
||||||
|| Exp::Tab;
|
|| Exp::Break()
|
||||||
|
|| Exp::Tab();
|
||||||
StringCharSource buffer(str.c_str(), str.size());
|
StringCharSource buffer(str.c_str(), str.size());
|
||||||
while(buffer) {
|
while(buffer) {
|
||||||
if(disallowed.Matches(buffer))
|
if(disallowed.Matches(buffer))
|
||||||
return false;
|
return false;
|
||||||
|
if(allowOnlyAscii && (0x7F < static_cast<unsigned char>(buffer[0])))
|
||||||
|
return false;
|
||||||
++buffer;
|
++buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WriteDoubleQuoteEscapeSequence(ostream& out, int codePoint) {
|
||||||
|
static const char hexDigits[] = "0123456789abcdef";
|
||||||
|
|
||||||
|
char escSeq[] = "\\U00000000";
|
||||||
|
int digits = 8;
|
||||||
|
if (codePoint < 0xFF) {
|
||||||
|
escSeq[1] = 'x';
|
||||||
|
digits = 2;
|
||||||
|
} else if (codePoint < 0xFFFF) {
|
||||||
|
escSeq[1] = 'u';
|
||||||
|
digits = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteAliasName(ostream& out, const std::string& str) {
|
||||||
|
int codePoint;
|
||||||
|
for(std::string::const_iterator i = str.begin();
|
||||||
|
GetNextCodePointAndAdvance(codePoint, i, str.end());
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!IsAnchorChar(codePoint))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
WriteCodePoint(out, codePoint);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteString(ostream& out, const std::string& str, bool inFlow)
|
bool WriteString(ostream& out, const std::string& str, bool inFlow, bool escapeNonAscii)
|
||||||
{
|
{
|
||||||
if(IsValidPlainScalar(str, inFlow)) {
|
if(IsValidPlainScalar(str, inFlow, escapeNonAscii)) {
|
||||||
out << str;
|
out << str;
|
||||||
return true;
|
return true;
|
||||||
} else
|
} else
|
||||||
return WriteDoubleQuotedString(out, str);
|
return WriteDoubleQuotedString(out, str, escapeNonAscii);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteSingleQuotedString(ostream& out, const std::string& str)
|
bool WriteSingleQuotedString(ostream& out, const std::string& str)
|
||||||
{
|
{
|
||||||
out << "'";
|
out << "'";
|
||||||
for(std::size_t i=0;i<str.size();i++) {
|
int codePoint;
|
||||||
char ch = str[i];
|
for(std::string::const_iterator i = str.begin();
|
||||||
if(!IsPrintable(ch))
|
GetNextCodePointAndAdvance(codePoint, i, str.end());
|
||||||
return false;
|
)
|
||||||
|
{
|
||||||
|
if (codePoint == '\n')
|
||||||
|
return false; // We can't handle a new line and the attendant indentation yet
|
||||||
|
|
||||||
if(ch == '\'')
|
if (codePoint == '\'')
|
||||||
out << "''";
|
out << "''";
|
||||||
else
|
else
|
||||||
out << ch;
|
WriteCodePoint(out, codePoint);
|
||||||
}
|
}
|
||||||
out << "'";
|
out << "'";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteDoubleQuotedString(ostream& out, const std::string& str)
|
bool WriteDoubleQuotedString(ostream& out, const std::string& str, bool escapeNonAscii)
|
||||||
{
|
{
|
||||||
out << "\"";
|
out << "\"";
|
||||||
for(std::size_t i=0;i<str.size();i++) {
|
int codePoint;
|
||||||
char ch = str[i];
|
for(std::string::const_iterator i = str.begin();
|
||||||
if(IsPrintable(ch)) {
|
GetNextCodePointAndAdvance(codePoint, i, str.end());
|
||||||
if(ch == '\"')
|
)
|
||||||
out << "\\\"";
|
{
|
||||||
else if(ch == '\\')
|
if (codePoint == '\"')
|
||||||
out << "\\\\";
|
out << "\\\"";
|
||||||
else
|
else if (codePoint == '\\')
|
||||||
out << ch;
|
out << "\\\\";
|
||||||
} else {
|
else if (codePoint < 0x20 || (codePoint >= 0x80 && codePoint <= 0xA0)) // Control characters and non-breaking space
|
||||||
// TODO: for the common escaped characters, give their usual symbol
|
WriteDoubleQuoteEscapeSequence(out, codePoint);
|
||||||
std::stringstream str;
|
else if (codePoint == 0xFEFF) // Byte order marks (ZWNS) should be escaped (YAML 1.2, sec. 5.2)
|
||||||
str << "\\x" << std::hex << std::setfill('0') << std::setw(2) << static_cast<unsigned int>(static_cast<unsigned char>(ch));
|
WriteDoubleQuoteEscapeSequence(out, codePoint);
|
||||||
out << str.str();
|
else if (escapeNonAscii && codePoint > 0x7E)
|
||||||
}
|
WriteDoubleQuoteEscapeSequence(out, codePoint);
|
||||||
|
else
|
||||||
|
WriteCodePoint(out, codePoint);
|
||||||
}
|
}
|
||||||
out << "\"";
|
out << "\"";
|
||||||
return true;
|
return true;
|
||||||
@@ -95,11 +252,15 @@ namespace YAML
|
|||||||
{
|
{
|
||||||
out << "|\n";
|
out << "|\n";
|
||||||
out << IndentTo(indent);
|
out << IndentTo(indent);
|
||||||
for(std::size_t i=0;i<str.size();i++) {
|
int codePoint;
|
||||||
if(str[i] == '\n')
|
for(std::string::const_iterator i = str.begin();
|
||||||
out << "\n" << IndentTo(indent);
|
GetNextCodePointAndAdvance(codePoint, i, str.end());
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (codePoint == '\n')
|
||||||
|
out << "\n" << IndentTo(indent);
|
||||||
else
|
else
|
||||||
out << str[i];
|
WriteCodePoint(out, codePoint);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -108,11 +269,15 @@ namespace YAML
|
|||||||
{
|
{
|
||||||
unsigned curIndent = out.col();
|
unsigned curIndent = out.col();
|
||||||
out << "#" << Indentation(postCommentIndent);
|
out << "#" << Indentation(postCommentIndent);
|
||||||
for(std::size_t i=0;i<str.size();i++) {
|
int codePoint;
|
||||||
if(str[i] == '\n')
|
for(std::string::const_iterator i = str.begin();
|
||||||
|
GetNextCodePointAndAdvance(codePoint, i, str.end());
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if(codePoint == '\n')
|
||||||
out << "\n" << IndentTo(curIndent) << "#" << Indentation(postCommentIndent);
|
out << "\n" << IndentTo(curIndent) << "#" << Indentation(postCommentIndent);
|
||||||
else
|
else
|
||||||
out << str[i];
|
WriteCodePoint(out, codePoint);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -120,24 +285,30 @@ namespace YAML
|
|||||||
bool WriteAlias(ostream& out, const std::string& str)
|
bool WriteAlias(ostream& out, const std::string& str)
|
||||||
{
|
{
|
||||||
out << "*";
|
out << "*";
|
||||||
for(std::size_t i=0;i<str.size();i++) {
|
return WriteAliasName(out, str);
|
||||||
if(!IsPrintable(str[i]) || str[i] == ' ' || str[i] == '\t' || str[i] == '\n' || str[i] == '\r')
|
|
||||||
return false;
|
|
||||||
|
|
||||||
out << str[i];
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteAnchor(ostream& out, const std::string& str)
|
bool WriteAnchor(ostream& out, const std::string& str)
|
||||||
{
|
{
|
||||||
out << "&";
|
out << "&";
|
||||||
for(std::size_t i=0;i<str.size();i++) {
|
return WriteAliasName(out, str);
|
||||||
if(!IsPrintable(str[i]) || str[i] == ' ' || str[i] == '\t' || str[i] == '\n' || str[i] == '\r')
|
}
|
||||||
|
|
||||||
|
bool WriteTag(ostream& out, const std::string& str)
|
||||||
|
{
|
||||||
|
out << "!<";
|
||||||
|
StringCharSource buffer(str.c_str(), str.size());
|
||||||
|
while(buffer) {
|
||||||
|
int n = Exp::URI().Match(buffer);
|
||||||
|
if(n <= 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
out << str[i];
|
while(--n >= 0) {
|
||||||
|
out << buffer[0];
|
||||||
|
++buffer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
out << ">";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -11,13 +11,14 @@ namespace YAML
|
|||||||
{
|
{
|
||||||
namespace Utils
|
namespace Utils
|
||||||
{
|
{
|
||||||
bool WriteString(ostream& out, const std::string& str, bool inFlow);
|
bool WriteString(ostream& out, const std::string& str, bool inFlow, bool escapeNonAscii);
|
||||||
bool WriteSingleQuotedString(ostream& out, const std::string& str);
|
bool WriteSingleQuotedString(ostream& out, const std::string& str);
|
||||||
bool WriteDoubleQuotedString(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 WriteLiteralString(ostream& out, const std::string& str, int indent);
|
||||||
bool WriteComment(ostream& out, const std::string& str, int postCommentIndent);
|
bool WriteComment(ostream& out, const std::string& str, int postCommentIndent);
|
||||||
bool WriteAlias(ostream& out, const std::string& str);
|
bool WriteAlias(ostream& out, const std::string& str);
|
||||||
bool WriteAnchor(ostream& out, const std::string& str);
|
bool WriteAnchor(ostream& out, const std::string& str);
|
||||||
|
bool WriteTag(ostream& out, const std::string& str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
#include "crt.h"
|
|
||||||
#include "exp.h"
|
#include "exp.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@@ -28,9 +27,9 @@ namespace YAML
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Str(char ch)
|
std::string Str(unsigned ch)
|
||||||
{
|
{
|
||||||
return std::string("") + ch;
|
return std::string(1, static_cast<char>(ch));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Escape
|
// Escape
|
||||||
|
166
src/exp.h
166
src/exp.h
@@ -17,45 +17,153 @@ namespace YAML
|
|||||||
namespace Exp
|
namespace Exp
|
||||||
{
|
{
|
||||||
// misc
|
// misc
|
||||||
const RegEx Space = RegEx(' ');
|
inline const RegEx& Space() {
|
||||||
const RegEx Tab = RegEx('\t');
|
static const RegEx e = RegEx(' ');
|
||||||
const RegEx Blank = Space || Tab;
|
return e;
|
||||||
const RegEx Break = RegEx('\n') || RegEx("\r\n");
|
}
|
||||||
const RegEx BlankOrBreak = Blank || Break;
|
inline const RegEx& Tab() {
|
||||||
const RegEx Digit = RegEx('0', '9');
|
static const RegEx e = RegEx('\t');
|
||||||
const RegEx Alpha = RegEx('a', 'z') || RegEx('A', 'Z');
|
return e;
|
||||||
const RegEx AlphaNumeric = Alpha || Digit;
|
}
|
||||||
const RegEx Hex = Digit || RegEx('A', 'F') || RegEx('a', 'f');
|
inline const RegEx& Blank() {
|
||||||
const RegEx Printable = RegEx(0x20, 0x7E);
|
static const RegEx e = Space() || Tab();
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& Break() {
|
||||||
|
static const RegEx e = RegEx('\n') || RegEx("\r\n");
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& BlankOrBreak() {
|
||||||
|
static const RegEx e = Blank() || Break();
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& Digit() {
|
||||||
|
static const RegEx e = RegEx('0', '9');
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& Alpha() {
|
||||||
|
static const RegEx e = RegEx('a', 'z') || RegEx('A', 'Z');
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& AlphaNumeric() {
|
||||||
|
static const RegEx e = Alpha() || Digit();
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& Word() {
|
||||||
|
static const RegEx e = AlphaNumeric() || RegEx('-');
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& Hex() {
|
||||||
|
static const RegEx e = Digit() || RegEx('A', 'F') || RegEx('a', 'f');
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
// Valid Unicode code points that are not part of c-printable (YAML 1.2, sec. 5.1)
|
||||||
|
inline const RegEx& NotPrintable() {
|
||||||
|
static const RegEx e = RegEx(0) ||
|
||||||
|
RegEx("\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x7F", REGEX_OR) ||
|
||||||
|
RegEx(0x0E, 0x1F) ||
|
||||||
|
(RegEx('\xC2') + (RegEx('\x80', '\x84') || RegEx('\x86', '\x9F')));
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& Utf8_ByteOrderMark() {
|
||||||
|
static const RegEx e = RegEx("\xEF\xBB\xBF");
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
// actual tags
|
// actual tags
|
||||||
|
|
||||||
const RegEx DocStart = RegEx("---") + (BlankOrBreak || RegEx());
|
inline const RegEx& DocStart() {
|
||||||
const RegEx DocEnd = RegEx("...") + (BlankOrBreak || RegEx());
|
static const RegEx e = RegEx("---") + (BlankOrBreak() || RegEx());
|
||||||
const RegEx DocIndicator = DocStart || DocEnd;
|
return e;
|
||||||
const RegEx BlockEntry = RegEx('-') + (BlankOrBreak || RegEx());
|
}
|
||||||
const RegEx Key = RegEx('?'),
|
inline const RegEx& DocEnd() {
|
||||||
KeyInFlow = RegEx('?') + BlankOrBreak;
|
static const RegEx e = RegEx("...") + (BlankOrBreak() || RegEx());
|
||||||
const RegEx Value = RegEx(':') + (BlankOrBreak || RegEx()),
|
return e;
|
||||||
ValueInFlow = RegEx(':') + (BlankOrBreak || RegEx(",}", REGEX_OR));
|
}
|
||||||
const RegEx Comment = RegEx('#');
|
inline const RegEx& DocIndicator() {
|
||||||
const RegEx AnchorEnd = RegEx("?:,]}%@`", REGEX_OR) || BlankOrBreak;
|
static const RegEx e = DocStart() || DocEnd();
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& BlockEntry() {
|
||||||
|
static const RegEx e = RegEx('-') + (BlankOrBreak() || RegEx());
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& Key() {
|
||||||
|
static const RegEx e = RegEx('?');
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& KeyInFlow() {
|
||||||
|
static const RegEx e = RegEx('?') + BlankOrBreak();
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& Value() {
|
||||||
|
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx());
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& ValueInFlow() {
|
||||||
|
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx(",}", REGEX_OR));
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& ValueInJSONFlow() {
|
||||||
|
static const RegEx e = RegEx(':');
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx Comment() {
|
||||||
|
static const RegEx e = RegEx('#');
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& AnchorEnd() {
|
||||||
|
static const RegEx e = RegEx("?:,]}%@`", REGEX_OR) || BlankOrBreak();
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& URI() {
|
||||||
|
static const RegEx e = Word() || RegEx("#;/?:@&=+$,_.!~*'()[]", REGEX_OR) || (RegEx('%') + Hex() + Hex());
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& Tag() {
|
||||||
|
static const RegEx e = Word() || RegEx("#;/?:@&=+$_.~*'", REGEX_OR) || (RegEx('%') + Hex() + Hex());
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
// Plain scalar rules:
|
// Plain scalar rules:
|
||||||
// . Cannot start with a blank.
|
// . Cannot start with a blank.
|
||||||
// . Can never start with any of , [ ] { } # & * ! | > \' \" % @ `
|
// . Can never start with any of , [ ] { } # & * ! | > \' \" % @ `
|
||||||
// . In the block context - ? : must be not be followed with a space.
|
// . In the block context - ? : must be not be followed with a space.
|
||||||
// . In the flow context ? is illegal and : and - must not be followed with a space.
|
// . In the flow context ? is illegal and : and - must not be followed with a space.
|
||||||
const RegEx PlainScalar = !(BlankOrBreak || RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-?:", REGEX_OR) + Blank)),
|
inline const RegEx& PlainScalar() {
|
||||||
PlainScalarInFlow = !(BlankOrBreak || RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-:", REGEX_OR) + Blank));
|
static const RegEx e = !(BlankOrBreak() || RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-?:", REGEX_OR) + Blank()));
|
||||||
const RegEx EndScalar = RegEx(':') + (BlankOrBreak || RegEx()),
|
return e;
|
||||||
EndScalarInFlow = (RegEx(':') + (BlankOrBreak || RegEx(",]}", REGEX_OR))) || RegEx(",?[]{}", REGEX_OR);
|
}
|
||||||
|
inline const RegEx& PlainScalarInFlow() {
|
||||||
|
static const RegEx e = !(BlankOrBreak() || RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) || (RegEx("-:", REGEX_OR) + Blank()));
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& EndScalar() {
|
||||||
|
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx());
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& EndScalarInFlow() {
|
||||||
|
static const RegEx e = (RegEx(':') + (BlankOrBreak() || RegEx(",]}", REGEX_OR))) || RegEx(",?[]{}", REGEX_OR);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
const RegEx EscSingleQuote = RegEx("\'\'");
|
inline const RegEx& EscSingleQuote() {
|
||||||
const RegEx EscBreak = RegEx('\\') + Break;
|
static const RegEx e = RegEx("\'\'");
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& EscBreak() {
|
||||||
|
static const RegEx e = RegEx('\\') + Break();
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
const RegEx ChompIndicator = RegEx("+-", REGEX_OR);
|
inline const RegEx& ChompIndicator() {
|
||||||
const RegEx Chomp = (ChompIndicator + Digit) || (Digit + ChompIndicator) || ChompIndicator || Digit;
|
static const RegEx e = RegEx("+-", REGEX_OR);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
inline const RegEx& Chomp() {
|
||||||
|
static const RegEx e = (ChompIndicator() + Digit()) || (Digit() + ChompIndicator()) || ChompIndicator() || Digit();
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
// and some functions
|
// and some functions
|
||||||
std::string Escape(Stream& in);
|
std::string Escape(Stream& in);
|
||||||
@@ -74,6 +182,8 @@ namespace YAML
|
|||||||
const char Tag = '!';
|
const char Tag = '!';
|
||||||
const char LiteralScalar = '|';
|
const char LiteralScalar = '|';
|
||||||
const char FoldedScalar = '>';
|
const char FoldedScalar = '>';
|
||||||
|
const char VerbatimTagStart = '<';
|
||||||
|
const char VerbatimTagEnd = '>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
#include "crt.h"
|
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "iterpriv.h"
|
#include "iterpriv.h"
|
||||||
|
69
src/map.cpp
69
src/map.cpp
@@ -1,11 +1,9 @@
|
|||||||
#include "crt.h"
|
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "emitter.h"
|
#include "emitter.h"
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
{
|
{
|
||||||
@@ -18,7 +16,7 @@ namespace YAML
|
|||||||
for(node_map::const_iterator it=data.begin();it!=data.end();++it) {
|
for(node_map::const_iterator it=data.begin();it!=data.end();++it) {
|
||||||
std::auto_ptr<Node> pKey = it->first->Clone();
|
std::auto_ptr<Node> pKey = it->first->Clone();
|
||||||
std::auto_ptr<Node> pValue = it->second->Clone();
|
std::auto_ptr<Node> pValue = it->second->Clone();
|
||||||
m_data[pKey.release()] = pValue.release();
|
AddEntry(pKey, pValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +56,7 @@ namespace YAML
|
|||||||
return m_data.size();
|
return m_data.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Map::Parse(Scanner *pScanner, const ParserState& state)
|
void Map::Parse(Scanner *pScanner, ParserState& state)
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
|
|
||||||
@@ -66,14 +64,17 @@ namespace YAML
|
|||||||
switch(pScanner->peek().type) {
|
switch(pScanner->peek().type) {
|
||||||
case Token::BLOCK_MAP_START: ParseBlock(pScanner, state); break;
|
case Token::BLOCK_MAP_START: ParseBlock(pScanner, state); break;
|
||||||
case Token::FLOW_MAP_START: ParseFlow(pScanner, state); break;
|
case Token::FLOW_MAP_START: ParseFlow(pScanner, state); break;
|
||||||
|
case Token::KEY: ParseCompact(pScanner, state); break;
|
||||||
|
case Token::VALUE: ParseCompactWithNoKey(pScanner, state); break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Map::ParseBlock(Scanner *pScanner, const ParserState& state)
|
void Map::ParseBlock(Scanner *pScanner, ParserState& state)
|
||||||
{
|
{
|
||||||
// eat start token
|
// eat start token
|
||||||
pScanner->pop();
|
pScanner->pop();
|
||||||
|
state.PushCollectionType(ParserState::BLOCK_MAP);
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
if(pScanner->empty())
|
if(pScanner->empty())
|
||||||
@@ -102,15 +103,17 @@ namespace YAML
|
|||||||
pValue->Parse(pScanner, state);
|
pValue->Parse(pScanner, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
// assign the map with the actual pointers
|
AddEntry(pKey, pValue);
|
||||||
m_data[pKey.release()] = pValue.release();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state.PopCollectionType(ParserState::BLOCK_MAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Map::ParseFlow(Scanner *pScanner, const ParserState& state)
|
void Map::ParseFlow(Scanner *pScanner, ParserState& state)
|
||||||
{
|
{
|
||||||
// eat start token
|
// eat start token
|
||||||
pScanner->pop();
|
pScanner->pop();
|
||||||
|
state.PushCollectionType(ParserState::FLOW_MAP);
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
if(pScanner->empty())
|
if(pScanner->empty())
|
||||||
@@ -144,9 +147,55 @@ namespace YAML
|
|||||||
else if(nextToken.type != Token::FLOW_MAP_END)
|
else if(nextToken.type != Token::FLOW_MAP_END)
|
||||||
throw ParserException(nextToken.mark, ErrorMsg::END_OF_MAP_FLOW);
|
throw ParserException(nextToken.mark, ErrorMsg::END_OF_MAP_FLOW);
|
||||||
|
|
||||||
// assign the map with the actual pointers
|
AddEntry(pKey, pValue);
|
||||||
m_data[pKey.release()] = pValue.release();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state.PopCollectionType(ParserState::FLOW_MAP);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseCompact
|
||||||
|
// . Single "key: value" pair in a flow sequence
|
||||||
|
void Map::ParseCompact(Scanner *pScanner, ParserState& state)
|
||||||
|
{
|
||||||
|
state.PushCollectionType(ParserState::COMPACT_MAP);
|
||||||
|
std::auto_ptr <Node> pKey(new Node), pValue(new Node);
|
||||||
|
|
||||||
|
// grab key
|
||||||
|
pScanner->pop();
|
||||||
|
pKey->Parse(pScanner, state);
|
||||||
|
|
||||||
|
// now grab value (optional)
|
||||||
|
if(!pScanner->empty() && pScanner->peek().type == Token::VALUE) {
|
||||||
|
pScanner->pop();
|
||||||
|
pValue->Parse(pScanner, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
AddEntry(pKey, pValue);
|
||||||
|
state.PopCollectionType(ParserState::COMPACT_MAP);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseCompactWithNoKey
|
||||||
|
// . Single ": value" pair in a flow sequence
|
||||||
|
void Map::ParseCompactWithNoKey(Scanner *pScanner, ParserState& state)
|
||||||
|
{
|
||||||
|
state.PushCollectionType(ParserState::COMPACT_MAP);
|
||||||
|
std::auto_ptr <Node> pKey(new Node), pValue(new Node);
|
||||||
|
|
||||||
|
// grab value
|
||||||
|
pScanner->pop();
|
||||||
|
pValue->Parse(pScanner, state);
|
||||||
|
|
||||||
|
AddEntry(pKey, pValue);
|
||||||
|
state.PopCollectionType(ParserState::COMPACT_MAP);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Map::AddEntry(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue)
|
||||||
|
{
|
||||||
|
node_map::const_iterator it = m_data.find(pKey.get());
|
||||||
|
if(it != m_data.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_data[pKey.release()] = pValue.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Map::Write(Emitter& out) const
|
void Map::Write(Emitter& out) const
|
||||||
|
11
src/map.h
11
src/map.h
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "content.h"
|
#include "content.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
{
|
{
|
||||||
@@ -27,7 +28,7 @@ namespace YAML
|
|||||||
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& it) const;
|
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& it) const;
|
||||||
virtual bool GetEnd(std::map <Node *, Node *, ltnode>::const_iterator& it) const;
|
virtual bool GetEnd(std::map <Node *, Node *, ltnode>::const_iterator& it) const;
|
||||||
virtual std::size_t GetSize() const;
|
virtual std::size_t GetSize() const;
|
||||||
virtual void Parse(Scanner *pScanner, const ParserState& state);
|
virtual void Parse(Scanner *pScanner, ParserState& state);
|
||||||
virtual void Write(Emitter& out) const;
|
virtual void Write(Emitter& out) const;
|
||||||
|
|
||||||
virtual bool IsMap() const { return true; }
|
virtual bool IsMap() const { return true; }
|
||||||
@@ -39,8 +40,12 @@ namespace YAML
|
|||||||
virtual int Compare(Map *pMap);
|
virtual int Compare(Map *pMap);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ParseBlock(Scanner *pScanner, const ParserState& state);
|
void ParseBlock(Scanner *pScanner, ParserState& state);
|
||||||
void ParseFlow(Scanner *pScanner, const ParserState& state);
|
void ParseFlow(Scanner *pScanner, ParserState& state);
|
||||||
|
void ParseCompact(Scanner *pScanner, ParserState& state);
|
||||||
|
void ParseCompactWithNoKey(Scanner *pScanner, ParserState& state);
|
||||||
|
|
||||||
|
void AddEntry(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
node_map m_data;
|
node_map m_data;
|
||||||
|
43
src/node.cpp
43
src/node.cpp
@@ -1,4 +1,3 @@
|
|||||||
#include "crt.h"
|
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
@@ -10,6 +9,7 @@
|
|||||||
#include "aliascontent.h"
|
#include "aliascontent.h"
|
||||||
#include "iterpriv.h"
|
#include "iterpriv.h"
|
||||||
#include "emitter.h"
|
#include "emitter.h"
|
||||||
|
#include "tag.h"
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
@@ -27,7 +27,7 @@ namespace YAML
|
|||||||
Node::Node(const Mark& mark, const std::string& anchor, const std::string& tag, const Content *pContent)
|
Node::Node(const Mark& mark, const std::string& anchor, const std::string& tag, const Content *pContent)
|
||||||
: m_mark(mark), m_anchor(anchor), m_tag(tag), m_pContent(0), m_alias(false), m_pIdentity(this), m_referenced(false)
|
: m_mark(mark), m_anchor(anchor), m_tag(tag), m_pContent(0), m_alias(false), m_pIdentity(this), m_referenced(false)
|
||||||
{
|
{
|
||||||
if(m_pContent)
|
if(pContent)
|
||||||
m_pContent = pContent->Clone();
|
m_pContent = pContent->Clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ namespace YAML
|
|||||||
return std::auto_ptr<Node> (new Node(m_mark, m_anchor, m_tag, m_pContent));
|
return std::auto_ptr<Node> (new Node(m_mark, m_anchor, m_tag, m_pContent));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::Parse(Scanner *pScanner, const ParserState& state)
|
void Node::Parse(Scanner *pScanner, ParserState& state)
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
|
|
||||||
@@ -65,6 +65,13 @@ namespace YAML
|
|||||||
// save location
|
// save location
|
||||||
m_mark = pScanner->peek().mark;
|
m_mark = pScanner->peek().mark;
|
||||||
|
|
||||||
|
// special case: a value node by itself must be a map, with no header
|
||||||
|
if(pScanner->peek().type == Token::VALUE) {
|
||||||
|
m_pContent = new Map;
|
||||||
|
m_pContent->Parse(pScanner, state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ParseHeader(pScanner, state);
|
ParseHeader(pScanner, state);
|
||||||
|
|
||||||
// is this an alias? if so, its contents are an alias to
|
// is this an alias? if so, its contents are an alias to
|
||||||
@@ -99,10 +106,12 @@ namespace YAML
|
|||||||
case Token::BLOCK_MAP_START:
|
case Token::BLOCK_MAP_START:
|
||||||
m_pContent = new Map;
|
m_pContent = new Map;
|
||||||
break;
|
break;
|
||||||
|
case Token::KEY:
|
||||||
|
// compact maps can only go in a flow sequence
|
||||||
|
if(state.GetCurCollectionType() == ParserState::FLOW_SEQ)
|
||||||
|
m_pContent = new Map;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// std::stringstream str;
|
|
||||||
// str << TokenNames[pScanner->peek().type];
|
|
||||||
// throw std::runtime_error(str.str());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +126,7 @@ namespace YAML
|
|||||||
|
|
||||||
// ParseHeader
|
// ParseHeader
|
||||||
// . Grabs any tag, alias, or anchor tokens and deals with them.
|
// . Grabs any tag, alias, or anchor tokens and deals with them.
|
||||||
void Node::ParseHeader(Scanner *pScanner, const ParserState& state)
|
void Node::ParseHeader(Scanner *pScanner, ParserState& state)
|
||||||
{
|
{
|
||||||
while(1) {
|
while(1) {
|
||||||
if(pScanner->empty())
|
if(pScanner->empty())
|
||||||
@@ -132,20 +141,18 @@ namespace YAML
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::ParseTag(Scanner *pScanner, const ParserState& state)
|
void Node::ParseTag(Scanner *pScanner, ParserState& state)
|
||||||
{
|
{
|
||||||
Token& token = pScanner->peek();
|
Token& token = pScanner->peek();
|
||||||
if(m_tag != "")
|
if(m_tag != "")
|
||||||
throw ParserException(token.mark, ErrorMsg::MULTIPLE_TAGS);
|
throw ParserException(token.mark, ErrorMsg::MULTIPLE_TAGS);
|
||||||
|
|
||||||
m_tag = state.TranslateTag(token.value);
|
Tag tag(token);
|
||||||
|
m_tag = tag.Translate(state);
|
||||||
for(std::size_t i=0;i<token.params.size();i++)
|
|
||||||
m_tag += token.params[i];
|
|
||||||
pScanner->pop();
|
pScanner->pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::ParseAnchor(Scanner *pScanner, const ParserState& /*state*/)
|
void Node::ParseAnchor(Scanner *pScanner, ParserState& /*state*/)
|
||||||
{
|
{
|
||||||
Token& token = pScanner->peek();
|
Token& token = pScanner->peek();
|
||||||
if(m_anchor != "")
|
if(m_anchor != "")
|
||||||
@@ -156,7 +163,7 @@ namespace YAML
|
|||||||
pScanner->pop();
|
pScanner->pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::ParseAlias(Scanner *pScanner, const ParserState& /*state*/)
|
void Node::ParseAlias(Scanner *pScanner, ParserState& /*state*/)
|
||||||
{
|
{
|
||||||
Token& token = pScanner->peek();
|
Token& token = pScanner->peek();
|
||||||
if(m_anchor != "")
|
if(m_anchor != "")
|
||||||
@@ -242,7 +249,10 @@ namespace YAML
|
|||||||
bool Node::GetScalar(std::string& s) const
|
bool Node::GetScalar(std::string& s) const
|
||||||
{
|
{
|
||||||
if(!m_pContent) {
|
if(!m_pContent) {
|
||||||
s = "~";
|
if(m_tag.empty())
|
||||||
|
s = "~";
|
||||||
|
else
|
||||||
|
s = "";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,7 +269,8 @@ namespace YAML
|
|||||||
out << Anchor(node.m_anchor);
|
out << Anchor(node.m_anchor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: write tag
|
if(node.m_tag != "")
|
||||||
|
out << VerbatimTag(node.m_tag);
|
||||||
|
|
||||||
// write content
|
// write content
|
||||||
if(node.m_pContent)
|
if(node.m_pContent)
|
||||||
|
@@ -1,40 +1,45 @@
|
|||||||
#include "crt.h"
|
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
|
#include "parserstate.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
{
|
{
|
||||||
Parser::Parser(std::istream& in): m_pScanner(0)
|
Parser::Parser()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Parser::Parser(std::istream& in)
|
||||||
{
|
{
|
||||||
Load(in);
|
Load(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
Parser::~Parser()
|
Parser::~Parser()
|
||||||
{
|
{
|
||||||
delete m_pScanner;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Parser::operator bool() const
|
Parser::operator bool() const
|
||||||
{
|
{
|
||||||
return !m_pScanner->empty();
|
return m_pScanner.get() && !m_pScanner->empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parser::Load(std::istream& in)
|
void Parser::Load(std::istream& in)
|
||||||
{
|
{
|
||||||
delete m_pScanner;
|
m_pScanner.reset(new Scanner(in));
|
||||||
m_pScanner = new Scanner(in);
|
m_pState.reset(new ParserState);
|
||||||
m_state.Reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNextDocument
|
// GetNextDocument
|
||||||
// . Reads the next document in the queue (of tokens).
|
// . Reads the next document in the queue (of tokens).
|
||||||
// . Throws a ParserException on error.
|
// . Throws a ParserException on error.
|
||||||
void Parser::GetNextDocument(Node& document)
|
bool Parser::GetNextDocument(Node& document)
|
||||||
{
|
{
|
||||||
|
if(!m_pScanner.get())
|
||||||
|
return false;
|
||||||
|
|
||||||
// clear node
|
// clear node
|
||||||
document.Clear();
|
document.Clear();
|
||||||
|
|
||||||
@@ -43,14 +48,14 @@ namespace YAML
|
|||||||
|
|
||||||
// we better have some tokens in the queue
|
// we better have some tokens in the queue
|
||||||
if(m_pScanner->empty())
|
if(m_pScanner->empty())
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
// first eat doc start (optional)
|
// first eat doc start (optional)
|
||||||
if(m_pScanner->peek().type == Token::DOC_START)
|
if(m_pScanner->peek().type == Token::DOC_START)
|
||||||
m_pScanner->pop();
|
m_pScanner->pop();
|
||||||
|
|
||||||
// now parse our root node
|
// now parse our root node
|
||||||
document.Parse(m_pScanner, m_state);
|
document.Parse(m_pScanner.get(), *m_pState);
|
||||||
|
|
||||||
// and finally eat any doc ends we see
|
// and finally eat any doc ends we see
|
||||||
while(!m_pScanner->empty() && m_pScanner->peek().type == Token::DOC_END)
|
while(!m_pScanner->empty() && m_pScanner->peek().type == Token::DOC_END)
|
||||||
@@ -58,6 +63,8 @@ namespace YAML
|
|||||||
|
|
||||||
// clear anchors from the scanner, which are no longer relevant
|
// clear anchors from the scanner, which are no longer relevant
|
||||||
m_pScanner->ClearAnchors();
|
m_pScanner->ClearAnchors();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseDirectives
|
// ParseDirectives
|
||||||
@@ -77,55 +84,66 @@ namespace YAML
|
|||||||
// we keep the directives from the last document if none are specified;
|
// we keep the directives from the last document if none are specified;
|
||||||
// but if any directives are specific, then we reset them
|
// but if any directives are specific, then we reset them
|
||||||
if(!readDirective)
|
if(!readDirective)
|
||||||
m_state.Reset();
|
m_pState.reset(new ParserState);
|
||||||
|
|
||||||
readDirective = true;
|
readDirective = true;
|
||||||
HandleDirective(&token);
|
HandleDirective(token);
|
||||||
m_pScanner->pop();
|
m_pScanner->pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parser::HandleDirective(Token *pToken)
|
void Parser::HandleDirective(const Token& token)
|
||||||
{
|
{
|
||||||
if(pToken->value == "YAML")
|
if(token.value == "YAML")
|
||||||
HandleYamlDirective(pToken);
|
HandleYamlDirective(token);
|
||||||
else if(pToken->value == "TAG")
|
else if(token.value == "TAG")
|
||||||
HandleTagDirective(pToken);
|
HandleTagDirective(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleYamlDirective
|
// HandleYamlDirective
|
||||||
// . Should be of the form 'major.minor' (like a version number)
|
// . Should be of the form 'major.minor' (like a version number)
|
||||||
void Parser::HandleYamlDirective(Token *pToken)
|
void Parser::HandleYamlDirective(const Token& token)
|
||||||
{
|
{
|
||||||
if(pToken->params.size() != 1)
|
if(token.params.size() != 1)
|
||||||
throw ParserException(pToken->mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
|
throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
|
||||||
|
|
||||||
std::stringstream str(pToken->params[0]);
|
if(!m_pState->version.isDefault)
|
||||||
str >> m_state.version.major;
|
throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE);
|
||||||
|
|
||||||
|
std::stringstream str(token.params[0]);
|
||||||
|
str >> m_pState->version.major;
|
||||||
str.get();
|
str.get();
|
||||||
str >> m_state.version.minor;
|
str >> m_pState->version.minor;
|
||||||
if(!str || str.peek() != EOF)
|
if(!str || str.peek() != EOF)
|
||||||
throw ParserException(pToken->mark, ErrorMsg::YAML_VERSION + pToken->params[0]);
|
throw ParserException(token.mark, ErrorMsg::YAML_VERSION + token.params[0]);
|
||||||
|
|
||||||
if(m_state.version.major > 1)
|
if(m_pState->version.major > 1)
|
||||||
throw ParserException(pToken->mark, ErrorMsg::YAML_MAJOR_VERSION);
|
throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION);
|
||||||
|
|
||||||
|
m_pState->version.isDefault = false;
|
||||||
// TODO: warning on major == 1, minor > 2?
|
// TODO: warning on major == 1, minor > 2?
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleTagDirective
|
// HandleTagDirective
|
||||||
// . Should be of the form 'handle prefix', where 'handle' is converted to 'prefix' in the file.
|
// . Should be of the form 'handle prefix', where 'handle' is converted to 'prefix' in the file.
|
||||||
void Parser::HandleTagDirective(Token *pToken)
|
void Parser::HandleTagDirective(const Token& token)
|
||||||
{
|
{
|
||||||
if(pToken->params.size() != 2)
|
if(token.params.size() != 2)
|
||||||
throw ParserException(pToken->mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
|
throw ParserException(token.mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
|
||||||
|
|
||||||
std::string handle = pToken->params[0], prefix = pToken->params[1];
|
const std::string& handle = token.params[0];
|
||||||
m_state.tags[handle] = prefix;
|
const std::string& prefix = token.params[1];
|
||||||
|
if(m_pState->tags.find(handle) != m_pState->tags.end())
|
||||||
|
throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE);
|
||||||
|
|
||||||
|
m_pState->tags[handle] = prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parser::PrintTokens(std::ostream& out)
|
void Parser::PrintTokens(std::ostream& out)
|
||||||
{
|
{
|
||||||
|
if(!m_pScanner.get())
|
||||||
|
return;
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
if(m_pScanner->empty())
|
if(m_pScanner->empty())
|
||||||
break;
|
break;
|
||||||
|
@@ -1,25 +1,23 @@
|
|||||||
#include "crt.h"
|
|
||||||
#include "parserstate.h"
|
#include "parserstate.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
{
|
{
|
||||||
void ParserState::Reset()
|
ParserState::ParserState()
|
||||||
{
|
{
|
||||||
// version
|
// version
|
||||||
|
version.isDefault = true;
|
||||||
version.major = 1;
|
version.major = 1;
|
||||||
version.minor = 2;
|
version.minor = 2;
|
||||||
|
|
||||||
// and tags
|
|
||||||
tags.clear();
|
|
||||||
tags["!"] = "!";
|
|
||||||
tags["!!"] = "tag:yaml.org,2002:";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ParserState::TranslateTag(const std::string& handle) const
|
const std::string ParserState::TranslateTagHandle(const std::string& handle) const
|
||||||
{
|
{
|
||||||
std::map <std::string, std::string>::const_iterator it = tags.find(handle);
|
std::map <std::string, std::string>::const_iterator it = tags.find(handle);
|
||||||
if(it == tags.end())
|
if(it == tags.end()) {
|
||||||
|
if(handle == "!!")
|
||||||
|
return "tag:yaml.org,2002:";
|
||||||
return handle;
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
37
src/parserstate.h
Normal file
37
src/parserstate.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef PARSERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
#define PARSERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <stack>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace YAML
|
||||||
|
{
|
||||||
|
struct Version {
|
||||||
|
bool isDefault;
|
||||||
|
int major, minor;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ParserState
|
||||||
|
{
|
||||||
|
enum COLLECTION_TYPE { NONE, BLOCK_MAP, BLOCK_SEQ, FLOW_MAP, FLOW_SEQ, COMPACT_MAP };
|
||||||
|
|
||||||
|
ParserState();
|
||||||
|
|
||||||
|
const std::string TranslateTagHandle(const std::string& handle) const;
|
||||||
|
COLLECTION_TYPE GetCurCollectionType() const { if(collectionStack.empty()) return NONE; return collectionStack.top(); }
|
||||||
|
|
||||||
|
void PushCollectionType(COLLECTION_TYPE type) { collectionStack.push(type); }
|
||||||
|
void PopCollectionType(COLLECTION_TYPE type) { assert(type == GetCurCollectionType()); collectionStack.pop(); }
|
||||||
|
|
||||||
|
Version version;
|
||||||
|
std::map <std::string, std::string> tags;
|
||||||
|
std::stack <COLLECTION_TYPE> collectionStack;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // PARSERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
@@ -1,4 +1,3 @@
|
|||||||
#include "crt.h"
|
|
||||||
#include "regex.h"
|
#include "regex.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
|
@@ -37,12 +37,12 @@ namespace YAML
|
|||||||
|
|
||||||
int Match(const std::string& str) const;
|
int Match(const std::string& str) const;
|
||||||
int Match(const Stream& in) const;
|
int Match(const Stream& in) const;
|
||||||
|
template <typename Source> int Match(const Source& source) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RegEx(REGEX_OP op);
|
RegEx(REGEX_OP op);
|
||||||
|
|
||||||
template <typename Source> bool IsValidSource(const Source& source) const;
|
template <typename Source> bool IsValidSource(const Source& source) const;
|
||||||
template <typename Source> int Match(const Source& source) const;
|
|
||||||
template <typename Source> int MatchUnchecked(const Source& source) const;
|
template <typename Source> int MatchUnchecked(const Source& source) const;
|
||||||
|
|
||||||
template <typename Source> int MatchOpEmpty(const Source& source) const;
|
template <typename Source> int MatchOpEmpty(const Source& source) const;
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
#include "crt.h"
|
|
||||||
#include "scalar.h"
|
#include "scalar.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
@@ -25,7 +24,7 @@ namespace YAML
|
|||||||
return new Scalar(m_data);
|
return new Scalar(m_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scalar::Parse(Scanner *pScanner, const ParserState& /*state*/)
|
void Scalar::Parse(Scanner *pScanner, ParserState& /*state*/)
|
||||||
{
|
{
|
||||||
Token& token = pScanner->peek();
|
Token& token = pScanner->peek();
|
||||||
m_data = token.value;
|
m_data = token.value;
|
||||||
|
@@ -18,7 +18,7 @@ namespace YAML
|
|||||||
|
|
||||||
virtual Content *Clone() const;
|
virtual Content *Clone() const;
|
||||||
|
|
||||||
virtual void Parse(Scanner *pScanner, const ParserState& state);
|
virtual void Parse(Scanner *pScanner, ParserState& state);
|
||||||
virtual void Write(Emitter& out) const;
|
virtual void Write(Emitter& out) const;
|
||||||
|
|
||||||
virtual bool IsScalar() const { return true; }
|
virtual bool IsScalar() const { return true; }
|
||||||
|
100
src/scanner.cpp
100
src/scanner.cpp
@@ -1,19 +1,22 @@
|
|||||||
#include "crt.h"
|
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "exp.h"
|
#include "exp.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
{
|
{
|
||||||
Scanner::Scanner(std::istream& in)
|
Scanner::Scanner(std::istream& in)
|
||||||
: INPUT(in), m_startedStream(false), m_endedStream(false), m_simpleKeyAllowed(false)
|
: INPUT(in), m_startedStream(false), m_endedStream(false), m_simpleKeyAllowed(false), m_canBeJSONFlow(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Scanner::~Scanner()
|
Scanner::~Scanner()
|
||||||
{
|
{
|
||||||
|
for(unsigned i=0;i<m_indentRefs.size();i++)
|
||||||
|
delete m_indentRefs[i];
|
||||||
|
m_indentRefs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// empty
|
// empty
|
||||||
@@ -116,10 +119,10 @@ namespace YAML
|
|||||||
return ScanDirective();
|
return ScanDirective();
|
||||||
|
|
||||||
// document token
|
// document token
|
||||||
if(INPUT.column() == 0 && Exp::DocStart.Matches(INPUT))
|
if(INPUT.column() == 0 && Exp::DocStart().Matches(INPUT))
|
||||||
return ScanDocStart();
|
return ScanDocStart();
|
||||||
|
|
||||||
if(INPUT.column() == 0 && Exp::DocEnd.Matches(INPUT))
|
if(INPUT.column() == 0 && Exp::DocEnd().Matches(INPUT))
|
||||||
return ScanDocEnd();
|
return ScanDocEnd();
|
||||||
|
|
||||||
// flow start/end/entry
|
// flow start/end/entry
|
||||||
@@ -133,13 +136,13 @@ namespace YAML
|
|||||||
return ScanFlowEntry();
|
return ScanFlowEntry();
|
||||||
|
|
||||||
// block/map stuff
|
// block/map stuff
|
||||||
if(Exp::BlockEntry.Matches(INPUT))
|
if(Exp::BlockEntry().Matches(INPUT))
|
||||||
return ScanBlockEntry();
|
return ScanBlockEntry();
|
||||||
|
|
||||||
if((InBlockContext() ? Exp::Key : Exp::KeyInFlow).Matches(INPUT))
|
if((InBlockContext() ? Exp::Key() : Exp::KeyInFlow()).Matches(INPUT))
|
||||||
return ScanKey();
|
return ScanKey();
|
||||||
|
|
||||||
if((InBlockContext() ? Exp::Value : Exp::ValueInFlow).Matches(INPUT))
|
if(GetValueRegex().Matches(INPUT))
|
||||||
return ScanValue();
|
return ScanValue();
|
||||||
|
|
||||||
// alias/anchor
|
// alias/anchor
|
||||||
@@ -158,7 +161,7 @@ namespace YAML
|
|||||||
return ScanQuotedScalar();
|
return ScanQuotedScalar();
|
||||||
|
|
||||||
// plain scalars
|
// plain scalars
|
||||||
if((InBlockContext() ? Exp::PlainScalar : Exp::PlainScalarInFlow).Matches(INPUT))
|
if((InBlockContext() ? Exp::PlainScalar() : Exp::PlainScalarInFlow()).Matches(INPUT))
|
||||||
return ScanPlainScalar();
|
return ScanPlainScalar();
|
||||||
|
|
||||||
// don't know what it is!
|
// don't know what it is!
|
||||||
@@ -172,24 +175,24 @@ namespace YAML
|
|||||||
while(1) {
|
while(1) {
|
||||||
// first eat whitespace
|
// first eat whitespace
|
||||||
while(INPUT && IsWhitespaceToBeEaten(INPUT.peek())) {
|
while(INPUT && IsWhitespaceToBeEaten(INPUT.peek())) {
|
||||||
if(InBlockContext() && Exp::Tab.Matches(INPUT))
|
if(InBlockContext() && Exp::Tab().Matches(INPUT))
|
||||||
m_simpleKeyAllowed = false;
|
m_simpleKeyAllowed = false;
|
||||||
INPUT.eat(1);
|
INPUT.eat(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// then eat a comment
|
// then eat a comment
|
||||||
if(Exp::Comment.Matches(INPUT)) {
|
if(Exp::Comment().Matches(INPUT)) {
|
||||||
// eat until line break
|
// eat until line break
|
||||||
while(INPUT && !Exp::Break.Matches(INPUT))
|
while(INPUT && !Exp::Break().Matches(INPUT))
|
||||||
INPUT.eat(1);
|
INPUT.eat(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if it's NOT a line break, then we're done!
|
// if it's NOT a line break, then we're done!
|
||||||
if(!Exp::Break.Matches(INPUT))
|
if(!Exp::Break().Matches(INPUT))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// otherwise, let's eat the line break and keep going
|
// otherwise, let's eat the line break and keep going
|
||||||
int n = Exp::Break.Match(INPUT);
|
int n = Exp::Break().Match(INPUT);
|
||||||
INPUT.eat(n);
|
INPUT.eat(n);
|
||||||
|
|
||||||
// oh yeah, and let's get rid of that simple key
|
// oh yeah, and let's get rid of that simple key
|
||||||
@@ -223,13 +226,25 @@ namespace YAML
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetValueRegex
|
||||||
|
// . Get the appropriate regex to check if it's a value token
|
||||||
|
const RegEx& Scanner::GetValueRegex() const
|
||||||
|
{
|
||||||
|
if(InBlockContext())
|
||||||
|
return Exp::Value();
|
||||||
|
|
||||||
|
return m_canBeJSONFlow ? Exp::ValueInJSONFlow() : Exp::ValueInFlow();
|
||||||
|
}
|
||||||
|
|
||||||
// StartStream
|
// StartStream
|
||||||
// . Set the initial conditions for starting a stream.
|
// . Set the initial conditions for starting a stream.
|
||||||
void Scanner::StartStream()
|
void Scanner::StartStream()
|
||||||
{
|
{
|
||||||
m_startedStream = true;
|
m_startedStream = true;
|
||||||
m_simpleKeyAllowed = true;
|
m_simpleKeyAllowed = true;
|
||||||
m_indents.push(IndentMarker(-1, IndentMarker::NONE));
|
IndentMarker *pIndent = new IndentMarker(-1, IndentMarker::NONE);
|
||||||
|
m_indentRefs.push_back(pIndent);
|
||||||
|
m_indents.push(pIndent);
|
||||||
m_anchors.clear();
|
m_anchors.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,6 +263,22 @@ namespace YAML
|
|||||||
m_endedStream = true;
|
m_endedStream = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Token *Scanner::PushToken(Token::TYPE type)
|
||||||
|
{
|
||||||
|
m_tokens.push(Token(type, INPUT.mark()));
|
||||||
|
return &m_tokens.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
Token::TYPE Scanner::GetStartTokenFor(IndentMarker::INDENT_TYPE type) const
|
||||||
|
{
|
||||||
|
switch(type) {
|
||||||
|
case IndentMarker::SEQ: return Token::BLOCK_SEQ_START;
|
||||||
|
case IndentMarker::MAP: return Token::BLOCK_MAP_START;
|
||||||
|
case IndentMarker::NONE: assert(false); break;
|
||||||
|
}
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
// PushIndentTo
|
// PushIndentTo
|
||||||
// . Pushes an indentation onto the stack, and enqueues the
|
// . Pushes an indentation onto the stack, and enqueues the
|
||||||
// proper token (sequence start or mapping start).
|
// proper token (sequence start or mapping start).
|
||||||
@@ -258,8 +289,9 @@ namespace YAML
|
|||||||
if(InFlowContext())
|
if(InFlowContext())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
IndentMarker indent(column, type);
|
std::auto_ptr<IndentMarker> pIndent(new IndentMarker(column, type));
|
||||||
const IndentMarker& lastIndent = m_indents.top();
|
IndentMarker& indent = *pIndent;
|
||||||
|
const IndentMarker& lastIndent = *m_indents.top();
|
||||||
|
|
||||||
// is this actually an indentation?
|
// is this actually an indentation?
|
||||||
if(indent.column < lastIndent.column)
|
if(indent.column < lastIndent.column)
|
||||||
@@ -268,22 +300,18 @@ namespace YAML
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// push a start token
|
// push a start token
|
||||||
if(type == IndentMarker::SEQ)
|
indent.pStartToken = PushToken(GetStartTokenFor(type));
|
||||||
m_tokens.push(Token(Token::BLOCK_SEQ_START, INPUT.mark()));
|
|
||||||
else if(type == IndentMarker::MAP)
|
|
||||||
m_tokens.push(Token(Token::BLOCK_MAP_START, INPUT.mark()));
|
|
||||||
else
|
|
||||||
assert(false);
|
|
||||||
indent.pStartToken = &m_tokens.back();
|
|
||||||
|
|
||||||
// and then the indent
|
// and then the indent
|
||||||
m_indents.push(indent);
|
m_indents.push(&indent);
|
||||||
return &m_indents.top();
|
m_indentRefs.push_back(pIndent.release());
|
||||||
|
return m_indentRefs.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
// PopIndentToHere
|
// PopIndentToHere
|
||||||
// . Pops indentations off the stack until we reach the current indentation level,
|
// . Pops indentations off the stack until we reach the current indentation level,
|
||||||
// and enqueues the proper token each time.
|
// and enqueues the proper token each time.
|
||||||
|
// . Then pops all invalid indentations off.
|
||||||
void Scanner::PopIndentToHere()
|
void Scanner::PopIndentToHere()
|
||||||
{
|
{
|
||||||
// are we in flow?
|
// are we in flow?
|
||||||
@@ -292,14 +320,17 @@ namespace YAML
|
|||||||
|
|
||||||
// now pop away
|
// now pop away
|
||||||
while(!m_indents.empty()) {
|
while(!m_indents.empty()) {
|
||||||
const IndentMarker& indent = m_indents.top();
|
const IndentMarker& indent = *m_indents.top();
|
||||||
if(indent.column < INPUT.column())
|
if(indent.column < INPUT.column())
|
||||||
break;
|
break;
|
||||||
if(indent.column == INPUT.column() && !(indent.type == IndentMarker::SEQ && !Exp::BlockEntry.Matches(INPUT)))
|
if(indent.column == INPUT.column() && !(indent.type == IndentMarker::SEQ && !Exp::BlockEntry().Matches(INPUT)))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
PopIndent();
|
PopIndent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while(!m_indents.empty() && m_indents.top()->status == IndentMarker::INVALID)
|
||||||
|
PopIndent();
|
||||||
}
|
}
|
||||||
|
|
||||||
// PopAllIndents
|
// PopAllIndents
|
||||||
@@ -313,7 +344,7 @@ namespace YAML
|
|||||||
|
|
||||||
// now pop away
|
// now pop away
|
||||||
while(!m_indents.empty()) {
|
while(!m_indents.empty()) {
|
||||||
const IndentMarker& indent = m_indents.top();
|
const IndentMarker& indent = *m_indents.top();
|
||||||
if(indent.type == IndentMarker::NONE)
|
if(indent.type == IndentMarker::NONE)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -325,17 +356,17 @@ namespace YAML
|
|||||||
// . Pops a single indent, pushing the proper token
|
// . Pops a single indent, pushing the proper token
|
||||||
void Scanner::PopIndent()
|
void Scanner::PopIndent()
|
||||||
{
|
{
|
||||||
IndentMarker indent = m_indents.top();
|
const IndentMarker& indent = *m_indents.top();
|
||||||
IndentMarker::INDENT_TYPE type = indent.type;
|
|
||||||
m_indents.pop();
|
m_indents.pop();
|
||||||
if(!indent.isValid) {
|
|
||||||
|
if(indent.status != IndentMarker::VALID) {
|
||||||
InvalidateSimpleKey();
|
InvalidateSimpleKey();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(type == IndentMarker::SEQ)
|
if(indent.type == IndentMarker::SEQ)
|
||||||
m_tokens.push(Token(Token::BLOCK_SEQ_END, INPUT.mark()));
|
m_tokens.push(Token(Token::BLOCK_SEQ_END, INPUT.mark()));
|
||||||
else if(type == IndentMarker::MAP)
|
else if(indent.type == IndentMarker::MAP)
|
||||||
m_tokens.push(Token(Token::BLOCK_MAP_END, INPUT.mark()));
|
m_tokens.push(Token(Token::BLOCK_MAP_END, INPUT.mark()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,7 +375,7 @@ namespace YAML
|
|||||||
{
|
{
|
||||||
if(m_indents.empty())
|
if(m_indents.empty())
|
||||||
return 0;
|
return 0;
|
||||||
return m_indents.top().column;
|
return m_indents.top()->column;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save
|
// Save
|
||||||
@@ -389,3 +420,4 @@ namespace YAML
|
|||||||
m_anchors.clear();
|
m_anchors.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
namespace YAML
|
namespace YAML
|
||||||
{
|
{
|
||||||
class Node;
|
class Node;
|
||||||
|
class RegEx;
|
||||||
|
|
||||||
class Scanner
|
class Scanner
|
||||||
{
|
{
|
||||||
@@ -36,11 +37,12 @@ namespace YAML
|
|||||||
private:
|
private:
|
||||||
struct IndentMarker {
|
struct IndentMarker {
|
||||||
enum INDENT_TYPE { MAP, SEQ, NONE };
|
enum INDENT_TYPE { MAP, SEQ, NONE };
|
||||||
IndentMarker(int column_, INDENT_TYPE type_): column(column_), type(type_), isValid(true), pStartToken(0) {}
|
enum STATUS { VALID, INVALID, UNKNOWN };
|
||||||
|
IndentMarker(int column_, INDENT_TYPE type_): column(column_), type(type_), status(VALID), pStartToken(0) {}
|
||||||
|
|
||||||
int column;
|
int column;
|
||||||
INDENT_TYPE type;
|
INDENT_TYPE type;
|
||||||
bool isValid;
|
STATUS status;
|
||||||
Token *pStartToken;
|
Token *pStartToken;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -53,11 +55,13 @@ namespace YAML
|
|||||||
void ScanToNextToken();
|
void ScanToNextToken();
|
||||||
void StartStream();
|
void StartStream();
|
||||||
void EndStream();
|
void EndStream();
|
||||||
|
Token *PushToken(Token::TYPE type);
|
||||||
|
|
||||||
bool InFlowContext() const { return !m_flows.empty(); }
|
bool InFlowContext() const { return !m_flows.empty(); }
|
||||||
bool InBlockContext() const { return m_flows.empty(); }
|
bool InBlockContext() const { return m_flows.empty(); }
|
||||||
int GetFlowLevel() const { return m_flows.size(); }
|
int GetFlowLevel() const { return m_flows.size(); }
|
||||||
|
|
||||||
|
Token::TYPE GetStartTokenFor(IndentMarker::INDENT_TYPE type) const;
|
||||||
IndentMarker *PushIndentTo(int column, IndentMarker::INDENT_TYPE type);
|
IndentMarker *PushIndentTo(int column, IndentMarker::INDENT_TYPE type);
|
||||||
void PopIndentToHere();
|
void PopIndentToHere();
|
||||||
void PopAllIndents();
|
void PopAllIndents();
|
||||||
@@ -75,6 +79,7 @@ namespace YAML
|
|||||||
void ThrowParserException(const std::string& msg) const;
|
void ThrowParserException(const std::string& msg) const;
|
||||||
|
|
||||||
bool IsWhitespaceToBeEaten(char ch);
|
bool IsWhitespaceToBeEaten(char ch);
|
||||||
|
const RegEx& GetValueRegex() const;
|
||||||
|
|
||||||
struct SimpleKey {
|
struct SimpleKey {
|
||||||
SimpleKey(const Mark& mark_, int flowLevel_);
|
SimpleKey(const Mark& mark_, int flowLevel_);
|
||||||
@@ -117,11 +122,14 @@ namespace YAML
|
|||||||
// state info
|
// state info
|
||||||
bool m_startedStream, m_endedStream;
|
bool m_startedStream, m_endedStream;
|
||||||
bool m_simpleKeyAllowed;
|
bool m_simpleKeyAllowed;
|
||||||
|
bool m_canBeJSONFlow;
|
||||||
std::stack <SimpleKey> m_simpleKeys;
|
std::stack <SimpleKey> m_simpleKeys;
|
||||||
std::stack <IndentMarker> m_indents;
|
std::stack <IndentMarker *> m_indents;
|
||||||
|
std::vector <IndentMarker *> m_indentRefs; // for "garbage collection"
|
||||||
std::stack <FLOW_MARKER> m_flows;
|
std::stack <FLOW_MARKER> m_flows;
|
||||||
std::map <std::string, const Node *> m_anchors;
|
std::map <std::string, const Node *> m_anchors;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
#include "crt.h"
|
|
||||||
#include "scanscalar.h"
|
#include "scanscalar.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "exp.h"
|
#include "exp.h"
|
||||||
@@ -32,12 +31,13 @@ namespace YAML
|
|||||||
// Phase #1: scan until line ending
|
// Phase #1: scan until line ending
|
||||||
|
|
||||||
std::size_t lastNonWhitespaceChar = scalar.size();
|
std::size_t lastNonWhitespaceChar = scalar.size();
|
||||||
while(!params.end.Matches(INPUT) && !Exp::Break.Matches(INPUT)) {
|
bool escapedNewline = false;
|
||||||
|
while(!params.end.Matches(INPUT) && !Exp::Break().Matches(INPUT)) {
|
||||||
if(!INPUT)
|
if(!INPUT)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// document indicator?
|
// document indicator?
|
||||||
if(INPUT.column() == 0 && Exp::DocIndicator.Matches(INPUT)) {
|
if(INPUT.column() == 0 && Exp::DocIndicator().Matches(INPUT)) {
|
||||||
if(params.onDocIndicator == BREAK)
|
if(params.onDocIndicator == BREAK)
|
||||||
break;
|
break;
|
||||||
else if(params.onDocIndicator == THROW)
|
else if(params.onDocIndicator == THROW)
|
||||||
@@ -48,11 +48,12 @@ namespace YAML
|
|||||||
pastOpeningBreak = true;
|
pastOpeningBreak = true;
|
||||||
|
|
||||||
// escaped newline? (only if we're escaping on slash)
|
// escaped newline? (only if we're escaping on slash)
|
||||||
if(params.escape == '\\' && Exp::EscBreak.Matches(INPUT)) {
|
if(params.escape == '\\' && Exp::EscBreak().Matches(INPUT)) {
|
||||||
int n = Exp::EscBreak.Match(INPUT);
|
// eat escape character and get out (but preserve trailing whitespace!)
|
||||||
INPUT.eat(n);
|
INPUT.get();
|
||||||
lastNonWhitespaceChar = scalar.size();
|
lastNonWhitespaceChar = scalar.size();
|
||||||
continue;
|
escapedNewline = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// escape this?
|
// escape this?
|
||||||
@@ -77,7 +78,7 @@ namespace YAML
|
|||||||
}
|
}
|
||||||
|
|
||||||
// doc indicator?
|
// doc indicator?
|
||||||
if(params.onDocIndicator == BREAK && INPUT.column() == 0 && Exp::DocIndicator.Matches(INPUT))
|
if(params.onDocIndicator == BREAK && INPUT.column() == 0 && Exp::DocIndicator().Matches(INPUT))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// are we done via character match?
|
// are we done via character match?
|
||||||
@@ -94,7 +95,7 @@ namespace YAML
|
|||||||
|
|
||||||
// ********************************
|
// ********************************
|
||||||
// Phase #2: eat line ending
|
// Phase #2: eat line ending
|
||||||
n = Exp::Break.Match(INPUT);
|
n = Exp::Break().Match(INPUT);
|
||||||
INPUT.eat(n);
|
INPUT.eat(n);
|
||||||
|
|
||||||
// ********************************
|
// ********************************
|
||||||
@@ -109,7 +110,7 @@ namespace YAML
|
|||||||
params.indent = std::max(params.indent, INPUT.column());
|
params.indent = std::max(params.indent, INPUT.column());
|
||||||
|
|
||||||
// and then the rest of the whitespace
|
// and then the rest of the whitespace
|
||||||
while(Exp::Blank.Matches(INPUT)) {
|
while(Exp::Blank().Matches(INPUT)) {
|
||||||
// we check for tabs that masquerade as indentation
|
// we check for tabs that masquerade as indentation
|
||||||
if(INPUT.peek() == '\t'&& INPUT.column() < params.indent && params.onTabInIndentation == THROW)
|
if(INPUT.peek() == '\t'&& INPUT.column() < params.indent && params.onTabInIndentation == THROW)
|
||||||
throw ParserException(INPUT.mark(), ErrorMsg::TAB_IN_INDENTATION);
|
throw ParserException(INPUT.mark(), ErrorMsg::TAB_IN_INDENTATION);
|
||||||
@@ -121,8 +122,8 @@ namespace YAML
|
|||||||
}
|
}
|
||||||
|
|
||||||
// was this an empty line?
|
// was this an empty line?
|
||||||
bool nextEmptyLine = Exp::Break.Matches(INPUT);
|
bool nextEmptyLine = Exp::Break().Matches(INPUT);
|
||||||
bool nextMoreIndented = Exp::Blank.Matches(INPUT);
|
bool nextMoreIndented = Exp::Blank().Matches(INPUT);
|
||||||
if(params.fold == FOLD_BLOCK && foldedNewlineCount == 0 && nextEmptyLine)
|
if(params.fold == FOLD_BLOCK && foldedNewlineCount == 0 && nextEmptyLine)
|
||||||
foldedNewlineStartedMoreIndented = moreIndented;
|
foldedNewlineStartedMoreIndented = moreIndented;
|
||||||
|
|
||||||
@@ -150,7 +151,7 @@ namespace YAML
|
|||||||
case FOLD_FLOW:
|
case FOLD_FLOW:
|
||||||
if(nextEmptyLine)
|
if(nextEmptyLine)
|
||||||
scalar += "\n";
|
scalar += "\n";
|
||||||
else if(!emptyLine && !nextEmptyLine)
|
else if(!emptyLine && !nextEmptyLine && !escapedNewline)
|
||||||
scalar += " ";
|
scalar += " ";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -40,3 +40,4 @@ namespace YAML
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif // SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
84
src/scantag.cpp
Normal file
84
src/scantag.cpp
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
#include "scanner.h"
|
||||||
|
#include "regex.h"
|
||||||
|
#include "exp.h"
|
||||||
|
#include "exceptions.h"
|
||||||
|
|
||||||
|
namespace YAML
|
||||||
|
{
|
||||||
|
const std::string ScanVerbatimTag(Stream& INPUT)
|
||||||
|
{
|
||||||
|
std::string tag;
|
||||||
|
|
||||||
|
// eat the start character
|
||||||
|
INPUT.get();
|
||||||
|
|
||||||
|
while(INPUT) {
|
||||||
|
if(INPUT.peek() == Keys::VerbatimTagEnd) {
|
||||||
|
// eat the end character
|
||||||
|
INPUT.get();
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
int n = Exp::URI().Match(INPUT);
|
||||||
|
if(n <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
tag += INPUT.get(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw ParserException(INPUT.mark(), ErrorMsg::END_OF_VERBATIM_TAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string ScanTagHandle(Stream& INPUT, bool& canBeHandle)
|
||||||
|
{
|
||||||
|
std::string tag;
|
||||||
|
canBeHandle = true;
|
||||||
|
Mark firstNonWordChar;
|
||||||
|
|
||||||
|
while(INPUT) {
|
||||||
|
if(INPUT.peek() == Keys::Tag) {
|
||||||
|
if(!canBeHandle)
|
||||||
|
throw ParserException(firstNonWordChar, ErrorMsg::CHAR_IN_TAG_HANDLE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int n = 0;
|
||||||
|
if(canBeHandle) {
|
||||||
|
n = Exp::Word().Match(INPUT);
|
||||||
|
if(n <= 0) {
|
||||||
|
canBeHandle = false;
|
||||||
|
firstNonWordChar = INPUT.mark();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!canBeHandle)
|
||||||
|
n = Exp::Tag().Match(INPUT);
|
||||||
|
|
||||||
|
if(n <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
tag += INPUT.get(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string ScanTagSuffix(Stream& INPUT)
|
||||||
|
{
|
||||||
|
std::string tag;
|
||||||
|
|
||||||
|
while(INPUT) {
|
||||||
|
int n = Exp::Tag().Match(INPUT);
|
||||||
|
if(n <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
tag += INPUT.get(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tag.empty())
|
||||||
|
throw ParserException(INPUT.mark(), ErrorMsg::TAG_WITH_NO_SUFFIX);
|
||||||
|
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
18
src/scantag.h
Normal file
18
src/scantag.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
#define SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "stream.h"
|
||||||
|
|
||||||
|
namespace YAML
|
||||||
|
{
|
||||||
|
const std::string ScanVerbatimTag(Stream& INPUT);
|
||||||
|
const std::string ScanTagHandle(Stream& INPUT, bool& canBeHandle);
|
||||||
|
const std::string ScanTagSuffix(Stream& INPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
@@ -1,9 +1,10 @@
|
|||||||
#include "crt.h"
|
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "exp.h"
|
#include "exp.h"
|
||||||
#include "scanscalar.h"
|
#include "scanscalar.h"
|
||||||
|
#include "scantag.h"
|
||||||
|
#include "tag.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
@@ -23,36 +24,34 @@ namespace YAML
|
|||||||
PopAllSimpleKeys();
|
PopAllSimpleKeys();
|
||||||
|
|
||||||
m_simpleKeyAllowed = false;
|
m_simpleKeyAllowed = false;
|
||||||
|
m_canBeJSONFlow = false;
|
||||||
|
|
||||||
// store pos and eat indicator
|
// store pos and eat indicator
|
||||||
Mark mark = INPUT.mark();
|
Token token(Token::DIRECTIVE, INPUT.mark());
|
||||||
INPUT.eat(1);
|
INPUT.eat(1);
|
||||||
|
|
||||||
// read name
|
// read name
|
||||||
while(INPUT && !Exp::BlankOrBreak.Matches(INPUT))
|
while(INPUT && !Exp::BlankOrBreak().Matches(INPUT))
|
||||||
name += INPUT.get();
|
token.value += INPUT.get();
|
||||||
|
|
||||||
// read parameters
|
// read parameters
|
||||||
while(1) {
|
while(1) {
|
||||||
// first get rid of whitespace
|
// first get rid of whitespace
|
||||||
while(Exp::Blank.Matches(INPUT))
|
while(Exp::Blank().Matches(INPUT))
|
||||||
INPUT.eat(1);
|
INPUT.eat(1);
|
||||||
|
|
||||||
// break on newline or comment
|
// break on newline or comment
|
||||||
if(!INPUT || Exp::Break.Matches(INPUT) || Exp::Comment.Matches(INPUT))
|
if(!INPUT || Exp::Break().Matches(INPUT) || Exp::Comment().Matches(INPUT))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// now read parameter
|
// now read parameter
|
||||||
std::string param;
|
std::string param;
|
||||||
while(INPUT && !Exp::BlankOrBreak.Matches(INPUT))
|
while(INPUT && !Exp::BlankOrBreak().Matches(INPUT))
|
||||||
param += INPUT.get();
|
param += INPUT.get();
|
||||||
|
|
||||||
params.push_back(param);
|
token.params.push_back(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
Token token(Token::DIRECTIVE, mark);
|
|
||||||
token.value = name;
|
|
||||||
token.params = params;
|
|
||||||
m_tokens.push(token);
|
m_tokens.push(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,6 +61,7 @@ namespace YAML
|
|||||||
PopAllIndents();
|
PopAllIndents();
|
||||||
PopAllSimpleKeys();
|
PopAllSimpleKeys();
|
||||||
m_simpleKeyAllowed = false;
|
m_simpleKeyAllowed = false;
|
||||||
|
m_canBeJSONFlow = false;
|
||||||
|
|
||||||
// eat
|
// eat
|
||||||
Mark mark = INPUT.mark();
|
Mark mark = INPUT.mark();
|
||||||
@@ -75,6 +75,7 @@ namespace YAML
|
|||||||
PopAllIndents();
|
PopAllIndents();
|
||||||
PopAllSimpleKeys();
|
PopAllSimpleKeys();
|
||||||
m_simpleKeyAllowed = false;
|
m_simpleKeyAllowed = false;
|
||||||
|
m_canBeJSONFlow = false;
|
||||||
|
|
||||||
// eat
|
// eat
|
||||||
Mark mark = INPUT.mark();
|
Mark mark = INPUT.mark();
|
||||||
@@ -88,6 +89,7 @@ namespace YAML
|
|||||||
// flows can be simple keys
|
// flows can be simple keys
|
||||||
InsertPotentialSimpleKey();
|
InsertPotentialSimpleKey();
|
||||||
m_simpleKeyAllowed = true;
|
m_simpleKeyAllowed = true;
|
||||||
|
m_canBeJSONFlow = false;
|
||||||
|
|
||||||
// eat
|
// eat
|
||||||
Mark mark = INPUT.mark();
|
Mark mark = INPUT.mark();
|
||||||
@@ -105,10 +107,15 @@ namespace YAML
|
|||||||
throw ParserException(INPUT.mark(), ErrorMsg::FLOW_END);
|
throw ParserException(INPUT.mark(), ErrorMsg::FLOW_END);
|
||||||
|
|
||||||
// we might have a solo entry in the flow context
|
// we might have a solo entry in the flow context
|
||||||
if(VerifySimpleKey())
|
if(InFlowContext()) {
|
||||||
m_tokens.push(Token(Token::VALUE, INPUT.mark()));
|
if(m_flows.top() == FLOW_MAP && VerifySimpleKey())
|
||||||
|
m_tokens.push(Token(Token::VALUE, INPUT.mark()));
|
||||||
|
else if(m_flows.top() == FLOW_SEQ)
|
||||||
|
InvalidateSimpleKey();
|
||||||
|
}
|
||||||
|
|
||||||
m_simpleKeyAllowed = false;
|
m_simpleKeyAllowed = false;
|
||||||
|
m_canBeJSONFlow = true;
|
||||||
|
|
||||||
// eat
|
// eat
|
||||||
Mark mark = INPUT.mark();
|
Mark mark = INPUT.mark();
|
||||||
@@ -127,11 +134,16 @@ namespace YAML
|
|||||||
// FlowEntry
|
// FlowEntry
|
||||||
void Scanner::ScanFlowEntry()
|
void Scanner::ScanFlowEntry()
|
||||||
{
|
{
|
||||||
// we might have a solo entry in the flow context
|
// we might have a solo entry in the flow context
|
||||||
if(VerifySimpleKey())
|
if(InFlowContext()) {
|
||||||
m_tokens.push(Token(Token::VALUE, INPUT.mark()));
|
if(m_flows.top() == FLOW_MAP && VerifySimpleKey())
|
||||||
|
m_tokens.push(Token(Token::VALUE, INPUT.mark()));
|
||||||
|
else if(m_flows.top() == FLOW_SEQ)
|
||||||
|
InvalidateSimpleKey();
|
||||||
|
}
|
||||||
|
|
||||||
m_simpleKeyAllowed = true;
|
m_simpleKeyAllowed = true;
|
||||||
|
m_canBeJSONFlow = false;
|
||||||
|
|
||||||
// eat
|
// eat
|
||||||
Mark mark = INPUT.mark();
|
Mark mark = INPUT.mark();
|
||||||
@@ -152,6 +164,7 @@ namespace YAML
|
|||||||
|
|
||||||
PushIndentTo(INPUT.column(), IndentMarker::SEQ);
|
PushIndentTo(INPUT.column(), IndentMarker::SEQ);
|
||||||
m_simpleKeyAllowed = true;
|
m_simpleKeyAllowed = true;
|
||||||
|
m_canBeJSONFlow = false;
|
||||||
|
|
||||||
// eat
|
// eat
|
||||||
Mark mark = INPUT.mark();
|
Mark mark = INPUT.mark();
|
||||||
@@ -184,6 +197,7 @@ namespace YAML
|
|||||||
{
|
{
|
||||||
// and check that simple key
|
// and check that simple key
|
||||||
bool isSimpleKey = VerifySimpleKey();
|
bool isSimpleKey = VerifySimpleKey();
|
||||||
|
m_canBeJSONFlow = false;
|
||||||
|
|
||||||
if(isSimpleKey) {
|
if(isSimpleKey) {
|
||||||
// can't follow a simple key with another simple key (dunno why, though - it seems fine)
|
// can't follow a simple key with another simple key (dunno why, though - it seems fine)
|
||||||
@@ -216,6 +230,7 @@ namespace YAML
|
|||||||
// insert a potential simple key
|
// insert a potential simple key
|
||||||
InsertPotentialSimpleKey();
|
InsertPotentialSimpleKey();
|
||||||
m_simpleKeyAllowed = false;
|
m_simpleKeyAllowed = false;
|
||||||
|
m_canBeJSONFlow = false;
|
||||||
|
|
||||||
// eat the indicator
|
// eat the indicator
|
||||||
Mark mark = INPUT.mark();
|
Mark mark = INPUT.mark();
|
||||||
@@ -223,7 +238,7 @@ namespace YAML
|
|||||||
alias = (indicator == Keys::Alias);
|
alias = (indicator == Keys::Alias);
|
||||||
|
|
||||||
// now eat the content
|
// now eat the content
|
||||||
while(Exp::AlphaNumeric.Matches(INPUT))
|
while(Exp::AlphaNumeric().Matches(INPUT))
|
||||||
name += INPUT.get();
|
name += INPUT.get();
|
||||||
|
|
||||||
// we need to have read SOMETHING!
|
// we need to have read SOMETHING!
|
||||||
@@ -231,7 +246,7 @@ namespace YAML
|
|||||||
throw ParserException(INPUT.mark(), alias ? ErrorMsg::ALIAS_NOT_FOUND : ErrorMsg::ANCHOR_NOT_FOUND);
|
throw ParserException(INPUT.mark(), alias ? ErrorMsg::ALIAS_NOT_FOUND : ErrorMsg::ANCHOR_NOT_FOUND);
|
||||||
|
|
||||||
// and needs to end correctly
|
// and needs to end correctly
|
||||||
if(INPUT && !Exp::AnchorEnd.Matches(INPUT))
|
if(INPUT && !Exp::AnchorEnd().Matches(INPUT))
|
||||||
throw ParserException(INPUT.mark(), alias ? ErrorMsg::CHAR_IN_ALIAS : ErrorMsg::CHAR_IN_ANCHOR);
|
throw ParserException(INPUT.mark(), alias ? ErrorMsg::CHAR_IN_ALIAS : ErrorMsg::CHAR_IN_ANCHOR);
|
||||||
|
|
||||||
// and we're done
|
// and we're done
|
||||||
@@ -243,37 +258,35 @@ namespace YAML
|
|||||||
// Tag
|
// Tag
|
||||||
void Scanner::ScanTag()
|
void Scanner::ScanTag()
|
||||||
{
|
{
|
||||||
std::string handle, suffix;
|
|
||||||
|
|
||||||
// insert a potential simple key
|
// insert a potential simple key
|
||||||
InsertPotentialSimpleKey();
|
InsertPotentialSimpleKey();
|
||||||
m_simpleKeyAllowed = false;
|
m_simpleKeyAllowed = false;
|
||||||
|
m_canBeJSONFlow = false;
|
||||||
|
|
||||||
|
Token token(Token::TAG, INPUT.mark());
|
||||||
|
|
||||||
// eat the indicator
|
// eat the indicator
|
||||||
Mark mark = INPUT.mark();
|
INPUT.get();
|
||||||
handle += INPUT.get();
|
|
||||||
|
|
||||||
// read the handle
|
if(INPUT && INPUT.peek() == Keys::VerbatimTagStart){
|
||||||
while(INPUT && INPUT.peek() != Keys::Tag && !Exp::BlankOrBreak.Matches(INPUT))
|
std::string tag = ScanVerbatimTag(INPUT);
|
||||||
handle += INPUT.get();
|
|
||||||
|
|
||||||
// is there a suffix?
|
token.value = tag;
|
||||||
if(INPUT.peek() == Keys::Tag) {
|
token.data = Tag::VERBATIM;
|
||||||
// eat the indicator
|
|
||||||
handle += INPUT.get();
|
|
||||||
|
|
||||||
// then read it
|
|
||||||
while(INPUT && !Exp::BlankOrBreak.Matches(INPUT))
|
|
||||||
suffix += INPUT.get();
|
|
||||||
} else {
|
} else {
|
||||||
// this is a bit weird: we keep just the '!' as the handle and move the rest to the suffix
|
bool canBeHandle;
|
||||||
suffix = handle.substr(1);
|
token.value = ScanTagHandle(INPUT, canBeHandle);
|
||||||
handle = "!";
|
token.data = (token.value.empty() ? Tag::SECONDARY_HANDLE : Tag::PRIMARY_HANDLE);
|
||||||
|
|
||||||
|
// is there a suffix?
|
||||||
|
if(canBeHandle && INPUT.peek() == Keys::Tag) {
|
||||||
|
// eat the indicator
|
||||||
|
INPUT.get();
|
||||||
|
token.params.push_back(ScanTagSuffix(INPUT));
|
||||||
|
token.data = Tag::NAMED_HANDLE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Token token(Token::TAG, mark);
|
|
||||||
token.value = handle;
|
|
||||||
token.params.push_back(suffix);
|
|
||||||
m_tokens.push(token);
|
m_tokens.push(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,10 +297,10 @@ namespace YAML
|
|||||||
|
|
||||||
// set up the scanning parameters
|
// set up the scanning parameters
|
||||||
ScanScalarParams params;
|
ScanScalarParams params;
|
||||||
params.end = (InFlowContext() ? Exp::EndScalarInFlow : Exp::EndScalar) || (Exp::BlankOrBreak + Exp::Comment);
|
params.end = (InFlowContext() ? Exp::EndScalarInFlow() : Exp::EndScalar()) || (Exp::BlankOrBreak() + Exp::Comment());
|
||||||
params.eatEnd = false;
|
params.eatEnd = false;
|
||||||
params.indent = (InFlowContext() ? 0 : GetTopIndent() + 1);
|
params.indent = (InFlowContext() ? 0 : GetTopIndent() + 1);
|
||||||
params.fold = FOLD_BLOCK;
|
params.fold = FOLD_FLOW;
|
||||||
params.eatLeadingWhitespace = true;
|
params.eatLeadingWhitespace = true;
|
||||||
params.trimTrailingSpaces = true;
|
params.trimTrailingSpaces = true;
|
||||||
params.chomp = STRIP;
|
params.chomp = STRIP;
|
||||||
@@ -302,6 +315,7 @@ namespace YAML
|
|||||||
|
|
||||||
// can have a simple key only if we ended the scalar by starting a new line
|
// can have a simple key only if we ended the scalar by starting a new line
|
||||||
m_simpleKeyAllowed = params.leadingSpaces;
|
m_simpleKeyAllowed = params.leadingSpaces;
|
||||||
|
m_canBeJSONFlow = false;
|
||||||
|
|
||||||
// finally, check and see if we ended on an illegal character
|
// finally, check and see if we ended on an illegal character
|
||||||
//if(Exp::IllegalCharInScalar.Matches(INPUT))
|
//if(Exp::IllegalCharInScalar.Matches(INPUT))
|
||||||
@@ -323,7 +337,7 @@ namespace YAML
|
|||||||
|
|
||||||
// setup the scanning parameters
|
// setup the scanning parameters
|
||||||
ScanScalarParams params;
|
ScanScalarParams params;
|
||||||
params.end = (single ? RegEx(quote) && !Exp::EscSingleQuote : RegEx(quote));
|
params.end = (single ? RegEx(quote) && !Exp::EscSingleQuote() : RegEx(quote));
|
||||||
params.eatEnd = true;
|
params.eatEnd = true;
|
||||||
params.escape = (single ? '\'' : '\\');
|
params.escape = (single ? '\'' : '\\');
|
||||||
params.indent = 0;
|
params.indent = 0;
|
||||||
@@ -344,6 +358,7 @@ namespace YAML
|
|||||||
// and scan
|
// and scan
|
||||||
scalar = ScanScalar(INPUT, params);
|
scalar = ScanScalar(INPUT, params);
|
||||||
m_simpleKeyAllowed = false;
|
m_simpleKeyAllowed = false;
|
||||||
|
m_canBeJSONFlow = true;
|
||||||
|
|
||||||
Token token(Token::SCALAR, mark);
|
Token token(Token::SCALAR, mark);
|
||||||
token.value = scalar;
|
token.value = scalar;
|
||||||
@@ -369,14 +384,14 @@ namespace YAML
|
|||||||
|
|
||||||
// eat chomping/indentation indicators
|
// eat chomping/indentation indicators
|
||||||
params.chomp = CLIP;
|
params.chomp = CLIP;
|
||||||
int n = Exp::Chomp.Match(INPUT);
|
int n = Exp::Chomp().Match(INPUT);
|
||||||
for(int i=0;i<n;i++) {
|
for(int i=0;i<n;i++) {
|
||||||
char ch = INPUT.get();
|
char ch = INPUT.get();
|
||||||
if(ch == '+')
|
if(ch == '+')
|
||||||
params.chomp = KEEP;
|
params.chomp = KEEP;
|
||||||
else if(ch == '-')
|
else if(ch == '-')
|
||||||
params.chomp = STRIP;
|
params.chomp = STRIP;
|
||||||
else if(Exp::Digit.Matches(ch)) {
|
else if(Exp::Digit().Matches(ch)) {
|
||||||
if(ch == '0')
|
if(ch == '0')
|
||||||
throw ParserException(INPUT.mark(), ErrorMsg::ZERO_INDENT_IN_BLOCK);
|
throw ParserException(INPUT.mark(), ErrorMsg::ZERO_INDENT_IN_BLOCK);
|
||||||
|
|
||||||
@@ -386,16 +401,16 @@ namespace YAML
|
|||||||
}
|
}
|
||||||
|
|
||||||
// now eat whitespace
|
// now eat whitespace
|
||||||
while(Exp::Blank.Matches(INPUT))
|
while(Exp::Blank().Matches(INPUT))
|
||||||
INPUT.eat(1);
|
INPUT.eat(1);
|
||||||
|
|
||||||
// and comments to the end of the line
|
// and comments to the end of the line
|
||||||
if(Exp::Comment.Matches(INPUT))
|
if(Exp::Comment().Matches(INPUT))
|
||||||
while(INPUT && !Exp::Break.Matches(INPUT))
|
while(INPUT && !Exp::Break().Matches(INPUT))
|
||||||
INPUT.eat(1);
|
INPUT.eat(1);
|
||||||
|
|
||||||
// if it's not a line break, then we ran into a bad character inline
|
// if it's not a line break, then we ran into a bad character inline
|
||||||
if(INPUT && !Exp::Break.Matches(INPUT))
|
if(INPUT && !Exp::Break().Matches(INPUT))
|
||||||
throw ParserException(INPUT.mark(), ErrorMsg::CHAR_IN_BLOCK);
|
throw ParserException(INPUT.mark(), ErrorMsg::CHAR_IN_BLOCK);
|
||||||
|
|
||||||
// set the initial indentation
|
// set the initial indentation
|
||||||
@@ -410,6 +425,7 @@ namespace YAML
|
|||||||
|
|
||||||
// simple keys always ok after block scalars (since we're gonna start a new line anyways)
|
// simple keys always ok after block scalars (since we're gonna start a new line anyways)
|
||||||
m_simpleKeyAllowed = true;
|
m_simpleKeyAllowed = true;
|
||||||
|
m_canBeJSONFlow = false;
|
||||||
|
|
||||||
Token token(Token::SCALAR, mark);
|
Token token(Token::SCALAR, mark);
|
||||||
token.value = scalar;
|
token.value = scalar;
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
#include "crt.h"
|
|
||||||
#include "sequence.h"
|
#include "sequence.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
@@ -60,7 +59,7 @@ namespace YAML
|
|||||||
return m_data.size();
|
return m_data.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sequence::Parse(Scanner *pScanner, const ParserState& state)
|
void Sequence::Parse(Scanner *pScanner, ParserState& state)
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
|
|
||||||
@@ -72,10 +71,11 @@ namespace YAML
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sequence::ParseBlock(Scanner *pScanner, const ParserState& state)
|
void Sequence::ParseBlock(Scanner *pScanner, ParserState& state)
|
||||||
{
|
{
|
||||||
// eat start token
|
// eat start token
|
||||||
pScanner->pop();
|
pScanner->pop();
|
||||||
|
state.PushCollectionType(ParserState::BLOCK_SEQ);
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
if(pScanner->empty())
|
if(pScanner->empty())
|
||||||
@@ -101,12 +101,15 @@ namespace YAML
|
|||||||
|
|
||||||
pNode->Parse(pScanner, state);
|
pNode->Parse(pScanner, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state.PopCollectionType(ParserState::BLOCK_SEQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sequence::ParseFlow(Scanner *pScanner, const ParserState& state)
|
void Sequence::ParseFlow(Scanner *pScanner, ParserState& state)
|
||||||
{
|
{
|
||||||
// eat start token
|
// eat start token
|
||||||
pScanner->pop();
|
pScanner->pop();
|
||||||
|
state.PushCollectionType(ParserState::FLOW_SEQ);
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
if(pScanner->empty())
|
if(pScanner->empty())
|
||||||
@@ -130,6 +133,8 @@ namespace YAML
|
|||||||
else if(token.type != Token::FLOW_SEQ_END)
|
else if(token.type != Token::FLOW_SEQ_END)
|
||||||
throw ParserException(token.mark, ErrorMsg::END_OF_SEQ_FLOW);
|
throw ParserException(token.mark, ErrorMsg::END_OF_SEQ_FLOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state.PopCollectionType(ParserState::FLOW_SEQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sequence::Write(Emitter& out) const
|
void Sequence::Write(Emitter& out) const
|
||||||
|
@@ -26,7 +26,7 @@ namespace YAML
|
|||||||
virtual Node *GetNode(std::size_t i) const;
|
virtual Node *GetNode(std::size_t i) const;
|
||||||
virtual std::size_t GetSize() const;
|
virtual std::size_t GetSize() const;
|
||||||
|
|
||||||
virtual void Parse(Scanner *pScanner, const ParserState& state);
|
virtual void Parse(Scanner *pScanner, ParserState& state);
|
||||||
virtual void Write(Emitter& out) const;
|
virtual void Write(Emitter& out) const;
|
||||||
|
|
||||||
virtual bool IsSequence() const { return true; }
|
virtual bool IsSequence() const { return true; }
|
||||||
@@ -38,8 +38,8 @@ namespace YAML
|
|||||||
virtual int Compare(Map *) { return -1; }
|
virtual int Compare(Map *) { return -1; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ParseBlock(Scanner *pScanner, const ParserState& state);
|
void ParseBlock(Scanner *pScanner, ParserState& state);
|
||||||
void ParseFlow(Scanner *pScanner, const ParserState& state);
|
void ParseFlow(Scanner *pScanner, ParserState& state);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector <Node *> m_data;
|
std::vector <Node *> m_data;
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
#include "crt.h"
|
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
@@ -13,9 +12,11 @@ namespace YAML
|
|||||||
|
|
||||||
void Scanner::SimpleKey::Validate()
|
void Scanner::SimpleKey::Validate()
|
||||||
{
|
{
|
||||||
// Note: pIndent will *not* be garbage here; see below
|
// Note: pIndent will *not* be garbage here;
|
||||||
|
// we "garbage collect" them so we can
|
||||||
|
// always refer to them
|
||||||
if(pIndent)
|
if(pIndent)
|
||||||
pIndent->isValid = true;
|
pIndent->status = IndentMarker::VALID;
|
||||||
if(pMapStart)
|
if(pMapStart)
|
||||||
pMapStart->status = Token::VALID;
|
pMapStart->status = Token::VALID;
|
||||||
if(pKey)
|
if(pKey)
|
||||||
@@ -24,8 +25,8 @@ namespace YAML
|
|||||||
|
|
||||||
void Scanner::SimpleKey::Invalidate()
|
void Scanner::SimpleKey::Invalidate()
|
||||||
{
|
{
|
||||||
// Note: pIndent might be a garbage pointer here, but that's ok
|
if(pIndent)
|
||||||
// An indent will only be popped if the simple key is invalid
|
pIndent->status = IndentMarker::INVALID;
|
||||||
if(pMapStart)
|
if(pMapStart)
|
||||||
pMapStart->status = Token::INVALID;
|
pMapStart->status = Token::INVALID;
|
||||||
if(pKey)
|
if(pKey)
|
||||||
@@ -38,9 +39,6 @@ namespace YAML
|
|||||||
if(!m_simpleKeyAllowed)
|
if(!m_simpleKeyAllowed)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(InFlowContext() && m_flows.top() != FLOW_MAP)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return !ExistsActiveSimpleKey();
|
return !ExistsActiveSimpleKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,11 +65,13 @@ namespace YAML
|
|||||||
SimpleKey key(INPUT.mark(), GetFlowLevel());
|
SimpleKey key(INPUT.mark(), GetFlowLevel());
|
||||||
|
|
||||||
// first add a map start, if necessary
|
// first add a map start, if necessary
|
||||||
key.pIndent = PushIndentTo(INPUT.column(), IndentMarker::MAP);
|
if(InBlockContext()) {
|
||||||
if(key.pIndent) {
|
key.pIndent = PushIndentTo(INPUT.column(), IndentMarker::MAP);
|
||||||
key.pIndent->isValid = false;
|
if(key.pIndent) {
|
||||||
key.pMapStart = key.pIndent->pStartToken;
|
key.pIndent->status = IndentMarker::UNKNOWN;
|
||||||
key.pMapStart->status = Token::UNVERIFIED;
|
key.pMapStart = key.pIndent->pStartToken;
|
||||||
|
key.pMapStart->status = Token::UNVERIFIED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// then add the (now unverified) key
|
// then add the (now unverified) key
|
||||||
@@ -136,3 +136,4 @@ namespace YAML
|
|||||||
m_simpleKeys.pop();
|
m_simpleKeys.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
#include "crt.h"
|
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "exp.h"
|
#include "exp.h"
|
||||||
|
@@ -30,6 +30,11 @@ namespace YAML
|
|||||||
++m_offset;
|
++m_offset;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StringCharSource& operator += (std::size_t offset) {
|
||||||
|
m_offset += offset;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
const char *m_str;
|
const char *m_str;
|
||||||
std::size_t m_size;
|
std::size_t m_size;
|
||||||
|
50
src/tag.cpp
Normal file
50
src/tag.cpp
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#include "tag.h"
|
||||||
|
#include "token.h"
|
||||||
|
#include "parserstate.h"
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace YAML
|
||||||
|
{
|
||||||
|
Tag::Tag(const Token& token): type(static_cast<TYPE>(token.data))
|
||||||
|
{
|
||||||
|
switch(type) {
|
||||||
|
case VERBATIM:
|
||||||
|
value = token.value;
|
||||||
|
break;
|
||||||
|
case PRIMARY_HANDLE:
|
||||||
|
value = token.value;
|
||||||
|
break;
|
||||||
|
case SECONDARY_HANDLE:
|
||||||
|
value = token.value;
|
||||||
|
break;
|
||||||
|
case NAMED_HANDLE:
|
||||||
|
handle = token.value;
|
||||||
|
value = token.params[0];
|
||||||
|
break;
|
||||||
|
case NON_SPECIFIC:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string Tag::Translate(const ParserState& state)
|
||||||
|
{
|
||||||
|
switch(type) {
|
||||||
|
case VERBATIM:
|
||||||
|
return value;
|
||||||
|
case PRIMARY_HANDLE:
|
||||||
|
return state.TranslateTagHandle("!") + value;
|
||||||
|
case SECONDARY_HANDLE:
|
||||||
|
return state.TranslateTagHandle("!!") + value;
|
||||||
|
case NAMED_HANDLE:
|
||||||
|
return state.TranslateTagHandle("!" + handle + "!") + value;
|
||||||
|
case NON_SPECIFIC:
|
||||||
|
// TODO:
|
||||||
|
return "!";
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
26
src/tag.h
Normal file
26
src/tag.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
#define TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace YAML
|
||||||
|
{
|
||||||
|
struct Token;
|
||||||
|
struct ParserState;
|
||||||
|
|
||||||
|
struct Tag {
|
||||||
|
enum TYPE {
|
||||||
|
VERBATIM, PRIMARY_HANDLE, SECONDARY_HANDLE, NAMED_HANDLE, NON_SPECIFIC
|
||||||
|
};
|
||||||
|
|
||||||
|
Tag(const Token& token);
|
||||||
|
const std::string Translate(const ParserState& state);
|
||||||
|
|
||||||
|
TYPE type;
|
||||||
|
std::string handle, value;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
@@ -24,6 +24,7 @@ namespace YAML
|
|||||||
"FLOW_MAP_START",
|
"FLOW_MAP_START",
|
||||||
"FLOW_SEQ_END",
|
"FLOW_SEQ_END",
|
||||||
"FLOW_MAP_END",
|
"FLOW_MAP_END",
|
||||||
|
"FLOW_MAP_COMPACT",
|
||||||
"FLOW_ENTRY",
|
"FLOW_ENTRY",
|
||||||
"KEY",
|
"KEY",
|
||||||
"VALUE",
|
"VALUE",
|
||||||
@@ -49,6 +50,7 @@ namespace YAML
|
|||||||
FLOW_MAP_START,
|
FLOW_MAP_START,
|
||||||
FLOW_SEQ_END,
|
FLOW_SEQ_END,
|
||||||
FLOW_MAP_END,
|
FLOW_MAP_END,
|
||||||
|
FLOW_MAP_COMPACT,
|
||||||
FLOW_ENTRY,
|
FLOW_ENTRY,
|
||||||
KEY,
|
KEY,
|
||||||
VALUE,
|
VALUE,
|
||||||
@@ -59,7 +61,7 @@ namespace YAML
|
|||||||
};
|
};
|
||||||
|
|
||||||
// data
|
// data
|
||||||
Token(TYPE type_, const Mark& mark_): status(VALID), type(type_), mark(mark_) {}
|
Token(TYPE type_, const Mark& mark_): status(VALID), type(type_), mark(mark_), data(0) {}
|
||||||
|
|
||||||
friend std::ostream& operator << (std::ostream& out, const Token& token) {
|
friend std::ostream& operator << (std::ostream& out, const Token& token) {
|
||||||
out << TokenNames[token.type] << std::string(": ") << token.value;
|
out << TokenNames[token.type] << std::string(": ") << token.value;
|
||||||
@@ -73,6 +75,7 @@ namespace YAML
|
|||||||
Mark mark;
|
Mark mark;
|
||||||
std::string value;
|
std::string value;
|
||||||
std::vector <std::string> params;
|
std::vector <std::string> params;
|
||||||
|
int data;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
226
test.vcproj
Normal file
226
test.vcproj
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="9.00"
|
||||||
|
Name="test"
|
||||||
|
ProjectGUID="{D1108F40-6ADF-467E-A95A-236C39A515C5}"
|
||||||
|
RootNamespace="test"
|
||||||
|
TargetFrameworkVersion="196613"
|
||||||
|
>
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"
|
||||||
|
/>
|
||||||
|
</Platforms>
|
||||||
|
<ToolFiles>
|
||||||
|
</ToolFiles>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="2"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
AdditionalOptions="/D_SCL_SECURE_NO_WARNINGS"
|
||||||
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories="include"
|
||||||
|
MinimalRebuild="true"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
WarningLevel="3"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
DisableSpecificWarnings="4127;4355"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalDependencies="yamlcppd.lib"
|
||||||
|
AdditionalLibraryDirectories="lib"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="2"
|
||||||
|
WholeProgramOptimization="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
AdditionalOptions="/D_SCL_SECURE_NO_WARNINGS"
|
||||||
|
Optimization="2"
|
||||||
|
EnableIntrinsicFunctions="true"
|
||||||
|
AdditionalIncludeDirectories="include"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
EnableFunctionLevelLinking="true"
|
||||||
|
WarningLevel="3"
|
||||||
|
DebugInformationFormat="3"
|
||||||
|
DisableSpecificWarnings="4127;4355"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalDependencies="yamlcpp.lib"
|
||||||
|
AdditionalLibraryDirectories="lib"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
OptimizeReferences="2"
|
||||||
|
EnableCOMDATFolding="2"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\test\emittertests.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\test\main.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\test\parsertests.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\test\spectests.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\test\tests.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Header Files"
|
||||||
|
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||||
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\test\emittertests.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\test\parsertests.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\test\spectests.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\test\tests.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Resource Files"
|
||||||
|
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||||
|
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||||
|
>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
10
test/CMakeLists.txt
Normal file
10
test/CMakeLists.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
file(GLOB test_headers [a-z]*.h)
|
||||||
|
file(GLOB test_sources [a-z]*.cpp)
|
||||||
|
|
||||||
|
add_executable(run-tests
|
||||||
|
${test_sources}
|
||||||
|
${test_headers}
|
||||||
|
)
|
||||||
|
target_link_libraries(run-tests yaml-cpp)
|
||||||
|
|
||||||
|
add_test(yaml-reader-test run-tests)
|
@@ -9,7 +9,7 @@ namespace Test
|
|||||||
|
|
||||||
void SimpleScalar(YAML::Emitter& out, std::string& desiredOutput) {
|
void SimpleScalar(YAML::Emitter& out, std::string& desiredOutput) {
|
||||||
out << "Hello, World!";
|
out << "Hello, World!";
|
||||||
desiredOutput = "Hello, World!";
|
desiredOutput = "--- Hello, World!";
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleSeq(YAML::Emitter& out, std::string& desiredOutput) {
|
void SimpleSeq(YAML::Emitter& out, std::string& desiredOutput) {
|
||||||
@@ -19,7 +19,7 @@ namespace Test
|
|||||||
out << "milk";
|
out << "milk";
|
||||||
out << YAML::EndSeq;
|
out << YAML::EndSeq;
|
||||||
|
|
||||||
desiredOutput = "- eggs\n- bread\n- milk";
|
desiredOutput = "---\n- eggs\n- bread\n- milk";
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleFlowSeq(YAML::Emitter& out, std::string& desiredOutput) {
|
void SimpleFlowSeq(YAML::Emitter& out, std::string& desiredOutput) {
|
||||||
@@ -30,7 +30,7 @@ namespace Test
|
|||||||
out << "Moe";
|
out << "Moe";
|
||||||
out << YAML::EndSeq;
|
out << YAML::EndSeq;
|
||||||
|
|
||||||
desiredOutput = "[Larry, Curly, Moe]";
|
desiredOutput = "--- [Larry, Curly, Moe]";
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmptyFlowSeq(YAML::Emitter& out, std::string& desiredOutput) {
|
void EmptyFlowSeq(YAML::Emitter& out, std::string& desiredOutput) {
|
||||||
@@ -38,7 +38,7 @@ namespace Test
|
|||||||
out << YAML::BeginSeq;
|
out << YAML::BeginSeq;
|
||||||
out << YAML::EndSeq;
|
out << YAML::EndSeq;
|
||||||
|
|
||||||
desiredOutput = "[]";
|
desiredOutput = "--- []";
|
||||||
}
|
}
|
||||||
|
|
||||||
void NestedBlockSeq(YAML::Emitter& out, std::string& desiredOutput) {
|
void NestedBlockSeq(YAML::Emitter& out, std::string& desiredOutput) {
|
||||||
@@ -47,7 +47,7 @@ namespace Test
|
|||||||
out << YAML::BeginSeq << "subitem 1" << "subitem 2" << YAML::EndSeq;
|
out << YAML::BeginSeq << "subitem 1" << "subitem 2" << YAML::EndSeq;
|
||||||
out << YAML::EndSeq;
|
out << YAML::EndSeq;
|
||||||
|
|
||||||
desiredOutput = "- item 1\n-\n - subitem 1\n - subitem 2";
|
desiredOutput = "---\n- item 1\n-\n - subitem 1\n - subitem 2";
|
||||||
}
|
}
|
||||||
|
|
||||||
void NestedFlowSeq(YAML::Emitter& out, std::string& desiredOutput) {
|
void NestedFlowSeq(YAML::Emitter& out, std::string& desiredOutput) {
|
||||||
@@ -56,7 +56,7 @@ namespace Test
|
|||||||
out << YAML::Flow << YAML::BeginSeq << "two" << "three" << YAML::EndSeq;
|
out << YAML::Flow << YAML::BeginSeq << "two" << "three" << YAML::EndSeq;
|
||||||
out << YAML::EndSeq;
|
out << YAML::EndSeq;
|
||||||
|
|
||||||
desiredOutput = "- one\n- [two, three]";
|
desiredOutput = "---\n- one\n- [two, three]";
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleMap(YAML::Emitter& out, std::string& desiredOutput) {
|
void SimpleMap(YAML::Emitter& out, std::string& desiredOutput) {
|
||||||
@@ -67,7 +67,7 @@ namespace Test
|
|||||||
out << YAML::Value << "3B";
|
out << YAML::Value << "3B";
|
||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
|
|
||||||
desiredOutput = "name: Ryan Braun\nposition: 3B";
|
desiredOutput = "---\nname: Ryan Braun\nposition: 3B";
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleFlowMap(YAML::Emitter& out, std::string& desiredOutput) {
|
void SimpleFlowMap(YAML::Emitter& out, std::string& desiredOutput) {
|
||||||
@@ -79,7 +79,7 @@ namespace Test
|
|||||||
out << YAML::Value << "blue";
|
out << YAML::Value << "blue";
|
||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
|
|
||||||
desiredOutput = "{shape: square, color: blue}";
|
desiredOutput = "--- {shape: square, color: blue}";
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapAndList(YAML::Emitter& out, std::string& desiredOutput) {
|
void MapAndList(YAML::Emitter& out, std::string& desiredOutput) {
|
||||||
@@ -90,7 +90,7 @@ namespace Test
|
|||||||
out << YAML::Value << YAML::BeginSeq << "Sasha" << "Malia" << YAML::EndSeq;
|
out << YAML::Value << YAML::BeginSeq << "Sasha" << "Malia" << YAML::EndSeq;
|
||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
|
|
||||||
desiredOutput = "name: Barack Obama\nchildren:\n - Sasha\n - Malia";
|
desiredOutput = "---\nname: Barack Obama\nchildren:\n - Sasha\n - Malia";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListAndMap(YAML::Emitter& out, std::string& desiredOutput) {
|
void ListAndMap(YAML::Emitter& out, std::string& desiredOutput) {
|
||||||
@@ -103,7 +103,7 @@ namespace Test
|
|||||||
out << "item 2";
|
out << "item 2";
|
||||||
out << YAML::EndSeq;
|
out << YAML::EndSeq;
|
||||||
|
|
||||||
desiredOutput = "- item 1\n-\n pens: 8\n pencils: 14\n- item 2";
|
desiredOutput = "---\n- item 1\n-\n pens: 8\n pencils: 14\n- item 2";
|
||||||
}
|
}
|
||||||
|
|
||||||
void NestedBlockMap(YAML::Emitter& out, std::string& desiredOutput) {
|
void NestedBlockMap(YAML::Emitter& out, std::string& desiredOutput) {
|
||||||
@@ -119,7 +119,7 @@ namespace Test
|
|||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
|
|
||||||
desiredOutput = "name: Fred\ngrades:\n algebra: A\n physics: C+\n literature: B";
|
desiredOutput = "---\nname: Fred\ngrades:\n algebra: A\n physics: C+\n literature: B";
|
||||||
}
|
}
|
||||||
|
|
||||||
void NestedFlowMap(YAML::Emitter& out, std::string& desiredOutput) {
|
void NestedFlowMap(YAML::Emitter& out, std::string& desiredOutput) {
|
||||||
@@ -136,7 +136,7 @@ namespace Test
|
|||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
|
|
||||||
desiredOutput = "{name: Fred, grades: {algebra: A, physics: C+, literature: B}}";
|
desiredOutput = "--- {name: Fred, grades: {algebra: A, physics: C+, literature: B}}";
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapListMix(YAML::Emitter& out, std::string& desiredOutput) {
|
void MapListMix(YAML::Emitter& out, std::string& desiredOutput) {
|
||||||
@@ -149,7 +149,7 @@ namespace Test
|
|||||||
out << YAML::Key << "invincible" << YAML::Value << YAML::OnOffBool << false;
|
out << YAML::Key << "invincible" << YAML::Value << YAML::OnOffBool << false;
|
||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
|
|
||||||
desiredOutput = "name: Bob\nposition: [2, 4]\ninvincible: off";
|
desiredOutput = "---\nname: Bob\nposition: [2, 4]\ninvincible: off";
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleLongKey(YAML::Emitter& out, std::string& desiredOutput)
|
void SimpleLongKey(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
@@ -162,7 +162,7 @@ namespace Test
|
|||||||
out << YAML::Value << 145;
|
out << YAML::Value << 145;
|
||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
|
|
||||||
desiredOutput = "? height\n: 5'9\"\n? weight\n: 145";
|
desiredOutput = "---\n? height\n: 5'9\"\n? weight\n: 145";
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleLongKey(YAML::Emitter& out, std::string& desiredOutput)
|
void SingleLongKey(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
@@ -176,7 +176,7 @@ namespace Test
|
|||||||
out << YAML::Value << 145;
|
out << YAML::Value << 145;
|
||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
|
|
||||||
desiredOutput = "age: 24\n? height\n: 5'9\"\nweight: 145";
|
desiredOutput = "---\nage: 24\n? height\n: 5'9\"\nweight: 145";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComplexLongKey(YAML::Emitter& out, std::string& desiredOutput)
|
void ComplexLongKey(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
@@ -189,7 +189,7 @@ namespace Test
|
|||||||
out << YAML::Value << "demon";
|
out << YAML::Value << "demon";
|
||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
|
|
||||||
desiredOutput = "?\n - 1\n - 3\n: monster\n? [2, 0]\n: demon";
|
desiredOutput = "---\n?\n - 1\n - 3\n: monster\n? [2, 0]\n: demon";
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoLongKey(YAML::Emitter& out, std::string& desiredOutput)
|
void AutoLongKey(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
@@ -203,7 +203,7 @@ namespace Test
|
|||||||
out << YAML::Value << "angel";
|
out << YAML::Value << "angel";
|
||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
|
|
||||||
desiredOutput = "?\n - 1\n - 3\n: monster\n? [2, 0]\n: demon\nthe origin: angel";
|
desiredOutput = "---\n?\n - 1\n - 3\n: monster\n? [2, 0]\n: demon\nthe origin: angel";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScalarFormat(YAML::Emitter& out, std::string& desiredOutput)
|
void ScalarFormat(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
@@ -217,7 +217,7 @@ namespace Test
|
|||||||
out << YAML::Literal << "literal scalar\nthat may span\nmany, many\nlines and have \"whatever\" crazy\tsymbols that we like";
|
out << YAML::Literal << "literal scalar\nthat may span\nmany, many\nlines and have \"whatever\" crazy\tsymbols that we like";
|
||||||
out << YAML::EndSeq;
|
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 = "---\n- 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";
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoLongKeyScalar(YAML::Emitter& out, std::string& desiredOutput)
|
void AutoLongKeyScalar(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
@@ -227,7 +227,7 @@ namespace Test
|
|||||||
out << YAML::Value << "and its value";
|
out << YAML::Value << "and its value";
|
||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
|
|
||||||
desiredOutput = "? |\n multi-line\n scalar\n: and its value";
|
desiredOutput = "---\n? |\n multi-line\n scalar\n: and its value";
|
||||||
}
|
}
|
||||||
|
|
||||||
void LongKeyFlowMap(YAML::Emitter& out, std::string& desiredOutput)
|
void LongKeyFlowMap(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
@@ -240,7 +240,7 @@ namespace Test
|
|||||||
out << YAML::Value << "and its value";
|
out << YAML::Value << "and its value";
|
||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
|
|
||||||
desiredOutput = "{simple key: and value, ? long key: and its value}";
|
desiredOutput = "--- {simple key: and value, ? long key: and its value}";
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockMapAsKey(YAML::Emitter& out, std::string& desiredOutput)
|
void BlockMapAsKey(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
@@ -255,7 +255,7 @@ namespace Test
|
|||||||
out << "total value";
|
out << "total value";
|
||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
|
|
||||||
desiredOutput = "?\n key: value\n next key: next value\n: total value";
|
desiredOutput = "---\n?\n key: value\n next key: next value\n: total value";
|
||||||
}
|
}
|
||||||
|
|
||||||
void AliasAndAnchor(YAML::Emitter& out, std::string& desiredOutput)
|
void AliasAndAnchor(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
@@ -269,7 +269,7 @@ namespace Test
|
|||||||
out << YAML::Alias("fred");
|
out << YAML::Alias("fred");
|
||||||
out << YAML::EndSeq;
|
out << YAML::EndSeq;
|
||||||
|
|
||||||
desiredOutput = "- &fred\n name: Fred\n age: 42\n- *fred";
|
desiredOutput = "---\n- &fred\n name: Fred\n age: 42\n- *fred";
|
||||||
}
|
}
|
||||||
|
|
||||||
void AliasAndAnchorWithNull(YAML::Emitter& out, std::string& desiredOutput)
|
void AliasAndAnchorWithNull(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
@@ -279,7 +279,98 @@ namespace Test
|
|||||||
out << YAML::Alias("fred");
|
out << YAML::Alias("fred");
|
||||||
out << YAML::EndSeq;
|
out << YAML::EndSeq;
|
||||||
|
|
||||||
desiredOutput = "- &fred ~\n- *fred";
|
desiredOutput = "---\n- &fred ~\n- *fred";
|
||||||
|
}
|
||||||
|
|
||||||
|
void SimpleVerbatimTag(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
|
{
|
||||||
|
out << YAML::VerbatimTag("!foo") << "bar";
|
||||||
|
|
||||||
|
desiredOutput = "--- !<!foo> bar";
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerbatimTagInBlockSeq(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
|
{
|
||||||
|
out << YAML::BeginSeq;
|
||||||
|
out << YAML::VerbatimTag("!foo") << "bar";
|
||||||
|
out << "baz";
|
||||||
|
out << YAML::EndSeq;
|
||||||
|
|
||||||
|
desiredOutput = "---\n- !<!foo> bar\n- baz";
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerbatimTagInFlowSeq(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
|
{
|
||||||
|
out << YAML::Flow << YAML::BeginSeq;
|
||||||
|
out << YAML::VerbatimTag("!foo") << "bar";
|
||||||
|
out << "baz";
|
||||||
|
out << YAML::EndSeq;
|
||||||
|
|
||||||
|
desiredOutput = "--- [!<!foo> bar, baz]";
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerbatimTagInFlowSeqWithNull(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
|
{
|
||||||
|
out << YAML::Flow << YAML::BeginSeq;
|
||||||
|
out << YAML::VerbatimTag("!foo") << YAML::Null;
|
||||||
|
out << "baz";
|
||||||
|
out << YAML::EndSeq;
|
||||||
|
|
||||||
|
desiredOutput = "--- [!<!foo> ~, baz]";
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerbatimTagInBlockMap(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
|
{
|
||||||
|
out << YAML::BeginMap;
|
||||||
|
out << YAML::Key << YAML::VerbatimTag("!foo") << "bar";
|
||||||
|
out << YAML::Value << YAML::VerbatimTag("!waz") << "baz";
|
||||||
|
out << YAML::EndMap;
|
||||||
|
|
||||||
|
desiredOutput = "---\n!<!foo> bar: !<!waz> baz";
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerbatimTagInFlowMap(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
|
{
|
||||||
|
out << YAML::Flow << YAML::BeginMap;
|
||||||
|
out << YAML::Key << YAML::VerbatimTag("!foo") << "bar";
|
||||||
|
out << YAML::Value << "baz";
|
||||||
|
out << YAML::EndMap;
|
||||||
|
|
||||||
|
desiredOutput = "--- {!<!foo> bar: baz}";
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerbatimTagInFlowMapWithNull(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
|
{
|
||||||
|
out << YAML::Flow << YAML::BeginMap;
|
||||||
|
out << YAML::Key << YAML::VerbatimTag("!foo") << YAML::Null;
|
||||||
|
out << YAML::Value << "baz";
|
||||||
|
out << YAML::EndMap;
|
||||||
|
|
||||||
|
desiredOutput = "--- {!<!foo> ~: baz}";
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerbatimTagWithEmptySeq(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
|
{
|
||||||
|
out << YAML::VerbatimTag("!foo") << YAML::BeginSeq << YAML::EndSeq;
|
||||||
|
|
||||||
|
desiredOutput = "--- !<!foo>\n[]";
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerbatimTagWithEmptyMap(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
|
{
|
||||||
|
out << YAML::VerbatimTag("!bar") << YAML::BeginMap << YAML::EndMap;
|
||||||
|
|
||||||
|
desiredOutput = "--- !<!bar>\n{}";
|
||||||
|
}
|
||||||
|
|
||||||
|
void VerbatimTagWithEmptySeqAndMap(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
|
{
|
||||||
|
out << YAML::BeginSeq;
|
||||||
|
out << YAML::VerbatimTag("!foo") << YAML::BeginSeq << YAML::EndSeq;
|
||||||
|
out << YAML::VerbatimTag("!bar") << YAML::BeginMap << YAML::EndMap;
|
||||||
|
out << YAML::EndSeq;
|
||||||
|
|
||||||
|
desiredOutput = "---\n- !<!foo>\n []\n- !<!bar>\n {}";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComplexDoc(YAML::Emitter& out, std::string& desiredOutput)
|
void ComplexDoc(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
@@ -335,7 +426,7 @@ namespace Test
|
|||||||
out << YAML::Value << YAML::Alias("id001");
|
out << YAML::Value << YAML::Alias("id001");
|
||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
|
|
||||||
desiredOutput = "receipt: Oz-Ware Purchase Invoice\ndate: 2007-08-06\ncustomer:\n given: Dorothy\n family: Gale\nitems:\n -\n part_no: A4786\n descrip: Water Bucket (Filled)\n price: 1.47\n quantity: 4\n -\n part_no: E1628\n descrip: High Heeled \"Ruby\" Slippers\n price: 100.27\n quantity: 1\nbill-to: &id001\n street: |\n 123 Tornado Alley\n Suite 16\n city: East Westville\n state: KS\nship-to: *id001";
|
desiredOutput = "---\nreceipt: Oz-Ware Purchase Invoice\ndate: 2007-08-06\ncustomer:\n given: Dorothy\n family: Gale\nitems:\n -\n part_no: A4786\n descrip: Water Bucket (Filled)\n price: 1.47\n quantity: 4\n -\n part_no: E1628\n descrip: High Heeled \"Ruby\" Slippers\n price: 100.27\n quantity: 1\nbill-to: &id001\n street: |\n 123 Tornado Alley\n Suite 16\n city: East Westville\n state: KS\nship-to: *id001";
|
||||||
}
|
}
|
||||||
|
|
||||||
void STLContainers(YAML::Emitter& out, std::string& desiredOutput)
|
void STLContainers(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
@@ -355,7 +446,7 @@ namespace Test
|
|||||||
out << ages;
|
out << ages;
|
||||||
out << YAML::EndSeq;
|
out << YAML::EndSeq;
|
||||||
|
|
||||||
desiredOutput = "- [2, 3, 5, 7, 11, 13]\n-\n Daniel: 26\n Jesse: 24";
|
desiredOutput = "---\n- [2, 3, 5, 7, 11, 13]\n-\n Daniel: 26\n Jesse: 24";
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleComment(YAML::Emitter& out, std::string& desiredOutput)
|
void SimpleComment(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
@@ -365,7 +456,7 @@ namespace Test
|
|||||||
out << YAML::Value << "least squares" << YAML::Comment("should we change this method?");
|
out << YAML::Value << "least squares" << YAML::Comment("should we change this method?");
|
||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
|
|
||||||
desiredOutput = "method: least squares # should we change this method?";
|
desiredOutput = "---\nmethod: least squares # should we change this method?";
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiLineComment(YAML::Emitter& out, std::string& desiredOutput)
|
void MultiLineComment(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
@@ -375,7 +466,7 @@ namespace Test
|
|||||||
out << "item 2";
|
out << "item 2";
|
||||||
out << YAML::EndSeq;
|
out << YAML::EndSeq;
|
||||||
|
|
||||||
desiredOutput = "- item 1 # really really long\n # comment that couldn't possibly\n # fit on one line\n- item 2";
|
desiredOutput = "---\n- item 1 # really really long\n # comment that couldn't possibly\n # fit on one line\n- item 2";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComplexComments(YAML::Emitter& out, std::string& desiredOutput)
|
void ComplexComments(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
@@ -385,7 +476,7 @@ namespace Test
|
|||||||
out << YAML::Value << "value";
|
out << YAML::Value << "value";
|
||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
|
|
||||||
desiredOutput = "? long key # long key\n: value";
|
desiredOutput = "---\n? long key # long key\n: value";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Indentation(YAML::Emitter& out, std::string& desiredOutput)
|
void Indentation(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
@@ -398,7 +489,7 @@ namespace Test
|
|||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
out << YAML::EndSeq;
|
out << YAML::EndSeq;
|
||||||
|
|
||||||
desiredOutput = "-\n key 1: value 1\n key 2:\n - a\n - b\n - c";
|
desiredOutput = "---\n-\n key 1: value 1\n key 2:\n - a\n - b\n - c";
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleGlobalSettings(YAML::Emitter& out, std::string& desiredOutput)
|
void SimpleGlobalSettings(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
@@ -413,7 +504,7 @@ namespace Test
|
|||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
out << YAML::EndSeq;
|
out << YAML::EndSeq;
|
||||||
|
|
||||||
desiredOutput = "-\n ? key 1\n : value 1\n ? key 2\n : [a, b, c]";
|
desiredOutput = "---\n-\n ? key 1\n : value 1\n ? key 2\n : [a, b, c]";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComplexGlobalSettings(YAML::Emitter& out, std::string& desiredOutput)
|
void ComplexGlobalSettings(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
@@ -432,7 +523,7 @@ namespace Test
|
|||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
out << YAML::EndSeq;
|
out << YAML::EndSeq;
|
||||||
|
|
||||||
desiredOutput = "-\n key 1: value 1\n key 2: [a, b, c]\n-\n ? [1, 2]\n :\n a: b";
|
desiredOutput = "---\n-\n key 1: value 1\n key 2: [a, b, c]\n-\n ? [1, 2]\n :\n a: b";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Null(YAML::Emitter& out, std::string& desiredOutput)
|
void Null(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
@@ -445,7 +536,95 @@ namespace Test
|
|||||||
out << YAML::EndMap;
|
out << YAML::EndMap;
|
||||||
out << YAML::EndSeq;
|
out << YAML::EndSeq;
|
||||||
|
|
||||||
desiredOutput = "- ~\n-\n null value: ~\n ~: null key";
|
desiredOutput = "---\n- ~\n-\n null value: ~\n ~: null key";
|
||||||
|
}
|
||||||
|
|
||||||
|
void EscapedUnicode(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
|
{
|
||||||
|
out << YAML::EscapeNonAscii << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2";
|
||||||
|
|
||||||
|
desiredOutput = "--- \"$ \\xa2 \\u20ac \\U00024b62\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Unicode(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
|
{
|
||||||
|
out << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2";
|
||||||
|
desiredOutput = "--- \x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2";
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoubleQuotedUnicode(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
|
{
|
||||||
|
out << YAML::DoubleQuoted << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2";
|
||||||
|
desiredOutput = "--- \"\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Foo {
|
||||||
|
Foo(): x(0) {}
|
||||||
|
Foo(int x_, const std::string& bar_): x(x_), bar(bar_) {}
|
||||||
|
|
||||||
|
int x;
|
||||||
|
std::string bar;
|
||||||
|
};
|
||||||
|
|
||||||
|
YAML::Emitter& operator << (YAML::Emitter& out, const Foo& foo) {
|
||||||
|
out << YAML::BeginMap;
|
||||||
|
out << YAML::Key << "x" << YAML::Value << foo.x;
|
||||||
|
out << YAML::Key << "bar" << YAML::Value << foo.bar;
|
||||||
|
out << YAML::EndMap;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserType(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
|
{
|
||||||
|
out << YAML::BeginSeq;
|
||||||
|
out << Foo(5, "hello");
|
||||||
|
out << Foo(3, "goodbye");
|
||||||
|
out << YAML::EndSeq;
|
||||||
|
|
||||||
|
desiredOutput = "---\n-\n x: 5\n bar: hello\n-\n x: 3\n bar: goodbye";
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserTypeInContainer(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
|
{
|
||||||
|
std::vector<Foo> fv;
|
||||||
|
fv.push_back(Foo(5, "hello"));
|
||||||
|
fv.push_back(Foo(3, "goodbye"));
|
||||||
|
out << fv;
|
||||||
|
|
||||||
|
desiredOutput = "---\n-\n x: 5\n bar: hello\n-\n x: 3\n bar: goodbye";
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
YAML::Emitter& operator << (YAML::Emitter& out, const T *v) {
|
||||||
|
if(v)
|
||||||
|
out << *v;
|
||||||
|
else
|
||||||
|
out << YAML::Null;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PointerToInt(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
|
{
|
||||||
|
int foo = 5;
|
||||||
|
int *bar = &foo;
|
||||||
|
int *baz = 0;
|
||||||
|
out << YAML::BeginSeq;
|
||||||
|
out << bar << baz;
|
||||||
|
out << YAML::EndSeq;
|
||||||
|
|
||||||
|
desiredOutput = "---\n- 5\n- ~";
|
||||||
|
}
|
||||||
|
|
||||||
|
void PointerToUserType(YAML::Emitter& out, std::string& desiredOutput)
|
||||||
|
{
|
||||||
|
Foo foo(5, "hello");
|
||||||
|
Foo *bar = &foo;
|
||||||
|
Foo *baz = 0;
|
||||||
|
out << YAML::BeginSeq;
|
||||||
|
out << bar << baz;
|
||||||
|
out << YAML::EndSeq;
|
||||||
|
|
||||||
|
desiredOutput = "---\n-\n x: 5\n bar: hello\n- ~";
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -600,6 +779,16 @@ namespace Test
|
|||||||
RunEmitterTest(&Emitter::BlockMapAsKey, "block map as key", passed, total);
|
RunEmitterTest(&Emitter::BlockMapAsKey, "block map as key", passed, total);
|
||||||
RunEmitterTest(&Emitter::AliasAndAnchor, "alias and anchor", passed, total);
|
RunEmitterTest(&Emitter::AliasAndAnchor, "alias and anchor", passed, total);
|
||||||
RunEmitterTest(&Emitter::AliasAndAnchorWithNull, "alias and anchor with null", passed, total);
|
RunEmitterTest(&Emitter::AliasAndAnchorWithNull, "alias and anchor with null", passed, total);
|
||||||
|
RunEmitterTest(&Emitter::SimpleVerbatimTag, "simple verbatim tag", passed, total);
|
||||||
|
RunEmitterTest(&Emitter::VerbatimTagInBlockSeq, "verbatim tag in block seq", passed, total);
|
||||||
|
RunEmitterTest(&Emitter::VerbatimTagInFlowSeq, "verbatim tag in flow seq", passed, total);
|
||||||
|
RunEmitterTest(&Emitter::VerbatimTagInFlowSeqWithNull, "verbatim tag in flow seq with null", passed, total);
|
||||||
|
RunEmitterTest(&Emitter::VerbatimTagInBlockMap, "verbatim tag in block map", passed, total);
|
||||||
|
RunEmitterTest(&Emitter::VerbatimTagInFlowMap, "verbatim tag in flow map", passed, total);
|
||||||
|
RunEmitterTest(&Emitter::VerbatimTagInFlowMapWithNull, "verbatim tag in flow map with null", passed, total);
|
||||||
|
RunEmitterTest(&Emitter::VerbatimTagWithEmptySeq, "verbatim tag with empty seq", passed, total);
|
||||||
|
RunEmitterTest(&Emitter::VerbatimTagWithEmptyMap, "verbatim tag with empty map", passed, total);
|
||||||
|
RunEmitterTest(&Emitter::VerbatimTagWithEmptySeqAndMap, "verbatim tag with empty seq and map", passed, total);
|
||||||
RunEmitterTest(&Emitter::ComplexDoc, "complex doc", passed, total);
|
RunEmitterTest(&Emitter::ComplexDoc, "complex doc", passed, total);
|
||||||
RunEmitterTest(&Emitter::STLContainers, "STL containers", passed, total);
|
RunEmitterTest(&Emitter::STLContainers, "STL containers", passed, total);
|
||||||
RunEmitterTest(&Emitter::SimpleComment, "simple comment", passed, total);
|
RunEmitterTest(&Emitter::SimpleComment, "simple comment", passed, total);
|
||||||
@@ -609,6 +798,13 @@ namespace Test
|
|||||||
RunEmitterTest(&Emitter::SimpleGlobalSettings, "simple global settings", passed, total);
|
RunEmitterTest(&Emitter::SimpleGlobalSettings, "simple global settings", passed, total);
|
||||||
RunEmitterTest(&Emitter::ComplexGlobalSettings, "complex global settings", passed, total);
|
RunEmitterTest(&Emitter::ComplexGlobalSettings, "complex global settings", passed, total);
|
||||||
RunEmitterTest(&Emitter::Null, "null", passed, total);
|
RunEmitterTest(&Emitter::Null, "null", passed, total);
|
||||||
|
RunEmitterTest(&Emitter::EscapedUnicode, "escaped unicode", passed, total);
|
||||||
|
RunEmitterTest(&Emitter::Unicode, "unicode", passed, total);
|
||||||
|
RunEmitterTest(&Emitter::DoubleQuotedUnicode, "double quoted unicode", passed, total);
|
||||||
|
RunEmitterTest(&Emitter::UserType, "user type", passed, total);
|
||||||
|
RunEmitterTest(&Emitter::UserTypeInContainer, "user type in container", passed, total);
|
||||||
|
RunEmitterTest(&Emitter::PointerToInt, "pointer to int", passed, total);
|
||||||
|
RunEmitterTest(&Emitter::PointerToUserType, "pointer to user type", passed, total);
|
||||||
|
|
||||||
RunEmitterErrorTest(&Emitter::ExtraEndSeq, "extra EndSeq", passed, total);
|
RunEmitterErrorTest(&Emitter::ExtraEndSeq, "extra EndSeq", passed, total);
|
||||||
RunEmitterErrorTest(&Emitter::ExtraEndMap, "extra EndMap", passed, total);
|
RunEmitterErrorTest(&Emitter::ExtraEndMap, "extra EndMap", passed, total);
|
7
test/main.cpp
Normal file
7
test/main.cpp
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#include "tests.h"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Test::RunAll();
|
||||||
|
return 0;
|
||||||
|
}
|
@@ -610,6 +610,102 @@ namespace Test
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BlockKeyWithNullValue()
|
||||||
|
{
|
||||||
|
std::string input =
|
||||||
|
"key:\n"
|
||||||
|
"just a key: value";
|
||||||
|
|
||||||
|
std::stringstream stream(input);
|
||||||
|
YAML::Parser parser(stream);
|
||||||
|
YAML::Node doc;
|
||||||
|
|
||||||
|
parser.GetNextDocument(doc);
|
||||||
|
if(doc.size() != 2)
|
||||||
|
return false;
|
||||||
|
if(!IsNull(doc["key"]))
|
||||||
|
return false;
|
||||||
|
if(doc["just a key"] != "value")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bases()
|
||||||
|
{
|
||||||
|
std::string input =
|
||||||
|
"- 15\n"
|
||||||
|
"- 0x10\n"
|
||||||
|
"- 030\n"
|
||||||
|
"- 0xffffffff\n";
|
||||||
|
|
||||||
|
std::stringstream stream(input);
|
||||||
|
YAML::Parser parser(stream);
|
||||||
|
YAML::Node doc;
|
||||||
|
|
||||||
|
parser.GetNextDocument(doc);
|
||||||
|
if(doc.size() != 4)
|
||||||
|
return false;
|
||||||
|
if(doc[0] != 15)
|
||||||
|
return false;
|
||||||
|
if(doc[1] != 0x10)
|
||||||
|
return false;
|
||||||
|
if(doc[2] != 030)
|
||||||
|
return false;
|
||||||
|
if(doc[3] != 0xffffffff)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KeyNotFound()
|
||||||
|
{
|
||||||
|
std::string input = "key: value";
|
||||||
|
std::stringstream stream(input);
|
||||||
|
YAML::Parser parser(stream);
|
||||||
|
YAML::Node doc;
|
||||||
|
parser.GetNextDocument(doc);
|
||||||
|
|
||||||
|
try {
|
||||||
|
doc["bad key"];
|
||||||
|
} catch(const YAML::Exception& e) {
|
||||||
|
if(e.msg != YAML::ErrorMsg::KEY_NOT_FOUND + ": bad key")
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
doc[5];
|
||||||
|
} catch(const YAML::Exception& e) {
|
||||||
|
if(e.msg != YAML::ErrorMsg::KEY_NOT_FOUND + ": 5")
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
doc[2.5];
|
||||||
|
} catch(const YAML::Exception& e) {
|
||||||
|
if(e.msg != YAML::ErrorMsg::KEY_NOT_FOUND + ": 2.5")
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DuplicateKey()
|
||||||
|
{
|
||||||
|
std::string input = "{a: 1, b: 2, c: 3, a: 4}";
|
||||||
|
std::stringstream stream(input);
|
||||||
|
YAML::Parser parser(stream);
|
||||||
|
YAML::Node doc;
|
||||||
|
parser.GetNextDocument(doc);
|
||||||
|
|
||||||
|
if(doc["a"] != 1)
|
||||||
|
return false;
|
||||||
|
if(doc["b"] != 2)
|
||||||
|
return false;
|
||||||
|
if(doc["c"] != 3)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -627,7 +723,7 @@ namespace Test
|
|||||||
doc >> output;
|
doc >> output;
|
||||||
} catch(const YAML::Exception& e) {
|
} catch(const YAML::Exception& e) {
|
||||||
ok = false;
|
ok = false;
|
||||||
error = e.msg;
|
error = e.what();
|
||||||
}
|
}
|
||||||
if(ok && output == desiredOutput) {
|
if(ok && output == desiredOutput) {
|
||||||
passed++;
|
passed++;
|
||||||
@@ -869,6 +965,10 @@ namespace Test
|
|||||||
RunParserTest(&Parser::MultipleDocs, "multiple docs", passed, total);
|
RunParserTest(&Parser::MultipleDocs, "multiple docs", passed, total);
|
||||||
RunParserTest(&Parser::ExplicitEndDoc, "explicit end doc", passed, total);
|
RunParserTest(&Parser::ExplicitEndDoc, "explicit end doc", passed, total);
|
||||||
RunParserTest(&Parser::MultipleDocsWithSomeExplicitIndicators, "multiple docs with some explicit indicators", passed, total);
|
RunParserTest(&Parser::MultipleDocsWithSomeExplicitIndicators, "multiple docs with some explicit indicators", passed, total);
|
||||||
|
RunParserTest(&Parser::BlockKeyWithNullValue, "block key with null value", passed, total);
|
||||||
|
RunParserTest(&Parser::Bases, "bases", passed, total);
|
||||||
|
RunParserTest(&Parser::KeyNotFound, "key not found", passed, total);
|
||||||
|
RunParserTest(&Parser::DuplicateKey, "duplicate key", passed, total);
|
||||||
|
|
||||||
RunEncodingTest(&EncodeToUtf8, false, "UTF-8, no BOM", passed, total);
|
RunEncodingTest(&EncodeToUtf8, false, "UTF-8, no BOM", passed, total);
|
||||||
RunEncodingTest(&EncodeToUtf8, true, "UTF-8 with BOM", passed, total);
|
RunEncodingTest(&EncodeToUtf8, true, "UTF-8 with BOM", passed, total);
|
File diff suppressed because it is too large
Load Diff
@@ -11,9 +11,8 @@ int main(int argc, char **argv)
|
|||||||
std::istream& input = (argc > 1 ? fin : std::cin);
|
std::istream& input = (argc > 1 ? fin : std::cin);
|
||||||
try {
|
try {
|
||||||
YAML::Parser parser(input);
|
YAML::Parser parser(input);
|
||||||
while(parser) {
|
YAML::Node doc;
|
||||||
YAML::Node doc;
|
while(parser.GetNextDocument(doc)) {
|
||||||
parser.GetNextDocument(doc);
|
|
||||||
YAML::Emitter emitter;
|
YAML::Emitter emitter;
|
||||||
emitter << doc;
|
emitter << doc;
|
||||||
std::cout << emitter.c_str() << "\n";
|
std::cout << emitter.c_str() << "\n";
|
||||||
|
@@ -1,10 +0,0 @@
|
|||||||
file(GLOB yaml-reader_headers *.h)
|
|
||||||
file(GLOB yaml-reader_sources *.cpp)
|
|
||||||
|
|
||||||
add_executable(yaml-reader
|
|
||||||
${yaml-reader_sources}
|
|
||||||
${yaml-reader_headers}
|
|
||||||
)
|
|
||||||
target_link_libraries(yaml-reader yaml-cpp)
|
|
||||||
|
|
||||||
add_test(yaml-reader-test yaml-reader)
|
|
@@ -1,11 +0,0 @@
|
|||||||
#include "tests.h"
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
#ifdef WINDOWS
|
|
||||||
_CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF|_CRTDBG_ALLOC_MEM_DF);
|
|
||||||
#endif // WINDOWS
|
|
||||||
Test::RunAll();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@@ -1,4 +0,0 @@
|
|||||||
--- &list
|
|
||||||
- This document contains a recursive list.
|
|
||||||
- *list
|
|
||||||
...
|
|
21
yamlcpp.sln
21
yamlcpp.sln
@@ -1,12 +1,17 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||||
# Visual Studio 2008
|
# Visual Studio 2008
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "yaml-reader", "yaml-reader.vcproj", "{E8CC0D8A-D784-4A6B-B78B-ACEA13F9FB0B}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "yamlcpp", "yamlcpp.vcproj", "{3104AB4E-CD31-4F47-95E9-0E8D9374E15D}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test.vcproj", "{D1108F40-6ADF-467E-A95A-236C39A515C5}"
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
{3104AB4E-CD31-4F47-95E9-0E8D9374E15D} = {3104AB4E-CD31-4F47-95E9-0E8D9374E15D}
|
{3104AB4E-CD31-4F47-95E9-0E8D9374E15D} = {3104AB4E-CD31-4F47-95E9-0E8D9374E15D}
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "yamlcpp", "yamlcpp.vcproj", "{3104AB4E-CD31-4F47-95E9-0E8D9374E15D}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "parse", "parse.vcproj", "{CD007B57-7812-4930-A5E2-6E5E56338814}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{3104AB4E-CD31-4F47-95E9-0E8D9374E15D} = {3104AB4E-CD31-4F47-95E9-0E8D9374E15D}
|
||||||
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@@ -14,14 +19,18 @@ Global
|
|||||||
Release|Win32 = Release|Win32
|
Release|Win32 = Release|Win32
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{E8CC0D8A-D784-4A6B-B78B-ACEA13F9FB0B}.Debug|Win32.ActiveCfg = Debug|Win32
|
|
||||||
{E8CC0D8A-D784-4A6B-B78B-ACEA13F9FB0B}.Debug|Win32.Build.0 = Debug|Win32
|
|
||||||
{E8CC0D8A-D784-4A6B-B78B-ACEA13F9FB0B}.Release|Win32.ActiveCfg = Release|Win32
|
|
||||||
{E8CC0D8A-D784-4A6B-B78B-ACEA13F9FB0B}.Release|Win32.Build.0 = Release|Win32
|
|
||||||
{3104AB4E-CD31-4F47-95E9-0E8D9374E15D}.Debug|Win32.ActiveCfg = Debug|Win32
|
{3104AB4E-CD31-4F47-95E9-0E8D9374E15D}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
{3104AB4E-CD31-4F47-95E9-0E8D9374E15D}.Debug|Win32.Build.0 = Debug|Win32
|
{3104AB4E-CD31-4F47-95E9-0E8D9374E15D}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
{3104AB4E-CD31-4F47-95E9-0E8D9374E15D}.Release|Win32.ActiveCfg = Release|Win32
|
{3104AB4E-CD31-4F47-95E9-0E8D9374E15D}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
{3104AB4E-CD31-4F47-95E9-0E8D9374E15D}.Release|Win32.Build.0 = Release|Win32
|
{3104AB4E-CD31-4F47-95E9-0E8D9374E15D}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{D1108F40-6ADF-467E-A95A-236C39A515C5}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{D1108F40-6ADF-467E-A95A-236C39A515C5}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{D1108F40-6ADF-467E-A95A-236C39A515C5}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{D1108F40-6ADF-467E-A95A-236C39A515C5}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{CD007B57-7812-4930-A5E2-6E5E56338814}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{CD007B57-7812-4930-A5E2-6E5E56338814}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{CD007B57-7812-4930-A5E2-6E5E56338814}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{CD007B57-7812-4930-A5E2-6E5E56338814}.Release|Win32.Build.0 = Release|Win32
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@@ -40,6 +40,7 @@
|
|||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
|
AdditionalOptions="/D_SCL_SECURE_NO_WARNINGS"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
AdditionalIncludeDirectories="include"
|
AdditionalIncludeDirectories="include"
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
|
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
|
||||||
@@ -49,6 +50,7 @@
|
|||||||
UsePrecompiledHeader="0"
|
UsePrecompiledHeader="0"
|
||||||
WarningLevel="4"
|
WarningLevel="4"
|
||||||
DebugInformationFormat="3"
|
DebugInformationFormat="3"
|
||||||
|
DisableSpecificWarnings="4127;4355"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCManagedResourceCompilerTool"
|
Name="VCManagedResourceCompilerTool"
|
||||||
@@ -104,6 +106,7 @@
|
|||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
|
AdditionalOptions="/D_SCL_SECURE_NO_WARNINGS"
|
||||||
Optimization="2"
|
Optimization="2"
|
||||||
EnableIntrinsicFunctions="true"
|
EnableIntrinsicFunctions="true"
|
||||||
AdditionalIncludeDirectories="include"
|
AdditionalIncludeDirectories="include"
|
||||||
@@ -113,6 +116,7 @@
|
|||||||
UsePrecompiledHeader="0"
|
UsePrecompiledHeader="0"
|
||||||
WarningLevel="4"
|
WarningLevel="4"
|
||||||
DebugInformationFormat="3"
|
DebugInformationFormat="3"
|
||||||
|
DisableSpecificWarnings="4127;4355"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCManagedResourceCompilerTool"
|
Name="VCManagedResourceCompilerTool"
|
||||||
@@ -171,10 +175,6 @@
|
|||||||
RelativePath=".\src\aliascontent.cpp"
|
RelativePath=".\src\aliascontent.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath=".\src\content.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\conversion.cpp"
|
RelativePath=".\src\conversion.cpp"
|
||||||
>
|
>
|
||||||
@@ -203,6 +203,10 @@
|
|||||||
RelativePath=".\src\sequence.cpp"
|
RelativePath=".\src\sequence.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\tag.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Scanner"
|
Name="Scanner"
|
||||||
@@ -223,6 +227,10 @@
|
|||||||
RelativePath=".\src\scanscalar.cpp"
|
RelativePath=".\src\scanscalar.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\scantag.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\scantoken.cpp"
|
RelativePath=".\src\scantoken.cpp"
|
||||||
>
|
>
|
||||||
@@ -337,6 +345,10 @@
|
|||||||
RelativePath=".\src\sequence.h"
|
RelativePath=".\src\sequence.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\tag.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Scanner"
|
Name="Scanner"
|
||||||
@@ -361,6 +373,10 @@
|
|||||||
RelativePath=".\src\scanscalar.h"
|
RelativePath=".\src\scanscalar.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\scantag.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\stream.h"
|
RelativePath=".\src\stream.h"
|
||||||
>
|
>
|
||||||
|
Reference in New Issue
Block a user