QtGStreamer  0.10.1
 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 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 #ifdef Q_MOC_RUN
00023 #define BOOST_TT_HAS_OPERATOR_HPP_INCLUDED
00024 #endif
00025 
00026 #include "global.h"
00027 #include "type.h"
00028 #include "refpointer.h"
00029 #include <boost/mpl/if.hpp>
00030 #include <boost/type_traits.hpp>
00031 #include <stdexcept>
00032 #include <QtCore/QString>
00033 #include <QtCore/QDebug>
00034 #include <QtCore/QSharedData>
00035 
00036 namespace QGlib {
00037 
00045 struct QTGLIB_EXPORT ValueVTable
00046 {
00047     typedef void (*SetFunction)(Value & value, const void *data);
00048     typedef void (*GetFunction)(const Value & value, void *data);
00049 
00050     inline ValueVTable() : set(NULL), get(NULL) {}
00051     inline ValueVTable(SetFunction s, GetFunction g) : set(s), get(g) {}
00052 
00053     SetFunction set;
00054     GetFunction get;
00055 };
00056 
00057 
00077 class QTGLIB_EXPORT Value
00078 {
00079 public:
00081     Value();
00082 
00084     explicit Value(const GValue *gvalue);
00085 
00093     explicit Value(Type type);
00094 
00095     Value(bool val); 
00096     Value(char val); 
00097     Value(uchar val); 
00098     Value(int val); 
00099     Value(uint val); 
00100     Value(long val); 
00101     Value(ulong val); 
00102     Value(qint64 val); 
00103     Value(quint64 val); 
00104     Value(float val); 
00105     Value(double val); 
00106     Value(const char *val); 
00107     Value(const QByteArray & val); 
00108     Value(const QString & val); 
00109 
00110     Value(const Value & other);
00111     Value & operator=(const Value & other);
00112 
00113     virtual ~Value();
00114 
00115 
00121     template <typename T>
00122     static inline Value create(const T & data);
00123 
00124 
00128     void init(Type type);
00129 
00135     template <typename T>
00136     inline void init();
00137 
00138 
00141     bool isValid() const;
00142 
00144     Type type() const;
00145 
00147     bool canTransformTo(Type type) const;
00148 
00153     Value transformTo(Type type) const;
00154 
00157     void clear();
00158 
00159 
00181     template <typename T> T get(bool *ok = NULL) const;
00182 
00193     template <typename T> void set(const T & data);
00194 
00195 
00197     inline bool toBool(bool *ok = NULL) const { return get<bool>(ok); }
00198 
00200     inline char toChar(bool *ok = NULL) const { return get<char>(ok); }
00201 
00203     inline uchar toUChar(bool *ok = NULL) const { return get<uchar>(ok); }
00204 
00206     inline int toInt(bool *ok = NULL) const { return get<int>(ok); }
00207 
00209     inline uint toUInt(bool *ok = NULL) const { return get<uint>(ok); }
00210 
00212     inline long toLong(bool *ok = NULL) const { return get<long>(ok); }
00213 
00215     inline ulong toULong(bool *ok = NULL) const { return get<ulong>(ok); }
00216 
00218     inline qint64 toInt64(bool *ok = NULL) const { return get<qint64>(ok); }
00219 
00221     inline quint64 toUInt64(bool *ok = NULL) const { return get<quint64>(ok); }
00222 
00224     inline QByteArray toByteArray(bool *ok = NULL) const { return get<QByteArray>(ok); }
00225 
00227     inline QString toString(bool *ok = NULL) const { return get<QString>(ok); }
00228 
00229 
00236     operator GValue*();
00237     operator const GValue*() const; 
00238 
00239 
00246     static void registerValueVTable(Type type, const ValueVTable & vtable);
00247 
00248 private:
00249     template <typename T>
00250     friend struct ValueImpl;
00251 
00259     void getData(Type dataType, void *data) const;
00260 
00268     void setData(Type dataType, const void *data);
00269 
00270     struct Data;
00271     QSharedDataPointer<Data> d;
00272 };
00273 
00274 
00283 template <typename T>
00284 struct ValueImpl
00285 {
00286     static inline T get(const Value & value);
00287     static inline void set(Value & value, const T & data);
00288 };
00289 
00290 // -- template implementations --
00291 
00292 //static
00293 template <typename T>
00294 inline Value Value::create(const T & data)
00295 {
00296     Value v;
00297     v.init<T>();
00298     v.set(data);
00299     return v;
00300 }
00301 
00302 template <typename T>
00303 inline void Value::init()
00304 {
00305     init(GetType<T>());
00306 }
00307 
00308 template <typename T>
00309 T Value::get(bool *ok) const
00310 {
00311     if (ok) {
00312         *ok = true;
00313     }
00314 
00315     try {
00316         return ValueImpl<T>::get(*this);
00317     } catch (const std::exception &) {
00318         if (ok) {
00319             *ok = false;
00320         }
00321         return T();
00322     }
00323 }
00324 
00325 template <typename T>
00326 void Value::set(const T & data)
00327 {
00328     try {
00329         ValueImpl<T>::set(*this, data);
00330     } catch (const std::exception & e) {
00331         qWarning() << "QGlib::Value::set:" << e.what();
00332     }
00333 }
00334 
00335 // -- default ValueImpl implementation --
00336 
00337 template <typename T>
00338 inline T ValueImpl<T>::get(const Value & value)
00339 {
00340     //Use int for enums, T for everything else
00341     typename boost::mpl::if_<
00342         boost::is_enum<T>,
00343         int, T
00344     >::type result;
00345 
00346     value.getData(GetType<T>(), &result);
00347     return static_cast<T>(result);
00348 }
00349 
00350 template <typename T>
00351 inline void ValueImpl<T>::set(Value & value, const T & data)
00352 {
00353     //Use const int for enums, const T for everything else
00354     typename boost::mpl::if_<
00355         boost::is_enum<T>,
00356         const int, const T &
00357     >::type dataRef = data;
00358 
00359     value.setData(GetType<T>(), &dataRef);
00360 }
00361 
00362 // -- ValueImpl specialization for QFlags --
00363 
00364 template <class T>
00365 struct ValueImpl< QFlags<T> >
00366 {
00367     static inline QFlags<T> get(const Value & value)
00368     {
00369         uint flags;
00370         value.getData(GetType< QFlags<T> >(), &flags);
00371         return QFlags<T>(QFlag(flags));
00372     }
00373 
00374     static inline void set(Value & value, const QFlags<T> & data)
00375     {
00376         uint flags = data;
00377         value.setData(GetType< QFlags<T> >(), &flags);
00378     }
00379 };
00380 
00381 // -- ValueImpl specialization for RefPointer --
00382 
00383 template <class T>
00384 struct ValueImpl< RefPointer<T> >
00385 {
00386     static inline RefPointer<T> get(const Value & value)
00387     {
00388         typename T::CType *gobj;
00389         value.getData(GetType<T>(), &gobj);
00390         return RefPointer<T>::wrap(gobj);
00391     }
00392 
00393     static inline void set(Value & value, const RefPointer<T> & data)
00394     {
00395         typename T::CType *gobj = static_cast<typename T::CType*>(data);
00396         value.setData(GetType<T>(), &gobj);
00397     }
00398 };
00399 
00400 // -- ValueImpl specializations for string literals --
00401 
00402 template <int N>
00403 struct ValueImpl<const char[N]> //ISO C++ string literals are const char[]
00404 {
00405     //No get method, obviously.
00406 
00407     static inline void set(Value & value, const char (&data)[N])
00408     {
00409         QByteArray str = QByteArray::fromRawData(data, N);
00410         value.setData(Type::String, &str);
00411     }
00412 };
00413 
00414 template <int N>
00415 struct ValueImpl<char[N]> //gcc string literals are char[]
00416 {
00417     //No get method, obviously.
00418 
00419     static inline void set(Value & value, const char (&data)[N])
00420     {
00421         QByteArray str = QByteArray::fromRawData(data, N);
00422         value.setData(Type::String, &str);
00423     }
00424 };
00425 
00426 // -- ValueImpl specialization for const char* --
00427 
00428 template <>
00429 struct ValueImpl<const char*>
00430 {
00431     //No get method, obviously.
00432 
00433     static inline void set(Value & value, const char *data)
00434     {
00435         QByteArray str = QByteArray::fromRawData(data, qstrlen(data));
00436         value.setData(Type::String, &str);
00437     }
00438 };
00439 
00440 // -- ValueImpl specialization for QString --
00441 
00442 template <>
00443 struct ValueImpl<QString>
00444 {
00445     static inline QString get(const Value & value)
00446     {
00447         QByteArray str;
00448         value.getData(Type::String, &str);
00449         return QString::fromUtf8(str);
00450     }
00451 
00452     static inline void set(Value & value, const QString & data)
00453     {
00454         QByteArray str = data.toUtf8();
00455         value.setData(Type::String, &str);
00456     }
00457 };
00458 
00459 // -- ValueImpl specialization for Value --
00460 
00461 template <>
00462 struct ValueImpl<Value>
00463 {
00464     static inline Value get(const Value & value)
00465     {
00466         return value;
00467     }
00468 
00469     static inline void set(Value & value, const Value & data)
00470     {
00471         value = data;
00472     }
00473 };
00474 
00475 // -- Exceptions thrown from getData/setData --
00476 
00477 namespace Private {
00478 
00479 class QTGLIB_EXPORT InvalidValueException : public std::logic_error
00480 {
00481 public:
00482     inline InvalidValueException()
00483         : std::logic_error("This Value instance has not been initialized") {}
00484 };
00485 
00486 class QTGLIB_EXPORT InvalidTypeException : public std::logic_error
00487 {
00488 public:
00489     inline InvalidTypeException(const std::string & dataType, const std::string & valueType)
00490         : std::logic_error("Unable to handle value type \"" + dataType +
00491                            "\". This Value instance has been initialized to hold values of type \""
00492                            + valueType + "\" and no conversion is possible") {}
00493 };
00494 
00495 class QTGLIB_EXPORT UnregisteredTypeException : public std::logic_error
00496 {
00497 public:
00498     inline UnregisteredTypeException(const std::string & typeName)
00499         : std::logic_error("Unable to handle unregistered type \"" + typeName + "\"") {}
00500 };
00501 
00502 class QTGLIB_EXPORT TransformationFailedException : public std::runtime_error
00503 {
00504 public:
00505     inline TransformationFailedException(const std::string & srcTypeName,
00506                                          const std::string & destTypeName)
00507         : std::runtime_error("Failed to transform value from type \""
00508                              + srcTypeName + "\" to type \"" + destTypeName + "\"") {}
00509 };
00510 
00511 } //namespace Private
00512 
00513 // -- QDebug operator --
00514 
00516 QTGLIB_EXPORT QDebug operator<<(QDebug debug, const Value & value);
00517 
00518 } //namespace QGlib
00519 
00520 QGLIB_REGISTER_TYPE(QGlib::Value)
00521 
00522 #endif
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator