ISIS Core Library 0.7.2 (api 3.0.0)
|
00001 // 00002 // C++ Interface: type 00003 // 00004 // Description: 00005 // 00006 // 00007 // Author: Enrico Reimer<reimer@cbs.mpg.de>, (C) 2009 00008 // 00009 // Copyright: See COPYING file that comes with this distribution 00010 // 00011 // 00012 00013 #ifndef ISISTYPE_HPP 00014 #define ISISTYPE_HPP 00015 00016 #include "value_base.hpp" 00017 00018 #include <string> 00019 #include <functional> 00020 #include <boost/type_traits/is_float.hpp> 00021 #include <boost/type_traits/is_integral.hpp> 00022 00023 namespace isis 00024 { 00025 namespace util 00026 { 00027 00028 template<class TYPE > class Value; 00029 00030 API_EXCLUDE_BEGIN 00032 namespace _internal 00033 { 00034 00040 template<typename T, bool isNumber> class type_compare 00041 { 00042 public: 00043 type_compare() {} // c++11 says we need a user defined constructor here 00044 bool operator()( const util::Value<T> &/*first*/, const ValueBase &/*second*/ )const { 00045 LOG( Debug, error ) << "comparison of " << util::Value<T>::staticName() << " is not supportet"; 00046 return false; 00047 } 00048 }; 00049 00060 template<typename T> class type_compare<T, true> 00061 { 00062 protected: 00063 virtual bool posOverflow( const util::Value<T> &/*first*/, const util::Value<T> &/*second*/ )const {return false;} //default to false 00064 virtual bool negOverflow( const util::Value<T> &/*first*/, const util::Value<T> &/*second*/ )const {return false;} //default to false 00065 virtual bool inRange( const util::Value<T> &/*first*/, const util::Value<T> &/*second*/ )const {return false;} //default to false 00066 public: 00067 bool operator()( const util::Value<T> &first, const ValueBase &second )const { 00068 // ask second for a converter from itself to Value<T> 00069 const ValueBase::Converter conv = second.getConverterTo( util::Value<T>::staticID ); 00070 00071 if ( conv ) { 00072 //try to convert second into T and handle results 00073 util::Value<T> buff; 00074 00075 switch ( conv->convert( second, buff ) ) { 00076 case boost::numeric::cPosOverflow: 00077 LOG( Debug, info ) << "Positive overflow when converting " << second.toString( true ) << " to " << util::Value<T>::staticName() << "."; 00078 return posOverflow( first, buff ); 00079 case boost::numeric::cNegOverflow: 00080 LOG( Debug, info ) << "Negative overflow when converting " << second.toString( true ) << " to " << util::Value<T>::staticName() << "."; 00081 return negOverflow( first, buff ); 00082 case boost::numeric::cInRange: 00083 return inRange( first, buff ); 00084 } 00085 } else { 00086 LOG( Debug, error ) << "No conversion of " << second.getTypeName() << " to " << util::Value<T>::staticName() << " available"; 00087 return false; 00088 } 00089 00090 return false; 00091 } 00092 type_compare() {} // c++11 says we need a user defined constructor here 00093 virtual ~type_compare() {} 00094 }; 00095 00096 template<typename T, bool isNumber> class type_less : public type_compare<T, isNumber> 00097 { 00098 public: // c++11 says we need a user defined constructor here 00099 type_less() {} 00100 };// we are going to specialize this for numeric T below 00101 template<typename T, bool isNumber> class type_greater : public type_compare<T, isNumber> 00102 { 00103 public: // c++11 says we need a user defined constructor here 00104 type_greater() {} 00105 }; 00106 template<typename T, bool isNumber> class type_eq : public type_compare<T, isNumber> 00107 { 00108 protected: 00109 bool inRange( const util::Value<T> &first, const util::Value<T> &second )const { 00110 return static_cast<const T &>( first ) == static_cast<const T &>( second ); 00111 } 00112 public: // c++11 says we need a user defined constructor here 00113 type_eq() {} 00114 }; 00115 00117 template<typename T> class type_less<T, true> : public type_compare<T, true> 00118 { 00119 protected: 00120 bool posOverflow( const util::Value<T> &/*first*/, const util::Value<T> &/*second*/ )const { 00121 return true; //getting an positive overflow when trying to convert second into T, obviously means first is less 00122 } 00123 bool inRange( const util::Value<T> &first, const util::Value<T> &second )const { 00124 return static_cast<const T &>( first ) < static_cast<const T &>( second ); 00125 } 00126 public: // c++11 says we need a user defined constructor here 00127 type_less() {} 00128 }; 00129 00131 template<typename T> class type_greater<T, true> : public type_compare<T, true> 00132 { 00133 protected: 00134 bool negOverflow( const util::Value<T> &/*first*/, const util::Value<T> &/*second*/ )const { 00135 return true; //getting an negative overflow when trying to convert second into T, obviously means first is greater 00136 } 00137 bool inRange( const util::Value<T> &first, const util::Value<T> &second )const { 00138 return static_cast<const T &>( first ) > static_cast<const T &>( second ); 00139 } 00140 public: // c++11 says we need a user defined constructor here 00141 type_greater() {} 00142 }; 00143 00144 } 00146 API_EXCLUDE_END 00147 00159 template<typename TYPE> class Value: public ValueBase 00160 { 00161 TYPE m_val; 00162 static const char m_typeName[]; 00163 protected: 00164 ValueBase *clone() const { 00165 return new Value<TYPE>( *this ); 00166 } 00167 public: 00168 static const unsigned short staticID = _internal::TypeID<TYPE>::value; 00169 Value(): m_val() { 00170 BOOST_STATIC_ASSERT( staticID < 0xFF ); 00171 checkType<TYPE>(); 00172 } 00180 template<typename T> Value( const T &value ) { 00181 m_val = _internal::__cast_to<TYPE>()( this, value ); 00182 BOOST_STATIC_ASSERT( staticID < 0xFF ); 00183 checkType<TYPE>(); 00184 } 00192 std::string toString( bool labeled = false )const { 00193 std::string ret; 00194 Reference ref = copyByID( Value<std::string>::staticID ); 00195 00196 if ( ref.isEmpty() ) { 00197 LOG( Debug, warning ) << "Automatic conversion of " << *this << " to string failed. Falling back to boost::lexical_cast<std::string>"; 00198 ret = boost::lexical_cast<std::string>( m_val ); 00199 } else { 00200 ret = ref->castTo<std::string>(); 00201 } 00202 00203 if ( labeled )ret += "(" + staticName() + ")"; 00204 00205 return ret; 00206 } 00207 00208 std::string getTypeName()const {return staticName();} 00209 unsigned short getTypeID()const {return staticID;} 00210 bool isFloat() const {return boost::is_float< TYPE >::value;} 00211 bool isInteger() const {return boost::is_integral< TYPE >::value;} 00212 00214 virtual bool operator==( const ValueBase &second )const { 00215 if ( second.is<TYPE>() ) { 00216 return m_val == second.castTo<TYPE>(); 00217 } else 00218 return false; 00219 } 00220 00222 static std::string staticName() {return m_typeName;} 00223 00235 operator const TYPE &()const {return m_val;} 00236 00248 operator TYPE &() {return m_val;} 00249 00259 bool gt( const ValueBase &ref )const { 00260 static const _internal::type_greater<TYPE, boost::is_arithmetic<TYPE>::value > greater; 00261 return greater.operator()( *this, ref ); 00262 } 00263 00273 bool lt( const ValueBase &ref )const { 00274 static const _internal::type_less<TYPE, boost::is_arithmetic<TYPE>::value > less; 00275 return less( *this, ref ); 00276 } 00277 00287 bool eq( const ValueBase &ref )const { 00288 static const _internal::type_eq<TYPE, boost::is_arithmetic<TYPE>::value > equal; 00289 return equal( *this, ref ); 00290 } 00291 00292 virtual ~Value() {} 00293 }; 00294 00295 template<typename T> const util::Value<T>& ValueBase::castToType() const 00296 { 00297 checkType<T>(); 00298 return m_cast_to<util::Value<T> >(); 00299 } 00300 template<typename T> const T &ValueBase::castTo() const 00301 { 00302 const util::Value<T> &ret = castToType<T>(); 00303 return ret.operator const T & (); 00304 } 00305 template<typename T> util::Value<T>& ValueBase::castToType() 00306 { 00307 checkType<T>(); 00308 return m_cast_to<util::Value<T> >(); 00309 } 00310 template<typename T> T &ValueBase::castTo() 00311 { 00312 util::Value<T> &ret = castToType<T>(); 00313 return ret.operator T & (); 00314 } 00315 00316 template<typename T> bool ValueBase::is()const 00317 { 00318 checkType<T>(); 00319 return getTypeID() == util::Value<T>::staticID; 00320 } 00321 00322 } 00323 } 00324 00325 #endif //DATATYPE_INC