Load the null with !!str tag correctly

This commit is contained in:
dota17 2020-06-16 11:32:35 +08:00
commit 503e58825c
29 changed files with 397 additions and 205 deletions

View File

@ -34,10 +34,11 @@ endif()
set(build-shared $<BOOL:${YAML_BUILD_SHARED_LIBS}>) set(build-shared $<BOOL:${YAML_BUILD_SHARED_LIBS}>)
set(build-windows-dll $<AND:$<BOOL:${CMAKE_HOST_WIN32}>,${build-shared}>) set(build-windows-dll $<AND:$<BOOL:${CMAKE_HOST_WIN32}>,${build-shared}>)
set(not-msvc $<NOT:$<CXX_COMPILER_ID:MSVC>>) set(not-msvc $<NOT:$<CXX_COMPILER_ID:MSVC>>)
set(msvc-shared_rt $<BOOL:${YAML_MSVC_SHARED_RT}>)
if (NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY) if (NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY)
set(CMAKE_MSVC_RUNTIME_LIBRARY set(CMAKE_MSVC_RUNTIME_LIBRARY
MultiThreaded$<$<CONFIG:Debug>:Debug>$<${build-shared}:DLL>) MultiThreaded$<$<CONFIG:Debug>:Debug>$<${msvc-shared_rt}:DLL>)
endif() endif()
set(contrib-pattern "src/contrib/*.cpp") set(contrib-pattern "src/contrib/*.cpp")
@ -108,7 +109,7 @@ target_sources(yaml-cpp
PRIVATE PRIVATE
$<$<BOOL:${YAML_CPP_BUILD_CONTRIB}>:${yaml-cpp-contrib-sources}> $<$<BOOL:${YAML_CPP_BUILD_CONTRIB}>:${yaml-cpp-contrib-sources}>
${yaml-cpp-sources}) ${yaml-cpp-sources})
if (NOT DEFINED CMAKE_DEBUG_POSTFIX) if (NOT DEFINED CMAKE_DEBUG_POSTFIX)
set(CMAKE_DEBUG_POSTFIX "d") set(CMAKE_DEBUG_POSTFIX "d")
endif() endif()

View File

@ -5,6 +5,7 @@
## HEAD ## ## HEAD ##
* Throws an exception when trying to parse a negative number as an unsigned integer. * Throws an exception when trying to parse a negative number as an unsigned integer.
* Supports the `as<int8_t>`/`as<uint8_t>`, which throws an exception when the value exceeds the range of `int8_t`/`uint8_t`.
## 0.6.0 ## ## 0.6.0 ##

View File

@ -1,6 +1,6 @@
# Encodings and `yaml-cpp` # # Encodings and `yaml-cpp` #
`yaml-cpp` will parse any file as specificed by the [YAML 1.2 spec](http://www.yaml.org/spec/1.2/spec.html#id2570322). Internally, it stores all strings in UTF-8, and representation is done with UTF-8. This means that in `yaml-cpp` will parse any file as specified by the [YAML 1.2 spec](http://www.yaml.org/spec/1.2/spec.html#id2570322). Internally, it stores all strings in UTF-8, and representation is done with UTF-8. This means that in
``` ```
std::string str; std::string str;

View File

@ -15,7 +15,6 @@
#include <sstream> #include <sstream>
#include <type_traits> #include <type_traits>
#include <vector> #include <vector>
#include <type_traits>
#include "yaml-cpp/binary.h" #include "yaml-cpp/binary.h"
#include "yaml-cpp/node/impl.h" #include "yaml-cpp/node/impl.h"
@ -114,6 +113,31 @@ typename std::enable_if<!std::is_floating_point<T>::value, void>::type
inner_encode(const T& rhs, std::stringstream& stream){ inner_encode(const T& rhs, std::stringstream& stream){
stream << rhs; stream << rhs;
} }
template <typename T>
typename std::enable_if<(std::is_same<T, unsigned char>::value ||
std::is_same<T, signed char>::value), bool>::type
ConvertStreamTo(std::stringstream& stream, T& rhs) {
int num;
if ((stream >> std::noskipws >> num) && (stream >> std::ws).eof()) {
if (num >= std::numeric_limits<T>::min() &&
num <= std::numeric_limits<T>::max()) {
rhs = num;
return true;
}
}
return false;
}
template <typename T>
typename std::enable_if<!(std::is_same<T, unsigned char>::value ||
std::is_same<T, signed char>::value), bool>::type
ConvertStreamTo(std::stringstream& stream, T& rhs) {
if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) {
return true;
}
return false;
}
} }
#define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op) \ #define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op) \
@ -137,7 +161,7 @@ inner_encode(const T& rhs, std::stringstream& stream){
if ((stream.peek() == '-') && std::is_unsigned<type>::value) { \ if ((stream.peek() == '-') && std::is_unsigned<type>::value) { \
return false; \ return false; \
} \ } \
if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) { \ if (conversion::ConvertStreamTo(stream, rhs)) { \
return true; \ return true; \
} \ } \
if (std::numeric_limits<type>::has_infinity) { \ if (std::numeric_limits<type>::has_infinity) { \
@ -201,9 +225,8 @@ template <typename K, typename V, typename C, typename A>
struct convert<std::map<K, V, C, A>> { struct convert<std::map<K, V, C, A>> {
static Node encode(const std::map<K, V, C, A>& rhs) { static Node encode(const std::map<K, V, C, A>& rhs) {
Node node(NodeType::Map); Node node(NodeType::Map);
for (typename std::map<K, V, C, A>::const_iterator it = rhs.begin(); for (const auto& element : rhs)
it != rhs.end(); ++it) node.force_insert(element.first, element.second);
node.force_insert(it->first, it->second);
return node; return node;
} }
@ -212,12 +235,12 @@ struct convert<std::map<K, V, C, A>> {
return false; return false;
rhs.clear(); rhs.clear();
for (const_iterator it = node.begin(); it != node.end(); ++it) for (const auto& element : node)
#if defined(__GNUC__) && __GNUC__ < 4 #if defined(__GNUC__) && __GNUC__ < 4
// workaround for GCC 3: // workaround for GCC 3:
rhs[it->first.template as<K>()] = it->second.template as<V>(); rhs[element.first.template as<K>()] = element.second.template as<V>();
#else #else
rhs[it->first.as<K>()] = it->second.as<V>(); rhs[element.first.as<K>()] = element.second.as<V>();
#endif #endif
return true; return true;
} }
@ -228,9 +251,8 @@ template <typename T, typename A>
struct convert<std::vector<T, A>> { struct convert<std::vector<T, A>> {
static Node encode(const std::vector<T, A>& rhs) { static Node encode(const std::vector<T, A>& rhs) {
Node node(NodeType::Sequence); Node node(NodeType::Sequence);
for (typename std::vector<T, A>::const_iterator it = rhs.begin(); for (const auto& element : rhs)
it != rhs.end(); ++it) node.push_back(element);
node.push_back(*it);
return node; return node;
} }
@ -239,12 +261,12 @@ struct convert<std::vector<T, A>> {
return false; return false;
rhs.clear(); rhs.clear();
for (const_iterator it = node.begin(); it != node.end(); ++it) for (const auto& element : node)
#if defined(__GNUC__) && __GNUC__ < 4 #if defined(__GNUC__) && __GNUC__ < 4
// workaround for GCC 3: // workaround for GCC 3:
rhs.push_back(it->template as<T>()); rhs.push_back(element.template as<T>());
#else #else
rhs.push_back(it->as<T>()); rhs.push_back(element.as<T>());
#endif #endif
return true; return true;
} }
@ -255,9 +277,8 @@ template <typename T, typename A>
struct convert<std::list<T,A>> { struct convert<std::list<T,A>> {
static Node encode(const std::list<T,A>& rhs) { static Node encode(const std::list<T,A>& rhs) {
Node node(NodeType::Sequence); Node node(NodeType::Sequence);
for (typename std::list<T,A>::const_iterator it = rhs.begin(); for (const auto& element : rhs)
it != rhs.end(); ++it) node.push_back(element);
node.push_back(*it);
return node; return node;
} }
@ -266,12 +287,12 @@ struct convert<std::list<T,A>> {
return false; return false;
rhs.clear(); rhs.clear();
for (const_iterator it = node.begin(); it != node.end(); ++it) for (const auto& element : node)
#if defined(__GNUC__) && __GNUC__ < 4 #if defined(__GNUC__) && __GNUC__ < 4
// workaround for GCC 3: // workaround for GCC 3:
rhs.push_back(it->template as<T>()); rhs.push_back(element.template as<T>());
#else #else
rhs.push_back(it->as<T>()); rhs.push_back(element.as<T>());
#endif #endif
return true; return true;
} }

View File

@ -9,6 +9,8 @@
#include "yaml-cpp/node/detail/node.h" #include "yaml-cpp/node/detail/node.h"
#include "yaml-cpp/node/detail/node_data.h" #include "yaml-cpp/node/detail/node_data.h"
#include <algorithm>
#include <type_traits> #include <type_traits>
namespace YAML { namespace YAML {
@ -125,13 +127,11 @@ inline node* node_data::get(const Key& key,
throw BadSubscript(m_mark, key); throw BadSubscript(m_mark, key);
} }
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) { auto it = std::find_if(m_map.begin(), m_map.end(), [&](const kv_pair m) {
if (it->first->equals(key, pMemory)) { return m.first->equals(key, pMemory);
return it->second; });
}
}
return nullptr; return it != m_map.end() ? it->second : nullptr;
} }
template <typename Key> template <typename Key>
@ -153,10 +153,12 @@ inline node& node_data::get(const Key& key, shared_memory_holder pMemory) {
throw BadSubscript(m_mark, key); throw BadSubscript(m_mark, key);
} }
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) { auto it = std::find_if(m_map.begin(), m_map.end(), [&](const kv_pair m) {
if (it->first->equals(key, pMemory)) { return m.first->equals(key, pMemory);
return *it->second; });
}
if (it != m_map.end()) {
return *it->second;
} }
node& k = convert_to_node(key, pMemory); node& k = convert_to_node(key, pMemory);
@ -169,7 +171,9 @@ template <typename Key>
inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) { inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) {
if (m_type == NodeType::Sequence) { if (m_type == NodeType::Sequence) {
return remove_idx<Key>::remove(m_sequence, key, m_seqSize); return remove_idx<Key>::remove(m_sequence, key, m_seqSize);
} else if (m_type == NodeType::Map) { }
if (m_type == NodeType::Map) {
kv_pairs::iterator it = m_undefinedPairs.begin(); kv_pairs::iterator it = m_undefinedPairs.begin();
while (it != m_undefinedPairs.end()) { while (it != m_undefinedPairs.end()) {
kv_pairs::iterator jt = std::next(it); kv_pairs::iterator jt = std::next(it);
@ -179,11 +183,13 @@ inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) {
it = jt; it = jt;
} }
for (node_map::iterator iter = m_map.begin(); iter != m_map.end(); ++iter) { auto iter = std::find_if(m_map.begin(), m_map.end(), [&](const kv_pair m) {
if (iter->first->equals(key, pMemory)) { return m.first->equals(key, pMemory);
m_map.erase(iter); });
return true;
} if (iter != m_map.end()) {
m_map.erase(iter);
return true;
} }
} }

View File

@ -60,8 +60,8 @@ class YAML_CPP_API node_data {
node_iterator end(); node_iterator end();
// sequence // sequence
void push_back(node& node, shared_memory_holder pMemory); void push_back(node& node, const shared_memory_holder& pMemory);
void insert(node& key, node& value, shared_memory_holder pMemory); void insert(node& key, node& value, const shared_memory_holder& pMemory);
// indexing // indexing
template <typename Key> template <typename Key>
@ -71,9 +71,9 @@ class YAML_CPP_API node_data {
template <typename Key> template <typename Key>
bool remove(const Key& key, shared_memory_holder pMemory); bool remove(const Key& key, shared_memory_holder pMemory);
node* get(node& key, shared_memory_holder pMemory) const; node* get(node& key, const shared_memory_holder& pMemory) const;
node& get(node& key, shared_memory_holder pMemory); node& get(node& key, const shared_memory_holder& pMemory);
bool remove(node& key, shared_memory_holder pMemory); bool remove(node& key, const shared_memory_holder& pMemory);
// map // map
template <typename Key, typename Value> template <typename Key, typename Value>
@ -91,8 +91,8 @@ class YAML_CPP_API node_data {
void reset_map(); void reset_map();
void insert_map_pair(node& key, node& value); void insert_map_pair(node& key, node& value);
void convert_to_map(shared_memory_holder pMemory); void convert_to_map(const shared_memory_holder& pMemory);
void convert_sequence_to_map(shared_memory_holder pMemory); void convert_sequence_to_map(const shared_memory_holder& pMemory);
template <typename T> template <typename T>
static node& convert_to_node(const T& rhs, shared_memory_holder pMemory); static node& convert_to_node(const T& rhs, shared_memory_holder pMemory);

View File

@ -16,8 +16,8 @@ namespace YAML {
template <typename Seq> template <typename Seq>
inline Emitter& EmitSeq(Emitter& emitter, const Seq& seq) { inline Emitter& EmitSeq(Emitter& emitter, const Seq& seq) {
emitter << BeginSeq; emitter << BeginSeq;
for (typename Seq::const_iterator it = seq.begin(); it != seq.end(); ++it) for (const auto& emit : seq)
emitter << *it; emitter << emit;
emitter << EndSeq; emitter << EndSeq;
return emitter; return emitter;
} }
@ -41,8 +41,8 @@ template <typename K, typename V>
inline Emitter& operator<<(Emitter& emitter, const std::map<K, V>& m) { inline Emitter& operator<<(Emitter& emitter, const std::map<K, V>& m) {
typedef typename std::map<K, V> map; typedef typename std::map<K, V> map;
emitter << BeginMap; emitter << BeginMap;
for (typename map::const_iterator it = m.begin(); it != m.end(); ++it) for (const auto& emit : m)
emitter << Key << it->first << Value << it->second; emitter << Key << emit.first << Value << emit.second;
emitter << EndMap; emitter << EndMap;
return emitter; return emitter;
} }

View File

@ -10,8 +10,7 @@ void* BuildGraphOfNextDocument(Parser& parser,
GraphBuilderAdapter eventHandler(graphBuilder); GraphBuilderAdapter eventHandler(graphBuilder);
if (parser.HandleNextDocument(eventHandler)) { if (parser.HandleNextDocument(eventHandler)) {
return eventHandler.RootNode(); return eventHandler.RootNode();
} else {
return nullptr;
} }
return nullptr;
} }
} // namespace YAML } // namespace YAML

View File

@ -16,11 +16,7 @@ std::string tolower(const std::string& str) {
template <typename T> template <typename T>
bool IsEntirely(const std::string& str, T func) { bool IsEntirely(const std::string& str, T func) {
for (char ch : str) return std::all_of(str.begin(), str.end(), [=](char ch) { return func(ch); });
if (!func(ch))
return false;
return true;
} }
// IsFlexibleCase // IsFlexibleCase

View File

@ -94,15 +94,13 @@ EmitterNodeType::value EmitterState::NextGroupType(
if (type == GroupType::Seq) { if (type == GroupType::Seq) {
if (GetFlowType(type) == Block) if (GetFlowType(type) == Block)
return EmitterNodeType::BlockSeq; return EmitterNodeType::BlockSeq;
else return EmitterNodeType::FlowSeq;
return EmitterNodeType::FlowSeq;
} else {
if (GetFlowType(type) == Block)
return EmitterNodeType::BlockMap;
else
return EmitterNodeType::FlowMap;
} }
if (GetFlowType(type) == Block)
return EmitterNodeType::BlockMap;
return EmitterNodeType::FlowMap;
// can't happen // can't happen
assert(false); assert(false);
return EmitterNodeType::NoType; return EmitterNodeType::NoType;
@ -156,9 +154,8 @@ void EmitterState::EndedGroup(GroupType::value type) {
if (m_groups.empty()) { if (m_groups.empty()) {
if (type == GroupType::Seq) { if (type == GroupType::Seq) {
return SetError(ErrorMsg::UNEXPECTED_END_SEQ); return SetError(ErrorMsg::UNEXPECTED_END_SEQ);
} else {
return SetError(ErrorMsg::UNEXPECTED_END_MAP);
} }
return SetError(ErrorMsg::UNEXPECTED_END_MAP);
} }
// get rid of the current group // get rid of the current group

View File

@ -1,3 +1,4 @@
#include <algorithm>
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
@ -199,15 +200,10 @@ bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii) { bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii) {
// TODO: check for non-printable characters? // TODO: check for non-printable characters?
for (char ch : str) { return std::none_of(str.begin(), str.end(), [=](char ch) {
if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch))) { return (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch))) ||
return false; (ch == '\n');
} });
if (ch == '\n') {
return false;
}
}
return true;
} }
bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType, bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType,
@ -217,12 +213,9 @@ bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType,
} }
// TODO: check for non-printable characters? // TODO: check for non-printable characters?
for (char ch : str) { return std::none_of(str.begin(), str.end(), [=](char ch) {
if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch))) { return (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch)));
return false; });
}
}
return true;
} }
void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint) { void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint) {
@ -373,15 +366,15 @@ bool WriteChar(ostream_wrapper& out, char ch) {
if (('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')) { if (('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')) {
out << ch; out << ch;
} else if (ch == '\"') { } else if (ch == '\"') {
out << "\"\\\"\""; out << R"("\"")";
} else if (ch == '\t') { } else if (ch == '\t') {
out << "\"\\t\""; out << R"("\t")";
} else if (ch == '\n') { } else if (ch == '\n') {
out << "\"\\n\""; out << R"("\n")";
} else if (ch == '\b') { } else if (ch == '\b') {
out << "\"\\b\""; out << R"("\b")";
} else if (ch == '\\') { } else if (ch == '\\') {
out << "\"\\\\\""; out << R"("\\")";
} else if (0x20 <= ch && ch <= 0x7e) { } else if (0x20 <= ch && ch <= 0x7e) {
out << "\"" << ch << "\""; out << "\"" << ch << "\"";
} else { } else {

View File

@ -54,14 +54,16 @@ std::string Escape(Stream& in, int codeLength) {
// now break it up into chars // now break it up into chars
if (value <= 0x7F) if (value <= 0x7F)
return Str(value); return Str(value);
else if (value <= 0x7FF)
if (value <= 0x7FF)
return Str(0xC0 + (value >> 6)) + Str(0x80 + (value & 0x3F)); return Str(0xC0 + (value >> 6)) + Str(0x80 + (value & 0x3F));
else if (value <= 0xFFFF)
if (value <= 0xFFFF)
return Str(0xE0 + (value >> 12)) + Str(0x80 + ((value >> 6) & 0x3F)) + return Str(0xE0 + (value >> 12)) + Str(0x80 + ((value >> 6) & 0x3F)) +
Str(0x80 + (value & 0x3F)); Str(0x80 + (value & 0x3F));
else
return Str(0xF0 + (value >> 18)) + Str(0x80 + ((value >> 12) & 0x3F)) + return Str(0xF0 + (value >> 18)) + Str(0x80 + ((value >> 12) & 0x3F)) +
Str(0x80 + ((value >> 6) & 0x3F)) + Str(0x80 + (value & 0x3F)); Str(0x80 + ((value >> 6) & 0x3F)) + Str(0x80 + (value & 0x3F));
} }
// Escape // Escape
@ -103,7 +105,7 @@ std::string Escape(Stream& in) {
case 'e': case 'e':
return "\x1B"; return "\x1B";
case ' ': case ' ':
return "\x20"; return R"( )";
case '\"': case '\"':
return "\""; return "\"";
case '\'': case '\'':

View File

@ -155,7 +155,7 @@ inline const RegEx& PlainScalar() {
inline const RegEx& PlainScalarInFlow() { inline const RegEx& PlainScalarInFlow() {
static const RegEx e = static const RegEx e =
!(BlankOrBreak() | RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) | !(BlankOrBreak() | RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) |
(RegEx("-:", REGEX_OR) + Blank())); (RegEx("-:", REGEX_OR) + (Blank() | RegEx())));
return e; return e;
} }
inline const RegEx& EndScalar() { inline const RegEx& EndScalar() {

View File

@ -1,3 +1,4 @@
#include <algorithm>
#include <cassert> #include <cassert>
#include <iterator> #include <iterator>
#include <sstream> #include <sstream>
@ -120,7 +121,7 @@ void node_data::compute_map_size() const {
const_node_iterator node_data::begin() const { const_node_iterator node_data::begin() const {
if (!m_isDefined) if (!m_isDefined)
return const_node_iterator(); return {};
switch (m_type) { switch (m_type) {
case NodeType::Sequence: case NodeType::Sequence:
@ -128,13 +129,13 @@ const_node_iterator node_data::begin() const {
case NodeType::Map: case NodeType::Map:
return const_node_iterator(m_map.begin(), m_map.end()); return const_node_iterator(m_map.begin(), m_map.end());
default: default:
return const_node_iterator(); return {};
} }
} }
node_iterator node_data::begin() { node_iterator node_data::begin() {
if (!m_isDefined) if (!m_isDefined)
return node_iterator(); return {};
switch (m_type) { switch (m_type) {
case NodeType::Sequence: case NodeType::Sequence:
@ -142,13 +143,13 @@ node_iterator node_data::begin() {
case NodeType::Map: case NodeType::Map:
return node_iterator(m_map.begin(), m_map.end()); return node_iterator(m_map.begin(), m_map.end());
default: default:
return node_iterator(); return {};
} }
} }
const_node_iterator node_data::end() const { const_node_iterator node_data::end() const {
if (!m_isDefined) if (!m_isDefined)
return const_node_iterator(); return {};
switch (m_type) { switch (m_type) {
case NodeType::Sequence: case NodeType::Sequence:
@ -156,13 +157,13 @@ const_node_iterator node_data::end() const {
case NodeType::Map: case NodeType::Map:
return const_node_iterator(m_map.end(), m_map.end()); return const_node_iterator(m_map.end(), m_map.end());
default: default:
return const_node_iterator(); return {};
} }
} }
node_iterator node_data::end() { node_iterator node_data::end() {
if (!m_isDefined) if (!m_isDefined)
return node_iterator(); return {};
switch (m_type) { switch (m_type) {
case NodeType::Sequence: case NodeType::Sequence:
@ -170,12 +171,13 @@ node_iterator node_data::end() {
case NodeType::Map: case NodeType::Map:
return node_iterator(m_map.end(), m_map.end()); return node_iterator(m_map.end(), m_map.end());
default: default:
return node_iterator(); return {};
} }
} }
// sequence // sequence
void node_data::push_back(node& node, shared_memory_holder /* pMemory */) { void node_data::push_back(node& node,
const shared_memory_holder& /* pMemory */) {
if (m_type == NodeType::Undefined || m_type == NodeType::Null) { if (m_type == NodeType::Undefined || m_type == NodeType::Null) {
m_type = NodeType::Sequence; m_type = NodeType::Sequence;
reset_sequence(); reset_sequence();
@ -187,7 +189,8 @@ void node_data::push_back(node& node, shared_memory_holder /* pMemory */) {
m_sequence.push_back(&node); m_sequence.push_back(&node);
} }
void node_data::insert(node& key, node& value, shared_memory_holder pMemory) { void node_data::insert(node& key, node& value,
const shared_memory_holder& pMemory) {
switch (m_type) { switch (m_type) {
case NodeType::Map: case NodeType::Map:
break; break;
@ -204,20 +207,21 @@ void node_data::insert(node& key, node& value, shared_memory_holder pMemory) {
} }
// indexing // indexing
node* node_data::get(node& key, shared_memory_holder /* pMemory */) const { node* node_data::get(node& key,
const shared_memory_holder& /* pMemory */) const {
if (m_type != NodeType::Map) { if (m_type != NodeType::Map) {
return nullptr; return nullptr;
} }
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) { for (const auto& it : m_map) {
if (it->first->is(key)) if (it.first->is(key))
return it->second; return it.second;
} }
return nullptr; return nullptr;
} }
node& node_data::get(node& key, shared_memory_holder pMemory) { node& node_data::get(node& key, const shared_memory_holder& pMemory) {
switch (m_type) { switch (m_type) {
case NodeType::Map: case NodeType::Map:
break; break;
@ -230,9 +234,9 @@ node& node_data::get(node& key, shared_memory_holder pMemory) {
throw BadSubscript(m_mark, key); throw BadSubscript(m_mark, key);
} }
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) { for (const auto& it : m_map) {
if (it->first->is(key)) if (it.first->is(key))
return *it->second; return *it.second;
} }
node& value = pMemory->create_node(); node& value = pMemory->create_node();
@ -240,7 +244,7 @@ node& node_data::get(node& key, shared_memory_holder pMemory) {
return value; return value;
} }
bool node_data::remove(node& key, shared_memory_holder /* pMemory */) { bool node_data::remove(node& key, const shared_memory_holder& /* pMemory */) {
if (m_type != NodeType::Map) if (m_type != NodeType::Map)
return false; return false;
@ -252,11 +256,15 @@ bool node_data::remove(node& key, shared_memory_holder /* pMemory */) {
it = jt; it = jt;
} }
for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) { auto it =
if (it->first->is(key)) { std::find_if(m_map.begin(), m_map.end(),
m_map.erase(it); [&](std::pair<YAML::detail::node*, YAML::detail::node*> j) {
return true; return (j.first->is(key));
} });
if (it != m_map.end()) {
m_map.erase(it);
return true;
} }
return false; return false;
@ -279,7 +287,7 @@ void node_data::insert_map_pair(node& key, node& value) {
m_undefinedPairs.emplace_back(&key, &value); m_undefinedPairs.emplace_back(&key, &value);
} }
void node_data::convert_to_map(shared_memory_holder pMemory) { void node_data::convert_to_map(const shared_memory_holder& pMemory) {
switch (m_type) { switch (m_type) {
case NodeType::Undefined: case NodeType::Undefined:
case NodeType::Null: case NodeType::Null:
@ -297,7 +305,7 @@ void node_data::convert_to_map(shared_memory_holder pMemory) {
} }
} }
void node_data::convert_sequence_to_map(shared_memory_holder pMemory) { void node_data::convert_sequence_to_map(const shared_memory_holder& pMemory) {
assert(m_type == NodeType::Sequence); assert(m_type == NodeType::Sequence);
reset_map(); reset_map();

View File

@ -92,7 +92,7 @@ void NodeBuilder::Push(detail::node& node) {
m_stack.push_back(&node); m_stack.push_back(&node);
if (needsKey) if (needsKey)
m_keys.push_back(PushedKey(&node, false)); m_keys.emplace_back(&node, false);
} }
void NodeBuilder::Pop() { void NodeBuilder::Pop() {

View File

@ -32,13 +32,12 @@ void NodeEvents::Setup(const detail::node& node) {
return; return;
if (node.type() == NodeType::Sequence) { if (node.type() == NodeType::Sequence) {
for (detail::const_node_iterator it = node.begin(); it != node.end(); ++it) for (auto element : node)
Setup(**it); Setup(*element);
} else if (node.type() == NodeType::Map) { } else if (node.type() == NodeType::Map) {
for (detail::const_node_iterator it = node.begin(); it != node.end(); for (auto element : node) {
++it) { Setup(*element.first);
Setup(*it->first); Setup(*element.second);
Setup(*it->second);
} }
} }
} }
@ -77,17 +76,15 @@ void NodeEvents::Emit(const detail::node& node, EventHandler& handler,
break; break;
case NodeType::Sequence: case NodeType::Sequence:
handler.OnSequenceStart(Mark(), node.tag(), anchor, node.style()); handler.OnSequenceStart(Mark(), node.tag(), anchor, node.style());
for (detail::const_node_iterator it = node.begin(); it != node.end(); for (auto element : node)
++it) Emit(*element, handler, am);
Emit(**it, handler, am);
handler.OnSequenceEnd(); handler.OnSequenceEnd();
break; break;
case NodeType::Map: case NodeType::Map:
handler.OnMapStart(Mark(), node.tag(), anchor, node.style()); handler.OnMapStart(Mark(), node.tag(), anchor, node.style());
for (detail::const_node_iterator it = node.begin(); it != node.end(); for (auto element : node) {
++it) { Emit(*element.first, handler, am);
Emit(*it->first, handler, am); Emit(*element.second, handler, am);
Emit(*it->second, handler, am);
} }
handler.OnMapEnd(); handler.OnMapEnd();
break; break;

View File

@ -51,7 +51,7 @@ std::vector<Node> LoadAll(std::istream& input) {
std::vector<Node> docs; std::vector<Node> docs;
Parser parser(input); Parser parser(input);
while (1) { while (true) {
NodeBuilder builder; NodeBuilder builder;
if (!parser.HandleNextDocument(builder)) { if (!parser.HandleNextDocument(builder)) {
break; break;

View File

@ -51,7 +51,7 @@ Token& Scanner::peek() {
Mark Scanner::mark() const { return INPUT.mark(); } Mark Scanner::mark() const { return INPUT.mark(); }
void Scanner::EnsureTokensInQueue() { void Scanner::EnsureTokensInQueue() {
while (1) { while (true) {
if (!m_tokens.empty()) { if (!m_tokens.empty()) {
Token& token = m_tokens.front(); Token& token = m_tokens.front();
@ -88,7 +88,7 @@ void Scanner::ScanNextToken() {
return StartStream(); return StartStream();
} }
// get rid of whitespace, etc. (in between tokens it should be irrelevent) // get rid of whitespace, etc. (in between tokens it should be irrelevant)
ScanToNextToken(); ScanToNextToken();
// maybe need to end some blocks // maybe need to end some blocks
@ -174,7 +174,7 @@ void Scanner::ScanNextToken() {
} }
void Scanner::ScanToNextToken() { void Scanner::ScanToNextToken() {
while (1) { while (true) {
// 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)) {

View File

@ -47,7 +47,8 @@ std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) {
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) { }
if (params.onDocIndicator == THROW) {
throw ParserException(INPUT.mark(), ErrorMsg::DOC_IN_SCALAR); throw ParserException(INPUT.mark(), ErrorMsg::DOC_IN_SCALAR);
} }
} }

View File

@ -57,7 +57,7 @@ struct ScanScalarParams {
bool leadingSpaces; bool leadingSpaces;
}; };
std::string ScanScalar(Stream& INPUT, ScanScalarParams& info); std::string ScanScalar(Stream& INPUT, ScanScalarParams& params);
} }
#endif // SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #endif // SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@ -37,7 +37,7 @@ void Scanner::ScanDirective() {
token.value += INPUT.get(); token.value += INPUT.get();
// read parameters // read parameters
while (1) { while (true) {
// 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);
@ -171,7 +171,7 @@ void Scanner::ScanBlockEntry() {
// Key // Key
void Scanner::ScanKey() { void Scanner::ScanKey() {
// handle keys diffently in the block context (and manage indents) // handle keys differently in the block context (and manage indents)
if (InBlockContext()) { if (InBlockContext()) {
if (!m_simpleKeyAllowed) if (!m_simpleKeyAllowed)
throw ParserException(INPUT.mark(), ErrorMsg::MAP_KEY); throw ParserException(INPUT.mark(), ErrorMsg::MAP_KEY);
@ -199,7 +199,7 @@ void Scanner::ScanValue() {
// seems fine) // seems fine)
m_simpleKeyAllowed = false; m_simpleKeyAllowed = false;
} else { } else {
// handle values diffently in the block context (and manage indents) // handle values differently in the block context (and manage indents)
if (InBlockContext()) { if (InBlockContext()) {
if (!m_simpleKeyAllowed) if (!m_simpleKeyAllowed)
throw ParserException(INPUT.mark(), ErrorMsg::MAP_VALUE); throw ParserException(INPUT.mark(), ErrorMsg::MAP_VALUE);

View File

@ -83,9 +83,8 @@ class SettingChanges {
} }
void restore() YAML_CPP_NOEXCEPT { void restore() YAML_CPP_NOEXCEPT {
for (setting_changes::const_iterator it = m_settingChanges.begin(); for (const auto& setting : m_settingChanges)
it != m_settingChanges.end(); ++it) setting->pop();
(*it)->pop();
} }
void push(std::unique_ptr<SettingChangeBase> pSettingChange) { void push(std::unique_ptr<SettingChangeBase> pSettingChange) {

View File

@ -167,7 +167,7 @@ void SingleDocParser::HandleBlockSequence(EventHandler& eventHandler) {
m_scanner.pop(); m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::BlockSeq); m_pCollectionStack->PushCollectionType(CollectionType::BlockSeq);
while (1) { while (true) {
if (m_scanner.empty()) if (m_scanner.empty())
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ); throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ);
@ -200,7 +200,7 @@ void SingleDocParser::HandleFlowSequence(EventHandler& eventHandler) {
m_scanner.pop(); m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::FlowSeq); m_pCollectionStack->PushCollectionType(CollectionType::FlowSeq);
while (1) { while (true) {
if (m_scanner.empty()) if (m_scanner.empty())
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW); throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);
@ -253,7 +253,7 @@ void SingleDocParser::HandleBlockMap(EventHandler& eventHandler) {
m_scanner.pop(); m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::BlockMap); m_pCollectionStack->PushCollectionType(CollectionType::BlockMap);
while (1) { while (true) {
if (m_scanner.empty()) if (m_scanner.empty())
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP); throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP);
@ -292,7 +292,7 @@ void SingleDocParser::HandleFlowMap(EventHandler& eventHandler) {
m_scanner.pop(); m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::FlowMap); m_pCollectionStack->PushCollectionType(CollectionType::FlowMap);
while (1) { while (true) {
if (m_scanner.empty()) if (m_scanner.empty())
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW); throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);
@ -377,7 +377,7 @@ void SingleDocParser::ParseProperties(std::string& tag, anchor_t& anchor,
anchor_name.clear(); anchor_name.clear();
anchor = NullAnchor; anchor = NullAnchor;
while (1) { while (true) {
if (m_scanner.empty()) if (m_scanner.empty())
return; return;

View File

@ -350,7 +350,9 @@ void Stream::StreamInUtf16() const {
// Trailing (low) surrogate...ugh, wrong order // Trailing (low) surrogate...ugh, wrong order
QueueUnicodeCodepoint(m_readahead, CP_REPLACEMENT_CHARACTER); QueueUnicodeCodepoint(m_readahead, CP_REPLACEMENT_CHARACTER);
return; return;
} else if (ch >= 0xD800 && ch < 0xDC00) { }
if (ch >= 0xD800 && ch < 0xDC00) {
// ch is a leading (high) surrogate // ch is a leading (high) surrogate
// Four byte UTF-8 code point // Four byte UTF-8 code point
@ -375,11 +377,10 @@ void Stream::StreamInUtf16() const {
// Easiest case: queue the codepoint and return // Easiest case: queue the codepoint and return
QueueUnicodeCodepoint(m_readahead, ch); QueueUnicodeCodepoint(m_readahead, ch);
return; return;
} else {
// Start the loop over with the new high surrogate
ch = chLow;
continue;
} }
// Start the loop over with the new high surrogate
ch = chLow;
continue;
} }
// Select the payload bits from the high surrogate // Select the payload bits from the high surrogate

View File

@ -52,6 +52,63 @@ TEST_F(EmitterTest, SimpleQuotedScalar) {
ExpectEmit("test"); ExpectEmit("test");
} }
TEST_F(EmitterTest, DumpAndSize) {
Node n(Load("test"));
EXPECT_EQ("test", Dump(n));
out << n;
EXPECT_EQ(4, out.size());
}
TEST_F(EmitterTest, NullScalar) {
Node n(Load("null"));
out << n;
ExpectEmit("~");
}
TEST_F(EmitterTest, AliasScalar) {
Node n(Load("[&a str, *a]"));
out << n;
ExpectEmit("[&1 str, *1]");
}
TEST_F(EmitterTest, StringFormat) {
out << BeginSeq;
out.SetStringFormat(SingleQuoted);
out << "string";
out.SetStringFormat(DoubleQuoted);
out << "string";
out.SetStringFormat(Literal);
out << "string";
out << EndSeq;
ExpectEmit("- 'string'\n- \"string\"\n- |\n string");
}
TEST_F(EmitterTest, IntBase) {
out << BeginSeq;
out.SetIntBase(Dec);
out << 1024;
out.SetIntBase(Hex);
out << 1024;
out.SetIntBase(Oct);
out << 1024;
out << EndSeq;
ExpectEmit("- 1024\n- 0x400\n- 02000");
}
TEST_F(EmitterTest, NumberPrecision) {
out.SetFloatPrecision(3);
out.SetDoublePrecision(2);
out << BeginSeq;
out << 3.1425926f;
out << 53.5893;
out << 2384626.4338;
out << EndSeq;
ExpectEmit("- 3.14\n- 54\n- 2.4e+06");
}
TEST_F(EmitterTest, SimpleSeq) { TEST_F(EmitterTest, SimpleSeq) {
out << BeginSeq; out << BeginSeq;
out << "eggs"; out << "eggs";
@ -429,6 +486,12 @@ TEST_F(EmitterTest, ByKindTagWithScalar) {
ExpectEmit("- \"12\"\n- 12\n- ! 12"); ExpectEmit("- \"12\"\n- 12\n- ! 12");
} }
TEST_F(EmitterTest, LocalTagInNameHandle) {
out << LocalTag("a", "foo") << "bar";
ExpectEmit("!a!foo bar");
}
TEST_F(EmitterTest, LocalTagWithScalar) { TEST_F(EmitterTest, LocalTagWithScalar) {
out << LocalTag("foo") << "bar"; out << LocalTag("foo") << "bar";
@ -516,6 +579,17 @@ TEST_F(EmitterTest, STLContainers) {
ExpectEmit("- [2, 3, 5, 7, 11, 13]\n- Daniel: 26\n Jesse: 24"); ExpectEmit("- [2, 3, 5, 7, 11, 13]\n- Daniel: 26\n Jesse: 24");
} }
TEST_F(EmitterTest, CommentStyle) {
out.SetPreCommentIndent(1);
out.SetPostCommentIndent(2);
out << BeginMap;
out << Key << "method";
out << Value << "least squares" << Comment("should we change this method?");
out << EndMap;
ExpectEmit("method: least squares # should we change this method?");
}
TEST_F(EmitterTest, SimpleComment) { TEST_F(EmitterTest, SimpleComment) {
out << BeginMap; out << BeginMap;
out << Key << "method"; out << Key << "method";
@ -644,6 +718,17 @@ TEST_F(EmitterTest, Null) {
ExpectEmit("- ~\n- null value: ~\n ~: null key"); ExpectEmit("- ~\n- null value: ~\n ~: null key");
} }
TEST_F(EmitterTest, OutputCharset) {
out << BeginSeq;
out.SetOutputCharset(EmitNonAscii);
out << "\x24 \xC2\xA2 \xE2\x82\xAC";
out.SetOutputCharset(EscapeNonAscii);
out << "\x24 \xC2\xA2 \xE2\x82\xAC";
out << EndSeq;
ExpectEmit("- $ ¢ €\n- \"$ \\xa2 \\u20ac\"");
}
TEST_F(EmitterTest, EscapedUnicode) { TEST_F(EmitterTest, EscapedUnicode) {
out << EscapeNonAscii << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2"; out << EscapeNonAscii << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2";
@ -660,6 +745,11 @@ TEST_F(EmitterTest, DoubleQuotedUnicode) {
ExpectEmit("\"\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2\""); ExpectEmit("\"\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2\"");
} }
TEST_F(EmitterTest, DoubleQuotedString) {
out << DoubleQuoted << "\" \\ \n \t \r \b \x15 \xEF\xBB\xBF \x24";
ExpectEmit("\"\\\" \\\\ \\n \\t \\r \\b \\x15 \\ufeff $\"");
}
struct Foo { struct Foo {
Foo() : x(0) {} Foo() : x(0) {}
Foo(int x_, const std::string& bar_) : x(x_), bar(bar_) {} Foo(int x_, const std::string& bar_) : x(x_), bar(bar_) {}
@ -826,6 +916,57 @@ TEST_F(EmitterTest, ColonAtEndOfScalarInFlow) {
ExpectEmit("{\"C:\": \"C:\"}"); ExpectEmit("{\"C:\": \"C:\"}");
} }
TEST_F(EmitterTest, GlobalBoolFormatting) {
out << BeginSeq;
out.SetBoolFormat(UpperCase);
out.SetBoolFormat(YesNoBool);
out << true;
out << false;
out.SetBoolFormat(TrueFalseBool);
out << true;
out << false;
out.SetBoolFormat(OnOffBool);
out << true;
out << false;
out.SetBoolFormat(LowerCase);
out.SetBoolFormat(YesNoBool);
out << true;
out << false;
out.SetBoolFormat(TrueFalseBool);
out << true;
out << false;
out.SetBoolFormat(OnOffBool);
out << true;
out << false;
out.SetBoolFormat(CamelCase);
out.SetBoolFormat(YesNoBool);
out << true;
out << false;
out.SetBoolFormat(TrueFalseBool);
out << true;
out << false;
out.SetBoolFormat(OnOffBool);
out << true;
out << false;
out.SetBoolFormat(ShortBool);
out.SetBoolFormat(UpperCase);
out.SetBoolFormat(YesNoBool);
out << true;
out << false;
out.SetBoolFormat(TrueFalseBool);
out << true;
out << false;
out.SetBoolFormat(OnOffBool);
out << true;
out << false;
out << EndSeq;
ExpectEmit(
"- YES\n- NO\n- TRUE\n- FALSE\n- ON\n- OFF\n"
"- yes\n- no\n- true\n- false\n- on\n- off\n"
"- Yes\n- No\n- True\n- False\n- On\n- Off\n"
"- Y\n- N\n- Y\n- N\n- Y\n- N");
}
TEST_F(EmitterTest, BoolFormatting) { TEST_F(EmitterTest, BoolFormatting) {
out << BeginSeq; out << BeginSeq;
out << TrueFalseBool << UpperCase << true; out << TrueFalseBool << UpperCase << true;

View File

@ -21,22 +21,35 @@ TEST(LoadNodeTest, FallbackValues) {
} }
TEST(LoadNodeTest, NumericConversion) { TEST(LoadNodeTest, NumericConversion) {
Node node = Load("[1.5, 1, .nan, .inf, -.inf, 0x15, 015]"); EXPECT_EQ(1.5f, Load("1.5").as<float>());
EXPECT_EQ(1.5f, node[0].as<float>()); EXPECT_EQ(1.5, Load("1.5").as<double>());
EXPECT_EQ(1.5, node[0].as<double>()); EXPECT_THROW(Load("1.5").as<int>(), TypedBadConversion<int>);
EXPECT_THROW(node[0].as<int>(), TypedBadConversion<int>); EXPECT_EQ(1, Load("1").as<int>());
EXPECT_EQ(1, node[1].as<int>()); EXPECT_EQ(1.0f, Load("1").as<float>());
EXPECT_EQ(1.0f, node[1].as<float>()); EXPECT_NE(Load(".nan").as<float>(), Load(".nan").as<float>());
EXPECT_NE(node[2].as<float>(), node[2].as<float>()); EXPECT_EQ(std::numeric_limits<float>::infinity(), Load(".inf").as<float>());
EXPECT_EQ(std::numeric_limits<float>::infinity(), node[3].as<float>()); EXPECT_EQ(-std::numeric_limits<float>::infinity(), Load("-.inf").as<float>());
EXPECT_EQ(-std::numeric_limits<float>::infinity(), node[4].as<float>()); EXPECT_EQ(21, Load("0x15").as<int>());
EXPECT_EQ(21, node[5].as<int>()); EXPECT_EQ(13, Load("015").as<int>());
EXPECT_EQ(13, node[6].as<int>()); EXPECT_EQ(-128, +Load("-128").as<int8_t>());
EXPECT_EQ(127, +Load("127").as<int8_t>());
EXPECT_THROW(Load("128").as<int8_t>(), TypedBadConversion<signed char>);
EXPECT_EQ(255, +Load("255").as<uint8_t>());
EXPECT_THROW(Load("256").as<uint8_t>(), TypedBadConversion<unsigned char>);
// test as<char>/as<uint8_t> with a,"ab",'1',"127"
EXPECT_EQ('a', Load("a").as<char>());
EXPECT_THROW(Load("ab").as<char>(), TypedBadConversion<char>);
EXPECT_EQ('1', Load("1").as<char>());
EXPECT_THROW(Load("127").as<char>(), TypedBadConversion<char>);
EXPECT_THROW(Load("a").as<uint8_t>(), TypedBadConversion<unsigned char>);
EXPECT_THROW(Load("ab").as<uint8_t>(), TypedBadConversion<unsigned char>);
EXPECT_EQ(1, +Load("1").as<uint8_t>());
// Throw exception: convert a negative number to an unsigned number. // Throw exception: convert a negative number to an unsigned number.
EXPECT_THROW(node[7].as<unsigned>(), TypedBadConversion<unsigned int>); EXPECT_THROW(Load("-128").as<unsigned>(), TypedBadConversion<unsigned int>);
EXPECT_THROW(node[7].as<unsigned short>(), TypedBadConversion<unsigned short>); EXPECT_THROW(Load("-128").as<unsigned short>(), TypedBadConversion<unsigned short>);
EXPECT_THROW(node[7].as<unsigned long>(), TypedBadConversion<unsigned long>); EXPECT_THROW(Load("-128").as<unsigned long>(), TypedBadConversion<unsigned long>);
EXPECT_THROW(node[7].as<unsigned long long>(), TypedBadConversion<unsigned long long>); EXPECT_THROW(Load("-128").as<unsigned long long>(), TypedBadConversion<unsigned long long>);
EXPECT_THROW(Load("-128").as<uint8_t>(), TypedBadConversion<unsigned char>);
} }
TEST(LoadNodeTest, Binary) { TEST(LoadNodeTest, Binary) {
@ -241,7 +254,7 @@ TEST(NodeTest, IncompleteJson) {
{"JSON map without end brace", "{\"access\":\"abc\"", {"JSON map without end brace", "{\"access\":\"abc\"",
ErrorMsg::END_OF_MAP_FLOW}, ErrorMsg::END_OF_MAP_FLOW},
}; };
for (const ParserExceptionTestCase test : tests) { for (const ParserExceptionTestCase& test : tests) {
try { try {
Load(test.input); Load(test.input);
FAIL() << "Expected exception " << test.expected_exception << " for " FAIL() << "Expected exception " << test.expected_exception << " for "
@ -256,7 +269,18 @@ TEST(NodeTest, LoadTildeAsNull) {
Node node = Load("~"); Node node = Load("~");
ASSERT_TRUE(node.IsNull()); ASSERT_TRUE(node.IsNull());
} }
TEST(NodeTest, LoadNullWithStrTag) {
Node node = Load("!!str null");
EXPECT_EQ(node.Tag(), "tag:yaml.org,2002:str");
EXPECT_EQ(node.as<std::string>(), "null");
}
TEST(NodeTest, LoadQuotedNull) {
Node node = Load("\"null\"");
EXPECT_EQ(node.as<std::string>(), "null");
}
TEST(NodeTest, LoadTagWithParenthesis) { TEST(NodeTest, LoadTagWithParenthesis) {
Node node = Load("!Complex(Tag) foo"); Node node = Load("!Complex(Tag) foo");
EXPECT_EQ(node.Tag(), "!Complex(Tag)"); EXPECT_EQ(node.Tag(), "!Complex(Tag)");

View File

@ -1127,5 +1127,10 @@ TEST(NodeSpecTest, Ex8_22_BlockCollectionNodes) {
EXPECT_EQ(1, doc["mapping"].size()); EXPECT_EQ(1, doc["mapping"].size());
EXPECT_EQ("bar", doc["mapping"]["foo"].as<std::string>()); EXPECT_EQ("bar", doc["mapping"]["foo"].as<std::string>());
} }
TEST(NodeSpecTest, FlowMapNotClosed) {
EXPECT_THROW_PARSER_EXCEPTION(Load("{x:"), ErrorMsg::UNKNOWN_TOKEN);
}
} }
} }

View File

@ -8,23 +8,23 @@
class NullEventHandler : public YAML::EventHandler { class NullEventHandler : public YAML::EventHandler {
public: public:
typedef YAML::Mark Mark; using Mark = YAML::Mark;
typedef YAML::anchor_t anchor_t; using anchor_t = YAML::anchor_t;
NullEventHandler() {} NullEventHandler() = default;
virtual void OnDocumentStart(const Mark&) {} void OnDocumentStart(const Mark&) override {}
virtual void OnDocumentEnd() {} void OnDocumentEnd() override {}
virtual void OnNull(const Mark&, anchor_t) {} void OnNull(const Mark&, anchor_t) override {}
virtual void OnAlias(const Mark&, anchor_t) {} void OnAlias(const Mark&, anchor_t) override {}
virtual void OnScalar(const Mark&, const std::string&, anchor_t, void OnScalar(const Mark&, const std::string&, anchor_t,
const std::string&) {} const std::string&) override {}
virtual void OnSequenceStart(const Mark&, const std::string&, anchor_t, void OnSequenceStart(const Mark&, const std::string&, anchor_t,
YAML::EmitterStyle::value style) {} YAML::EmitterStyle::value style) override {}
virtual void OnSequenceEnd() {} void OnSequenceEnd() override {}
virtual void OnMapStart(const Mark&, const std::string&, anchor_t, void OnMapStart(const Mark&, const std::string&, anchor_t,
YAML::EmitterStyle::value style) {} YAML::EmitterStyle::value style) override {}
virtual void OnMapEnd() {} void OnMapEnd() override {}
}; };
void run(std::istream& in) { void run(std::istream& in) {
@ -68,14 +68,14 @@ int main(int argc, char** argv) {
} }
} }
if (N > 1 && !cache && filename == "") { if (N > 1 && !cache && filename.empty()) {
usage(); usage();
return -1; return -1;
} }
if (cache) { if (cache) {
std::string input; std::string input;
if (filename != "") { if (!filename.empty()) {
std::ifstream in(filename); std::ifstream in(filename);
input = read_stream(in); input = read_stream(in);
} else { } else {
@ -87,7 +87,7 @@ int main(int argc, char** argv) {
run(in); run(in);
} }
} else { } else {
if (filename != "") { if (!filename.empty()) {
std::ifstream in(filename); std::ifstream in(filename);
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {
in.seekg(std::ios_base::beg); in.seekg(std::ios_base::beg);

View File

@ -6,23 +6,23 @@
class NullEventHandler : public YAML::EventHandler { class NullEventHandler : public YAML::EventHandler {
public: public:
typedef YAML::Mark Mark; using Mark = YAML::Mark;
typedef YAML::anchor_t anchor_t; using anchor_t = YAML::anchor_t;
NullEventHandler() {} NullEventHandler() = default;
virtual void OnDocumentStart(const Mark&) {} void OnDocumentStart(const Mark&) override {}
virtual void OnDocumentEnd() {} void OnDocumentEnd() override {}
virtual void OnNull(const Mark&, anchor_t) {} void OnNull(const Mark&, anchor_t) override {}
virtual void OnAlias(const Mark&, anchor_t) {} void OnAlias(const Mark&, anchor_t) override {}
virtual void OnScalar(const Mark&, const std::string&, anchor_t, void OnScalar(const Mark&, const std::string&, anchor_t,
const std::string&) {} const std::string&) override {}
virtual void OnSequenceStart(const Mark&, const std::string&, anchor_t, void OnSequenceStart(const Mark&, const std::string&, anchor_t,
YAML::EmitterStyle::value style) {} YAML::EmitterStyle::value style) override {}
virtual void OnSequenceEnd() {} void OnSequenceEnd() override {}
virtual void OnMapStart(const Mark&, const std::string&, anchor_t, void OnMapStart(const Mark&, const std::string&, anchor_t,
YAML::EmitterStyle::value style) {} YAML::EmitterStyle::value style) override {}
virtual void OnMapEnd() {} void OnMapEnd() override {}
}; };
int main() { int main() {