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

Last change on this file since 4034 was 3619, checked in by cmv, 16 years ago

add various #include<> for g++ 4.3 (jaunty 9.04), cmv 05/05/2009

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