aboutsummaryrefslogtreecommitdiff
path: root/PDContainer/include
diff options
context:
space:
mode:
Diffstat (limited to 'PDContainer/include')
-rwxr-xr-xPDContainer/include/ContainerBase.h136
-rwxr-xr-xPDContainer/include/GlobalStuff.h274
-rwxr-xr-xPDContainer/include/HDeque.h80
-rwxr-xr-xPDContainer/include/HList.h250
-rwxr-xr-xPDContainer/include/HMap.h67
-rwxr-xr-xPDContainer/include/HMultiMap.h80
-rwxr-xr-xPDContainer/include/HMultiSet.h81
-rwxr-xr-xPDContainer/include/HPrioQueue.h100
-rwxr-xr-xPDContainer/include/HQueue.h77
-rwxr-xr-xPDContainer/include/HSet.h82
-rwxr-xr-xPDContainer/include/HStack.h77
-rwxr-xr-xPDContainer/include/HVector.h66
-rwxr-xr-xPDContainer/include/MapBase.h655
-rwxr-xr-xPDContainer/include/QueueStack.h61
-rwxr-xr-xPDContainer/include/SequBase.h341
-rwxr-xr-xPDContainer/include/SimpleBase.h539
16 files changed, 2966 insertions, 0 deletions
diff --git a/PDContainer/include/ContainerBase.h b/PDContainer/include/ContainerBase.h
new file mode 100755
index 0000000..c32a22a
--- /dev/null
+++ b/PDContainer/include/ContainerBase.h
@@ -0,0 +1,136 @@
+// *********************(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___
diff --git a/PDContainer/include/GlobalStuff.h b/PDContainer/include/GlobalStuff.h
new file mode 100755
index 0000000..6cb96cc
--- /dev/null
+++ b/PDContainer/include/GlobalStuff.h
@@ -0,0 +1,274 @@
+// *********************(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___
diff --git a/PDContainer/include/HDeque.h b/PDContainer/include/HDeque.h
new file mode 100755
index 0000000..02600cf
--- /dev/null
+++ b/PDContainer/include/HDeque.h
@@ -0,0 +1,80 @@
+// *********************(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__
diff --git a/PDContainer/include/HList.h b/PDContainer/include/HList.h
new file mode 100755
index 0000000..b8a5768
--- /dev/null
+++ b/PDContainer/include/HList.h
@@ -0,0 +1,250 @@
+// *********************(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__
diff --git a/PDContainer/include/HMap.h b/PDContainer/include/HMap.h
new file mode 100755
index 0000000..0f68497
--- /dev/null
+++ b/PDContainer/include/HMap.h
@@ -0,0 +1,67 @@
+// *********************(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__
diff --git a/PDContainer/include/HMultiMap.h b/PDContainer/include/HMultiMap.h
new file mode 100755
index 0000000..0c7a9f7
--- /dev/null
+++ b/PDContainer/include/HMultiMap.h
@@ -0,0 +1,80 @@
+// *********************(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__
diff --git a/PDContainer/include/HMultiSet.h b/PDContainer/include/HMultiSet.h
new file mode 100755
index 0000000..7bfc36f
--- /dev/null
+++ b/PDContainer/include/HMultiSet.h
@@ -0,0 +1,81 @@
+// *********************(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__
diff --git a/PDContainer/include/HPrioQueue.h b/PDContainer/include/HPrioQueue.h
new file mode 100755
index 0000000..d1bddda
--- /dev/null
+++ b/PDContainer/include/HPrioQueue.h
@@ -0,0 +1,100 @@
+// *********************(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__
diff --git a/PDContainer/include/HQueue.h b/PDContainer/include/HQueue.h
new file mode 100755
index 0000000..025fe52
--- /dev/null
+++ b/PDContainer/include/HQueue.h
@@ -0,0 +1,77 @@
+// *********************(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__
diff --git a/PDContainer/include/HSet.h b/PDContainer/include/HSet.h
new file mode 100755
index 0000000..231b909
--- /dev/null
+++ b/PDContainer/include/HSet.h
@@ -0,0 +1,82 @@
+// *********************(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__
diff --git a/PDContainer/include/HStack.h b/PDContainer/include/HStack.h
new file mode 100755
index 0000000..8050af9
--- /dev/null
+++ b/PDContainer/include/HStack.h
@@ -0,0 +1,77 @@
+// *********************(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__
diff --git a/PDContainer/include/HVector.h b/PDContainer/include/HVector.h
new file mode 100755
index 0000000..933da80
--- /dev/null
+++ b/PDContainer/include/HVector.h
@@ -0,0 +1,66 @@
+// *********************(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__
diff --git a/PDContainer/include/MapBase.h b/PDContainer/include/MapBase.h
new file mode 100755
index 0000000..cf295de
--- /dev/null
+++ b/PDContainer/include/MapBase.h
@@ -0,0 +1,655 @@
+// *********************(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__
diff --git a/PDContainer/include/QueueStack.h b/PDContainer/include/QueueStack.h
new file mode 100755
index 0000000..eb72408
--- /dev/null
+++ b/PDContainer/include/QueueStack.h
@@ -0,0 +1,61 @@
+// *********************(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__
diff --git a/PDContainer/include/SequBase.h b/PDContainer/include/SequBase.h
new file mode 100755
index 0000000..40bc4d7
--- /dev/null
+++ b/PDContainer/include/SequBase.h
@@ -0,0 +1,341 @@
+// *********************(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__
diff --git a/PDContainer/include/SimpleBase.h b/PDContainer/include/SimpleBase.h
new file mode 100755
index 0000000..75203ec
--- /dev/null
+++ b/PDContainer/include/SimpleBase.h
@@ -0,0 +1,539 @@
+// *********************(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__