removed using namespace from stfu, moved the file reading part to a place where it belongs
This commit is contained in:
parent
afa05183a9
commit
a5d7513e56
7 changed files with 438 additions and 363 deletions
|
@ -6,18 +6,9 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "stfu/stf.hpp"
|
#include "stfu/stf.hpp"
|
||||||
|
|
||||||
|
#include "AttractorKernel.hpp"
|
||||||
#include "Projector.hpp"
|
#include "Projector.hpp"
|
||||||
|
|
||||||
#include "AttractorKernel.hpp"
|
|
||||||
#include "kernels/Logistic.hpp"
|
|
||||||
#include "kernels/Lorenz3D.hpp"
|
|
||||||
#include "kernels/Polynomial.hpp"
|
|
||||||
#include "kernels/PolynomialA3D.hpp"
|
|
||||||
#include "kernels/Unravel3D.hpp"
|
|
||||||
|
|
||||||
Attractor::Attractor() {
|
|
||||||
myAttractor = new Lorenz3D();
|
|
||||||
}
|
|
||||||
|
|
||||||
Attractor::Attractor(const char* const fileName) {
|
Attractor::Attractor(const char* const fileName) {
|
||||||
// opening file
|
// opening file
|
||||||
|
@ -25,69 +16,10 @@ Attractor::Attractor(const char* const fileName) {
|
||||||
|
|
||||||
stfu::node system;
|
stfu::node system;
|
||||||
system.read(fileName);
|
system.read(fileName);
|
||||||
stfu::node attractor = system.getChild("attractor");
|
stfu::node attractor = system.getChild("AttractorKernel");
|
||||||
|
|
||||||
|
myAttractor = AttractorKernel::createAttractorKernel(attractor);
|
||||||
|
|
||||||
// reading basic stuff
|
|
||||||
std::string attractorType = attractor.getValue("type");
|
|
||||||
const std::string attractorDimension = attractor.getValue("dimensions");
|
|
||||||
|
|
||||||
for ( unsigned int i = 0; attractorType[i] != '\0'; i++ ) {
|
|
||||||
attractorType[i] = tolower(attractorType[i]);
|
|
||||||
}
|
|
||||||
const unsigned int dimension = atoi(attractorDimension.c_str());
|
|
||||||
|
|
||||||
std::cout << " Formula: " << attractorType << std::endl;
|
|
||||||
std::cout << " Dimensions: " << dimension << std::endl;
|
|
||||||
|
|
||||||
|
|
||||||
// depending on type, make the formula object
|
|
||||||
if ( attractorType == "lorenz" ){
|
|
||||||
if ( dimension == 3 ) {
|
|
||||||
myAttractor = new Lorenz3D();
|
|
||||||
} else {
|
|
||||||
std::cerr << "something wrong";
|
|
||||||
exit(37);
|
|
||||||
}
|
|
||||||
} else if ( attractorType == "polynomial" ) {
|
|
||||||
const std::string attractorOrde = attractor.getValue("orde");
|
|
||||||
const unsigned int orde = atoi(attractorOrde.c_str());
|
|
||||||
std::cout << " Orde: " << orde << std::endl;
|
|
||||||
myAttractor = new Polynomial(dimension, orde);
|
|
||||||
|
|
||||||
} else if ( attractorType == "polynomial a" ) {
|
|
||||||
if ( dimension == 3 ) {
|
|
||||||
myAttractor = new PolynomialA3D();
|
|
||||||
} else {
|
|
||||||
std::cerr << "something wrong";
|
|
||||||
exit(37);
|
|
||||||
}
|
|
||||||
} else if ( attractorType == "logistic" ) {
|
|
||||||
myAttractor = new Logistic(dimension);
|
|
||||||
|
|
||||||
} else if ( attractorType == "unravel" ) {
|
|
||||||
if ( dimension == 3 ) {
|
|
||||||
myAttractor = new Unravel3D();
|
|
||||||
} else {
|
|
||||||
std::cerr << "somtheing wrong";
|
|
||||||
exit(37);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
std::cout << "'" << attractorType << "' not recognized" << std::endl;
|
|
||||||
exit(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// read parameters
|
|
||||||
const unsigned int numberOfParameters = myAttractor->getNumberOfParameters();
|
|
||||||
|
|
||||||
for ( unsigned int i = 0; i < numberOfParameters; i++ ) {
|
|
||||||
stfu::node attractorParameters = attractor.getChild("parameters");
|
|
||||||
(*myAttractor)[i] = atof(attractorParameters.getValue(i).c_str());
|
|
||||||
std::cout << " Parameter " << i << " set to " << (*myAttractor)[i] << ", ";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << std::endl << " Reading file complete" << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Attractor::~Attractor(){
|
Attractor::~Attractor(){
|
||||||
|
|
|
@ -16,7 +16,6 @@ public:
|
||||||
// should be private really
|
// should be private really
|
||||||
std::vector<Projector *> projectors;
|
std::vector<Projector *> projectors;
|
||||||
|
|
||||||
Attractor();
|
|
||||||
Attractor(const char* const filename);
|
Attractor(const char* const filename);
|
||||||
~Attractor();
|
~Attractor();
|
||||||
|
|
||||||
|
|
|
@ -82,3 +82,80 @@ unsigned int AttractorKernel::getDimension() const{
|
||||||
return dimension;
|
return dimension;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark factory function
|
||||||
|
|
||||||
|
#include "AttractorKernel.hpp"
|
||||||
|
#include "kernels/Logistic.hpp"
|
||||||
|
#include "kernels/Lorenz3D.hpp"
|
||||||
|
#include "kernels/Polynomial.hpp"
|
||||||
|
#include "kernels/PolynomialA3D.hpp"
|
||||||
|
#include "kernels/Unravel3D.hpp"
|
||||||
|
|
||||||
|
AttractorKernel * AttractorKernel::createAttractorKernel(stfu::node& attractor){
|
||||||
|
|
||||||
|
AttractorKernel * myAttractor = NULL;
|
||||||
|
|
||||||
|
// reading basic stuff
|
||||||
|
const std::string attractorType = attractor.getValue("type");
|
||||||
|
const std::string attractorDimension = attractor.getValue("dimensions");
|
||||||
|
|
||||||
|
// for ( unsigned int i = 0; attractorType[i] != '\0'; i++ ) {
|
||||||
|
// attractorType[i] = tolower(attractorType[i]);
|
||||||
|
// }
|
||||||
|
const unsigned int dimension = atoi(attractorDimension.c_str());
|
||||||
|
|
||||||
|
std::cout << " Formula: " << attractorType << std::endl;
|
||||||
|
std::cout << " Dimensions: " << dimension << std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
// depending on type, make the formula object
|
||||||
|
if ( attractorType == "lorenz" ){
|
||||||
|
if ( dimension == 3 ) {
|
||||||
|
myAttractor = new Lorenz3D();
|
||||||
|
} else {
|
||||||
|
std::cerr << "something wrong";
|
||||||
|
exit(37);
|
||||||
|
}
|
||||||
|
} else if ( attractorType == "polynomial" ) {
|
||||||
|
const std::string attractorOrde = attractor.getValue("orde");
|
||||||
|
const unsigned int orde = atoi(attractorOrde.c_str());
|
||||||
|
std::cout << " Orde: " << orde << std::endl;
|
||||||
|
myAttractor = new Polynomial(dimension, orde);
|
||||||
|
|
||||||
|
} else if ( attractorType == "polynomial a" ) {
|
||||||
|
if ( dimension == 3 ) {
|
||||||
|
myAttractor = new PolynomialA3D();
|
||||||
|
} else {
|
||||||
|
std::cerr << "something wrong";
|
||||||
|
exit(37);
|
||||||
|
}
|
||||||
|
} else if ( attractorType == "logistic" ) {
|
||||||
|
myAttractor = new Logistic(dimension);
|
||||||
|
} else if ( attractorType == "unravel" ) {
|
||||||
|
if ( dimension == 3 ) {
|
||||||
|
myAttractor = new Unravel3D();
|
||||||
|
} else {
|
||||||
|
std::cerr << "something wrong";
|
||||||
|
exit(37);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::cout << "'" << attractorType << "' not recognized" << std::endl;
|
||||||
|
exit(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// read parameters
|
||||||
|
const unsigned int numberOfParameters = myAttractor->getNumberOfParameters();
|
||||||
|
|
||||||
|
for ( unsigned int i = 0; i < numberOfParameters; i++ ) {
|
||||||
|
stfu::node attractorParameters = attractor.getChild("parameters");
|
||||||
|
(*myAttractor)[i] = atof(attractorParameters.getValue(i).c_str());
|
||||||
|
std::cout << " Parameter " << i << " set to " << (*myAttractor)[i] << ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << std::endl << " Reading file complete" << std::endl;
|
||||||
|
|
||||||
|
return myAttractor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
#ifndef ATTRACTORKERNEL_HPP
|
#ifndef ATTRACTORKERNEL_HPP
|
||||||
#define ATTRACTORKERNEL_HPP
|
#define ATTRACTORKERNEL_HPP
|
||||||
|
|
||||||
|
#include "stfu/stf.hpp"
|
||||||
|
|
||||||
/*
|
|
||||||
ABC
|
|
||||||
*/
|
|
||||||
class AttractorKernel {
|
class AttractorKernel {
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -38,15 +36,15 @@ public:
|
||||||
|
|
||||||
// getter functions for teh resulta (can't be used as setters)
|
// getter functions for teh resulta (can't be used as setters)
|
||||||
double const * vector() const;
|
double const * vector() const;
|
||||||
// double const * vector() const{
|
|
||||||
// return vectorNew;
|
|
||||||
// }
|
|
||||||
double const * previousVector() const;
|
double const * previousVector() const;
|
||||||
unsigned int getDimension() const;
|
unsigned int getDimension() const;
|
||||||
|
|
||||||
// dtor, should be virtual for subclasses to be deleted
|
// dtor, should be virtual for subclasses to be deleted
|
||||||
virtual ~AttractorKernel();
|
virtual ~AttractorKernel();
|
||||||
|
|
||||||
|
// factory function
|
||||||
|
static AttractorKernel * createAttractorKernel(stfu::node& attractorKernel);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ATTRACTORKERNEL_HPP
|
#endif // ATTRACTORKERNEL_HPP
|
||||||
|
|
69
attractors/testUnravelNew.stf
Normal file
69
attractors/testUnravelNew.stf
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
|
||||||
|
input: "AttractorKernel"
|
||||||
|
output: "Canvas"
|
||||||
|
iterations: "100000"
|
||||||
|
|
||||||
|
AttractorKernel: {
|
||||||
|
type: "unravel"
|
||||||
|
dimensions: "3"
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
{
|
||||||
|
:"-0.78"
|
||||||
|
:"2.042"
|
||||||
|
:"1.22"
|
||||||
|
:"-1.267"
|
||||||
|
:"1.37"
|
||||||
|
:"2.3"
|
||||||
|
:"-2.195"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
projections: Applied in order they appear {
|
||||||
|
:{
|
||||||
|
type: "auto center"
|
||||||
|
}
|
||||||
|
:{
|
||||||
|
type: "lineair map"
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
{
|
||||||
|
:{ :"1" :"0" :"0" }
|
||||||
|
:{ :"0" :"1" :"0" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Canvas: {
|
||||||
|
type: "2D canvas"
|
||||||
|
output: "png"
|
||||||
|
|
||||||
|
width: "6400"
|
||||||
|
height: "6400"
|
||||||
|
colors: "3"
|
||||||
|
|
||||||
|
imageConversion: description how to show the abstract canvas classe
|
||||||
|
{
|
||||||
|
colorMatrix: desciribing lineair map from canvas colors to RGB colorspace
|
||||||
|
{
|
||||||
|
:{ :"1" :"0" :"0" }
|
||||||
|
:{ :"0" :"1" :"0" }
|
||||||
|
:{ :"0" :"0" :"1" }
|
||||||
|
}
|
||||||
|
|
||||||
|
vibrancy: "0"
|
||||||
|
gamma: "-2.5"
|
||||||
|
exposure: "3"
|
||||||
|
}
|
||||||
|
|
||||||
|
pngFile: png options
|
||||||
|
{
|
||||||
|
fileName: leave empty to autogenerate filename
|
||||||
|
=> ""
|
||||||
|
|
||||||
|
compression: "9"
|
||||||
|
author: "Joshua Moerman"
|
||||||
|
title: "Unravel"
|
||||||
|
description: "A unravel-type attractor made with AwesomeAttractor"
|
||||||
|
}
|
||||||
|
}
|
469
stfu/stf.cpp
469
stfu/stf.cpp
|
@ -37,240 +37,239 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "stf.hpp"
|
#include "stf.hpp"
|
||||||
|
|
||||||
using namespace std;
|
namespace stfu{
|
||||||
using stfu::node;
|
|
||||||
using stfu::child;
|
std::ostream &operator<< (std::ostream &out, const node &root) {
|
||||||
using stfu::value;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
ostream &stfu::operator<< (ostream &out, const node &root) {
|
|
||||||
root.write(out);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool stfu:: operator<< (const char *filename, const node &root){
|
|
||||||
return root.write(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool stfu::operator<< (ofstream &out, const node &root) {
|
|
||||||
return root.write(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool stfu::operator>> (istream &in, node &root) {
|
|
||||||
return root.read(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool stfu::operator>> (const char *filename, node &root) {
|
|
||||||
return root.read(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
const string &node::getValue(const string &name, size_t index) const throw (out_of_range) {
|
|
||||||
return get_indexed<string, string>(values, name, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Function is const, but shouldn't be called on const objects since it returns a nonconst-reference to a member*/
|
|
||||||
string &node::getValue(const string &name, size_t index) throw (out_of_range) {
|
|
||||||
return get_indexed<string, string>(values, name, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
string &node::addValue(const string &name) {
|
|
||||||
return values.insert(pair<string, string>(name, string()))->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
string &node::value(const string &name, size_t index) {
|
|
||||||
try {
|
|
||||||
return getValue(name, index);
|
|
||||||
} catch (out_of_range &e) {
|
|
||||||
//it doesn't exist: create it
|
|
||||||
return addValue(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void node::removeValue(const string &name, size_t index) throw (out_of_range) {
|
|
||||||
values.erase(get_indexed_it(values, name, index));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void node::renameValue(const string &oldName, const string &newName, size_t index) {
|
|
||||||
addValue(newName) = value(oldName, index);
|
|
||||||
removeValue(oldName, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const node &node::getChild(const string &name, size_t index) const throw (out_of_range) {
|
|
||||||
return get_indexed<string, node>(children, name, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
node &node::getChild(const string &name, size_t index) throw (out_of_range) {
|
|
||||||
return get_indexed<string, node>(children, name, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
node &node::addChild(const string &name) {
|
|
||||||
return children.insert(pair<string, node>(name, node()))->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
node &node::addChild(const string &name, node &newNode) {
|
|
||||||
return children.insert(pair<string, node>(name, newNode))->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
node &node::child(const string &name, size_t index) {
|
|
||||||
//if there's no such child, add one
|
|
||||||
try {
|
|
||||||
return getChild(name, index);
|
|
||||||
} catch (out_of_range &e) {
|
|
||||||
//it doesn't exist: create it
|
|
||||||
return addChild(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void node::renameChild(const string &oldName, const string &newName, size_t index) {
|
|
||||||
node copy = child(oldName, index);
|
|
||||||
removeChild(oldName, index);
|
|
||||||
addChild(newName) = copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
void node::removeChild(const string &name, size_t index) throw (out_of_range) {
|
|
||||||
children.erase(get_indexed_it(children, name, index));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool node::read(const char *filename) {
|
|
||||||
ifstream f(filename);
|
|
||||||
|
|
||||||
if (!f.good()) return false;
|
|
||||||
|
|
||||||
bool success = read(f);
|
|
||||||
f.close();
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool node::read(istream &in) {
|
|
||||||
while (1) {
|
|
||||||
in >> 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
|
|
||||||
}
|
|
||||||
|
|
||||||
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 '"': {
|
|
||||||
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(pair<string,string>(name, value));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//in case of child
|
|
||||||
case '{': {
|
|
||||||
node sub;
|
|
||||||
if (!sub.read(in)) { //Recursively read the subnode
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
this->children.insert(pair<string,node>(name,sub));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Writes to a file using it's overloaded self*/
|
|
||||||
bool node::write(const char *filename) const {
|
|
||||||
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(ostream &out, size_t depth, string indent) const {
|
|
||||||
string indentation;
|
|
||||||
for (size_t i = 0; i < depth; i++) {
|
|
||||||
indentation += indent;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (multimap<string, string>::const_iterator value_it = values.begin(); value_it != values.end(); value_it++) {
|
|
||||||
//Escape all the '"' by adding a second '"'
|
|
||||||
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 << '"' << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (multimap<string, node>::const_iterator child_it = children.begin(); child_it != children.end(); child_it++) {
|
|
||||||
out << indentation << child_it->first << ": {" << endl;
|
|
||||||
child_it->second.write(out, depth+1);
|
|
||||||
out << indentation << '}' << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
char node::streamSkip(istream &in, const string &delimiters) {
|
|
||||||
char cur;
|
|
||||||
|
|
||||||
//Return if the current char is part of delimiters[]
|
|
||||||
while (in >> noskipws >> cur) {
|
|
||||||
if (delimiters.find_first_of(cur) != delimiters.npos) return cur;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char node::streamRead(istream &in, string &out, const string &delimiters) {
|
|
||||||
char cur;
|
|
||||||
|
|
||||||
//Return if the current char is part of delimiters[]
|
|
||||||
while (in >> noskipws >> cur) {
|
|
||||||
if (delimiters.find(cur) != delimiters.npos) return cur;
|
|
||||||
out += cur;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char node::streamRead(istream &in, string &out, const char delimiter) {
|
|
||||||
char cur;
|
|
||||||
|
|
||||||
//Return if the current char is delimiter
|
|
||||||
while (in >> noskipws >> cur) {
|
|
||||||
if (delimiter == cur) return cur;
|
|
||||||
out += cur;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
101
stfu/stf.hpp
101
stfu/stf.hpp
|
@ -39,8 +39,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#define STFU_HPP
|
#define STFU_HPP
|
||||||
|
|
||||||
namespace stfu {
|
namespace stfu {
|
||||||
using namespace std;
|
|
||||||
const static 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.
|
||||||
|
@ -54,16 +54,16 @@ namespace stfu {
|
||||||
class node {
|
class node {
|
||||||
|
|
||||||
/** Overloaded ostream's operator<< */
|
/** Overloaded ostream's operator<< */
|
||||||
friend ostream &operator<< (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<< (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>> (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);
|
||||||
|
@ -71,8 +71,8 @@ namespace stfu {
|
||||||
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*/
|
||||||
multimap<string, string> values;
|
std::multimap<std::string, std::string> values;
|
||||||
multimap<string, node> children;
|
std::multimap<std::string, node> children;
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -83,19 +83,20 @@ namespace stfu {
|
||||||
children.clear();
|
children.clear();
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
Gets the 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
|
||||||
*/
|
*/
|
||||||
string &value(const 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.
\return Same as value
|
\param index If there are more unnamed values, they are indexed. Here you can supply its indexnumber.
|
||||||
|
\return Same as value
|
||||||
*/
|
*/
|
||||||
string &value(size_t index){
|
std::string &value(size_t index){
|
||||||
return value("", index);
|
return value("", index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,41 +105,41 @@ namespace stfu {
|
||||||
\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.
|
||||||
*/
|
*/
|
||||||
string &addValue(const 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 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 string &getValue(const string &name, size_t index) const throw (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 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 string &getValue(size_t index) const throw (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 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 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
|
||||||
*/
|
*/
|
||||||
string &getValue(const string &name, size_t index = 0) throw (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 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
|
||||||
*/
|
*/
|
||||||
string &getValue(size_t index) throw (out_of_range){
|
std::string &getValue(size_t index) throw (std::out_of_range){
|
||||||
return getValue("", index);
|
return getValue("", index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,14 +148,14 @@ namespace stfu {
|
||||||
\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 string &name, size_t index = 0) throw (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 (out_of_range){
|
void removeValue(size_t index) throw (std::out_of_range){
|
||||||
removeValue("", index);
|
removeValue("", index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,7 +165,7 @@ namespace stfu {
|
||||||
\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 string &oldName, const 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
|
||||||
|
@ -175,7 +176,7 @@ namespace stfu {
|
||||||
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 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.
|
||||||
|
@ -192,7 +193,7 @@ namespace stfu {
|
||||||
\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 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.
|
||||||
|
@ -200,7 +201,7 @@ namespace stfu {
|
||||||
\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 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
|
||||||
|
@ -218,7 +219,7 @@ namespace stfu {
|
||||||
\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 string &name, size_t index = 0) const throw (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&.
|
||||||
|
@ -226,7 +227,7 @@ namespace stfu {
|
||||||
\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 (out_of_range){
|
const node &getChild(size_t index = 0) const throw (std::out_of_range){
|
||||||
return getChild("", index);
|
return getChild("", index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,7 +237,7 @@ namespace stfu {
|
||||||
\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 string &name, size_t index = 0) throw (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.
|
||||||
|
@ -244,7 +245,7 @@ namespace stfu {
|
||||||
\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 (out_of_range){
|
node &getChild(size_t index = 0) throw (std::out_of_range){
|
||||||
return getChild("", index);
|
return getChild("", index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,13 +254,13 @@ namespace stfu {
|
||||||
\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 string &name, size_t index = 0) throw (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 (out_of_range){
|
void removeChild(size_t index = 0) throw (std::out_of_range){
|
||||||
removeChild("", index);
|
removeChild("", index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,7 +270,7 @@ namespace stfu {
|
||||||
\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 string &oldName, const string &newName, size_t index = 0);
|
void renameChild(const std::string &oldName, const std::string &newName, size_t index = 0);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -277,7 +278,7 @@ namespace stfu {
|
||||||
|
|
||||||
\return Returns whether it was succesful
|
\return Returns whether it was succesful
|
||||||
*/
|
*/
|
||||||
bool read(istream &in);
|
bool read(std::istream &in);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Reads the STF from a file
|
Reads the STF from a file
|
||||||
|
@ -290,10 +291,10 @@ namespace stfu {
|
||||||
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 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(ostream &out, size_t depth = 0, 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.
|
||||||
|
@ -303,9 +304,9 @@ namespace stfu {
|
||||||
bool write(const char *filename) const;
|
bool write(const char *filename) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char streamRead(istream &in,string &out, const string &delim);
|
char streamRead(std::istream &in,std::string &out, const std::string &delim);
|
||||||
char streamRead(istream &in, string &out, const char delim);
|
char streamRead(std::istream &in, std::string &out, const char delim);
|
||||||
char streamSkip(istream &in, const 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
|
||||||
|
@ -313,15 +314,15 @@ namespace stfu {
|
||||||
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 multimap<T1, T2> &container, const T1 &key, size_t index = 0) const throw (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 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 out_of_range((string)"get_indexed->"+"Element " + key + "doesn't exist!");
|
throw std::out_of_range((std::string)"get_indexed->"+"Element " + key + "doesn't exist!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,25 +335,25 @@ namespace stfu {
|
||||||
// while (index--) it++;
|
// while (index--) it++;
|
||||||
// return it;
|
// return it;
|
||||||
// } else {
|
// } else {
|
||||||
// throw out_of_range((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 (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 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 pair<string, string> value;
|
typedef std::pair<std::string, std::string> value;
|
||||||
typedef pair<string, node> child;
|
typedef std::pair<std::string, node> child;
|
||||||
|
|
||||||
typedef multimap<string, string>::iterator valueiterator;
|
typedef std::multimap<std::string, std::string>::iterator valueiterator;
|
||||||
typedef multimap<string, node>::iterator childiterator;
|
typedef std::multimap<std::string, node>::iterator childiterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // STFU_HPP
|
#endif // STFU_HPP
|
||||||
|
|
Reference in a new issue