1 /************************************************************************
2 *
3 * Copyright 2010 - 2012 Jakob Leben (jakob.leben@gmail.com)
4 *
5 * This file is part of SuperCollider Qt GUI.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ************************************************************************/
21
22 #pragma once
23
24 #include "type_codec.hpp"
25
26 #include <PyrSlot.h>
27
28 #include <QMetaType>
29 #include <QVariant>
30
31 namespace QtCollider {
32
33 struct MetaType {
34 public:
35 static void initAll();
36
37 static MetaType* find(PyrSlot*);
38 static MetaType* find(int id);
39
40 // Generic algorithms
41
readQtCollider::MetaType42 template <typename T> static void* read(PyrSlot* slot, void* ptr) {
43 if (slot)
44 return new (ptr) T(TypeCodec<T>::read(slot));
45 else
46 return new (ptr) T();
47 }
48
readQtCollider::MetaType49 template <typename T> static QVariant read(PyrSlot* slot) {
50 return QVariant::fromValue<T>(TypeCodec<T>::read(slot));
51 }
52
writeQtCollider::MetaType53 template <typename T> static void write(PyrSlot* slot, void* ptr) {
54 TypeCodec<T>::write(slot, *reinterpret_cast<T*>(ptr));
55 }
56
writeQtCollider::MetaType57 template <typename T> static void write(PyrSlot* slot, const QVariant& var) {
58 TypeCodec<T>::write(slot, var.value<T>());
59 }
60
destructQtCollider::MetaType61 template <typename T> static void destruct(void* ptr) {
62 T* typed_ptr = reinterpret_cast<T*>(ptr);
63 typed_ptr->~T();
64 }
65
66 // Abstract access to generic algorithms
67
68 virtual size_t size() = 0;
69 virtual void* read(PyrSlot*, void* ptr) = 0;
70 virtual QVariant read(PyrSlot*) = 0;
71 virtual void write(PyrSlot*, void* ptr) = 0;
72 virtual void write(PyrSlot*, const QVariant&) = 0;
73 virtual void destruct(void* ptr) = 0;
74
idQtCollider::MetaType75 const int& id() const { return mId; }
76
77 protected:
MetaTypeQtCollider::MetaType78 MetaType(int a_id): mId(a_id) {}
79 int mId;
80 };
81
82 template <typename T> struct MetaTypeImpl : MetaType {
MetaTypeImplQtCollider::MetaTypeImpl83 MetaTypeImpl(): MetaType(qMetaTypeId<T>()) {}
84
sizeQtCollider::MetaTypeImpl85 size_t size() { return sizeof(T); }
86
readQtCollider::MetaTypeImpl87 void* read(PyrSlot* slot, void* ptr) { return MetaType::read<T>(slot, ptr); }
88
readQtCollider::MetaTypeImpl89 QVariant read(PyrSlot* slot) { return MetaType::read<T>(slot); }
90
writeQtCollider::MetaTypeImpl91 void write(PyrSlot* slot, void* ptr) { MetaType::write<T>(slot, ptr); }
92
writeQtCollider::MetaTypeImpl93 void write(PyrSlot* slot, const QVariant& var) { MetaType::write<T>(slot, var); }
94
destructQtCollider::MetaTypeImpl95 void destruct(void* ptr) { MetaType::destruct<T>(ptr); }
96
97 /////////////
98
99 static MetaTypeImpl<T>* instance;
100 };
101
102 class MetaValue {
103 public:
MetaValue()104 MetaValue(): mType(0), mData(0) {}
105
~MetaValue()106 ~MetaValue() {
107 if (mType)
108 mType->destruct(mData);
109 }
110
type() const111 MetaType* type() const { return mType; }
112
read(void * mem,MetaType * type,PyrSlot * slot)113 void read(void* mem, MetaType* type, PyrSlot* slot) {
114 mData = mem;
115 mType = type;
116 mType->read(slot, mData);
117 }
118
write(PyrSlot * slot)119 void write(PyrSlot* slot) {
120 if (mType)
121 mType->write(slot, mData);
122 }
123
value()124 template <typename T> T value() {
125 if (mType && qMetaTypeId<T>() == mType->id())
126 return *reinterpret_cast<T*>(mData);
127 else
128 return T();
129 }
130
toGenericArgument()131 QGenericArgument toGenericArgument() {
132 if (mType)
133 return QGenericArgument(QMetaType::typeName(mType->id()), mData);
134 else
135 return QGenericArgument();
136 }
137
toGenericReturnArgument()138 QGenericReturnArgument toGenericReturnArgument() {
139 if (mType)
140 return QGenericReturnArgument(QMetaType::typeName(mType->id()), mData);
141 else
142 return QGenericReturnArgument();
143 }
144
145 private:
146 MetaType* mType;
147 void* mData;
148 };
149
150
metaType()151 template <typename T> inline MetaType* metaType() { return MetaTypeImpl<T>::instance; }
152
153 template <> struct TypeCodec<QVariant> {
safeReadQtCollider::TypeCodec154 static QVariant safeRead(PyrSlot* slot) {
155 MetaType* mt = MetaType::find(slot);
156 return mt ? mt->read(slot) : QVariant();
157 }
158 };
159
set(PyrSlot * s,const QVariant & var)160 inline bool set(PyrSlot* s, const QVariant& var) {
161 MetaType* mt = MetaType::find(var.userType());
162 if (!mt)
163 return false;
164 mt->write(s, var);
165 return true;
166 }
167
168 } // namespace QtCollider
169