Joshua Moerman
14 years ago
21 changed files with 5031 additions and 5484 deletions
@ -1,3 +1,3 @@ |
|||
#include "Canvas.hpp" |
|||
|
|||
// lol
|
|||
#include "Canvas.hpp" |
|||
|
|||
// lol
|
|||
|
@ -1,22 +1,22 @@ |
|||
#ifndef CANVAS_HPP |
|||
#define CANVAS_HPP |
|||
|
|||
|
|||
class Canvas { |
|||
protected: |
|||
|
|||
unsigned int dimension; |
|||
Canvas (const unsigned int dimension) : dimension (dimension) {}; |
|||
|
|||
public: |
|||
|
|||
unsigned int getDimension() const { return dimension; }; |
|||
|
|||
virtual ~Canvas() {}; |
|||
|
|||
virtual void clear() = 0; |
|||
virtual void plot (const double * normalizedPosition) = 0; |
|||
virtual void output_file (const char * filename) const = 0; |
|||
}; |
|||
|
|||
#endif // CANVAS_HPP
|
|||
#ifndef CANVAS_HPP |
|||
#define CANVAS_HPP |
|||
|
|||
|
|||
class Canvas { |
|||
protected: |
|||
|
|||
unsigned int dimension; |
|||
Canvas(const unsigned int dimension) : dimension(dimension) {}; |
|||
|
|||
public: |
|||
|
|||
unsigned int getDimension() const { return dimension; }; |
|||
|
|||
virtual ~Canvas() {}; |
|||
|
|||
virtual void clear() = 0; |
|||
virtual void plot(const double* normalizedPosition) = 0; |
|||
virtual void output_file(const char* filename) const = 0; |
|||
}; |
|||
|
|||
#endif // CANVAS_HPP
|
|||
|
@ -1,13 +1,12 @@ |
|||
|
|||
#define DEFAULT_ATTRACTOR_FILE "attractors/testUnravel.stf" |
|||
|
|||
#ifdef UNI_BUILD |
|||
#warning Building for the RU, are you sure? |
|||
#define DEFAULT_WIDTH 8000 |
|||
#define DEFAULT_HEIGHT 8000 |
|||
#define DEFAULT_ITERATIONS 4200000000 |
|||
#warning Building for the RU, are you sure? |
|||
#define DEFAULT_WIDTH 8000 |
|||
#define DEFAULT_HEIGHT 8000 |
|||
#define DEFAULT_ITERATIONS 4200000000 |
|||
#else |
|||
#define DEFAULT_WIDTH 800 |
|||
#define DEFAULT_HEIGHT 800 |
|||
#define DEFAULT_ITERATIONS 1000000 |
|||
#define DEFAULT_WIDTH 800 |
|||
#define DEFAULT_HEIGHT 800 |
|||
#define DEFAULT_ITERATIONS 1000000 |
|||
#endif |
|||
|
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -1,10 +1,10 @@ |
|||
#include "Projection.hpp" |
|||
|
|||
Projection::Projection(unsigned int inputDimension, unsigned int outputDimension) : Projector(inputDimension, outputDimension){ |
|||
Projection::Projection(unsigned int inputDimension, unsigned int outputDimension) : Projector(inputDimension, outputDimension) { |
|||
} |
|||
|
|||
void Projection::project(const double* point){ |
|||
for ( unsigned int i = 0; i < inputDimension; ++i){ |
|||
void Projection::project(const double* point) { |
|||
for(unsigned int i = 0; i < inputDimension; ++i) { |
|||
projectedPoint[i] = point[i]; |
|||
} |
|||
} |
|||
|
@ -1,275 +1,275 @@ |
|||
/*
|
|||
Copyright (c) 2009 Maurice Bos and Nick Overdijk |
|||
All rights reserved. |
|||
|
|||
Redistribution and use in source and binary forms, with or without |
|||
modification, are permitted provided that the following conditions are met: |
|||
* Redistributions of source code must retain the above copyright |
|||
notice, this list of conditions and the following disclaimer. |
|||
* Redistributions in binary form must reproduce the above copyright |
|||
notice, this list of conditions and the following disclaimer in the |
|||
documentation and/or other materials provided with the distribution. |
|||
* The names of the authors may not be used to endorse or promote |
|||
products derived from this software without specific prior written |
|||
permission. |
|||
|
|||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY |
|||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY |
|||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|||
|
|||
- Maurice Bos (maurice@bosbyte.nl) |
|||
- Nick Overdijk (nick@dotsimplicity.net) |
|||
|
|||
*/ |
|||
|
|||
#include <iostream> |
|||
#include <fstream> |
|||
#include <map> |
|||
#include <string> |
|||
#include <typeinfo> |
|||
|
|||
#include "stf.hpp" |
|||
|
|||
namespace stfu{ |
|||
|
|||
std::ostream &operator<< (std::ostream &out, const node &root) { |
|||
root.write(out); |
|||
return out; |
|||
} |
|||
|
|||
bool operator<< (const char *filename, const node &root){ |
|||
return root.write(filename); |
|||
} |
|||
|
|||
bool operator<< (std::ofstream &out, const node &root) { |
|||
return root.write(out); |
|||
} |
|||
|
|||
bool operator>> (std::istream &in, node &root) { |
|||
return root.read(in); |
|||
} |
|||
|
|||
bool operator>> (const char *filename, node &root) { |
|||
return root.read(filename); |
|||
} |
|||
|
|||
const std::string &node::getValue(const std::string &name, size_t index) const throw (std::out_of_range) { |
|||
return get_indexed<std::string, std::string>(values, name, index); |
|||
} |
|||
|
|||
/*Function is const, but shouldn't be called on const objects since it returns a nonconst-reference to a member*/ |
|||
std::string &node::getValue(const std::string &name, size_t index) throw (std::out_of_range) { |
|||
return get_indexed<std::string, std::string>(values, name, index); |
|||
} |
|||
|
|||
std::string &node::addValue(const std::string &name) { |
|||
return values.insert(std::pair<std::string, std::string>(name, std::string()))->second; |
|||
} |
|||
|
|||
std::string &node::value(const std::string &name, size_t index) { |
|||
try { |
|||
return getValue(name, index); |
|||
} catch (std::out_of_range &e) { |
|||
//it doesn't exist: create it
|
|||
return addValue(name); |
|||
} |
|||
} |
|||
|
|||
void node::removeValue(const std::string &name, size_t index) throw (std::out_of_range) { |
|||
values.erase(get_indexed_it(values, name, index)); |
|||
return; |
|||
} |
|||
|
|||
void node::renameValue(const std::string &oldName, const std::string &newName, size_t index) { |
|||
addValue(newName) = value(oldName, index); |
|||
removeValue(oldName, index); |
|||
} |
|||
|
|||
|
|||
const node &node::getChild(const std::string &name, size_t index) const throw (std::out_of_range) { |
|||
return get_indexed<std::string, node>(children, name, index); |
|||
} |
|||
|
|||
node &node::getChild(const std::string &name, size_t index) throw (std::out_of_range) { |
|||
return get_indexed<std::string, node>(children, name, index); |
|||
} |
|||
|
|||
node &node::addChild(const std::string &name) { |
|||
return children.insert(std::pair<std::string, node>(name, node()))->second; |
|||
} |
|||
|
|||
node &node::addChild(const std::string &name, node &newNode) { |
|||
return children.insert(std::pair<std::string, node>(name, newNode))->second; |
|||
} |
|||
|
|||
node &node::child(const std::string &name, size_t index) { |
|||
//if there's no such child, add one
|
|||
try { |
|||
return getChild(name, index); |
|||
} catch (std::out_of_range &e) { |
|||
//it doesn't exist: create it
|
|||
return addChild(name); |
|||
} |
|||
} |
|||
|
|||
void node::renameChild(const std::string &oldName, const std::string &newName, size_t index) { |
|||
node copy = child(oldName, index); |
|||
removeChild(oldName, index); |
|||
addChild(newName) = copy; |
|||
} |
|||
|
|||
void node::removeChild(const std::string &name, size_t index) throw (std::out_of_range) { |
|||
children.erase(get_indexed_it(children, name, index)); |
|||
return; |
|||
} |
|||
|
|||
bool node::read(const char *filename) { |
|||
std::ifstream f(filename); |
|||
|
|||
if (!f.good()) return false; |
|||
|
|||
bool success = read(f); |
|||
f.close(); |
|||
|
|||
return success; |
|||
} |
|||
|
|||
bool node::read(std::istream &in) { |
|||
while (1) { |
|||
in >> std::ws; //Skip whitespace
|
|||
|
|||
//if end of node is reached, return
|
|||
if (in.peek() == '}') { |
|||
in.ignore(); |
|||
return true; |
|||
} |
|||
|
|||
if (in.eof()) { |
|||
return true; //End of the file is reached
|
|||
} |
|||
|
|||
std::string name; |
|||
char type; // '{' or '"'
|
|||
streamRead(in, name, ':'); //Read name (all chars before ':')
|
|||
type = streamSkip(in,"\"{"); //Skip everything until '{' or '"'
|
|||
|
|||
switch (type) { |
|||
|
|||
//in case of value
|
|||
case '"': { |
|||
std::string value; |
|||
while (1) { |
|||
if (streamRead(in, value, '"') == 0) { //Read to the closing-"
|
|||
return false; |
|||
} |
|||
if (in.peek() == '"') { |
|||
in.ignore(); |
|||
value += '"'; |
|||
continue; |
|||
} else { |
|||
break; |
|||
} |
|||
} |
|||
this->values.insert(std::pair<std::string,std::string>(name, value)); |
|||
break; |
|||
} |
|||
|
|||
//in case of child
|
|||
case '{': { |
|||
node sub; |
|||
if (!sub.read(in)) { //Recursively read the subnode
|
|||
return false; |
|||
} |
|||
this->children.insert(std::pair<std::string,node>(name,sub)); |
|||
break; |
|||
} |
|||
|
|||
default: |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/*Writes to a file using it's overloaded self*/ |
|||
bool node::write(const char *filename) const { |
|||
std::ofstream f(filename); |
|||
|
|||
if (!f.good()) { |
|||
return false; |
|||
} |
|||
|
|||
bool success = write(f); |
|||
f.close(); |
|||
|
|||
return success; |
|||
} |
|||
|
|||
// TODO (Nick#1#): Make write() not put unnamed values on a new line, children are okay.
|
|||
bool node::write(std::ostream &out, size_t depth, std::string indent) const { |
|||
std::string indentation; |
|||
for (size_t i = 0; i < depth; i++) { |
|||
indentation += indent; |
|||
} |
|||
|
|||
for (std::multimap<std::string, std::string>::const_iterator value_it = values.begin(); value_it != values.end(); value_it++) { |
|||
//Escape all the '"' by adding a second '"'
|
|||
std::string value(value_it->second); |
|||
size_t found = value.find('"'); |
|||
|
|||
//while there are more ", insert second "s
|
|||
while (found != value.npos) { |
|||
value.insert(found, 1, '"'); |
|||
found = value.find('"', found+2); |
|||
} |
|||
out << indentation << value_it->first << ": \"" << value << '"' << std::endl; |
|||
} |
|||
|
|||
for (std::multimap<std::string, node>::const_iterator child_it = children.begin(); child_it != children.end(); child_it++) { |
|||
out << indentation << child_it->first << ": {" << std::endl; |
|||
child_it->second.write(out, depth+1); |
|||
out << indentation << '}' << std::endl; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
char node::streamSkip(std::istream &in, const std::string &delimiters) { |
|||
char cur; |
|||
|
|||
//Return if the current char is part of delimiters[]
|
|||
while (in >> std::noskipws >> cur) { |
|||
if (delimiters.find_first_of(cur) != delimiters.npos) return cur; |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
char node::streamRead(std::istream &in, std::string &out, const std::string &delimiters) { |
|||
char cur; |
|||
|
|||
//Return if the current char is part of delimiters[]
|
|||
while (in >> std::noskipws >> cur) { |
|||
if (delimiters.find(cur) != delimiters.npos) return cur; |
|||
out += cur; |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
char node::streamRead(std::istream &in, std::string &out, const char delimiter) { |
|||
char cur; |
|||
|
|||
//Return if the current char is delimiter
|
|||
while (in >> std::noskipws >> cur) { |
|||
if (delimiter == cur) return cur; |
|||
out += cur; |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
} |
|||
/*
|
|||
Copyright (c) 2009 Maurice Bos and Nick Overdijk |
|||
All rights reserved. |
|||
|
|||
Redistribution and use in source and binary forms, with or without |
|||
modification, are permitted provided that the following conditions are met: |
|||
* Redistributions of source code must retain the above copyright |
|||
notice, this list of conditions and the following disclaimer. |
|||
* Redistributions in binary form must reproduce the above copyright |
|||
notice, this list of conditions and the following disclaimer in the |
|||
documentation and/or other materials provided with the distribution. |
|||
* The names of the authors may not be used to endorse or promote |
|||
products derived from this software without specific prior written |
|||
permission. |
|||
|
|||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY |
|||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY |
|||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|||
|
|||
- Maurice Bos (maurice@bosbyte.nl) |
|||
- Nick Overdijk (nick@dotsimplicity.net) |
|||
|
|||
*/ |
|||
|
|||
#include <iostream> |
|||
#include <fstream> |
|||
#include <map> |
|||
#include <string> |
|||
#include <typeinfo> |
|||
|
|||
#include "stf.hpp" |
|||
|
|||
namespace stfu { |
|||
|
|||
std::ostream& operator<< (std::ostream& out, const node& root) { |
|||
root.write(out); |
|||
return out; |
|||
} |
|||
|
|||
bool operator<< (const char* filename, const node& root) { |
|||
return root.write(filename); |
|||
} |
|||
|
|||
bool operator<< (std::ofstream& out, const node& root) { |
|||
return root.write(out); |
|||
} |
|||
|
|||
bool operator>> (std::istream& in, node& root) { |
|||
return root.read(in); |
|||
} |
|||
|
|||
bool operator>> (const char* filename, node& root) { |
|||
return root.read(filename); |
|||
} |
|||
|
|||
const std::string& node::getValue(const std::string& name, size_t index) const throw(std::out_of_range) { |
|||
return get_indexed<std::string, std::string>(values, name, index); |
|||
} |
|||
|
|||
/*Function is const, but shouldn't be called on const objects since it returns a nonconst-reference to a member*/ |
|||
std::string& node::getValue(const std::string& name, size_t index) throw(std::out_of_range) { |
|||
return get_indexed<std::string, std::string>(values, name, index); |
|||
} |
|||
|
|||
std::string& node::addValue(const std::string& name) { |
|||
return values.insert(std::pair<std::string, std::string>(name, std::string()))->second; |
|||
} |
|||
|
|||
std::string& node::value(const std::string& name, size_t index) { |
|||
try { |
|||
return getValue(name, index); |
|||
} catch(std::out_of_range& e) { |
|||
//it doesn't exist: create it
|
|||
return addValue(name); |
|||
} |
|||
} |
|||
|
|||
void node::removeValue(const std::string& name, size_t index) throw(std::out_of_range) { |
|||
values.erase(get_indexed_it(values, name, index)); |
|||
return; |
|||
} |
|||
|
|||
void node::renameValue(const std::string& oldName, const std::string& newName, size_t index) { |
|||
addValue(newName) = value(oldName, index); |
|||
removeValue(oldName, index); |
|||
} |
|||
|
|||
|
|||
const node& node::getChild(const std::string& name, size_t index) const throw(std::out_of_range) { |
|||
return get_indexed<std::string, node>(children, name, index); |
|||
} |
|||
|
|||
node& node::getChild(const std::string& name, size_t index) throw(std::out_of_range) { |
|||
return get_indexed<std::string, node>(children, name, index); |
|||
} |
|||
|
|||
node& node::addChild(const std::string& name) { |
|||
return children.insert(std::pair<std::string, node>(name, node()))->second; |
|||
} |
|||
|
|||
node& node::addChild(const std::string& name, node& newNode) { |
|||
return children.insert(std::pair<std::string, node>(name, newNode))->second; |
|||
} |
|||
|
|||
node& node::child(const std::string& name, size_t index) { |
|||
//if there's no such child, add one
|
|||
try { |
|||
return getChild(name, index); |
|||
} catch(std::out_of_range& e) { |
|||
//it doesn't exist: create it
|
|||
return addChild(name); |
|||
} |
|||
} |
|||
|
|||
void node::renameChild(const std::string& oldName, const std::string& newName, size_t index) { |
|||
node copy = child(oldName, index); |
|||
removeChild(oldName, index); |
|||
addChild(newName) = copy; |
|||
} |
|||
|
|||
void node::removeChild(const std::string& name, size_t index) throw(std::out_of_range) { |
|||
children.erase(get_indexed_it(children, name, index)); |
|||
return; |
|||
} |
|||
|
|||
bool node::read(const char* filename) { |
|||
std::ifstream f(filename); |
|||
|
|||
if(!f.good()) return false; |
|||
|
|||
bool success = read(f); |
|||
f.close(); |
|||
|
|||
return success; |
|||
} |
|||
|
|||
bool node::read(std::istream& in) { |
|||
while(1) { |
|||
in >> std::ws; //Skip whitespace
|
|||
|
|||
//if end of node is reached, return
|
|||
if(in.peek() == '}') { |
|||
in.ignore(); |
|||
return true; |
|||
} |
|||
|
|||
if(in.eof()) { |
|||
return true; //End of the file is reached
|
|||
} |
|||
|
|||
std::string name; |
|||
char type; // '{' or '"'
|
|||
streamRead(in, name, ':'); //Read name (all chars before ':')
|
|||
type = streamSkip(in,"\"{"); //Skip everything until '{' or '"'
|
|||
|
|||
switch(type) { |
|||
|
|||
//in case of value
|
|||
case '"': { |
|||
std::string value; |
|||
while(1) { |
|||
if(streamRead(in, value, '"') == 0) { //Read to the closing-"
|
|||
return false; |
|||
} |
|||
if(in.peek() == '"') { |
|||
in.ignore(); |
|||
value += '"'; |
|||
continue; |
|||
} else { |
|||
break; |
|||
} |
|||
} |
|||
this->values.insert(std::pair<std::string,std::string>(name, value)); |
|||
break; |
|||
} |
|||
|
|||
//in case of child
|
|||
case '{': { |
|||
node sub; |
|||
if(!sub.read(in)) { //Recursively read the subnode
|
|||
return false; |
|||
} |
|||
this->children.insert(std::pair<std::string,node>(name,sub)); |
|||
break; |
|||
} |
|||
|
|||
default: |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/*Writes to a file using it's overloaded self*/ |
|||
bool node::write(const char* filename) const { |
|||
std::ofstream f(filename); |
|||
|
|||
if(!f.good()) { |
|||
return false; |
|||
} |
|||
|
|||
bool success = write(f); |
|||
f.close(); |
|||
|
|||
return success; |
|||
} |
|||
|
|||
// TODO (Nick#1#): Make write() not put unnamed values on a new line, children are okay.
|
|||
bool node::write(std::ostream& out, size_t depth, std::string indent) const { |
|||
std::string indentation; |
|||
for(size_t i = 0; i < depth; i++) { |
|||
indentation += indent; |
|||
} |
|||
|
|||
for(std::multimap<std::string, std::string>::const_iterator value_it = values.begin(); value_it != values.end(); value_it++) { |
|||
//Escape all the '"' by adding a second '"'
|
|||
std::string value(value_it->second); |
|||
size_t found = value.find('"'); |
|||
|
|||
//while there are more ", insert second "s
|
|||
while(found != value.npos) { |
|||
value.insert(found, 1, '"'); |
|||
found = value.find('"', found+2); |
|||
} |
|||
out << indentation << value_it->first << ": \"" << value << '"' << std::endl; |
|||
} |
|||
|
|||
for(std::multimap<std::string, node>::const_iterator child_it = children.begin(); child_it != children.end(); child_it++) { |
|||
out << indentation << child_it->first << ": {" << std::endl; |
|||
child_it->second.write(out, depth+1); |
|||
out << indentation << '}' << std::endl; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
char node::streamSkip(std::istream& in, const std::string& delimiters) { |
|||
char cur; |
|||
|
|||
//Return if the current char is part of delimiters[]
|
|||
while(in >> std::noskipws >> cur) { |
|||
if(delimiters.find_first_of(cur) != delimiters.npos) return cur; |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
char node::streamRead(std::istream& in, std::string& out, const std::string& delimiters) { |
|||
char cur; |
|||
|
|||
//Return if the current char is part of delimiters[]
|
|||
while(in >> std::noskipws >> cur) { |
|||
if(delimiters.find(cur) != delimiters.npos) return cur; |
|||
out += cur; |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
char node::streamRead(std::istream& in, std::string& out, const char delimiter) { |
|||
char cur; |
|||
|
|||
//Return if the current char is delimiter
|
|||
while(in >> std::noskipws >> cur) { |
|||
if(delimiter == cur) return cur; |
|||
out += cur; |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
} |
|||
|
@ -1,359 +1,359 @@ |
|||
/*
|
|||
Copyright (c) 2009 Maurice Bos and Nick Overdijk |
|||
All rights reserved. |
|||
|
|||
Redistribution and use in source and binary forms, with or without |
|||
modification, are permitted provided that the following conditions are met: |
|||
* Redistributions of source code must retain the above copyright |
|||
notice, this list of conditions and the following disclaimer. |
|||
* Redistributions in binary form must reproduce the above copyright |
|||
notice, this list of conditions and the following disclaimer in the |
|||
documentation and/or other materials provided with the distribution. |
|||
* The names of the authors may not be used to endorse or promote |
|||
products derived from this software without specific prior written |
|||
permission. |
|||
|
|||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY |
|||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY |
|||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|||
|
|||
- Maurice Bos (maurice@bosbyte.nl) |
|||
- Nick Overdijk (nick@dotsimplicity.net) |
|||
|
|||
*/ |
|||
|
|||
#include <fstream> |
|||
#include <string> |
|||
#include <sstream> |
|||
#include <map> |
|||
#include <stdexcept> |
|||
|
|||
#ifndef STFU_HPP |
|||
#define STFU_HPP |
|||
|
|||
namespace stfu { |
|||
|
|||
const static std::string not_found("search->No such child/value"); |
|||
|
|||
/*! \class node
|
|||
* \brief A node in an STF tree. |
|||
* \author Maurice Bos |
|||
* \author Nick Overdijk |
|||
* \version 1.0 |
|||
* \date 2009-04-25 |
|||
* |
|||
* When you read an STF file through a node (with read() for example), this node will be the root node, without a name. See the examples for more information. |
|||
*/ |
|||
class node { |
|||
|
|||
/** Overloaded ostream's operator<< */ |
|||
friend std::ostream &operator<< (std::ostream &out, const node &root); |
|||
|
|||
/** Returns whether it was succesful or not*/ |
|||
friend bool operator<< (std::ofstream &out, const node &root); |
|||
|
|||
/** Acts like write(), but looks like this: "filename" << node */ |
|||
friend bool operator<< (const char *filename, const node &root); |
|||
|
|||
/** Overloaded istream's operator>> */ |
|||
friend bool operator>> (std::istream &in, node &root); |
|||
|
|||
/** Acts like read(), but looks like this: "filename" >> node */ |
|||
friend bool operator>> (const char *filename, node &root); |
|||
|
|||
public: |
|||
//@{
|
|||
/** The values and children belonging to this node. To add, remove, do whatever: you CAN use these variables directly. To use indexing, use the member functions below*/ |
|||
std::multimap<std::string, std::string> values; |
|||
std::multimap<std::string, node> children; |
|||
//@}
|
|||
|
|||
/**
|
|||
Clears the whole node recursively. |
|||
*/ |
|||
void clear() { |
|||
values.clear(); |
|||
children.clear(); |
|||
} |
|||
/**
|
|||
Gets the std::string value from a variable |
|||
\param name The name of the value you wish to retrieve |
|||
\param index If there are more values with the same name, they are indexed. Here you can supply its indexnumber. |
|||
\return The retrieved value |
|||
*/ |
|||
std::string &value(const std::string &name, size_t index = 0); |
|||
|
|||
/**
|
|||
Same as value(), but for unnamed values |
|||
\note same as value("", index) |
|||
\param index If there are more unnamed values, they are indexed. Here you can supply its indexnumber. |
|||
\return Same as value |
|||
*/ |
|||
std::string &value(size_t index){ |
|||
return value("", index); |
|||
} |
|||
|
|||
/**
|
|||
Creates and adds a value. |
|||
\param name The name of the value to be created |
|||
\return A reference to the value of the created value. |
|||
*/ |
|||
std::string &addValue(const std::string &name = ""); |
|||
|
|||
/**
|
|||
Const function for const objects to get a value. It's NOT possible to call value() on constant objects for value() isn't const. |
|||
\param name Name of the value to be retrieved |
|||
\param index If there are > 1 values with the same name, they are indexed. Here you can supply an indexnumber. |
|||
\return Returns a const std::string& to the value of value with the name and index specified |
|||
*/ |
|||
const std::string &getValue(const std::string &name, size_t index) const throw (std::out_of_range); |
|||
|
|||
/**
|
|||
Same as getValue() const, but for unnamed values |
|||
\note same as getValue("", index) const |
|||
\param index If there are > 1 unnamed values, they are indexed. Here you can supply an indexnumber. |
|||
\return Returns a const std::string& to the value of value with the name and index specified |
|||
*/ |
|||
const std::string &getValue(size_t index) const throw (std::out_of_range){ |
|||
return getValue("", index); |
|||
} |
|||
|
|||
/**
|
|||
Same as getValue() const, but for non-const objects. The returned std::string& can safely be modified. |
|||
\param name Name of the value to be retrieved |
|||
\param index If there are > 1 values with the same name, they are indexed. Here you can supply an indexnumber. |
|||
\return Returns a std::string& to the value of value with the name and index specified |
|||
*/ |
|||
std::string &getValue(const std::string &name, size_t index = 0) throw (std::out_of_range); |
|||
|
|||
/**
|
|||
Same as getValue(), but for unnamed values |
|||
\note same as getValue("", index) |
|||
\param index If there are > 1 unnamed values, they are indexed. Here you can supply an indexnumber. |
|||
\return Returns a std::string& to the value of value with the name and index specified |
|||
*/ |
|||
std::string &getValue(size_t index) throw (std::out_of_range){ |
|||
return getValue("", index); |
|||
} |
|||
|
|||
/**
|
|||
Removes a value. Surprise huh? |
|||
\param name Name of the value to be removed |
|||
\param index If there are > 1 values with the same name, they are indexed. Here you can supply an indexnumber. |
|||
*/ |
|||
void removeValue(const std::string &name, size_t index = 0) throw (std::out_of_range); |
|||
|
|||
/**
|
|||
Removes an unnamed value. |
|||
\note same as removeValue("", index); |
|||
\param index If there are > 1 unnamed values, they are indexed. Here you can supply an indexnumber. |
|||
*/ |
|||
void removeValue(size_t index) throw (std::out_of_range){ |
|||
removeValue("", index); |
|||
} |
|||
|
|||
/**
|
|||
Renames a value. |
|||
\param oldName Name of the value to be renamed |
|||
\param newName The name that the oldName-value should have |
|||
\param index If there are > 1 values with the same name, they are indexed. Here you can supply an indexnumber. |
|||
*/ |
|||
void renameValue(const std::string &oldName, const std::string &newName, size_t index = 0); |
|||
|
|||
/**
|
|||
Changes, adds or retrieves node |
|||
\param name The name of the child you wish to retrieve, change or add. |
|||
\param index If there are > 1 children with the same name, they are indexed. Here you can supply an indexnumber. |
|||
\return The retrieved node |
|||
|
|||
If this index number is > the number of variables with that name, a new variable with that name is created with index = current number of same name variables + 1. |
|||
So say you have 4 variables named "tree", you call child("tree", 10), another tree gets made with index 5, NOT 10. |
|||
*/ |
|||
node &child(const std::string &name, size_t index = 0); |
|||
|
|||
/**
|
|||
Same as child(), but for unnamed children. |
|||
\note same as child("", index) |
|||
\param index If there are > 1 unnamed children, they are indexed. Here you can supply an indexnumber. |
|||
\return The retrieved node |
|||
*/ |
|||
node &child(size_t index = 0){ |
|||
return child("", index); |
|||
} |
|||
|
|||
/**
|
|||
Guarranteed to add a child |
|||
\param name Name for the child |
|||
\return A reference to the created node |
|||
*/ |
|||
node &addChild(const std::string &name = ""); |
|||
|
|||
/**
|
|||
As addChild(name), but copies data from newChild as well. |
|||
\param name Name for the child |
|||
\param newChild Data to copy from the child. |
|||
\return A reference to the created node |
|||
*/ |
|||
node &addChild(const std::string &name, node &newChild); |
|||
|
|||
/**
|
|||
As addChild(name, newChild), but without name, for unnamed children |
|||
\note same as addChild("", newChild); |
|||
\param newChild Data to copy from the child. |
|||
\return A reference to the created node |
|||
*/ |
|||
node &addChild(node &newChild){ |
|||
return addChild("", newChild); |
|||
} |
|||
|
|||
/**
|
|||
Const function for const objects to get a node. It's NOT possible to call child() for this, for child() isn't const. |
|||
\param name Name of the child to be retrieved |
|||
\param index If there are > 1 children with the same name, they are indexed. Here you can supply an indexnumber. |
|||
\return Returns a const node& to the node with the name and index specified |
|||
*/ |
|||
const node &getChild(const std::string &name, size_t index = 0) const throw (std::out_of_range); |
|||
|
|||
/**
|
|||
Const function for const objects to get an unnamed const node&. |
|||
\note same as getChild("", index) const; |
|||
\param index If there are > 1 unnamed children, they are indexed. Here you can supply an indexnumber. |
|||
\return Returns a const node& to the node with the name and index specified |
|||
*/ |
|||
const node &getChild(size_t index = 0) const throw (std::out_of_range){ |
|||
return getChild("", index); |
|||
} |
|||
|
|||
/**
|
|||
Same as getChild() const, but for non-const objects. The returned child & can be modified |
|||
\param name Name of the child to be retrieved |
|||
\param index If there are > 1 children with the same name, they are indexed. Here you can supply an indexnumber. |
|||
\return Returns a node& to the node with the name and index specified |
|||
*/ |
|||
node &getChild(const std::string &name, size_t index = 0) throw (std::out_of_range); |
|||
|
|||
/**
|
|||
Same as getChild() const, but for non-const objects. |
|||
\note same as getChild("", index); |
|||
\param index If there are > 1 unnamed children, they are indexed. Here you can supply an indexnumber. |
|||
\return Returns a node& to the node with the name and index specified |
|||
*/ |
|||
node &getChild(size_t index = 0) throw (std::out_of_range){ |
|||
return getChild("", index); |
|||
} |
|||
|
|||
/**
|
|||
Removes a child. Surprise huh? |
|||
\param name Name of the child to be removed |
|||
\param index If there are > 1 children with the same name, they are indexed. Here you can supply an indexnumber. |
|||
*/ |
|||
void removeChild(const std::string &name, size_t index = 0) throw (std::out_of_range); |
|||
|
|||
/**
|
|||
As removeChild() for unnamed children. |
|||
\param index If there are > 1 unnamed children, they are indexed. Here you can supply an indexnumber. |
|||
*/ |
|||
void removeChild(size_t index = 0) throw (std::out_of_range){ |
|||
removeChild("", index); |
|||
} |
|||
|
|||
/**
|
|||
Renames a child. |
|||
\param oldName Name of the child to be renamed |
|||
\param newName The name that the oldName-child should have |
|||
\param index If there are > 1 children with the same name, they are indexed. Here you can supply an indexnumber. |
|||
*/ |
|||
void renameChild(const std::string &oldName, const std::string &newName, size_t index = 0); |
|||
|
|||
|
|||
/**
|
|||
Reads the STF from an istream |
|||
|
|||
\return Returns whether it was succesful |
|||
*/ |
|||
bool read(std::istream &in); |
|||
|
|||
/**
|
|||
Reads the STF from a file |
|||
|
|||
\return Returns whether it was succesful |
|||
*/ |
|||
bool read(const char *filename); |
|||
|
|||
/**
|
|||
Writes the STF to an ostream with optional indentation |
|||
\param out ostream to write to |
|||
\param depth how much indentation to start with |
|||
\param indent What std::string to use as indenation |
|||
\return Returns whether it was succesful |
|||
*/ |
|||
bool write(std::ostream &out, size_t depth = 0, std::string indent = "\t") const; |
|||
|
|||
/**
|
|||
Writes to a file. Simply first opens a file and passes that ostream to itself. |
|||
\param filename File to write to |
|||
\return Returns whether it was succesful |
|||
*/ |
|||
bool write(const char *filename) const; |
|||
|
|||
private: |
|||
char streamRead(std::istream &in,std::string &out, const std::string &delim); |
|||
char streamRead(std::istream &in, std::string &out, const char delim); |
|||
char streamSkip(std::istream &in, const std::string &delim); |
|||
|
|||
/*
|
|||
returns a T2&, not a const T2&. The functions getValue/getChild make sure this will be done correctly for const objects |
|||
this function can NOT use get_indexed_it, because that function can't be const: |
|||
const_iterators can not be transformed into iterators, and the iterator is needed for erase(), which wants an iterator. |
|||
*/ |
|||
template <typename T1, typename T2> |
|||
T2& get_indexed(const std::multimap<T1, T2> &container, const T1 &key, size_t index = 0) const throw (std::out_of_range) { |
|||
size_t count = container.count(key); |
|||
|
|||
if (count != 0 && count-1 >= index) { |
|||
typename std::multimap<T1, T2>::const_iterator it = container.find(key); |
|||
while (index--) it++; |
|||
return const_cast<T2&>(it->second); |
|||
} else { |
|||
throw std::out_of_range((std::string)"get_indexed->"+"Element " + key + "doesn't exist!"); |
|||
} |
|||
} |
|||
|
|||
// template <typename T1, typename T2>
|
|||
// typename multimap<T1, T2>::iterator get_indexed_it(multimap<T1, T2> &container, const T1 &key, size_t index = 0) throw (out_of_range) {
|
|||
// size_t count = container.count(key);
|
|||
//
|
|||
// if (count != 0 && count-1 >= index) {
|
|||
// typename multimap<T1, T2>::iterator it = container.find(key);
|
|||
// while (index--) it++;
|
|||
// return it;
|
|||
// } else {
|
|||
// throw out_of_range((std::string)"get_indexed_it->"+"Element " + key + "doesn't exist!");
|
|||
// }
|
|||
// }
|
|||
|
|||
template <typename Container, typename T> |
|||
typename Container::iterator get_indexed_it(Container& container, const T& key, size_t index = 0) |
|||
throw (std::out_of_range) { |
|||
typename Container::iterator it = container.find(key); |
|||
while (index-- && it != container.end() && it->first==key) it++; |
|||
if (it == container.end()) throw std::out_of_range("get_indexed_it(Container&, const T&, size_t)"); |
|||
return it; |
|||
} |
|||
}; |
|||
|
|||
typedef std::pair<std::string, std::string> value; |
|||
typedef std::pair<std::string, node> child; |
|||
|
|||
typedef std::multimap<std::string, std::string>::iterator valueiterator; |
|||
typedef std::multimap<std::string, node>::iterator childiterator; |
|||
} |
|||
|
|||
#endif // STFU_HPP
|
|||
/*
|
|||
Copyright (c) 2009 Maurice Bos and Nick Overdijk |
|||
All rights reserved. |
|||
|
|||
Redistribution and use in source and binary forms, with or without |
|||
modification, are permitted provided that the following conditions are met: |
|||
* Redistributions of source code must retain the above copyright |
|||
notice, this list of conditions and the following disclaimer. |
|||
* Redistributions in binary form must reproduce the above copyright |
|||
notice, this list of conditions and the following disclaimer in the |
|||
documentation and/or other materials provided with the distribution. |
|||
* The names of the authors may not be used to endorse or promote |
|||
products derived from this software without specific prior written |
|||
permission. |
|||
|
|||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY |
|||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY |
|||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|||
|
|||
- Maurice Bos (maurice@bosbyte.nl) |
|||
- Nick Overdijk (nick@dotsimplicity.net) |
|||
|
|||
*/ |
|||
|
|||
#include <fstream> |
|||
#include <string> |
|||
#include <sstream> |
|||
#include <map> |
|||
#include <stdexcept> |
|||
|
|||
#ifndef STFU_HPP |
|||
#define STFU_HPP |
|||
|
|||
namespace stfu { |
|||
|
|||
const static std::string not_found("search->No such child/value"); |
|||
|
|||
/*! \class node
|
|||
* \brief A node in an STF tree. |
|||
* \author Maurice Bos |
|||
* \author Nick Overdijk |
|||
* \version 1.0 |
|||
* \date 2009-04-25 |
|||
* |
|||
* When you read an STF file through a node (with read() for example), this node will be the root node, without a name. See the examples for more information. |
|||
*/ |
|||
class node { |
|||
|
|||
/** Overloaded ostream's operator<< */ |
|||
friend std::ostream& operator<< (std::ostream& out, const node& root); |
|||
|
|||
/** Returns whether it was succesful or not*/ |
|||
friend bool operator<< (std::ofstream& out, const node& root); |
|||
|
|||
/** Acts like write(), but looks like this: "filename" << node */ |
|||
friend bool operator<< (const char* filename, const node& root); |
|||
|
|||
/** Overloaded istream's operator>> */ |
|||
friend bool operator>> (std::istream& in, node& root); |
|||
|
|||
/** Acts like read(), but looks like this: "filename" >> node */ |
|||
friend bool operator>> (const char* filename, node& root); |
|||
|
|||
public: |
|||
//@{
|
|||
/** The values and children belonging to this node. To add, remove, do whatever: you CAN use these variables directly. To use indexing, use the member functions below*/ |
|||
std::multimap<std::string, std::string> values; |
|||
std::multimap<std::string, node> children; |
|||
//@}
|
|||
|
|||
/**
|
|||
Clears the whole node recursively. |
|||
*/ |
|||
void clear() { |
|||
values.clear(); |
|||
children.clear(); |
|||
} |
|||
/**
|
|||
Gets the std::string value from a variable |
|||
\param name The name of the value you wish to retrieve |
|||
\param index If there are more values with the same name, they are indexed. Here you can supply its indexnumber. |
|||
\return The retrieved value |
|||
*/ |
|||
std::string& value(const std::string& name, size_t index = 0); |
|||
|
|||
/**
|
|||
Same as value(), but for unnamed values |
|||
\note same as value("", index) |
|||
\param index If there are more unnamed values, they are indexed. Here you can supply its indexnumber. |
|||
\return Same as value |
|||
*/ |
|||
std::string& value(size_t index) { |
|||
return value("", index); |
|||
} |
|||
|
|||
/**
|
|||
Creates and adds a value. |
|||
\param name The name of the value to be created |
|||
\return A reference to the value of the created value. |
|||
*/ |
|||
std::string& addValue(const std::string& name = ""); |
|||
|
|||
/**
|
|||
Const function for const objects to get a value. It's NOT possible to call value() on constant objects for value() isn't const. |
|||
\param name Name of the value to be retrieved |
|||
\param index If there are > 1 values with the same name, they are indexed. Here you can supply an indexnumber. |
|||
\return Returns a const std::string& to the value of value with the name and index specified |
|||
*/ |
|||
const std::string& getValue(const std::string& name, size_t index) const throw(std::out_of_range); |
|||
|
|||
/**
|
|||
Same as getValue() const, but for unnamed values |
|||
\note same as getValue("", index) const |
|||
\param index If there are > 1 unnamed values, they are indexed. Here you can supply an indexnumber. |
|||
\return Returns a const std::string& to the value of value with the name and index specified |
|||
*/ |
|||
const std::string& getValue(size_t index) const throw(std::out_of_range) { |
|||
return getValue("", index); |
|||
} |
|||
|
|||
/**
|
|||
Same as getValue() const, but for non-const objects. The returned std::string& can safely be modified. |
|||
\param name Name of the value to be retrieved |
|||
\param index If there are > 1 values with the same name, they are indexed. Here you can supply an indexnumber. |
|||
\return Returns a std::string& to the value of value with the name and index specified |
|||
*/ |
|||
std::string& getValue(const std::string& name, size_t index = 0) throw(std::out_of_range); |
|||
|
|||
/**
|
|||
Same as getValue(), but for unnamed values |
|||
\note same as getValue("", index) |
|||
\param index If there are > 1 unnamed values, they are indexed. Here you can supply an indexnumber. |
|||
\return Returns a std::string& to the value of value with the name and index specified |
|||
*/ |
|||
std::string& getValue(size_t index) throw(std::out_of_range) { |
|||
return getValue("", index); |
|||
} |
|||
|
|||
/**
|
|||
Removes a value. Surprise huh? |
|||
\param name Name of the value to be removed |
|||
\param index If there are > 1 values with the same name, they are indexed. Here you can supply an indexnumber. |
|||
*/ |
|||
void removeValue(const std::string& name, size_t index = 0) throw(std::out_of_range); |
|||
|
|||
/**
|
|||
Removes an unnamed value. |
|||
\note same as removeValue("", index); |
|||
\param index If there are > 1 unnamed values, they are indexed. Here you can supply an indexnumber. |
|||
*/ |
|||
void removeValue(size_t index) throw(std::out_of_range) { |
|||
removeValue("", index); |
|||
} |
|||
|
|||
/**
|
|||
Renames a value. |
|||
\param oldName Name of the value to be renamed |
|||
\param newName The name that the oldName-value should have |
|||
\param index If there are > 1 values with the same name, they are indexed. Here you can supply an indexnumber. |
|||
*/ |
|||
void renameValue(const std::string& oldName, const std::string& newName, size_t index = 0); |
|||
|
|||
/**
|
|||
Changes, adds or retrieves node |
|||
\param name The name of the child you wish to retrieve, change or add. |
|||
\param index If there are > 1 children with the same name, they are indexed. Here you can supply an indexnumber. |
|||
\return The retrieved node |
|||
|
|||
If this index number is > the number of variables with that name, a new variable with that name is created with index = current number of same name variables + 1. |
|||
So say you have 4 variables named "tree", you call child("tree", 10), another tree gets made with index 5, NOT 10. |
|||
*/ |
|||
node& child(const std::string& name, size_t index = 0); |
|||
|
|||
/**
|
|||
Same as child(), but for unnamed children. |
|||
\note same as child("", index) |
|||
\param index If there are > 1 unnamed children, they are indexed. Here you can supply an indexnumber. |
|||
\return The retrieved node |
|||
*/ |
|||
node& child(size_t index = 0) { |
|||
return child("", index); |
|||
} |
|||
|
|||
/**
|
|||
Guarranteed to add a child |
|||
\param name Name for the child |
|||
\return A reference to the created node |
|||
*/ |
|||
node& addChild(const std::string& name = ""); |
|||
|
|||
/**
|
|||
As addChild(name), but copies data from newChild as well. |
|||
\param name Name for the child |
|||
\param newChild Data to copy from the child. |
|||
\return A reference to the created node |
|||
*/ |
|||
node& addChild(const std::string& name, node& newChild); |
|||
|
|||
/**
|
|||
As addChild(name, newChild), but without name, for unnamed children |
|||
\note same as addChild("", newChild); |
|||
\param newChild Data to copy from the child. |
|||
\return A reference to the created node |
|||
*/ |
|||
node& addChild(node& newChild) { |
|||
return addChild("", newChild); |
|||
} |
|||
|
|||
/**
|
|||
Const function for const objects to get a node. It's NOT possible to call child() for this, for child() isn't const. |
|||
\param name Name of the child to be retrieved |
|||
\param index If there are > 1 children with the same name, they are indexed. Here you can supply an indexnumber. |
|||
\return Returns a const node& to the node with the name and index specified |
|||
*/ |
|||
const node& getChild(const std::string& name, size_t index = 0) const throw(std::out_of_range); |
|||
|
|||
/**
|
|||
Const function for const objects to get an unnamed const node&. |
|||
\note same as getChild("", index) const; |
|||
\param index If there are > 1 unnamed children, they are indexed. Here you can supply an indexnumber. |
|||
\return Returns a const node& to the node with the name and index specified |
|||
*/ |
|||
const node& getChild(size_t index = 0) const throw(std::out_of_range) { |
|||
return getChild("", index); |
|||
} |
|||
|
|||
/**
|
|||
Same as getChild() const, but for non-const objects. The returned child & can be modified |
|||
\param name Name of the child to be retrieved |
|||
\param index If there are > 1 children with the same name, they are indexed. Here you can supply an indexnumber. |
|||
\return Returns a node& to the node with the name and index specified |
|||
*/ |
|||
node& getChild(const std::string& name, size_t index = 0) throw(std::out_of_range); |
|||
|
|||
/**
|
|||
Same as getChild() const, but for non-const objects. |
|||
\note same as getChild("", index); |
|||
\param index If there are > 1 unnamed children, they are indexed. Here you can supply an indexnumber. |
|||
\return Returns a node& to the node with the name and index specified |
|||
*/ |
|||
node& getChild(size_t index = 0) throw(std::out_of_range) { |
|||
return getChild("", index); |
|||
} |
|||
|
|||
/**
|
|||
Removes a child. Surprise huh? |
|||
\param name Name of the child to be removed |
|||
\param index If there are > 1 children with the same name, they are indexed. Here you can supply an indexnumber. |
|||
*/ |
|||
void removeChild(const std::string& name, size_t index = 0) throw(std::out_of_range); |
|||
|
|||
/**
|
|||
As removeChild() for unnamed children. |
|||
\param index If there are > 1 unnamed children, they are indexed. Here you can supply an indexnumber. |
|||
*/ |
|||
void removeChild(size_t index = 0) throw(std::out_of_range) { |
|||
removeChild("", index); |
|||
} |
|||
|
|||
/**
|
|||
Renames a child. |
|||
\param oldName Name of the child to be renamed |
|||
\param newName The name that the oldName-child should have |
|||
\param index If there are > 1 children with the same name, they are indexed. Here you can supply an indexnumber. |
|||
*/ |
|||
void renameChild(const std::string& oldName, const std::string& newName, size_t index = 0); |
|||
|
|||
|
|||
/**
|
|||
Reads the STF from an istream |
|||
|
|||
\return Returns whether it was succesful |
|||
*/ |
|||
bool read(std::istream& in); |
|||
|
|||
/**
|
|||
Reads the STF from a file |
|||
|
|||
\return Returns whether it was succesful |
|||
*/ |
|||
bool read(const char* filename); |
|||
|
|||
/**
|
|||
Writes the STF to an ostream with optional indentation |
|||
\param out ostream to write to |
|||
\param depth how much indentation to start with |
|||
\param indent What std::string to use as indenation |
|||
\return Returns whether it was succesful |
|||
*/ |
|||
bool write(std::ostream& out, size_t depth = 0, std::string indent = "\t") const; |
|||
|
|||
/**
|
|||
Writes to a file. Simply first opens a file and passes that ostream to itself. |
|||
\param filename File to write to |
|||
\return Returns whether it was succesful |
|||
*/ |
|||
bool write(const char* filename) const; |
|||
|
|||
private: |
|||
char streamRead(std::istream& in,std::string& out, const std::string& delim); |
|||
char streamRead(std::istream& in, std::string& out, const char delim); |
|||
char streamSkip(std::istream& in, const std::string& delim); |
|||
|
|||
/*
|
|||
returns a T2&, not a const T2&. The functions getValue/getChild make sure this will be done correctly for const objects |
|||
this function can NOT use get_indexed_it, because that function can't be const: |
|||
const_iterators can not be transformed into iterators, and the iterator is needed for erase(), which wants an iterator. |
|||
*/ |
|||
template <typename T1, typename T2> |
|||
T2& get_indexed(const std::multimap<T1, T2> &container, const T1& key, size_t index = 0) const throw(std::out_of_range) { |
|||
size_t count = container.count(key); |
|||
|
|||
if(count != 0 && count-1 >= index) { |
|||
typename std::multimap<T1, T2>::const_iterator it = container.find(key); |
|||
while(index--) it++; |
|||
return const_cast<T2&>(it->second); |
|||
} else { |
|||
throw std::out_of_range((std::string)"get_indexed->"+"Element " + key + "doesn't exist!"); |
|||
} |
|||
} |
|||
|
|||
// template <typename T1, typename T2>
|
|||
// typename multimap<T1, T2>::iterator get_indexed_it(multimap<T1, T2> &container, const T1 &key, size_t index = 0) throw (out_of_range) {
|
|||
// size_t count = container.count(key);
|
|||
//
|
|||
// if (count != 0 && count-1 >= index) {
|
|||
// typename multimap<T1, T2>::iterator it = container.find(key);
|
|||
// while (index--) it++;
|
|||
// return it;
|
|||
// } else {
|
|||
// throw out_of_range((std::string)"get_indexed_it->"+"Element " + key + "doesn't exist!");
|
|||
// }
|
|||
// }
|
|||
|
|||
template <typename Container, typename T> |
|||
typename Container::iterator get_indexed_it(Container& container, const T& key, size_t index = 0) |
|||
throw(std::out_of_range) { |
|||
typename Container::iterator it = container.find(key); |
|||
while(index-- && it != container.end() && it->first==key) it++; |
|||
if(it == container.end()) throw std::out_of_range("get_indexed_it(Container&, const T&, size_t)"); |
|||
return it; |
|||
} |
|||
}; |
|||
|
|||
typedef std::pair<std::string, std::string> value; |
|||
typedef std::pair<std::string, node> child; |
|||
|
|||
typedef std::multimap<std::string, std::string>::iterator valueiterator; |
|||
typedef std::multimap<std::string, node>::iterator childiterator; |
|||
} |
|||
|
|||
#endif // STFU_HPP
|
|||
|
Reference in new issue