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 
00029 
00030 #ifndef RVE_PROPERTIES_PROPERTY_VALUE_H
00031 #define RVE_PROPERTIES_PROPERTY_VALUE_H
00032 
00033 #include "forwards.h"
00034 
00035 #include <sstream>
00036 
00037 #include <ros/types.h>
00038 #include <ros/assert.h>
00039 
00040 #include <typeinfo>
00041 #include <stdexcept>
00042 
00043 #include <cstdlib>
00044 
00045 namespace rve_properties
00046 {
00047 
00048 template<typename T>
00049 struct ValueTraits
00050 {
00051   
00052   inline static const char* typeName() { return "unknown"; }
00053   inline static std::string toString(void* mem)
00054   {
00055     T* val = reinterpret_cast<T*>(mem);
00056     std::stringstream ss;
00057     ss << *val;
00058     return ss.str();
00059   }
00060 
00061   inline static void fromString(void* mem, const std::string& str)
00062   {
00063     T* val = reinterpret_cast<T*>(mem);
00064     std::istringstream in(str);
00065     in >> *val;
00066   }
00067 };
00068 
00069 #define RVE_PROPERTIES_DEFINE_SIMPLE_VALUE_TRAITS(type, name) \
00070   template<> \
00071   struct ValueTraits<type> \
00072   { \
00073     inline static const char* typeName() { return #name; } \
00074     inline static std::string toString(void* mem) \
00075     { \
00076       type* val = reinterpret_cast<type*>(mem); \
00077       std::stringstream ss; \
00078       ss << *val; \
00079       return ss.str(); \
00080     } \
00081  \
00082     inline static void fromString(void* mem, const std::string& str) \
00083     { \
00084       type* val = reinterpret_cast<type*>(mem); \
00085       std::istringstream in(str); \
00086       in >> *val; \
00087     } \
00088   };
00089 
00090 RVE_PROPERTIES_DEFINE_SIMPLE_VALUE_TRAITS(bool, bool);
00091 RVE_PROPERTIES_DEFINE_SIMPLE_VALUE_TRAITS(uint8_t, uint8);
00092 RVE_PROPERTIES_DEFINE_SIMPLE_VALUE_TRAITS(int8_t, int8);
00093 RVE_PROPERTIES_DEFINE_SIMPLE_VALUE_TRAITS(uint16_t, uint16);
00094 RVE_PROPERTIES_DEFINE_SIMPLE_VALUE_TRAITS(int16_t, int16);
00095 RVE_PROPERTIES_DEFINE_SIMPLE_VALUE_TRAITS(uint32_t, uint32);
00096 RVE_PROPERTIES_DEFINE_SIMPLE_VALUE_TRAITS(int32_t, int32);
00097 RVE_PROPERTIES_DEFINE_SIMPLE_VALUE_TRAITS(uint64_t, uint64);
00098 RVE_PROPERTIES_DEFINE_SIMPLE_VALUE_TRAITS(int64_t, int64);
00099 RVE_PROPERTIES_DEFINE_SIMPLE_VALUE_TRAITS(float, float);
00100 RVE_PROPERTIES_DEFINE_SIMPLE_VALUE_TRAITS(double, double);
00101 
00102 template<>
00103 struct ValueTraits<const char*>
00104 {
00105   inline static const char* typeName() { return "string"; }
00106 
00107   
00108   inline static std::string toString(void* mem)
00109   {
00110     ROS_BREAK();
00111     return std::string();
00112   }
00113   inline static void fromString(void* mem, const std::string& str)
00114   {
00115     ROS_BREAK();
00116   }
00117 };
00118 
00119 template<>
00120 struct ValueTraits<std::string>
00121 {
00122   inline static const char* typeName() { return "string"; }
00123 
00124   inline static std::string toString(void* mem)
00125   {
00126     return *reinterpret_cast<std::string*>(mem);
00127   }
00128   inline static void fromString(void* mem, const std::string& str)
00129   {
00130     *reinterpret_cast<std::string*>(mem) = str;
00131   }
00132 };
00133 
00134 struct PropertyValueOperators
00135 {
00136   virtual std::string toString(void* mem) = 0;
00137   virtual void fromString(void* mem, const std::string& str) = 0;
00138   virtual void valueDestructor(void* mem) = 0;
00139   virtual void valueCopy(void* dst, const void* src) = 0;
00140   virtual const std::type_info& typeInfo() = 0;
00141   virtual const char* typeName() = 0;
00142 };
00143 
00144 template<typename T>
00145 struct PropertyValueOperatorsT : public PropertyValueOperators
00146 {
00147   virtual std::string toString(void* mem)
00148   {
00149     return ValueTraits<T>::toString(mem);
00150   }
00151 
00152   virtual void fromString(void* mem, const std::string& str)
00153   {
00154     return ValueTraits<T>::fromString(mem, str);
00155   }
00156 
00157   virtual void valueDestructor(void* mem)
00158   {
00159     T* val = reinterpret_cast<T*>(mem);
00160     val->~T();
00161   }
00162 
00163   virtual void valueCopy(void* dst, const void* src)
00164   {
00165     const T* src_val = reinterpret_cast<const T*>(src);
00166     new(dst) T(*src_val);
00167   }
00168 
00169   virtual const std::type_info& typeInfo()
00170   {
00171     return typeid(T);
00172   }
00173 
00174   virtual const char* typeName()
00175   {
00176     return ValueTraits<T>::typeName();
00177   }
00178 
00179   static PropertyValueOperatorsT<T> static_copy;
00180 };
00181 
00182 template<typename T> PropertyValueOperatorsT<T> PropertyValueOperatorsT<T>::static_copy;
00183 
00184 class PropertyValue
00185 {
00186 public:
00187   PropertyValue()
00188   : large_buffer_(0)
00189   , buffer_size_(0)
00190   , ops_(0)
00191   {
00192   }
00193 
00194   ~PropertyValue()
00195   {
00196     free(large_buffer_);
00197   }
00198 
00199   PropertyValue(const PropertyValue& rhs)
00200   {
00201     *this = rhs;
00202   }
00203 
00204   PropertyValue& operator=(const PropertyValue& rhs)
00205   {
00206     void* buf = large_buffer_ ? large_buffer_ : small_buffer_;
00207     if (filled())
00208     {
00209       ops_->valueDestructor(buf);
00210     }
00211 
00212     buffer_size_ = rhs.buffer_size_;
00213     ops_ = rhs.ops_;
00214 
00215     const void* source_buf = rhs.large_buffer_ ? rhs.large_buffer_ : rhs.small_buffer_;
00216     void* dest_buf = 0;
00217     if (rhs.large_buffer_)
00218     {
00219       large_buffer_ = (uint8_t*)realloc(large_buffer_, buffer_size_);
00220       dest_buf = large_buffer_;
00221     }
00222     else
00223     {
00224       free(large_buffer_);
00225       dest_buf = small_buffer_;
00226     }
00227 
00228     ops_->valueCopy(dest_buf, source_buf);
00229 
00230     return *this;
00231   }
00232 
00233   template<typename T>
00234   void set(T t)
00235   {
00236     void* buf = large_buffer_ ? large_buffer_ : small_buffer_;
00237     if (filled())
00238     {
00239       ops_->valueDestructor(buf);
00240     }
00241 
00242     buffer_size_ = sizeof(T);
00243     if (sizeof(T) <= sizeof(small_buffer_))
00244     {
00245       free(large_buffer_);
00246       large_buffer_ = 0;
00247 
00248       T* copy = new (small_buffer_) T;
00249       *copy = t;
00250     }
00251     else
00252     {
00253       large_buffer_ = (uint8_t*)realloc(large_buffer_, sizeof(T));
00254       T* copy = new (large_buffer_) T;
00255       *copy = t;
00256     }
00257 
00258     ops_ = &PropertyValueOperatorsT<T>::static_copy;
00259   }
00260 
00261   template<typename T>
00262   void get(T& t, T default_value)
00263   {
00264     if (!ops_)
00265     {
00266       t = default_value;
00267       set(default_value);
00268     }
00269 
00270     getImpl(t);
00271   }
00272 
00273   template<typename T>
00274   void get(T& t)
00275   {
00276     if (!ops_)
00277     {
00278       throw std::bad_cast();
00279     }
00280 
00281     getImpl(t);
00282   }
00283 
00284   template<typename T>
00285   T get()
00286   {
00287     T t;
00288     get(t);
00289     return t;
00290   }
00291 
00292   bool empty()
00293   {
00294     return !ops_;
00295   }
00296 
00297   bool filled()
00298   {
00299     return ops_;
00300   }
00301 
00302   const char* getTypeName()
00303   {
00304     if (!ops_)
00305     {
00306       return "empty";
00307     }
00308 
00309     return ops_->typeName();
00310   }
00311 
00312   const std::type_info& getTypeInfo()
00313   {
00314     if (!ops_)
00315     {
00316       return typeid(void);
00317     }
00318 
00319     return ops_->typeInfo();
00320   }
00321 
00322 private:
00323   template<typename T>
00324   void getImpl(T& t)
00325   {
00326     void* buf = large_buffer_ ? large_buffer_ : small_buffer_;
00327 
00328     
00329     if (typeid(T) == ops_->typeInfo())
00330     {
00331       t = *reinterpret_cast<T*>(buf);
00332       return;
00333     }
00334 
00335     
00336     std::string str = ops_->toString(buf);
00337     ValueTraits<T>::fromString(&t, str);
00338   }
00339 
00340   uint8_t small_buffer_[8]; 
00341   uint8_t* large_buffer_;
00342   size_t buffer_size_;
00343   PropertyValueOperators* ops_;
00344 };
00345 
00346 template<>
00347 inline void PropertyValue::set<const char*>(const char* str)
00348 {
00349   set<std::string>(std::string(str));
00350 }
00351 
00352 template<>
00353 inline void PropertyValue::getImpl<std::string>(std::string& str)
00354 {
00355   void* buf = large_buffer_ ? large_buffer_ : small_buffer_;
00356 
00357   
00358   if (typeid(std::string) == ops_->typeInfo())
00359   {
00360     str = *reinterpret_cast<std::string*>(buf);
00361     return;
00362   }
00363 
00364   
00365   str = ops_->toString(buf);
00366 }
00367 
00368 template<>
00369 inline void PropertyValue::getImpl<char*>(char*& str)
00370 {
00371   ROS_BREAK();
00372 }
00373 
00374 #define PROPERTY_VALUE_EXTERNS(type) \
00375     extern template class PropertyValueOperatorsT<type>; \
00376     extern template void PropertyValue::set(type); \
00377     extern template void PropertyValue::get(type&, type); \
00378     extern template void PropertyValue::get(type&); \
00379     extern template type PropertyValue::get(); \
00380     extern template void PropertyValue::getImpl(type&);
00381 
00382 PROPERTY_VALUE_EXTERNS(bool);
00383 PROPERTY_VALUE_EXTERNS(uint8_t);
00384 PROPERTY_VALUE_EXTERNS(int8_t);
00385 PROPERTY_VALUE_EXTERNS(uint16_t);
00386 PROPERTY_VALUE_EXTERNS(int16_t);
00387 PROPERTY_VALUE_EXTERNS(uint32_t);
00388 PROPERTY_VALUE_EXTERNS(int32_t);
00389 PROPERTY_VALUE_EXTERNS(uint64_t);
00390 PROPERTY_VALUE_EXTERNS(int64_t);
00391 PROPERTY_VALUE_EXTERNS(float);
00392 PROPERTY_VALUE_EXTERNS(double);
00393 PROPERTY_VALUE_EXTERNS(std::string);
00394 
00395 }
00396 
00397 #endif // RVE_PROPERTIES_PROPERTY_VALUE_H
00398