22 #include <boost/type_traits.hpp>
23 #include <glib-object.h>
24 #include <QtCore/QDebug>
25 #include <QtCore/QReadWriteLock>
35 ValueVTable getVTable(Type t)
const;
36 void setVTable(Type t,
const ValueVTable & vtable);
39 mutable QReadWriteLock lock;
40 QHash<Type, ValueVTable> dispatchTable;
43 Dispatcher::Dispatcher()
45 #define DECLARE_VTABLE(T, NICK, GTYPE) \
46 struct ValueVTable_##NICK \
48 static void get(const Value & value, void *data) \
50 *reinterpret_cast<T*>(data) = g_value_get_##NICK(value); \
53 static void set(Value & value, const void *data) \
55 g_value_set_##NICK(value, *reinterpret_cast<T const *>(data)); \
58 setVTable(GTYPE, ValueVTable(ValueVTable_##NICK::set, ValueVTable_##NICK::get));
60 DECLARE_VTABLE(
char,
char, Type::Char)
61 DECLARE_VTABLE(
unsigned char, uchar, Type::Uchar)
62 DECLARE_VTABLE(
bool,
boolean, Type::Boolean)
63 DECLARE_VTABLE(
int,
int, Type::Int)
64 DECLARE_VTABLE(
unsigned int, uint, Type::Uint)
65 DECLARE_VTABLE(
long,
long, Type::Long)
66 DECLARE_VTABLE(
unsigned long, ulong, Type::Ulong)
67 DECLARE_VTABLE(qint64, int64, Type::Int64)
68 DECLARE_VTABLE(quint64, uint64, Type::Uint64)
69 DECLARE_VTABLE(
int, enum, Type::Enum);
70 DECLARE_VTABLE(uint, flags, Type::Flags)
71 DECLARE_VTABLE(
float,
float, Type::Float)
72 DECLARE_VTABLE(
double,
double, Type::Double)
73 DECLARE_VTABLE(QByteArray,
string, Type::String)
74 DECLARE_VTABLE(
void*, pointer, Type::Pointer)
75 DECLARE_VTABLE(
void*, boxed, Type::Boxed)
76 DECLARE_VTABLE(GParamSpec*, param, Type::Param)
77 DECLARE_VTABLE(
void*,
object, Type::Object)
78 DECLARE_VTABLE(QGlib::Type, gtype, GetType<QGlib::Type>())
83 ValueVTable Dispatcher::getVTable(Type t)
const
88 if (t.isInterface()) {
89 QList<Type> prerequisites = t.interfacePrerequisites();
90 Q_FOREACH(Type prereq, prerequisites) {
91 if (prereq.isInstantiatable()) {
99 if (!t.isInstantiatable()) {
100 return ValueVTable();
104 QReadLocker l(&lock);
106 if (dispatchTable.contains(t)) {
107 return dispatchTable[t];
110 while (t.isDerived()) {
112 if (dispatchTable.contains(t)) {
113 return dispatchTable[t];
117 return ValueVTable();
120 void Dispatcher::setVTable(Type t,
const ValueVTable & vtable)
122 QWriteLocker l(&lock);
123 dispatchTable[t] = vtable;
128 Q_GLOBAL_STATIC(Private::Dispatcher, s_dispatcher);
134 struct QTGLIB_NO_EXPORT Value::Data :
public QSharedData
137 Data(
const Data & other);
140 inline Type type()
const {
return G_VALUE_TYPE(&m_value); }
141 inline GValue *value() {
return &m_value; }
142 inline const GValue *value()
const {
return &m_value; }
150 std::memset(&m_value, 0,
sizeof(GValue));
153 Value::Data::Data(
const Value::Data & other)
156 std::memset(&m_value, 0,
sizeof(GValue));
158 if (other.type() != Type::Invalid) {
159 g_value_init(value(), other.type());
160 g_value_copy(other.value(), value());
166 if (type() != Type::Invalid) {
167 g_value_unset(value());
183 if (gvalue && G_IS_VALUE(gvalue)) {
184 init(G_VALUE_TYPE(gvalue));
185 g_value_copy(gvalue, d->value());
195 #define VALUE_CONSTRUCTOR(T) \
196 Value::Value(T val) \
200 boost::remove_const< \
201 boost::remove_reference<T>::type \
207 VALUE_CONSTRUCTOR(
bool)
208 VALUE_CONSTRUCTOR(
char)
209 VALUE_CONSTRUCTOR(uchar)
210 VALUE_CONSTRUCTOR(
int)
211 VALUE_CONSTRUCTOR(uint)
212 VALUE_CONSTRUCTOR(
long)
213 VALUE_CONSTRUCTOR(ulong)
214 VALUE_CONSTRUCTOR(qint64)
215 VALUE_CONSTRUCTOR(quint64)
216 VALUE_CONSTRUCTOR(
float)
217 VALUE_CONSTRUCTOR(
double)
218 VALUE_CONSTRUCTOR(const
char *)
219 VALUE_CONSTRUCTOR(const QByteArray &)
220 VALUE_CONSTRUCTOR(const QString &)
222 #undef VALUE_CONSTRUCTOR
229 Value & Value::operator=(
const Value & other)
242 g_value_unset(d->value());
244 g_value_init(d->value(),
type);
249 return d->type() != Type::Invalid;
259 return isValid() ? g_value_type_transformable(
type(), t) :
false;
267 g_value_transform(d->value(), dest.d->value());
275 g_value_reset(d->value());
279 Value::operator GValue* ()
284 Value::operator
const GValue * ()
const
292 s_dispatcher()->setVTable(type, vtable);
295 static inline std::string toStdStringHelper(
const QString & str)
298 return str.toStdString();
300 const QByteArray asc = str.toAscii();
301 return std::string(asc.constData(), asc.length());
305 void Value::getData(Type dataType,
void *data)
const
308 throw Private::InvalidValueException();
309 }
else if (g_value_type_compatible(
type(), dataType)) {
310 ValueVTable vtable = s_dispatcher()->getVTable(dataType);
311 if (vtable.get != NULL) {
312 vtable.get(*
this, data);
314 throw Private::UnregisteredTypeException(toStdStringHelper(dataType.name()));
316 }
else if (dataType.isValueType() && g_value_type_transformable(
type(), dataType)) {
320 if (!g_value_transform(d->value(), v.d->value())) {
321 throw Private::TransformationFailedException(toStdStringHelper(
type().name()),
322 toStdStringHelper(dataType.name()));
325 v.getData(dataType, data);
327 throw Private::InvalidTypeException(toStdStringHelper(dataType.name()),
328 toStdStringHelper(
type().name()));
332 void Value::setData(Type dataType,
const void *data)
335 throw Private::InvalidValueException();
336 }
else if (g_value_type_compatible(dataType,
type())) {
337 ValueVTable vtable = s_dispatcher()->getVTable(dataType);
338 if (vtable.set != NULL) {
339 vtable.set(*
this, data);
341 throw Private::UnregisteredTypeException(toStdStringHelper(dataType.name()));
343 }
else if (dataType.isValueType() && g_value_type_transformable(dataType,
type())) {
346 v.setData(dataType, data);
348 if (!g_value_transform(v.d->value(), d->value())) {
349 throw Private::TransformationFailedException(toStdStringHelper(dataType.name()),
350 toStdStringHelper(
type().name()));
353 throw Private::InvalidTypeException(toStdStringHelper(dataType.name()),
354 toStdStringHelper(
type().name()));
359 QDebug operator<<(QDebug debug,
const Value & value)
361 debug.nospace() <<
"QGlib::Value";
363 debug <<
"(<invalid>)";
364 return debug.space();
368 if (g_value_fits_pointer(value)) {
369 quintptr ptr =
reinterpret_cast<quintptr
>(g_value_peek_pointer(value));
370 str = QString(QLatin1String(
"0x%1")).arg(ptr,
sizeof(quintptr)*2,
371 16, QLatin1Char(
'0'));
373 str = QLatin1String(
"<unknown value>");
377 debug <<
"(" << value.
type().name() <<
", " << str <<
")";
378 return debug.space();