00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00291
00292
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
00336
00337 template <typename T>
00338 inline T ValueImpl<T>::get(const Value & value)
00339 {
00340
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
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
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
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
00401
00402 template <int N>
00403 struct ValueImpl<const char[N]>
00404 {
00405
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]>
00416 {
00417
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
00427
00428 template <>
00429 struct ValueImpl<const char*>
00430 {
00431
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
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
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
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 }
00512
00513
00514
00516 QTGLIB_EXPORT QDebug operator<<(QDebug debug, const Value & value);
00517
00518 }
00519
00520 QGLIB_REGISTER_TYPE(QGlib::Value)
00521
00522 #endif