QtGStreamer  0.10.2
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator
value.h
00001 /*
00002     Copyright (C) 2009-2010  George Kiagiadakis <kiagiadakis.george@gmail.com>
00003     Copyright (C) 2010 Collabora Ltd.
00004       @author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
00005 
00006     This library is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU Lesser General Public License as published
00008     by the Free Software Foundation; either version 2.1 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU Lesser General Public License for more details.
00015 
00016     You should have received a copy of the GNU Lesser General Public License
00017     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00018 */
00019 #ifndef QGLIB_VALUE_H
00020 #define QGLIB_VALUE_H
00021 
00022 #include "global.h"
00023 #include "type.h"
00024 #include "refpointer.h"
00025 #include <boost/mpl/if.hpp>
00026 #include <boost/type_traits.hpp>
00027 #include <stdexcept>
00028 #include <QtCore/QString>
00029 #include <QtCore/QDebug>
00030 #include <QtCore/QSharedData>
00031 
00032 namespace QGlib {
00033 
00041 struct QTGLIB_EXPORT ValueVTable
00042 {
00043     typedef void (*SetFunction)(Value & value, const void *data);
00044     typedef void (*GetFunction)(const Value & value, void *data);
00045 
00046     inline ValueVTable() : set(NULL), get(NULL) {}
00047     inline ValueVTable(SetFunction s, GetFunction g) : set(s), get(g) {}
00048 
00049     SetFunction set;
00050     GetFunction get;
00051 };
00052 
00053 
00073 class QTGLIB_EXPORT Value
00074 {
00075 public:
00077     Value();
00078 
00080     explicit Value(const GValue *gvalue);
00081 
00089     explicit Value(Type type);
00090 
00091     Value(bool val); 
00092     Value(char val); 
00093     Value(uchar val); 
00094     Value(int val); 
00095     Value(uint val); 
00096     Value(long val); 
00097     Value(ulong val); 
00098     Value(qint64 val); 
00099     Value(quint64 val); 
00100     Value(float val); 
00101     Value(double val); 
00102     Value(const char *val); 
00103     Value(const QByteArray & val); 
00104     Value(const QString & val); 
00105 
00106     Value(const Value & other);
00107     Value & operator=(const Value & other);
00108 
00109     virtual ~Value();
00110 
00111 
00117     template <typename T>
00118     static inline Value create(const T & data);
00119 
00120 
00124     void init(Type type);
00125 
00131     template <typename T>
00132     inline void init();
00133 
00134 
00137     bool isValid() const;
00138 
00140     Type type() const;
00141 
00143     bool canTransformTo(Type type) const;
00144 
00149     Value transformTo(Type type) const;
00150 
00153     void clear();
00154 
00155 
00177     template <typename T> T get(bool *ok = NULL) const;
00178 
00189     template <typename T> void set(const T & data);
00190 
00191 
00193     inline bool toBool(bool *ok = NULL) const { return get<bool>(ok); }
00194 
00196     inline char toChar(bool *ok = NULL) const { return get<char>(ok); }
00197 
00199     inline uchar toUChar(bool *ok = NULL) const { return get<uchar>(ok); }
00200 
00202     inline int toInt(bool *ok = NULL) const { return get<int>(ok); }
00203 
00205     inline uint toUInt(bool *ok = NULL) const { return get<uint>(ok); }
00206 
00208     inline long toLong(bool *ok = NULL) const { return get<long>(ok); }
00209 
00211     inline ulong toULong(bool *ok = NULL) const { return get<ulong>(ok); }
00212 
00214     inline qint64 toInt64(bool *ok = NULL) const { return get<qint64>(ok); }
00215 
00217     inline quint64 toUInt64(bool *ok = NULL) const { return get<quint64>(ok); }
00218 
00220     inline QByteArray toByteArray(bool *ok = NULL) const { return get<QByteArray>(ok); }
00221 
00223     inline QString toString(bool *ok = NULL) const { return get<QString>(ok); }
00224 
00225 
00232     operator GValue*();
00233     operator const GValue*() const; 
00234 
00235 
00242     static void registerValueVTable(Type type, const ValueVTable & vtable);
00243 
00244 private:
00245     template <typename T>
00246     friend struct ValueImpl;
00247 
00255     void getData(Type dataType, void *data) const;
00256 
00264     void setData(Type dataType, const void *data);
00265 
00266     struct Data;
00267     QSharedDataPointer<Data> d;
00268 };
00269 
00270 
00279 template <typename T>
00280 struct ValueImpl
00281 {
00282     static inline T get(const Value & value);
00283     static inline void set(Value & value, const T & data);
00284 };
00285 
00286 // -- template implementations --
00287 
00288 //static
00289 template <typename T>
00290 inline Value Value::create(const T & data)
00291 {
00292     Value v;
00293     v.init<T>();
00294     v.set(data);
00295     return v;
00296 }
00297 
00298 template <typename T>
00299 inline void Value::init()
00300 {
00301     init(GetType<T>());
00302 }
00303 
00304 template <typename T>
00305 T Value::get(bool *ok) const
00306 {
00307     if (ok) {
00308         *ok = true;
00309     }
00310 
00311     try {
00312         return ValueImpl<T>::get(*this);
00313     } catch (const std::exception &) {
00314         if (ok) {
00315             *ok = false;
00316         }
00317         return T();
00318     }
00319 }
00320 
00321 template <typename T>
00322 void Value::set(const T & data)
00323 {
00324     try {
00325         ValueImpl<T>::set(*this, data);
00326     } catch (const std::exception & e) {
00327         qWarning() << "QGlib::Value::set:" << e.what();
00328     }
00329 }
00330 
00331 // -- default ValueImpl implementation --
00332 
00333 template <typename T>
00334 inline T ValueImpl<T>::get(const Value & value)
00335 {
00336     //Use int for enums, T for everything else
00337     typename boost::mpl::if_<
00338         boost::is_enum<T>,
00339         int, T
00340     >::type result;
00341 
00342     value.getData(GetType<T>(), &result);
00343     return static_cast<T>(result);
00344 }
00345 
00346 template <typename T>
00347 inline void ValueImpl<T>::set(Value & value, const T & data)
00348 {
00349     //Use const int for enums, const T for everything else
00350     typename boost::mpl::if_<
00351         boost::is_enum<T>,
00352         const int, const T &
00353     >::type dataRef = data;
00354 
00355     value.setData(GetType<T>(), &dataRef);
00356 }
00357 
00358 // -- ValueImpl specialization for QFlags --
00359 
00360 template <class T>
00361 struct ValueImpl< QFlags<T> >
00362 {
00363     static inline QFlags<T> get(const Value & value)
00364     {
00365         uint flags;
00366         value.getData(GetType< QFlags<T> >(), &flags);
00367         return QFlags<T>(QFlag(flags));
00368     }
00369 
00370     static inline void set(Value & value, const QFlags<T> & data)
00371     {
00372         uint flags = data;
00373         value.setData(GetType< QFlags<T> >(), &flags);
00374     }
00375 };
00376 
00377 // -- ValueImpl specialization for RefPointer --
00378 
00379 template <class T>
00380 struct ValueImpl< RefPointer<T> >
00381 {
00382     static inline RefPointer<T> get(const Value & value)
00383     {
00384         typename T::CType *gobj;
00385         value.getData(GetType<T>(), &gobj);
00386         return RefPointer<T>::wrap(gobj);
00387     }
00388 
00389     static inline void set(Value & value, const RefPointer<T> & data)
00390     {
00391         typename T::CType *gobj = static_cast<typename T::CType*>(data);
00392         value.setData(GetType<T>(), &gobj);
00393     }
00394 };
00395 
00396 // -- ValueImpl specializations for string literals --
00397 
00398 template <int N>
00399 struct ValueImpl<const char[N]> //ISO C++ string literals are const char[]
00400 {
00401     //No get method, obviously.
00402 
00403     static inline void set(Value & value, const char (&data)[N])
00404     {
00405         QByteArray str = QByteArray::fromRawData(data, N);
00406         value.setData(Type::String, &str);
00407     }
00408 };
00409 
00410 template <int N>
00411 struct ValueImpl<char[N]> //gcc string literals are char[]
00412 {
00413     //No get method, obviously.
00414 
00415     static inline void set(Value & value, const char (&data)[N])
00416     {
00417         QByteArray str = QByteArray::fromRawData(data, N);
00418         value.setData(Type::String, &str);
00419     }
00420 };
00421 
00422 // -- ValueImpl specialization for const char* --
00423 
00424 template <>
00425 struct ValueImpl<const char*>
00426 {
00427     //No get method, obviously.
00428 
00429     static inline void set(Value & value, const char *data)
00430     {
00431         QByteArray str = QByteArray::fromRawData(data, qstrlen(data));
00432         value.setData(Type::String, &str);
00433     }
00434 };
00435 
00436 // -- ValueImpl specialization for QString --
00437 
00438 template <>
00439 struct ValueImpl<QString>
00440 {
00441     static inline QString get(const Value & value)
00442     {
00443         QByteArray str;
00444         value.getData(Type::String, &str);
00445         return QString::fromUtf8(str);
00446     }
00447 
00448     static inline void set(Value & value, const QString & data)
00449     {
00450         QByteArray str = data.toUtf8();
00451         value.setData(Type::String, &str);
00452     }
00453 };
00454 
00455 // -- ValueImpl specialization for Value --
00456 
00457 template <>
00458 struct ValueImpl<Value>
00459 {
00460     static inline Value get(const Value & value)
00461     {
00462         return value;
00463     }
00464 
00465     static inline void set(Value & value, const Value & data)
00466     {
00467         value = data;
00468     }
00469 };
00470 
00471 // -- Exceptions thrown from getData/setData --
00472 
00473 namespace Private {
00474 
00475 class QTGLIB_EXPORT InvalidValueException : public std::logic_error
00476 {
00477 public:
00478     inline InvalidValueException()
00479         : std::logic_error("This Value instance has not been initialized") {}
00480 };
00481 
00482 class QTGLIB_EXPORT InvalidTypeException : public std::logic_error
00483 {
00484 public:
00485     inline InvalidTypeException(const std::string & dataType, const std::string & valueType)
00486         : std::logic_error("Unable to handle value type \"" + dataType +
00487                            "\". This Value instance has been initialized to hold values of type \""
00488                            + valueType + "\" and no conversion is possible") {}
00489 };
00490 
00491 class QTGLIB_EXPORT UnregisteredTypeException : public std::logic_error
00492 {
00493 public:
00494     inline UnregisteredTypeException(const std::string & typeName)
00495         : std::logic_error("Unable to handle unregistered type \"" + typeName + "\"") {}
00496 };
00497 
00498 class QTGLIB_EXPORT TransformationFailedException : public std::runtime_error
00499 {
00500 public:
00501     inline TransformationFailedException(const std::string & srcTypeName,
00502                                          const std::string & destTypeName)
00503         : std::runtime_error("Failed to transform value from type \""
00504                              + srcTypeName + "\" to type \"" + destTypeName + "\"") {}
00505 };
00506 
00507 } //namespace Private
00508 
00509 // -- QDebug operator --
00510 
00512 QTGLIB_EXPORT QDebug operator<<(QDebug debug, const Value & value);
00513 
00514 } //namespace QGlib
00515 
00516 QGLIB_REGISTER_TYPE(QGlib::Value)
00517 
00518 #endif