00001
00002
00003
00004
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
00055
00056
00057
00058
00059
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
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
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
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
00202
00203 const std::type_info& typeInfo = typeid( T );
00204 if ( typeInfo == this->fDataType() )
00205 {
00206
00207 item = (*(T*)fData);
00208 return;
00209 }
00210 else
00211 {
00212
00213
00214
00215 if ( typeInfo == this->fVectorType() )
00216 {
00217
00218 std::vector<T>& param = (*(std::vector<T>*)fData);
00219
00220 if ( param.size() == 1 )
00221 {
00222
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
00239
00240
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
00261 if (fData) {
00262 this->fDataDelete(fData);
00263 fData = 0;
00264 }
00265
00266
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
00275 fDataCopyCons(&fData, &t);
00276 }
00277 }
00278 #endif // CFGPARAM_H
00279