property_value.h
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2010, Willow Garage, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
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   // Default to stream operators
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   // Should never actually get into these
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     // Types match, just grab the type
00329     if (typeid(T) == ops_->typeInfo())
00330     {
00331       t = *reinterpret_cast<T*>(buf);
00332       return;
00333     }
00334 
00335     // Types don't match, have to go through a string
00336     std::string str = ops_->toString(buf);
00337     ValueTraits<T>::fromString(&t, str);
00338   }
00339 
00340   uint8_t small_buffer_[8]; // Used for small values so we don't have to allocate
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   // Types match, just grab the type
00358   if (typeid(std::string) == ops_->typeInfo())
00359   {
00360     str = *reinterpret_cast<std::string*>(buf);
00361     return;
00362   }
00363 
00364   // Types don't match, have to convert
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 


rve_properties
Author(s): Josh Faust
autogenerated on Wed Dec 11 2013 14:31:27