Update of /cvsroot/pure-data/externals/grh/PDContainer/include In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15862/include
Added Files: ContainerBase.h GlobalStuff.h HDeque.h HList.h HMap.h HMultiMap.h HMultiSet.h HPrioQueue.h HQueue.h HSet.h HStack.h HVector.h MapBase.h QueueStack.h SequBase.h SimpleBase.h Log Message: only moving to a new directory
--- NEW FILE: HPrioQueue.h --- // *********************(c)*2004*********************> // -holzilib--holzilib--holzilib--holzilib--holzilib-> // ++++PD-External++by+Georg+Holzmann++grh@gmx.at++++> // // PDContainer: // this is a port of the containers from the C++ STL // (Standard Template Library) // for usage see the documentation and PD help files // for license see readme.txt // // HPriority_Queue.h
#ifndef _h_priority_queue_h__ #define _h_priority_queue_h__
#include "include/QueueStack.h" #include <queue>
using std::priority_queue;
class ElementPrio { public: Element element; float priority;
bool operator< (const ElementPrio &key) const { return (priority < key.priority); } const ElementPrio& operator = (const ElementPrio &src) { priority = src.priority; element = src.element; return (*this); } };
//--------------------------------------------------- /* this is the class of the priority_queue */ class HPrioQueue : public QueueStack< priority_queue<ElementPrio>, int > {
private:
/* Copy Construction is not allowed */ HPrioQueue(const HPrioQueue &src) { }
/* assignement operator is not allowed */ const HPrioQueue& operator = (const HPrioQueue&) { return *this; }
public:
/* Standard Constructor * no namespace */ HPrioQueue() { dataname_ = "h_priority_queue"; }
/* Constructor * with a namespace */ HPrioQueue(string h_namespace) { dataname_ = "h_priority_queue"; setNamespace(h_namespace); }
/* Destructor */ virtual ~HPrioQueue() { }
/* inserts an element in the container */ virtual void push(float prio, Element value) { ElementPrio data; data.priority = prio; data.element = value;
data_[h_namespace_].push(data); }
/* returns the element from the top of * the stack */ virtual Element top() const { return data_[h_namespace_].top().element; } };
#endif //_h_priority_queue_h__
--- NEW FILE: HList.h --- // *********************(c)*2004*********************> // -holzilib--holzilib--holzilib--holzilib--holzilib-> // ++++PD-External++by+Georg+Holzmann++grh@gmx.at++++> // // PDContainer: // this is a port of the containers from the C++ STL // (Standard Template Library) // for usage see the documentation and PD help files // for license see readme.txt // // HList.h
#ifndef _h_list_h__ #define _h_list_h__
#include "include/SimpleBase.h" #include <list>
using std::list;
//--------------------------------------------------- /* this is the class of the list */ class HList : public SimpleBase< list<Element>, list<Element>::iterator > { protected: /* this integer holds the current position of the * iterator, because accessing the iterator directly * from PD is very buggy... * (maybe I'll change this !) */ int i_pos_;
/* the internal iterator, you can navigate * through the container with it */ list<Element>::iterator iter_;
private:
/* Copy Construction is not allowed */ HList(const HList &src) { }
/* assignement operator is not allowed */ const HList& operator = (const HList&) { return *this; }
public:
/* Standard Constructor * no namespace */ HList() { dataname_ = "h_list"; i_pos_=0; }
/* Constructor * with a namespace */ HList(string h_namespace) { dataname_ = "h_list"; setNamespace(h_namespace); i_pos_=0; }
/* Destructor */ virtual ~HList() { }
/* inserts an element at the end of * the container */ virtual void pushBack(Element value) { data_[h_namespace_].push_back(value); }
/* removes the element from the end of * the container */ virtual void popBack() { data_[h_namespace_].pop_back(); }
/* inserts an element at the end of * the container */ virtual void pushFront(Element value) { data_[h_namespace_].push_front(value); }
/* removes the element from the end of * the container */ virtual void popFront() { data_[h_namespace_].pop_front(); }
/* returns the last element */ virtual Element &back() const { return data_[h_namespace_].back(); }
/* returns the first element */ virtual Element &front() const { return data_[h_namespace_].front(); }
/* inserts an element at the current * iterator position */ virtual void insert(Element value) { makeIterator(); data_[h_namespace_].insert(iter_, value); i_pos_++; }
/* overrides the element at the current * iterator position */ virtual void modify(Element value) { makeIterator(); *iter_=value; }
/* gives back the element at the current * iterator position */ virtual Element get() { makeIterator();
// key was not found if iterator is pointing to the end if(iter_ == data_[h_namespace_].end()) throw "h_list, get: Element not found !";
return *iter_; }
/* removes all elements with that value */ virtual void remove(Element value) { data_[h_namespace_].remove(value); }
/* removes an element at the current * iterator position */ virtual void del() { makeIterator();
if(data_[h_namespace_].size() == 0) return;
if(iter_ == data_[h_namespace_].end()) { post("h_list, delete: not possible, go back by 1 (iterator points to the element after the end) !!!"); return; }
data_[h_namespace_].erase(iter_); }
/* get the size of the sequence */ virtual int getSize() const { return data_[h_namespace_].size(); }
/* set current iterator position */ virtual void setIterPos(int position) { i_pos_ = position; }
/* get the current iterator position */ virtual int getIterPos() { makeIterator(); return i_pos_; }
/* sets the iterator position the the begin * of the list */ virtual void begin() { i_pos_ = 0; }
/* sets the iterator position the the end * of the list */ virtual void end() { i_pos_ = data_[h_namespace_].size(); }
/* increases the iterator position by one */ virtual void next() { i_pos_++; }
/* decreases the iterator position by one */ virtual void last() { i_pos_--; }
/* removes all but the first element in every * consecutive group of equal elements */ virtual void unique() { data_[h_namespace_].unique(); }
/* reverses the order of elements in the list */ virtual void reverse() { data_[h_namespace_].reverse(); }
/* sorts the list according to operator< */ virtual void sort() { data_[h_namespace_].sort(); }
/* reads from file */ virtual bool readFromFile(string filename);
private: /* generates the current iterator position */ void makeIterator() { if(i_pos_<0) i_pos_=0;
if((unsigned)i_pos_ > data_[h_namespace_].size()) i_pos_=data_[h_namespace_].size();
// this is a hack to make the iterator, I'll change this ! iter_=data_[h_namespace_].begin(); for(int i = 0; i<i_pos_; i++) iter_++; } };
#endif //_h_list_h__
--- NEW FILE: HMultiMap.h --- // *********************(c)*2004*********************> // -holzilib--holzilib--holzilib--holzilib--holzilib-> // ++++PD-External++by+Georg+Holzmann++grh@gmx.at++++> // // PDContainer: // this is a port of the containers from the C++ STL // (Standard Template Library) // for usage see the documentation and PD help files // for license see readme.txt // // HMultiMap.h
#ifndef _h_multi_map_h__ #define _h_multi_map_h__
#include "include/MapBase.h"
using std::multimap;
//--------------------------------------------------- /* this is the class of the map */ class HMultiMap : public MapBase< multimap<Element,Element>, multimap<Element,Element>::iterator > {
private:
/* Copy Construction is not allowed */ HMultiMap(const HMultiMap &src) { }
/* assignement operator is not allowed */ const HMultiMap& operator = (const HMultiMap&) { return *this; }
public:
/* Constructor * no namespace */ HMultiMap() { dataname_ = "h_multimap"; }
/* Constructor * with a namespace */ HMultiMap(string h_namespace) { dataname_ = "h_multimap"; setNamespace(h_namespace); }
/* Destructor */ virtual ~HMultiMap() { }
/* Add a key-value pair */ virtual void add(Element key, Element value) { this->data_[this->h_namespace_].insert(std::pair<Element,Element>(key,value)); }
/* Get the Nr. of values from the specific Key */ virtual int getNr(Element &key) const { return data_[h_namespace_].count(key); }
/* Get a value from the specific Key with the index number * index starts with 0 */ virtual Element &get(Element &key, int index) const; };
#endif // _h_multi_map_h__
--- NEW FILE: HMultiSet.h --- // *********************(c)*2004*********************> // -holzilib--holzilib--holzilib--holzilib--holzilib-> // ++++PD-External++by+Georg+Holzmann++grh@gmx.at++++> // // PDContainer: // this is a port of the containers from the C++ STL // (Standard Template Library) // for usage see the documentation and PD help files // for license see readme.txt // // HMultiSet.h
#ifndef _h_multi_set_h__ #define _h_multi_set_h__
#include "include/SimpleBase.h" #include <set>
using std::multiset;
//--------------------------------------------------- /* this is the class of the set */ class HMultiSet : public SimpleBase< multiset<Element>, multiset<Element>::iterator > {
private:
/* Copy Construction is not allowed */ HMultiSet(const HMultiSet &src) { }
/* assignement operator is not allowed */ const HMultiSet& operator = (const HMultiSet&) { return *this; }
public:
/* Constructor * no namespace */ HMultiSet() { dataname_ = "h_multiset"; }
/* Constructor * with a namespace */ HMultiSet(string h_namespace) { dataname_ = "h_multiset"; setNamespace(h_namespace); }
/* Destructor */ virtual ~HMultiSet() { }
/* add an element */ virtual void add(Element key) { data_[h_namespace_].insert(key); }
/* look if the element is set * returns how often this element was set * 0 if it isn't set */ virtual int get(const Element &key) const { return data_[h_namespace_].count(key); }
/* removes an element from the container */ virtual void remove(const Element &key) const { data_[h_namespace_].erase(key); } };
#endif // _h_multi_set_h__
--- NEW FILE: HStack.h --- // *********************(c)*2004*********************> // -holzilib--holzilib--holzilib--holzilib--holzilib-> // ++++PD-External++by+Georg+Holzmann++grh@gmx.at++++> // // PDContainer: // this is a port of the containers from the C++ STL // (Standard Template Library) // for usage see the documentation and PD help files // for license see readme.txt // // HStack.h
#ifndef _h_stack_h__ #define _h_stack_h__
#include "include/QueueStack.h" #include <stack>
using std::stack;
//--------------------------------------------------- /* this is the class of the stack */ class HStack : public QueueStack< stack<Element>, int > {
private:
/* Copy Construction is not allowed */ HStack(const HStack &src) { }
/* assignement operator is not allowed */ const HStack& operator = (const HStack&) { return *this; }
public:
/* Standard Constructor * no namespace */ HStack() { dataname_ = "h_stack"; }
/* Constructor * with a namespace */ HStack(string h_namespace) { dataname_ = "h_stack"; setNamespace(h_namespace); }
/* Destructor */ virtual ~HStack() { }
/* inserts an element in the container */ virtual void push(Element value) { data_[h_namespace_].push(value); }
/* returns the element from the top of * the stack */ virtual Element &top() const { return data_[h_namespace_].top(); } };
#endif //_h_stack_h__
--- NEW FILE: ContainerBase.h --- // *********************(c)*2004*********************> // -holzilib--holzilib--holzilib--holzilib--holzilib-> // ++++PD-External++by+Georg+Holzmann++grh@gmx.at++++> // // PDContainer: // this is a port of the containers from the C++ STL // (Standard Template Library) // for usage see the documentation and PD help files // for license see readme.txt // // ContainerBase.h
#ifndef _container_base_h___ #define _container_base_h___
#include "include/GlobalStuff.h" #include <map>
using std::map;
//--------------------------------------------------- /* this is the base class of all the containers */ template <class ContainerType, class ContTypeIterator> class ContainerBase { protected:
/* this is the static container with all the datas * the string is the namespace of the Container */ static map<string,ContainerType> data_;
/* holds the number of the current namespace * (the string of the namespace is stored in the map above) */ string h_namespace_;
/* this string is the name of the datatype * (e.g. h_set, h_map, ...) */ string dataname_;
private:
/* Copy Construction is not allowed */ ContainerBase(const ContainerBase<ContainerType,ContTypeIterator> &src) { }
/* assignement operator is not allowed */ const ContainerBase<ContainerType,ContTypeIterator>& operator = (const ContainerBase<ContainerType,ContTypeIterator>&) { }
public:
/* Standard Constructor * no namespace */ ContainerBase() { }
/* Destructor */ virtual ~ContainerBase() { }
/* sets the namespace variable */ void setNamespace(string h_namespace) { h_namespace_ = h_namespace; //ContainerType container; //data_.insert(std::pair<string,ContainerType>(h_namespace_,container)); }
/* get the namespace string */ string getNamespace() const { return h_namespace_; }
/* prints out the help text */ virtual void help();
/* clears all the data of the current namespaces * in all objects from the same container */ virtual void clearNamespace() { data_.erase(h_namespace_); }
/* clears all the data of the current container * ( in all namespaces !!!!! ) * so be carefull !!! */ virtual void clearAll() { data_.clear(); }
/* get the size of the container */ virtual int getSize() const { return data_[h_namespace_].size(); } };
//--------------------------------------------------- /* defines the static members */ template<class ContainerType, class ContTypeIterator> map<string,ContainerType> ContainerBase<ContainerType,ContTypeIterator>::data_;
//--------------------------------------------------- /* prints out the help text */ template<class ContainerType, class ContTypeIterator> void ContainerBase<ContainerType,ContTypeIterator>::help() { post("\nPD-Container, Version: "PDC_VERSION""); post("object: %s",dataname_.c_str()); post("------------------------------------------"); post("this is an implementation of the container"); post("objects from the Standard Template"); post("Library (STL) of C++"); post("for documentation see the help patches"); post("(by Georg Holzmann grh@mur.at, 2004-2005)"); post("------------------------------------------\n"); }
#endif //_container_base_h___
--- NEW FILE: MapBase.h --- // *********************(c)*2004*********************> // -holzilib--holzilib--holzilib--holzilib--holzilib-> // ++++PD-External++by+Georg+Holzmann++grh@gmx.at++++> // // PDContainer: // this is a port of the containers from the C++ STL // (Standard Template Library) // for usage see the documentation and PD help files // for license see readme.txt // // MapBase.h
#ifndef _map_base_h__ #define _map_base_h__
#include "include/ContainerBase.h"
//--------------------------------------------------- /* this is the base class of map and multimap */ template <class ContainerType, class ContTypeIterator> class MapBase : public ContainerBase<ContainerType,ContTypeIterator> {
private:
/* Copy Construction is not allowed */ MapBase(const MapBase<ContainerType,ContTypeIterator> &src) { }
/* assignement operator is not allowed */ const MapBase<ContainerType,ContTypeIterator>& operator = (const MapBase<ContainerType,ContTypeIterator>&) { }
public:
/* Standard Constructor * no namespace */ MapBase() { }
/* Destructor */ virtual ~MapBase() { };
/* Add a key-value pair */ virtual void add(Element key, Element value) { // first remove old entry, then insert this->data_[this->h_namespace_].erase(key); this->data_[this->h_namespace_].insert(std::pair<Element,Element>(key,value)); }
/* Get a value from the specific Key */ virtual Element &get(const Element &key) const { ContTypeIterator iter = this->data_[this->h_namespace_].find(key);
// key was not found if iterator is pointing to the end if(iter == this->data_[this->h_namespace_].end()) throw "PDContainer, get: Element not found !";
return (*iter).second; }
/* removes a pair with this key */ virtual void remove(const Element &key) { if(!this->data_[this->h_namespace_].erase(key)) throw "PDContainer, remove: Element not found !"; }
/* prints all the data of the current namespace to the console */ virtual void printAll();
/* saves all the data of the current namespace to a file * Fileformat: * <key_atom_type1> <key_atom1> ... - <data_atom_type1> <data_atom1> ... * e.g.: * f 1 f 2 - f 4 * s foo f 12.34234 - f 3 f 5 s gege * types: s=symbol, f=float * ATTENTION: if the file exists, all the old data of * the file is lost * returns true on success */ virtual bool saveToFile(string filename);
/* saves all the data of the current namespace to a XML file * ATTENTION: if the file exists, all the old data of * the file is lost * returns true on success */ virtual bool saveToFileXML(string filename);
/* reads from an input file and adds the data to * the current namespace * Fileformat: see saveToFile * returns true on success */ virtual bool readFromFile(string filename);
/* reads from an XML input file and adds the data to * the current namespace * returns true on success */ virtual bool readFromFileXML(string filename); };
//---------------------------------------------------- /* prints all the data of the current namespace to the console */ template<class ContainerType, class ContTypeIterator> void MapBase<ContainerType,ContTypeIterator>::printAll() { ContTypeIterator iter = this->data_[this->h_namespace_].begin();
post("\n%s: printing namespace %s",this->dataname_.c_str(),this->h_namespace_.c_str()); post("--------------------------------------------------");
bool data_here = false; while(iter != this->data_[this->h_namespace_].end()) { ostringstream output("");
// Key: Element key = (*iter).first; if (key.getLength() > 1) // list { output << "list "; for (int i=0; i < key.getLength(); i++) { if (key.getAtom()[i].a_type == A_FLOAT) output << key.getAtom()[i].a_w.w_float << " "; if (key.getAtom()[i].a_type == A_SYMBOL) output << key.getAtom()[i].a_w.w_symbol->s_name << " "; if (key.getAtom()[i].a_type == A_POINTER) output << "(gpointer)" << key.getAtom()[i].a_w.w_gpointer << " "; } } else // no list { if (key.getAtom()[0].a_type == A_FLOAT) output << "float " << key.getAtom()[0].a_w.w_float << " "; if (key.getAtom()[0].a_type == A_SYMBOL) output << "symbol " << key.getAtom()[0].a_w.w_symbol->s_name << " "; if (key.getAtom()[0].a_type == A_POINTER) output << "pointer " << key.getAtom()[0].a_w.w_gpointer << " "; }
// Value: output << " -- "; Element el = (*iter).second; if (el.getLength() > 1) // list { output << "list "; for (int i=0; i < el.getLength(); i++) { if (el.getAtom()[i].a_type == A_FLOAT) output << el.getAtom()[i].a_w.w_float << " "; if (el.getAtom()[i].a_type == A_SYMBOL) output << el.getAtom()[i].a_w.w_symbol->s_name << " "; if (el.getAtom()[i].a_type == A_POINTER) output << "(gpointer)" << el.getAtom()[i].a_w.w_gpointer << " "; } } else // no list { if (el.getAtom()[0].a_type == A_FLOAT) // hier segfault nach get !!! output << "float " << el.getAtom()[0].a_w.w_float << " "; if (el.getAtom()[0].a_type == A_SYMBOL) output << "symbol " << el.getAtom()[0].a_w.w_symbol->s_name << " "; if (el.getAtom()[0].a_type == A_POINTER) output << "pointer " << el.getAtom()[0].a_w.w_gpointer << " "; }
post("%s",output.str().c_str()); data_here = true; iter++; } if(!data_here) post("no data in current namespace!"); post("--------------------------------------------------"); }
//---------------------------------------------------- /* saves all the data of the current namespace to a file * Fileformat: * <key_atom_type1> <key_atom1> ... - <data_atom_type1> <data_atom1> ... * e.g.: * f 1 f 2 - f 4 * s foo f 12.34234 - f 3 f 5 s gege * types: s=symbol, f=float * ATTENTION: if the file exists, all the old data of * the file is lost * returns true on success */ template<class ContainerType, class ContTypeIterator> bool MapBase<ContainerType,ContTypeIterator>::saveToFile(string filename) { ofstream outfile; ContTypeIterator iter = this->data_[this->h_namespace_].begin();
outfile.open(filename.c_str());
if(!outfile) return false;
while(iter != this->data_[this->h_namespace_].end()) { Element key = (*iter).first; Element el = (*iter).second; bool have_pointer = false;
// check if there is a pointer and then don't store it for (int i=0; i < key.getLength(); i++) if (key.getAtom()[i].a_type == A_POINTER) have_pointer=true; for (int i=0; i < el.getLength(); i++) if (el.getAtom()[i].a_type == A_POINTER) have_pointer=true;
if(have_pointer) { post("PDContainer: will not store pointers !!!"); iter++; } else { // add key: for (int i=0; i < key.getLength(); i++) { if (key.getAtom()[i].a_type == A_FLOAT) outfile << "f " << key.getAtom()[i].a_w.w_float << " "; if (key.getAtom()[i].a_type == A_SYMBOL) outfile << "s " << key.getAtom()[i].a_w.w_symbol->s_name << " "; }
outfile << "- ";
// add Value: for (int i=0; i < el.getLength(); i++) { if (el.getAtom()[i].a_type == A_FLOAT) outfile << "f " << el.getAtom()[i].a_w.w_float << " "; if (el.getAtom()[i].a_type == A_SYMBOL) outfile << "s " << el.getAtom()[i].a_w.w_symbol->s_name << " "; }
outfile << endl; iter++; } }
outfile.close();
return true; }
//---------------------------------------------------- /* saves all the data of the current namespace to a XML file * ATTENTION: if the file exists, all the old data of * the file is lost * returns true on success */ template<class ContainerType, class ContTypeIterator> bool MapBase<ContainerType,ContTypeIterator>::saveToFileXML(string filename) { ostringstream output(""); ContTypeIterator iter = this->data_[this->h_namespace_].begin();
// add XML Header: output << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n" << "<!DOCTYPE PDContainer SYSTEM " << "\"http://grh.mur.at/software/pdcontainer_multi.dtd\">\n" << "<PDContainer type="" << this->dataname_ << "">\n";
while(iter != this->data_[this->h_namespace_].end()) { Element key((*iter).first); Element el((*iter).second); bool have_pointer = false;
// check if there is a pointer and then don't store it for (int i=0; i < key.getLength(); i++) if (key.getAtom()[i].a_type == A_POINTER) have_pointer=true; for (int i=0; i < el.getLength(); i++) if (el.getAtom()[i].a_type == A_POINTER) have_pointer=true;
if(have_pointer) { post("PDContainer: will not store pointers !!!"); iter++; } else {
output << "<element>\n";
// add Key: output << "<key>\n";
for (int i=0; i < key.getLength(); i++) { if (key.getAtom()[i].a_type == A_FLOAT) output << "<f> " << key.getAtom()[i].a_w.w_float << " </f>\n"; if (key.getAtom()[i].a_type == A_SYMBOL) output << "<s>" << key.getAtom()[i].a_w.w_symbol->s_name << " </s>\n"; }
output << "</key>\n";
// add Value: output << "<value>\n";
for (int i=0; i < el.getLength(); i++) { if (el.getAtom()[i].a_type == A_FLOAT) output << "<f> " << el.getAtom()[i].a_w.w_float << " </f>\n"; if (el.getAtom()[i].a_type == A_SYMBOL) output << "<s>" << el.getAtom()[i].a_w.w_symbol->s_name << " </s>\n"; }
output << "</value>\n";
output << "</element>\n";
iter++;
} }
output << "</PDContainer>\n";
// now write to file: TiXmlDocument outfile( filename.c_str() ); outfile.Parse( output.str().c_str() );
if ( outfile.Error() ) return false;
outfile.SaveFile();
return true; }
//---------------------------------------------------- /* reads the data from the file into the current * namespace * Fileformat: see saveToFile * returns true on success */ template<class ContainerType, class ContTypeIterator> bool MapBase<ContainerType,ContTypeIterator>::readFromFile(string filename) { ifstream infile; infile.open(filename.c_str());
if(!infile) return false;
Element key; Element el;
string line; bool go_on = false; char type; string symbol; t_float number; int key_count, val_count;
while (getline(infile, line)) { // first parse the instream, to get the number of atoms // (= length of the elements)
istringstream instream(line); ostringstream key_str(""); ostringstream value_str("");
// Key: go_on = false; key_count = 0; while(!go_on) { instream >> type; if (type == 's') { key_count++; instream >> symbol; key_str << "s " << symbol; } if (type == 'f') { key_count++; instream >> number; key_str << "f " << number; } if (type == '-') go_on = true; key_str << " "; }
// Value: go_on = false; val_count = 0; while(!go_on) { instream >> type; if (instream.eof()) { go_on = true; break; } if (type == 's') { val_count++; instream >> symbol; value_str << "s " << symbol; } if (type == 'f') { val_count++; instream >> number; value_str << "f " << number; } if (instream.eof()) go_on = true; value_str << " "; }
// now make the key and value objects, parse again the data // into the objects and add them to the container
// Key:
t_atom *key_atom = (t_atom*)getbytes(key_count*sizeof(t_atom)); t_atom *val_atom = (t_atom*)getbytes(val_count*sizeof(t_atom)); if(key_atom == NULL || val_atom == NULL) post("Fatal Error Out Of Memory (%s-readFromFile)",this->dataname_.c_str());
istringstream key_istr(key_str.str()); istringstream value_istr(value_str.str());
for(int i = 0; i < key_count; i++) { key_istr >> type; if (type == 's') { key_istr >> symbol; SETSYMBOL(&key_atom[i],gensym(const_cast<char*>(symbol.c_str()))); } if (type == 'f') { key_istr >> number; SETFLOAT(&key_atom[i],number); } }
for(int i = 0; i < val_count; i++) { value_istr >> type; if (type == 's') { value_istr >> symbol; SETSYMBOL(&val_atom[i],gensym(const_cast<char*>(symbol.c_str()))); } if (type == 'f') { value_istr >> number; SETFLOAT(&val_atom[i],number); } }
key.setAtoms(key_count,key_atom); el.setAtoms(val_count, val_atom); // insert the data this->data_[this->h_namespace_].insert(std::pair<Element,Element>(key,el));
freebytes(key_atom, key_count*sizeof(t_atom)); freebytes(val_atom, val_count*sizeof(t_atom)); }
infile.close();
return true; }
//---------------------------------------------------- /* reads the data from the XML file into the current * namespace * returns true on success */ template<class ContainerType, class ContTypeIterator> bool MapBase<ContainerType,ContTypeIterator>::readFromFileXML(string filename) { TiXmlDocument doc( filename.c_str() );
if( !doc.LoadFile() ) return false;
TiXmlNode *parent = 0; TiXmlElement *child1 = 0; TiXmlElement *child2 = 0; TiXmlElement *child3 = 0;
t_atom *key_atom = 0; t_atom *val_atom = 0; Element key; Element el; t_float f; bool parsed=false;
// Get the <PDContainer> tag and check type parent = doc.FirstChild( "PDContainer" ); if(!parent) return false;
if(!parent->ToElement()) return false; if(!parent->ToElement()->Attribute("type")) { post("readXML: you must specify an attribute type in <PDContainer> !"); return false; }
string type(parent->ToElement()->Attribute("type")); if( type != "h_map" && type != "h_multimap" ) { post("readXML: wrong container type (attribute type in <PDContainer>) !"); return false; }
if( type != this->dataname_ ) post("readXML: importing data from %s!", type.c_str() );
// iterate through all the <element> tags for( child1 = parent->FirstChildElement("element"); child1; child1 = child1->NextSiblingElement("element") ) { // get the <key> tag child2 = child1->FirstChildElement( "key" ); if(!child2) return false;
// get nr of keys and allocate mem for them // (if its a pd list) int key_count = 0; for( child3 = child2->FirstChildElement(); child3; child3 = child3->NextSiblingElement() ) key_count++;
key_atom = (t_atom*)getbytes(key_count*sizeof(t_atom)); if(key_atom == NULL) { post("Fatal Error Out Of Memory (%s-readFromFile)",this->dataname_.c_str()); return false; }
// iterate through all the atoms of <key> key_count = 0; for( child3 = child2->FirstChildElement(); child3; child3 = child3->NextSiblingElement() ) { string tag(child3->Value());
if(!child3->FirstChild()) continue; istringstream in(child3->FirstChild()->Value());
if(tag == "f" || tag == "float") { in >> f; SETFLOAT(&key_atom[key_count], f); } if(tag == "s" || tag == "symbol") { SETSYMBOL(&key_atom[key_count], gensym(const_cast<char*>(in.str().c_str()))); }
key_count++; }
if(!key_count) continue;
//----------------------
// get the <value> tag child2 = child1->FirstChildElement( "value" ); if(!child2) return false;
// get nr of values and allocate mem for them // (if its a pd list) int val_count = 0; for( child3 = child2->FirstChildElement(); child3; child3 = child3->NextSiblingElement() ) val_count++;
val_atom = (t_atom*)getbytes(val_count*sizeof(t_atom)); if(val_atom == NULL) { post("Fatal Error Out Of Memory (%s-readFromFile)",this->dataname_.c_str()); return false; }
// iterate through all the atoms of <value> val_count = 0; for( child3 = child2->FirstChildElement(); child3; child3 = child3->NextSiblingElement() ) { string tag(child3->Value());
if(!child3->FirstChild()) continue; istringstream in(child3->FirstChild()->Value());
if(tag == "f" || tag == "float") { in >> f; SETFLOAT(&val_atom[val_count],f); } if(tag == "s" || tag == "symbol") { SETSYMBOL(&val_atom[val_count], gensym(const_cast<char*>(in.str().c_str()))); }
val_count++; }
if(!val_count) continue;
// add the element to the container key.setAtoms(key_count,key_atom); el.setAtoms(val_count,val_atom); this->data_[this->h_namespace_].insert(std::pair<Element,Element>(key,el));
freebytes(key_atom, key_count*sizeof(t_atom)); freebytes(val_atom, val_count*sizeof(t_atom));
parsed = true; } return parsed; }
#endif // _map_base_h__
--- NEW FILE: HDeque.h --- // *********************(c)*2004*********************> // -holzilib--holzilib--holzilib--holzilib--holzilib-> // ++++PD-External++by+Georg+Holzmann++grh@gmx.at++++> // // PDContainer: // this is a port of the containers from the C++ STL // (Standard Template Library) // for usage see the documentation and PD help files // for license see readme.txt // // HDeque.h
#ifndef _h_deque_h__ #define _h_deque_h__
#include "include/SequBase.h" #include <deque>
using std::deque;
//--------------------------------------------------- /* this is the class of the deque */ class HDeque : public SequBase< deque<Element>, deque<Element>::iterator > {
private:
/* Copy Construction is not allowed */ HDeque(const HDeque &src) { }
/* assignement operator is not allowed */ const HDeque& operator = (const HDeque&) { return *this; }
public:
/* Standard Constructor * no namespace */ HDeque() { dataname_ = "h_deque"; }
/* Constructor * with a namespace */ HDeque(string h_namespace) { dataname_ = "h_deque"; setNamespace(h_namespace); }
/* Destructor */ virtual ~HDeque() { }
/* inserts an element at the front of * the container (so then the size * increases by one !!!) */ virtual void pushFront(Element value) { data_[h_namespace_].push_front(value); }
/* removes the element from the front of * the container (so then the size * decreases by one !!!) */ virtual void popFront() { data_[h_namespace_].pop_front(); } };
#endif //_h_deque_h__
--- NEW FILE: SequBase.h --- // *********************(c)*2004*********************> // -holzilib--holzilib--holzilib--holzilib--holzilib-> // ++++PD-External++by+Georg+Holzmann++grh@gmx.at++++> // // PDContainer: // this is a port of the containers from the C++ STL // (Standard Template Library) // for usage see the documentation and PD help files // for license see readme.txt // // SequBase.h
#ifndef _sequ_base_h__ #define _sequ_base_h__
#include "include/SimpleBase.h"
//--------------------------------------------------- /* this is the base class of vector and deque */ template <class ContainerType, class ContTypeIterator> class SequBase : public SimpleBase<ContainerType,ContTypeIterator> {
private:
/* Copy Construction is not allowed */ SequBase(const SequBase<ContainerType,ContTypeIterator> &src) { }
/* assignement operator is not allowed */ const SequBase<ContainerType,ContTypeIterator>& operator = (const SequBase<ContainerType,ContTypeIterator>&) { }
public:
/* Standard Constructor * no namespace */ SequBase() { }
/* Destructor */ virtual ~SequBase() { };
/* change the element at the index */ virtual void set(int index, Element value) { this->data_[this->h_namespace_][index] = value; }
/* get the element from the index */ virtual Element &get(int index) const { return this->data_[this->h_namespace_][index]; }
/* resize the sequence */ virtual void resize(int size) { this->data_[this->h_namespace_].resize(size); }
/* inserts an element at the end of * the container (so then the size * increases by one !!!) */ virtual void pushBack(Element value) { this->data_[this->h_namespace_].push_back(value); }
/* removes the element from the end of * the container (so then the size * decreases by one !!!) */ virtual void popBack() { this->data_[this->h_namespace_].pop_back(); }
/* returns the last element */ virtual Element &back() const { return this->data_[this->h_namespace_].back(); }
/* returns the first element */ virtual Element &front() const { return this->data_[this->h_namespace_].front(); }
/* inserts an element before the element * with the given index */ virtual void insert(int index, Element value) { this->data_[this->h_namespace_].insert(this->data_[this->h_namespace_].begin()+index, value); }
/* removes the element with that index from the * container */ virtual void remove(int index) { this->data_[this->h_namespace_].erase(this->data_[this->h_namespace_].begin()+index); }
/* reads from an input file and adds the data to * the current namespace * Fileformat: see saveToFile * index: inserts the data starting with this index * returns true on success */ virtual bool readFromFile2(string filename, int index);
/* reads from a XML input file and adds the data to * the current namespace * index: inserts the data starting with this index * returns true on success */ virtual bool readFromFile2XML(string filename, int index); };
//---------------------------------------------------- /* reads the data from the file into the current * namespace * Fileformat: see saveToFile * index: inserts the data starting with this index * returns true on success */ template<class ContainerType, class ContTypeIterator> bool SequBase<ContainerType,ContTypeIterator>::readFromFile2(string filename, int index) { ifstream infile; infile.open(filename.c_str());
if(!infile) return false;
Element key;
string line; bool go_on = false; char type; string symbol; t_float number; int key_count; int max_index = this->data_[this->h_namespace_].size();
while (getline(infile, line)) { // first parse the instream, to get the number of atoms // (= size of the list)
if(index < 0 || index >= max_index) { post("%s, read: wrong index !!",this->dataname_.c_str()); return false; }
istringstream instream(line); ostringstream key_str("");
go_on = false; key_count = 0; while(!go_on) { instream >> type; if (instream.eof()) { go_on = true; break; } if (type == 's') { key_count++; instream >> symbol; key_str << "s " << symbol; } if (type == 'f') { key_count++; instream >> number; key_str << "f " << number; } if (instream.eof()) go_on = true; key_str << " "; }
// now objects, parse again the data // into the objects and add them to the container
t_atom *key_atom = (t_atom*)getbytes(key_count*sizeof(t_atom));
if(key_atom == NULL) post("Fatal Error Out Of Memory (%s-readFromFile)",this->dataname_.c_str());
istringstream key_istr(key_str.str());
for(int i = 0; i < key_count; i++) { key_istr >> type; if (type == 's') { key_istr >> symbol; SETSYMBOL(&key_atom[i],gensym(const_cast<char*>(symbol.c_str()))); } if (type == 'f') { key_istr >> number; SETFLOAT(&key_atom[i],number); } }
key.setAtoms(key_count,key_atom); // insert the data this->data_[this->h_namespace_][index] = key; index++;
freebytes(key_atom, key_count*sizeof(t_atom)); }
infile.close();
return true; }
//---------------------------------------------------- /* reads the data from the XML file into the current * namespace * index: inserts the data starting with this index * returns true on success */ template<class ContainerType, class ContTypeIterator> bool SequBase<ContainerType,ContTypeIterator>::readFromFile2XML(string filename, int index) { int max_index = this->data_[this->h_namespace_].size(); if(index < 0 || index >= max_index) { post("%s, read: wrong index !!",this->dataname_.c_str()); return false; }
TiXmlDocument doc( filename.c_str() );
if( !doc.LoadFile() ) return false;
TiXmlNode *parent = 0; TiXmlElement *child1 = 0; TiXmlElement *child2 = 0;
t_atom *el_atom = 0; Element el; t_float f; bool parsed=false;
// Get the <PDContainer> tag and check type parent = doc.FirstChild( "PDContainer" ); if(!parent) return false;
if(!parent->ToElement()) return false; if(!parent->ToElement()->Attribute("type")) { post("readXML: you must specify an attribute type in <PDContainer> !"); return false; }
string type(parent->ToElement()->Attribute("type"));
if( type != "h_vector" && type != "h_list" && type != "h_deque" && type != "h_set" && type != "h_multiset") { post("readXML: wrong container type (attribute type in <PDContainer>) !"); return false; }
if( type != this->dataname_ ) post("readXML: importing data from %s!", type.c_str() );
// iterate through all the <element> tags for( child1 = parent->FirstChildElement("element"); child1; child1 = child1->NextSiblingElement("element") ) { // get nr of atoms and allocate mem for them // (if its a pd list) int atoms = 0; for( child2 = child1->FirstChildElement(); child2; child2 = child2->NextSiblingElement() ) atoms++;
el_atom = (t_atom*)getbytes(atoms*sizeof(t_atom));
if(el_atom == NULL) { post("Fatal Error Out Of Memory (%s-readFromFile)",this->dataname_.c_str()); return false; }
// iterate through all the atoms of one <element> atoms = 0; for( child2 = child1->FirstChildElement(); child2; child2 = child2->NextSiblingElement() ) { string tag(child2->Value());
if(!child2->FirstChild()) continue; istringstream in(child2->FirstChild()->Value());
if(tag == "f" || tag == "float") { in >> f; SETFLOAT(&el_atom[atoms], f); } if(tag == "s" || tag == "symbol") { SETSYMBOL(&el_atom[atoms], gensym(const_cast<char*>(in.str().c_str()))); }
atoms++; }
if(!atoms) continue;
// add the element to the container el.setAtoms(atoms,el_atom);
// insert the data this->data_[this->h_namespace_][index] = el; index++;
freebytes(el_atom, atoms*sizeof(t_atom));
parsed = true; } return parsed;
}
#endif //_sequ_base_h__
--- NEW FILE: GlobalStuff.h --- // *********************(c)*2004*********************> // -holzilib--holzilib--holzilib--holzilib--holzilib-> // ++++PD-External++by+Georg+Holzmann++grh@gmx.at++++> // // PDContainer: // this is a port of the containers from the C++ STL // (Standard Template Library) // for usage see the documentation and PD help files // for license see readme.txt // // GlobalStuff.h
#ifndef _global_stuff_h___ #define _global_stuff_h___
#include "m_pd.h" #include <string> #include <sstream> #include <fstream> #include <iterator> #include <list> //#include <iostream> //DEBUG
using std::string; using std::ostringstream; using std::istringstream; using std::ofstream; using std::ifstream; using std::endl;
// current version #define PDC_VERSION "0.2"
// TinyXML //#define TIXML_USE_STL #include "tinyxml/tinyxml.h"
//--------------------------------------------------- /* This function compares two pd t_atoms */ static bool compareAtoms(t_atom &atom1, t_atom &atom2) { if(atom1.a_type == A_FLOAT && atom2.a_type == A_FLOAT) return (atom1.a_w.w_float == atom2.a_w.w_float);
if(atom1.a_type == A_SYMBOL && atom2.a_type == A_SYMBOL) return (strcmp(atom1.a_w.w_symbol->s_name, atom2.a_w.w_symbol->s_name) == 0);
if(atom1.a_type == A_POINTER && atom2.a_type == A_POINTER) return (atom1.a_w.w_gpointer == atom2.a_w.w_gpointer);
return false; }
//--------------------------------------------------- /* one Element holds one data element, which can be * a list, a float or a symbol */ class Element { private: t_atom *atom; int length;
public: Element() : atom(NULL), length(0) { }
Element(int size_, t_atom *atom_) : atom(NULL), length(0) { if(atom_ && size_) { length = size_;
// !!!! FIXME !!!! // hack to avoid lockating too much memory // (somewhere I read an uninitialized value ... // ... but where !?) if(length>999) { post("Element, constr1: invalid construction !!! should be fixed !!!"); length=0; atom=NULL; return; }
atom = (t_atom*)copybytes(atom_, length*sizeof(t_atom)); } }
// Copy Constr. Element(const Element &src) : atom(NULL), length(0) { if(src.atom) { length = src.length;
// !!!! FIXME !!!! // hack to avoid lockating too much memory // (somewhere I read an uninitialized value ... // ... but where !?) if(length>999) { post("Element, constr2: invalid construction !!! should be fixed !!!"); length=0; atom=NULL; return; }
atom = (t_atom*)copybytes(src.atom, length*sizeof(t_atom)); } }
// Destructor ~Element() { if(atom) freebytes(atom, length*sizeof(t_atom)); }
// set atoms and length void setAtoms(int size_, t_atom *atom_) { if(atom) { freebytes(atom, length*sizeof(t_atom)); length=0; atom=NULL; }
if(atom_) { length = size_;
// !!!! FIXME !!!! // hack to avoid lockating too much memory // (somewhere I read an uninitialized value ... // ... but where !?) if(length>999) { post("Element, setAtoms: invalid construction !!! should be fixed !!!"); length=0; atom=NULL; return; }
atom = (t_atom*)copybytes(atom_, length*sizeof(t_atom)); } }
int getLength() { return length; }
// shallow copy !!! t_atom *getAtom() { return atom; }
//Assignement Operator const Element& operator = (const Element &src) { if(atom) { freebytes(atom, length*sizeof(t_atom)); length=0; atom=NULL; }
if(src.atom) { length = src.length;
// !!!! FIXME !!!! // hack to avoid lockating too much memory // (somewhere I read an uninitialized value ... // ... but where !?) if(length>999) { post("Element, assignment: invalid construction !!! should be fixed !!!"); length=0; atom=NULL; return (*this); }
atom = (t_atom*)copybytes(src.atom, length*sizeof(t_atom)); }
return (*this); }
// operator== to compare the objects bool operator== (const Element &key) const { if (length != key.length) return false;
for (int i=0; i < length; i++) { if(!compareAtoms(atom[i],key.atom[i])) return false; }
return true; }
// operator< to compare the objects // (needed by map, set, ...) bool operator< (const Element &key) const { if (length == key.length) { bool difference = false; int index;
for (index = 0; index<length; index++) { if(!compareAtoms(atom[index],key.atom[index])) { difference = true; break; } } // definition: // A_FLOAT < A_SYMBOL < A_POINTER
if( atom[index].a_type == A_FLOAT && key.atom[index].a_type != A_FLOAT ) return true;
if( atom[index].a_type == A_SYMBOL ) { if( key.atom[index].a_type == A_FLOAT ) return false; if( key.atom[index].a_type == A_POINTER ) return true; } // compare, when they are the same type: if( atom[index].a_type == A_POINTER && key.atom[index].a_type != A_POINTER ) return false;
if( atom[index].a_type == A_FLOAT && key.atom[index].a_type == A_FLOAT ) return (atom[index].a_w.w_float < key.atom[index].a_w.w_float);
if( atom[index].a_type == A_SYMBOL && key.atom[index].a_type == A_SYMBOL ) return (strcmp(atom[index].a_w.w_symbol->s_name, key.atom[index].a_w.w_symbol->s_name) < 0); if( atom[index].a_type == A_POINTER && key.atom[index].a_type == A_POINTER ) return (atom[index].a_w.w_gpointer < key.atom[index].a_w.w_gpointer); return false; } // different length else return (length < key.length);
} };
#endif //_global_stuff_h___
--- NEW FILE: QueueStack.h --- // *********************(c)*2004*********************> // -holzilib--holzilib--holzilib--holzilib--holzilib-> // ++++PD-External++by+Georg+Holzmann++grh@gmx.at++++> // // PDContainer: // this is a port of the containers from the C++ STL // (Standard Template Library) // for usage see the documentation and PD help files // for license see readme.txt // // HQueueStack.h
#ifndef _h_queue_stack_h__ #define _h_queue_stack_h__
#include "include/ContainerBase.h"
//--------------------------------------------------- /* this is the class of the queue, stack and priority queue */ template <class ContainerType, class ContTypeIterator> class QueueStack : public ContainerBase<ContainerType,ContTypeIterator> {
private:
/* Copy Construction is not allowed */ QueueStack(const QueueStack<ContainerType,ContTypeIterator> &src) { }
/* assignement operator is not allowed */ const QueueStack<ContainerType,ContTypeIterator>& operator = (const QueueStack<ContainerType,ContTypeIterator>&) { }
public:
/* Standard Constructor * no namespace */ QueueStack() { }
/* Destructor */ virtual ~QueueStack() { }
/* removes the value from the top of * the container */ virtual void pop() { this->data_[this->h_namespace_].pop(); } };
#endif //_h_queue_stack_h__
--- NEW FILE: HVector.h --- // *********************(c)*2004*********************> // -holzilib--holzilib--holzilib--holzilib--holzilib-> // ++++PD-External++by+Georg+Holzmann++grh@gmx.at++++> // // PDContainer: // this is a port of the containers from the C++ STL // (Standard Template Library) // for usage see the documentation and PD help files // for license see readme.txt // // HVector.h
#ifndef _h_vector_h__ #define _h_vector_h__
#include "include/SequBase.h" #include <vector>
using std::vector;
//--------------------------------------------------- /* this is the class of the vector */ class HVector : public SequBase< vector<Element>, vector<Element>::iterator > {
private:
/* Copy Construction is not allowed */ HVector(const HVector &src) { }
/* assignement operator is not allowed */ const HVector& operator = (const HVector&) { return *this; }
public:
/* Standard Constructor * no namespace */ HVector() { dataname_ = "h_vector"; }
/* Constructor * with a namespace */ HVector(string h_namespace) { dataname_ = "h_vector"; setNamespace(h_namespace); }
/* Destructor */ virtual ~HVector() { } };
#endif //_h_vector_h__
--- NEW FILE: HQueue.h --- // *********************(c)*2004*********************> // -holzilib--holzilib--holzilib--holzilib--holzilib-> // ++++PD-External++by+Georg+Holzmann++grh@gmx.at++++> // // PDContainer: // this is a port of the containers from the C++ STL // (Standard Template Library) // for usage see the documentation and PD help files // for license see readme.txt // // HQueue.h
#ifndef _h_queue_h__ #define _h_queue_h__
#include "include/QueueStack.h" #include <queue>
using std::queue;
//--------------------------------------------------- /* this is the class of the queue */ class HQueue : public QueueStack< queue<Element>, int > {
private:
/* Copy Construction is not allowed */ HQueue(const HQueue &src) { }
/* assignement operator is not allowed */ const HQueue& operator = (const HQueue&) { return *this; }
public:
/* Standard Constructor * no namespace */ HQueue() { dataname_ = "h_queue"; }
/* Constructor * with a namespace */ HQueue(string h_namespace) { dataname_ = "h_queue"; setNamespace(h_namespace); }
/* Destructor */ virtual ~HQueue() { }
/* inserts an element in the container */ virtual void push(Element value) { data_[h_namespace_].push(value); }
/* returns the element from the top of * the stack */ virtual Element &front() const { return data_[h_namespace_].front(); } };
#endif //_h_queue_h__
--- NEW FILE: HSet.h --- // *********************(c)*2004*********************> // -holzilib--holzilib--holzilib--holzilib--holzilib-> // ++++PD-External++by+Georg+Holzmann++grh@gmx.at++++> // // PDContainer: // this is a port of the containers from the C++ STL // (Standard Template Library) // for usage see the documentation and PD help files // for license see readme.txt // // HSet.h
#ifndef _h_set_h__ #define _h_set_h__
#include "include/SimpleBase.h" #include <set>
using std::set;
//--------------------------------------------------- /* this is the class of the set */ class HSet : public SimpleBase< set<Element>, set<Element>::iterator > {
private:
/* Copy Construction is not allowed */ HSet(const HSet &src) { }
/* assignement operator is not allowed */ const HSet& operator = (const HSet&) { return *this; }
public:
/* Constructor * no namespace */ HSet() { dataname_ = "h_set"; }
/* Constructor * with a namespace */ HSet(string h_namespace) { dataname_ = "h_set"; setNamespace(h_namespace); }
/* Destructor */ virtual ~HSet() { }
/* add an element */ virtual void add(Element key) { data_[h_namespace_].insert(key); }
/* look if the element is set * returns 1 if it is set * 0 if it isn't set */ virtual int get(const Element &key) const { return (data_[h_namespace_].find(key) != data_[h_namespace_].end()); }
/* removes an element from the container */ virtual void remove(const Element &key) const { data_[h_namespace_].erase(key); } };
#endif // _h_set_h__
--- NEW FILE: HMap.h --- // *********************(c)*2004*********************> // -holzilib--holzilib--holzilib--holzilib--holzilib-> // ++++PD-External++by+Georg+Holzmann++grh@gmx.at++++> // // PDContainer: // this is a port of the containers from the C++ STL // (Standard Template Library) // for usage see the documentation and PD help files // for license see readme.txt // // HMap.h
#ifndef _h_map_h__ #define _h_map_h__
#include "include/MapBase.h"
using std::map;
//--------------------------------------------------- /* this is the class of the map */ class HMap : public MapBase< map<Element,Element>, map<Element,Element>::iterator > { // gcc4.0 food: //this->data_; //this->h_namespace_; //this->dataname_;
private:
/* Copy Construction is not allowed */ HMap(const HMap &src) { }
/* assignement operator is not allowed */ const HMap& operator = (const HMap&) { return *this; }
public:
/* Constructor * no namespace */ HMap() { dataname_ = "h_map"; }
/* Constructor * with a namespace */ HMap(string h_namespace) { dataname_ = "h_map"; setNamespace(h_namespace); }
/* Destructor */ virtual ~HMap() { } };
#endif // _h_map_h__
--- NEW FILE: SimpleBase.h --- // *********************(c)*2004*********************> // -holzilib--holzilib--holzilib--holzilib--holzilib-> // ++++PD-External++by+Georg+Holzmann++grh@gmx.at++++> // // PDContainer: // this is a port of the containers from the C++ STL // (Standard Template Library) // for usage see the documentation and PD help files // for license see readme.txt // // SimpleBase.h
#ifndef _simple_base_h__ #define _simple_base_h__
#include "include/ContainerBase.h"
//--------------------------------------------------- /* this is the base class of all simple containers */ template <class ContainerType, class ContTypeIterator> class SimpleBase : public ContainerBase<ContainerType,ContTypeIterator> {
private:
/* Copy Construction is not allowed */ SimpleBase(const SimpleBase<ContainerType,ContTypeIterator> &src) { }
/* assignement operator is not allowed */ const SimpleBase<ContainerType,ContTypeIterator>& operator = (const SimpleBase<ContainerType,ContTypeIterator>&) { }
public:
/* Standard Constructor * no namespace */ SimpleBase() { }
/* Destructor */ virtual ~SimpleBase() { };
/* prints all the data of the current namespace to the console */ virtual void printAll();
/* prints all the data of the current namespace to the console * (with the index as prefix) */ virtual void printAllIndex();
/* saves all the data of the current namespace to a file * Fileformat: * <data_atom_type1> <data_atom1> <data_atom_type2> <data_atom2> ... * e.g.: * f 1 f 2 f 4 * s foo f 12.34234 * types: s=symbol, f=float * ATTENTION: if the file exists, all the old data of * the file is lost * returns true on success */ virtual bool saveToFile(string filename);
/* saves all the data of the current namespace to a XML file * ATTENTION: if the file exists, all the old data of * the file is lost * returns true on success */ virtual bool saveToFileXML(string filename);
/* reads from an input file and adds the data to * the current namespace * Fileformat: see saveToFile * returns true on success */ virtual bool readFromFile(string filename);
/* reads from an input XML file and adds the data to * the current namespace * returns true on success */ virtual bool readFromFileXML(string filename); };
//---------------------------------------------------- /* prints all the data of the current namespace to the console */ template<class ContainerType, class ContTypeIterator> void SimpleBase<ContainerType,ContTypeIterator>::printAll() { ContTypeIterator iter = this->data_[this->h_namespace_].begin();
post("\n%s: printing namespace %s",this->dataname_.c_str(),this->h_namespace_.c_str()); post("--------------------------------------------------");
bool data_here = false; while(iter != this->data_[this->h_namespace_].end()) { ostringstream output("");
Element key((*iter)); if(key.getLength() == 0) { iter++; continue; }
if (key.getLength() > 1) // list { output << "list "; for (int i=0; i < key.getLength(); i++) { if (key.getAtom()[i].a_type == A_FLOAT) output << key.getAtom()[i].a_w.w_float << " "; if (key.getAtom()[i].a_type == A_SYMBOL) output << key.getAtom()[i].a_w.w_symbol->s_name << " "; if (key.getAtom()[i].a_type == A_POINTER) output << "(gpointer)" << key.getAtom()[i].a_w.w_gpointer << " "; } } else // no list { if (key.getAtom()[0].a_type == A_FLOAT) output << "float " << key.getAtom()[0].a_w.w_float << " "; if (key.getAtom()[0].a_type == A_SYMBOL) output << "symbol " << key.getAtom()[0].a_w.w_symbol->s_name << " "; if (key.getAtom()[0].a_type == A_POINTER) output << "pointer " << key.getAtom()[0].a_w.w_gpointer << " "; }
post("%s",output.str().c_str()); data_here = true; iter++; } if(!data_here) post("no data in current namespace!"); post("--------------------------------------------------"); }
//---------------------------------------------------- /* prints all the data of the current namespace to the console * (with the index as prefix) */ template<class ContainerType, class ContTypeIterator> void SimpleBase<ContainerType,ContTypeIterator>::printAllIndex() { ContTypeIterator iter = this->data_[this->h_namespace_].begin();
post("\n%s: printing namespace %s",this->dataname_.c_str(),this->h_namespace_.c_str()); post("--------------------------------------------------");
bool data_here = false; int i=0; while(iter != this->data_[this->h_namespace_].end()) { ostringstream output("");
Element key((*iter)); if(key.getLength() == 0) { iter++; i++; continue; }
if (key.getLength() > 1) // list { output << "list "; for (int i=0; i < key.getLength(); i++) { if (key.getAtom()[i].a_type == A_FLOAT) output << key.getAtom()[i].a_w.w_float << " "; if (key.getAtom()[i].a_type == A_SYMBOL) output << key.getAtom()[i].a_w.w_symbol->s_name << " "; if (key.getAtom()[i].a_type == A_POINTER) output << "(gpointer)" << key.getAtom()[i].a_w.w_gpointer << " "; } } else // no list { if (key.getAtom()[0].a_type == A_FLOAT) output << "float " << key.getAtom()[0].a_w.w_float << " "; if (key.getAtom()[0].a_type == A_SYMBOL) output << "symbol " << key.getAtom()[0].a_w.w_symbol->s_name << " "; if (key.getAtom()[0].a_type == A_POINTER) output << "pointer " << key.getAtom()[0].a_w.w_gpointer << " "; }
post("%d: %s",i,output.str().c_str()); data_here = true; iter++; i++; } if(!data_here) post("no data in current namespace!"); post("--------------------------------------------------"); }
//---------------------------------------------------- /* saves all the data of the current namespace to a file * Fileformat: * <key_atom_type1> <key_atom1> ... - <data_atom_type1> <data_atom1> ... * e.g.: * f 1 f 2 - f 4 * s foo f 12.34234 - f 3 f 5 s gege * types: s=symbol, f=float * ATTENTION: if the file exists, all the old data of * the file is lost * returns true on success */ template<class ContainerType, class ContTypeIterator> bool SimpleBase<ContainerType,ContTypeIterator>::saveToFile(string filename) { ofstream outfile; ContTypeIterator iter = this->data_[this->h_namespace_].begin();
outfile.open(filename.c_str());
if(!outfile) return false;
while(iter != this->data_[this->h_namespace_].end()) { Element key((*iter)); bool have_pointer = false;
// check for pointers first for (int i=0; i < key.getLength(); i++) if (key.getAtom()[i].a_type == A_POINTER) have_pointer = true;
if(have_pointer) { post("PDContainer warning: pointers can't be saved and are ignored !!!"); iter++; } else {
for (int i=0; i < key.getLength(); i++) { if (key.getAtom()[i].a_type == A_FLOAT) outfile << "f " << key.getAtom()[i].a_w.w_float << " "; if (key.getAtom()[i].a_type == A_SYMBOL) outfile << "s " << key.getAtom()[i].a_w.w_symbol->s_name << " "; }
outfile << endl; iter++;
} }
outfile.close();
return true; }
//---------------------------------------------------- /* saves all the data of the current namespace to a XML file * ATTENTION: if the file exists, all the old data of * the file is lost * returns true on success */ template<class ContainerType, class ContTypeIterator> bool SimpleBase<ContainerType,ContTypeIterator>::saveToFileXML(string filename) { ostringstream output(""); ContTypeIterator iter = this->data_[this->h_namespace_].begin();
// add XML Header: output << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n" << "<!DOCTYPE PDContainer SYSTEM " << "\"http://grh.mur.at/software/pdcontainer_simple.dtd\">\n" << "<PDContainer type="" << this->dataname_ << "">\n";
while(iter != this->data_[this->h_namespace_].end()) { // add Element: Element el((*iter)); bool have_pointer = false;
// check for pointers first for (int i=0; i < el.getLength(); i++) if (el.getAtom()[i].a_type == A_POINTER) have_pointer = true;
if(have_pointer) { post("PDContainer warning: pointers can't be saved and are ignored !!!"); iter++; } else {
output << "<element>\n";
for (int i=0; i < el.getLength(); i++) { if (el.getAtom()[i].a_type == A_FLOAT) output << "<f> " << el.getAtom()[i].a_w.w_float << " </f>\n"; if (el.getAtom()[i].a_type == A_SYMBOL) output << "<s>" << el.getAtom()[i].a_w.w_symbol->s_name << " </s>\n"; }
output << "</element>\n";
iter++;
} }
output << "</PDContainer>\n";
// now write to file: TiXmlDocument outfile( filename.c_str() ); outfile.Parse( output.str().c_str() );
if ( outfile.Error() ) return false;
outfile.SaveFile();
return true; }
//---------------------------------------------------- /* reads the data from the file into the current * namespace * Fileformat: see saveToFile * returns true on success */ template<class ContainerType, class ContTypeIterator> bool SimpleBase<ContainerType,ContTypeIterator>::readFromFile(string filename) { ifstream infile; infile.open(filename.c_str());
if(!infile) return false;
Element key;
string line; bool go_on = false; char type; string symbol; t_float number; int key_count;
while (getline(infile, line)) { // first parse the instream, to get the number of atoms // (= size of the list)
istringstream instream(line); ostringstream key_str("");
go_on = false; key_count = 0; while(!go_on) { instream >> type; if (instream.eof()) { go_on = true; break; } if (type == 's') { key_count++; instream >> symbol; key_str << "s " << symbol; } if (type == 'f') { key_count++; instream >> number; key_str << "f " << number; } if (instream.eof()) go_on = true; key_str << " "; }
// now objects, parse again the data // into the objects and add them to the container
t_atom *key_atom = (t_atom*)getbytes(key_count*sizeof(t_atom)); if(key_atom == NULL) post("Fatal Error Out Of Memory (%s-readFromFile)",this->dataname_.c_str());
istringstream key_istr(key_str.str());
for(int i = 0; i < key_count; i++) { key_istr >> type; if (type == 's') { key_istr >> symbol; SETSYMBOL(&key_atom[i],gensym(const_cast<char*>(symbol.c_str()))); } if (type == 'f') { key_istr >> number; SETFLOAT(&key_atom[i],number); } }
key.setAtoms(key_count,key_atom);
// insert the data this->data_[this->h_namespace_].insert(this->data_[this->h_namespace_].end(),key);
freebytes(key_atom, key_count*sizeof(t_atom)); }
infile.close();
return true; }
//---------------------------------------------------- /* reads the data from th XML file into the current * namespace * returns true on success */ template<class ContainerType, class ContTypeIterator> bool SimpleBase<ContainerType,ContTypeIterator>::readFromFileXML(string filename) { TiXmlDocument doc( filename.c_str() );
if( !doc.LoadFile() ) return false;
TiXmlNode *parent = 0; TiXmlElement *child1 = 0; TiXmlElement *child2 = 0;
t_atom *el_atom = 0; Element el; t_float f; bool parsed=false;
// Get the <PDContainer> tag and check type parent = doc.FirstChild( "PDContainer" ); if(!parent) return false;
if(!parent->ToElement()) return false; if(!parent->ToElement()->Attribute("type")) { post("readXML: you must specify an attribute type in <PDContainer> !"); return false; }
string type(parent->ToElement()->Attribute("type"));
if( type != "h_vector" && type != "h_list" && type != "h_deque" && type != "h_set" && type != "h_multiset") { post("readXML: wrong container type (attribute type in <PDContainer>) !"); return false; }
if( type != this->dataname_ ) post("readXML: importing data from %s!", type.c_str() );
// iterate through all the <element> tags for( child1 = parent->FirstChildElement("element"); child1; child1 = child1->NextSiblingElement("element") ) { // get nr of atoms and allocate mem for them // (if its a pd list) int atoms = 0; for( child2 = child1->FirstChildElement(); child2; child2 = child2->NextSiblingElement() ) atoms++;
el_atom = (t_atom*)getbytes(atoms*sizeof(t_atom)); if(el_atom == NULL) { post("Fatal Error Out Of Memory (%s-readFromFile)",this->dataname_.c_str()); return false; }
// iterate through all the atoms of one <element> atoms = 0; for( child2 = child1->FirstChildElement(); child2; child2 = child2->NextSiblingElement() ) { string tag(child2->Value());
if(!child2->FirstChild()) continue; istringstream in(child2->FirstChild()->Value());
if(tag == "f" || tag == "float") { in >> f; SETFLOAT(&el_atom[atoms], f); } if(tag == "s" || tag == "symbol") { SETSYMBOL(&el_atom[atoms], gensym(const_cast<char*>(in.str().c_str()))); }
atoms++; }
if(!atoms) continue;
// add the element to the container el.setAtoms(atoms,el_atom);
// insert it in the container this->data_[this->h_namespace_].insert(this->data_[this->h_namespace_].end(),el);
freebytes(el_atom, atoms*sizeof(t_atom));
parsed = true; } return parsed; }
#endif // _simple_base_h__