source: Sophya/trunk/SophyaLib/BaseTools/dvlist.cc@ 3113

Last change on this file since 3113 was 2936, checked in by ansari, 19 years ago

Correction permettant d'aavoir des cle avec blanc (espace) ds DVList - Reza 3 Avril 2006

File size: 19.0 KB
Line 
1// Classe Dynamic Variable List (DVList) de PEIDA
2// R. Ansari 1997
3// LAL (Orsay) / IN2P3-CNRS DAPNIA/SPP (Saclay) / CEA
4
5#include "sopnamsp.h"
6#include "machdefs.h"
7#include <stdlib.h>
8#include <stdio.h>
9
10#include "dvlist.h"
11#include "strutil.h"
12
13//++
14// Class DVList
15// Lib BaseTools
16// include dvlist.h
17//
18// Cette classe permet de gérer une ensemble de variables (ou paramètres)
19// pouvant être définies dynamiquement à l'execution. Le nom des
20// variables ne doit pas contenir de blancs ("<espace>") et est
21// limité à 64 caractères maximum. Cette classe
22// offre la possibilité de sauvegarder l'ensemble
23// des variables (Nom, Type, Valeur) dans un fichier, ou de
24// recréer l'objet DVList et l'ensemble de ses variables à
25// partir d'un fichier (Objet PPersist). Une zone commentaire (max=320 c.)
26// est associée à chaque objet DVList, accessible à travers
27// la méthode "Comment()". Les objets de cette classe sont
28// en particulier destinés à être inclus dans d'autres objets
29// PPersist plus complexes. La classe DVList gère des
30// variables de type entier ("int_8"), réél double précision ("r_8")
31// et de type chaine de caracteres ("string, char*", maxi 30 caracteres ).
32// Une classe intermédiaire (*MuTyV*) est utilisée pour représenter une
33// variable et fournit les services de conversion entre les différents types.
34//--
35//--
36//++
37// Links Parents
38// PPersist
39//--
40
41
42static MuTyV ddvdum(-9.e19);
43
44
45/*!
46 \class SOPHYA::DVList
47 \ingroup BaseTools
48 This class can be used to construct list of values associated with names.
49 Variables names should not contain space characters and is limited to 64
50 characters. The DVList class uses \b SOPHYA::MuTyV objects to hold values
51 of type string, integer (\b int_8) or float (\b r_8) or time/date (TimeStamp).
52 A comment string can be associated with each variable name. A global comment string
53 can be attached to the DVList object. DVList objects can conveniently be
54 used to represent FITS headers. The class \b SOPHYA::ObjFileIO<DVList>
55 handles serialisation for DVList. (See SOPHYA::PPersist ).
56
57 \sa SOPHYA::ObjFileIO<DVList>
58 \sa SOPHYA::MuTyV
59
60 \code
61 // ------- Using DVList objects ------
62 DVList dvl;
63 dvl("toto") = 14; // Integer type value (=14) named toto
64 dvl("titi") = 25.5; // float type value (=25.5) named titi
65 dvl("tata") = "Bonjour !"; // string type value (="Bonjour !") named tata
66 // Upper and lower case letters are distinguished
67 dvl("hello") = 88;
68 dvl("Hello") = 77.77;
69 dvl("ToDay") = TimeStamp();
70 dvl.Comment() = "DVList test object, with values named hello, Hello ";
71 // Saving the dvl object into a PPF file
72 POutStream os("dvl.ppf");
73 os << dvl;
74 // later on ...
75 DVList dvlr;
76 PInStream is("dvl.ppf");
77 is << dvlr;
78 int k = dvlr["toto"] ; // k = 14
79 r_8 b = dvlr["titi"] ; // b = 25.5
80 string s = dvlr["tata"] ; // s = "Bonjour !"
81 int m = dvlr["hello"] ; // m = 88
82
83 \endcode
84*/
85
86//++
87// Titre Constructeurs
88//--
89
90//++
91// DVList()
92// Constructeur par défaut
93// DVList(DVList& cfd)
94// Constructeur par copie. Le nouvel objet est une copie complète de "cfd"
95// DVList(char* flnm)
96// Constructeur avec initialisation à partir du contenu du fichier (PPF)
97// "flnm". Le fichier doit avoir été créé par la méthode "Write()"
98//--
99
100/* --Methode-- */
101/*! Default constructor */
102DVList::DVList()
103{
104comment = "";
105}
106
107/* --Methode-- */
108/*! copy constructor */
109DVList::DVList(const DVList& dvl)
110{
111Merge(dvl);
112}
113
114/* --Methode-- */
115/*! Copy constructor - Object initialized using the PPF file \b flnm */
116DVList::DVList(char *flnm)
117{
118PInPersist s(flnm);
119ObjFileIO<DVList> fiodvl(this);
120fiodvl.Read(s);
121}
122
123
124/* --Methode-- */
125DVList::~DVList()
126{
127}
128
129//++
130// Titre Gestion des variables et opérateurs
131//--
132
133//++
134// void Clear()
135// Supprime la définition de toutes les variables de l'objet.
136// DVList& Merge(const DVList& lv)
137// Fusionne l'objet avec la liste des variables de l'objet "lv"
138// DVList& operator= (const DVList& cofr)
139// Remplace la liste des variables de l'objet par celle de l'objet "cofr".
140//--
141
142/* --Methode-- */
143/*! Copy operator - Replaces the variables list with the list from \b dvl */
144DVList& DVList::operator= (const DVList& dvl)
145{
146Clear();
147return(Merge(dvl));
148}
149
150
151/* --Methode-- */
152/*! Resets the object and clears the variable list and global comment */
153void DVList::Clear()
154{
155mvlist.erase(mvlist.begin(), mvlist.end());
156comment = "";
157}
158
159/* --Methode-- */
160/*! Appends the values from the object \b dvl to the objects list */
161DVList& DVList::Merge(const DVList& dvl)
162{
163ValList::const_iterator it;
164for(it = dvl.mvlist.begin(); it != dvl.mvlist.end(); it++)
165 {
166 switch ((*it).second.elval.Type())
167 {
168 case MuTyV::MTVInteger :
169 SetI((*it).first, (*it).second.elval.GetIntPart());
170 break;
171 case MuTyV::MTVFloat :
172 SetD((*it).first, (*it).second.elval.GetRealPart());
173 break;
174 case MuTyV::MTVComplex :
175 SetZ((*it).first, complex<r_8>((*it).second.elval.GetRealPart(), (*it).second.elval.GetImagPart()));
176 break;
177 case MuTyV::MTVString :
178 SetS((*it).first, *((*it).second.elval.GetStringPointer()));
179 break;
180 default :
181 break;
182 }
183 SetComment((*it).first, (*it).second.elcomm);
184 }
185comment = comment + "\n" + dvl.comment;
186return(*this);
187}
188
189
190//++
191// int_8 GetI(string const& key, int_8 def=-1)
192// r_8 GetD(string const& key, r_8 def=-9.e19)
193// string GetS(string const& key, char* def="")
194// Retourne la valeur de la variable de nom "key" et de type entier, réél,
195// chaine de caracteres.
196// Si la variable n'existe pas, la valeur par défaut "def" est renvoyée.
197// string GetComment(string const& key)
198// Retourne le commentaire associé à la variable de nom "key".
199//--
200
201/* --Methode-- */
202/*! Returns the value corresponding to name \b key, converted to integer
203 Default value \b def is returned if name \b key not found */
204int_8 DVList::GetI(string const& key, int_8 def) const
205{
206ValList::const_iterator it = mvlist.find(key);
207if (it == mvlist.end()) return(def);
208return( (int_8)((*it).second.elval) );
209}
210
211/* --Methode-- */
212/*! Returns the value corresponding to name \b key, converted to double
213 Default value \b def is returned if name \b key not found */
214r_8 DVList::GetD(string const& key, r_8 def) const
215{
216ValList::const_iterator it = mvlist.find(key);
217if (it == mvlist.end()) return(def);
218return( (r_8)((*it).second.elval) );
219}
220
221/* --Methode-- */
222/*! Returns the value corresponding to name \b key, converted to complex
223 Default value \b def is returned if name \b key not found */
224complex<r_8> DVList::GetZ(string const& key, complex<r_8> def) const
225{
226ValList::const_iterator it = mvlist.find(key);
227if (it == mvlist.end()) return(def);
228/*
229 Appel explicite de l'operateur de conversion
230 suite a la suggestion de M. Reinecke, Reza 31/7/2002
231#if defined(__GNUG__)
232complex<r_8> z;
233z = (*it).second.elval;
234return(z);
235#else
236return( (complex<r_8>)(*it).second.elval );
237#endif
238 --- Appel explicite de l'operateur de conversion sur l'objet MuTyV
239*/
240return( (*it).second.elval.operator complex<r_8>() );
241}
242
243/* --Methode-- */
244/*! Returns the value corresponding to name \b key, converted to string
245 Default value \b def is returned if name \b key not found */
246string DVList::GetS(string const& key, char* def) const
247{
248ValList::const_iterator it = mvlist.find(key);
249if (it == mvlist.end()) return(def);
250return( (string)((*it).second.elval) );
251}
252
253/* --Methode-- */
254/*! Returns the comment associated with name \b key */
255string DVList::GetComment(string const& key) const
256{
257ValList::const_iterator it = mvlist.find(key);
258if (it == mvlist.end()) return("");
259return((*it).second.elcomm);
260}
261
262//++
263// void SetI(string const& key, int_8 val)
264// void SetD(string const& key, r_8 val)
265// void SetZ(string const& key, complex<r_8> val)
266// void SetS(string const& key, char* val)
267// void SetS(string const& key, string val)
268// Crée la variable de nom "key", de type entier, double, complexe, string et
269// lui attribue la valeur "val". Si une variable du même nom existe,
270// sa valeur et eventuellement son type sont modifiés. Les noms de
271// variables ne doivent pas contenir de caractères spéciaux,
272// en particulier pas de CR/LF.
273// void SetComment(string const& key, string const& comm)
274// Modifie le commentaire associé à la variable de nom "key", si
275// celle-ci existe. Le texte du commentaire ne doit pas contenir
276// de caractères spéciaux, et en particulier pas de CR/LF.
277//--
278
279/* --Methode-- */
280/*! Removes the definition and value associated with the name \b key.
281 Return \c true if the \b key is found in the list, \c false otherwise. */
282bool DVList::DeleteKey(string const& key)
283{
284ValList::iterator it = mvlist.find(key);
285if (it == mvlist.end()) return(false);
286mvlist.erase(it);
287return(true);
288}
289
290/* --Methode-- */
291/*! Return \c true if the \b key is found in the list, \c false otherwise. */
292bool DVList::HasKey(string const& key) const
293{
294ValList::const_iterator it = mvlist.find(key);
295if (it == mvlist.end()) return(false);
296return(true);
297}
298
299
300/* --Methode-- */
301/*! Appends or sets the integer value \b val in the list with name \b key */
302void DVList::SetI(string const& key, int_8 val)
303{
304Get(key) = (int_8)val;
305}
306
307/* --Methode-- */
308void DVList::SetD(string const& key, r_8 val)
309/*! Appends or sets the double value \b val in the list with name \b key */
310{
311Get(key) = (r_8)val;
312}
313
314/* --Methode-- */
315void DVList::SetZ(string const& key, complex<r_8> val)
316/*! Appends or sets the complex value \b val in the list with name \b key */
317{
318Get(key) = val;
319}
320
321/* --Methode-- */
322/*! Appends or sets the string value \b val in the list with name \b key */
323void DVList::SetS(string const& key, char const* val)
324{
325MuTyV div(val);
326Get(key) = div;
327}
328
329/* --Methode-- */
330/*! Appends or sets the string value \b val in the list with name \b key */
331void DVList::SetS(string const& key, string const& val)
332{
333MuTyV div(val);
334Get(key) = div;
335}
336
337/* --Methode-- */
338/*! Appends or sets the TimeStamp value \b val in the list with name \b key */
339void DVList::SetT(string const& key, TimeStamp const& val)
340{
341MuTyV div(val);
342Get(key) = div;
343}
344
345/* --Methode-- */
346/*! Assigns the comment \b comm with the name \b key .
347 Does nothing if the entry with name is not present in the list */
348void DVList::SetComment(string const& key, string const& comm)
349{
350ValList::iterator it = mvlist.find(key);
351if (it == mvlist.end()) return;
352(*it).second.elcomm = comm;
353}
354
355//++
356// MuTyV& Get(string const& key)
357// Renvoie une référence sur l'objet "MuTyV" de la liste avec le nom "key".
358// Si cet objet (variable) n'existe pas, il est créé.
359// MuTyV& operator() (string const& key)
360// MuTyV& operator[] (string const& key)
361//
362// Renvoie la variable de nom "key". Equivalent à "Get(key)".
363// string& Comment()
364// Renvoie une référence sur le champ commentaire de l'objet.
365//--
366
367/* --Methode-- */
368/*! Return the MuTyV value associated with name \b key .
369 Integer 0 is returned if \b key is not present in the list */
370MuTyV DVList::Get(string const& key) const
371{
372ValList::const_iterator it = mvlist.find(key);
373if (it == mvlist.end()) return(MuTyV( (int_8) 0));
374else return((*it).second.elval);
375}
376
377/* --Methode-- */
378/*! Return the MuTyV value associated with name \b key .
379 Adds an entry of type integer in the list if \b key is not present in the list */
380MuTyV& DVList::Get(string const& key)
381{
382size_t l = key.length();
383if (l < 1) return(ddvdum);
384// dvlElement xxx = {(int_8)0 , ""}; marche pas sur mac/CW (!) - cf DY
385dvlElement xxx; xxx.elval = (int_8)0; xxx.elcomm = "";
386ValList::iterator it = mvlist.find(key);
387if (it == mvlist.end()) mvlist[key] = xxx;
388it = mvlist.find(key);
389if (it == mvlist.end()) return(ddvdum);
390else return((*it).second.elval);
391}
392
393//++
394// Titre Entrée-Sortie
395//--
396
397//++
398// void Print()
399// Imprime (sur "cout") la liste des variables et leurs valeurs.
400// void Print(ostream& os)
401// Imprime sur le flot "os" la liste des variables et leurs valeurs.
402// ostream& operator << (ostream& s, DVList& dvl)
403// sortie sur flot "s" (Appel a "Print(s)").
404//--
405
406/* --Methode-- */
407/*! Prints a brief description of object on on the output stream \b os */
408void DVList::Show(ostream& os) const
409{
410os << "DVList::Show() - NVar= " << (int)mvlist.size() << "\n";
411os << comment << endl;
412}
413
414/* --Methode-- */
415/*! Prints the list of variables on the output stream \b os */
416void DVList::Print(ostream& os) const
417{
418os << "DVList::Print() - NVar= " << (int)mvlist.size() << "\n";
419if (comment.length() > 0) os << comment << endl;
420char buff[1024];
421TimeStamp ts;
422ValList::const_iterator it;
423for(it = mvlist.begin(); it != mvlist.end(); it++) {
424 switch ((*it).second.elval.Type())
425 {
426 case MuTyV::MTVInteger :
427 sprintf(buff, "%s = %ld (int) %s\n", (*it).first.substr(0,64).c_str(),
428 (long)((*it).second.elval.GetIntPart()), (*it).second.elcomm.substr(0,128).c_str());
429 break;
430 case MuTyV::MTVFloat :
431 sprintf(buff, "%s = %.20g (double) %s\n", (*it).first.substr(0,64).c_str(),
432 (*it).second.elval.GetRealPart(), (*it).second.elcomm.substr(0,128).c_str());
433 break;
434 case MuTyV::MTVComplex :
435 sprintf(buff, "%s = %.20g %.20g i (complex) %s\n", (*it).first.substr(0,64).c_str(),
436 (*it).second.elval.GetRealPart(), (*it).second.elval.GetImagPart(), (*it).second.elcomm.substr(0,128).c_str());
437 break;
438 case MuTyV::MTVString :
439 sprintf(buff, "%s = %s (string) %s\n", (*it).first.substr(0,64).c_str(),
440 (*it).second.elval.GetStringPointer()->substr(0,800).c_str(), (*it).second.elcomm.substr(0,128).c_str());
441 break;
442 case MuTyV::MTVTimeStamp :
443 ts.Set((*it).second.elval.GetRealPart());
444 sprintf(buff, "%s = %s (TimeStamp) %s\n", (*it).first.substr(0,64).c_str(),
445 ts.ToString().c_str(), (*it).second.elcomm.substr(0,128).c_str());
446 break;
447 default :
448 break;
449 }
450 os << (string)buff;
451 }
452os << endl;
453}
454
455
456//++
457// Titre Exemples
458// Utilisation des objets *MuTyV* :
459//| MuTyV mvu; // Declaration d'une variable
460//| mvu = 60; // mvu est de type entier (= 60)
461//| mvu = 66.6; // et double (= 66.6) maintenant ...
462//| MuTyV mvi(14); // On construit une variable entiere = 14
463//| r_4 x = mvi; // x vaut 14.0
464//| MuTyV mvd(44.4); // Variable double = 44.4
465//| int k = mvd; // k vaut 44
466//| MuTyV mvs("Bonjour, Ca va ?"); // Variable chaine de caracteres
467//| string s = mvs; // s vaut "Bonjour, Ca va ?"
468// Utilisation des *DVList* :
469//| DVList dvl;
470//| dvl("toto") = 14;
471//| dvl("titi") = 25.5;
472//| dvl("tata") = "Bonjour, Ca va ?";
473// Majuscules et minuscules sont differenciees pour les noms, pas de blanc ...
474//| dvl("hello") = 88;
475//| dvl("Hello") = 77.77;
476//| dvl.Comment() = "Test d'objet DVList, avec variables hello, Hello ";
477//| dvl.Write("dvlist.ppf");
478// Plus loin, ou dans un autre programme, on relit le fichier fabrique plus haut
479//| DVList dvlr("dvlist.ppf");
480//| int k = dvlr["toto"] ; // k = 14
481//| r_8 b = dvlr["titi"] ; // b = 25.5
482//| string s = dvlr["tata"] ; // s = "Bonjour, Ca va ?"
483//| r_4 c = dvlr["Hello"] ; // c = 77.77
484//| int l = dvlr["Hello"] ; // l = 77
485//| int m = dvlr["hello"] ; // m = 88
486//--
487
488
489//----------------------------------------------------------
490// Classe pour la gestion de persistance
491// ObjFileIO<DVList>
492//----------------------------------------------------------
493
494/* --Methode-- */
495DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
496void ObjFileIO<DVList>::WriteSelf(POutPersist& s) const
497{
498if (dobj == NULL)
499 throw NullPtrError("ObjFileIO<DVList>::WriteSelf() dobj=NULL");
500
501char buf[1024];
502string sfw;
503int lc = dobj->Comment().length();
504// itab - 0 : Version, 1 : NVar, 2 : Comment length, 3 reserved
505uint_4 itab[4];
506itab[0] = 2; // Version number = 2
507itab[1] = dobj->Size();
508itab[2] = lc;
509itab[3] = 0;
510s.Put(itab, 4);
511
512if (lc > 0) s.PutStr(dobj->Comment());
513sfw = "\n----Variable-List---------------\n";
514s.PutStr(sfw);
515
516DVList::ValList::const_iterator it;
517for(it = dobj->Begin(); it != dobj->End(); it++) {
518 switch ((*it).second.elval.Type()) {
519 case MuTyV::MTVInteger :
520 sprintf(buf,"I %s %ld\n", (*it).first.substr(0,64).c_str(), (long)((*it).second.elval.GetIntPart()) );
521 sfw = buf; s.PutStr(sfw);
522 break;
523 case MuTyV::MTVFloat :
524 sprintf(buf,"F %s %.20g\n", (*it).first.substr(0,64).c_str(), (*it).second.elval.GetRealPart() );
525 sfw = buf; s.PutStr(sfw);
526 break;
527 case MuTyV::MTVComplex :
528 sprintf(buf,"Z %s %.20g %.20g\n", (*it).first.substr(0,64).c_str(), (*it).second.elval.GetRealPart(),
529 (*it).second.elval.GetImagPart());
530 sfw = buf; s.PutStr(sfw);
531 break;
532 case MuTyV::MTVString :
533 sprintf(buf,"S %s %s\n", (*it).first.substr(0,64).c_str(), (*it).second.elval.GetStringPointer()->substr(0,960).c_str() );
534 sfw = buf; s.PutStr(sfw);
535 break;
536 case MuTyV::MTVTimeStamp :
537 sprintf(buf,"T %s %.20g\n", (*it).first.substr(0,64).c_str(), (*it).second.elval.GetRealPart() );
538 sfw = buf; s.PutStr(sfw);
539 break;
540 default :
541 break;
542 }
543// Ecriture eventuelle du commentaire associe
544 if ((*it).second.elcomm.length() > 0) {
545 sprintf(buf,"# %s", (*it).second.elcomm.substr(0,256).c_str());
546 sfw = buf; s.PutStr(sfw);
547 }
548}
549
550sfw = "ZZZZZ--End-of-Variable-List------"; s.PutStr(sfw);
551}
552
553/* --Methode-- */
554DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */
555void ObjFileIO<DVList>::ReadSelf(PInPersist& s)
556{
557char buf[1024];
558string sfr;
559int_8 j,iv,k;
560r_8 dv, dvi;
561bool ok=true;
562buf[0] = '\0';
563if (dobj == NULL) dobj = new DVList;
564else dobj->Clear();
565
566// itab - 0 : Version, 1 : NVar, 2 : Comment length, 3 reserved
567uint_4 itab[4];
568s.Get(itab, 4);
569if (itab[2] > 0) { // Il y a un champ commentaire a lire
570 s.GetStr(sfr);
571 dobj->Comment() = sfr;
572 }
573
574s.GetStr(sfr); // Pour lire les "------- "
575
576string key="";
577while(ok) {
578 s.GetStr(sfr);
579 strncpy(buf, sfr.c_str(), 1024);
580 buf[1023] = '\0';
581 j = strlen(buf)-1;
582 if ( (j >= 0) && (buf[j] == '\n') ) buf[j] = '\0';
583 if (strncmp(buf,"ZZZZZ",5) == 0) { ok=false; break; }
584 if (buf[0] == '#') {
585 dobj->SetComment(key, buf+2);
586 continue;
587 }
588 j = posc(buf+2, ' ')+2;
589 buf[j] = '\0';
590 switch (buf[0]) {
591 case 'I' :
592 iv = (int_8)atol(buf+j+1);
593 key = buf+2;
594 dobj->SetI(key, iv);
595 break;
596 case 'F' :
597 dv = atof(buf+j+1);
598 key = buf+2;
599 dobj->SetD(key, dv);
600 break;
601 case 'Z' :
602 k = posc(buf+j+1, ' ')+j+1;
603 buf[k] = '\0';
604 dv = atof(buf+j+1);
605 dvi = atof(buf+k+1);
606 key = buf+2;
607 dobj->SetZ(key, complex<r_8>(dv, dvi));
608 break;
609 case 'S' :
610 key = buf+2;
611 dobj->SetS(key, buf+j+1);
612 break;
613 case 'T' :
614 dv = atof(buf+j+1);
615 key = buf+2;
616 dobj->SetT(key, TimeStamp(dv));
617 break;
618 default :
619 break;
620 }
621 }
622if (dobj->Size() != itab[1]) // Probleme !!!
623 throw FileFormatExc("ObjFileIO<DVList>::ReadSelf() Error in Nb. Variables !");
624}
625
626#ifdef __CXX_PRAGMA_TEMPLATES__
627#pragma define_template ObjFileIO<DVList>
628#endif
629
630#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
631template class SOPHYA::ObjFileIO<DVList>;
632#endif
Note: See TracBrowser for help on using the repository browser.