|
Urbi SDK Remote for C++
2.7.3
|
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 std::ostream& operator<<(std::ostream& s, const UDictionary& d); 00151 00152 00153 /*--------------. 00154 | UNamedValue. | 00155 `--------------*/ 00156 00157 class URBI_SDK_API UNamedValue 00158 { 00159 public: 00160 UNamedValue(const std::string& n = "", UValue* v = 0); 00161 // Used on errors. 00162 static UNamedValue& error(); 00163 std::string name; 00164 UValue* val; 00165 }; 00166 00167 00168 /*---------. 00169 | UValue. | 00170 `---------*/ 00171 00174 class URBI_SDK_API UValue 00175 { 00176 public: 00177 UDataType type; 00178 00179 ufloat val; 00180 union 00181 { 00182 std::string* stringValue; 00183 UBinary* binary; 00184 UList* list; 00185 UDictionary* dictionary; 00186 void* storage; 00187 }; 00188 00189 UValue(); 00190 UValue(const UValue&); 00191 00192 ~UValue(); 00193 00194 UValue& operator=(const UValue&); 00198 UValue& set(const UValue&, bool copy=true); 00200 void clear(); 00203 static UValue& error(); 00204 00210 UValue& operator, (const UValue &b); 00211 00213 const char* format_string() const; 00214 00215 #define CTOR_AND_ASSIGN_AND_COMMA(Type) \ 00216 explicit UValue(Type, bool copy=true); \ 00217 UValue& operator=(Type); \ 00218 UValue& operator,(Type rhs); 00219 00220 // Types convertibles to DATA_DOUBLE 00221 #define URBI_DERIVED_NUMERIC_TYPES \ 00222 LIBPORT_LIST(int, long, unsigned int, unsigned long, \ 00223 unsigned long long, long long,) 00224 00225 #define URBI_NUMERIC_TYPES \ 00226 LIBPORT_LIST(ufloat, int, long, unsigned int, unsigned long, \ 00227 unsigned long long, long long,) 00228 00229 // Types convertibles to DATA_STRING 00230 #define URBI_STRING_TYPES \ 00231 LIBPORT_LIST(const char*, const void*, const std::string&,) 00232 00233 #define URBI_MISC_TYPES \ 00234 LIBPORT_LIST(const UBinary&, const UList&, const UDictionary&, \ 00235 const USound&, const UImage&,) 00236 00237 # ifndef SWIG 00238 LIBPORT_LIST_APPLY(CTOR_AND_ASSIGN_AND_COMMA, URBI_NUMERIC_TYPES) 00239 LIBPORT_LIST_APPLY(CTOR_AND_ASSIGN_AND_COMMA, URBI_STRING_TYPES) 00240 LIBPORT_LIST_APPLY(CTOR_AND_ASSIGN_AND_COMMA, URBI_MISC_TYPES) 00241 # else 00242 // UFloats. 00243 CTOR_AND_ASSIGN_AND_COMMA(ufloat); 00244 CTOR_AND_ASSIGN_AND_COMMA(int); 00245 CTOR_AND_ASSIGN_AND_COMMA(long); 00246 CTOR_AND_ASSIGN_AND_COMMA(unsigned int); 00247 CTOR_AND_ASSIGN_AND_COMMA(unsigned long); 00248 CTOR_AND_ASSIGN_AND_COMMA(unsigned long long); 00249 CTOR_AND_ASSIGN_AND_COMMA(long long); 00250 00251 // Strings. 00252 CTOR_AND_ASSIGN_AND_COMMA(const char*); 00253 CTOR_AND_ASSIGN_AND_COMMA(const void*); 00254 CTOR_AND_ASSIGN_AND_COMMA(const std::string&); 00255 00256 // Others. 00257 CTOR_AND_ASSIGN_AND_COMMA(const UBinary&); 00258 CTOR_AND_ASSIGN_AND_COMMA(const UList&); 00259 CTOR_AND_ASSIGN_AND_COMMA(const UDictionary&); 00260 CTOR_AND_ASSIGN_AND_COMMA(const USound&); 00261 CTOR_AND_ASSIGN_AND_COMMA(const UImage&); 00262 # endif 00263 00264 #undef CTOR_AND_ASSIGN_AND_COMMA 00265 00266 #define CAST_OPERATOR(Type) \ 00267 operator Type() const; 00268 00269 # ifndef SWIG 00270 LIBPORT_LIST_APPLY(CAST_OPERATOR, URBI_NUMERIC_TYPES) 00271 # else 00272 operator ufloat() const; 00273 operator std::string() const; 00274 operator int() const; 00275 operator unsigned int() const; 00276 operator long() const; 00277 operator unsigned long() const; 00278 operator bool() const; 00279 # endif 00280 #undef CAST_OPERATOR 00281 00282 #ifdef DOXYGEN 00283 // Doxygens needs a prototype for ufloat. 00284 operator ufloat() const; 00285 #endif 00286 00287 operator std::string() const; 00288 operator bool() const; 00289 00291 operator const UBinary&() const; 00292 00294 operator UList() const; 00295 00297 operator UDictionary() const; 00298 00300 operator UImage() const; 00301 00303 operator USound() const; 00304 00309 UValue& operator()(); 00310 00313 int parse(const char* message, 00314 int pos, 00315 const binaries_type& bins, 00316 binaries_type::const_iterator& binpos); 00317 00319 std::ostream& print(std::ostream& s) const; 00320 00321 // Huge hack. 00322 static const bool copy = true; 00323 }; 00324 00325 std::ostream& 00326 operator<<(std::ostream& s, const UValue& v); 00327 00328 00329 /*----------. 00330 | Casters. | 00331 `----------*/ 00332 00333 // For each Type, define an operator() that casts its UValue& 00334 // argument into Type. We need partial specialization. 00335 00336 template <typename Type> 00337 struct uvalue_caster 00338 { 00339 }; 00340 00341 // T -> UVar& if T = UVar 00342 // T -> T otherwise. 00343 template <typename T> 00344 struct uvar_ref_traits 00345 { 00346 typedef T type; 00347 }; 00348 00349 template <> 00350 struct uvar_ref_traits<UVar> 00351 { 00352 typedef UVar& type; 00353 }; 00354 00355 // Run the uvalue_caster<Type> on v. 00356 00357 /* NM: Why exactly are we moving the const away? 00358 * I'm dropping it for UValue as it makes unnecessary copy. 00359 */ 00360 00361 template<typename T> struct uvalue_cast_return_type 00362 { 00363 typedef typename libport::traits::remove_reference<T>::type type; 00364 }; 00365 00366 template<> struct uvalue_cast_return_type<const UValue&> 00367 { 00368 typedef const UValue& type; 00369 }; 00370 00371 template <typename Type> 00372 typename uvar_ref_traits<typename uvalue_cast_return_type<Type>::type>::type 00373 uvalue_cast (UValue& v); 00374 00375 } // namespace urbi 00376 00377 #define URBI_STRUCT_CAST_FIELD(_, Cname, Field) \ 00378 if (libport::mhas(dict, BOOST_PP_STRINGIZE(Field))) \ 00379 uvalue_cast_bounce(res.Field, dict[BOOST_PP_STRINGIZE(Field)]); \ 00380 else \ 00381 GD_WARN("Serialized data for " #Cname "is missing field" \ 00382 BOOST_PP_STRINGIZE(Field)); \ 00383 00384 #define URBI_STRUCT_BCAST_FIELD(_, Cname, Field) \ 00385 dict[BOOST_PP_STRINGIZE(Field)], c.Field; 00386 00387 00388 #define URBI_REGISTER_STRUCT(Cname, ...) \ 00389 namespace urbi \ 00390 { \ 00391 template<> \ 00392 struct uvalue_caster<Cname> \ 00393 { \ 00394 Cname operator()(UValue& v) \ 00395 { \ 00396 if (v.type != DATA_DICTIONARY) \ 00397 throw std::runtime_error("invalid cast to " #Cname "from " \ 00398 + string_cast(v)); \ 00399 UDictionary& dict = *v.dictionary; \ 00400 Cname res; \ 00401 LIBPORT_VAARGS_APPLY(URBI_STRUCT_CAST_FIELD, Cname, __VA_ARGS__); \ 00402 return res; \ 00403 } \ 00404 }; \ 00405 \ 00406 static UValue& operator,(UValue& v, const Cname &c) \ 00407 { \ 00408 v = UDictionary(); \ 00409 UDictionary& dict = *v.dictionary; \ 00410 dict["$sn"] = BOOST_PP_STRINGIZE(Cname); \ 00411 LIBPORT_VAARGS_APPLY(URBI_STRUCT_BCAST_FIELD, Cname, __VA_ARGS__); \ 00412 return v; \ 00413 } \ 00414 } 00415 00421 template<typename T> class UPackedData: public std::vector<T> 00422 { 00423 public: 00424 UPackedData() {}; 00425 UPackedData(const std::vector<T>& src): std::vector<T>(src) {}; 00426 template<typename I> UPackedData(I begin, I end):std::vector<T>(begin, end){}; 00427 }; 00428 00429 # include <urbi/uvalue.hxx> 00430 00431 # include <libport/warning-pop.hh> 00432 00433 #endif // ! URBI_UVALUE_HH