// This may look like C code, but it is really -*- C++ -*-
// Classe DVList : Liste dynamique de variables (valeurs) 
// identifiees par un nom    Reza Ansari - Dec 96

#ifndef DVLIST_H_SEEN
#define DVLIST_H_SEEN

#include "objfio.h"

#include <stdio.h>

#include <iostream.h>

#include <list>
#include <map>
#include <string.h>
#include <string>

namespace SOPHYA {

// Classe utilitaire pour manipuler des variables typees 
class MuTyV {
public:
  union {
  int_4 iv;
  double dv;
  char strv[31];
  } mtv; 
  char typ;

  static char myStrBuf[64];  

  inline MuTyV() { typ = 'I'; mtv.iv = 0;  mtv.dv = 0.;  mtv.strv[0] ='\0'; }
  inline MuTyV(int_4 i) { typ = 'I'; mtv.iv = i; mtv.dv = 0.;  mtv.strv[0] ='\0'; }
  inline MuTyV(float f) { typ = 'D'; mtv.dv = (double)f;  mtv.iv = 0;  mtv.strv[0] ='\0'; }
  inline MuTyV(double d) { typ = 'D'; mtv.dv = d; mtv.iv = 0;  mtv.strv[0] ='\0'; }
  inline MuTyV(char const* s)  { typ = 'S'; strncpy(mtv.strv, s, 31); mtv.strv[30] = '\0'; }
  inline MuTyV(string const& s) { typ = 'S'; strncpy(mtv.strv, s.c_str(), 31); mtv.strv[30] = '\0'; }
  inline int_4  operator= (int_4 v)  { typ = 'I'; mtv.iv = v; return(v); }
  inline float  operator= (float v)  { typ = 'D'; mtv.dv = (double)v; return(v); }
  inline double operator= (double v) { typ = 'D'; mtv.dv = v; return(v); }
  inline char*  operator= (char* s)  { typ = 'S'; strncpy(mtv.strv, s, 31); 
                                       mtv.strv[30] = '\0';  return(s); }
  inline string& operator= (string& s)    { typ = 'S'; strncpy(mtv.strv, s.c_str(), 31); 
                                            mtv.strv[30] = '\0'; return(s); }

  inline operator int_4() { if (typ == 'I')  return(mtv.iv);
                            else if (typ == 'D') return((int_4)mtv.dv); 
                            else return(atol(mtv.strv)); }
  inline operator float() { if (typ == 'I')  return((float)mtv.iv);
                            else if (typ == 'D') return((float)mtv.dv); 
                            else return((float)atof(mtv.strv)); }
  inline operator double() { if (typ == 'I')  return((double)mtv.iv);
                            else if (typ == 'D') return(mtv.dv); 
                            else return(atof(mtv.strv)); }
  inline operator string() { char *ss=myStrBuf;
                            if (typ == 'I')  sprintf(ss,"%d", mtv.iv);
                            else if (typ == 'D') sprintf(ss,"%.20g", mtv.dv);
                            else ss = mtv.strv;
                            return(ss); }
};

//  Classe liste de variables  Dynamic Variable List  

class DVList : public AnyDataObj {
public:
//  enum {classId = ClassId_DVList };

                    DVList();
                    DVList(const DVList&);
                    DVList(char *flnm);

  virtual           ~DVList();

  DVList&           operator= (const DVList&);

  void              Clear();
  DVList&           Merge(const DVList&);

  int_4             GetI(string const& key, int_4 def=-1);
  double            GetD(string const& key, double def=-9.e19);
  string            GetS(string const& key, char* def="");

  void              SetI(string const& key, int_4 val);
  void              SetD(string const& key, double val);
  void              SetS(string const& key, char const*  val);
  void              SetS(string const& key, string val);

  MuTyV&            Get(string const& key);
  inline MuTyV&     operator()  (string const& key)  { return Get(key); }
  inline MuTyV&     operator[]  (string const& key)  { return Get(key); }
  inline string&    Comment() { return(comment); }

  inline void       Print() const  { Print(cout); }  
  virtual void      Print(ostream& os)  const;

  typedef map<string, MuTyV, less<string> >  ValList; 
  inline ValList::const_iterator Begin() { return(mvlist.begin()); } 
  inline ValList::const_iterator End() { return(mvlist.end()); } 
  
//  int_4             ClassId() const        { return classId; }
//  static PPersist*  Create()               { return new DVList;}

//  virtual void      WriteSelf(POutPersist&) const;
//  virtual void      ReadSelf(PInPersist&);

private:
  
  ValList mvlist;
  string comment;
};

inline ostream& operator << (ostream& s, DVList const & dvl)
  {  dvl.Print(s);  return(s);  }

inline POutPersist& operator << (POutPersist& os, DVList & obj)
{ ObjFileIO<DVList> fio(&obj);  fio.Write(os);  return(os); }
inline PInPersist& operator >> (PInPersist& is, DVList & obj)
{ ObjFileIO<DVList> fio(&obj);  fio.Read(is);  return(is); }

// Classe pour la gestion de persistance
// ObjFileIO<DVList>

} // namespace SOPHYA

#endif /* DVLIST_H__SEEN */


