23 #include <boost/type_traits.hpp>
25 #include <glib-object.h>
26 #include <QtCore/QDebug>
27 #include <QtCore/QReadWriteLock>
37 ValueVTable getVTable(Type t)
const;
38 void setVTable(Type t,
const ValueVTable & vtable);
41 mutable QReadWriteLock lock;
42 QHash<Type, ValueVTable> dispatchTable;
45 Dispatcher::Dispatcher()
47 #define DECLARE_VTABLE(T, NICK, GTYPE) \
48 struct ValueVTable_##NICK \
50 static void get(const Value & value, void *data) \
52 *reinterpret_cast<T*>(data) = g_value_get_##NICK(value); \
55 static void set(Value & value, const void *data) \
57 g_value_set_##NICK(value, *reinterpret_cast<T const *>(data)); \
60 setVTable(GTYPE, ValueVTable(ValueVTable_##NICK::set, ValueVTable_##NICK::get));
62 DECLARE_VTABLE(
char,
char, Type::Char)
63 DECLARE_VTABLE(
unsigned char, uchar, Type::Uchar)
64 DECLARE_VTABLE(
bool,
boolean, Type::Boolean)
65 DECLARE_VTABLE(
int,
int, Type::Int)
66 DECLARE_VTABLE(
unsigned int, uint, Type::Uint)
67 DECLARE_VTABLE(
long,
long, Type::Long)
68 DECLARE_VTABLE(
unsigned long, ulong, Type::Ulong)
69 DECLARE_VTABLE(qint64, int64, Type::Int64)
70 DECLARE_VTABLE(quint64, uint64, Type::Uint64)
71 DECLARE_VTABLE(
int,
enum, Type::Enum);
72 DECLARE_VTABLE(uint, flags, Type::Flags)
73 DECLARE_VTABLE(
float,
float, Type::Float)
74 DECLARE_VTABLE(
double,
double, Type::Double)
75 DECLARE_VTABLE(QByteArray,
string, Type::String)
76 DECLARE_VTABLE(
void*, pointer, Type::Pointer)
77 DECLARE_VTABLE(
void*, boxed, Type::Boxed)
78 DECLARE_VTABLE(GParamSpec*, param, Type::Param)
79 DECLARE_VTABLE(
void*,
object, Type::Object)
80 DECLARE_VTABLE(
QGlib::Type, gtype, GetType<QGlib::Type>())
85 ValueVTable Dispatcher::getVTable(Type t)
const
90 if (t.isInterface()) {
91 QList<Type> prerequisites = t.interfacePrerequisites();
92 Q_FOREACH(Type prereq, prerequisites) {
93 if (prereq.isInstantiatable()) {
101 if (!t.isInstantiatable()) {
102 return ValueVTable();
106 QReadLocker l(&lock);
108 if (dispatchTable.contains(t)) {
109 return dispatchTable[t];
112 while (t.isDerived()) {
114 if (dispatchTable.contains(t)) {
115 return dispatchTable[t];
119 return ValueVTable();
122 void Dispatcher::setVTable(Type t,
const ValueVTable & vtable)
124 QWriteLocker l(&lock);
125 dispatchTable[t] = vtable;
130 Q_GLOBAL_STATIC(Private::Dispatcher, s_dispatcher);
136 struct QTGLIB_NO_EXPORT Value::Data :
public QSharedData
139 Data(
const Data & other);
142 inline Type type()
const {
return G_VALUE_TYPE(&m_value); }
143 inline GValue *value() {
return &m_value; }
144 inline const GValue *value()
const {
return &m_value; }
152 std::memset(&m_value, 0,
sizeof(GValue));
155 Value::Data::Data(
const Value::Data & other)
158 std::memset(&m_value, 0,
sizeof(GValue));
160 if (other.type() != Type::Invalid) {
161 g_value_init(value(), other.type());
162 g_value_copy(other.value(), value());
168 if (type() != Type::Invalid) {
169 g_value_unset(value());
185 if (gvalue && G_IS_VALUE(gvalue)) {
186 init(G_VALUE_TYPE(gvalue));
187 g_value_copy(gvalue, d->value());
197 #define VALUE_CONSTRUCTOR(T) \
198 Value::Value(T val) \
202 boost::remove_const< \
203 boost::remove_reference<T>::type \
209 VALUE_CONSTRUCTOR(
bool)
210 VALUE_CONSTRUCTOR(
char)
211 VALUE_CONSTRUCTOR(uchar)
212 VALUE_CONSTRUCTOR(
int)
213 VALUE_CONSTRUCTOR(uint)
214 VALUE_CONSTRUCTOR(
long)
215 VALUE_CONSTRUCTOR(ulong)
216 VALUE_CONSTRUCTOR(qint64)
217 VALUE_CONSTRUCTOR(quint64)
218 VALUE_CONSTRUCTOR(
float)
219 VALUE_CONSTRUCTOR(
double)
220 VALUE_CONSTRUCTOR(
const char *)
221 VALUE_CONSTRUCTOR(
const QByteArray &)
222 VALUE_CONSTRUCTOR(
const QString &)
224 #undef VALUE_CONSTRUCTOR
231 Value & Value::operator=(
const Value & other)
244 g_value_unset(d->value());
246 g_value_init(d->value(),
type);
251 return d->type() != Type::Invalid;
261 return isValid() ? g_value_type_transformable(
type(), t) :
false;
269 g_value_transform(d->value(), dest.d->value());
277 g_value_reset(d->value());
281 Value::operator GValue* ()
286 Value::operator
const GValue * ()
const
294 s_dispatcher()->setVTable(
type, vtable);
297 static inline std::string toStdStringHelper(
const QString & str)
300 return str.toStdString();
302 const QByteArray asc = str.toAscii();
303 return std::string(asc.constData(), asc.length());
307 void Value::getData(Type dataType,
void *data)
const
310 throw Private::InvalidValueException();
311 }
else if (g_value_type_compatible(
type(), dataType)) {
312 ValueVTable vtable = s_dispatcher()->getVTable(dataType);
313 if (vtable.get != NULL) {
314 vtable.get(*
this, data);
316 throw Private::UnregisteredTypeException(toStdStringHelper(dataType.name()));
318 }
else if (dataType.isValueType() && g_value_type_transformable(
type(), dataType)) {
322 if (!g_value_transform(d->value(), v.d->value())) {
323 throw Private::TransformationFailedException(toStdStringHelper(
type().name()),
324 toStdStringHelper(dataType.name()));
327 v.getData(dataType, data);
329 throw Private::InvalidTypeException(toStdStringHelper(dataType.name()),
330 toStdStringHelper(
type().name()));
334 void Value::setData(Type dataType,
const void *data)
337 throw Private::InvalidValueException();
338 }
else if (g_value_type_compatible(dataType,
type())) {
339 ValueVTable vtable = s_dispatcher()->getVTable(dataType);
340 if (vtable.set != NULL) {
341 vtable.set(*
this, data);
343 throw Private::UnregisteredTypeException(toStdStringHelper(dataType.name()));
345 }
else if (dataType.isValueType() && g_value_type_transformable(dataType,
type())) {
348 v.setData(dataType, data);
350 if (!g_value_transform(v.d->value(), d->value())) {
351 throw Private::TransformationFailedException(toStdStringHelper(dataType.name()),
352 toStdStringHelper(
type().name()));
355 throw Private::InvalidTypeException(toStdStringHelper(dataType.name()),
356 toStdStringHelper(
type().name()));
361 QDebug operator<<(QDebug debug,
const Value & value)
363 debug.nospace() <<
"QGlib::Value";
364 if(!value.isValid()) {
365 debug <<
"(<invalid>)";
366 return debug.space();
368 QString str = value.toString();
370 if (g_value_fits_pointer(value)) {
371 quintptr ptr =
reinterpret_cast<quintptr
>(g_value_peek_pointer(value));
372 str = QString(QLatin1String(
"0x%1")).arg(ptr,
sizeof(quintptr)*2,
373 16, QLatin1Char(
'0'));
375 str = QLatin1String(
"<unknown value>");
379 debug <<
"(" << value.type().name() <<
", " << str <<
")";
380 return debug.space();
Wrapper class for GValue.
bool canTransformTo(Type type) const
Value transformTo(Type type) const
static void registerValueVTable(Type type, const ValueVTable &vtable)
Wrappers for Glib and GObject classes.