Urbi SDK Remote for C++  2.7.3
uvalue.hh
Go to the documentation of this file.
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