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

Last change on this file since 2406 was 2339, checked in by ansari, 23 years ago

Compli avec SGI-CC -LANG:std et remplacement template <> pour SGI-CC par DECL_TEMP_SPEC - Reza 10/03/2003

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