ISIS Core Library 0.7.2 (api 3.0.0)

/scr/tee1/isis/lib/Core/CoreUtils/value.hpp

Go to the documentation of this file.
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