QtGStreamer  0.10.2
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Pages
value.h
1 /*
2  Copyright (C) 2009-2010 George Kiagiadakis <kiagiadakis.george@gmail.com>
3  Copyright (C) 2010 Collabora Ltd.
4  @author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
5 
6  This library is free software; you can redistribute it and/or modify
7  it under the terms of the GNU Lesser General Public License as published
8  by the Free Software Foundation; either version 2.1 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 #ifndef QGLIB_VALUE_H
20 #define QGLIB_VALUE_H
21 
22 #include "global.h"
23 #include "type.h"
24 #include "refpointer.h"
25 #include <boost/mpl/if.hpp>
26 #include <boost/type_traits.hpp>
27 #include <stdexcept>
28 #include <QtCore/QString>
29 #include <QtCore/QDebug>
30 #include <QtCore/QSharedData>
31 
32 namespace QGlib {
33 
41 struct QTGLIB_EXPORT ValueVTable
42 {
43  typedef void (*SetFunction)(Value & value, const void *data);
44  typedef void (*GetFunction)(const Value & value, void *data);
45 
46  inline ValueVTable() : set(NULL), get(NULL) {}
47  inline ValueVTable(SetFunction s, GetFunction g) : set(s), get(g) {}
48 
49  SetFunction set;
50  GetFunction get;
51 };
52 
53 
73 class QTGLIB_EXPORT Value
74 {
75 public:
77  Value();
78 
80  explicit Value(const GValue *gvalue);
81 
89  explicit Value(Type type);
90 
91  Value(bool val);
92  Value(char val);
93  Value(uchar val);
94  Value(int val);
95  Value(uint val);
96  Value(long val);
97  Value(ulong val);
98  Value(qint64 val);
99  Value(quint64 val);
100  Value(float val);
101  Value(double val);
102  Value(const char *val);
103  Value(const QByteArray & val);
104  Value(const QString & val);
105 
106  Value(const Value & other);
107  Value & operator=(const Value & other);
108 
109  virtual ~Value();
110 
111 
117  template <typename T>
118  static inline Value create(const T & data);
119 
120 
124  void init(Type type);
125 
131  template <typename T>
132  inline void init();
133 
134 
137  bool isValid() const;
138 
140  Type type() const;
141 
143  bool canTransformTo(Type type) const;
144 
149  Value transformTo(Type type) const;
150 
153  void clear();
154 
155 
177  template <typename T> T get(bool *ok = NULL) const;
178 
189  template <typename T> void set(const T & data);
190 
191 
193  inline bool toBool(bool *ok = NULL) const { return get<bool>(ok); }
194 
196  inline char toChar(bool *ok = NULL) const { return get<char>(ok); }
197 
199  inline uchar toUChar(bool *ok = NULL) const { return get<uchar>(ok); }
200 
202  inline int toInt(bool *ok = NULL) const { return get<int>(ok); }
203 
205  inline uint toUInt(bool *ok = NULL) const { return get<uint>(ok); }
206 
208  inline long toLong(bool *ok = NULL) const { return get<long>(ok); }
209 
211  inline ulong toULong(bool *ok = NULL) const { return get<ulong>(ok); }
212 
214  inline qint64 toInt64(bool *ok = NULL) const { return get<qint64>(ok); }
215 
217  inline quint64 toUInt64(bool *ok = NULL) const { return get<quint64>(ok); }
218 
220  inline QByteArray toByteArray(bool *ok = NULL) const { return get<QByteArray>(ok); }
221 
223  inline QString toString(bool *ok = NULL) const { return get<QString>(ok); }
224 
225 
232  operator GValue*();
233  operator const GValue*() const;
234 
235 
242  static void registerValueVTable(Type type, const ValueVTable & vtable);
243 
244 private:
245  template <typename T>
246  friend struct ValueImpl;
247 
255  void getData(Type dataType, void *data) const;
256 
264  void setData(Type dataType, const void *data);
265 
266  struct Data;
267  QSharedDataPointer<Data> d;
268 };
269 
270 
279 template <typename T>
280 struct ValueImpl
281 {
282  static inline T get(const Value & value);
283  static inline void set(Value & value, const T & data);
284 };
285 
286 // -- template implementations --
287 
288 //static
289 template <typename T>
290 inline Value Value::create(const T & data)
291 {
292  Value v;
293  v.init<T>();
294  v.set(data);
295  return v;
296 }
297 
298 template <typename T>
299 inline void Value::init()
300 {
301  init(GetType<T>());
302 }
303 
304 template <typename T>
305 T Value::get(bool *ok) const
306 {
307  if (ok) {
308  *ok = true;
309  }
310 
311  try {
312  return ValueImpl<T>::get(*this);
313  } catch (const std::exception &) {
314  if (ok) {
315  *ok = false;
316  }
317  return T();
318  }
319 }
320 
321 template <typename T>
322 void Value::set(const T & data)
323 {
324  try {
325  ValueImpl<T>::set(*this, data);
326  } catch (const std::exception & e) {
327  qWarning() << "QGlib::Value::set:" << e.what();
328  }
329 }
330 
331 // -- default ValueImpl implementation --
332 
333 template <typename T>
334 inline T ValueImpl<T>::get(const Value & value)
335 {
336  //Use int for enums, T for everything else
337  typename boost::mpl::if_<
338  boost::is_enum<T>,
339  int, T
340  >::type result;
341 
342  value.getData(GetType<T>(), &result);
343  return static_cast<T>(result);
344 }
345 
346 template <typename T>
347 inline void ValueImpl<T>::set(Value & value, const T & data)
348 {
349  //Use const int for enums, const T for everything else
350  typename boost::mpl::if_<
351  boost::is_enum<T>,
352  const int, const T &
353  >::type dataRef = data;
354 
355  value.setData(GetType<T>(), &dataRef);
356 }
357 
358 // -- ValueImpl specialization for QFlags --
359 
360 template <class T>
361 struct ValueImpl< QFlags<T> >
362 {
363  static inline QFlags<T> get(const Value & value)
364  {
365  uint flags;
366  value.getData(GetType< QFlags<T> >(), &flags);
367  return QFlags<T>(QFlag(flags));
368  }
369 
370  static inline void set(Value & value, const QFlags<T> & data)
371  {
372  uint flags = data;
373  value.setData(GetType< QFlags<T> >(), &flags);
374  }
375 };
376 
377 // -- ValueImpl specialization for RefPointer --
378 
379 template <class T>
380 struct ValueImpl< RefPointer<T> >
381 {
382  static inline RefPointer<T> get(const Value & value)
383  {
384  typename T::CType *gobj;
385  value.getData(GetType<T>(), &gobj);
386  return RefPointer<T>::wrap(gobj);
387  }
388 
389  static inline void set(Value & value, const RefPointer<T> & data)
390  {
391  typename T::CType *gobj = static_cast<typename T::CType*>(data);
392  value.setData(GetType<T>(), &gobj);
393  }
394 };
395 
396 // -- ValueImpl specializations for string literals --
397 
398 template <int N>
399 struct ValueImpl<const char[N]> //ISO C++ string literals are const char[]
400 {
401  //No get method, obviously.
402 
403  static inline void set(Value & value, const char (&data)[N])
404  {
405  QByteArray str = QByteArray::fromRawData(data, N);
406  value.setData(Type::String, &str);
407  }
408 };
409 
410 template <int N>
411 struct ValueImpl<char[N]> //gcc string literals are char[]
412 {
413  //No get method, obviously.
414 
415  static inline void set(Value & value, const char (&data)[N])
416  {
417  QByteArray str = QByteArray::fromRawData(data, N);
418  value.setData(Type::String, &str);
419  }
420 };
421 
422 // -- ValueImpl specialization for const char* --
423 
424 template <>
425 struct ValueImpl<const char*>
426 {
427  //No get method, obviously.
428 
429  static inline void set(Value & value, const char *data)
430  {
431  QByteArray str = QByteArray::fromRawData(data, qstrlen(data));
432  value.setData(Type::String, &str);
433  }
434 };
435 
436 // -- ValueImpl specialization for QString --
437 
438 template <>
439 struct ValueImpl<QString>
440 {
441  static inline QString get(const Value & value)
442  {
443  QByteArray str;
444  value.getData(Type::String, &str);
445  return QString::fromUtf8(str);
446  }
447 
448  static inline void set(Value & value, const QString & data)
449  {
450  QByteArray str = data.toUtf8();
451  value.setData(Type::String, &str);
452  }
453 };
454 
455 // -- ValueImpl specialization for Value --
456 
457 template <>
458 struct ValueImpl<Value>
459 {
460  static inline Value get(const Value & value)
461  {
462  return value;
463  }
464 
465  static inline void set(Value & value, const Value & data)
466  {
467  value = data;
468  }
469 };
470 
471 // -- Exceptions thrown from getData/setData --
472 
473 namespace Private {
474 
475 class QTGLIB_EXPORT InvalidValueException : public std::logic_error
476 {
477 public:
478  inline InvalidValueException()
479  : std::logic_error("This Value instance has not been initialized") {}
480 };
481 
482 class QTGLIB_EXPORT InvalidTypeException : public std::logic_error
483 {
484 public:
485  inline InvalidTypeException(const std::string & dataType, const std::string & valueType)
486  : std::logic_error("Unable to handle value type \"" + dataType +
487  "\". This Value instance has been initialized to hold values of type \""
488  + valueType + "\" and no conversion is possible") {}
489 };
490 
491 class QTGLIB_EXPORT UnregisteredTypeException : public std::logic_error
492 {
493 public:
494  inline UnregisteredTypeException(const std::string & typeName)
495  : std::logic_error("Unable to handle unregistered type \"" + typeName + "\"") {}
496 };
497 
498 class QTGLIB_EXPORT TransformationFailedException : public std::runtime_error
499 {
500 public:
501  inline TransformationFailedException(const std::string & srcTypeName,
502  const std::string & destTypeName)
503  : std::runtime_error("Failed to transform value from type \""
504  + srcTypeName + "\" to type \"" + destTypeName + "\"") {}
505 };
506 
507 } //namespace Private
508 
509 // -- QDebug operator --
510 
512 QTGLIB_EXPORT QDebug operator<<(QDebug debug, const Value & value);
513 
514 } //namespace QGlib
515 
516 QGLIB_REGISTER_TYPE(QGlib::Value)
517 
518 #endif