mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2025-09-09 04:41:16 +00:00
Merged r295:305 from the tags branch to the trunk
This commit is contained in:
@@ -52,6 +52,7 @@ namespace YAML
|
||||
Emitter& Write(double d);
|
||||
Emitter& Write(const _Alias& alias);
|
||||
Emitter& Write(const _Anchor& anchor);
|
||||
Emitter& Write(const _Tag& tag);
|
||||
Emitter& Write(const _Comment& comment);
|
||||
Emitter& Write(const _Null& null);
|
||||
|
||||
|
@@ -80,6 +80,16 @@ namespace YAML
|
||||
inline _Anchor Anchor(const std::string content) {
|
||||
return _Anchor(content);
|
||||
}
|
||||
|
||||
struct _Tag {
|
||||
_Tag(const std::string& content_): content(content_), verbatim(true) {}
|
||||
std::string content;
|
||||
bool verbatim;
|
||||
};
|
||||
|
||||
inline _Tag VerbatimTag(const std::string& content) {
|
||||
return _Tag(content);
|
||||
}
|
||||
|
||||
struct _Comment {
|
||||
_Comment(const std::string& content_): content(content_) {}
|
||||
|
@@ -17,7 +17,12 @@ namespace YAML
|
||||
const std::string YAML_DIRECTIVE_ARGS = "YAML directives must have exactly one argument";
|
||||
const std::string YAML_VERSION = "bad YAML version: ";
|
||||
const std::string YAML_MAJOR_VERSION = "YAML major version too large";
|
||||
const std::string REPEATED_YAML_DIRECTIVE= "repeated YAML directive";
|
||||
const std::string TAG_DIRECTIVE_ARGS = "TAG directives must have exactly two arguments";
|
||||
const std::string REPEATED_TAG_DIRECTIVE = "repeated TAG directive";
|
||||
const std::string CHAR_IN_TAG_HANDLE = "illegal character found while scanning tag handle";
|
||||
const std::string TAG_WITH_NO_SUFFIX = "tag handle with no suffix";
|
||||
const std::string END_OF_VERBATIM_TAG = "end of verbatim tag not found";
|
||||
const std::string END_OF_MAP = "end of map not found";
|
||||
const std::string END_OF_MAP_FLOW = "end of map flow not found";
|
||||
const std::string END_OF_SEQ = "end of sequence not found";
|
||||
@@ -57,6 +62,7 @@ namespace YAML
|
||||
const std::string SINGLE_QUOTED_CHAR = "invalid character in single-quoted string";
|
||||
const std::string INVALID_ANCHOR = "invalid anchor";
|
||||
const std::string INVALID_ALIAS = "invalid alias";
|
||||
const std::string INVALID_TAG = "invalid tag";
|
||||
const std::string EXPECTED_KEY_TOKEN = "expected key token";
|
||||
const std::string EXPECTED_VALUE_TOKEN = "expected value token";
|
||||
const std::string UNEXPECTED_KEY_TOKEN = "unexpected key token";
|
||||
|
@@ -9,7 +9,6 @@
|
||||
#include "iterator.h"
|
||||
#include "mark.h"
|
||||
#include "noncopyable.h"
|
||||
#include "parserstate.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -21,6 +20,7 @@ namespace YAML
|
||||
class Content;
|
||||
class Scanner;
|
||||
class Emitter;
|
||||
class ParserState;
|
||||
|
||||
enum CONTENT_TYPE { CT_NONE, CT_SCALAR, CT_SEQUENCE, CT_MAP };
|
||||
|
||||
@@ -75,6 +75,9 @@ namespace YAML
|
||||
const Node *Identity() const { return m_pIdentity; }
|
||||
bool IsAlias() const { return m_alias; }
|
||||
bool IsReferenced() const { return m_referenced; }
|
||||
|
||||
// for tags
|
||||
const std::string GetTag() const { return m_tag; } // TODO: should an aliased node return its alias's tag?
|
||||
|
||||
// emitting
|
||||
friend Emitter& operator << (Emitter& out, const Node& node);
|
||||
|
@@ -5,7 +5,6 @@
|
||||
|
||||
|
||||
#include "node.h"
|
||||
#include "parserstate.h"
|
||||
#include "noncopyable.h"
|
||||
#include <ios>
|
||||
#include <string>
|
||||
@@ -16,6 +15,7 @@
|
||||
namespace YAML
|
||||
{
|
||||
class Scanner;
|
||||
class ParserState;
|
||||
struct Token;
|
||||
|
||||
class Parser: private noncopyable
|
||||
@@ -33,13 +33,13 @@ namespace YAML
|
||||
|
||||
private:
|
||||
void ParseDirectives();
|
||||
void HandleDirective(Token *pToken);
|
||||
void HandleYamlDirective(Token *pToken);
|
||||
void HandleTagDirective(Token *pToken);
|
||||
void HandleDirective(const Token& token);
|
||||
void HandleYamlDirective(const Token& token);
|
||||
void HandleTagDirective(const Token& token);
|
||||
|
||||
private:
|
||||
std::auto_ptr<Scanner> m_pScanner;
|
||||
ParserState m_state;
|
||||
std::auto_ptr<ParserState> m_pState;
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -146,6 +146,8 @@ namespace YAML
|
||||
switch(curState) {
|
||||
// document-level
|
||||
case ES_WAITING_FOR_DOC:
|
||||
m_stream << "---";
|
||||
m_pState->RequireSeparation();
|
||||
m_pState->SwitchState(ES_WRITING_DOC);
|
||||
return true;
|
||||
case ES_WRITING_DOC:
|
||||
@@ -323,7 +325,10 @@ namespace YAML
|
||||
EMITTER_STATE curState = m_pState->GetCurState();
|
||||
EMITTER_MANIP flowType = m_pState->GetFlowType(GT_SEQ);
|
||||
if(flowType == Block) {
|
||||
if(curState == ES_WRITING_BLOCK_SEQ_ENTRY || curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE) {
|
||||
if(curState == ES_WRITING_BLOCK_SEQ_ENTRY ||
|
||||
curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE ||
|
||||
curState == ES_WRITING_DOC
|
||||
) {
|
||||
m_stream << "\n";
|
||||
m_pState->UnsetSeparation();
|
||||
}
|
||||
@@ -354,8 +359,12 @@ namespace YAML
|
||||
// to a flow sequence if it is
|
||||
assert(curState == ES_DONE_WITH_BLOCK_SEQ_ENTRY || curState == ES_WAITING_FOR_BLOCK_SEQ_ENTRY);
|
||||
if(curState == ES_WAITING_FOR_BLOCK_SEQ_ENTRY) {
|
||||
// Note: only one of these will actually output anything for a given situation
|
||||
EmitSeparationIfNecessary();
|
||||
unsigned curIndent = m_pState->GetCurIndent();
|
||||
m_stream << IndentTo(curIndent) << "[]";
|
||||
m_stream << IndentTo(curIndent);
|
||||
|
||||
m_stream << "[]";
|
||||
}
|
||||
} else if(flowType == FT_FLOW) {
|
||||
// Note: flow sequences are allowed to be empty
|
||||
@@ -384,7 +393,10 @@ namespace YAML
|
||||
EMITTER_STATE curState = m_pState->GetCurState();
|
||||
EMITTER_MANIP flowType = m_pState->GetFlowType(GT_MAP);
|
||||
if(flowType == Block) {
|
||||
if(curState == ES_WRITING_BLOCK_SEQ_ENTRY || curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE) {
|
||||
if(curState == ES_WRITING_BLOCK_SEQ_ENTRY ||
|
||||
curState == ES_WRITING_BLOCK_MAP_KEY || curState == ES_WRITING_BLOCK_MAP_VALUE ||
|
||||
curState == ES_WRITING_DOC
|
||||
) {
|
||||
m_stream << "\n";
|
||||
m_pState->UnsetSeparation();
|
||||
}
|
||||
@@ -415,8 +427,11 @@ namespace YAML
|
||||
// to a flow sequence if it is
|
||||
assert(curState == ES_DONE_WITH_BLOCK_MAP_VALUE || curState == ES_WAITING_FOR_BLOCK_MAP_ENTRY);
|
||||
if(curState == ES_WAITING_FOR_BLOCK_MAP_ENTRY) {
|
||||
// Note: only one of these will actually output anything for a given situation
|
||||
EmitSeparationIfNecessary();
|
||||
unsigned curIndent = m_pState->GetCurIndent();
|
||||
m_stream << IndentTo(curIndent) << "{}";
|
||||
m_stream << IndentTo(curIndent);
|
||||
m_stream << "{}";
|
||||
}
|
||||
} else if(flowType == FT_FLOW) {
|
||||
// Note: flow maps are allowed to be empty
|
||||
@@ -675,6 +690,22 @@ namespace YAML
|
||||
return *this;
|
||||
}
|
||||
|
||||
Emitter& Emitter::Write(const _Tag& tag)
|
||||
{
|
||||
if(!good())
|
||||
return *this;
|
||||
|
||||
PreAtomicWrite();
|
||||
EmitSeparationIfNecessary();
|
||||
if(!Utils::WriteTag(m_stream, tag.content)) {
|
||||
m_pState->SetError(ErrorMsg::INVALID_TAG);
|
||||
return *this;
|
||||
}
|
||||
m_pState->RequireSeparation();
|
||||
// Note: no PostAtomicWrite() because we need another value for this node
|
||||
return *this;
|
||||
}
|
||||
|
||||
Emitter& Emitter::Write(const _Comment& comment)
|
||||
{
|
||||
if(!good())
|
||||
|
@@ -293,6 +293,24 @@ namespace YAML
|
||||
out << "&";
|
||||
return WriteAliasName(out, str);
|
||||
}
|
||||
|
||||
bool WriteTag(ostream& out, const std::string& str)
|
||||
{
|
||||
out << "!<";
|
||||
StringCharSource buffer(str.c_str(), str.size());
|
||||
while(buffer) {
|
||||
int n = Exp::URI.Match(buffer);
|
||||
if(n <= 0)
|
||||
return false;
|
||||
|
||||
while(--n >= 0) {
|
||||
out << buffer[0];
|
||||
++buffer;
|
||||
}
|
||||
}
|
||||
out << ">";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -18,6 +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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -25,6 +25,7 @@ namespace YAML
|
||||
const RegEx Digit = RegEx('0', '9');
|
||||
const RegEx Alpha = RegEx('a', 'z') || RegEx('A', 'Z');
|
||||
const RegEx AlphaNumeric = Alpha || Digit;
|
||||
const RegEx Word = AlphaNumeric || RegEx('-');
|
||||
const RegEx Hex = Digit || RegEx('A', 'F') || RegEx('a', 'f');
|
||||
// Valid Unicode code points that are not part of c-printable (YAML 1.2, sec. 5.1)
|
||||
const RegEx NotPrintable = RegEx(0) ||
|
||||
@@ -45,6 +46,8 @@ namespace YAML
|
||||
ValueInFlow = RegEx(':') + (BlankOrBreak || RegEx(",}", REGEX_OR));
|
||||
const RegEx Comment = RegEx('#');
|
||||
const RegEx AnchorEnd = RegEx("?:,]}%@`", REGEX_OR) || BlankOrBreak;
|
||||
const RegEx URI = Word || RegEx("#;/?:@&=+$,_.!~*'()[]", REGEX_OR) || (RegEx('%') + Hex + Hex);
|
||||
const RegEx Tag = Word || RegEx("#;/?:@&=+$_.~*'", REGEX_OR) || (RegEx('%') + Hex + Hex);
|
||||
|
||||
// Plain scalar rules:
|
||||
// . Cannot start with a blank.
|
||||
@@ -79,6 +82,8 @@ namespace YAML
|
||||
const char Tag = '!';
|
||||
const char LiteralScalar = '|';
|
||||
const char FoldedScalar = '>';
|
||||
const char VerbatimTagStart = '<';
|
||||
const char VerbatimTagEnd = '>';
|
||||
}
|
||||
}
|
||||
|
||||
|
15
src/node.cpp
15
src/node.cpp
@@ -9,6 +9,7 @@
|
||||
#include "aliascontent.h"
|
||||
#include "iterpriv.h"
|
||||
#include "emitter.h"
|
||||
#include "tag.h"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace YAML
|
||||
@@ -137,10 +138,8 @@ namespace YAML
|
||||
if(m_tag != "")
|
||||
throw ParserException(token.mark, ErrorMsg::MULTIPLE_TAGS);
|
||||
|
||||
m_tag = state.TranslateTag(token.value);
|
||||
|
||||
for(std::size_t i=0;i<token.params.size();i++)
|
||||
m_tag += token.params[i];
|
||||
Tag tag(token);
|
||||
m_tag = tag.Translate(state);
|
||||
pScanner->pop();
|
||||
}
|
||||
|
||||
@@ -241,7 +240,10 @@ namespace YAML
|
||||
bool Node::GetScalar(std::string& s) const
|
||||
{
|
||||
if(!m_pContent) {
|
||||
s = "~";
|
||||
if(m_tag.empty())
|
||||
s = "~";
|
||||
else
|
||||
s = "";
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -258,7 +260,8 @@ namespace YAML
|
||||
out << Anchor(node.m_anchor);
|
||||
}
|
||||
|
||||
// TODO: write tag
|
||||
if(node.m_tag != "")
|
||||
out << VerbatimTag(node.m_tag);
|
||||
|
||||
// write content
|
||||
if(node.m_pContent)
|
||||
|
@@ -2,6 +2,7 @@
|
||||
#include "scanner.h"
|
||||
#include "token.h"
|
||||
#include "exceptions.h"
|
||||
#include "parserstate.h"
|
||||
#include <sstream>
|
||||
#include <cstdio>
|
||||
|
||||
@@ -28,7 +29,7 @@ namespace YAML
|
||||
void Parser::Load(std::istream& in)
|
||||
{
|
||||
m_pScanner.reset(new Scanner(in));
|
||||
m_state.Reset();
|
||||
m_pState.reset(new ParserState);
|
||||
}
|
||||
|
||||
// GetNextDocument
|
||||
@@ -54,7 +55,7 @@ namespace YAML
|
||||
m_pScanner->pop();
|
||||
|
||||
// now parse our root node
|
||||
document.Parse(m_pScanner.get(), m_state);
|
||||
document.Parse(m_pScanner.get(), *m_pState);
|
||||
|
||||
// and finally eat any doc ends we see
|
||||
while(!m_pScanner->empty() && m_pScanner->peek().type == Token::DOC_END)
|
||||
@@ -83,51 +84,59 @@ namespace YAML
|
||||
// we keep the directives from the last document if none are specified;
|
||||
// but if any directives are specific, then we reset them
|
||||
if(!readDirective)
|
||||
m_state.Reset();
|
||||
m_pState.reset(new ParserState);
|
||||
|
||||
readDirective = true;
|
||||
HandleDirective(&token);
|
||||
HandleDirective(token);
|
||||
m_pScanner->pop();
|
||||
}
|
||||
}
|
||||
|
||||
void Parser::HandleDirective(Token *pToken)
|
||||
void Parser::HandleDirective(const Token& token)
|
||||
{
|
||||
if(pToken->value == "YAML")
|
||||
HandleYamlDirective(pToken);
|
||||
else if(pToken->value == "TAG")
|
||||
HandleTagDirective(pToken);
|
||||
if(token.value == "YAML")
|
||||
HandleYamlDirective(token);
|
||||
else if(token.value == "TAG")
|
||||
HandleTagDirective(token);
|
||||
}
|
||||
|
||||
// HandleYamlDirective
|
||||
// . Should be of the form 'major.minor' (like a version number)
|
||||
void Parser::HandleYamlDirective(Token *pToken)
|
||||
void Parser::HandleYamlDirective(const Token& token)
|
||||
{
|
||||
if(pToken->params.size() != 1)
|
||||
throw ParserException(pToken->mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
|
||||
if(token.params.size() != 1)
|
||||
throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
|
||||
|
||||
if(!m_pState->version.isDefault)
|
||||
throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE);
|
||||
|
||||
std::stringstream str(pToken->params[0]);
|
||||
str >> m_state.version.major;
|
||||
std::stringstream str(token.params[0]);
|
||||
str >> m_pState->version.major;
|
||||
str.get();
|
||||
str >> m_state.version.minor;
|
||||
str >> m_pState->version.minor;
|
||||
if(!str || str.peek() != EOF)
|
||||
throw ParserException(pToken->mark, ErrorMsg::YAML_VERSION + pToken->params[0]);
|
||||
throw ParserException(token.mark, ErrorMsg::YAML_VERSION + token.params[0]);
|
||||
|
||||
if(m_state.version.major > 1)
|
||||
throw ParserException(pToken->mark, ErrorMsg::YAML_MAJOR_VERSION);
|
||||
if(m_pState->version.major > 1)
|
||||
throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION);
|
||||
|
||||
m_pState->version.isDefault = false;
|
||||
// TODO: warning on major == 1, minor > 2?
|
||||
}
|
||||
|
||||
// HandleTagDirective
|
||||
// . Should be of the form 'handle prefix', where 'handle' is converted to 'prefix' in the file.
|
||||
void Parser::HandleTagDirective(Token *pToken)
|
||||
void Parser::HandleTagDirective(const Token& token)
|
||||
{
|
||||
if(pToken->params.size() != 2)
|
||||
throw ParserException(pToken->mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
|
||||
if(token.params.size() != 2)
|
||||
throw ParserException(token.mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
|
||||
|
||||
std::string handle = pToken->params[0], prefix = pToken->params[1];
|
||||
m_state.tags[handle] = prefix;
|
||||
const std::string& handle = token.params[0];
|
||||
const std::string& prefix = token.params[1];
|
||||
if(m_pState->tags.find(handle) != m_pState->tags.end())
|
||||
throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE);
|
||||
|
||||
m_pState->tags[handle] = prefix;
|
||||
}
|
||||
|
||||
void Parser::PrintTokens(std::ostream& out)
|
||||
|
@@ -2,23 +2,22 @@
|
||||
|
||||
namespace YAML
|
||||
{
|
||||
void ParserState::Reset()
|
||||
ParserState::ParserState()
|
||||
{
|
||||
// version
|
||||
version.isDefault = true;
|
||||
version.major = 1;
|
||||
version.minor = 2;
|
||||
|
||||
// and tags
|
||||
tags.clear();
|
||||
tags["!"] = "!";
|
||||
tags["!!"] = "tag:yaml.org,2002:";
|
||||
}
|
||||
|
||||
std::string ParserState::TranslateTag(const std::string& handle) const
|
||||
const std::string ParserState::TranslateTagHandle(const std::string& handle) const
|
||||
{
|
||||
std::map <std::string, std::string>::const_iterator it = tags.find(handle);
|
||||
if(it == tags.end())
|
||||
if(it == tags.end()) {
|
||||
if(handle == "!!")
|
||||
return "tag:yaml.org,2002:";
|
||||
return handle;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
@@ -10,16 +10,17 @@
|
||||
namespace YAML
|
||||
{
|
||||
struct Version {
|
||||
bool isDefault;
|
||||
int major, minor;
|
||||
};
|
||||
|
||||
|
||||
struct ParserState
|
||||
{
|
||||
ParserState();
|
||||
const std::string TranslateTagHandle(const std::string& handle) const;
|
||||
|
||||
Version version;
|
||||
std::map <std::string, std::string> tags;
|
||||
|
||||
void Reset();
|
||||
std::string TranslateTag(const std::string& handle) const;
|
||||
};
|
||||
}
|
||||
|
@@ -37,12 +37,12 @@ namespace YAML
|
||||
|
||||
int Match(const std::string& str) const;
|
||||
int Match(const Stream& in) const;
|
||||
template <typename Source> int Match(const Source& source) const;
|
||||
|
||||
private:
|
||||
RegEx(REGEX_OP op);
|
||||
|
||||
template <typename Source> bool IsValidSource(const Source& source) const;
|
||||
template <typename Source> int Match(const Source& source) const;
|
||||
template <typename Source> int MatchUnchecked(const Source& source) const;
|
||||
|
||||
template <typename Source> int MatchOpEmpty(const Source& source) const;
|
||||
|
@@ -3,6 +3,7 @@
|
||||
#include "exceptions.h"
|
||||
#include "exp.h"
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
|
||||
namespace YAML
|
||||
{
|
||||
@@ -13,6 +14,9 @@ namespace YAML
|
||||
|
||||
Scanner::~Scanner()
|
||||
{
|
||||
for(unsigned i=0;i<m_indentRefs.size();i++)
|
||||
delete m_indentRefs[i];
|
||||
m_indentRefs.clear();
|
||||
}
|
||||
|
||||
// empty
|
||||
@@ -228,7 +232,9 @@ namespace YAML
|
||||
{
|
||||
m_startedStream = true;
|
||||
m_simpleKeyAllowed = true;
|
||||
m_indents.push(IndentMarker(-1, IndentMarker::NONE));
|
||||
IndentMarker *pIndent = new IndentMarker(-1, IndentMarker::NONE);
|
||||
m_indentRefs.push_back(pIndent);
|
||||
m_indents.push(pIndent);
|
||||
m_anchors.clear();
|
||||
}
|
||||
|
||||
@@ -257,8 +263,9 @@ namespace YAML
|
||||
if(InFlowContext())
|
||||
return 0;
|
||||
|
||||
IndentMarker indent(column, type);
|
||||
const IndentMarker& lastIndent = m_indents.top();
|
||||
std::auto_ptr<IndentMarker> pIndent(new IndentMarker(column, type));
|
||||
IndentMarker& indent = *pIndent;
|
||||
const IndentMarker& lastIndent = *m_indents.top();
|
||||
|
||||
// is this actually an indentation?
|
||||
if(indent.column < lastIndent.column)
|
||||
@@ -276,13 +283,15 @@ namespace YAML
|
||||
indent.pStartToken = &m_tokens.back();
|
||||
|
||||
// and then the indent
|
||||
m_indents.push(indent);
|
||||
return &m_indents.top();
|
||||
m_indents.push(&indent);
|
||||
m_indentRefs.push_back(pIndent.release());
|
||||
return m_indentRefs.back();
|
||||
}
|
||||
|
||||
// PopIndentToHere
|
||||
// . Pops indentations off the stack until we reach the current indentation level,
|
||||
// and enqueues the proper token each time.
|
||||
// . Then pops all invalid indentations off.
|
||||
void Scanner::PopIndentToHere()
|
||||
{
|
||||
// are we in flow?
|
||||
@@ -291,7 +300,7 @@ namespace YAML
|
||||
|
||||
// now pop away
|
||||
while(!m_indents.empty()) {
|
||||
const IndentMarker& indent = m_indents.top();
|
||||
const IndentMarker& indent = *m_indents.top();
|
||||
if(indent.column < INPUT.column())
|
||||
break;
|
||||
if(indent.column == INPUT.column() && !(indent.type == IndentMarker::SEQ && !Exp::BlockEntry.Matches(INPUT)))
|
||||
@@ -299,6 +308,9 @@ namespace YAML
|
||||
|
||||
PopIndent();
|
||||
}
|
||||
|
||||
while(!m_indents.empty() && m_indents.top()->status == IndentMarker::INVALID)
|
||||
PopIndent();
|
||||
}
|
||||
|
||||
// PopAllIndents
|
||||
@@ -312,7 +324,7 @@ namespace YAML
|
||||
|
||||
// now pop away
|
||||
while(!m_indents.empty()) {
|
||||
const IndentMarker& indent = m_indents.top();
|
||||
const IndentMarker& indent = *m_indents.top();
|
||||
if(indent.type == IndentMarker::NONE)
|
||||
break;
|
||||
|
||||
@@ -324,17 +336,17 @@ namespace YAML
|
||||
// . Pops a single indent, pushing the proper token
|
||||
void Scanner::PopIndent()
|
||||
{
|
||||
IndentMarker indent = m_indents.top();
|
||||
IndentMarker::INDENT_TYPE type = indent.type;
|
||||
const IndentMarker& indent = *m_indents.top();
|
||||
m_indents.pop();
|
||||
if(!indent.isValid) {
|
||||
|
||||
if(indent.status != IndentMarker::VALID) {
|
||||
InvalidateSimpleKey();
|
||||
return;
|
||||
}
|
||||
|
||||
if(type == IndentMarker::SEQ)
|
||||
if(indent.type == IndentMarker::SEQ)
|
||||
m_tokens.push(Token(Token::BLOCK_SEQ_END, INPUT.mark()));
|
||||
else if(type == IndentMarker::MAP)
|
||||
else if(indent.type == IndentMarker::MAP)
|
||||
m_tokens.push(Token(Token::BLOCK_MAP_END, INPUT.mark()));
|
||||
}
|
||||
|
||||
@@ -343,7 +355,7 @@ namespace YAML
|
||||
{
|
||||
if(m_indents.empty())
|
||||
return 0;
|
||||
return m_indents.top().column;
|
||||
return m_indents.top()->column;
|
||||
}
|
||||
|
||||
// Save
|
||||
|
@@ -36,11 +36,12 @@ namespace YAML
|
||||
private:
|
||||
struct IndentMarker {
|
||||
enum INDENT_TYPE { MAP, SEQ, NONE };
|
||||
IndentMarker(int column_, INDENT_TYPE type_): column(column_), type(type_), isValid(true), pStartToken(0) {}
|
||||
enum STATUS { VALID, INVALID, UNKNOWN };
|
||||
IndentMarker(int column_, INDENT_TYPE type_): column(column_), type(type_), status(VALID), pStartToken(0) {}
|
||||
|
||||
int column;
|
||||
INDENT_TYPE type;
|
||||
bool isValid;
|
||||
STATUS status;
|
||||
Token *pStartToken;
|
||||
};
|
||||
|
||||
@@ -118,10 +119,12 @@ namespace YAML
|
||||
bool m_startedStream, m_endedStream;
|
||||
bool m_simpleKeyAllowed;
|
||||
std::stack <SimpleKey> m_simpleKeys;
|
||||
std::stack <IndentMarker> m_indents;
|
||||
std::stack <IndentMarker *> m_indents;
|
||||
std::vector <IndentMarker *> m_indentRefs; // for "garbage collection"
|
||||
std::stack <FLOW_MARKER> m_flows;
|
||||
std::map <std::string, const Node *> m_anchors;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
|
@@ -40,3 +40,4 @@ namespace YAML
|
||||
}
|
||||
|
||||
#endif // SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
|
84
src/scantag.cpp
Normal file
84
src/scantag.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
#include "scanner.h"
|
||||
#include "regex.h"
|
||||
#include "exp.h"
|
||||
#include "exceptions.h"
|
||||
|
||||
namespace YAML
|
||||
{
|
||||
const std::string ScanVerbatimTag(Stream& INPUT)
|
||||
{
|
||||
std::string tag;
|
||||
|
||||
// eat the start character
|
||||
INPUT.get();
|
||||
|
||||
while(INPUT) {
|
||||
if(INPUT.peek() == Keys::VerbatimTagEnd) {
|
||||
// eat the end character
|
||||
INPUT.get();
|
||||
return tag;
|
||||
}
|
||||
|
||||
int n = Exp::URI.Match(INPUT);
|
||||
if(n <= 0)
|
||||
break;
|
||||
|
||||
tag += INPUT.get(n);
|
||||
}
|
||||
|
||||
throw ParserException(INPUT.mark(), ErrorMsg::END_OF_VERBATIM_TAG);
|
||||
}
|
||||
|
||||
const std::string ScanTagHandle(Stream& INPUT, bool& canBeHandle)
|
||||
{
|
||||
std::string tag;
|
||||
canBeHandle = true;
|
||||
Mark firstNonWordChar;
|
||||
|
||||
while(INPUT) {
|
||||
if(INPUT.peek() == Keys::Tag) {
|
||||
if(!canBeHandle)
|
||||
throw ParserException(firstNonWordChar, ErrorMsg::CHAR_IN_TAG_HANDLE);
|
||||
break;
|
||||
}
|
||||
|
||||
int n = 0;
|
||||
if(canBeHandle) {
|
||||
n = Exp::Word.Match(INPUT);
|
||||
if(n <= 0) {
|
||||
canBeHandle = false;
|
||||
firstNonWordChar = INPUT.mark();
|
||||
}
|
||||
}
|
||||
|
||||
if(!canBeHandle)
|
||||
n = Exp::Tag.Match(INPUT);
|
||||
|
||||
if(n <= 0)
|
||||
break;
|
||||
|
||||
tag += INPUT.get(n);
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
const std::string ScanTagSuffix(Stream& INPUT)
|
||||
{
|
||||
std::string tag;
|
||||
|
||||
while(INPUT) {
|
||||
int n = Exp::Tag.Match(INPUT);
|
||||
if(n <= 0)
|
||||
break;
|
||||
|
||||
tag += INPUT.get(n);
|
||||
}
|
||||
|
||||
if(tag.empty())
|
||||
throw ParserException(INPUT.mark(), ErrorMsg::TAG_WITH_NO_SUFFIX);
|
||||
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
|
18
src/scantag.h
Normal file
18
src/scantag.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
|
||||
#include <string>
|
||||
#include "stream.h"
|
||||
|
||||
namespace YAML
|
||||
{
|
||||
const std::string ScanVerbatimTag(Stream& INPUT);
|
||||
const std::string ScanTagHandle(Stream& INPUT, bool& canBeHandle);
|
||||
const std::string ScanTagSuffix(Stream& INPUT);
|
||||
}
|
||||
|
||||
#endif // SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
@@ -3,6 +3,8 @@
|
||||
#include "exceptions.h"
|
||||
#include "exp.h"
|
||||
#include "scanscalar.h"
|
||||
#include "scantag.h"
|
||||
#include "tag.h"
|
||||
#include <sstream>
|
||||
|
||||
namespace YAML
|
||||
@@ -24,12 +26,12 @@ namespace YAML
|
||||
m_simpleKeyAllowed = false;
|
||||
|
||||
// store pos and eat indicator
|
||||
Mark mark = INPUT.mark();
|
||||
Token token(Token::DIRECTIVE, INPUT.mark());
|
||||
INPUT.eat(1);
|
||||
|
||||
// read name
|
||||
while(INPUT && !Exp::BlankOrBreak.Matches(INPUT))
|
||||
name += INPUT.get();
|
||||
token.value += INPUT.get();
|
||||
|
||||
// read parameters
|
||||
while(1) {
|
||||
@@ -46,12 +48,9 @@ namespace YAML
|
||||
while(INPUT && !Exp::BlankOrBreak.Matches(INPUT))
|
||||
param += INPUT.get();
|
||||
|
||||
params.push_back(param);
|
||||
token.params.push_back(param);
|
||||
}
|
||||
|
||||
Token token(Token::DIRECTIVE, mark);
|
||||
token.value = name;
|
||||
token.params = params;
|
||||
m_tokens.push(token);
|
||||
}
|
||||
|
||||
@@ -242,37 +241,34 @@ namespace YAML
|
||||
// Tag
|
||||
void Scanner::ScanTag()
|
||||
{
|
||||
std::string handle, suffix;
|
||||
|
||||
// insert a potential simple key
|
||||
InsertPotentialSimpleKey();
|
||||
m_simpleKeyAllowed = false;
|
||||
|
||||
Token token(Token::TAG, INPUT.mark());
|
||||
|
||||
// eat the indicator
|
||||
Mark mark = INPUT.mark();
|
||||
handle += INPUT.get();
|
||||
INPUT.get();
|
||||
|
||||
if(INPUT && INPUT.peek() == Keys::VerbatimTagStart){
|
||||
std::string tag = ScanVerbatimTag(INPUT);
|
||||
|
||||
// read the handle
|
||||
while(INPUT && INPUT.peek() != Keys::Tag && !Exp::BlankOrBreak.Matches(INPUT))
|
||||
handle += INPUT.get();
|
||||
|
||||
// is there a suffix?
|
||||
if(INPUT.peek() == Keys::Tag) {
|
||||
// eat the indicator
|
||||
handle += INPUT.get();
|
||||
|
||||
// then read it
|
||||
while(INPUT && !Exp::BlankOrBreak.Matches(INPUT))
|
||||
suffix += INPUT.get();
|
||||
token.value = tag;
|
||||
token.data = Tag::VERBATIM;
|
||||
} else {
|
||||
// this is a bit weird: we keep just the '!' as the handle and move the rest to the suffix
|
||||
suffix = handle.substr(1);
|
||||
handle = "!";
|
||||
bool canBeHandle;
|
||||
token.value = ScanTagHandle(INPUT, canBeHandle);
|
||||
token.data = (token.value.empty() ? Tag::SECONDARY_HANDLE : Tag::PRIMARY_HANDLE);
|
||||
|
||||
// is there a suffix?
|
||||
if(canBeHandle && INPUT.peek() == Keys::Tag) {
|
||||
// eat the indicator
|
||||
INPUT.get();
|
||||
token.params.push_back(ScanTagSuffix(INPUT));
|
||||
token.data = Tag::NAMED_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
Token token(Token::TAG, mark);
|
||||
token.value = handle;
|
||||
token.params.push_back(suffix);
|
||||
m_tokens.push(token);
|
||||
}
|
||||
|
||||
|
@@ -12,9 +12,11 @@ namespace YAML
|
||||
|
||||
void Scanner::SimpleKey::Validate()
|
||||
{
|
||||
// Note: pIndent will *not* be garbage here; see below
|
||||
// Note: pIndent will *not* be garbage here;
|
||||
// we "garbage collect" them so we can
|
||||
// always refer to them
|
||||
if(pIndent)
|
||||
pIndent->isValid = true;
|
||||
pIndent->status = IndentMarker::VALID;
|
||||
if(pMapStart)
|
||||
pMapStart->status = Token::VALID;
|
||||
if(pKey)
|
||||
@@ -23,8 +25,8 @@ namespace YAML
|
||||
|
||||
void Scanner::SimpleKey::Invalidate()
|
||||
{
|
||||
// Note: pIndent might be a garbage pointer here, but that's ok
|
||||
// An indent will only be popped if the simple key is invalid
|
||||
if(pIndent)
|
||||
pIndent->status = IndentMarker::INVALID;
|
||||
if(pMapStart)
|
||||
pMapStart->status = Token::INVALID;
|
||||
if(pKey)
|
||||
@@ -68,7 +70,7 @@ namespace YAML
|
||||
// first add a map start, if necessary
|
||||
key.pIndent = PushIndentTo(INPUT.column(), IndentMarker::MAP);
|
||||
if(key.pIndent) {
|
||||
key.pIndent->isValid = false;
|
||||
key.pIndent->status = IndentMarker::UNKNOWN;
|
||||
key.pMapStart = key.pIndent->pStartToken;
|
||||
key.pMapStart->status = Token::UNVERIFIED;
|
||||
}
|
||||
@@ -135,3 +137,4 @@ namespace YAML
|
||||
m_simpleKeys.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -30,6 +30,11 @@ namespace YAML
|
||||
++m_offset;
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringCharSource& operator += (std::size_t offset) {
|
||||
m_offset += offset;
|
||||
return *this;
|
||||
}
|
||||
private:
|
||||
const char *m_str;
|
||||
std::size_t m_size;
|
||||
|
50
src/tag.cpp
Normal file
50
src/tag.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "tag.h"
|
||||
#include "token.h"
|
||||
#include "parserstate.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace YAML
|
||||
{
|
||||
Tag::Tag(const Token& token): type(static_cast<TYPE>(token.data))
|
||||
{
|
||||
switch(type) {
|
||||
case VERBATIM:
|
||||
value = token.value;
|
||||
break;
|
||||
case PRIMARY_HANDLE:
|
||||
value = token.value;
|
||||
break;
|
||||
case SECONDARY_HANDLE:
|
||||
value = token.value;
|
||||
break;
|
||||
case NAMED_HANDLE:
|
||||
handle = token.value;
|
||||
value = token.params[0];
|
||||
break;
|
||||
case NON_SPECIFIC:
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
const std::string Tag::Translate(const ParserState& state)
|
||||
{
|
||||
switch(type) {
|
||||
case VERBATIM:
|
||||
return value;
|
||||
case PRIMARY_HANDLE:
|
||||
return state.TranslateTagHandle("!") + value;
|
||||
case SECONDARY_HANDLE:
|
||||
return state.TranslateTagHandle("!!") + value;
|
||||
case NAMED_HANDLE:
|
||||
return state.TranslateTagHandle("!" + handle + "!") + value;
|
||||
case NON_SPECIFIC:
|
||||
// TODO:
|
||||
return "!";
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
26
src/tag.h
Normal file
26
src/tag.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace YAML
|
||||
{
|
||||
struct Token;
|
||||
struct ParserState;
|
||||
|
||||
struct Tag {
|
||||
enum TYPE {
|
||||
VERBATIM, PRIMARY_HANDLE, SECONDARY_HANDLE, NAMED_HANDLE, NON_SPECIFIC
|
||||
};
|
||||
|
||||
Tag(const Token& token);
|
||||
const std::string Translate(const ParserState& state);
|
||||
|
||||
TYPE type;
|
||||
std::string handle, value;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
@@ -59,7 +59,7 @@ namespace YAML
|
||||
};
|
||||
|
||||
// data
|
||||
Token(TYPE type_, const Mark& mark_): status(VALID), type(type_), mark(mark_) {}
|
||||
Token(TYPE type_, const Mark& mark_): status(VALID), type(type_), mark(mark_), data(0) {}
|
||||
|
||||
friend std::ostream& operator << (std::ostream& out, const Token& token) {
|
||||
out << TokenNames[token.type] << std::string(": ") << token.value;
|
||||
@@ -73,6 +73,7 @@ namespace YAML
|
||||
Mark mark;
|
||||
std::string value;
|
||||
std::vector <std::string> params;
|
||||
int data;
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -9,7 +9,7 @@ namespace Test
|
||||
|
||||
void SimpleScalar(YAML::Emitter& out, std::string& desiredOutput) {
|
||||
out << "Hello, World!";
|
||||
desiredOutput = "Hello, World!";
|
||||
desiredOutput = "--- Hello, World!";
|
||||
}
|
||||
|
||||
void SimpleSeq(YAML::Emitter& out, std::string& desiredOutput) {
|
||||
@@ -19,7 +19,7 @@ namespace Test
|
||||
out << "milk";
|
||||
out << YAML::EndSeq;
|
||||
|
||||
desiredOutput = "- eggs\n- bread\n- milk";
|
||||
desiredOutput = "---\n- eggs\n- bread\n- milk";
|
||||
}
|
||||
|
||||
void SimpleFlowSeq(YAML::Emitter& out, std::string& desiredOutput) {
|
||||
@@ -30,7 +30,7 @@ namespace Test
|
||||
out << "Moe";
|
||||
out << YAML::EndSeq;
|
||||
|
||||
desiredOutput = "[Larry, Curly, Moe]";
|
||||
desiredOutput = "--- [Larry, Curly, Moe]";
|
||||
}
|
||||
|
||||
void EmptyFlowSeq(YAML::Emitter& out, std::string& desiredOutput) {
|
||||
@@ -38,7 +38,7 @@ namespace Test
|
||||
out << YAML::BeginSeq;
|
||||
out << YAML::EndSeq;
|
||||
|
||||
desiredOutput = "[]";
|
||||
desiredOutput = "--- []";
|
||||
}
|
||||
|
||||
void NestedBlockSeq(YAML::Emitter& out, std::string& desiredOutput) {
|
||||
@@ -47,7 +47,7 @@ namespace Test
|
||||
out << YAML::BeginSeq << "subitem 1" << "subitem 2" << YAML::EndSeq;
|
||||
out << YAML::EndSeq;
|
||||
|
||||
desiredOutput = "- item 1\n-\n - subitem 1\n - subitem 2";
|
||||
desiredOutput = "---\n- item 1\n-\n - subitem 1\n - subitem 2";
|
||||
}
|
||||
|
||||
void NestedFlowSeq(YAML::Emitter& out, std::string& desiredOutput) {
|
||||
@@ -56,7 +56,7 @@ namespace Test
|
||||
out << YAML::Flow << YAML::BeginSeq << "two" << "three" << YAML::EndSeq;
|
||||
out << YAML::EndSeq;
|
||||
|
||||
desiredOutput = "- one\n- [two, three]";
|
||||
desiredOutput = "---\n- one\n- [two, three]";
|
||||
}
|
||||
|
||||
void SimpleMap(YAML::Emitter& out, std::string& desiredOutput) {
|
||||
@@ -67,7 +67,7 @@ namespace Test
|
||||
out << YAML::Value << "3B";
|
||||
out << YAML::EndMap;
|
||||
|
||||
desiredOutput = "name: Ryan Braun\nposition: 3B";
|
||||
desiredOutput = "---\nname: Ryan Braun\nposition: 3B";
|
||||
}
|
||||
|
||||
void SimpleFlowMap(YAML::Emitter& out, std::string& desiredOutput) {
|
||||
@@ -79,7 +79,7 @@ namespace Test
|
||||
out << YAML::Value << "blue";
|
||||
out << YAML::EndMap;
|
||||
|
||||
desiredOutput = "{shape: square, color: blue}";
|
||||
desiredOutput = "--- {shape: square, color: blue}";
|
||||
}
|
||||
|
||||
void MapAndList(YAML::Emitter& out, std::string& desiredOutput) {
|
||||
@@ -90,7 +90,7 @@ namespace Test
|
||||
out << YAML::Value << YAML::BeginSeq << "Sasha" << "Malia" << YAML::EndSeq;
|
||||
out << YAML::EndMap;
|
||||
|
||||
desiredOutput = "name: Barack Obama\nchildren:\n - Sasha\n - Malia";
|
||||
desiredOutput = "---\nname: Barack Obama\nchildren:\n - Sasha\n - Malia";
|
||||
}
|
||||
|
||||
void ListAndMap(YAML::Emitter& out, std::string& desiredOutput) {
|
||||
@@ -103,7 +103,7 @@ namespace Test
|
||||
out << "item 2";
|
||||
out << YAML::EndSeq;
|
||||
|
||||
desiredOutput = "- item 1\n-\n pens: 8\n pencils: 14\n- item 2";
|
||||
desiredOutput = "---\n- item 1\n-\n pens: 8\n pencils: 14\n- item 2";
|
||||
}
|
||||
|
||||
void NestedBlockMap(YAML::Emitter& out, std::string& desiredOutput) {
|
||||
@@ -119,7 +119,7 @@ namespace Test
|
||||
out << YAML::EndMap;
|
||||
out << YAML::EndMap;
|
||||
|
||||
desiredOutput = "name: Fred\ngrades:\n algebra: A\n physics: C+\n literature: B";
|
||||
desiredOutput = "---\nname: Fred\ngrades:\n algebra: A\n physics: C+\n literature: B";
|
||||
}
|
||||
|
||||
void NestedFlowMap(YAML::Emitter& out, std::string& desiredOutput) {
|
||||
@@ -136,7 +136,7 @@ namespace Test
|
||||
out << YAML::EndMap;
|
||||
out << YAML::EndMap;
|
||||
|
||||
desiredOutput = "{name: Fred, grades: {algebra: A, physics: C+, literature: B}}";
|
||||
desiredOutput = "--- {name: Fred, grades: {algebra: A, physics: C+, literature: B}}";
|
||||
}
|
||||
|
||||
void MapListMix(YAML::Emitter& out, std::string& desiredOutput) {
|
||||
@@ -149,7 +149,7 @@ namespace Test
|
||||
out << YAML::Key << "invincible" << YAML::Value << YAML::OnOffBool << false;
|
||||
out << YAML::EndMap;
|
||||
|
||||
desiredOutput = "name: Bob\nposition: [2, 4]\ninvincible: off";
|
||||
desiredOutput = "---\nname: Bob\nposition: [2, 4]\ninvincible: off";
|
||||
}
|
||||
|
||||
void SimpleLongKey(YAML::Emitter& out, std::string& desiredOutput)
|
||||
@@ -162,7 +162,7 @@ namespace Test
|
||||
out << YAML::Value << 145;
|
||||
out << YAML::EndMap;
|
||||
|
||||
desiredOutput = "? height\n: 5'9\"\n? weight\n: 145";
|
||||
desiredOutput = "---\n? height\n: 5'9\"\n? weight\n: 145";
|
||||
}
|
||||
|
||||
void SingleLongKey(YAML::Emitter& out, std::string& desiredOutput)
|
||||
@@ -176,7 +176,7 @@ namespace Test
|
||||
out << YAML::Value << 145;
|
||||
out << YAML::EndMap;
|
||||
|
||||
desiredOutput = "age: 24\n? height\n: 5'9\"\nweight: 145";
|
||||
desiredOutput = "---\nage: 24\n? height\n: 5'9\"\nweight: 145";
|
||||
}
|
||||
|
||||
void ComplexLongKey(YAML::Emitter& out, std::string& desiredOutput)
|
||||
@@ -189,7 +189,7 @@ namespace Test
|
||||
out << YAML::Value << "demon";
|
||||
out << YAML::EndMap;
|
||||
|
||||
desiredOutput = "?\n - 1\n - 3\n: monster\n? [2, 0]\n: demon";
|
||||
desiredOutput = "---\n?\n - 1\n - 3\n: monster\n? [2, 0]\n: demon";
|
||||
}
|
||||
|
||||
void AutoLongKey(YAML::Emitter& out, std::string& desiredOutput)
|
||||
@@ -203,7 +203,7 @@ namespace Test
|
||||
out << YAML::Value << "angel";
|
||||
out << YAML::EndMap;
|
||||
|
||||
desiredOutput = "?\n - 1\n - 3\n: monster\n? [2, 0]\n: demon\nthe origin: angel";
|
||||
desiredOutput = "---\n?\n - 1\n - 3\n: monster\n? [2, 0]\n: demon\nthe origin: angel";
|
||||
}
|
||||
|
||||
void ScalarFormat(YAML::Emitter& out, std::string& desiredOutput)
|
||||
@@ -217,7 +217,7 @@ namespace Test
|
||||
out << YAML::Literal << "literal scalar\nthat may span\nmany, many\nlines and have \"whatever\" crazy\tsymbols that we like";
|
||||
out << YAML::EndSeq;
|
||||
|
||||
desiredOutput = "- simple scalar\n- 'explicit single-quoted scalar'\n- \"explicit double-quoted scalar\"\n- \"auto-detected\\x0adouble-quoted scalar\"\n- a non-\"auto-detected\" double-quoted scalar\n- |\n literal scalar\n that may span\n many, many\n lines and have \"whatever\" crazy\tsymbols that we like";
|
||||
desiredOutput = "---\n- simple scalar\n- 'explicit single-quoted scalar'\n- \"explicit double-quoted scalar\"\n- \"auto-detected\\x0adouble-quoted scalar\"\n- a non-\"auto-detected\" double-quoted scalar\n- |\n literal scalar\n that may span\n many, many\n lines and have \"whatever\" crazy\tsymbols that we like";
|
||||
}
|
||||
|
||||
void AutoLongKeyScalar(YAML::Emitter& out, std::string& desiredOutput)
|
||||
@@ -227,7 +227,7 @@ namespace Test
|
||||
out << YAML::Value << "and its value";
|
||||
out << YAML::EndMap;
|
||||
|
||||
desiredOutput = "? |\n multi-line\n scalar\n: and its value";
|
||||
desiredOutput = "---\n? |\n multi-line\n scalar\n: and its value";
|
||||
}
|
||||
|
||||
void LongKeyFlowMap(YAML::Emitter& out, std::string& desiredOutput)
|
||||
@@ -240,7 +240,7 @@ namespace Test
|
||||
out << YAML::Value << "and its value";
|
||||
out << YAML::EndMap;
|
||||
|
||||
desiredOutput = "{simple key: and value, ? long key: and its value}";
|
||||
desiredOutput = "--- {simple key: and value, ? long key: and its value}";
|
||||
}
|
||||
|
||||
void BlockMapAsKey(YAML::Emitter& out, std::string& desiredOutput)
|
||||
@@ -255,7 +255,7 @@ namespace Test
|
||||
out << "total value";
|
||||
out << YAML::EndMap;
|
||||
|
||||
desiredOutput = "?\n key: value\n next key: next value\n: total value";
|
||||
desiredOutput = "---\n?\n key: value\n next key: next value\n: total value";
|
||||
}
|
||||
|
||||
void AliasAndAnchor(YAML::Emitter& out, std::string& desiredOutput)
|
||||
@@ -269,7 +269,7 @@ namespace Test
|
||||
out << YAML::Alias("fred");
|
||||
out << YAML::EndSeq;
|
||||
|
||||
desiredOutput = "- &fred\n name: Fred\n age: 42\n- *fred";
|
||||
desiredOutput = "---\n- &fred\n name: Fred\n age: 42\n- *fred";
|
||||
}
|
||||
|
||||
void AliasAndAnchorWithNull(YAML::Emitter& out, std::string& desiredOutput)
|
||||
@@ -279,7 +279,98 @@ namespace Test
|
||||
out << YAML::Alias("fred");
|
||||
out << YAML::EndSeq;
|
||||
|
||||
desiredOutput = "- &fred ~\n- *fred";
|
||||
desiredOutput = "---\n- &fred ~\n- *fred";
|
||||
}
|
||||
|
||||
void SimpleVerbatimTag(YAML::Emitter& out, std::string& desiredOutput)
|
||||
{
|
||||
out << YAML::VerbatimTag("!foo") << "bar";
|
||||
|
||||
desiredOutput = "--- !<!foo> bar";
|
||||
}
|
||||
|
||||
void VerbatimTagInBlockSeq(YAML::Emitter& out, std::string& desiredOutput)
|
||||
{
|
||||
out << YAML::BeginSeq;
|
||||
out << YAML::VerbatimTag("!foo") << "bar";
|
||||
out << "baz";
|
||||
out << YAML::EndSeq;
|
||||
|
||||
desiredOutput = "---\n- !<!foo> bar\n- baz";
|
||||
}
|
||||
|
||||
void VerbatimTagInFlowSeq(YAML::Emitter& out, std::string& desiredOutput)
|
||||
{
|
||||
out << YAML::Flow << YAML::BeginSeq;
|
||||
out << YAML::VerbatimTag("!foo") << "bar";
|
||||
out << "baz";
|
||||
out << YAML::EndSeq;
|
||||
|
||||
desiredOutput = "--- [!<!foo> bar, baz]";
|
||||
}
|
||||
|
||||
void VerbatimTagInFlowSeqWithNull(YAML::Emitter& out, std::string& desiredOutput)
|
||||
{
|
||||
out << YAML::Flow << YAML::BeginSeq;
|
||||
out << YAML::VerbatimTag("!foo") << YAML::Null;
|
||||
out << "baz";
|
||||
out << YAML::EndSeq;
|
||||
|
||||
desiredOutput = "--- [!<!foo> ~, baz]";
|
||||
}
|
||||
|
||||
void VerbatimTagInBlockMap(YAML::Emitter& out, std::string& desiredOutput)
|
||||
{
|
||||
out << YAML::BeginMap;
|
||||
out << YAML::Key << YAML::VerbatimTag("!foo") << "bar";
|
||||
out << YAML::Value << YAML::VerbatimTag("!waz") << "baz";
|
||||
out << YAML::EndMap;
|
||||
|
||||
desiredOutput = "---\n!<!foo> bar: !<!waz> baz";
|
||||
}
|
||||
|
||||
void VerbatimTagInFlowMap(YAML::Emitter& out, std::string& desiredOutput)
|
||||
{
|
||||
out << YAML::Flow << YAML::BeginMap;
|
||||
out << YAML::Key << YAML::VerbatimTag("!foo") << "bar";
|
||||
out << YAML::Value << "baz";
|
||||
out << YAML::EndMap;
|
||||
|
||||
desiredOutput = "--- {!<!foo> bar: baz}";
|
||||
}
|
||||
|
||||
void VerbatimTagInFlowMapWithNull(YAML::Emitter& out, std::string& desiredOutput)
|
||||
{
|
||||
out << YAML::Flow << YAML::BeginMap;
|
||||
out << YAML::Key << YAML::VerbatimTag("!foo") << YAML::Null;
|
||||
out << YAML::Value << "baz";
|
||||
out << YAML::EndMap;
|
||||
|
||||
desiredOutput = "--- {!<!foo> ~: baz}";
|
||||
}
|
||||
|
||||
void VerbatimTagWithEmptySeq(YAML::Emitter& out, std::string& desiredOutput)
|
||||
{
|
||||
out << YAML::VerbatimTag("!foo") << YAML::BeginSeq << YAML::EndSeq;
|
||||
|
||||
desiredOutput = "--- !<!foo>\n[]";
|
||||
}
|
||||
|
||||
void VerbatimTagWithEmptyMap(YAML::Emitter& out, std::string& desiredOutput)
|
||||
{
|
||||
out << YAML::VerbatimTag("!bar") << YAML::BeginMap << YAML::EndMap;
|
||||
|
||||
desiredOutput = "--- !<!bar>\n{}";
|
||||
}
|
||||
|
||||
void VerbatimTagWithEmptySeqAndMap(YAML::Emitter& out, std::string& desiredOutput)
|
||||
{
|
||||
out << YAML::BeginSeq;
|
||||
out << YAML::VerbatimTag("!foo") << YAML::BeginSeq << YAML::EndSeq;
|
||||
out << YAML::VerbatimTag("!bar") << YAML::BeginMap << YAML::EndMap;
|
||||
out << YAML::EndSeq;
|
||||
|
||||
desiredOutput = "---\n- !<!foo>\n []\n- !<!bar>\n {}";
|
||||
}
|
||||
|
||||
void ComplexDoc(YAML::Emitter& out, std::string& desiredOutput)
|
||||
@@ -335,7 +426,7 @@ namespace Test
|
||||
out << YAML::Value << YAML::Alias("id001");
|
||||
out << YAML::EndMap;
|
||||
|
||||
desiredOutput = "receipt: Oz-Ware Purchase Invoice\ndate: 2007-08-06\ncustomer:\n given: Dorothy\n family: Gale\nitems:\n -\n part_no: A4786\n descrip: Water Bucket (Filled)\n price: 1.47\n quantity: 4\n -\n part_no: E1628\n descrip: High Heeled \"Ruby\" Slippers\n price: 100.27\n quantity: 1\nbill-to: &id001\n street: |\n 123 Tornado Alley\n Suite 16\n city: East Westville\n state: KS\nship-to: *id001";
|
||||
desiredOutput = "---\nreceipt: Oz-Ware Purchase Invoice\ndate: 2007-08-06\ncustomer:\n given: Dorothy\n family: Gale\nitems:\n -\n part_no: A4786\n descrip: Water Bucket (Filled)\n price: 1.47\n quantity: 4\n -\n part_no: E1628\n descrip: High Heeled \"Ruby\" Slippers\n price: 100.27\n quantity: 1\nbill-to: &id001\n street: |\n 123 Tornado Alley\n Suite 16\n city: East Westville\n state: KS\nship-to: *id001";
|
||||
}
|
||||
|
||||
void STLContainers(YAML::Emitter& out, std::string& desiredOutput)
|
||||
@@ -355,7 +446,7 @@ namespace Test
|
||||
out << ages;
|
||||
out << YAML::EndSeq;
|
||||
|
||||
desiredOutput = "- [2, 3, 5, 7, 11, 13]\n-\n Daniel: 26\n Jesse: 24";
|
||||
desiredOutput = "---\n- [2, 3, 5, 7, 11, 13]\n-\n Daniel: 26\n Jesse: 24";
|
||||
}
|
||||
|
||||
void SimpleComment(YAML::Emitter& out, std::string& desiredOutput)
|
||||
@@ -365,7 +456,7 @@ namespace Test
|
||||
out << YAML::Value << "least squares" << YAML::Comment("should we change this method?");
|
||||
out << YAML::EndMap;
|
||||
|
||||
desiredOutput = "method: least squares # should we change this method?";
|
||||
desiredOutput = "---\nmethod: least squares # should we change this method?";
|
||||
}
|
||||
|
||||
void MultiLineComment(YAML::Emitter& out, std::string& desiredOutput)
|
||||
@@ -375,7 +466,7 @@ namespace Test
|
||||
out << "item 2";
|
||||
out << YAML::EndSeq;
|
||||
|
||||
desiredOutput = "- item 1 # really really long\n # comment that couldn't possibly\n # fit on one line\n- item 2";
|
||||
desiredOutput = "---\n- item 1 # really really long\n # comment that couldn't possibly\n # fit on one line\n- item 2";
|
||||
}
|
||||
|
||||
void ComplexComments(YAML::Emitter& out, std::string& desiredOutput)
|
||||
@@ -385,7 +476,7 @@ namespace Test
|
||||
out << YAML::Value << "value";
|
||||
out << YAML::EndMap;
|
||||
|
||||
desiredOutput = "? long key # long key\n: value";
|
||||
desiredOutput = "---\n? long key # long key\n: value";
|
||||
}
|
||||
|
||||
void Indentation(YAML::Emitter& out, std::string& desiredOutput)
|
||||
@@ -398,7 +489,7 @@ namespace Test
|
||||
out << YAML::EndMap;
|
||||
out << YAML::EndSeq;
|
||||
|
||||
desiredOutput = "-\n key 1: value 1\n key 2:\n - a\n - b\n - c";
|
||||
desiredOutput = "---\n-\n key 1: value 1\n key 2:\n - a\n - b\n - c";
|
||||
}
|
||||
|
||||
void SimpleGlobalSettings(YAML::Emitter& out, std::string& desiredOutput)
|
||||
@@ -413,7 +504,7 @@ namespace Test
|
||||
out << YAML::EndMap;
|
||||
out << YAML::EndSeq;
|
||||
|
||||
desiredOutput = "-\n ? key 1\n : value 1\n ? key 2\n : [a, b, c]";
|
||||
desiredOutput = "---\n-\n ? key 1\n : value 1\n ? key 2\n : [a, b, c]";
|
||||
}
|
||||
|
||||
void ComplexGlobalSettings(YAML::Emitter& out, std::string& desiredOutput)
|
||||
@@ -432,7 +523,7 @@ namespace Test
|
||||
out << YAML::EndMap;
|
||||
out << YAML::EndSeq;
|
||||
|
||||
desiredOutput = "-\n key 1: value 1\n key 2: [a, b, c]\n-\n ? [1, 2]\n :\n a: b";
|
||||
desiredOutput = "---\n-\n key 1: value 1\n key 2: [a, b, c]\n-\n ? [1, 2]\n :\n a: b";
|
||||
}
|
||||
|
||||
void Null(YAML::Emitter& out, std::string& desiredOutput)
|
||||
@@ -445,26 +536,26 @@ namespace Test
|
||||
out << YAML::EndMap;
|
||||
out << YAML::EndSeq;
|
||||
|
||||
desiredOutput = "- ~\n-\n null value: ~\n ~: null key";
|
||||
desiredOutput = "---\n- ~\n-\n null value: ~\n ~: null key";
|
||||
}
|
||||
|
||||
void EscapedUnicode(YAML::Emitter& out, std::string& desiredOutput)
|
||||
{
|
||||
out << YAML::EscapeNonAscii << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2";
|
||||
|
||||
desiredOutput = "\"$ \\xa2 \\u20ac \\U00024b62\"";
|
||||
desiredOutput = "--- \"$ \\xa2 \\u20ac \\U00024b62\"";
|
||||
}
|
||||
|
||||
void Unicode(YAML::Emitter& out, std::string& desiredOutput)
|
||||
{
|
||||
out << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2";
|
||||
desiredOutput = "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2";
|
||||
desiredOutput = "--- \x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2";
|
||||
}
|
||||
|
||||
void DoubleQuotedUnicode(YAML::Emitter& out, std::string& desiredOutput)
|
||||
{
|
||||
out << YAML::DoubleQuoted << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2";
|
||||
desiredOutput = "\"\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2\"";
|
||||
desiredOutput = "--- \"\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2\"";
|
||||
}
|
||||
|
||||
|
||||
@@ -620,6 +711,16 @@ namespace Test
|
||||
RunEmitterTest(&Emitter::BlockMapAsKey, "block map as key", passed, total);
|
||||
RunEmitterTest(&Emitter::AliasAndAnchor, "alias and anchor", passed, total);
|
||||
RunEmitterTest(&Emitter::AliasAndAnchorWithNull, "alias and anchor with null", passed, total);
|
||||
RunEmitterTest(&Emitter::SimpleVerbatimTag, "simple verbatim tag", passed, total);
|
||||
RunEmitterTest(&Emitter::VerbatimTagInBlockSeq, "verbatim tag in block seq", passed, total);
|
||||
RunEmitterTest(&Emitter::VerbatimTagInFlowSeq, "verbatim tag in flow seq", passed, total);
|
||||
RunEmitterTest(&Emitter::VerbatimTagInFlowSeqWithNull, "verbatim tag in flow seq with null", passed, total);
|
||||
RunEmitterTest(&Emitter::VerbatimTagInBlockMap, "verbatim tag in block map", passed, total);
|
||||
RunEmitterTest(&Emitter::VerbatimTagInFlowMap, "verbatim tag in flow map", passed, total);
|
||||
RunEmitterTest(&Emitter::VerbatimTagInFlowMapWithNull, "verbatim tag in flow map with null", passed, total);
|
||||
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::ComplexDoc, "complex doc", passed, total);
|
||||
RunEmitterTest(&Emitter::STLContainers, "STL containers", passed, total);
|
||||
RunEmitterTest(&Emitter::SimpleComment, "simple comment", passed, total);
|
||||
|
@@ -32,7 +32,7 @@ namespace Test {
|
||||
ret = test();
|
||||
} catch(const YAML::Exception& e) {
|
||||
ret.ok = false;
|
||||
ret.error = " Exception caught: " + e.msg;
|
||||
ret.error = std::string(" Exception caught: ") + e.what();
|
||||
}
|
||||
|
||||
if(!ret.ok) {
|
||||
@@ -459,7 +459,136 @@ namespace Test {
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: 2.19 - 2.26 tags
|
||||
// TODO: 2.19 - 2.22 tags
|
||||
|
||||
// 2.23
|
||||
TEST VariousExplicitTags()
|
||||
{
|
||||
std::string input =
|
||||
"---\n"
|
||||
"not-date: !!str 2002-04-28\n"
|
||||
"\n"
|
||||
"picture: !!binary |\n"
|
||||
" R0lGODlhDAAMAIQAAP//9/X\n"
|
||||
" 17unp5WZmZgAAAOfn515eXv\n"
|
||||
" Pz7Y6OjuDg4J+fn5OTk6enp\n"
|
||||
" 56enmleECcgggoBADs=\n"
|
||||
"\n"
|
||||
"application specific tag: !something |\n"
|
||||
" The semantics of the tag\n"
|
||||
" above may be different for\n"
|
||||
" different documents.";
|
||||
|
||||
PARSE(doc, input);
|
||||
YAML_ASSERT(doc.size() == 3);
|
||||
YAML_ASSERT(doc["not-date"].GetTag() == "tag:yaml.org,2002:str");
|
||||
YAML_ASSERT(doc["not-date"] == "2002-04-28");
|
||||
YAML_ASSERT(doc["picture"].GetTag() == "tag:yaml.org,2002:binary");
|
||||
YAML_ASSERT(doc["picture"] ==
|
||||
"R0lGODlhDAAMAIQAAP//9/X\n"
|
||||
"17unp5WZmZgAAAOfn515eXv\n"
|
||||
"Pz7Y6OjuDg4J+fn5OTk6enp\n"
|
||||
"56enmleECcgggoBADs=\n"
|
||||
);
|
||||
YAML_ASSERT(doc["application specific tag"].GetTag() == "!something");
|
||||
YAML_ASSERT(doc["application specific tag"] ==
|
||||
"The semantics of the tag\n"
|
||||
"above may be different for\n"
|
||||
"different documents."
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2.24
|
||||
TEST GlobalTags()
|
||||
{
|
||||
std::string input =
|
||||
"%TAG ! tag:clarkevans.com,2002:\n"
|
||||
"--- !shape\n"
|
||||
" # Use the ! handle for presenting\n"
|
||||
" # tag:clarkevans.com,2002:circle\n"
|
||||
"- !circle\n"
|
||||
" center: &ORIGIN {x: 73, y: 129}\n"
|
||||
" radius: 7\n"
|
||||
"- !line\n"
|
||||
" start: *ORIGIN\n"
|
||||
" finish: { x: 89, y: 102 }\n"
|
||||
"- !label\n"
|
||||
" start: *ORIGIN\n"
|
||||
" color: 0xFFEEBB\n"
|
||||
" text: Pretty vector drawing.";
|
||||
|
||||
PARSE(doc, input);
|
||||
YAML_ASSERT(doc.GetTag() == "tag:clarkevans.com,2002:shape");
|
||||
YAML_ASSERT(doc.size() == 3);
|
||||
YAML_ASSERT(doc[0].GetTag() == "tag:clarkevans.com,2002:circle");
|
||||
YAML_ASSERT(doc[0].size() == 2);
|
||||
YAML_ASSERT(doc[0]["center"].size() == 2);
|
||||
YAML_ASSERT(doc[0]["center"]["x"] == 73);
|
||||
YAML_ASSERT(doc[0]["center"]["y"] == 129);
|
||||
YAML_ASSERT(doc[0]["radius"] == 7);
|
||||
YAML_ASSERT(doc[1].GetTag() == "tag:clarkevans.com,2002:line");
|
||||
YAML_ASSERT(doc[1].size() == 2);
|
||||
YAML_ASSERT(doc[1]["start"].size() == 2);
|
||||
YAML_ASSERT(doc[1]["start"]["x"] == 73);
|
||||
YAML_ASSERT(doc[1]["start"]["y"] == 129);
|
||||
YAML_ASSERT(doc[1]["finish"].size() == 2);
|
||||
YAML_ASSERT(doc[1]["finish"]["x"] == 89);
|
||||
YAML_ASSERT(doc[1]["finish"]["y"] == 102);
|
||||
YAML_ASSERT(doc[2].GetTag() == "tag:clarkevans.com,2002:label");
|
||||
YAML_ASSERT(doc[2].size() == 3);
|
||||
YAML_ASSERT(doc[2]["start"].size() == 2);
|
||||
YAML_ASSERT(doc[2]["start"]["x"] == 73);
|
||||
YAML_ASSERT(doc[2]["start"]["y"] == 129);
|
||||
YAML_ASSERT(doc[2]["color"] == "0xFFEEBB");
|
||||
YAML_ASSERT(doc[2]["text"] == "Pretty vector drawing.");
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2.25
|
||||
TEST UnorderedSets()
|
||||
{
|
||||
std::string input =
|
||||
"# Sets are represented as a\n"
|
||||
"# Mapping where each key is\n"
|
||||
"# associated with a null value\n"
|
||||
"--- !!set\n"
|
||||
"? Mark McGwire\n"
|
||||
"? Sammy Sosa\n"
|
||||
"? Ken Griffey";
|
||||
|
||||
PARSE(doc, input);
|
||||
YAML_ASSERT(doc.GetTag() == "tag:yaml.org,2002:set");
|
||||
YAML_ASSERT(doc.size() == 3);
|
||||
YAML_ASSERT(IsNull(doc["Mark McGwire"]));
|
||||
YAML_ASSERT(IsNull(doc["Sammy Sosa"]));
|
||||
YAML_ASSERT(IsNull(doc["Ken Griffey"]));
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2.26
|
||||
TEST OrderedMappings()
|
||||
{
|
||||
std::string input =
|
||||
"# Ordered maps are represented as\n"
|
||||
"# A sequence of mappings, with\n"
|
||||
"# each mapping having one key\n"
|
||||
"--- !!omap\n"
|
||||
"- Mark McGwire: 65\n"
|
||||
"- Sammy Sosa: 63\n"
|
||||
"- Ken Griffey: 58";
|
||||
|
||||
PARSE(doc, input);
|
||||
YAML_ASSERT(doc.GetTag() == "tag:yaml.org,2002:omap");
|
||||
YAML_ASSERT(doc.size() == 3);
|
||||
YAML_ASSERT(doc[0].size() == 1);
|
||||
YAML_ASSERT(doc[0]["Mark McGwire"] == 65);
|
||||
YAML_ASSERT(doc[1].size() == 1);
|
||||
YAML_ASSERT(doc[1]["Sammy Sosa"] == 63);
|
||||
YAML_ASSERT(doc[2].size() == 1);
|
||||
YAML_ASSERT(doc[2]["Ken Griffey"] == 58);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2.27
|
||||
TEST Invoice()
|
||||
@@ -496,6 +625,7 @@ namespace Test {
|
||||
" Billsmer @ 338-4338.";
|
||||
|
||||
PARSE(doc, input);
|
||||
YAML_ASSERT(doc.GetTag() == "tag:clarkevans.com,2002:invoice");
|
||||
YAML_ASSERT(doc.size() == 8);
|
||||
YAML_ASSERT(doc["invoice"] == 34843);
|
||||
YAML_ASSERT(doc["date"] == "2001-01-23");
|
||||
@@ -993,8 +1123,291 @@ namespace Test {
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: 6.13 - 6.17 directives
|
||||
// TODO: 6.18 - 6.28 tags
|
||||
// 6.13
|
||||
TEST ReservedDirectives()
|
||||
{
|
||||
std::string input =
|
||||
"%FOO bar baz # Should be ignored\n"
|
||||
" # with a warning.\n"
|
||||
"--- \"foo\"";
|
||||
|
||||
PARSE(doc, input);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 6.14
|
||||
TEST YAMLDirective()
|
||||
{
|
||||
std::string input =
|
||||
"%YAML 1.3 # Attempt parsing\n"
|
||||
" # with a warning\n"
|
||||
"---\n"
|
||||
"\"foo\"";
|
||||
|
||||
PARSE(doc, input);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 6.15
|
||||
TEST InvalidRepeatedYAMLDirective()
|
||||
{
|
||||
std::string input =
|
||||
"%YAML 1.2\n"
|
||||
"%YAML 1.1\n"
|
||||
"foo";
|
||||
|
||||
try {
|
||||
PARSE(doc, input);
|
||||
} catch(const YAML::ParserException& e) {
|
||||
if(e.msg == YAML::ErrorMsg::REPEATED_YAML_DIRECTIVE)
|
||||
return true;
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
return " No exception was thrown";
|
||||
}
|
||||
|
||||
// 6.16
|
||||
TEST TagDirective()
|
||||
{
|
||||
std::string input =
|
||||
"%TAG !yaml! tag:yaml.org,2002:\n"
|
||||
"---\n"
|
||||
"!yaml!str \"foo\"";
|
||||
|
||||
PARSE(doc, input);
|
||||
YAML_ASSERT(doc.GetTag() == "tag:yaml.org,2002:str");
|
||||
YAML_ASSERT(doc == "foo");
|
||||
return true;
|
||||
}
|
||||
|
||||
// 6.17
|
||||
TEST InvalidRepeatedTagDirective()
|
||||
{
|
||||
std::string input =
|
||||
"%TAG ! !foo\n"
|
||||
"%TAG ! !foo\n"
|
||||
"bar";
|
||||
|
||||
try {
|
||||
PARSE(doc, input);
|
||||
} catch(const YAML::ParserException& e) {
|
||||
if(e.msg == YAML::ErrorMsg::REPEATED_TAG_DIRECTIVE)
|
||||
return true;
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
return " No exception was thrown";
|
||||
}
|
||||
|
||||
// 6.18
|
||||
TEST PrimaryTagHandle()
|
||||
{
|
||||
std::string input =
|
||||
"# Private\n"
|
||||
"!foo \"bar\"\n"
|
||||
"...\n"
|
||||
"# Global\n"
|
||||
"%TAG ! tag:example.com,2000:app/\n"
|
||||
"---\n"
|
||||
"!foo \"bar\"";
|
||||
|
||||
PARSE(doc, input);
|
||||
YAML_ASSERT(doc.GetTag() == "!foo");
|
||||
YAML_ASSERT(doc == "bar");
|
||||
|
||||
PARSE_NEXT(doc);
|
||||
YAML_ASSERT(doc.GetTag() == "tag:example.com,2000:app/foo");
|
||||
YAML_ASSERT(doc == "bar");
|
||||
return true;
|
||||
}
|
||||
|
||||
// 6.19
|
||||
TEST SecondaryTagHandle()
|
||||
{
|
||||
std::string input =
|
||||
"%TAG !! tag:example.com,2000:app/\n"
|
||||
"---\n"
|
||||
"!!int 1 - 3 # Interval, not integer";
|
||||
|
||||
PARSE(doc, input);
|
||||
YAML_ASSERT(doc.GetTag() == "tag:example.com,2000:app/int");
|
||||
YAML_ASSERT(doc == "1 - 3");
|
||||
return true;
|
||||
}
|
||||
|
||||
// 6.20
|
||||
TEST TagHandles()
|
||||
{
|
||||
std::string input =
|
||||
"%TAG !e! tag:example.com,2000:app/\n"
|
||||
"---\n"
|
||||
"!e!foo \"bar\"";
|
||||
|
||||
PARSE(doc, input);
|
||||
YAML_ASSERT(doc.GetTag() == "tag:example.com,2000:app/foo");
|
||||
YAML_ASSERT(doc == "bar");
|
||||
return true;
|
||||
}
|
||||
|
||||
// 6.21
|
||||
TEST LocalTagPrefix()
|
||||
{
|
||||
std::string input =
|
||||
"%TAG !m! !my-\n"
|
||||
"--- # Bulb here\n"
|
||||
"!m!light fluorescent\n"
|
||||
"...\n"
|
||||
"%TAG !m! !my-\n"
|
||||
"--- # Color here\n"
|
||||
"!m!light green";
|
||||
|
||||
PARSE(doc, input);
|
||||
YAML_ASSERT(doc.GetTag() == "!my-light");
|
||||
YAML_ASSERT(doc == "fluorescent");
|
||||
|
||||
PARSE_NEXT(doc);
|
||||
YAML_ASSERT(doc.GetTag() == "!my-light");
|
||||
YAML_ASSERT(doc == "green");
|
||||
return true;
|
||||
}
|
||||
|
||||
// 6.22
|
||||
TEST GlobalTagPrefix()
|
||||
{
|
||||
std::string input =
|
||||
"%TAG !e! tag:example.com,2000:app/\n"
|
||||
"---\n"
|
||||
"- !e!foo \"bar\"";
|
||||
|
||||
PARSE(doc, input);
|
||||
YAML_ASSERT(doc.size() == 1);
|
||||
YAML_ASSERT(doc[0].GetTag() == "tag:example.com,2000:app/foo");
|
||||
YAML_ASSERT(doc[0] == "bar");
|
||||
return true;
|
||||
}
|
||||
|
||||
// 6.23
|
||||
TEST NodeProperties()
|
||||
{
|
||||
std::string input =
|
||||
"!!str &a1 \"foo\":\n"
|
||||
" !!str bar\n"
|
||||
"&a2 baz : *a1";
|
||||
|
||||
PARSE(doc, input);
|
||||
YAML_ASSERT(doc.size() == 2);
|
||||
for(YAML::Iterator it=doc.begin();it!=doc.end();++it) {
|
||||
if(it.first() == "foo") {
|
||||
YAML_ASSERT(it.first().GetTag() == "tag:yaml.org,2002:str");
|
||||
YAML_ASSERT(it.second().GetTag() == "tag:yaml.org,2002:str");
|
||||
YAML_ASSERT(it.second() == "bar");
|
||||
} else if(it.first() == "baz") {
|
||||
YAML_ASSERT(it.second() == "foo");
|
||||
} else
|
||||
return " unknown key";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 6.24
|
||||
TEST VerbatimTags()
|
||||
{
|
||||
std::string input =
|
||||
"!<tag:yaml.org,2002:str> foo :\n"
|
||||
" !<!bar> baz";
|
||||
|
||||
PARSE(doc, input);
|
||||
YAML_ASSERT(doc.size() == 1);
|
||||
for(YAML::Iterator it=doc.begin();it!=doc.end();++it) {
|
||||
YAML_ASSERT(it.first().GetTag() == "tag:yaml.org,2002:str");
|
||||
YAML_ASSERT(it.first() == "foo");
|
||||
YAML_ASSERT(it.second().GetTag() == "!bar");
|
||||
YAML_ASSERT(it.second() == "baz");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 6.25
|
||||
TEST InvalidVerbatimTags()
|
||||
{
|
||||
std::string input =
|
||||
"- !<!> foo\n"
|
||||
"- !<$:?> bar\n";
|
||||
|
||||
PARSE(doc, input);
|
||||
return " not implemented yet"; // TODO: check tags (but we probably will say these are valid, I think)
|
||||
}
|
||||
|
||||
// 6.26
|
||||
TEST TagShorthands()
|
||||
{
|
||||
std::string input =
|
||||
"%TAG !e! tag:example.com,2000:app/\n"
|
||||
"---\n"
|
||||
"- !local foo\n"
|
||||
"- !!str bar\n"
|
||||
"- !e!tag%21 baz\n";
|
||||
|
||||
PARSE(doc, input);
|
||||
YAML_ASSERT(doc.size() == 3);
|
||||
YAML_ASSERT(doc[0].GetTag() == "!local");
|
||||
YAML_ASSERT(doc[0] == "foo");
|
||||
YAML_ASSERT(doc[1].GetTag() == "tag:yaml.org,2002:str");
|
||||
YAML_ASSERT(doc[1] == "bar");
|
||||
YAML_ASSERT(doc[2].GetTag() == "tag:example.com,2000:app/tag%21");
|
||||
YAML_ASSERT(doc[2] == "baz");
|
||||
return true;
|
||||
}
|
||||
|
||||
// 6.27
|
||||
TEST InvalidTagShorthands()
|
||||
{
|
||||
std::string input1 =
|
||||
"%TAG !e! tag:example,2000:app/\n"
|
||||
"---\n"
|
||||
"- !e! foo";
|
||||
|
||||
bool threw = false;
|
||||
try {
|
||||
PARSE(doc, input1);
|
||||
} catch(const YAML::ParserException& e) {
|
||||
threw = true;
|
||||
if(e.msg != YAML::ErrorMsg::TAG_WITH_NO_SUFFIX)
|
||||
throw;
|
||||
}
|
||||
|
||||
if(!threw)
|
||||
return " No exception was thrown for a tag with no suffix";
|
||||
|
||||
std::string input2 =
|
||||
"%TAG !e! tag:example,2000:app/\n"
|
||||
"---\n"
|
||||
"- !h!bar baz";
|
||||
|
||||
PARSE(doc, input2); // TODO: should we reject this one (since !h! is not declared)?
|
||||
return " not implemented yet";
|
||||
}
|
||||
|
||||
// 6.28
|
||||
TEST NonSpecificTags()
|
||||
{
|
||||
std::string input =
|
||||
"# Assuming conventional resolution:\n"
|
||||
"- \"12\"\n"
|
||||
"- 12\n"
|
||||
"- ! 12";
|
||||
|
||||
PARSE(doc, input);
|
||||
YAML_ASSERT(doc.size() == 3);
|
||||
YAML_ASSERT(doc[0] == "12"); // TODO: check tags. How?
|
||||
YAML_ASSERT(doc[1] == 12);
|
||||
YAML_ASSERT(doc[2] == "12");
|
||||
return true;
|
||||
}
|
||||
|
||||
// 6.29
|
||||
TEST NodeAnchors()
|
||||
@@ -1039,8 +1452,16 @@ namespace Test {
|
||||
|
||||
PARSE(doc, input);
|
||||
YAML_ASSERT(doc.size() == 2);
|
||||
YAML_ASSERT(doc["foo"] == ""); // TODO: check tag
|
||||
YAML_ASSERT(doc[""] == "bar");
|
||||
for(YAML::Iterator it=doc.begin();it!=doc.end();++it) {
|
||||
if(it.first() == "foo") {
|
||||
YAML_ASSERT(it.second().GetTag() == "tag:yaml.org,2002:str");
|
||||
YAML_ASSERT(it.second() == "");
|
||||
} else if(it.first() == "") {
|
||||
YAML_ASSERT(it.first().GetTag() == "tag:yaml.org,2002:str");
|
||||
YAML_ASSERT(it.second() == "bar");
|
||||
} else
|
||||
return " unexpected key";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1232,6 +1653,10 @@ namespace Test {
|
||||
RunSpecTest(&Spec::QuotedScalars, "2.17", "Quoted scalars", passed, total);
|
||||
RunSpecTest(&Spec::MultiLineFlowScalars, "2.18", "Multi-line flow scalars", passed, total);
|
||||
|
||||
RunSpecTest(&Spec::VariousExplicitTags, "2.23", "Various Explicit Tags", passed, total);
|
||||
RunSpecTest(&Spec::GlobalTags, "2.24", "Global Tags", passed, total);
|
||||
RunSpecTest(&Spec::UnorderedSets, "2.25", "Unordered Sets", passed, total);
|
||||
RunSpecTest(&Spec::OrderedMappings, "2.26", "Ordered Mappings", passed, total);
|
||||
RunSpecTest(&Spec::Invoice, "2.27", "Invoice", passed, total);
|
||||
RunSpecTest(&Spec::LogFile, "2.28", "Log File", passed, total);
|
||||
|
||||
@@ -1255,8 +1680,24 @@ namespace Test {
|
||||
RunSpecTest(&Spec::FlowFolding, "6.8", "Flow Folding", passed, total);
|
||||
RunSpecTest(&Spec::SeparatedComment, "6.9", "Separated Comment", passed, total);
|
||||
RunSpecTest(&Spec::CommentLines, "6.10", "Comment Lines", passed, total);
|
||||
RunSpecTest(&Spec::SeparationSpacesII, "6.11", "Separation Spaces", passed, total);
|
||||
|
||||
RunSpecTest(&Spec::MultiLineComments, "6.11", "Multi-Line Comments", passed, total);
|
||||
RunSpecTest(&Spec::SeparationSpacesII, "6.12", "Separation Spaces", passed, total);
|
||||
RunSpecTest(&Spec::ReservedDirectives, "6.13", "Reserved Directives", passed, total);
|
||||
RunSpecTest(&Spec::YAMLDirective, "6.14", "YAML Directive", passed, total);
|
||||
RunSpecTest(&Spec::InvalidRepeatedYAMLDirective, "6.15", "Invalid Repeated YAML Directive", passed, total);
|
||||
RunSpecTest(&Spec::TagDirective, "6.16", "Tag Directive", passed, total);
|
||||
RunSpecTest(&Spec::InvalidRepeatedTagDirective, "6.17", "Invalid Repeated Tag Directive", passed, total);
|
||||
RunSpecTest(&Spec::PrimaryTagHandle, "6.18", "Primary Tag Handle", passed, total);
|
||||
RunSpecTest(&Spec::SecondaryTagHandle, "6.19", "SecondaryTagHandle", passed, total);
|
||||
RunSpecTest(&Spec::TagHandles, "6.20", "TagHandles", passed, total);
|
||||
RunSpecTest(&Spec::LocalTagPrefix, "6.21", "LocalTagPrefix", passed, total);
|
||||
RunSpecTest(&Spec::GlobalTagPrefix, "6.22", "GlobalTagPrefix", passed, total);
|
||||
RunSpecTest(&Spec::NodeProperties, "6.23", "NodeProperties", passed, total);
|
||||
RunSpecTest(&Spec::VerbatimTags, "6.24", "Verbatim Tags", passed, total);
|
||||
RunSpecTest(&Spec::InvalidVerbatimTags, "6.25", "Invalid Verbatim Tags", passed, total);
|
||||
RunSpecTest(&Spec::TagShorthands, "6.26", "Tag Shorthands", passed, total);
|
||||
RunSpecTest(&Spec::InvalidTagShorthands, "6.27", "Invalid Tag Shorthands", passed, total);
|
||||
RunSpecTest(&Spec::NonSpecificTags, "6.28", "Non Specific Tags", passed, total);
|
||||
RunSpecTest(&Spec::NodeAnchors, "6.29", "Node Anchors", passed, total);
|
||||
|
||||
RunSpecTest(&Spec::AliasNodes, "7.1", "Alias Nodes", passed, total);
|
||||
|
Reference in New Issue
Block a user