Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef PANGOLIN_VARS_INTERNAL_H
00029 #define PANGOLIN_VARS_INTERNAL_H
00030
00031 #include <boost/utility.hpp>
00032 #include <boost/type_traits.hpp>
00033
00034 #include <iostream>
00035
00036
00037 namespace pangolin
00038 {
00039
00040 struct BadInputException : std::exception
00041 {
00042 char const* what() const throw()
00043 {
00044 return "Failed to serialise type";
00045 }
00046 };
00047
00048
00049 template<typename T, typename S> struct Convert
00050 {
00051 static T Do(const S& src)
00052 {
00053 std::ostringstream oss;
00054 oss << src;
00055 std::istringstream iss(oss.str());
00056 T target;
00057 iss >> target;
00058
00059 if(iss.fail())
00060 throw BadInputException();
00061
00062 return target;
00063
00064 }
00065 };
00066
00067
00068 template<> struct Convert<bool,std::string>
00069 {
00070 static bool Do(const std::string& src)
00071 {
00072 bool target;
00073 std::istringstream iss(src);
00074 iss >> target;
00075
00076 if(iss.fail())
00077 {
00078 std::istringstream iss2(src);
00079 iss2 >> std::boolalpha >> target;
00080 if( iss2.fail())
00081 throw BadInputException();
00082 }
00083
00084 return target;
00085 }
00086 };
00087
00088
00089 template<typename T> struct Convert<T,std::string>
00090 {
00091 static T Do(const std::string& src)
00092 {
00093 T target;
00094 std::istringstream iss(src);
00095 iss >> target;
00096
00097 if(iss.fail())
00098 throw BadInputException();
00099
00100 return target;
00101 }
00102 };
00103
00104
00105 template<typename S> struct Convert<std::string, S>
00106 {
00107 static std::string Do(const S& src)
00108 {
00109 std::ostringstream oss;
00110 oss << src;
00111 return oss.str();
00112 }
00113 };
00114
00115
00116 template<> struct Convert<std::string, std::string>
00117 {
00118 static std::string Do(const std::string& src)
00119 {
00120 return src;
00121 }
00122 };
00123
00124 struct UnknownTypeException : std::exception
00125 {
00126 char const* what() const throw()
00127 {
00128 return "Unknown type in generic container";
00129 }
00130 };
00131
00132 struct _Var
00133 {
00134 _Var()
00135 : val(NULL), val_default(NULL), generic(false)
00136 {}
00137 ~_Var()
00138 {
00139 clean();
00140 }
00141
00142 void create(void* new_val, void* new_val_default, const char* new_type_name)
00143 {
00144 clean();
00145 val = new_val;
00146 val_default = new_val_default;
00147 type_name = new_type_name;
00148 generic = false;
00149 }
00150
00151 void clean()
00152 {
00153 if (val!=NULL)
00154 {
00155 if( type_name == typeid(double).name() )
00156 {
00157 delete (double *) val;
00158 }
00159 else if( type_name == typeid(int).name() )
00160 {
00161 delete (int *) val;
00162 }
00163 else if( type_name == typeid(std::string).name() )
00164 {
00165 delete (std::string *) val;
00166 }
00167 else if( type_name == typeid(bool).name() )
00168 {
00169 delete (bool *) val;
00170 }
00171 else
00172 {
00173 throw UnknownTypeException();
00174 }
00175 }
00176
00177 if (val_default!=NULL)
00178 {
00179 if( type_name == typeid(double).name() )
00180 {
00181 delete (double *) val_default;
00182 }
00183 else if( type_name == typeid(int).name() )
00184 {
00185 delete (int *) val_default;
00186 }
00187 else if( type_name == typeid(std::string).name() )
00188 {
00189 delete (std::string *) val_default;
00190 }
00191 else if( type_name == typeid(bool).name() )
00192 {
00193 delete (bool *) val_default;
00194 }
00195 else
00196 {
00197 throw UnknownTypeException();
00198 }
00199 }
00200 }
00201
00202
00203
00204
00205 void* val;
00206 void* val_default;
00207
00208 const char* type_name;
00209
00210 bool generic;
00211 std::string meta_full_name;
00212 std::string meta_friendly;
00213 double meta_range[2];
00214 double meta_increment;
00215 int meta_flags;
00216 bool meta_gui_changed;
00217 bool logscale;
00218 };
00219
00220
00221 template<typename T, typename S, class Enable1 = void, class Enable2 = void, class Enable3 = void>
00222 struct _Accessor;
00223
00224 template<typename T>
00225 struct Accessor
00226 {
00227 virtual ~Accessor() {}
00228 virtual const T& Get() const = 0;
00229 virtual void Set(const T& val) = 0;
00230 static Accessor<T>* Create(const char* typeidname, void* var)
00231 {
00232 if( typeidname == typeid(double).name() )
00233 {
00234 return new _Accessor<T,double>( *(double*)var);
00235 }
00236 else if( typeidname == typeid(int).name() )
00237 {
00238 return new _Accessor<T,int>( *(int*)var );
00239 }
00240 else if( typeidname == typeid(std::string).name() )
00241 {
00242 return new _Accessor<T,std::string>( *(std::string*)var );
00243 }
00244 else if( typeidname == typeid(bool).name() )
00245 {
00246 return new _Accessor<T,bool>( *(bool*)var );
00247 }
00248 else
00249 {
00250 throw UnknownTypeException();
00251 }
00252 }
00253 };
00254
00255 template<typename T, typename S>
00256 struct _Accessor<T,S, typename boost::enable_if_c<
00257 (boost::is_scalar<T>::value || boost::is_same<T,bool>::value) &&
00258 (boost::is_scalar<S>::value || boost::is_same<S,bool>::value) &&
00259 !boost::is_same<T,S>::value
00260 >::type> : Accessor<T>
00261 {
00262 _Accessor(S& var) : var(var)
00263 {
00264
00265 }
00266
00267 const T& Get() const
00268 {
00269 cache = (T)var;
00270 return cache;
00271 }
00272
00273 void Set(const T& val)
00274 {
00275 var = (S)val;
00276 }
00277
00278 S& var;
00279 mutable T cache;
00280 };
00281
00282 template<typename T>
00283 struct _Accessor<T,T> : Accessor<T>
00284 {
00285 _Accessor(T& var) : var(var)
00286 {
00287
00288 }
00289
00290 const T& Get() const
00291 {
00292 return var;
00293 }
00294
00295 void Set(const T& val)
00296 {
00297 var = val;
00298 }
00299 T& var;
00300 };
00301
00302 template<typename T, typename S>
00303 struct _Accessor<T,S ,typename boost::enable_if_c<
00304 !((boost::is_scalar<T>::value || boost::is_same<T,bool>::value) &&
00305 (boost::is_scalar<S>::value || boost::is_same<S,bool>::value)) &&
00306 !boost::is_same<T,S>::value
00307 >::type> : Accessor<T>
00308 {
00309 _Accessor(S& var) : var(var)
00310 {
00311 }
00312
00313 const T& Get() const
00314 {
00315
00316 cache = Convert<T,S>::Do(var);
00317
00318
00319
00320
00321 return cache;
00322 }
00323
00324 void Set(const T& val)
00325 {
00326
00327 var = Convert<S,T>::Do(val);
00328
00329
00330
00331 }
00332 S& var;
00333 mutable T cache;
00334 };
00335
00336 }
00337
00338 #endif // PANGOLIN_VARS_INTERNAL_H
00339