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