mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2025-09-08 12:21:17 +00:00
emitter: Support std::string_view
Accept Emitter::operator<<(std::string_view). ABI remains C++11 compatible by exposing new method Emitter::Write(const char*, size_t). All affected calls optimized to pass std::string values as pointer + size tuple into appropriate routines.
This commit is contained in:

committed by
Jesse Beder

parent
8a9a7b74ef
commit
7470c2d871
@@ -9,12 +9,17 @@
|
|||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <cstring>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
|
||||||
|
#include <string_view>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "yaml-cpp/binary.h"
|
#include "yaml-cpp/binary.h"
|
||||||
#include "yaml-cpp/dll.h"
|
#include "yaml-cpp/dll.h"
|
||||||
#include "yaml-cpp/emitterdef.h"
|
#include "yaml-cpp/emitterdef.h"
|
||||||
@@ -68,6 +73,7 @@ class YAML_CPP_API Emitter {
|
|||||||
Emitter& SetLocalPrecision(const _Precision& precision);
|
Emitter& SetLocalPrecision(const _Precision& precision);
|
||||||
|
|
||||||
// overloads of write
|
// overloads of write
|
||||||
|
Emitter& Write(const char* str, std::size_t size);
|
||||||
Emitter& Write(const std::string& str);
|
Emitter& Write(const std::string& str);
|
||||||
Emitter& Write(bool b);
|
Emitter& Write(bool b);
|
||||||
Emitter& Write(char ch);
|
Emitter& Write(char ch);
|
||||||
@@ -201,8 +207,13 @@ inline void Emitter::SetStreamablePrecision<double>(std::stringstream& stream) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// overloads of insertion
|
// overloads of insertion
|
||||||
|
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, const std::string_view& v) {
|
||||||
|
return emitter.Write(v.data(), v.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
inline Emitter& operator<<(Emitter& emitter, const std::string& v) {
|
inline Emitter& operator<<(Emitter& emitter, const std::string& v) {
|
||||||
return emitter.Write(v);
|
return emitter.Write(v.data(), v.size());
|
||||||
}
|
}
|
||||||
inline Emitter& operator<<(Emitter& emitter, bool v) {
|
inline Emitter& operator<<(Emitter& emitter, bool v) {
|
||||||
return emitter.Write(v);
|
return emitter.Write(v);
|
||||||
@@ -233,7 +244,7 @@ inline Emitter& operator<<(Emitter& emitter, const Binary& b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline Emitter& operator<<(Emitter& emitter, const char* v) {
|
inline Emitter& operator<<(Emitter& emitter, const char* v) {
|
||||||
return emitter.Write(std::string(v));
|
return emitter.Write(v, std::strlen(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Emitter& operator<<(Emitter& emitter, int v) {
|
inline Emitter& operator<<(Emitter& emitter, int v) {
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "yaml-cpp/dll.h"
|
#include "yaml-cpp/dll.h"
|
||||||
#include <string>
|
#include <cstddef>
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
class Node;
|
class Node;
|
||||||
@@ -18,7 +18,7 @@ inline bool operator==(const _Null&, const _Null&) { return true; }
|
|||||||
inline bool operator!=(const _Null&, const _Null&) { return false; }
|
inline bool operator!=(const _Null&, const _Null&) { return false; }
|
||||||
|
|
||||||
YAML_CPP_API bool IsNull(const Node& node); // old API only
|
YAML_CPP_API bool IsNull(const Node& node); // old API only
|
||||||
YAML_CPP_API bool IsNullString(const std::string& str);
|
YAML_CPP_API bool IsNullString(const char* str, std::size_t size);
|
||||||
|
|
||||||
extern YAML_CPP_API _Null Null;
|
extern YAML_CPP_API _Null Null;
|
||||||
}
|
}
|
||||||
|
@@ -716,33 +716,33 @@ StringEscaping::value GetStringEscapingStyle(const EMITTER_MANIP emitterManip) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Emitter& Emitter::Write(const std::string& str) {
|
Emitter& Emitter::Write(const char* str, std::size_t size) {
|
||||||
if (!good())
|
if (!good())
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
StringEscaping::value stringEscaping = GetStringEscapingStyle(m_pState->GetOutputCharset());
|
StringEscaping::value stringEscaping = GetStringEscapingStyle(m_pState->GetOutputCharset());
|
||||||
|
|
||||||
const StringFormat::value strFormat =
|
const StringFormat::value strFormat =
|
||||||
Utils::ComputeStringFormat(str, m_pState->GetStringFormat(),
|
Utils::ComputeStringFormat(str, size, m_pState->GetStringFormat(),
|
||||||
m_pState->CurGroupFlowType(), stringEscaping == StringEscaping::NonAscii);
|
m_pState->CurGroupFlowType(), stringEscaping == StringEscaping::NonAscii);
|
||||||
|
|
||||||
if (strFormat == StringFormat::Literal || str.size() > 1024)
|
if (strFormat == StringFormat::Literal || size > 1024)
|
||||||
m_pState->SetMapKeyFormat(YAML::LongKey, FmtScope::Local);
|
m_pState->SetMapKeyFormat(YAML::LongKey, FmtScope::Local);
|
||||||
|
|
||||||
PrepareNode(EmitterNodeType::Scalar);
|
PrepareNode(EmitterNodeType::Scalar);
|
||||||
|
|
||||||
switch (strFormat) {
|
switch (strFormat) {
|
||||||
case StringFormat::Plain:
|
case StringFormat::Plain:
|
||||||
m_stream << str;
|
m_stream.write(str, size);
|
||||||
break;
|
break;
|
||||||
case StringFormat::SingleQuoted:
|
case StringFormat::SingleQuoted:
|
||||||
Utils::WriteSingleQuotedString(m_stream, str);
|
Utils::WriteSingleQuotedString(m_stream, str, size);
|
||||||
break;
|
break;
|
||||||
case StringFormat::DoubleQuoted:
|
case StringFormat::DoubleQuoted:
|
||||||
Utils::WriteDoubleQuotedString(m_stream, str, stringEscaping);
|
Utils::WriteDoubleQuotedString(m_stream, str, size, stringEscaping);
|
||||||
break;
|
break;
|
||||||
case StringFormat::Literal:
|
case StringFormat::Literal:
|
||||||
Utils::WriteLiteralString(m_stream, str,
|
Utils::WriteLiteralString(m_stream, str, size,
|
||||||
m_pState->CurIndent() + m_pState->GetIndent());
|
m_pState->CurIndent() + m_pState->GetIndent());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -752,6 +752,10 @@ Emitter& Emitter::Write(const std::string& str) {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Emitter& Emitter::Write(const std::string& str) {
|
||||||
|
return Write(str.data(), str.size());
|
||||||
|
}
|
||||||
|
|
||||||
std::size_t Emitter::GetFloatPrecision() const {
|
std::size_t Emitter::GetFloatPrecision() const {
|
||||||
return m_pState->GetFloatPrecision();
|
return m_pState->GetFloatPrecision();
|
||||||
}
|
}
|
||||||
@@ -865,7 +869,7 @@ Emitter& Emitter::Write(const _Alias& alias) {
|
|||||||
|
|
||||||
PrepareNode(EmitterNodeType::Scalar);
|
PrepareNode(EmitterNodeType::Scalar);
|
||||||
|
|
||||||
if (!Utils::WriteAlias(m_stream, alias.content)) {
|
if (!Utils::WriteAlias(m_stream, alias.content.data(), alias.content.size())) {
|
||||||
m_pState->SetError(ErrorMsg::INVALID_ALIAS);
|
m_pState->SetError(ErrorMsg::INVALID_ALIAS);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -888,7 +892,7 @@ Emitter& Emitter::Write(const _Anchor& anchor) {
|
|||||||
|
|
||||||
PrepareNode(EmitterNodeType::Property);
|
PrepareNode(EmitterNodeType::Property);
|
||||||
|
|
||||||
if (!Utils::WriteAnchor(m_stream, anchor.content)) {
|
if (!Utils::WriteAnchor(m_stream, anchor.content.data(), anchor.content.size())) {
|
||||||
m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
|
m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -937,7 +941,7 @@ Emitter& Emitter::Write(const _Comment& comment) {
|
|||||||
|
|
||||||
if (m_stream.col() > 0)
|
if (m_stream.col() > 0)
|
||||||
m_stream << Indentation(m_pState->GetPreCommentIndent());
|
m_stream << Indentation(m_pState->GetPreCommentIndent());
|
||||||
Utils::WriteComment(m_stream, comment.content,
|
Utils::WriteComment(m_stream, comment.content.data(), comment.content.size(),
|
||||||
m_pState->GetPostCommentIndent());
|
m_pState->GetPostCommentIndent());
|
||||||
|
|
||||||
m_pState->SetNonContent();
|
m_pState->SetNonContent();
|
||||||
|
@@ -89,8 +89,8 @@ int Utf8BytesIndicated(char ch) {
|
|||||||
bool IsTrailingByte(char ch) { return (ch & 0xC0) == 0x80; }
|
bool IsTrailingByte(char ch) { return (ch & 0xC0) == 0x80; }
|
||||||
|
|
||||||
bool GetNextCodePointAndAdvance(int& codePoint,
|
bool GetNextCodePointAndAdvance(int& codePoint,
|
||||||
std::string::const_iterator& first,
|
const char*& first,
|
||||||
std::string::const_iterator last) {
|
const char* last) {
|
||||||
if (first == last)
|
if (first == last)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -153,23 +153,23 @@ void WriteCodePoint(ostream_wrapper& out, int codePoint) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
|
bool IsValidPlainScalar(const char* str, std::size_t size, FlowType::value flowType,
|
||||||
bool allowOnlyAscii) {
|
bool allowOnlyAscii) {
|
||||||
// check against null
|
// check against null
|
||||||
if (IsNullString(str)) {
|
if (IsNullString(str, size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the start
|
// check the start
|
||||||
const RegEx& start = (flowType == FlowType::Flow ? Exp::PlainScalarInFlow()
|
const RegEx& start = (flowType == FlowType::Flow ? Exp::PlainScalarInFlow()
|
||||||
: Exp::PlainScalar());
|
: Exp::PlainScalar());
|
||||||
if (!start.Matches(str)) {
|
if (!start.Matches(StringCharSource(str, size))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// and check the end for plain whitespace (which can't be faithfully kept in a
|
// and check the end for plain whitespace (which can't be faithfully kept in a
|
||||||
// plain scalar)
|
// plain scalar)
|
||||||
if (!str.empty() && *str.rbegin() == ' ') {
|
if (size != 0 && str[size - 1] == ' ') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,7 +185,7 @@ bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
|
|||||||
const RegEx& disallowed =
|
const RegEx& disallowed =
|
||||||
flowType == FlowType::Flow ? disallowed_flow : disallowed_block;
|
flowType == FlowType::Flow ? disallowed_flow : disallowed_block;
|
||||||
|
|
||||||
StringCharSource buffer(str.c_str(), str.size());
|
StringCharSource buffer(str, size);
|
||||||
while (buffer) {
|
while (buffer) {
|
||||||
if (disallowed.Matches(buffer)) {
|
if (disallowed.Matches(buffer)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -199,22 +199,22 @@ bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii) {
|
bool IsValidSingleQuotedScalar(const char* str, std::size_t size, bool escapeNonAscii) {
|
||||||
// TODO: check for non-printable characters?
|
// TODO: check for non-printable characters?
|
||||||
return std::none_of(str.begin(), str.end(), [=](char ch) {
|
return std::none_of(str, str + size, [=](char ch) {
|
||||||
return (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch))) ||
|
return (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch))) ||
|
||||||
(ch == '\n');
|
(ch == '\n');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType,
|
bool IsValidLiteralScalar(const char* str, std::size_t size, FlowType::value flowType,
|
||||||
bool escapeNonAscii) {
|
bool escapeNonAscii) {
|
||||||
if (flowType == FlowType::Flow) {
|
if (flowType == FlowType::Flow) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check for non-printable characters?
|
// TODO: check for non-printable characters?
|
||||||
return std::none_of(str.begin(), str.end(), [=](char ch) {
|
return std::none_of(str, str + size, [=](char ch) {
|
||||||
return (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch)));
|
return (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -254,10 +254,10 @@ void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint, StringE
|
|||||||
out << hexDigits[(codePoint >> (4 * (digits - 1))) & 0xF];
|
out << hexDigits[(codePoint >> (4 * (digits - 1))) & 0xF];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteAliasName(ostream_wrapper& out, const std::string& str) {
|
bool WriteAliasName(ostream_wrapper& out, const char* str, std::size_t size) {
|
||||||
int codePoint;
|
int codePoint;
|
||||||
for (std::string::const_iterator i = str.begin();
|
for (const char* i = str;
|
||||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
|
||||||
if (!IsAnchorChar(codePoint)) {
|
if (!IsAnchorChar(codePoint)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -268,25 +268,25 @@ bool WriteAliasName(ostream_wrapper& out, const std::string& str) {
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
StringFormat::value ComputeStringFormat(const std::string& str,
|
StringFormat::value ComputeStringFormat(const char* str, std::size_t size,
|
||||||
EMITTER_MANIP strFormat,
|
EMITTER_MANIP strFormat,
|
||||||
FlowType::value flowType,
|
FlowType::value flowType,
|
||||||
bool escapeNonAscii) {
|
bool escapeNonAscii) {
|
||||||
switch (strFormat) {
|
switch (strFormat) {
|
||||||
case Auto:
|
case Auto:
|
||||||
if (IsValidPlainScalar(str, flowType, escapeNonAscii)) {
|
if (IsValidPlainScalar(str, size, flowType, escapeNonAscii)) {
|
||||||
return StringFormat::Plain;
|
return StringFormat::Plain;
|
||||||
}
|
}
|
||||||
return StringFormat::DoubleQuoted;
|
return StringFormat::DoubleQuoted;
|
||||||
case SingleQuoted:
|
case SingleQuoted:
|
||||||
if (IsValidSingleQuotedScalar(str, escapeNonAscii)) {
|
if (IsValidSingleQuotedScalar(str, size, escapeNonAscii)) {
|
||||||
return StringFormat::SingleQuoted;
|
return StringFormat::SingleQuoted;
|
||||||
}
|
}
|
||||||
return StringFormat::DoubleQuoted;
|
return StringFormat::DoubleQuoted;
|
||||||
case DoubleQuoted:
|
case DoubleQuoted:
|
||||||
return StringFormat::DoubleQuoted;
|
return StringFormat::DoubleQuoted;
|
||||||
case Literal:
|
case Literal:
|
||||||
if (IsValidLiteralScalar(str, flowType, escapeNonAscii)) {
|
if (IsValidLiteralScalar(str, size, flowType, escapeNonAscii)) {
|
||||||
return StringFormat::Literal;
|
return StringFormat::Literal;
|
||||||
}
|
}
|
||||||
return StringFormat::DoubleQuoted;
|
return StringFormat::DoubleQuoted;
|
||||||
@@ -297,11 +297,11 @@ StringFormat::value ComputeStringFormat(const std::string& str,
|
|||||||
return StringFormat::DoubleQuoted;
|
return StringFormat::DoubleQuoted;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str) {
|
bool WriteSingleQuotedString(ostream_wrapper& out, const char* str, std::size_t size) {
|
||||||
out << "'";
|
out << "'";
|
||||||
int codePoint;
|
int codePoint;
|
||||||
for (std::string::const_iterator i = str.begin();
|
for (const char* i = str;
|
||||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
|
||||||
if (codePoint == '\n') {
|
if (codePoint == '\n') {
|
||||||
return false; // We can't handle a new line and the attendant indentation
|
return false; // We can't handle a new line and the attendant indentation
|
||||||
// yet
|
// yet
|
||||||
@@ -317,12 +317,12 @@ bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
|
bool WriteDoubleQuotedString(ostream_wrapper& out, const char* str, std::size_t size,
|
||||||
StringEscaping::value stringEscaping) {
|
StringEscaping::value stringEscaping) {
|
||||||
out << "\"";
|
out << "\"";
|
||||||
int codePoint;
|
int codePoint;
|
||||||
for (std::string::const_iterator i = str.begin();
|
for (const char* i = str;
|
||||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
|
||||||
switch (codePoint) {
|
switch (codePoint) {
|
||||||
case '\"':
|
case '\"':
|
||||||
out << "\\\"";
|
out << "\\\"";
|
||||||
@@ -364,12 +364,12 @@ bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
|
bool WriteLiteralString(ostream_wrapper& out, const char* str, std::size_t size,
|
||||||
std::size_t indent) {
|
std::size_t indent) {
|
||||||
out << "|\n";
|
out << "|\n";
|
||||||
int codePoint;
|
int codePoint;
|
||||||
for (std::string::const_iterator i = str.begin();
|
for (const char* i = str;
|
||||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
|
||||||
if (codePoint == '\n') {
|
if (codePoint == '\n') {
|
||||||
out << "\n";
|
out << "\n";
|
||||||
} else {
|
} else {
|
||||||
@@ -407,14 +407,14 @@ bool WriteChar(ostream_wrapper& out, char ch, StringEscaping::value stringEscapi
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteComment(ostream_wrapper& out, const std::string& str,
|
bool WriteComment(ostream_wrapper& out, const char* str, std::size_t size,
|
||||||
std::size_t postCommentIndent) {
|
std::size_t postCommentIndent) {
|
||||||
const std::size_t curIndent = out.col();
|
const std::size_t curIndent = out.col();
|
||||||
out << "#" << Indentation(postCommentIndent);
|
out << "#" << Indentation(postCommentIndent);
|
||||||
out.set_comment();
|
out.set_comment();
|
||||||
int codePoint;
|
int codePoint;
|
||||||
for (std::string::const_iterator i = str.begin();
|
for (const char* i = str;
|
||||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
|
||||||
if (codePoint == '\n') {
|
if (codePoint == '\n') {
|
||||||
out << "\n"
|
out << "\n"
|
||||||
<< IndentTo(curIndent) << "#" << Indentation(postCommentIndent);
|
<< IndentTo(curIndent) << "#" << Indentation(postCommentIndent);
|
||||||
@@ -426,14 +426,14 @@ bool WriteComment(ostream_wrapper& out, const std::string& str,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteAlias(ostream_wrapper& out, const std::string& str) {
|
bool WriteAlias(ostream_wrapper& out, const char* str, std::size_t size) {
|
||||||
out << "*";
|
out << "*";
|
||||||
return WriteAliasName(out, str);
|
return WriteAliasName(out, str, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteAnchor(ostream_wrapper& out, const std::string& str) {
|
bool WriteAnchor(ostream_wrapper& out, const char* str, std::size_t size) {
|
||||||
out << "&";
|
out << "&";
|
||||||
return WriteAliasName(out, str);
|
return WriteAliasName(out, str, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim) {
|
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim) {
|
||||||
@@ -490,7 +490,8 @@ bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool WriteBinary(ostream_wrapper& out, const Binary& binary) {
|
bool WriteBinary(ostream_wrapper& out, const Binary& binary) {
|
||||||
WriteDoubleQuotedString(out, EncodeBase64(binary.data(), binary.size()),
|
std::string encoded = EncodeBase64(binary.data(), binary.size());
|
||||||
|
WriteDoubleQuotedString(out, encoded.data(), encoded.size(),
|
||||||
StringEscaping::None);
|
StringEscaping::None);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -29,22 +29,22 @@ struct StringEscaping {
|
|||||||
};
|
};
|
||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
StringFormat::value ComputeStringFormat(const std::string& str,
|
StringFormat::value ComputeStringFormat(const char* str, std::size_t size,
|
||||||
EMITTER_MANIP strFormat,
|
EMITTER_MANIP strFormat,
|
||||||
FlowType::value flowType,
|
FlowType::value flowType,
|
||||||
bool escapeNonAscii);
|
bool escapeNonAscii);
|
||||||
|
|
||||||
bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str);
|
bool WriteSingleQuotedString(ostream_wrapper& out, const char* str, std::size_t size);
|
||||||
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
|
bool WriteDoubleQuotedString(ostream_wrapper& out, const char* str, std::size_t size,
|
||||||
StringEscaping::value stringEscaping);
|
StringEscaping::value stringEscaping);
|
||||||
bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
|
bool WriteLiteralString(ostream_wrapper& out, const char* str, std::size_t size,
|
||||||
std::size_t indent);
|
std::size_t indent);
|
||||||
bool WriteChar(ostream_wrapper& out, char ch,
|
bool WriteChar(ostream_wrapper& out, char ch,
|
||||||
StringEscaping::value stringEscapingStyle);
|
StringEscaping::value stringEscapingStyle);
|
||||||
bool WriteComment(ostream_wrapper& out, const std::string& str,
|
bool WriteComment(ostream_wrapper& out, const char* str, std::size_t size,
|
||||||
std::size_t postCommentIndent);
|
std::size_t postCommentIndent);
|
||||||
bool WriteAlias(ostream_wrapper& out, const std::string& str);
|
bool WriteAlias(ostream_wrapper& out, const char* str, std::size_t size);
|
||||||
bool WriteAnchor(ostream_wrapper& out, const std::string& str);
|
bool WriteAnchor(ostream_wrapper& out, const char* str, std::size_t size);
|
||||||
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim);
|
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim);
|
||||||
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
|
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
|
||||||
const std::string& tag);
|
const std::string& tag);
|
||||||
|
13
src/null.cpp
13
src/null.cpp
@@ -1,10 +1,17 @@
|
|||||||
#include "yaml-cpp/null.h"
|
#include "yaml-cpp/null.h"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
_Null Null;
|
_Null Null;
|
||||||
|
|
||||||
bool IsNullString(const std::string& str) {
|
template <std::size_t N>
|
||||||
return str.empty() || str == "~" || str == "null" || str == "Null" ||
|
static bool same(const char* str, std::size_t size, const char (&literal)[N]) {
|
||||||
str == "NULL";
|
constexpr int literalSize = N - 1; // minus null terminator
|
||||||
|
return size == literalSize && std::strncmp(str, literal, literalSize) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsNullString(const char* str, std::size_t size) {
|
||||||
|
return size == 0 || same(str, size, "~") || same(str, size, "null") ||
|
||||||
|
same(str, size, "Null") || same(str, size, "NULL");
|
||||||
}
|
}
|
||||||
} // namespace YAML
|
} // namespace YAML
|
||||||
|
@@ -27,6 +27,10 @@ inline bool RegEx::Matches(const Stream& in) const { return Match(in) >= 0; }
|
|||||||
|
|
||||||
template <typename Source>
|
template <typename Source>
|
||||||
inline bool RegEx::Matches(const Source& source) const {
|
inline bool RegEx::Matches(const Source& source) const {
|
||||||
|
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201103L) || __cplusplus >= 201103L)
|
||||||
|
static_assert(!std::is_same<Source, const char*>::value,
|
||||||
|
#endif
|
||||||
|
"Must use StringCharSource instead of plain C-string");
|
||||||
return Match(source) >= 0;
|
return Match(source) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -94,7 +94,7 @@ void SingleDocParser::HandleNode(EventHandler& eventHandler) {
|
|||||||
tag = (token.type == Token::NON_PLAIN_SCALAR ? "!" : "?");
|
tag = (token.type == Token::NON_PLAIN_SCALAR ? "!" : "?");
|
||||||
|
|
||||||
if (token.type == Token::PLAIN_SCALAR
|
if (token.type == Token::PLAIN_SCALAR
|
||||||
&& tag.compare("?") == 0 && IsNullString(token.value)) {
|
&& tag.compare("?") == 0 && IsNullString(token.value.data(), token.value.size())) {
|
||||||
eventHandler.OnNull(mark, anchor);
|
eventHandler.OnNull(mark, anchor);
|
||||||
m_scanner.pop();
|
m_scanner.pop();
|
||||||
return;
|
return;
|
||||||
|
@@ -46,6 +46,26 @@ TEST_F(EmitterTest, SimpleScalar) {
|
|||||||
ExpectEmit("Hello, World!");
|
ExpectEmit("Hello, World!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(EmitterTest, SimpleStdStringScalar) {
|
||||||
|
out << std::string("Hello, std string");
|
||||||
|
|
||||||
|
ExpectEmit("Hello, std string");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
|
||||||
|
TEST_F(EmitterTest, SimpleStdStringViewScalar) {
|
||||||
|
out << std::string_view("Hello, std string view");
|
||||||
|
|
||||||
|
ExpectEmit("Hello, std string view");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(EmitterTest, UnterminatedStdStringViewScalar) {
|
||||||
|
out << std::string_view("HelloUnterminated", 5);
|
||||||
|
|
||||||
|
ExpectEmit("Hello");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
TEST_F(EmitterTest, SimpleQuotedScalar) {
|
TEST_F(EmitterTest, SimpleQuotedScalar) {
|
||||||
Node n(Load("\"test\""));
|
Node n(Load("\"test\""));
|
||||||
out << n;
|
out << n;
|
||||||
|
Reference in New Issue
Block a user