Urbi SDK Remote for C++  2.7.5
uvalue.hxx
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2009-2011, Gostai S.A.S.
00003  *
00004  * This software is provided "as is" without warranty of any kind,
00005  * either expressed or implied, including but not limited to the
00006  * implied warranties of fitness for a particular purpose.
00007  *
00008  * See the LICENSE file for more information.
00009  */
00010 
00012 
00013 #include <libport/cassert>
00014 #include <libport/foreach.hh>
00015 #include <libport/lexical-cast.hh>
00016 #include <libport/preproc.hh>
00017 
00018 namespace urbi
00019 {
00020 
00021   /*--------.
00022   | UList.  |
00023   `--------*/
00024 
00025 # define ULIST_NTH(Const)                       \
00026   inline                                        \
00027   Const UValue&                                 \
00028   UList::operator[](size_t i) Const             \
00029   {                                             \
00030     i += offset;                                \
00031     if (i < size())                             \
00032       return *array[i];                         \
00033     else                                        \
00034       return UValue::error();                   \
00035   }
00036 
00037   ULIST_NTH(__)
00038   ULIST_NTH(const)
00039 
00040 # undef ULIST_NTH
00041 
00042   inline
00043   UList::iterator
00044   UList::begin()
00045   {
00046     return array.begin();
00047   }
00048 
00049   inline
00050   UList::iterator
00051   UList::end()
00052   {
00053     return array.end();
00054   }
00055 
00056   inline
00057   UList::const_iterator
00058   UList::begin() const
00059   {
00060     return array.begin();
00061   }
00062 
00063   inline
00064   UList::const_iterator
00065   UList::end() const
00066   {
00067     return array.end();
00068   }
00069 
00070   inline
00071   size_t
00072   UList::size() const
00073   {
00074     return array.size();
00075   }
00076 
00077   inline
00078   void
00079   UList::setOffset(size_t n)
00080   {
00081     offset = n;
00082   }
00083 
00084   template<typename T>
00085   inline
00086   UList&
00087   UList::push_back(const T& v)
00088   {
00089     array.push_back(new UValue(v));
00090     return *this;
00091   }
00092 
00093   inline
00094   UValue&
00095   UList::front()
00096   {
00097    return *array.front();
00098   }
00099 
00100   inline
00101   void
00102   UList::pop_back()
00103   {
00104     array.pop_back();
00105   }
00106 
00107   /*--------------.
00108   | UNamedValue.  |
00109   `--------------*/
00110 
00111   inline
00112   UNamedValue::UNamedValue(const std::string& n, UValue* v)
00113     : name(n)
00114     , val(v)
00115   {}
00116 
00117   inline
00118   UNamedValue&
00119   UNamedValue::error()
00120   {
00121     static UNamedValue instance("<<UNamedValue::error (denotes an error)>>");
00122     return instance;
00123   }
00124 
00125 
00126   /*---------.
00127   | UValue.  |
00128   `---------*/
00129 
00135   inline
00136   UValue&
00137   UValue::operator, (const UValue &b)
00138   {
00139     return *this = b;
00140   }
00141 
00142 #  define CONTAINER_TO_UVALUE_DECLARE(Type)                     \
00143   template <typename T>                                         \
00144   inline                                                        \
00145   UValue&                                                       \
00146   operator, (UValue &b, const Type<T> &v)                       \
00147   {                                                             \
00148     b.type = DATA_LIST;                                         \
00149     b.list = new UList();                                       \
00150     for (typename Type<T>::const_iterator i = v.begin(),        \
00151            i_end = v.end();                                     \
00152          i != i_end; ++i)                                       \
00153     {                                                           \
00154       UValue r;                                                 \
00155       r, *i;                                                    \
00156       b.list->array.push_back(new UValue(r));                   \
00157     }                                                           \
00158     return b;                                                   \
00159   }
00160 
00161   CONTAINER_TO_UVALUE_DECLARE(std::list)
00162   CONTAINER_TO_UVALUE_DECLARE(std::vector)
00163 
00164 # undef CONTAINER_TO_UVALUE_DECLARE
00165 
00166 
00167 # define OP_COMMA(Type)                         \
00168   inline                                        \
00169   UValue& UValue::operator, (Type rhs)          \
00170   {                                             \
00171     return *this = rhs;                         \
00172   }
00173 
00174   LIBPORT_LIST_APPLY(OP_COMMA, URBI_NUMERIC_TYPES)
00175   LIBPORT_LIST_APPLY(OP_COMMA, URBI_STRING_TYPES)
00176   LIBPORT_LIST_APPLY(OP_COMMA, URBI_MISC_TYPES)
00177 
00178 # undef OP_COMMA
00179 
00180 
00181 
00182 # define UVALUE_INTEGRAL_CAST(Type)                             \
00183   inline                                                        \
00184   UValue::operator Type() const                                 \
00185   {                                                             \
00186     return static_cast<Type>(static_cast<ufloat>((*this)));     \
00187   }
00188 
00189   LIBPORT_LIST_APPLY(UVALUE_INTEGRAL_CAST, URBI_DERIVED_NUMERIC_TYPES)
00190 # undef UVALUE_INTEGRAL_CAST
00191 
00192 
00193   inline
00194   UValue::operator bool() const
00195   {
00196     return static_cast<int>(static_cast<ufloat>((*this))) != 0;
00197   }
00198 
00199 
00200   inline
00201   UValue&
00202   UValue::operator()()
00203   {
00204     return *this;
00205   }
00206 
00207   inline
00208   std::ostream&
00209   operator<<(std::ostream& s, const UValue& v)
00210   {
00211     // Looks bizarre, but might happen without have the "print" die
00212     // (it *has* happened).
00213     aver(&v);
00214     return v.print(s);
00215   }
00216 
00217 
00218 
00219   /*----------.
00220   | Casters.  |
00221   `----------*/
00222 
00223 
00224   // Run the uvalue_caster<Type> on v.
00225   template <typename Type>
00226   inline
00227   typename uvar_ref_traits<typename uvalue_cast_return_type<Type>::type>::type
00228   uvalue_cast(UValue& v)
00229   {
00230     typedef typename libport::traits::remove_reference<Type>::type res_type;
00231     return uvalue_caster<res_type>()(v);
00232   }
00233 
00234 
00235 # define UVALUE_CASTER_DEFINE(Type)             \
00236   template <>                                   \
00237   struct uvalue_caster <Type>                   \
00238   {                                             \
00239     Type operator() (UValue& v)                 \
00240     {                                           \
00241       return v;                                 \
00242     }                                           \
00243   };
00244 
00245   LIBPORT_LIST_APPLY(UVALUE_CASTER_DEFINE, URBI_NUMERIC_TYPES)
00246   UVALUE_CASTER_DEFINE(std::string);
00247   UVALUE_CASTER_DEFINE(const std::string);
00248   UVALUE_CASTER_DEFINE(bool);
00249   UVALUE_CASTER_DEFINE(UImage);
00250   UVALUE_CASTER_DEFINE(USound);
00251 
00252 #undef UVALUE_CASTER_DEFINE
00253 
00254 
00255   /*-----------------------------------.
00256   | Casting an UValue into an UValue.  |
00257   `-----------------------------------*/
00258 
00259   // Always return a const UValue&, a copy will be made if required.
00260 # define UVALUE_CASTER_DEFINE(Type)              \
00261   template <>                                   \
00262   struct uvalue_caster<Type>                    \
00263   {                                             \
00264     const UValue& operator()(UValue& v)         \
00265     {                                           \
00266       return v;                                 \
00267     }                                           \
00268   }
00269 
00270   UVALUE_CASTER_DEFINE(const UValue&);
00271   UVALUE_CASTER_DEFINE(UValue&);
00272   UVALUE_CASTER_DEFINE(const UValue);
00273   UVALUE_CASTER_DEFINE(UValue);
00274 # undef UVALUE_CASTER_DEFINE
00275 
00276 
00277 
00278   // The following ones are defined in uvalue-common.cc.
00279   template <>
00280   struct URBI_SDK_API uvalue_caster<UVar>
00281   {
00282     UVar& operator () (UValue& v);
00283   };
00284 
00285 
00286 # define UVALUE_CASTER_DECLARE(Type)            \
00287   template <>                                   \
00288   struct URBI_SDK_API uvalue_caster<Type>       \
00289   {                                             \
00290     Type operator () (UValue& v);               \
00291   }
00292 
00293   UVALUE_CASTER_DECLARE(UBinary);
00294   UVALUE_CASTER_DECLARE(UList);
00295   UVALUE_CASTER_DECLARE(UDictionary);
00296   UVALUE_CASTER_DECLARE(const char*);
00297 
00298 # undef UVALUE_CASTER_DECLARE
00299 
00300 
00301 # ifndef UOBJECT_NO_LIST_CAST
00302 
00303 #  define UVALUE_CONTAINER_CASTER_DECLARE(Type)                 \
00304   template <typename T>                                         \
00305   struct uvalue_caster< Type<T> >                               \
00306   {                                                             \
00307     Type<T>                                                     \
00308     operator()(UValue& v)                                       \
00309     {                                                           \
00310       Type<T> res;                                              \
00311       if (v.type != DATA_LIST)                                  \
00312         /* Cast just the element.  */                           \
00313         res.push_back(uvalue_cast<T>(v));                       \
00314       else                                                      \
00315         for (size_t i = 0; i < v.list->size(); ++i)             \
00316           res.push_back(uvalue_cast<T>(*v.list->array[i]));     \
00317       return res;                                               \
00318     }                                                           \
00319   }
00320 
00321   UVALUE_CONTAINER_CASTER_DECLARE(std::list);
00322   UVALUE_CONTAINER_CASTER_DECLARE(std::vector);
00323 
00324 #  undef UVALUE_CONTAINER_CASTER_DECLARE
00325 
00326 # endif
00327 
00328   // Dictionary casters.
00329   template <typename V>
00330   struct uvalue_caster<boost::unordered_map<std::string, V> >
00331   {
00332     boost::unordered_map<std::string, V> operator()(UValue& v)
00333     {
00334       boost::unordered_map<std::string, V> res;
00335       if (v.type != DATA_DICTIONARY)
00336         throw std::runtime_error("UValue is not a dictionary.");
00337       typedef UDictionary::value_type DictVal;
00338       foreach (UDictionary::value_type& val, *v.dictionary)
00339         res[val.first] = uvalue_cast<V>(val.second);
00340       return res;
00341     }
00342   };
00343 
00344   template <typename V>
00345   inline
00346   UValue&
00347   operator,(UValue& v, const boost::unordered_map<std::string, V> & d)
00348   {
00349     typedef typename boost::unordered_map<std::string, V>::value_type DictVal;
00350     v.clear();
00351     v.type = DATA_DICTIONARY;
00352     v.dictionary = new UDictionary;
00353     foreach (const DictVal & val, d)
00354     {
00355       UValue nv;
00356       nv, val.second;
00357       (*v.dictionary)[val.first] = nv;
00358      }
00359      return v;
00360   }
00361 
00362   // Uses casters, must be at the end
00363   template <typename T>
00364   inline
00365   UList&
00366   UList::operator=(const T& container)
00367   {
00368     array.clear();
00369     typedef const typename T::value_type constv;
00370     foreach (constv& v, container)
00371     {
00372       UValue val;
00373       val,v;
00374       array.push_back(new UValue(val));
00375     }
00376     return *this;
00377   }
00378 
00379   template <typename T>
00380   inline
00381   T
00382   UList::as()
00383   {
00384     T res;
00385     foreach (UValue* v, array)
00386       res.push_back(uvalue_caster<typename T::value_type>()(*v));
00387     return res;
00388   }
00389 
00393   template <typename T>
00394   inline
00395   void uvalue_cast_bounce(T& t, UValue& v)
00396   {
00397     t = uvalue_cast<T>(v);
00398   }
00399 
00400   template <typename T>
00401   struct uvalue_caster<UPackedData<T> >
00402   {
00403     UPackedData<T> operator() (UValue& v)
00404     {
00405       if (v.type != DATA_BINARY)
00406         throw std::runtime_error("invalid cast to UPackedData: not a Binary");
00407       if (v.binary->common.size % sizeof(T))
00408         throw std::runtime_error("invalid cast to UPackedData: incorrect binary"
00409                                  "size");
00410       return UPackedData<T>((T*)v.binary->common.data,
00411                             (T*)((char*)v.binary->common.data
00412                                  + v.binary->common.size));
00413     }
00414   };
00415 
00416   template <typename T>
00417   inline
00418   UValue& operator, (UValue&v, const UPackedData<T>& d)
00419   {
00420     v = UBinary();
00421     UBinary& b = *v.binary;
00422     b.common.size = sizeof(T)*d.size();
00423     b.common.data = malloc(b.common.size);
00424     b.message = "packed " + string_cast(sizeof(T)) + " " + typeid(T).name();
00425     memcpy(b.common.data, &d.front(), b.common.size);
00426     return v;
00427   }
00428 
00429 } // namespace urbi