From 1d6d1e8c73193f57a9c98387ea42eb91eb4d21d1 Mon Sep 17 00:00:00 2001 From: Georg Holzmann Date: Fri, 21 Oct 2005 11:56:32 +0000 Subject: only moving to a new directory svn path=/trunk/externals/grh/; revision=3740 --- PDContainer/include/MapBase.h | 655 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 655 insertions(+) create mode 100755 PDContainer/include/MapBase.h (limited to 'PDContainer/include/MapBase.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 MapBase : public ContainerBase +{ + + private: + + /* Copy Construction is not allowed + */ + MapBase(const MapBase &src) + { } + + /* assignement operator is not allowed + */ + const MapBase& operator = + (const MapBase&) + { } + + 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(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: + * ... - ... + * 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 +void MapBase::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: + * ... - ... + * 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 +bool MapBase::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 + bool MapBase::saveToFileXML(string filename) +{ + ostringstream output(""); + ContTypeIterator iter = this->data_[this->h_namespace_].begin(); + + // add XML Header: + output << "\n" + << "\n" + << "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 << "\n"; + + // add Key: + output << "\n"; + + for (int i=0; i < key.getLength(); i++) + { + if (key.getAtom()[i].a_type == A_FLOAT) + output << " " << key.getAtom()[i].a_w.w_float << " \n"; + if (key.getAtom()[i].a_type == A_SYMBOL) + output << "" << key.getAtom()[i].a_w.w_symbol->s_name << " \n"; + } + + output << "\n"; + + + // add Value: + output << "\n"; + + for (int i=0; i < el.getLength(); i++) + { + if (el.getAtom()[i].a_type == A_FLOAT) + output << " " << el.getAtom()[i].a_w.w_float << " \n"; + if (el.getAtom()[i].a_type == A_SYMBOL) + output << "" << el.getAtom()[i].a_w.w_symbol->s_name << " \n"; + } + + output << "\n"; + + output << "\n"; + + iter++; + + } + } + + output << "\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 +bool MapBase::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(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(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(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 + bool MapBase::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 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 !"); + return false; + } + + string type(parent->ToElement()->Attribute("type")); + if( type != "h_map" && type != "h_multimap" ) + { + post("readXML: wrong container type (attribute type in ) !"); + return false; + } + + if( type != this->dataname_ ) + post("readXML: importing data from %s!", type.c_str() ); + + // iterate through all the tags + for( child1 = parent->FirstChildElement("element"); child1; + child1 = child1->NextSiblingElement("element") ) + { + // get the 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_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(in.str().c_str()))); + } + + key_count++; + } + + if(!key_count) continue; + + //---------------------- + + // get the 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 + 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(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(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__ -- cgit v1.2.1