mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2025-09-09 20:51:16 +00:00
Replaced the queue of Token pointers with values.
We were getting memory leaks (as told by the CRT detectors, which I also added), and there's really no reason (as long as we're careful) to use pointers there.
This commit is contained in:
10
include/crt.h
Normal file
10
include/crt.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// for memory leaks
|
||||||
|
#ifdef _DEBUG
|
||||||
|
|
||||||
|
#define _CRTDBG_MAP_ALLOC
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <crtdbg.h>
|
||||||
|
|
||||||
|
#endif // _DEBUG
|
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
{
|
{
|
||||||
@@ -9,6 +10,7 @@ namespace YAML
|
|||||||
public:
|
public:
|
||||||
ParserException(int line_, int column_, const std::string& msg_)
|
ParserException(int line_, int column_, const std::string& msg_)
|
||||||
: line(line_), column(column_), msg(msg_) {}
|
: line(line_), column(column_), msg(msg_) {}
|
||||||
|
|
||||||
int line, column;
|
int line, column;
|
||||||
std::string msg;
|
std::string msg;
|
||||||
};
|
};
|
||||||
|
6
include/yaml.h
Normal file
6
include/yaml.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "crt.h"
|
||||||
|
#include "parser.h"
|
||||||
|
#include "node.h"
|
||||||
|
#include "exceptions.h"
|
@@ -1,3 +1,4 @@
|
|||||||
|
#include "crt.h"
|
||||||
#include "content.h"
|
#include "content.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
#include "crt.h"
|
||||||
#include "exp.h"
|
#include "exp.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
#include "crt.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
|
|
||||||
|
53
src/map.cpp
53
src/map.cpp
@@ -1,3 +1,4 @@
|
|||||||
|
#include "crt.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
@@ -41,9 +42,9 @@ namespace YAML
|
|||||||
Clear();
|
Clear();
|
||||||
|
|
||||||
// split based on start token
|
// split based on start token
|
||||||
Token *pToken = pScanner->PeekNextToken();
|
Token& token = pScanner->PeekToken();
|
||||||
|
|
||||||
switch(pToken->type) {
|
switch(token.type) {
|
||||||
case TT_BLOCK_MAP_START: ParseBlock(pScanner, state); break;
|
case TT_BLOCK_MAP_START: ParseBlock(pScanner, state); break;
|
||||||
case TT_FLOW_MAP_START: ParseFlow(pScanner, state); break;
|
case TT_FLOW_MAP_START: ParseFlow(pScanner, state); break;
|
||||||
}
|
}
|
||||||
@@ -52,18 +53,18 @@ namespace YAML
|
|||||||
void Map::ParseBlock(Scanner *pScanner, const ParserState& state)
|
void Map::ParseBlock(Scanner *pScanner, const ParserState& state)
|
||||||
{
|
{
|
||||||
// eat start token
|
// eat start token
|
||||||
pScanner->EatNextToken();
|
pScanner->PopToken();
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
Token *pToken = pScanner->PeekNextToken();
|
if(pScanner->IsEmpty())
|
||||||
if(!pToken)
|
|
||||||
throw ParserException(-1, -1, ErrorMsg::END_OF_MAP);
|
throw ParserException(-1, -1, ErrorMsg::END_OF_MAP);
|
||||||
|
|
||||||
if(pToken->type != TT_KEY && pToken->type != TT_BLOCK_END)
|
Token token = pScanner->PeekToken();
|
||||||
throw ParserException(pToken->line, pToken->column, ErrorMsg::END_OF_MAP);
|
if(token.type != TT_KEY && token.type != TT_BLOCK_END)
|
||||||
|
throw ParserException(token.line, token.column, ErrorMsg::END_OF_MAP);
|
||||||
|
|
||||||
pScanner->PopNextToken();
|
pScanner->PopToken();
|
||||||
if(pToken->type == TT_BLOCK_END)
|
if(token.type == TT_BLOCK_END)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
Node *pKey = new Node;
|
Node *pKey = new Node;
|
||||||
@@ -74,8 +75,8 @@ namespace YAML
|
|||||||
pKey->Parse(pScanner, state);
|
pKey->Parse(pScanner, state);
|
||||||
|
|
||||||
// now grab value (optional)
|
// now grab value (optional)
|
||||||
if(pScanner->PeekNextToken() && pScanner->PeekNextToken()->type == TT_VALUE) {
|
if(!pScanner->IsEmpty() && pScanner->PeekToken().type == TT_VALUE) {
|
||||||
pScanner->PopNextToken();
|
pScanner->PopToken();
|
||||||
pValue->Parse(pScanner, state);
|
pValue->Parse(pScanner, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,24 +92,24 @@ namespace YAML
|
|||||||
void Map::ParseFlow(Scanner *pScanner, const ParserState& state)
|
void Map::ParseFlow(Scanner *pScanner, const ParserState& state)
|
||||||
{
|
{
|
||||||
// eat start token
|
// eat start token
|
||||||
pScanner->EatNextToken();
|
pScanner->PopToken();
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
Token *pToken = pScanner->PeekNextToken();
|
if(pScanner->IsEmpty())
|
||||||
if(!pToken)
|
|
||||||
throw ParserException(-1, -1, ErrorMsg::END_OF_MAP_FLOW);
|
throw ParserException(-1, -1, ErrorMsg::END_OF_MAP_FLOW);
|
||||||
|
|
||||||
|
Token& token = pScanner->PeekToken();
|
||||||
// first check for end
|
// first check for end
|
||||||
if(pToken->type == TT_FLOW_MAP_END) {
|
if(token.type == TT_FLOW_MAP_END) {
|
||||||
pScanner->EatNextToken();
|
pScanner->PopToken();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// now it better be a key
|
// now it better be a key
|
||||||
if(pToken->type != TT_KEY)
|
if(token.type != TT_KEY)
|
||||||
throw ParserException(pToken->line, pToken->column, ErrorMsg::END_OF_MAP_FLOW);
|
throw ParserException(token.line, token.column, ErrorMsg::END_OF_MAP_FLOW);
|
||||||
|
|
||||||
pScanner->PopNextToken();
|
pScanner->PopToken();
|
||||||
|
|
||||||
Node *pKey = new Node;
|
Node *pKey = new Node;
|
||||||
Node *pValue = new Node;
|
Node *pValue = new Node;
|
||||||
@@ -118,17 +119,17 @@ namespace YAML
|
|||||||
pKey->Parse(pScanner, state);
|
pKey->Parse(pScanner, state);
|
||||||
|
|
||||||
// now grab value (optional)
|
// now grab value (optional)
|
||||||
if(pScanner->PeekNextToken() && pScanner->PeekNextToken()->type == TT_VALUE) {
|
if(!pScanner->IsEmpty() && pScanner->PeekToken().type == TT_VALUE) {
|
||||||
pScanner->PopNextToken();
|
pScanner->PopToken();
|
||||||
pValue->Parse(pScanner, state);
|
pValue->Parse(pScanner, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
// now eat the separator (or could be a map end, which we ignore - but if it's neither, then it's a bad node)
|
// now eat the separator (or could be a map end, which we ignore - but if it's neither, then it's a bad node)
|
||||||
pToken = pScanner->PeekNextToken();
|
Token& nextToken = pScanner->PeekToken();
|
||||||
if(pToken->type == TT_FLOW_ENTRY)
|
if(nextToken.type == TT_FLOW_ENTRY)
|
||||||
pScanner->EatNextToken();
|
pScanner->PopToken();
|
||||||
else if(pToken->type != TT_FLOW_MAP_END)
|
else if(nextToken.type != TT_FLOW_MAP_END)
|
||||||
throw ParserException(pToken->line, pToken->column, ErrorMsg::END_OF_MAP_FLOW);
|
throw ParserException(nextToken.line, nextToken.column, ErrorMsg::END_OF_MAP_FLOW);
|
||||||
|
|
||||||
m_data[pKey] = pValue;
|
m_data[pKey] = pValue;
|
||||||
} catch(Exception& e) {
|
} catch(Exception& e) {
|
||||||
|
46
src/node.cpp
46
src/node.cpp
@@ -1,3 +1,4 @@
|
|||||||
|
#include "crt.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
@@ -42,11 +43,7 @@ namespace YAML
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// now split based on what kind of node we should be
|
// now split based on what kind of node we should be
|
||||||
Token *pToken = pScanner->PeekNextToken();
|
switch(pScanner->PeekToken().type) {
|
||||||
if(pToken->type == TT_DOC_END)
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch(pToken->type) {
|
|
||||||
case TT_SCALAR:
|
case TT_SCALAR:
|
||||||
m_pContent = new Scalar;
|
m_pContent = new Scalar;
|
||||||
m_pContent->Parse(pScanner, state);
|
m_pContent->Parse(pScanner, state);
|
||||||
@@ -61,6 +58,7 @@ namespace YAML
|
|||||||
case TT_BLOCK_MAP_START:
|
case TT_BLOCK_MAP_START:
|
||||||
m_pContent = new Map;
|
m_pContent = new Map;
|
||||||
m_pContent->Parse(pScanner, state);
|
m_pContent->Parse(pScanner, state);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,53 +67,53 @@ namespace YAML
|
|||||||
void Node::ParseHeader(Scanner *pScanner, const ParserState& state)
|
void Node::ParseHeader(Scanner *pScanner, const ParserState& state)
|
||||||
{
|
{
|
||||||
while(1) {
|
while(1) {
|
||||||
Token *pToken = pScanner->PeekNextToken();
|
if(pScanner->IsEmpty())
|
||||||
if(!pToken || (pToken->type != TT_TAG && pToken->type != TT_ANCHOR && pToken->type != TT_ALIAS))
|
return;
|
||||||
break;
|
|
||||||
|
|
||||||
switch(pToken->type) {
|
switch(pScanner->PeekToken().type) {
|
||||||
case TT_TAG: ParseTag(pScanner, state); break;
|
case TT_TAG: ParseTag(pScanner, state); break;
|
||||||
case TT_ANCHOR: ParseAnchor(pScanner, state); break;
|
case TT_ANCHOR: ParseAnchor(pScanner, state); break;
|
||||||
case TT_ALIAS: ParseAlias(pScanner, state); break;
|
case TT_ALIAS: ParseAlias(pScanner, state); break;
|
||||||
|
default: return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::ParseTag(Scanner *pScanner, const ParserState& state)
|
void Node::ParseTag(Scanner *pScanner, const ParserState& state)
|
||||||
{
|
{
|
||||||
Token *pToken = pScanner->PeekNextToken();
|
Token& token = pScanner->PeekToken();
|
||||||
if(m_tag != "")
|
if(m_tag != "")
|
||||||
throw ParserException(pToken->line, pToken->column, ErrorMsg::MULTIPLE_TAGS);
|
throw ParserException(token.line, token.column, ErrorMsg::MULTIPLE_TAGS);
|
||||||
|
|
||||||
m_tag = state.TranslateTag(pToken->value);
|
m_tag = state.TranslateTag(token.value);
|
||||||
|
|
||||||
for(unsigned i=0;i<pToken->params.size();i++)
|
for(unsigned i=0;i<token.params.size();i++)
|
||||||
m_tag += pToken->params[i];
|
m_tag += token.params[i];
|
||||||
pScanner->PopNextToken();
|
pScanner->PopToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::ParseAnchor(Scanner *pScanner, const ParserState& state)
|
void Node::ParseAnchor(Scanner *pScanner, const ParserState& state)
|
||||||
{
|
{
|
||||||
Token *pToken = pScanner->PeekNextToken();
|
Token& token = pScanner->PeekToken();
|
||||||
if(m_anchor != "")
|
if(m_anchor != "")
|
||||||
throw ParserException(pToken->line, pToken->column, ErrorMsg::MULTIPLE_ANCHORS);
|
throw ParserException(token.line, token.column, ErrorMsg::MULTIPLE_ANCHORS);
|
||||||
|
|
||||||
m_anchor = pToken->value;
|
m_anchor = token.value;
|
||||||
m_alias = false;
|
m_alias = false;
|
||||||
pScanner->PopNextToken();
|
pScanner->PopToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::ParseAlias(Scanner *pScanner, const ParserState& state)
|
void Node::ParseAlias(Scanner *pScanner, const ParserState& state)
|
||||||
{
|
{
|
||||||
Token *pToken = pScanner->PeekNextToken();
|
Token& token = pScanner->PeekToken();
|
||||||
if(m_anchor != "")
|
if(m_anchor != "")
|
||||||
throw ParserException(pToken->line, pToken->column, ErrorMsg::MULTIPLE_ALIASES);
|
throw ParserException(token.line, token.column, ErrorMsg::MULTIPLE_ALIASES);
|
||||||
if(m_tag != "")
|
if(m_tag != "")
|
||||||
throw ParserException(pToken->line, pToken->column, ErrorMsg::ALIAS_CONTENT);
|
throw ParserException(token.line, token.column, ErrorMsg::ALIAS_CONTENT);
|
||||||
|
|
||||||
m_anchor = pToken->value;
|
m_anchor = token.value;
|
||||||
m_alias = true;
|
m_alias = true;
|
||||||
pScanner->PopNextToken();
|
pScanner->PopToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine) const
|
void Node::Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine) const
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
#include "crt.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
@@ -18,7 +19,7 @@ namespace YAML
|
|||||||
|
|
||||||
Parser::operator bool() const
|
Parser::operator bool() const
|
||||||
{
|
{
|
||||||
return m_pScanner->PeekNextToken() != 0;
|
return !m_pScanner->IsEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parser::Load(std::istream& in)
|
void Parser::Load(std::istream& in)
|
||||||
@@ -40,19 +41,19 @@ namespace YAML
|
|||||||
ParseDirectives();
|
ParseDirectives();
|
||||||
|
|
||||||
// we better have some tokens in the queue
|
// we better have some tokens in the queue
|
||||||
if(!m_pScanner->PeekNextToken())
|
if(m_pScanner->IsEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// first eat doc start (optional)
|
// first eat doc start (optional)
|
||||||
if(m_pScanner->PeekNextToken()->type == TT_DOC_START)
|
if(m_pScanner->PeekToken().type == TT_DOC_START)
|
||||||
m_pScanner->EatNextToken();
|
m_pScanner->PopToken();
|
||||||
|
|
||||||
// now parse our root node
|
// now parse our root node
|
||||||
document.Parse(m_pScanner, m_state);
|
document.Parse(m_pScanner, m_state);
|
||||||
|
|
||||||
// and finally eat any doc ends we see
|
// and finally eat any doc ends we see
|
||||||
while(m_pScanner->PeekNextToken() && m_pScanner->PeekNextToken()->type == TT_DOC_END)
|
while(!m_pScanner->IsEmpty() && m_pScanner->PeekToken().type == TT_DOC_END)
|
||||||
m_pScanner->EatNextToken();
|
m_pScanner->PopToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseDirectives
|
// ParseDirectives
|
||||||
@@ -62,8 +63,11 @@ namespace YAML
|
|||||||
bool readDirective = false;
|
bool readDirective = false;
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
Token *pToken = m_pScanner->PeekNextToken();
|
if(m_pScanner->IsEmpty())
|
||||||
if(!pToken || pToken->type != TT_DIRECTIVE)
|
break;
|
||||||
|
|
||||||
|
Token& token = m_pScanner->PeekToken();
|
||||||
|
if(token.type != TT_DIRECTIVE)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// we keep the directives from the last document if none are specified;
|
// we keep the directives from the last document if none are specified;
|
||||||
@@ -72,8 +76,8 @@ namespace YAML
|
|||||||
m_state.Reset();
|
m_state.Reset();
|
||||||
|
|
||||||
readDirective = true;
|
readDirective = true;
|
||||||
HandleDirective(pToken);
|
HandleDirective(&token);
|
||||||
m_pScanner->PopNextToken();
|
m_pScanner->PopToken();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,11 +123,11 @@ namespace YAML
|
|||||||
void Parser::PrintTokens(std::ostream& out)
|
void Parser::PrintTokens(std::ostream& out)
|
||||||
{
|
{
|
||||||
while(1) {
|
while(1) {
|
||||||
Token *pToken = m_pScanner->GetNextToken();
|
if(m_pScanner->IsEmpty())
|
||||||
if(!pToken)
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
out << *pToken << std::endl;
|
out << m_pScanner->PeekToken() << std::endl;
|
||||||
|
m_pScanner->PopToken();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
#include "crt.h"
|
||||||
#include "parserstate.h"
|
#include "parserstate.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
#include "crt.h"
|
||||||
#include "regex.h"
|
#include "regex.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
#include "crt.h"
|
||||||
#include "scalar.h"
|
#include "scalar.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
@@ -16,9 +17,9 @@ namespace YAML
|
|||||||
|
|
||||||
void Scalar::Parse(Scanner *pScanner, const ParserState& state)
|
void Scalar::Parse(Scanner *pScanner, const ParserState& state)
|
||||||
{
|
{
|
||||||
Token *pToken = pScanner->GetNextToken();
|
Token& token = pScanner->PeekToken();
|
||||||
m_data = pToken->value;
|
m_data = token.value;
|
||||||
delete pToken;
|
pScanner->PopToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scalar::Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine)
|
void Scalar::Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine)
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
#include "crt.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
@@ -12,62 +13,46 @@ namespace YAML
|
|||||||
|
|
||||||
Scanner::~Scanner()
|
Scanner::~Scanner()
|
||||||
{
|
{
|
||||||
while(!m_tokens.empty()) {
|
|
||||||
delete m_tokens.front();
|
|
||||||
m_tokens.pop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNextToken
|
// IsEmpty
|
||||||
// . Removes and returns the next token on the queue.
|
// . Returns true if there are no more tokens to be read
|
||||||
Token *Scanner::GetNextToken()
|
bool Scanner::IsEmpty()
|
||||||
{
|
{
|
||||||
Token *pToken = PeekNextToken();
|
PeekToken(); // to ensure that there are tokens in the queue, if possible
|
||||||
|
return m_tokens.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// PopToken
|
||||||
|
// . Simply removes the next token on the queue.
|
||||||
|
void Scanner::PopToken()
|
||||||
|
{
|
||||||
|
PeekToken(); // to ensure that there are tokens in the queue
|
||||||
if(!m_tokens.empty())
|
if(!m_tokens.empty())
|
||||||
m_tokens.pop();
|
m_tokens.pop();
|
||||||
return pToken;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PopNextToken
|
// PeekToken
|
||||||
// . Simply removes the next token on the queue.
|
|
||||||
void Scanner::PopNextToken()
|
|
||||||
{
|
|
||||||
GetNextToken();
|
|
||||||
}
|
|
||||||
|
|
||||||
// EatNextToken
|
|
||||||
// . Removes and deletes the next token on the queue
|
|
||||||
void Scanner::EatNextToken()
|
|
||||||
{
|
|
||||||
delete GetNextToken();
|
|
||||||
}
|
|
||||||
|
|
||||||
// PeekNextToken
|
|
||||||
// . Returns (but does not remove) the next token on the queue, and scans if only we need to.
|
// . Returns (but does not remove) the next token on the queue, and scans if only we need to.
|
||||||
Token *Scanner::PeekNextToken()
|
Token& Scanner::PeekToken()
|
||||||
{
|
{
|
||||||
while(1) {
|
while(1) {
|
||||||
Token *pToken = 0;
|
if(!m_tokens.empty()) {
|
||||||
|
Token& token = m_tokens.front();
|
||||||
|
|
||||||
// is there a token in the queue?
|
// return this guy if it's valid
|
||||||
if(!m_tokens.empty())
|
if(token.status == TS_VALID)
|
||||||
pToken = m_tokens.front();
|
return token;
|
||||||
|
|
||||||
// (here's where we clean up the impossible tokens)
|
// here's where we clean up the impossible tokens
|
||||||
if(pToken && pToken->status == TS_INVALID) {
|
if(token.status == TS_INVALID) {
|
||||||
m_tokens.pop();
|
m_tokens.pop();
|
||||||
delete pToken;
|
continue;
|
||||||
continue;
|
}
|
||||||
|
|
||||||
|
// note: what's left are the unverified tokens
|
||||||
}
|
}
|
||||||
|
|
||||||
// on unverified tokens, we just have to wait
|
|
||||||
if(pToken && pToken->status == TS_UNVERIFIED)
|
|
||||||
pToken = 0;
|
|
||||||
|
|
||||||
// then that's what we want
|
|
||||||
if(pToken)
|
|
||||||
return pToken;
|
|
||||||
|
|
||||||
// no token? maybe we've actually finished
|
// no token? maybe we've actually finished
|
||||||
if(m_endedStream)
|
if(m_endedStream)
|
||||||
break;
|
break;
|
||||||
@@ -76,7 +61,7 @@ namespace YAML
|
|||||||
ScanNextToken();
|
ScanNextToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
// TODO: find something to return here, or assert (but can't do that! maybe split into two functions?)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScanNextToken
|
// ScanNextToken
|
||||||
@@ -254,14 +239,12 @@ namespace YAML
|
|||||||
|
|
||||||
// now push
|
// now push
|
||||||
m_indents.push(column);
|
m_indents.push(column);
|
||||||
Token *pToken = 0;
|
|
||||||
if(sequence)
|
if(sequence)
|
||||||
pToken = new Token(TT_BLOCK_SEQ_START, INPUT.line, INPUT.column);
|
m_tokens.push(Token(TT_BLOCK_SEQ_START, INPUT.line, INPUT.column));
|
||||||
else
|
else
|
||||||
pToken = new Token(TT_BLOCK_MAP_START, INPUT.line, INPUT.column);
|
m_tokens.push(Token(TT_BLOCK_MAP_START, INPUT.line, INPUT.column));
|
||||||
|
|
||||||
m_tokens.push(pToken);
|
return &m_tokens.back();
|
||||||
return pToken;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PopIndentTo
|
// PopIndentTo
|
||||||
@@ -276,7 +259,7 @@ namespace YAML
|
|||||||
// now pop away
|
// now pop away
|
||||||
while(!m_indents.empty() && m_indents.top() > column) {
|
while(!m_indents.empty() && m_indents.top() > column) {
|
||||||
m_indents.pop();
|
m_indents.pop();
|
||||||
m_tokens.push(new Token(TT_BLOCK_END, INPUT.line, INPUT.column));
|
m_tokens.push(Token(TT_BLOCK_END, INPUT.line, INPUT.column));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,21 +6,19 @@
|
|||||||
#include <stack>
|
#include <stack>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
|
#include "token.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
{
|
{
|
||||||
struct Token;
|
|
||||||
|
|
||||||
class Scanner
|
class Scanner
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Scanner(std::istream& in);
|
Scanner(std::istream& in);
|
||||||
~Scanner();
|
~Scanner();
|
||||||
|
|
||||||
Token *GetNextToken();
|
bool IsEmpty();
|
||||||
void EatNextToken();
|
void PopToken();
|
||||||
void PopNextToken();
|
Token& PeekToken();
|
||||||
Token *PeekNextToken();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// scanning
|
// scanning
|
||||||
@@ -72,7 +70,7 @@ namespace YAML
|
|||||||
Stream INPUT;
|
Stream INPUT;
|
||||||
|
|
||||||
// the output (tokens)
|
// the output (tokens)
|
||||||
std::queue <Token *> m_tokens;
|
std::queue <Token> m_tokens;
|
||||||
|
|
||||||
// state info
|
// state info
|
||||||
bool m_startedStream, m_endedStream;
|
bool m_startedStream, m_endedStream;
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
#include "crt.h"
|
||||||
#include "scanscalar.h"
|
#include "scanscalar.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "exp.h"
|
#include "exp.h"
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
#include "crt.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
@@ -49,10 +50,10 @@ namespace YAML
|
|||||||
params.push_back(param);
|
params.push_back(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
Token *pToken = new Token(TT_DIRECTIVE, line, column);
|
Token token(TT_DIRECTIVE, line, column);
|
||||||
pToken->value = name;
|
token.value = name;
|
||||||
pToken->params = params;
|
token.params = params;
|
||||||
m_tokens.push(pToken);
|
m_tokens.push(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
// DocStart
|
// DocStart
|
||||||
@@ -65,7 +66,7 @@ namespace YAML
|
|||||||
// eat
|
// eat
|
||||||
int line = INPUT.line, column = INPUT.column;
|
int line = INPUT.line, column = INPUT.column;
|
||||||
INPUT.eat(3);
|
INPUT.eat(3);
|
||||||
m_tokens.push(new Token(TT_DOC_START, line, column));
|
m_tokens.push(Token(TT_DOC_START, line, column));
|
||||||
}
|
}
|
||||||
|
|
||||||
// DocEnd
|
// DocEnd
|
||||||
@@ -78,7 +79,7 @@ namespace YAML
|
|||||||
// eat
|
// eat
|
||||||
int line = INPUT.line, column = INPUT.column;
|
int line = INPUT.line, column = INPUT.column;
|
||||||
INPUT.eat(3);
|
INPUT.eat(3);
|
||||||
m_tokens.push(new Token(TT_DOC_END, line, column));
|
m_tokens.push(Token(TT_DOC_END, line, column));
|
||||||
}
|
}
|
||||||
|
|
||||||
// FlowStart
|
// FlowStart
|
||||||
@@ -93,7 +94,7 @@ namespace YAML
|
|||||||
int line = INPUT.line, column = INPUT.column;
|
int line = INPUT.line, column = INPUT.column;
|
||||||
char ch = INPUT.get();
|
char ch = INPUT.get();
|
||||||
TOKEN_TYPE type = (ch == Keys::FlowSeqStart ? TT_FLOW_SEQ_START : TT_FLOW_MAP_START);
|
TOKEN_TYPE type = (ch == Keys::FlowSeqStart ? TT_FLOW_SEQ_START : TT_FLOW_MAP_START);
|
||||||
m_tokens.push(new Token(type, line, column));
|
m_tokens.push(Token(type, line, column));
|
||||||
}
|
}
|
||||||
|
|
||||||
// FlowEnd
|
// FlowEnd
|
||||||
@@ -109,7 +110,7 @@ namespace YAML
|
|||||||
int line = INPUT.line, column = INPUT.column;
|
int line = INPUT.line, column = INPUT.column;
|
||||||
char ch = INPUT.get();
|
char ch = INPUT.get();
|
||||||
TOKEN_TYPE type = (ch == Keys::FlowSeqEnd ? TT_FLOW_SEQ_END : TT_FLOW_MAP_END);
|
TOKEN_TYPE type = (ch == Keys::FlowSeqEnd ? TT_FLOW_SEQ_END : TT_FLOW_MAP_END);
|
||||||
m_tokens.push(new Token(type, line, column));
|
m_tokens.push(Token(type, line, column));
|
||||||
}
|
}
|
||||||
|
|
||||||
// FlowEntry
|
// FlowEntry
|
||||||
@@ -120,7 +121,7 @@ namespace YAML
|
|||||||
// eat
|
// eat
|
||||||
int line = INPUT.line, column = INPUT.column;
|
int line = INPUT.line, column = INPUT.column;
|
||||||
INPUT.eat(1);
|
INPUT.eat(1);
|
||||||
m_tokens.push(new Token(TT_FLOW_ENTRY, line, column));
|
m_tokens.push(Token(TT_FLOW_ENTRY, line, column));
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockEntry
|
// BlockEntry
|
||||||
@@ -140,7 +141,7 @@ namespace YAML
|
|||||||
// eat
|
// eat
|
||||||
int line = INPUT.line, column = INPUT.column;
|
int line = INPUT.line, column = INPUT.column;
|
||||||
INPUT.eat(1);
|
INPUT.eat(1);
|
||||||
m_tokens.push(new Token(TT_BLOCK_ENTRY, line, column));
|
m_tokens.push(Token(TT_BLOCK_ENTRY, line, column));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Key
|
// Key
|
||||||
@@ -163,7 +164,7 @@ namespace YAML
|
|||||||
// eat
|
// eat
|
||||||
int line = INPUT.line, column = INPUT.column;
|
int line = INPUT.line, column = INPUT.column;
|
||||||
INPUT.eat(1);
|
INPUT.eat(1);
|
||||||
m_tokens.push(new Token(TT_KEY, line, column));
|
m_tokens.push(Token(TT_KEY, line, column));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Value
|
// Value
|
||||||
@@ -192,7 +193,7 @@ namespace YAML
|
|||||||
// eat
|
// eat
|
||||||
int line = INPUT.line, column = INPUT.column;
|
int line = INPUT.line, column = INPUT.column;
|
||||||
INPUT.eat(1);
|
INPUT.eat(1);
|
||||||
m_tokens.push(new Token(TT_VALUE, line, column));
|
m_tokens.push(Token(TT_VALUE, line, column));
|
||||||
}
|
}
|
||||||
|
|
||||||
// AnchorOrAlias
|
// AnchorOrAlias
|
||||||
@@ -224,9 +225,9 @@ namespace YAML
|
|||||||
throw ParserException(INPUT.line, INPUT.column, alias ? ErrorMsg::CHAR_IN_ALIAS : ErrorMsg::CHAR_IN_ANCHOR);
|
throw ParserException(INPUT.line, INPUT.column, alias ? ErrorMsg::CHAR_IN_ALIAS : ErrorMsg::CHAR_IN_ANCHOR);
|
||||||
|
|
||||||
// and we're done
|
// and we're done
|
||||||
Token *pToken = new Token(alias ? TT_ALIAS : TT_ANCHOR, line, column);
|
Token token(alias ? TT_ALIAS : TT_ANCHOR, line, column);
|
||||||
pToken->value = name;
|
token.value = name;
|
||||||
m_tokens.push(pToken);
|
m_tokens.push(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tag
|
// Tag
|
||||||
@@ -261,10 +262,10 @@ namespace YAML
|
|||||||
handle = "!";
|
handle = "!";
|
||||||
}
|
}
|
||||||
|
|
||||||
Token *pToken = new Token(TT_TAG, line, column);
|
Token token(TT_TAG, line, column);
|
||||||
pToken->value = handle;
|
token.value = handle;
|
||||||
pToken->params.push_back(suffix);
|
token.params.push_back(suffix);
|
||||||
m_tokens.push(pToken);
|
m_tokens.push(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
// PlainScalar
|
// PlainScalar
|
||||||
@@ -298,9 +299,9 @@ namespace YAML
|
|||||||
//if(Exp::IllegalCharInScalar.Matches(INPUT))
|
//if(Exp::IllegalCharInScalar.Matches(INPUT))
|
||||||
// throw ParserException(INPUT.line, INPUT.column, ErrorMsg::CHAR_IN_SCALAR);
|
// throw ParserException(INPUT.line, INPUT.column, ErrorMsg::CHAR_IN_SCALAR);
|
||||||
|
|
||||||
Token *pToken = new Token(TT_SCALAR, line, column);
|
Token token(TT_SCALAR, line, column);
|
||||||
pToken->value = scalar;
|
token.value = scalar;
|
||||||
m_tokens.push(pToken);
|
m_tokens.push(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
// QuotedScalar
|
// QuotedScalar
|
||||||
@@ -332,9 +333,9 @@ namespace YAML
|
|||||||
scalar = ScanScalar(INPUT, params);
|
scalar = ScanScalar(INPUT, params);
|
||||||
m_simpleKeyAllowed = false;
|
m_simpleKeyAllowed = false;
|
||||||
|
|
||||||
Token *pToken = new Token(TT_SCALAR, line, column);
|
Token token(TT_SCALAR, line, column);
|
||||||
pToken->value = scalar;
|
token.value = scalar;
|
||||||
m_tokens.push(pToken);
|
m_tokens.push(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockScalarToken
|
// BlockScalarToken
|
||||||
@@ -397,8 +398,8 @@ namespace YAML
|
|||||||
// simple keys always ok after block scalars (since we're gonna start a new line anyways)
|
// simple keys always ok after block scalars (since we're gonna start a new line anyways)
|
||||||
m_simpleKeyAllowed = true;
|
m_simpleKeyAllowed = true;
|
||||||
|
|
||||||
Token *pToken = new Token(TT_SCALAR, line, column);
|
Token token(TT_SCALAR, line, column);
|
||||||
pToken->value = scalar;
|
token.value = scalar;
|
||||||
m_tokens.push(pToken);
|
m_tokens.push(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
#include "crt.h"
|
||||||
#include "sequence.h"
|
#include "sequence.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
@@ -51,9 +52,9 @@ namespace YAML
|
|||||||
Clear();
|
Clear();
|
||||||
|
|
||||||
// split based on start token
|
// split based on start token
|
||||||
Token *pToken = pScanner->PeekNextToken();
|
Token& token = pScanner->PeekToken();
|
||||||
|
|
||||||
switch(pToken->type) {
|
switch(token.type) {
|
||||||
case TT_BLOCK_SEQ_START: ParseBlock(pScanner, state); break;
|
case TT_BLOCK_SEQ_START: ParseBlock(pScanner, state); break;
|
||||||
case TT_BLOCK_ENTRY: ParseImplicit(pScanner, state); break;
|
case TT_BLOCK_ENTRY: ParseImplicit(pScanner, state); break;
|
||||||
case TT_FLOW_SEQ_START: ParseFlow(pScanner, state); break;
|
case TT_FLOW_SEQ_START: ParseFlow(pScanner, state); break;
|
||||||
@@ -63,18 +64,18 @@ namespace YAML
|
|||||||
void Sequence::ParseBlock(Scanner *pScanner, const ParserState& state)
|
void Sequence::ParseBlock(Scanner *pScanner, const ParserState& state)
|
||||||
{
|
{
|
||||||
// eat start token
|
// eat start token
|
||||||
pScanner->EatNextToken();
|
pScanner->PopToken();
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
Token *pToken = pScanner->PeekNextToken();
|
if(pScanner->IsEmpty())
|
||||||
if(!pToken)
|
|
||||||
throw ParserException(-1, -1, ErrorMsg::END_OF_SEQ);
|
throw ParserException(-1, -1, ErrorMsg::END_OF_SEQ);
|
||||||
|
|
||||||
if(pToken->type != TT_BLOCK_ENTRY && pToken->type != TT_BLOCK_END)
|
Token token = pScanner->PeekToken();
|
||||||
throw ParserException(pToken->line, pToken->column, ErrorMsg::END_OF_SEQ);
|
if(token.type != TT_BLOCK_ENTRY && token.type != TT_BLOCK_END)
|
||||||
|
throw ParserException(token.line, token.column, ErrorMsg::END_OF_SEQ);
|
||||||
|
|
||||||
pScanner->PopNextToken();
|
pScanner->PopToken();
|
||||||
if(pToken->type == TT_BLOCK_END)
|
if(token.type == TT_BLOCK_END)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
Node *pNode = new Node;
|
Node *pNode = new Node;
|
||||||
@@ -86,16 +87,16 @@ namespace YAML
|
|||||||
void Sequence::ParseImplicit(Scanner *pScanner, const ParserState& state)
|
void Sequence::ParseImplicit(Scanner *pScanner, const ParserState& state)
|
||||||
{
|
{
|
||||||
while(1) {
|
while(1) {
|
||||||
Token *pToken = pScanner->PeekNextToken();
|
|
||||||
// we're actually *allowed* to have no tokens at some point
|
// we're actually *allowed* to have no tokens at some point
|
||||||
if(!pToken)
|
if(pScanner->IsEmpty())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// and we end at anything other than a block entry
|
// and we end at anything other than a block entry
|
||||||
if(pToken->type != TT_BLOCK_ENTRY)
|
Token& token = pScanner->PeekToken();
|
||||||
|
if(token.type != TT_BLOCK_ENTRY)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
pScanner->PopNextToken();
|
pScanner->PopToken();
|
||||||
|
|
||||||
Node *pNode = new Node;
|
Node *pNode = new Node;
|
||||||
m_data.push_back(pNode);
|
m_data.push_back(pNode);
|
||||||
@@ -106,16 +107,15 @@ namespace YAML
|
|||||||
void Sequence::ParseFlow(Scanner *pScanner, const ParserState& state)
|
void Sequence::ParseFlow(Scanner *pScanner, const ParserState& state)
|
||||||
{
|
{
|
||||||
// eat start token
|
// eat start token
|
||||||
pScanner->EatNextToken();
|
pScanner->PopToken();
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
Token *pToken = pScanner->PeekNextToken();
|
if(pScanner->IsEmpty())
|
||||||
if(!pToken)
|
|
||||||
throw ParserException(-1, -1, ErrorMsg::END_OF_SEQ_FLOW);
|
throw ParserException(-1, -1, ErrorMsg::END_OF_SEQ_FLOW);
|
||||||
|
|
||||||
// first check for end
|
// first check for end
|
||||||
if(pToken->type == TT_FLOW_SEQ_END) {
|
if(pScanner->PeekToken().type == TT_FLOW_SEQ_END) {
|
||||||
pScanner->PopNextToken();
|
pScanner->PopToken();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,11 +125,11 @@ namespace YAML
|
|||||||
pNode->Parse(pScanner, state);
|
pNode->Parse(pScanner, state);
|
||||||
|
|
||||||
// now eat the separator (or could be a sequence end, which we ignore - but if it's neither, then it's a bad node)
|
// now eat the separator (or could be a sequence end, which we ignore - but if it's neither, then it's a bad node)
|
||||||
pToken = pScanner->PeekNextToken();
|
Token& token = pScanner->PeekToken();
|
||||||
if(pToken->type == TT_FLOW_ENTRY)
|
if(token.type == TT_FLOW_ENTRY)
|
||||||
pScanner->EatNextToken();
|
pScanner->PopToken();
|
||||||
else if(pToken->type != TT_FLOW_SEQ_END)
|
else if(token.type != TT_FLOW_SEQ_END)
|
||||||
throw ParserException(pToken->line, pToken->column, ErrorMsg::END_OF_SEQ_FLOW);
|
throw ParserException(token.line, token.column, ErrorMsg::END_OF_SEQ_FLOW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
#include "crt.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
@@ -39,9 +40,9 @@ namespace YAML
|
|||||||
key.pMapStart->status = TS_UNVERIFIED;
|
key.pMapStart->status = TS_UNVERIFIED;
|
||||||
|
|
||||||
// then add the (now unverified) key
|
// then add the (now unverified) key
|
||||||
key.pKey = new Token(TT_KEY, INPUT.line, INPUT.column);
|
m_tokens.push(Token(TT_KEY, INPUT.line, INPUT.column));
|
||||||
|
key.pKey = &m_tokens.back();
|
||||||
key.pKey->status = TS_UNVERIFIED;
|
key.pKey->status = TS_UNVERIFIED;
|
||||||
m_tokens.push(key.pKey);
|
|
||||||
|
|
||||||
m_simpleKeys.push(key);
|
m_simpleKeys.push(key);
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
#include "crt.h"
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
|
@@ -206,7 +206,7 @@
|
|||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\yaml-reader\test.yaml"
|
RelativePath=".\yaml-reader\tests\test.yaml"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
#include "parser.h"
|
#include "yaml.h"
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -9,85 +9,29 @@
|
|||||||
#pragma comment(lib, "yamlcpp.lib")
|
#pragma comment(lib, "yamlcpp.lib")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct Vec3 {
|
void run()
|
||||||
float x, y, z;
|
|
||||||
|
|
||||||
friend std::ostream& operator << (std::ostream& out, const Vec3& v) {
|
|
||||||
out << v.x << " " << v.y << " " << v.z;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void operator >> (const YAML::Node& node, Vec3& v)
|
|
||||||
{
|
{
|
||||||
node[0] >> v.x;
|
std::ifstream fin("yaml-reader/tests/test.yaml");
|
||||||
node[1] >> v.y;
|
|
||||||
node[2] >> v.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Room {
|
try {
|
||||||
std::string name;
|
YAML::Parser parser(fin);
|
||||||
Vec3 pos, size;
|
if(!parser)
|
||||||
float height;
|
return;
|
||||||
|
|
||||||
friend std::ostream& operator << (std::ostream& out, const Room& room) {
|
YAML::Node doc;
|
||||||
out << "Name: " << room.name << std::endl;
|
parser.GetNextDocument(doc);
|
||||||
out << "Pos: " << room.pos << std::endl;
|
std::cout << doc;
|
||||||
out << "Size: " << room.size << std::endl;
|
} catch(YAML::Exception&) {
|
||||||
out << "Height: " << room.height << std::endl;
|
std::cout << "Error parsing the yaml!\n";
|
||||||
return out;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void operator >> (const YAML::Node& node, Room& room)
|
|
||||||
{
|
|
||||||
node["name"] >> room.name;
|
|
||||||
node["pos"] >> room.pos;
|
|
||||||
node["size"] >> room.size;
|
|
||||||
node["height"] >> room.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Level {
|
|
||||||
std::vector <Room> rooms;
|
|
||||||
|
|
||||||
friend std::ostream& operator << (std::ostream& out, const Level& level) {
|
|
||||||
for(unsigned i=0;i<level.rooms.size();i++) {
|
|
||||||
out << level.rooms[i];
|
|
||||||
out << "---------------------------------------\n";
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void operator >> (const YAML::Node& node, Level& level)
|
|
||||||
{
|
|
||||||
const YAML::Node& rooms = node["rooms"];
|
|
||||||
for(unsigned i=0;i<rooms.size();i++) {
|
|
||||||
Room room;
|
|
||||||
rooms[i] >> room;
|
|
||||||
level.rooms.push_back(room);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
YAML::Test::RunAll();
|
_CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF|_CRTDBG_ALLOC_MEM_DF);
|
||||||
|
Test::RunAll();
|
||||||
//std::ifstream fin("test.yaml");
|
run();
|
||||||
|
|
||||||
//try {
|
|
||||||
// YAML::Parser parser(fin);
|
|
||||||
// if(!parser)
|
|
||||||
// return 0;
|
|
||||||
|
|
||||||
// YAML::Node doc;
|
|
||||||
// parser.GetNextDocument(doc);
|
|
||||||
// std::cout << doc;
|
|
||||||
//} catch(YAML::Exception&) {
|
|
||||||
// std::cout << "Error parsing the yaml!\n";
|
|
||||||
//}
|
|
||||||
|
|
||||||
getchar();
|
getchar();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
79
yaml-reader/tests.cpp
Normal file
79
yaml-reader/tests.cpp
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#include "yaml.h"
|
||||||
|
#include "tests.h"
|
||||||
|
#include "parser.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace Test
|
||||||
|
{
|
||||||
|
// runs all the tests on all data we have
|
||||||
|
void RunAll()
|
||||||
|
{
|
||||||
|
std::vector <std::string> files;
|
||||||
|
files.push_back("yaml-reader/tests/simple.yaml");
|
||||||
|
files.push_back("yaml-reader/tests/mixed.yaml");
|
||||||
|
files.push_back("yaml-reader/tests/scalars.yaml");
|
||||||
|
files.push_back("yaml-reader/tests/directives.yaml");
|
||||||
|
|
||||||
|
bool passed = true;
|
||||||
|
for(unsigned i=0;i<files.size();i++) {
|
||||||
|
if(!Inout(files[i])) {
|
||||||
|
std::cout << "Inout test failed on " << files[i] << std::endl;
|
||||||
|
passed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(passed)
|
||||||
|
std::cout << "All tests passed!\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// loads the given YAML file, outputs it, and then loads the outputted file,
|
||||||
|
// outputs again, and makes sure that the two outputs are the same
|
||||||
|
bool Inout(const std::string& file)
|
||||||
|
{
|
||||||
|
std::ifstream fin(file.c_str());
|
||||||
|
|
||||||
|
try {
|
||||||
|
// read and output
|
||||||
|
YAML::Parser parser(fin);
|
||||||
|
if(!parser)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
YAML::Node doc;
|
||||||
|
parser.GetNextDocument(doc);
|
||||||
|
|
||||||
|
std::stringstream out;
|
||||||
|
out << doc;
|
||||||
|
// and save
|
||||||
|
std::string firstTry = out.str();
|
||||||
|
|
||||||
|
// and now again
|
||||||
|
parser.Load(out);
|
||||||
|
if(!parser)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
parser.GetNextDocument(doc);
|
||||||
|
std::stringstream out2;
|
||||||
|
out2 << doc;
|
||||||
|
// and save
|
||||||
|
std::string secondTry = out2.str();
|
||||||
|
|
||||||
|
// now compare
|
||||||
|
if(firstTry == secondTry)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
std::ofstream fout("tests/out.yaml");
|
||||||
|
fout << "---\n";
|
||||||
|
fout << firstTry << std::endl;
|
||||||
|
fout << "---\n";
|
||||||
|
fout << secondTry << std::endl;
|
||||||
|
} catch(YAML::ParserException& e) {
|
||||||
|
std::cout << file << " (line " << e.line + 1 << ", col " << e.column + 1 << "): " << e.msg << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
6
yaml-reader/tests.h
Normal file
6
yaml-reader/tests.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Test {
|
||||||
|
void RunAll();
|
||||||
|
bool Inout(const std::string& file);
|
||||||
|
}
|
@@ -230,10 +230,18 @@
|
|||||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||||
>
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\include\crt.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\include\exceptions.h"
|
RelativePath=".\include\exceptions.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\include\yaml.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Parser"
|
Name="Parser"
|
||||||
>
|
>
|
||||||
|
Reference in New Issue
Block a user