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 #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
00287
00288
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
00332
00333 template <typename T>
00334 inline T ValueImpl<T>::get(const Value & value)
00335 {
00336
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
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
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
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
00397
00398 template <int N>
00399 struct ValueImpl<const char[N]>
00400 {
00401
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]>
00412 {
00413
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
00423
00424 template <>
00425 struct ValueImpl<const char*>
00426 {
00427
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
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
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
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 }
00508
00509
00510
00512 QTGLIB_EXPORT QDebug operator<<(QDebug debug, const Value & value);
00513
00514 }
00515
00516 QGLIB_REGISTER_TYPE(QGlib::Value)
00517
00518 #endif