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 }