Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/yaml-cpp/emitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ class YAML_CPP_API Emitter {
Emitter& SetLocalPrecision(const _Precision& precision);

// overloads of write
Emitter& Write(const char* str, std::size_t size, EMITTER_MANIP emitterManip);
Emitter& Write(const char* str, std::size_t size);
Emitter& Write(const std::string& str, EMITTER_MANIP emitterManip);
Emitter& Write(const std::string& str);
Emitter& Write(bool b);
Emitter& Write(char ch);
Expand Down
6 changes: 5 additions & 1 deletion src/emitfromevents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ void EmitFromEvents::OnScalar(const Mark&, const std::string& tag,
anchor_t anchor, const std::string& value) {
BeginNode();
EmitProps(tag, anchor);
m_emitter << value;
if (tag != "!") {
m_emitter << value;
} else {
m_emitter.Write(value, EMITTER_MANIP::DoubleQuoted);
}
}

void EmitFromEvents::OnSequenceStart(const Mark&, const std::string& tag,
Expand Down
20 changes: 15 additions & 5 deletions src/emitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -716,15 +716,17 @@ StringEscaping::value GetStringEscapingStyle(const EMITTER_MANIP emitterManip) {
}
}

Emitter& Emitter::Write(const char* str, std::size_t size) {
Emitter& Emitter::Write(const char* str, std::size_t size,
EMITTER_MANIP emitterManip) {
if (!good())
return *this;

StringEscaping::value stringEscaping = GetStringEscapingStyle(m_pState->GetOutputCharset());
StringEscaping::value stringEscaping =
GetStringEscapingStyle(m_pState->GetOutputCharset());

const StringFormat::value strFormat =
Utils::ComputeStringFormat(str, size, m_pState->GetStringFormat(),
m_pState->CurGroupFlowType(), stringEscaping == StringEscaping::NonAscii);
const StringFormat::value strFormat = Utils::ComputeStringFormat(
str, size, emitterManip, m_pState->CurGroupFlowType(),
stringEscaping == StringEscaping::NonAscii);

if (strFormat == StringFormat::Literal || size > 1024)
m_pState->SetMapKeyFormat(YAML::LongKey, FmtScope::Local);
Expand Down Expand Up @@ -752,6 +754,14 @@ Emitter& Emitter::Write(const char* str, std::size_t size) {
return *this;
}

Emitter& Emitter::Write(const char* str, std::size_t size) {
return Write(str, size, m_pState->GetStringFormat());
}

Emitter& Emitter::Write(const std::string& str, EMITTER_MANIP emitterManip) {
return Write(str.data(), str.size(), emitterManip);
}

Emitter& Emitter::Write(const std::string& str) {
return Write(str.data(), str.size());
}
Expand Down
26 changes: 24 additions & 2 deletions test/integration/emitter_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,31 @@ TEST_F(EmitterTest, UnterminatedStdStringViewScalar) {
#endif

TEST_F(EmitterTest, SimpleQuotedScalar) {
Node n(Load("\"test\""));
const std::string quoted = "\"test\"";
Node n(Load(quoted));
out << n;
ExpectEmit("test");
ExpectEmit(quoted);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is a little weird; I'd much prefer that it would display

test

rather than

"test"

since the quotes are redundant.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The behavior is different, but seems reasonable (to me) since the input value was already quoted; it's not adding quotes. To maintain correct behavior while only quoting when strictly necessary requires a reliable way to detect that it's safe to omit quotes. #1276 mentions using "a laundry list of regexes, such as those for all the number formats, infinities, true/false etc." to check. Looking at the yaml spec, that seems error prone.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking further in the yaml spec, it has a list of regular expressions in the Core Schema chapter. The regexes would be different for the fail-safe or json schemas, but AFAICT yaml-cpp does not support those.

}

TEST_F(EmitterTest, QuotedScalarFalse) {
const std::string quoted = "\"false\"";
Node n(Load(quoted));
out << n;
ExpectEmit(quoted);
}

TEST_F(EmitterTest, QuotedScalarTrue) {
const std::string quoted = "\"true\"";
Node n(Load(quoted));
out << n;
ExpectEmit(quoted);
}

TEST_F(EmitterTest, QuotedScalarInt) {
const std::string quoted = "\"3\"";
Node n(Load(quoted));
out << n;
ExpectEmit(quoted);
}

TEST_F(EmitterTest, DumpAndSize) {
Expand Down
Loading