- 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:
rtweeks21
2010-10-16 09:08:03 +00:00
parent 3126507ab9
commit 7d1508e090
11 changed files with 210 additions and 14 deletions

View File

@@ -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;

View File

@@ -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_) {}

View File

@@ -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)

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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
View File

@@ -0,0 +1,6 @@
#include "token.h"
namespace YAML
{
const std::string Token::PLAIN_SCALAR("pln");
}

View File

@@ -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) {}

View File

@@ -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;

View File

@@ -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);