mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2025-09-08 04:11:17 +00:00
- Reintegrated the other-tags branch into my staging branch. Local edits were required to integrate with the changes from the event-api branch.
This commit is contained in:
@@ -77,6 +77,8 @@ namespace YAML
|
||||
void EmitEndMap();
|
||||
void EmitKey();
|
||||
void EmitValue();
|
||||
void EmitKindTag();
|
||||
void EmitTag(bool verbatim, const _Tag& tag);
|
||||
|
||||
private:
|
||||
ostream m_stream;
|
||||
|
@@ -11,6 +11,7 @@ namespace YAML
|
||||
enum EMITTER_MANIP {
|
||||
// general manipulators
|
||||
Auto,
|
||||
TagByKind,
|
||||
|
||||
// output character set
|
||||
EmitNonAscii,
|
||||
@@ -82,14 +83,24 @@ namespace YAML
|
||||
}
|
||||
|
||||
struct _Tag {
|
||||
_Tag(const std::string& content_): content(content_), verbatim(true) {}
|
||||
explicit _Tag(const std::string& content_)
|
||||
: content(content_), verbatim(true)
|
||||
{
|
||||
}
|
||||
std::string content;
|
||||
bool verbatim;
|
||||
};
|
||||
|
||||
inline _Tag VerbatimTag(const std::string& content) {
|
||||
return _Tag(content);
|
||||
}
|
||||
typedef _Tag VerbatimTag;
|
||||
|
||||
struct LocalTag : public _Tag
|
||||
{
|
||||
explicit LocalTag(const std::string& content_)
|
||||
: _Tag(content_)
|
||||
{
|
||||
verbatim = false;
|
||||
}
|
||||
};
|
||||
|
||||
struct _Comment {
|
||||
_Comment(const std::string& content_): content(content_) {}
|
||||
|
@@ -120,6 +120,9 @@ namespace YAML
|
||||
case Value:
|
||||
EmitValue();
|
||||
break;
|
||||
case TagByKind:
|
||||
EmitKindTag();
|
||||
break;
|
||||
default:
|
||||
m_pState->SetLocalValue(value);
|
||||
break;
|
||||
@@ -651,15 +654,26 @@ namespace YAML
|
||||
if(!good())
|
||||
return *this;
|
||||
|
||||
EmitTag(tag.verbatim, tag);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Emitter::EmitTag(bool verbatim, const _Tag& tag)
|
||||
{
|
||||
PreAtomicWrite();
|
||||
EmitSeparationIfNecessary();
|
||||
if(!Utils::WriteTag(m_stream, tag.content)) {
|
||||
if(!Utils::WriteTag(m_stream, tag.content, verbatim)) {
|
||||
m_pState->SetError(ErrorMsg::INVALID_TAG);
|
||||
return *this;
|
||||
return;
|
||||
}
|
||||
m_pState->RequireSeparation();
|
||||
// Note: no PostAtomicWrite() because we need another value for this node
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Emitter::EmitKindTag()
|
||||
{
|
||||
_Tag tag("");
|
||||
EmitTag(false, tag);
|
||||
}
|
||||
|
||||
Emitter& Emitter::Write(const _Comment& comment)
|
||||
|
@@ -294,12 +294,13 @@ namespace YAML
|
||||
return WriteAliasName(out, str);
|
||||
}
|
||||
|
||||
bool WriteTag(ostream& out, const std::string& str)
|
||||
bool WriteTag(ostream& out, const std::string& str, bool verbatim)
|
||||
{
|
||||
out << "!<";
|
||||
out << (verbatim ? "!<" : "!");
|
||||
StringCharSource buffer(str.c_str(), str.size());
|
||||
const RegEx& reValid = verbatim ? Exp::URI() : Exp::Tag();
|
||||
while(buffer) {
|
||||
int n = Exp::URI().Match(buffer);
|
||||
int n = reValid.Match(buffer);
|
||||
if(n <= 0)
|
||||
return false;
|
||||
|
||||
@@ -308,7 +309,8 @@ namespace YAML
|
||||
++buffer;
|
||||
}
|
||||
}
|
||||
out << ">";
|
||||
if (verbatim)
|
||||
out << ">";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -18,7 +18,7 @@ namespace YAML
|
||||
bool WriteComment(ostream& out, const std::string& str, int postCommentIndent);
|
||||
bool WriteAlias(ostream& out, const std::string& str);
|
||||
bool WriteAnchor(ostream& out, const std::string& str);
|
||||
bool WriteTag(ostream& out, const std::string& str);
|
||||
bool WriteTag(ostream& out, const std::string& str, bool verbatim);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -276,7 +276,12 @@ namespace YAML
|
||||
} else {
|
||||
bool canBeHandle;
|
||||
token.value = ScanTagHandle(INPUT, canBeHandle);
|
||||
token.data = (token.value.empty() ? Tag::SECONDARY_HANDLE : Tag::PRIMARY_HANDLE);
|
||||
if(!canBeHandle && token.value.empty())
|
||||
token.data = Tag::NON_SPECIFIC;
|
||||
else if(token.value.empty())
|
||||
token.data = Tag::SECONDARY_HANDLE;
|
||||
else
|
||||
token.data = Tag::PRIMARY_HANDLE;
|
||||
|
||||
// is there a suffix?
|
||||
if(canBeHandle && INPUT.peek() == Keys::Tag) {
|
||||
@@ -323,6 +328,7 @@ namespace YAML
|
||||
|
||||
Token token(Token::SCALAR, mark);
|
||||
token.value = scalar;
|
||||
token.params.push_back(Token::PLAIN_SCALAR);
|
||||
m_tokens.push(token);
|
||||
}
|
||||
|
||||
|
@@ -8,6 +8,7 @@
|
||||
#include "token.h"
|
||||
#include <sstream>
|
||||
#include <cstdio>
|
||||
#include <algorithm>
|
||||
|
||||
namespace YAML
|
||||
{
|
||||
@@ -73,6 +74,17 @@ namespace YAML
|
||||
anchor_t anchor;
|
||||
ParseProperties(tag, anchor);
|
||||
|
||||
if (tag.empty()) {
|
||||
const Token& token = m_scanner.peek();
|
||||
const std::vector<std::string>& tparams = token.params;
|
||||
if (token.type != Token::SCALAR ||
|
||||
std::find(tparams.begin(), tparams.end(), Token::PLAIN_SCALAR) != tparams.end()) {
|
||||
tag = "?";
|
||||
} else {
|
||||
tag = "!";
|
||||
}
|
||||
}
|
||||
|
||||
// now split based on what kind of node we should be
|
||||
switch(m_scanner.peek().type) {
|
||||
case Token::SCALAR:
|
||||
|
6
src/token.cpp
Normal file
6
src/token.cpp
Normal file
@@ -0,0 +1,6 @@
|
||||
#include "token.h"
|
||||
|
||||
namespace YAML
|
||||
{
|
||||
const std::string Token::PLAIN_SCALAR("pln");
|
||||
}
|
@@ -59,6 +59,8 @@ namespace YAML
|
||||
TAG,
|
||||
SCALAR
|
||||
};
|
||||
|
||||
static const std::string PLAIN_SCALAR;
|
||||
|
||||
// data
|
||||
Token(TYPE type_, const Mark& mark_): status(VALID), type(type_), mark(mark_), data(0) {}
|
||||
|
@@ -373,6 +373,31 @@ namespace Test
|
||||
desiredOutput = "---\n- !<!foo>\n []\n- !<!bar>\n {}";
|
||||
}
|
||||
|
||||
void ByKindTagWithScalar(YAML::Emitter& out, std::string& desiredOutput)
|
||||
{
|
||||
out << YAML::BeginSeq;
|
||||
out << YAML::DoubleQuoted << "12";
|
||||
out << "12";
|
||||
out << YAML::TagByKind << "12";
|
||||
out << YAML::EndSeq;
|
||||
|
||||
desiredOutput = "---\n- \"12\"\n- 12\n- ! 12";
|
||||
}
|
||||
|
||||
void LocalTagWithScalar(YAML::Emitter& out, std::string& desiredOutput)
|
||||
{
|
||||
out << YAML::LocalTag("foo") << "bar";
|
||||
|
||||
desiredOutput = "--- !foo bar";
|
||||
}
|
||||
|
||||
void BadLocalTag(YAML::Emitter& out, std::string& desiredError)
|
||||
{
|
||||
out << YAML::LocalTag("e!far") << "bar";
|
||||
|
||||
desiredError = "invalid tag";
|
||||
}
|
||||
|
||||
void ComplexDoc(YAML::Emitter& out, std::string& desiredOutput)
|
||||
{
|
||||
out << YAML::BeginMap;
|
||||
@@ -789,6 +814,8 @@ namespace Test
|
||||
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::ByKindTagWithScalar, "by-kind tag with scalar", passed, total);
|
||||
RunEmitterTest(&Emitter::LocalTagWithScalar, "local tag with scalar", passed, total);
|
||||
RunEmitterTest(&Emitter::ComplexDoc, "complex doc", passed, total);
|
||||
RunEmitterTest(&Emitter::STLContainers, "STL containers", passed, total);
|
||||
RunEmitterTest(&Emitter::SimpleComment, "simple comment", passed, total);
|
||||
@@ -815,6 +842,7 @@ namespace Test
|
||||
RunEmitterErrorTest(&Emitter::MissingValue, "missing value", passed, total);
|
||||
RunEmitterErrorTest(&Emitter::UnexpectedKey, "unexpected key", passed, total);
|
||||
RunEmitterErrorTest(&Emitter::UnexpectedValue, "unexpected value", passed, total);
|
||||
RunEmitterErrorTest(&Emitter::BadLocalTag, "bad local tag", passed, total);
|
||||
|
||||
std::cout << "Emitter tests: " << passed << "/" << total << " passed\n";
|
||||
return passed == total;
|
||||
|
@@ -706,6 +706,106 @@ namespace Test
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PrepareNodeForTagExam(YAML::Node& doc, const std::string& input)
|
||||
{
|
||||
std::stringstream stream(input);
|
||||
YAML::Parser parser(stream);
|
||||
parser.GetNextDocument(doc);
|
||||
}
|
||||
|
||||
struct TagMismatch: public std::exception {
|
||||
TagMismatch(const std::string& actualTag, const std::string& expectedTag) {
|
||||
std::stringstream output;
|
||||
output << "Tag has value \"" << actualTag << "\" but \"" << expectedTag << "\" was expected";
|
||||
what_ = output.str();
|
||||
}
|
||||
virtual ~TagMismatch() throw() {}
|
||||
virtual const char *what() const throw() { return what_.c_str(); }
|
||||
|
||||
private:
|
||||
std::string what_;
|
||||
};
|
||||
|
||||
bool ExpectedTagValue(YAML::Node& node, const char* tag)
|
||||
{
|
||||
if(node.GetTag() == tag)
|
||||
return true;
|
||||
|
||||
throw TagMismatch(node.GetTag(), tag);
|
||||
}
|
||||
|
||||
bool DefaultPlainScalarTag()
|
||||
{
|
||||
YAML::Node node;
|
||||
PrepareNodeForTagExam(node, "--- 12");
|
||||
|
||||
return ExpectedTagValue(node, "?");
|
||||
}
|
||||
|
||||
bool DefaultSingleQuotedScalarTag()
|
||||
{
|
||||
YAML::Node node;
|
||||
PrepareNodeForTagExam(node, "--- '12'");
|
||||
|
||||
return ExpectedTagValue(node, "!");
|
||||
}
|
||||
|
||||
bool ExplicitNonSpecificPlainScalarTag()
|
||||
{
|
||||
YAML::Node node;
|
||||
PrepareNodeForTagExam(node, "--- ! 12");
|
||||
|
||||
return ExpectedTagValue(node, "!");
|
||||
}
|
||||
|
||||
bool BasicLocalTag()
|
||||
{
|
||||
YAML::Node node;
|
||||
PrepareNodeForTagExam(node, "--- !foo 12");
|
||||
|
||||
return ExpectedTagValue(node, "!foo");
|
||||
}
|
||||
|
||||
bool VerbatimLocalTag()
|
||||
{
|
||||
YAML::Node node;
|
||||
PrepareNodeForTagExam(node, "--- !<!foo> 12");
|
||||
|
||||
return ExpectedTagValue(node, "!foo");
|
||||
}
|
||||
|
||||
bool StandardShortcutTag()
|
||||
{
|
||||
YAML::Node node;
|
||||
PrepareNodeForTagExam(node, "--- !!int 12");
|
||||
|
||||
return ExpectedTagValue(node, "tag:yaml.org,2002:int");
|
||||
}
|
||||
|
||||
bool VerbatimURITag()
|
||||
{
|
||||
YAML::Node node;
|
||||
PrepareNodeForTagExam(node, "--- !<tag:yaml.org,2002:int> 12");
|
||||
|
||||
return ExpectedTagValue(node, "tag:yaml.org,2002:int");
|
||||
}
|
||||
|
||||
bool DefaultSequenceTag()
|
||||
{
|
||||
YAML::Node node;
|
||||
PrepareNodeForTagExam(node, "--- [12]");
|
||||
|
||||
return ExpectedTagValue(node, "?");
|
||||
}
|
||||
|
||||
bool ExplicitNonSpecificSequenceTag()
|
||||
{
|
||||
YAML::Node node;
|
||||
PrepareNodeForTagExam(node, "--- ! [12]");
|
||||
|
||||
return ExpectedTagValue(node, "!");
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
@@ -746,7 +846,10 @@ namespace Test
|
||||
ok = test();
|
||||
} catch(const YAML::Exception& e) {
|
||||
ok = false;
|
||||
error = e.msg;
|
||||
error = e.what();
|
||||
} catch(const Parser::TagMismatch& e) {
|
||||
ok = false;
|
||||
error = e.what();
|
||||
}
|
||||
if(ok) {
|
||||
passed++;
|
||||
@@ -969,6 +1072,16 @@ namespace Test
|
||||
RunParserTest(&Parser::Bases, "bases", passed, total);
|
||||
RunParserTest(&Parser::KeyNotFound, "key not found", passed, total);
|
||||
RunParserTest(&Parser::DuplicateKey, "duplicate key", passed, total);
|
||||
RunParserTest(&Parser::DefaultPlainScalarTag, "default plain scalar tag", passed, total);
|
||||
RunParserTest(&Parser::DefaultSingleQuotedScalarTag, "default single-quoted scalar tag", passed, total);
|
||||
RunParserTest(&Parser::ExplicitNonSpecificPlainScalarTag, "explicit, non-specific plain scalar tag", passed, total);
|
||||
RunParserTest(&Parser::BasicLocalTag, "basic local tag", passed, total);
|
||||
RunParserTest(&Parser::VerbatimLocalTag, "verbatim local tag", passed, total);
|
||||
RunParserTest(&Parser::StandardShortcutTag, "standard shortcut tag", passed, total);
|
||||
RunParserTest(&Parser::VerbatimURITag, "verbatim URI tag", passed, total);
|
||||
RunParserTest(&Parser::DefaultPlainScalarTag, "default plain scalar tag", passed, total);
|
||||
RunParserTest(&Parser::DefaultSequenceTag, "default sequence tag", passed, total);
|
||||
RunParserTest(&Parser::ExplicitNonSpecificSequenceTag, "explicit, non-specific sequence tag", passed, total);
|
||||
|
||||
RunEncodingTest(&EncodeToUtf8, false, "UTF-8, no BOM", passed, total);
|
||||
RunEncodingTest(&EncodeToUtf8, true, "UTF-8 with BOM", passed, total);
|
||||
|
Reference in New Issue
Block a user