|
Urbi SDK Remote for C++
2.7.3
|
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