Added an iterator class that can iterate through both sequence and map nodes.

This commit is contained in:
Jesse Beder 2008-07-02 01:22:39 +00:00
parent f7358701f2
commit d56b54b34f
16 changed files with 393 additions and 105 deletions

View file

@ -1,12 +1,16 @@
#pragma once
#include <ios>
#include <vector>
#include <map>
#include "parserstate.h"
#include "exceptions.h"
namespace YAML
{
class Scanner;
class Parser;
class Node;
class Content
{
@ -17,6 +21,20 @@ namespace YAML
virtual void Parse(Scanner *pScanner, const ParserState& state) = 0;
virtual void Write(std::ostream& out, int indent) = 0;
virtual bool GetBegin(std::vector <Node *>::const_iterator& it) { return false; }
virtual bool GetBegin(std::map <Node *, Node *>::const_iterator& it) { return false; }
virtual bool GetEnd(std::vector <Node *>::const_iterator& it) { return false; }
virtual bool GetEnd(std::map <Node *, Node *>::const_iterator& it) { return false; }
// extraction
virtual void Read(std::string& s) { throw InvalidScalar(); }
virtual void Read(int& i) { throw InvalidScalar(); }
virtual void Read(unsigned& u) { throw InvalidScalar(); }
virtual void Read(long& l) { throw InvalidScalar(); }
virtual void Read(float& f) { throw InvalidScalar(); }
virtual void Read(double& d) { throw InvalidScalar(); }
virtual void Read(char& c) { throw InvalidScalar(); }
protected:
};
}

View file

@ -41,8 +41,17 @@ namespace YAML
pScanner->EatNextToken();
}
const Node& Document::GetRoot() const
{
if(!m_pRoot)
throw;
return *m_pRoot;
}
std::ostream& operator << (std::ostream& out, const Document& doc)
{
out << "---\n";
if(!doc.m_pRoot) {
out << "{empty node}\n";
return out;

View file

@ -16,6 +16,7 @@ namespace YAML
void Clear();
void Parse(Scanner *pScanner, const ParserState& state);
const Node& GetRoot() const;
friend std::ostream& operator << (std::ostream& out, const Document& doc);

View file

@ -6,7 +6,9 @@ namespace YAML
{
class Exception: public std::exception {};
class ScannerException: public Exception {};
class RepresentationException: public Exception {};
// scanner exceptions
class UnknownToken: public ScannerException {};
class IllegalBlockEntry: public ScannerException {};
class IllegalMapKey: public ScannerException {};
@ -37,4 +39,8 @@ namespace YAML
InvalidUnicode(unsigned value_): value(value_) {}
unsigned value;
};
// representation exceptions
class InvalidScalar: public RepresentationException {};
class BadDereference: public RepresentationException {};
}

73
iterator.cpp Normal file
View file

@ -0,0 +1,73 @@
#include "node.h"
#include "exceptions.h"
namespace YAML
{
Node::Iterator::Iterator(): type(IT_NONE)
{
}
Node::Iterator::Iterator(std::vector <Node *>::const_iterator it): seqIter(it), type(IT_SEQ)
{
}
Node::Iterator::Iterator(std::map <Node *, Node *>::const_iterator it): mapIter(it), type(IT_MAP)
{
}
Node::Iterator::~Iterator()
{
}
Node::Iterator& Node::Iterator::operator ++ ()
{
if(type == IT_SEQ)
++seqIter;
else if(type == IT_MAP)
++mapIter;
return *this;
}
const Node& Node::Iterator::operator * ()
{
if(type == IT_SEQ)
return **seqIter;
throw BadDereference();
}
const Node& Node::Iterator::first()
{
if(type == IT_MAP)
return *mapIter->first;
throw BadDereference();
}
const Node& Node::Iterator::second()
{
if(type == IT_MAP)
return *mapIter->second;
throw BadDereference();
}
bool operator == (const Node::Iterator& it, const Node::Iterator& jt)
{
if(it.type != jt.type)
return false;
if(it.type == Node::Iterator::IT_SEQ)
return it.seqIter == jt.seqIter;
else if(it.type == Node::Iterator::IT_MAP)
return it.mapIter == jt.mapIter;
return true;
}
bool operator != (const Node::Iterator& it, const Node::Iterator& jt)
{
return !(it == jt);
}
}

View file

@ -1,18 +1,39 @@
#include "parser.h"
#include "node.h"
#include "exceptions.h"
#include <fstream>
#include <iostream>
int main()
{
std::ifstream fin("test.yaml");
YAML::Parser parser(fin);
YAML::Document doc;
while(parser) {
std::cout << "---\n";
try {
YAML::Parser parser(fin);
if(!parser)
return 0;
YAML::Document doc;
parser.GetNextDocument(doc);
std::cout << doc;
const YAML::Node& root = doc.GetRoot();
for(YAML::Node::Iterator it=root.begin();it!=root.end();++it) {
std::string name;
(*it)["name"] >> name;
std::cout << "Name: " << name << std::endl;
int age;
(*it)["age"] >> age;
std::cout << "Age: " << age << std::endl;
std::string school;
(*it)["school"] >> school;
std::cout << "School: " << school << std::endl;
}
} catch(YAML::Exception& e) {
std::cout << "Error parsing the yaml!\n";
}
getchar();
return 0;

12
map.cpp
View file

@ -23,6 +23,18 @@ namespace YAML
m_data.clear();
}
bool Map::GetBegin(std::map <Node *, Node *>::const_iterator& it)
{
it = m_data.begin();
return true;
}
bool Map::GetEnd(std::map <Node *, Node *>::const_iterator& it)
{
it = m_data.end();
return true;
}
void Map::Parse(Scanner *pScanner, const ParserState& state)
{
Clear();

2
map.h
View file

@ -14,6 +14,8 @@ namespace YAML
virtual ~Map();
void Clear();
virtual bool GetBegin(std::map <Node *, Node *>::const_iterator& it);
virtual bool GetEnd(std::map <Node *, Node *>::const_iterator& it);
virtual void Parse(Scanner *pScanner, const ParserState& state);
virtual void Write(std::ostream& out, int indent);

View file

@ -136,4 +136,99 @@ namespace YAML
m_pContent->Write(out, indent);
}
}
// begin
// Returns an iterator to the beginning of this (sequence or map).
Node::Iterator Node::begin() const
{
if(!m_pContent)
return Iterator();
std::vector <Node *>::const_iterator seqIter;
if(m_pContent->GetBegin(seqIter))
return Iterator(seqIter);
std::map <Node *, Node *>::const_iterator mapIter;
if(m_pContent->GetBegin(mapIter))
return Iterator(mapIter);
return Iterator();
}
// end
// . Returns an iterator to the end of this (sequence or map).
Node::Iterator Node::end() const
{
if(!m_pContent)
return Iterator();
std::vector <Node *>::const_iterator seqIter;
if(m_pContent->GetEnd(seqIter))
return Iterator(seqIter);
std::map <Node *, Node *>::const_iterator mapIter;
if(m_pContent->GetEnd(mapIter))
return Iterator(mapIter);
return Iterator();
}
///////////////////////////////////////////////////////
// Extraction
void operator >> (const Node& node, std::string& s)
{
if(!node.m_pContent)
throw;
node.m_pContent->Read(s);
}
void operator >> (const Node& node, int& i)
{
if(!node.m_pContent)
throw;
node.m_pContent->Read(i);
}
void operator >> (const Node& node, unsigned& u)
{
if(!node.m_pContent)
throw;
node.m_pContent->Read(u);
}
void operator >> (const Node& node, long& l)
{
if(!node.m_pContent)
throw;
node.m_pContent->Read(l);
}
void operator >> (const Node& node, float& f)
{
if(!node.m_pContent)
throw;
node.m_pContent->Read(f);
}
void operator >> (const Node& node, double& d)
{
if(!node.m_pContent)
throw;
node.m_pContent->Read(d);
}
void operator >> (const Node& node, char& c)
{
if(!node.m_pContent)
throw;
node.m_pContent->Read(c);
}
}

65
node.h
View file

@ -2,19 +2,42 @@
#include <string>
#include <ios>
#include <vector>
#include <map>
#include "parserstate.h"
#include "exceptions.h"
namespace YAML
{
const std::string StrTag = "!!str";
const std::string SeqTag = "!!seq";
const std::string MapTag = "!!map";
class Content;
class Scanner;
class Node
{
public:
class Iterator
{
public:
Iterator();
Iterator(std::vector <Node *>::const_iterator it);
Iterator(std::map <Node *, Node *>::const_iterator it);
~Iterator();
friend bool operator == (const Iterator& it, const Iterator& jt);
friend bool operator != (const Iterator& it, const Iterator& jt);
Iterator& operator ++ ();
const Node& operator * ();
const Node& first();
const Node& second();
private:
enum ITER_TYPE { IT_NONE, IT_SEQ, IT_MAP };
ITER_TYPE type;
std::vector <Node *>::const_iterator seqIter;
std::map <Node *, Node *>::const_iterator mapIter;
};
public:
Node();
~Node();
@ -23,6 +46,40 @@ namespace YAML
void Parse(Scanner *pScanner, const ParserState& state);
void Write(std::ostream& out, int indent);
Iterator begin() const;
Iterator end() const;
template <typename T>
const Node& operator [] (const T& key) const {
if(!m_pContent)
throw BadDereference();
for(Iterator it=begin();it!=end();++it) {
T t;
try {
it.first() >> t;
if(key == t)
return it.second();
} catch(InvalidScalar&) {
}
}
throw BadDereference();
}
const Node& operator [] (const char *key) const {
return operator [] (std::string(key));
}
// extraction
friend void operator >> (const Node& node, std::string& s);
friend void operator >> (const Node& node, int& i);
friend void operator >> (const Node& node, unsigned& u);
friend void operator >> (const Node& node, long& l);
friend void operator >> (const Node& node, float& f);
friend void operator >> (const Node& node, double& d);
friend void operator >> (const Node& node, char& c);
private:
void ParseHeader(Scanner *pScanner, const ParserState& state);
void ParseTag(Scanner *pScanner, const ParserState& state);

View file

@ -1,6 +1,8 @@
#include "scalar.h"
#include "scanner.h"
#include "token.h"
#include "exceptions.h"
#include <sstream>
namespace YAML
{
@ -28,4 +30,57 @@ namespace YAML
out << " ";
out << m_data << std::endl;
}
void Scalar::Read(std::string& s)
{
s = m_data;
}
void Scalar::Read(int& i)
{
std::stringstream data(m_data);
data >> i;
if(!data)
throw InvalidScalar();
}
void Scalar::Read(unsigned& u)
{
std::stringstream data(m_data);
data >> u;
if(!data)
throw InvalidScalar();
}
void Scalar::Read(long& l)
{
std::stringstream data(m_data);
data >> l;
if(!data)
throw InvalidScalar();
}
void Scalar::Read(float& f)
{
std::stringstream data(m_data);
data >> f;
if(!data)
throw InvalidScalar();
}
void Scalar::Read(double& d)
{
std::stringstream data(m_data);
data >> d;
if(!data)
throw InvalidScalar();
}
void Scalar::Read(char& c)
{
std::stringstream data(m_data);
data >> c;
if(!data)
throw InvalidScalar();
}
}

View file

@ -14,6 +14,15 @@ namespace YAML
virtual void Parse(Scanner *pScanner, const ParserState& state);
virtual void Write(std::ostream& out, int indent);
// extraction
virtual void Read(std::string& s);
virtual void Read(int& i);
virtual void Read(unsigned& u);
virtual void Read(long& l);
virtual void Read(float& f);
virtual void Read(double& d);
virtual void Read(char& c);
protected:
std::string m_data;
};

View file

@ -22,6 +22,18 @@ namespace YAML
m_data.clear();
}
bool Sequence::GetBegin(std::vector <Node *>::const_iterator& it)
{
it = m_data.begin();
return true;
}
bool Sequence::GetEnd(std::vector <Node *>::const_iterator& it)
{
it = m_data.end();
return true;
}
void Sequence::Parse(Scanner *pScanner, const ParserState& state)
{
Clear();

View file

@ -14,6 +14,9 @@ namespace YAML
virtual ~Sequence();
void Clear();
virtual bool GetBegin(std::vector <Node *>::const_iterator& it);
virtual bool GetEnd(std::vector <Node *>::const_iterator& it);
virtual void Parse(Scanner *pScanner, const ParserState& state);
virtual void Write(std::ostream& out, int indent);

103
test.yaml
View file

@ -1,97 +1,8 @@
---
model:
file: data/models/compound.model
textures: data/materials/compound
rooms:
- name: "Room #1"
pos: [0, 0, 0]
size: [1000, 1000, 500]
height: 500
stairtype: none
display: []
pathfinding:
tilesize: 50
size: [24, 24]
map: |
-----------------------
-+++++++++++++++++++++-
-+-------------------+-
-+-------------------+-
-+-------------------+-
-+-------------------+-
-+-------------------+-
-+-------------------+-
-+-------------------+-
-+-------------------+-
-+---------------------
-+---------------------
-+---------------------
-+---------------------
-+-------------------+-
-+-------------------+-
-+-------------------+-
-+-------------------+-
-+-------------------+-
-+-------------------+-
-+-------------------+-
-+-------------------+-
-+++++++++++++++++++++-
-----------------------
- name: Doorway
pos: [1000, 400, 0]
size: [50, 200, 500]
height: 500
stairtype: none
display: []
pathfinding:
tilesize: 50
size: [5, 9]
map: |
-----
-+++-
-----
-----
-----
-----
-----
-+++-
-----
- name: "Room #2"
pos: [1050, 0, 0]
size: [1000, 1000, 500]
height: 500
stairtype: none
display: []
pathfinding:
tilesize: 50
size: [24, 24]
map: |
-----------------------
-+++++++++++++++++++++-
-+-------------------+-
-+-------------------+-
-+-------------------+-
-+-------------------+-
-+-------------------+-
-+-------------------+-
-+-------------------+-
-+-------------------+-
---------------------+-
---------------------+-
---------------------+-
---------------------+-
-+-------------------+-
-+-------------------+-
-+-------------------+-
-+-------------------+-
-+-------------------+-
-+-------------------+-
-+-------------------+-
-+-------------------+-
-+++++++++++++++++++++-
-----------------------
exits:
- room1: "Room #1"
room2: "Room #2"
dir: e
pos: [400, 600]
- name: Jesse
age: 23
school: University of Illinois
- name: Naftali
age: 21
school: Rhode Island School of Design
...

View file

@ -220,6 +220,10 @@
RelativePath=".\document.cpp"
>
</File>
<File
RelativePath=".\iterator.cpp"
>
</File>
<File
RelativePath=".\map.cpp"
>