Skip to content
Merged
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
28 changes: 19 additions & 9 deletions src/emitfromevents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,16 +117,26 @@ void EmitFromEvents::BeginNode() {

void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor) {
if (!tag.empty() && tag != "?" && tag != "!"){
if (tag.size() >= 2 && tag[0] == '!' && tag[1] == '!') {
// Tags like "!!str" use the secondary tag handle; emit them through
// SecondaryTag so the rendered output keeps both bangs instead of
// failing the LocalTag regex check on the inner '!'. See #1373.
m_emitter << SecondaryTag(std::string(tag.begin()+2, tag.end()));
} else if (tag[0] == '!') {
m_emitter << LocalTag(std::string(tag.begin()+1, tag.end()));
} else {
m_emitter << VerbatimTag(tag);
if (tag.size() >= 2 && tag[0] == '!' && tag[1] == '!') {
// Tags like "!!str" use the secondary tag handle; emit them through
// SecondaryTag so the rendered output keeps both bangs instead of
// failing the LocalTag regex check on the inner '!'. See #1373.
m_emitter << SecondaryTag(std::string(tag.begin()+2, tag.end()));
} else if (tag[0] == '!') {
auto prefix_end = tag.begin() + 1;
while (prefix_end != tag.end() && *prefix_end != '!') {
++prefix_end;
}
if (prefix_end == tag.end()) {
m_emitter << LocalTag(std::string(tag.begin() + 1, tag.end()));
}
else {
m_emitter << LocalTag(std::string(tag.begin() + 1, prefix_end),
std::string(prefix_end + 1, tag.end()));
}
} else {
m_emitter << VerbatimTag(tag);
}
}
if (anchor)
m_emitter << Anchor(ToString(anchor));
Expand Down
24 changes: 23 additions & 1 deletion test/integration/load_node_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,17 @@ TEST(NodeTest, EmitEmptyNode) {
EXPECT_EQ("", std::string(emitter.c_str()));
}

TEST(NodeTest, SetVerbatimTag) {
Node node, root;
node = 42;
node.SetTag("hello");
root["num"] = node;

Emitter emitter;
emitter << root;
EXPECT_EQ("num: !<hello> 42", std::string(emitter.c_str()));
}

// Regression for #1373: emitting a node whose tag begins with "!!"
// (a YAML secondary tag handle, e.g. "!!str") used to bail out with
// INVALID_TAG and truncate the output after the first '!'.
Expand Down Expand Up @@ -258,6 +269,17 @@ TEST(NodeTest, EmitSetTagPrimaryHandle) {
EXPECT_EQ("v: !mytag hello", std::string(emitter.c_str()));
}

TEST(NodeTest, EmitSetLocalTagInNameHandle) {
Node node, root;
node = 42;
node.SetTag("!a!foo");
root["num"] = node;

Emitter emitter;
emitter << root;
EXPECT_EQ("num: !a!foo 42", std::string(emitter.c_str()));
}

TEST(NodeTest, ParseNodeStyle) {
EXPECT_EQ(EmitterStyle::Flow, Load("[1, 2, 3]").Style());
EXPECT_EQ(EmitterStyle::Flow, Load("{foo: bar}").Style());
Expand Down Expand Up @@ -497,4 +519,4 @@ TEST(LoadNodeTest, NonUniqueMapKey) {
}

} // namespace
} // namespace YAML
} // namespace YAML
Loading