Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

Param.h

Go to the documentation of this file.
00001 
00002 // $Id: Param.h,v 1.3 2009/04/22 16:26:24 fmwk Exp $
00003 //
00004 // messier@indiana.edu
00006 #ifndef CFG_PARAM_H
00007 #define CFG_PARAM_H
00008 #include <iostream>
00009 #include <sstream>
00010 #include <string>
00011 #include <vector>
00012 #include <typeinfo>
00013 #include <ctime>
00014 #include "Config/Exception.h"
00015 
00016 namespace cfg {
00017   
00019   //
00023   class Param {
00024   public:
00025     friend std::ostream& operator<<(std::ostream& os, const Param& p);
00026     
00027   public:
00028     Param();
00029     Param(const Param& p);
00030     Param(const char* name, const char* comment);
00031     template <class T>
00032       Param(const char* name, const T& d, const char* comment);
00033     ~Param();
00034     
00035   public:
00036     const char* GetName()               const;
00037     const char* GetComment()            const;
00038     const char* XMLTag()                const;
00039     void        Print(std::ostream& os) const;
00040 
00041     template <typename T> void Get(T& t) const;
00042     
00043   public:
00044     template <class T> void Set(const T& t);
00045     Param& operator=(const Param& rhs);
00046     
00047     
00048   private:
00049     std::string fName;    
00050     std::string fComment; 
00051     void*       fData;    
00052     
00053   private:
00054     // The following methods allow one to correctly treat the void*
00055     // fData as a class of correct type.  (For those still learning
00056     // C++: the following item defines fDataType as a pointer to a
00057     // function that accepts no arguments and returns a type_info
00058     // reference; similarly, all the rest of these class members are
00059     // function pointers.)
00060     const std::type_info& (*fDataType)(void);
00061     const std::type_info& (*fVectorType)(void);
00062     void                  (*fDataDelete)(void*);
00063     void                  (*fDataCopyCons)(void** dest, const void* src);
00064     void                  (*fDataCopy)(void* dest, const void* src);
00065     void                  (*fDataPrint)(std::ostream& os, const void* d);
00066   };
00068   
00070   // Inlined templated functions
00072   
00076   template <class T>
00077     static const std::type_info& gsDataType(void) 
00078     {
00079       return typeid(T);
00080     }
00081   
00086   template <class T>
00087     static const std::type_info& gsVectorType(void) 
00088     {
00089       return typeid(typename T::value_type);
00090     }
00091   
00092   //......................................................................
00093   
00097   template <class T>
00098     static void gsDataDelete(void* p) 
00099     {
00100       T* pc = (T*)p; delete pc; 
00101     }
00102   
00103   //......................................................................
00104 
00109   template <class T>
00110     static void gsDataCopyCons(void** dest, const void* src) 
00111     {
00112       T* srcc = (T*)src;
00113       T* newt = new T(*srcc);
00114       *dest   = (void*)newt;
00115     }
00116   
00117   //......................................................................
00118 
00123   template <class T>
00124     static void gsDataCopy(void* dest, const void* src) 
00125     {
00126       T* destc = (T*)dest;
00127       T* srcc  = (T*)src;
00128       (*destc) = (*srcc);
00129     }
00130   
00131   //......................................................................
00132 
00136   template <class T>
00137     static void gsDataPrint(std::ostream& os, const void* p)
00138     {
00139       T* pc = (T*)p;
00140       os << (*pc);
00141     }
00142   
00143   //......................................................................
00144   
00148   template <class T>
00149     static std::ostream& operator<<(std::ostream& os, const std::vector<T>& v) 
00150     {
00151       int sz   = v.size();
00152       int szm1 = sz-1;
00153       if ( (typeid(T) == typeid(std::string)) || 
00154            (typeid(T) == typeid(const char*)) ) {
00155         // Add quotes if data is of string type
00156         for (int i=0; i<sz; ++i) {
00157           if (i==szm1) os << "\"" << v[i] << "\"";
00158           else         os << "\"" << v[i] << "\" ";
00159         }
00160       }
00161       else {
00162         // Non-string data gets streamed normally
00163         for (int i=0; i<sz; ++i) {
00164           if (i==szm1) os << v[i];
00165           else         os << v[i] << " ";
00166         }
00167       }
00168       return os;
00169     }
00170   
00171   //......................................................................
00172 
00176   template <class T>
00177     Param::Param(const char* name, const T& d, const char* comment) :
00178     fName        ( name    ),
00179     fComment     ( comment ),
00180     fData        ( 0 ),
00181     fDataType    ( 0 ),
00182     fVectorType  ( 0 ),
00183     fDataDelete  ( 0 ),
00184     fDataCopyCons( 0 ),
00185     fDataCopy    ( 0 ),
00186     fDataPrint   ( 0 )
00187     {
00188       this->Set(d);
00189     }
00190   
00191   //......................................................................
00192 
00198   template <typename T>
00199   void Param::Get( T& item ) const
00200   {
00201     // Basic check: The types match exactly.  In that case, just
00202     // make a copy and return it.
00203     const std::type_info& typeInfo = typeid( T );
00204     if ( typeInfo == this->fDataType() ) 
00205       {
00206         // Copy the parameter into the return object.
00207         item = (*(T*)fData);
00208         return;
00209       }
00210     else
00211       {
00212         // Perhaps the user has asked for a simple type.  This is
00213         // fine, as long this parameter is vector of that type and
00214         // only has a single value.
00215         if ( typeInfo == this->fVectorType() )
00216           {
00217             // The parameter is a vector of the type that the user requests.
00218             std::vector<T>& param = (*(std::vector<T>*)fData);
00219             // Does this vector have exactly one element in it?
00220             if ( param.size() == 1 )
00221               {
00222                 // Yes, so return that item.
00223                 item = param.front();
00224                 return;
00225               }
00226             else
00227               {
00228                 std::ostringstream os;
00229                 os << "Parameter " << this->GetName() << " has multiple values of type "
00230                    << typeInfo.name();
00231                 throw cfg::Exception(Exception::kTypeMismatch,
00232                                      os.str().c_str(),
00233                                      __FILE__,
00234                                      __LINE__);
00235               }
00236           }
00237       }
00238     // If we get here, we don't know how to handle the
00239     // difference between the type the user has requested
00240     // and the type of this parameter.  Throw an exception.
00241     std::ostringstream os;
00242     os << "Attempt to get data of type " << typeInfo.name()
00243        << " from parameter " << this->GetName() << " which is of type "
00244        << this->fDataType().name() << " (a vector of " 
00245        << this->fVectorType().name() << ")";
00246     throw cfg::Exception(Exception::kTypeMismatch,
00247                          os.str().c_str(),
00248                          __FILE__,
00249                          __LINE__);
00250   }
00251   
00252   //......................................................................
00253   
00257   template <class T>
00258     void Param::Set(const T& t)
00259     {
00260       // Delete the data currently held
00261       if (fData) {
00262         this->fDataDelete(fData);
00263         fData = 0;
00264       }
00265       
00266       // Setup the methods for handling this datum
00267       fDataType     = gsDataType<T>;
00268       fVectorType   = gsVectorType<T>;
00269       fDataDelete   = gsDataDelete<T>;
00270       fDataCopyCons = gsDataCopyCons<T>;
00271       fDataCopy     = gsDataCopy<T>;
00272       fDataPrint    = gsDataPrint<T>;
00273       
00274       // Create the data from the data passed in
00275       fDataCopyCons(&fData, &t);
00276     }
00277 }
00278 #endif // CFGPARAM_H
00279 

Generated on Mon Nov 23 04:45:26 2009 for NOvA Offline by  doxygen 1.3.9.1