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