[PD-cvs] externals/grh/PDContainer/include ContainerBase.h, NONE, 1.1 GlobalStuff.h, NONE, 1.1 HDeque.h, NONE, 1.1 HList.h, NONE, 1.1 HMap.h, NONE, 1.1 HMultiMap.h, NONE, 1.1 HMultiSet.h, NONE, 1.1 HPrioQueue.h, NONE, 1.1 HQueue.h, NONE, 1.1 HSet.h, NONE, 1.1 HStack.h, NONE, 1.1 HVector.h, NONE, 1.1 MapBase.h, NONE, 1.1 QueueStack.h, NONE, 1.1 SequBase.h, NONE, 1.1 SimpleBase.h, NONE, 1.1

Georg Holzmann grholzi at users.sourceforge.net
Fri Oct 21 13:56:34 CEST 2005


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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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__





More information about the Pd-cvs mailing list