|
Urbi SDK Remote for C++
2.7.5
|
00001 /* 00002 * Copyright (C) 2007, 2008, 2009, 2010, 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 #ifndef URBI_UVALUE_HH 00013 # define URBI_UVALUE_HH 00014 00015 # include <libport/warning-push.hh> 00016 00017 # include <vector> 00018 00019 # include <libport/hash.hh> 00020 # include <libport/preproc.hh> 00021 # include <libport/traits.hh> 00022 # include <libport/ufloat.h> 00023 00024 # include <urbi/fwd.hh> 00025 # include <urbi/export.hh> 00026 # include <urbi/ubinary.hh> 00027 00028 namespace urbi 00029 { 00030 00031 /*--------------------------. 00032 | Free standing functions. | 00033 `--------------------------*/ 00034 00036 URBI_SDK_API 00037 int& kernelMajor(std::ostream& o); 00038 00044 URBI_SDK_API 00045 std::string 00046 syncline_push(const std::string& srcdir, std::string file, unsigned line); 00047 00048 #define SYNCLINE_PUSH() \ 00049 "//#push " BOOST_PP_STRINGIZE(__LINE__) " \"" __FILE__ "\"\n" 00050 00051 #define SYNCLINE_POP() \ 00052 "//#pop\n" 00053 00054 #ifndef __SRCDIR__ 00055 # define __SRCDIR__ "" 00056 #endif 00057 00058 #define SYNCLINE_WRAP(...) \ 00059 (::urbi::syncline_push(__SRCDIR__, __FILE__, __LINE__) \ 00060 + libport::format(__VA_ARGS__) \ 00061 + "\n" \ 00062 SYNCLINE_POP()) 00063 00064 00065 00066 // UValue and other related types 00067 00069 enum UDataType 00070 { 00071 DATA_BINARY = 0, 00072 DATA_DICTIONARY = 1, 00073 DATA_DOUBLE = 2, 00074 DATA_LIST = 3, 00075 // No longer supported. DATA_OBJECT = 4, 00076 DATA_STRING = 5, 00077 DATA_SLOTNAME = 6, 00078 DATA_VOID = 7, 00079 }; 00080 00081 /*--------. 00082 | UList. | 00083 `--------*/ 00084 00086 class URBI_SDK_API UList 00087 { 00088 public: 00089 UList(); 00090 UList(const UList &b); 00091 ~UList(); 00092 00093 UList& operator=(const UList &b); 00094 00095 // Assign a container to the UList 00096 template<typename T> 00097 UList& operator=(const T& container); 00098 00099 UList& operator=(UVar& v); 00100 00101 // Transform the UList to a container. 00102 template<typename T> 00103 T as(); 00104 00106 typedef std::vector<UValue*> list_type; 00107 typedef list_type::iterator iterator; 00108 typedef list_type::const_iterator const_iterator; 00109 iterator begin(); 00110 iterator end(); 00111 const_iterator begin() const; 00112 const_iterator end() const; 00113 00114 // Append an element to the end. 00115 template<typename T> 00116 UList& 00117 push_back(const T& v); 00118 00119 void pop_back(); 00120 00121 UValue& front(); 00122 00123 UValue& operator[](size_t i); 00124 const UValue& operator[](size_t i) const; 00125 00126 size_t size() const; 00127 void setOffset(size_t n); 00128 00129 std::ostream& print(std::ostream& o) const; 00130 00131 // The actual contents. 00132 list_type array; 00133 00134 private: 00135 void clear(); 00136 size_t offset; 00137 friend class UValue; 00138 }; 00139 00140 URBI_SDK_API 00141 std::ostream& operator<< (std::ostream& o, const UList& t); 00142 00143 00144 /*--------------. 00145 | UDictionary. | 00146 `--------------*/ 00147 00148 typedef boost::unordered_map<std::string, UValue> UDictionary; 00149 00150 URBI_SDK_API 00151 std::ostream& operator<<(std::ostream& s, const UDictionary& d); 00152 00153 00154 /*--------------. 00155 | UNamedValue. | 00156 `--------------*/ 00157 00158 class URBI_SDK_API UNamedValue 00159 { 00160 public: 00161 UNamedValue(const std::string& n = "", UValue* v = 0); 00162 // Used on errors. 00163 static UNamedValue& error(); 00164 std::string name; 00165 UValue* val; 00166 }; 00167 00168 00169 /*---------. 00170 | UValue. | 00171 `---------*/ 00172 00175 class URBI_SDK_API UValue 00176 { 00177 public: 00178 UDataType type; 00179 00180 ufloat val; 00181 union 00182 { 00183 std::string* stringValue; 00184 UBinary* binary; 00185 UList* list; 00186 UDictionary* dictionary; 00187 void* storage; 00188 }; 00189 00190 UValue(); 00191 UValue(const UValue&); 00192 00193 ~UValue(); 00194 00195 UValue& operator=(const UValue&); 00199 UValue& set(const UValue&, bool copy=true); 00201 void clear(); 00204 static UValue& error(); 00205 00211 UValue& operator, (const UValue &b); 00212 00214 const char* format_string() const; 00215 00216 #define CTOR_AND_ASSIGN_AND_COMMA(Type) \ 00217 explicit UValue(Type, bool copy=true); \ 00218 UValue& operator=(Type); \ 00219 UValue& operator,(Type rhs); 00220 00221 // Types convertibles to DATA_DOUBLE 00222 #define URBI_DERIVED_NUMERIC_TYPES \ 00223 LIBPORT_LIST(int, long, unsigned int, unsigned long, \ 00224 unsigned long long, long long,) 00225 00226 #define URBI_NUMERIC_TYPES \ 00227 LIBPORT_LIST(ufloat, int, long, unsigned int, unsigned long, \ 00228 unsigned long long, long long,) 00229 00230 // Types convertibles to DATA_STRING 00231 #define URBI_STRING_TYPES \ 00232 LIBPORT_LIST(const char*, const void*, const std::string&,) 00233 00234 #define URBI_MISC_TYPES \ 00235 LIBPORT_LIST(const UBinary&, const UList&, const UDictionary&, \ 00236 const USound&, const UImage&,) 00237 00238 # ifndef SWIG 00239 LIBPORT_LIST_APPLY(CTOR_AND_ASSIGN_AND_COMMA, URBI_NUMERIC_TYPES) 00240 LIBPORT_LIST_APPLY(CTOR_AND_ASSIGN_AND_COMMA, URBI_STRING_TYPES) 00241 LIBPORT_LIST_APPLY(CTOR_AND_ASSIGN_AND_COMMA, URBI_MISC_TYPES) 00242 # else 00243 // UFloats. 00244 CTOR_AND_ASSIGN_AND_COMMA(ufloat); 00245 CTOR_AND_ASSIGN_AND_COMMA(int); 00246 CTOR_AND_ASSIGN_AND_COMMA(long); 00247 CTOR_AND_ASSIGN_AND_COMMA(unsigned int); 00248 CTOR_AND_ASSIGN_AND_COMMA(unsigned long); 00249 CTOR_AND_ASSIGN_AND_COMMA(unsigned long long); 00250 CTOR_AND_ASSIGN_AND_COMMA(long long); 00251 00252 // Strings. 00253 CTOR_AND_ASSIGN_AND_COMMA(const char*); 00254 CTOR_AND_ASSIGN_AND_COMMA(const void*); 00255 CTOR_AND_ASSIGN_AND_COMMA(const std::string&); 00256 00257 // Others. 00258 CTOR_AND_ASSIGN_AND_COMMA(const UBinary&); 00259 CTOR_AND_ASSIGN_AND_COMMA(const UList&); 00260 CTOR_AND_ASSIGN_AND_COMMA(const UDictionary&); 00261 CTOR_AND_ASSIGN_AND_COMMA(const USound&); 00262 CTOR_AND_ASSIGN_AND_COMMA(const UImage&); 00263 # endif 00264 00265 #undef CTOR_AND_ASSIGN_AND_COMMA 00266 00267 #define CAST_OPERATOR(Type) \ 00268 operator Type() const; 00269 00270 # ifndef SWIG 00271 LIBPORT_LIST_APPLY(CAST_OPERATOR, URBI_NUMERIC_TYPES) 00272 # else 00273 operator ufloat() const; 00274 operator std::string() const; 00275 operator int() const; 00276 operator unsigned int() const; 00277 operator long() const; 00278 operator unsigned long() const; 00279 operator bool() const; 00280 # endif 00281 #undef CAST_OPERATOR 00282 00283 #ifdef DOXYGEN 00284 // Doxygens needs a prototype for ufloat. 00285 operator ufloat() const; 00286 #endif 00287 00288 operator std::string() const; 00289 operator bool() const; 00290 00292 operator const UBinary&() const; 00293 00295 operator UList() const; 00296 00298 operator UDictionary() const; 00299 00301 operator UImage() const; 00302 00304 operator USound() const; 00305 00310 UValue& operator()(); 00311 00314 int parse(const char* message, 00315 int pos, 00316 const binaries_type& bins, 00317 binaries_type::const_iterator& binpos); 00318 00320 std::ostream& print(std::ostream& s) const; 00321 00322 // Huge hack. 00323 static const bool copy = true; 00324 }; 00325 00326 std::ostream& 00327 operator<<(std::ostream& s, const UValue& v); 00328 00329 00330 /*----------. 00331 | Casters. | 00332 `----------*/ 00333 00334 // For each Type, define an operator() that casts its UValue& 00335 // argument into Type. We need partial specialization. 00336 00337 template <typename Type> 00338 struct uvalue_caster 00339 { 00340 }; 00341 00342 // T -> UVar& if T = UVar 00343 // T -> T otherwise. 00344 template <typename T> 00345 struct uvar_ref_traits 00346 { 00347 typedef T type; 00348 }; 00349 00350 template <> 00351 struct uvar_ref_traits<UVar> 00352 { 00353 typedef UVar& type; 00354 }; 00355 00356 // Run the uvalue_caster<Type> on v. 00357 00358 /* NM: Why exactly are we moving the const away? 00359 * I'm dropping it for UValue as it makes unnecessary copy. 00360 */ 00361 00362 template<typename T> struct uvalue_cast_return_type 00363 { 00364 typedef typename libport::traits::remove_reference<T>::type type; 00365 }; 00366 00367 template<> struct uvalue_cast_return_type<const UValue&> 00368 { 00369 typedef const UValue& type; 00370 }; 00371 00372 template <typename Type> 00373 typename uvar_ref_traits<typename uvalue_cast_return_type<Type>::type>::type 00374 uvalue_cast (UValue& v); 00375 00376 } // namespace urbi 00377 00378 #define URBI_STRUCT_CAST_FIELD(_, Cname, Field) \ 00379 if (libport::mhas(dict, BOOST_PP_STRINGIZE(Field))) \ 00380 uvalue_cast_bounce(res.Field, dict[BOOST_PP_STRINGIZE(Field)]); \ 00381 else \ 00382 GD_WARN("Serialized data for " #Cname "is missing field" \ 00383 BOOST_PP_STRINGIZE(Field)); \ 00384 00385 #define URBI_STRUCT_BCAST_FIELD(_, Cname, Field) \ 00386 dict[BOOST_PP_STRINGIZE(Field)], c.Field; 00387 00388 00389 #define URBI_REGISTER_STRUCT(Cname, ...) \ 00390 namespace urbi \ 00391 { \ 00392 template<> \ 00393 struct uvalue_caster<Cname> \ 00394 { \ 00395 Cname operator()(UValue& v) \ 00396 { \ 00397 if (v.type != DATA_DICTIONARY) \ 00398 throw std::runtime_error("invalid cast to " #Cname "from " \ 00399 + string_cast(v)); \ 00400 UDictionary& dict = *v.dictionary; \ 00401 Cname res; \ 00402 LIBPORT_VAARGS_APPLY(URBI_STRUCT_CAST_FIELD, Cname, __VA_ARGS__); \ 00403 return res; \ 00404 } \ 00405 }; \ 00406 \ 00407 static UValue& operator,(UValue& v, const Cname &c) \ 00408 { \ 00409 v = UDictionary(); \ 00410 UDictionary& dict = *v.dictionary; \ 00411 dict["$sn"] = BOOST_PP_STRINGIZE(Cname); \ 00412 LIBPORT_VAARGS_APPLY(URBI_STRUCT_BCAST_FIELD, Cname, __VA_ARGS__); \ 00413 return v; \ 00414 } \ 00415 } 00416 00422 template<typename T> 00423 class UPackedData: public std::vector<T> 00424 { 00425 public: 00426 UPackedData() 00427 {}; 00428 UPackedData(const std::vector<T>& src) 00429 : std::vector<T>(src) 00430 {}; 00431 template<typename I> 00432 UPackedData(I begin, I end) 00433 : std::vector<T>(begin, end) 00434 {}; 00435 }; 00436 00437 # include <urbi/uvalue.hxx> 00438 00439 # include <libport/warning-pop.hh> 00440 00441 #endif // ! URBI_UVALUE_HH