File indexing completed on 2024-03-24 15:37:25
0001 /*************************************************************************** 0002 * metafunction.cpp 0003 * This file is part of the KDE project 0004 * copyright (C)2005-2006 Ian Reinhart Geiser <geiseri@kde.org> 0005 * copyright (C)2005-2006 Matt Broadstone <mbroadst@gmail.com> 0006 * copyright (C)2005-2006 Richard J. Moore <rich@kde.org> 0007 * copyright (C)2005-2006 Erik L. Bunce <kde@bunce.us> 0008 * copyright (C)2005-2007 by Sebastian Sauer <mail@dipe.org> 0009 * 0010 * This program is free software; you can redistribute it and/or 0011 * modify it under the terms of the GNU Library General Public 0012 * License as published by the Free Software Foundation; either 0013 * version 2 of the License, or (at your option) any later version. 0014 * This program is distributed in the hope that it will be useful, 0015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0017 * Library General Public License for more details. 0018 * You should have received a copy of the GNU Library General Public License 0019 * along with this program; see the file COPYING. If not, write to 0020 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0021 * Boston, MA 02110-1301, USA. 0022 ***************************************************************************/ 0023 0024 #include "metafunction.h" 0025 0026 #include <QVector> 0027 0028 namespace Kross 0029 { 0030 0031 static const char s_fakeClassName[] = "ScriptFunction"; 0032 0033 class KROSSCORE_NO_EXPORT MetaFunction::Private 0034 { 0035 public: 0036 /// The stringdata. 0037 char* stringData; 0038 /// The data array. 0039 QVector<uint> data; 0040 }; 0041 0042 MetaFunction::MetaFunction(QObject *sender, const QByteArray &signal) 0043 : QObject() 0044 , m_sender(sender) 0045 , m_signature(QMetaObject::normalizedSignature(signal.constData())) 0046 , d(new Private) 0047 { 0048 //krossdebug(QString("MetaFunction sender=\"%1\" signal=\"%2\"").arg(sender->objectName()).arg(m_signature.constData())); 0049 0050 const QByteArray signalName = signal.left(signal.indexOf('(')); 0051 0052 const QList<QByteArray> types = parameterTypeNamesFromSignature(m_signature.constData()); 0053 0054 QList<int> parameterMetaTypes; 0055 parameterMetaTypes.append(QMetaType::Void); // return type 0056 foreach(const QByteArray &typeName, types) { 0057 parameterMetaTypes.append(QMetaType::type(typeName.constData())); // ## might be missing support for non-builtin types... 0058 } 0059 0060 QVector<uint>& dataRef = d->data; 0061 dataRef.resize(20 + parameterMetaTypes.count()); 0062 0063 // content 0064 dataRef[0] = 7; // revision 0065 dataRef[1] = 0; // classname (the first string) 0066 dataRef[2] = 0; // classinfo count 0067 dataRef[3] = 0; // classinfo data 0068 dataRef[4] = 1; // methods count 0069 dataRef[5] = 14; // methods data 0070 dataRef[6] = 0; // properties count 0071 dataRef[7] = 0; // properties data 0072 dataRef[8] = 0; // enums/sets count 0073 dataRef[9] = 0; // enums/sets data 0074 dataRef[10] = 0; // constructors count 0075 dataRef[11] = 0; // constructors data 0076 dataRef[12] = 0; // flags 0077 dataRef[13] = 0; // signal count 0078 0079 // slots: name, argc, parameters, tag, flags 0080 dataRef[14] = 1; // name 0081 dataRef[15] = types.count(); // parameter count 0082 dataRef[16] = 19; // parameter data 0083 dataRef[17] = 2; // tag (RequiresVariantMetaObject) 0084 dataRef[18] = 0x0a; // flags (public slot) 0085 0086 // slots: parameters 0087 int i = 19; 0088 foreach (int metaType, parameterMetaTypes) { 0089 dataRef[i++] = metaType; 0090 } 0091 0092 dataRef[i++] = 0; // eod 0093 0094 // string table 0095 // qt_metacast expects the first string in the string table to be the class name. 0096 const QByteArray className(s_fakeClassName); 0097 int offsetOfStringdataMember = 2 * sizeof(QByteArrayData); 0098 int stringdataOffset = 0; 0099 d->stringData = new char[offsetOfStringdataMember + className.size() + 1 + signalName.size() + 1]; 0100 writeString(d->stringData, /*index*/0, className, offsetOfStringdataMember, stringdataOffset); 0101 writeString(d->stringData, 1, signalName, offsetOfStringdataMember, stringdataOffset); 0102 0103 // static metaobject 0104 staticMetaObject.d.superdata = &QObject::staticMetaObject; 0105 staticMetaObject.d.stringdata = reinterpret_cast<const QByteArrayData *>(d->stringData); 0106 staticMetaObject.d.data = dataRef.data(); 0107 staticMetaObject.d.relatedMetaObjects = nullptr; 0108 staticMetaObject.d.extradata = nullptr; 0109 staticMetaObject.d.static_metacall = nullptr; 0110 } 0111 0112 MetaFunction::~MetaFunction() { 0113 delete[] d->stringData; 0114 delete d; 0115 } 0116 0117 const QMetaObject *MetaFunction::metaObject() const 0118 { 0119 return &staticMetaObject; 0120 } 0121 0122 void *MetaFunction::qt_metacast(const char *_clname) 0123 { 0124 if (! _clname) { 0125 return nullptr; 0126 } 0127 if (! qstrcmp(_clname, s_fakeClassName)) { 0128 return static_cast<void *>(const_cast< MetaFunction * >(this)); 0129 } 0130 return QObject::qt_metacast(_clname); 0131 } 0132 0133 // from Qt5's qmetaobjectbuilder.cpp 0134 void MetaFunction::writeString(char *out, int i, const QByteArray &str, 0135 const int offsetOfStringdataMember, int &stringdataOffset) 0136 { 0137 int size = str.size(); 0138 qptrdiff offset = offsetOfStringdataMember + stringdataOffset 0139 - i * sizeof(QByteArrayData); 0140 const QByteArrayData data = 0141 Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, offset); 0142 memcpy(out + i * sizeof(QByteArrayData), &data, sizeof(QByteArrayData)); 0143 memcpy(out + offsetOfStringdataMember + stringdataOffset, str.constData(), size); 0144 out[offsetOfStringdataMember + stringdataOffset + size] = '\0'; 0145 stringdataOffset += size + 1; 0146 } 0147 0148 // from Qt5's QMetaObjectPrivate 0149 QList<QByteArray> MetaFunction::parameterTypeNamesFromSignature(const char *signature) 0150 { 0151 QList<QByteArray> list; 0152 while (*signature && *signature != '(') 0153 ++signature; 0154 while (*signature && *signature != ')' && *++signature != ')') { 0155 const char *begin = signature; 0156 int level = 0; 0157 while (*signature && (level > 0 || *signature != ',') && *signature != ')') { 0158 if (*signature == '<') 0159 ++level; 0160 else if (*signature == '>') 0161 --level; 0162 ++signature; 0163 } 0164 list += QByteArray(begin, signature - begin); 0165 } 0166 return list; 0167 } 0168 0169 }