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