// Classe Dynamic Variable List (DVList) de PEIDA // R. Ansari 1997 // LAL (Orsay) / IN2P3-CNRS DAPNIA/SPP (Saclay) / CEA #include "machdefs.h" #include #include #include "dvlist.h" #include "strutil.h" //++ // Class DVList // Lib Outils++ // include dvlist.h // // Cette classe permet de gérer une ensemble de variables (ou paramètres) // pouvant être définies dynamiquement à l'execution. Le nom des // variables ne doit pas contenir de blancs ("") et est // limité à 64 caractères maximum. Cette classe // offre la possibilité de sauvegarder l'ensemble // des variables (Nom, Type, Valeur) dans un fichier, ou de // recréer l'objet DVList et l'ensemble de ses variables à // partir d'un fichier (Objet PPersist). Une zone commentaire (max=320 c.) // est associée à chaque objet DVList, accessible à travers // la méthode "Comment()". Les objets de cette classe sont // en particulier destinés à être inclus dans d'autres objets // PPersist plus complexes. La classe DVList gère des // variables de type entier ("int_8"), réél double précision ("r_8") // et de type chaine de caracteres ("string, char*", maxi 30 caracteres ). // Une classe intermédiaire (*MuTyV*) est utilisée pour représenter une // variable et fournit les services de conversion entre les différents types. //-- //-- //++ // Links Parents // PPersist //-- char MuTyV::myStrBuf[64]; // Declare static ds le .h static MuTyV ddvdum(-9.e19); //++ // Titre Constructeurs //-- //++ // DVList() // Constructeur par défaut // DVList(DVList& cfd) // Constructeur par copie. Le nouvel objet est une copie complète de "cfd" // DVList(char* flnm) // Constructeur avec initialisation à partir du contenu du fichier (PPF) // "flnm". Le fichier doit avoir été créé par la méthode "Write()" //-- /* --Methode-- */ DVList::DVList() { comment = ""; } /* --Methode-- */ DVList::DVList(const DVList& dvl) { Merge(dvl); } /* --Methode-- */ DVList::DVList(char *flnm) { PInPersist s(flnm); ObjFileIO fiodvl(this); fiodvl.Read(s); } /* --Methode-- */ DVList::~DVList() { } //++ // Titre Gestion des variables et opérateurs //-- //++ // void Clear() // Supprime la définition de toutes les variables de l'objet. // DVList& Merge(const DVList& lv) // Fusionne l'objet avec la liste des variables de l'objet "lv" // DVList& operator= (const DVList& cofr) // Remplace la liste des variables de l'objet par celle de l'objet "cofr". //-- /* --Methode-- */ DVList& DVList::operator= (const DVList& dvl) { Clear(); return(Merge(dvl)); } /* --Methode-- */ void DVList::Clear() { mvlist.erase(mvlist.begin(), mvlist.end()); comment = ""; } /* --Methode-- */ DVList& DVList::Merge(const DVList& dvl) { ValList::const_iterator it; for(it = dvl.mvlist.begin(); it != dvl.mvlist.end(); it++) { switch ((*it).second.elval.typ) { case 'I' : SetI((*it).first, (*it).second.elval.mtv.iv); break; case 'D' : SetD((*it).first, (*it).second.elval.mtv.dv); break; case 'S' : SetS((*it).first, (*it).second.elval.mtv.strv); break; default : break; } } comment = comment + "\n" + dvl.comment; return(*this); } //++ // int_8 GetI(string const& key, int_8 def=-1) // r_8 GetD(string const& key, r_8 def=-9.e19) // string GetS(string const& key, char* def="") // Retourne la valeur de la variable de nom "key" et de type entier, réél, // chaine de caracteres. // Si la variable n'existe pas, la valeur par défaut "def" est renvoyée. // string GetComment(string const& key) // Retourne le commentaire associé à la variable de nom "key". //-- /* --Methode-- */ int_8 DVList::GetI(string const& key, int_8 def) { ValList::iterator it = mvlist.find(key); if (it == mvlist.end()) return(def); if ( (*it).second.elval.typ != 'I') return(def); return((*it).second.elval.mtv.iv); } /* --Methode-- */ r_8 DVList::GetD(string const& key, r_8 def) { ValList::iterator it = mvlist.find(key); if (it == mvlist.end()) return(def); if ( (*it).second.elval.typ != 'D') return(def); return((*it).second.elval.mtv.dv); } /* --Methode-- */ string DVList::GetS(string const& key, char* def) { ValList::iterator it = mvlist.find(key); if (it == mvlist.end()) return(def); if ( (*it).second.elval.typ != 'S') return(def); return((*it).second.elval.mtv.strv); } /* --Methode-- */ string DVList::GetComment(string const& key) { ValList::iterator it = mvlist.find(key); if (it == mvlist.end()) return(""); return((*it).second.elcomm); } //++ // void SetI(string const& key, int_8 val) // void SetD(string const& key, r_8 val) // void SetS(string const& key, char* val) // void SetS(string const& key, string val) // Crée la variable de nom "key", de type entier, double, string et // lui attribue la valeur "val". Si une variable du même nom existe, // sa valeur et eventuellement son type sont modifiés. Les noms de // variables ne doivent pas contenir de caractères spéciaux, // en particulier pas de CR/LF. // void SetComment(string const& key, string const& comm) // Modifie le commentaire associé à la variable de nom "key", si // celle-ci existe. Le texte du commentaire ne doit pas contenir // de caractères spéciaux, et en particulier pas de CR/LF. //-- /* --Methode-- */ void DVList::SetI(string const& key, int_8 val) { Get(key) = (int_8)val; } /* --Methode-- */ void DVList::SetD(string const& key, r_8 val) { Get(key) = (r_8)val; } /* --Methode-- */ void DVList::SetS(string const& key, char const* val) { MuTyV div(val); Get(key) = div; } /* --Methode-- */ void DVList::SetS(string const& key, string val) { MuTyV div(val); Get(key) = div; } /* --Methode-- */ void DVList::SetComment(string const& key, string const& comm) { ValList::iterator it = mvlist.find(key); if (it == mvlist.end()) return; (*it).second.elcomm = comm; } //++ // MuTyV& Get(string const& key) // Renvoie une référence sur l'objet "MuTyV" de la liste avec le nom "key". // Si cet objet (variable) n'existe pas, il est créé. // MuTyV& operator() (string const& key) // MuTyV& operator[] (string const& key) // // Renvoie la variable de nom "key". Equivalent à "Get(key)". // string& Comment() // Renvoie une référence sur le champ commentaire de l'objet. //-- /* --Methode-- */ MuTyV& DVList::Get(string const& key) { size_t l = key.length(); if ( (l < 1) || (key.find_first_of(" ") < l) ) return(ddvdum); // dvlElement xxx = {(int_8)0 , ""}; marche pas sur mac/CW (!) - cf DY dvlElement xxx; xxx.elval = (int_8)0; xxx.elcomm = ""; ValList::iterator it = mvlist.find(key); if (it == mvlist.end()) mvlist[key] = xxx; it = mvlist.find(key); if (it == mvlist.end()) return(ddvdum); else return((*it).second.elval); } //++ // Titre Entrée-Sortie //-- //++ // void Print() // Imprime (sur "cout") la liste des variables et leurs valeurs. // void Print(ostream& os) // Imprime sur le flot "os" la liste des variables et leurs valeurs. // ostream& operator << (ostream& s, DVList& dvl) // sortie sur flot "s" (Appel a "Print(s)"). //-- /* --Methode-- */ void DVList::Print(ostream& os) const { os << "DVList::Print() - NVar= " << (int)mvlist.size() << "\n"; if (comment.length() > 0) os << comment << endl; char buff[256]; ValList::const_iterator it; for(it = mvlist.begin(); it != mvlist.end(); it++) { switch ((*it).second.elval.typ) { case 'I' : sprintf(buff, "%s = %d (int) %s\n", (*it).first.substr(0,64).c_str(), (*it).second.elval.mtv.iv, (*it).second.elcomm.substr(0,128).c_str()); break; case 'D' : sprintf(buff, "%s = %.20g (double) %s\n", (*it).first.substr(0,64).c_str(), (*it).second.elval.mtv.dv, (*it).second.elcomm.substr(0,128).c_str()); break; case 'S' : sprintf(buff, "%s = %s (string) %s\n", (*it).first.substr(0,64).c_str(), (*it).second.elval.mtv.strv, (*it).second.elcomm.substr(0,128).c_str()); break; default : break; } os << (string)buff; } os << endl; } //++ // Titre Exemples // Utilisation des objets *MuTyV* : //| MuTyV mvu; // Declaration d'une variable //| mvu = 60; // mvu est de type entier (= 60) //| mvu = 66.6; // et double (= 66.6) maintenant ... //| MuTyV mvi(14); // On construit une variable entiere = 14 //| r_4 x = mvi; // x vaut 14.0 //| MuTyV mvd(44.4); // Variable double = 44.4 //| int k = mvd; // k vaut 44 //| MuTyV mvs("Bonjour, Ca va ?"); // Variable chaine de caracteres //| string s = mvs; // s vaut "Bonjour, Ca va ?" // Utilisation des *DVList* : //| DVList dvl; //| dvl("toto") = 14; //| dvl("titi") = 25.5; //| dvl("tata") = "Bonjour, Ca va ?"; // Majuscules et minuscules sont differenciees pour les noms, pas de blanc ... //| dvl("hello") = 88; //| dvl("Hello") = 77.77; //| dvl.Comment() = "Test d'objet DVList, avec variables hello, Hello "; //| dvl.Write("dvlist.ppf"); // Plus loin, ou dans un autre programme, on relit le fichier fabrique plus haut //| DVList dvlr("dvlist.ppf"); //| int k = dvlr["toto"] ; // k = 14 //| r_8 b = dvlr["titi"] ; // b = 25.5 //| string s = dvlr["tata"] ; // s = "Bonjour, Ca va ?" //| r_4 c = dvlr["Hello"] ; // c = 77.77 //| int l = dvlr["Hello"] ; // l = 77 //| int m = dvlr["hello"] ; // m = 88 //-- //---------------------------------------------------------- // Classe pour la gestion de persistance // ObjFileIO //---------------------------------------------------------- /* --Methode-- */ void ObjFileIO::WriteSelf(POutPersist& s) const { char buf[512]; string sfw; int lc = dobj->Comment().length(); if (lc > 0) { sprintf(buf,"Comment: ( %6d ) ", lc); sfw = buf; s.PutStr(sfw); s.PutStr(dobj->Comment()); } sfw = "----Variable-List---------------"; s.PutStr(sfw); DVList::ValList::const_iterator it; for(it = dobj->Begin(); it != dobj->End(); it++) { switch ((*it).second.elval.typ) { case 'I' : sprintf(buf,"I %s %d", (*it).first.substr(0,64).c_str(), (*it).second.elval.mtv.iv ); sfw = buf; s.PutStr(sfw); break; case 'D' : sprintf(buf,"D %s %.20g", (*it).first.substr(0,64).c_str(), (*it).second.elval.mtv.dv ); sfw = buf; s.PutStr(sfw); break; case 'S' : sprintf(buf,"S %s %s", (*it).first.substr(0,64).c_str(), (*it).second.elval.mtv.strv ); sfw = buf; s.PutStr(sfw); break; default : break; } // Ecriture eventuelle du commentaire associe if ((*it).second.elcomm.length() > 0) { sprintf(buf,"# %s", (*it).second.elcomm.substr(0,256).c_str()); sfw = buf; s.PutStr(sfw); } } sfw = "ZZZZZ--End-of-Varible-List------"; s.PutStr(sfw); } /* --Methode-- */ void ObjFileIO::ReadSelf(PInPersist& s) { char buf[512]; string sfr; int_8 j,iv; r_8 dv; bool ok=true; buf[0] = '\0'; dobj->Clear(); s.GetStr(sfr); // Pour lire les "------- " if (sfr[0] != '-') { // Il y a un champ commentaire a lire s.GetStr(sfr); dobj->Comment() = sfr; } string key=""; while(ok) { s.GetStr(sfr); strncpy(buf, sfr.c_str(), 512); buf[511] = '\0'; if (strncmp(buf,"ZZZZZ",5) == 0) { ok=false; break; } if (buf[0] == '#') { dobj->SetComment(key, buf+2); continue; } j = posc(buf+2, ' ')+2; buf[j] = '\0'; switch (buf[0]) { case 'I' : iv = (int_8)atol(buf+j+1); key = buf+2; dobj->SetI(key, iv); break; case 'D' : dv = atof(buf+j+1); key = buf+2; dobj->SetD(key, dv); break; case 'S' : key = buf+2; dobj->SetS(key, buf+j+1); break; default : break; } } } #ifdef __CXX_PRAGMA_TEMPLATES__ #pragma define_template ObjFileIO #endif #if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES) template class ObjFileIO; #endif