Merge remote-tracking branch 'origin/containers' into api_changes
Change-Id: Ib8427caca38a14c040850bf45346f3213ffd04b3
This commit is contained in:
commit
08a993526e
26
dist/changes-5.0.0
vendored
26
dist/changes-5.0.0
vendored
@ -36,6 +36,13 @@ information about a particular change.
|
||||
- QCoreApplication::translate() will no longer return the source text when
|
||||
the translation is empty. Use lrelease -removeidentical for optimization.
|
||||
|
||||
- QString and QByteArray constructors that take a size argument will now treat
|
||||
negative sizes to indicate nul-terminated strings (a nul-terminated array of
|
||||
QChar, in the case of QString). In Qt 4, negative sizes were ignored and
|
||||
result in empty QString and QByteArray, respectively. The size argument to
|
||||
those constructors now has a default value of -1, thus replacing the separate
|
||||
constructors that did the same.
|
||||
|
||||
- Qt::escape() is deprecated (but can be enabled via
|
||||
QT_DISABLE_DEPRECATED_BEFORE), use QString::toHtmlEscaped() instead.
|
||||
|
||||
@ -51,6 +58,11 @@ information about a particular change.
|
||||
* QMetaType::construct() has been renamed to QMetaType::create().
|
||||
* QMetaType::unregisterType() has been removed.
|
||||
|
||||
- QMetaMethod::signature() has been renamed to QMetaMethod::methodSignature(),
|
||||
and the return type has been changed to QByteArray. This was done to be able
|
||||
to generate the signature string on demand, rather than always storing it in
|
||||
the meta-data.
|
||||
|
||||
- QTestLib:
|
||||
* The plain-text, xml and lightxml test output formats have been changed to
|
||||
show a test result for every row of test data in data-driven tests. In
|
||||
@ -533,6 +545,20 @@ Qt for Windows CE
|
||||
QMetaType::User, which means that it points to the first registered custom
|
||||
type, instead of a nonexistent type.
|
||||
|
||||
- QMetaType
|
||||
|
||||
* Interpretation of QMetaType::Void was changed. Before, in some cases
|
||||
it was returned as an invalid type id, but sometimes it was used as a valid
|
||||
type (C++ "void"). In Qt5, new QMetaType::UnknownType was introduced to
|
||||
distinguish between these two. QMetaType::UnknownType is an invalid type id
|
||||
signaling that a type is unknown to QMetaType, and QMetaType::Void
|
||||
is a valid type id of C++ void type. The difference will be visible for
|
||||
example in call to QMetaType::typeName(), this function will return null for
|
||||
QMetaType::UnknownType and a pointer to "void" string for
|
||||
QMetaType::Void.
|
||||
Please, notice that QMetaType::UnknownType has value 0, which previously was
|
||||
reserved for QMetaType::Void.
|
||||
|
||||
|
||||
- QMessageBox
|
||||
|
||||
|
@ -107,7 +107,7 @@ for(int i = metaObject->propertyOffset(); i < metaObject->propertyCount(); ++i)
|
||||
const QMetaObject* metaObject = obj->metaObject();
|
||||
QStringList methods;
|
||||
for(int i = metaObject->methodOffset(); i < metaObject->methodCount(); ++i)
|
||||
methods << QString::fromLatin1(metaObject->method(i).signature());
|
||||
methods << QString::fromLatin1(metaObject->method(i).methodSignature());
|
||||
//! [methodCount]
|
||||
|
||||
//! [6]
|
||||
|
@ -73,7 +73,7 @@ MyStruct s2 = var.value<MyStruct>();
|
||||
|
||||
//! [3]
|
||||
int id = QMetaType::type("MyClass");
|
||||
if (id != 0) {
|
||||
if (id != QMetaType::UnknownType) {
|
||||
void *myClassPtr = QMetaType::create(id);
|
||||
...
|
||||
QMetaType::destroy(id, myClassPtr);
|
||||
|
@ -400,7 +400,7 @@ QString QJsonValue::toString() const
|
||||
if (t != String)
|
||||
return QString();
|
||||
stringData->ref.ref(); // the constructor below doesn't add a ref.
|
||||
return QString(*(const QConstStringData<1> *)stringData);
|
||||
return QString(*(const QStaticStringData<1> *)stringData);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -57,8 +57,13 @@ class Q_CORE_EXPORT QMetaMethod
|
||||
public:
|
||||
inline QMetaMethod() : mobj(0),handle(0) {}
|
||||
|
||||
const char *signature() const;
|
||||
QByteArray methodSignature() const;
|
||||
QByteArray name() const;
|
||||
const char *typeName() const;
|
||||
int returnType() const;
|
||||
int parameterCount() const;
|
||||
int parameterType(int index) const;
|
||||
void getParameterTypes(int *types) const;
|
||||
QList<QByteArray> parameterTypes() const;
|
||||
QList<QByteArray> parameterNames() const;
|
||||
const char *tag() const;
|
||||
@ -137,8 +142,16 @@ public:
|
||||
inline bool isValid() const { return mobj != 0; }
|
||||
|
||||
private:
|
||||
#if QT_DEPRECATED_SINCE(5,0)
|
||||
// signature() has been renamed to methodSignature() in Qt 5.
|
||||
// Warning, that function returns a QByteArray; check the life time if
|
||||
// you convert to char*.
|
||||
char *signature(struct renamedInQt5_warning_checkTheLifeTime * = 0) Q_DECL_EQ_DELETE;
|
||||
#endif
|
||||
|
||||
const QMetaObject *mobj;
|
||||
uint handle;
|
||||
friend class QMetaMethodPrivate;
|
||||
friend struct QMetaObject;
|
||||
friend struct QMetaObjectPrivate;
|
||||
friend class QObject;
|
||||
|
@ -105,11 +105,64 @@ enum MetaObjectFlags {
|
||||
RequiresVariantMetaObject = 0x02
|
||||
};
|
||||
|
||||
enum MetaDataFlags {
|
||||
IsUnresolvedType = 0x80000000,
|
||||
TypeNameIndexMask = 0x7FFFFFFF
|
||||
};
|
||||
|
||||
class QArgumentType
|
||||
{
|
||||
public:
|
||||
QArgumentType(int type)
|
||||
: _type(type)
|
||||
{}
|
||||
QArgumentType(const QByteArray &name)
|
||||
: _type(QMetaType::type(name.constData())), _name(name)
|
||||
{}
|
||||
QArgumentType()
|
||||
: _type(0)
|
||||
{}
|
||||
int type() const
|
||||
{ return _type; }
|
||||
QByteArray name() const
|
||||
{
|
||||
if (_type && _name.isEmpty())
|
||||
const_cast<QArgumentType *>(this)->_name = QMetaType::typeName(_type);
|
||||
return _name;
|
||||
}
|
||||
bool operator==(const QArgumentType &other) const
|
||||
{
|
||||
if (_type)
|
||||
return _type == other._type;
|
||||
else if (other._type)
|
||||
return false;
|
||||
else
|
||||
return _name == other._name;
|
||||
}
|
||||
bool operator!=(const QArgumentType &other) const
|
||||
{
|
||||
if (_type)
|
||||
return _type != other._type;
|
||||
else if (other._type)
|
||||
return true;
|
||||
else
|
||||
return _name != other._name;
|
||||
}
|
||||
|
||||
private:
|
||||
int _type;
|
||||
QByteArray _name;
|
||||
};
|
||||
|
||||
template <class T, int> class QVarLengthArray;
|
||||
typedef QVarLengthArray<QArgumentType, 10> QArgumentTypeArray;
|
||||
|
||||
class QMetaMethodPrivate;
|
||||
class QMutex;
|
||||
|
||||
struct QMetaObjectPrivate
|
||||
{
|
||||
enum { OutputRevision = 6 }; // Used by moc and qmetaobjectbuilder
|
||||
enum { OutputRevision = 7 }; // Used by moc, qmetaobjectbuilder and qdbus
|
||||
|
||||
int revision;
|
||||
int className;
|
||||
@ -122,6 +175,7 @@ struct QMetaObjectPrivate
|
||||
int signalCount; //since revision 4
|
||||
// revision 5 introduces changes in normalized signatures, no new members
|
||||
// revision 6 added qt_static_metacall as a member of each Q_OBJECT and inside QMetaObject itself
|
||||
// revision 7 is Qt 5
|
||||
|
||||
static inline const QMetaObjectPrivate *get(const QMetaObject *metaobject)
|
||||
{ return reinterpret_cast<const QMetaObjectPrivate*>(metaobject->d.data); }
|
||||
@ -134,6 +188,27 @@ struct QMetaObjectPrivate
|
||||
bool normalizeStringData);
|
||||
static int originalClone(const QMetaObject *obj, int local_method_index);
|
||||
|
||||
static QByteArray decodeMethodSignature(const char *signature,
|
||||
QArgumentTypeArray &types);
|
||||
static int indexOfSignalRelative(const QMetaObject **baseObject,
|
||||
const QByteArray &name, int argc,
|
||||
const QArgumentType *types);
|
||||
static int indexOfSlotRelative(const QMetaObject **m,
|
||||
const QByteArray &name, int argc,
|
||||
const QArgumentType *types);
|
||||
static int indexOfSignal(const QMetaObject *m, const QByteArray &name,
|
||||
int argc, const QArgumentType *types);
|
||||
static int indexOfSlot(const QMetaObject *m, const QByteArray &name,
|
||||
int argc, const QArgumentType *types);
|
||||
static int indexOfMethod(const QMetaObject *m, const QByteArray &name,
|
||||
int argc, const QArgumentType *types);
|
||||
static int indexOfConstructor(const QMetaObject *m, const QByteArray &name,
|
||||
int argc, const QArgumentType *types);
|
||||
static bool checkConnectArgs(int signalArgc, const QArgumentType *signalTypes,
|
||||
int methodArgc, const QArgumentType *methodTypes);
|
||||
static bool checkConnectArgs(const QMetaMethodPrivate *signal,
|
||||
const QMetaMethodPrivate *method);
|
||||
|
||||
static QList<QByteArray> parameterTypeNamesFromSignature(const char *signature);
|
||||
|
||||
#ifndef QT_NO_QOBJECT
|
||||
|
@ -78,26 +78,17 @@ QT_BEGIN_NAMESPACE
|
||||
*/
|
||||
|
||||
// copied from moc's generator.cpp
|
||||
uint qvariant_nameToType(const char* name)
|
||||
bool isBuiltinType(const QByteArray &type)
|
||||
{
|
||||
if (!name)
|
||||
return 0;
|
||||
|
||||
uint tp = QMetaType::type(name);
|
||||
return tp < QMetaType::User ? tp : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns true if the type is a QVariant types.
|
||||
*/
|
||||
bool isVariantType(const char* type)
|
||||
{
|
||||
return qvariant_nameToType(type) != 0;
|
||||
int id = QMetaType::type(type);
|
||||
if (!id && !type.isEmpty() && type != "void")
|
||||
return false;
|
||||
return (id < QMetaType::User);
|
||||
}
|
||||
|
||||
// copied from qmetaobject.cpp
|
||||
static inline const QMetaObjectPrivate *priv(const uint* data)
|
||||
{ return reinterpret_cast<const QMetaObjectPrivate*>(data); }
|
||||
// end of copied lines from qmetaobject.cpp
|
||||
|
||||
class QMetaMethodBuilderPrivate
|
||||
{
|
||||
@ -136,6 +127,21 @@ public:
|
||||
{
|
||||
attributes = ((attributes & ~AccessMask) | (int)value);
|
||||
}
|
||||
|
||||
QList<QByteArray> parameterTypes() const
|
||||
{
|
||||
return QMetaObjectPrivate::parameterTypeNamesFromSignature(signature);
|
||||
}
|
||||
|
||||
int parameterCount() const
|
||||
{
|
||||
return parameterTypes().size();
|
||||
}
|
||||
|
||||
QByteArray name() const
|
||||
{
|
||||
return signature.left(qMax(signature.indexOf('('), 0));
|
||||
}
|
||||
};
|
||||
|
||||
class QMetaPropertyBuilderPrivate
|
||||
@ -458,13 +464,13 @@ QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QMetaMethod& prototype)
|
||||
{
|
||||
QMetaMethodBuilder method;
|
||||
if (prototype.methodType() == QMetaMethod::Method)
|
||||
method = addMethod(prototype.signature());
|
||||
method = addMethod(prototype.methodSignature());
|
||||
else if (prototype.methodType() == QMetaMethod::Signal)
|
||||
method = addSignal(prototype.signature());
|
||||
method = addSignal(prototype.methodSignature());
|
||||
else if (prototype.methodType() == QMetaMethod::Slot)
|
||||
method = addSlot(prototype.signature());
|
||||
method = addSlot(prototype.methodSignature());
|
||||
else if (prototype.methodType() == QMetaMethod::Constructor)
|
||||
method = addConstructor(prototype.signature());
|
||||
method = addConstructor(prototype.methodSignature());
|
||||
method.setReturnType(prototype.typeName());
|
||||
method.setParameterNames(prototype.parameterNames());
|
||||
method.setTag(prototype.tag());
|
||||
@ -535,7 +541,7 @@ QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QByteArray& signatur
|
||||
QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QMetaMethod& prototype)
|
||||
{
|
||||
Q_ASSERT(prototype.methodType() == QMetaMethod::Constructor);
|
||||
QMetaMethodBuilder ctor = addConstructor(prototype.signature());
|
||||
QMetaMethodBuilder ctor = addConstructor(prototype.methodSignature());
|
||||
ctor.setReturnType(prototype.typeName());
|
||||
ctor.setParameterNames(prototype.parameterNames());
|
||||
ctor.setTag(prototype.tag());
|
||||
@ -588,7 +594,7 @@ QMetaPropertyBuilder QMetaObjectBuilder::addProperty(const QMetaProperty& protot
|
||||
if (prototype.hasNotifySignal()) {
|
||||
// Find an existing method for the notify signal, or add a new one.
|
||||
QMetaMethod method = prototype.notifySignal();
|
||||
int index = indexOfMethod(method.signature());
|
||||
int index = indexOfMethod(method.methodSignature());
|
||||
if (index == -1)
|
||||
index = addMethod(method).index();
|
||||
d->properties[property._index].notifySignal = index;
|
||||
@ -1070,75 +1076,82 @@ int QMetaObjectBuilder::indexOfClassInfo(const QByteArray& name)
|
||||
#define ALIGN(size,type) \
|
||||
(size) = ((size) + sizeof(type) - 1) & ~(sizeof(type) - 1)
|
||||
|
||||
class MetaStringTable
|
||||
/*!
|
||||
\class QMetaStringTable
|
||||
\internal
|
||||
\brief The QMetaStringTable class can generate a meta-object string table at runtime.
|
||||
*/
|
||||
|
||||
QMetaStringTable::QMetaStringTable()
|
||||
: m_index(0) {}
|
||||
|
||||
// Enters the given value into the string table (if it hasn't already been
|
||||
// entered). Returns the index of the string.
|
||||
int QMetaStringTable::enter(const QByteArray &value)
|
||||
{
|
||||
public:
|
||||
typedef QHash<QByteArray, int> Entries; // string --> offset mapping
|
||||
typedef Entries::const_iterator const_iterator;
|
||||
Entries::const_iterator constBegin() const
|
||||
{ return m_entries.constBegin(); }
|
||||
Entries::const_iterator constEnd() const
|
||||
{ return m_entries.constEnd(); }
|
||||
|
||||
MetaStringTable() : m_offset(0) {}
|
||||
|
||||
int enter(const QByteArray &value)
|
||||
{
|
||||
Entries::iterator it = m_entries.find(value);
|
||||
if (it != m_entries.end())
|
||||
return it.value();
|
||||
int pos = m_offset;
|
||||
int pos = m_index;
|
||||
m_entries.insert(value, pos);
|
||||
m_offset += value.size() + 1;
|
||||
++m_index;
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
|
||||
int arraySize() const { return m_offset; }
|
||||
|
||||
private:
|
||||
Entries m_entries;
|
||||
int m_offset;
|
||||
};
|
||||
|
||||
// Build the parameter array string for a method.
|
||||
static QByteArray buildParameterNames
|
||||
(const QByteArray& signature, const QList<QByteArray>& parameterNames)
|
||||
int QMetaStringTable::preferredAlignment()
|
||||
{
|
||||
// If the parameter name list is specified, then concatenate them.
|
||||
if (!parameterNames.isEmpty()) {
|
||||
QByteArray names;
|
||||
bool first = true;
|
||||
foreach (const QByteArray &name, parameterNames) {
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
names += (char)',';
|
||||
names += name;
|
||||
}
|
||||
return names;
|
||||
}
|
||||
#ifdef Q_ALIGNOF
|
||||
return Q_ALIGNOF(QByteArrayData);
|
||||
#else
|
||||
return sizeof(void *);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Count commas in the signature, excluding those inside template arguments.
|
||||
int index = signature.indexOf('(');
|
||||
if (index < 0)
|
||||
return QByteArray();
|
||||
++index;
|
||||
if (index >= signature.size())
|
||||
return QByteArray();
|
||||
if (signature[index] == ')')
|
||||
return QByteArray();
|
||||
int count = 1;
|
||||
int brackets = 0;
|
||||
while (index < signature.size() && signature[index] != ',') {
|
||||
char ch = signature[index++];
|
||||
if (ch == '<')
|
||||
++brackets;
|
||||
else if (ch == '>')
|
||||
--brackets;
|
||||
else if (ch == ',' && brackets <= 0)
|
||||
++count;
|
||||
// Returns the size (in bytes) required for serializing this string table.
|
||||
int QMetaStringTable::blobSize() const
|
||||
{
|
||||
int size = m_entries.size() * sizeof(QByteArrayData);
|
||||
Entries::const_iterator it;
|
||||
for (it = m_entries.constBegin(); it != m_entries.constEnd(); ++it)
|
||||
size += it.key().size() + 1;
|
||||
return size;
|
||||
}
|
||||
|
||||
// Writes strings to string data struct.
|
||||
// The struct consists of an array of QByteArrayData, followed by a char array
|
||||
// containing the actual strings. This format must match the one produced by
|
||||
// moc (see generator.cpp).
|
||||
void QMetaStringTable::writeBlob(char *out)
|
||||
{
|
||||
Q_ASSERT(!(reinterpret_cast<quintptr>(out) & (preferredAlignment()-1)));
|
||||
|
||||
int offsetOfStringdataMember = m_entries.size() * sizeof(QByteArrayData);
|
||||
int stringdataOffset = 0;
|
||||
for (int i = 0; i < m_entries.size(); ++i) {
|
||||
const QByteArray &str = m_entries.key(i);
|
||||
int size = str.size();
|
||||
qptrdiff offset = offsetOfStringdataMember + stringdataOffset
|
||||
- i * sizeof(QByteArrayData);
|
||||
const QByteArrayData data = { Q_REFCOUNT_INITIALIZE_STATIC, size, 0, 0, offset };
|
||||
|
||||
memcpy(out + i * sizeof(QByteArrayData), &data, sizeof(QByteArrayData));
|
||||
|
||||
memcpy(out + offsetOfStringdataMember + stringdataOffset, str.constData(), size);
|
||||
out[offsetOfStringdataMember + stringdataOffset + size] = '\0';
|
||||
|
||||
stringdataOffset += size + 1;
|
||||
}
|
||||
return QByteArray(count - 1, ',');
|
||||
}
|
||||
|
||||
// Returns the sum of all parameters (including return type) for the given
|
||||
// \a methods. This is needed for calculating the size of the methods'
|
||||
// parameter type/name meta-data.
|
||||
static int aggregateParameterCount(const QList<QMetaMethodBuilderPrivate> &methods)
|
||||
{
|
||||
int sum = 0;
|
||||
for (int i = 0; i < methods.size(); ++i)
|
||||
sum += methods.at(i).parameterCount() + 1; // +1 for return type
|
||||
return sum;
|
||||
}
|
||||
|
||||
// Build a QMetaObject in "buf" based on the information in "d".
|
||||
@ -1151,6 +1164,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
|
||||
Q_UNUSED(expectedSize); // Avoid warning in release mode
|
||||
int size = 0;
|
||||
int dataIndex;
|
||||
int paramsIndex;
|
||||
int enumIndex;
|
||||
int index;
|
||||
bool hasRevisionedMethods = d->hasRevisionedMethods();
|
||||
@ -1181,8 +1195,13 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
|
||||
break;
|
||||
}
|
||||
}
|
||||
int methodParametersDataSize =
|
||||
((aggregateParameterCount(d->methods)
|
||||
+ aggregateParameterCount(d->constructors)) * 2) // types and parameter names
|
||||
- d->methods.size() // return "parameters" don't have names
|
||||
- d->constructors.size(); // "this" parameters don't have names
|
||||
if (buf) {
|
||||
Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 6, "QMetaObjectBuilder should generate the same version as moc");
|
||||
Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 7, "QMetaObjectBuilder should generate the same version as moc");
|
||||
pmeta->revision = QMetaObjectPrivate::OutputRevision;
|
||||
pmeta->flags = d->flags;
|
||||
pmeta->className = 0; // Class name is always the first string.
|
||||
@ -1197,6 +1216,8 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
|
||||
dataIndex += 5 * d->methods.size();
|
||||
if (hasRevisionedMethods)
|
||||
dataIndex += d->methods.size();
|
||||
paramsIndex = dataIndex;
|
||||
dataIndex += methodParametersDataSize;
|
||||
|
||||
pmeta->propertyCount = d->properties.size();
|
||||
pmeta->propertyData = dataIndex;
|
||||
@ -1218,6 +1239,8 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
|
||||
dataIndex += 5 * d->methods.size();
|
||||
if (hasRevisionedMethods)
|
||||
dataIndex += d->methods.size();
|
||||
paramsIndex = dataIndex;
|
||||
dataIndex += methodParametersDataSize;
|
||||
dataIndex += 3 * d->properties.size();
|
||||
if (hasNotifySignals)
|
||||
dataIndex += d->properties.size();
|
||||
@ -1240,13 +1263,14 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
|
||||
// Find the start of the data and string tables.
|
||||
int *data = reinterpret_cast<int *>(pmeta);
|
||||
size += dataIndex * sizeof(int);
|
||||
ALIGN(size, void *);
|
||||
char *str = reinterpret_cast<char *>(buf + size);
|
||||
if (buf) {
|
||||
if (relocatable) {
|
||||
meta->d.stringdata = reinterpret_cast<const char *>((quintptr)size);
|
||||
meta->d.stringdata = reinterpret_cast<const QByteArrayData *>((quintptr)size);
|
||||
meta->d.data = reinterpret_cast<uint *>((quintptr)pmetaSize);
|
||||
} else {
|
||||
meta->d.stringdata = str;
|
||||
meta->d.stringdata = reinterpret_cast<const QByteArrayData *>(str);
|
||||
meta->d.data = reinterpret_cast<uint *>(data);
|
||||
}
|
||||
}
|
||||
@ -1254,7 +1278,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
|
||||
// Reset the current data position to just past the QMetaObjectPrivate.
|
||||
dataIndex = MetaObjectPrivateFieldCount;
|
||||
|
||||
MetaStringTable strings;
|
||||
QMetaStringTable strings;
|
||||
strings.enter(d->className);
|
||||
|
||||
// Output the class infos,
|
||||
@ -1273,24 +1297,21 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
|
||||
Q_ASSERT(!buf || dataIndex == pmeta->methodData);
|
||||
for (index = 0; index < d->methods.size(); ++index) {
|
||||
QMetaMethodBuilderPrivate *method = &(d->methods[index]);
|
||||
int sig = strings.enter(method->signature);
|
||||
int params;
|
||||
QByteArray names = buildParameterNames
|
||||
(method->signature, method->parameterNames);
|
||||
params = strings.enter(names);
|
||||
int ret = strings.enter(method->returnType);
|
||||
int name = strings.enter(method->name());
|
||||
int argc = method->parameterCount();
|
||||
int tag = strings.enter(method->tag);
|
||||
int attrs = method->attributes;
|
||||
if (buf) {
|
||||
data[dataIndex] = sig;
|
||||
data[dataIndex + 1] = params;
|
||||
data[dataIndex + 2] = ret;
|
||||
data[dataIndex] = name;
|
||||
data[dataIndex + 1] = argc;
|
||||
data[dataIndex + 2] = paramsIndex;
|
||||
data[dataIndex + 3] = tag;
|
||||
data[dataIndex + 4] = attrs;
|
||||
if (method->methodType() == QMetaMethod::Signal)
|
||||
pmeta->signalCount++;
|
||||
}
|
||||
dataIndex += 5;
|
||||
paramsIndex += 1 + argc * 2;
|
||||
}
|
||||
if (hasRevisionedMethods) {
|
||||
for (index = 0; index < d->methods.size(); ++index) {
|
||||
@ -1301,23 +1322,59 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
|
||||
}
|
||||
}
|
||||
|
||||
// Output the method parameters in the class.
|
||||
Q_ASSERT(!buf || dataIndex == pmeta->methodData + d->methods.size() * 5
|
||||
+ (hasRevisionedMethods ? d->methods.size() : 0));
|
||||
for (int x = 0; x < 2; ++x) {
|
||||
QList<QMetaMethodBuilderPrivate> &methods = (x == 0) ? d->methods : d->constructors;
|
||||
for (index = 0; index < methods.size(); ++index) {
|
||||
QMetaMethodBuilderPrivate *method = &(methods[index]);
|
||||
QList<QByteArray> paramTypeNames = method->parameterTypes();
|
||||
int paramCount = paramTypeNames.size();
|
||||
for (int i = -1; i < paramCount; ++i) {
|
||||
const QByteArray &typeName = (i < 0) ? method->returnType : paramTypeNames.at(i);
|
||||
int typeInfo;
|
||||
if (isBuiltinType(typeName))
|
||||
typeInfo = QMetaType::type(typeName);
|
||||
else
|
||||
typeInfo = IsUnresolvedType | strings.enter(typeName);
|
||||
if (buf)
|
||||
data[dataIndex] = typeInfo;
|
||||
++dataIndex;
|
||||
}
|
||||
|
||||
QList<QByteArray> paramNames = method->parameterNames;
|
||||
while (paramNames.size() < paramCount)
|
||||
paramNames.append(QByteArray());
|
||||
for (int i = 0; i < paramCount; ++i) {
|
||||
int stringIndex = strings.enter(paramNames.at(i));
|
||||
if (buf)
|
||||
data[dataIndex] = stringIndex;
|
||||
++dataIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Output the properties in the class.
|
||||
Q_ASSERT(!buf || dataIndex == pmeta->propertyData);
|
||||
for (index = 0; index < d->properties.size(); ++index) {
|
||||
QMetaPropertyBuilderPrivate *prop = &(d->properties[index]);
|
||||
int name = strings.enter(prop->name);
|
||||
int type = strings.enter(prop->type);
|
||||
|
||||
int typeInfo;
|
||||
if (isBuiltinType(prop->type))
|
||||
typeInfo = QMetaType::type(prop->type);
|
||||
else
|
||||
typeInfo = IsUnresolvedType | strings.enter(prop->type);
|
||||
|
||||
int flags = prop->flags;
|
||||
|
||||
if (!isVariantType(prop->type)) {
|
||||
if (!isBuiltinType(prop->type))
|
||||
flags |= EnumOrFlag;
|
||||
} else {
|
||||
flags |= qvariant_nameToType(prop->type) << 24;
|
||||
}
|
||||
|
||||
if (buf) {
|
||||
data[dataIndex] = name;
|
||||
data[dataIndex + 1] = type;
|
||||
data[dataIndex + 1] = typeInfo;
|
||||
data[dataIndex + 2] = flags;
|
||||
}
|
||||
dataIndex += 3;
|
||||
@ -1372,34 +1429,25 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
|
||||
Q_ASSERT(!buf || dataIndex == pmeta->constructorData);
|
||||
for (index = 0; index < d->constructors.size(); ++index) {
|
||||
QMetaMethodBuilderPrivate *method = &(d->constructors[index]);
|
||||
int sig = strings.enter(method->signature);
|
||||
int params;
|
||||
QByteArray names = buildParameterNames
|
||||
(method->signature, method->parameterNames);
|
||||
params = strings.enter(names);
|
||||
int ret = strings.enter(method->returnType);
|
||||
int name = strings.enter(method->name());
|
||||
int argc = method->parameterCount();
|
||||
int tag = strings.enter(method->tag);
|
||||
int attrs = method->attributes;
|
||||
if (buf) {
|
||||
data[dataIndex] = sig;
|
||||
data[dataIndex + 1] = params;
|
||||
data[dataIndex + 2] = ret;
|
||||
data[dataIndex] = name;
|
||||
data[dataIndex + 1] = argc;
|
||||
data[dataIndex + 2] = paramsIndex;
|
||||
data[dataIndex + 3] = tag;
|
||||
data[dataIndex + 4] = attrs;
|
||||
}
|
||||
dataIndex += 5;
|
||||
paramsIndex += 1 + argc * 2;
|
||||
}
|
||||
|
||||
size += strings.arraySize();
|
||||
size += strings.blobSize();
|
||||
|
||||
if (buf) {
|
||||
// Write strings to string data array.
|
||||
MetaStringTable::const_iterator it;
|
||||
for (it = strings.constBegin(); it != strings.constEnd(); ++it) {
|
||||
memcpy(str + it.value(), it.key().constData(), it.key().size());
|
||||
str[it.value() + it.key().size()] = '\0';
|
||||
}
|
||||
}
|
||||
if (buf)
|
||||
strings.writeBlob(str);
|
||||
|
||||
// Output the zero terminator in the data array.
|
||||
if (buf)
|
||||
@ -1508,7 +1556,7 @@ void QMetaObjectBuilder::fromRelocatableData(QMetaObject *output,
|
||||
quintptr dataOffset = (quintptr)dataMo->d.data;
|
||||
|
||||
output->d.superdata = superclass;
|
||||
output->d.stringdata = buf + stringdataOffset;
|
||||
output->d.stringdata = reinterpret_cast<const QByteArrayData *>(buf + stringdataOffset);
|
||||
output->d.data = reinterpret_cast<const uint *>(buf + dataOffset);
|
||||
output->d.extradata = 0;
|
||||
}
|
||||
@ -1896,7 +1944,7 @@ QByteArray QMetaMethodBuilder::returnType() const
|
||||
is empty, then the method's return type is \c{void}. The \a value
|
||||
will be normalized before it is added to the method.
|
||||
|
||||
\sa returnType(), signature()
|
||||
\sa returnType(), parameterTypes(), signature()
|
||||
*/
|
||||
void QMetaMethodBuilder::setReturnType(const QByteArray& value)
|
||||
{
|
||||
@ -1905,6 +1953,20 @@ void QMetaMethodBuilder::setReturnType(const QByteArray& value)
|
||||
d->returnType = QMetaObject::normalizedType(value);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the list of parameter types for this method.
|
||||
|
||||
\sa returnType(), parameterNames()
|
||||
*/
|
||||
QList<QByteArray> QMetaMethodBuilder::parameterTypes() const
|
||||
{
|
||||
QMetaMethodBuilderPrivate *d = d_func();
|
||||
if (d)
|
||||
return d->parameterTypes();
|
||||
else
|
||||
return QList<QByteArray>();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the list of parameter names for this method.
|
||||
|
||||
|
@ -56,6 +56,7 @@
|
||||
#include <QtCore/qobject.h>
|
||||
#include <QtCore/qmetaobject.h>
|
||||
#include <QtCore/qdatastream.h>
|
||||
#include <QtCore/qhash.h>
|
||||
#include <QtCore/qmap.h>
|
||||
|
||||
|
||||
@ -203,6 +204,7 @@ public:
|
||||
QByteArray returnType() const;
|
||||
void setReturnType(const QByteArray& value);
|
||||
|
||||
QList<QByteArray> parameterTypes() const;
|
||||
QList<QByteArray> parameterNames() const;
|
||||
void setParameterNames(const QList<QByteArray>& value);
|
||||
|
||||
@ -318,6 +320,23 @@ private:
|
||||
QMetaEnumBuilderPrivate *d_func() const;
|
||||
};
|
||||
|
||||
class Q_CORE_EXPORT QMetaStringTable
|
||||
{
|
||||
public:
|
||||
QMetaStringTable();
|
||||
|
||||
int enter(const QByteArray &value);
|
||||
|
||||
static int preferredAlignment();
|
||||
int blobSize() const;
|
||||
void writeBlob(char *out);
|
||||
|
||||
private:
|
||||
typedef QHash<QByteArray, int> Entries; // string --> index mapping
|
||||
Entries m_entries;
|
||||
int m_index;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaObjectBuilder::AddMembers)
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaObjectBuilder::MetaObjectFlags)
|
||||
|
||||
|
@ -242,6 +242,7 @@ template<> struct TypeDefinition<QRegExp> { static const bool IsAvailable = fals
|
||||
\value QEasingCurve QEasingCurve
|
||||
|
||||
\value User Base value for user types
|
||||
\value UnknownType This is an invalid type id. It is returned from QMetaType for types that are not registered
|
||||
|
||||
\omitvalue FirstGuiType
|
||||
\omitvalue FirstWidgetsType
|
||||
@ -311,7 +312,7 @@ static const struct { const char * typeName; int typeNameLength; int type; } typ
|
||||
QT_FOR_EACH_STATIC_TYPE(QT_ADD_STATIC_METATYPE)
|
||||
QT_FOR_EACH_STATIC_ALIAS_TYPE(QT_ADD_STATIC_METATYPE_ALIASES_ITER)
|
||||
QT_FOR_EACH_STATIC_HACKS_TYPE(QT_ADD_STATIC_METATYPE_HACKS_ITER)
|
||||
{0, 0, QMetaType::Void}
|
||||
{0, 0, QMetaType::UnknownType}
|
||||
};
|
||||
|
||||
Q_CORE_EXPORT const QMetaTypeInterface *qMetaTypeGuiHelper = 0;
|
||||
@ -348,10 +349,7 @@ Q_GLOBAL_STATIC(QReadWriteLock, customTypesLock)
|
||||
void QMetaType::registerStreamOperators(const char *typeName, SaveOperator saveOp,
|
||||
LoadOperator loadOp)
|
||||
{
|
||||
int idx = type(typeName);
|
||||
if (!idx)
|
||||
return;
|
||||
registerStreamOperators(idx, saveOp, loadOp);
|
||||
registerStreamOperators(type(typeName), saveOp, loadOp);
|
||||
}
|
||||
|
||||
/*! \internal
|
||||
@ -434,7 +432,7 @@ static int qMetaTypeCustomType_unlocked(const char *typeName, int length)
|
||||
{
|
||||
const QVector<QCustomTypeInfo> * const ct = customTypes();
|
||||
if (!ct)
|
||||
return 0;
|
||||
return QMetaType::UnknownType;
|
||||
|
||||
for (int v = 0; v < ct->count(); ++v) {
|
||||
const QCustomTypeInfo &customInfo = ct->at(v);
|
||||
@ -445,7 +443,7 @@ static int qMetaTypeCustomType_unlocked(const char *typeName, int length)
|
||||
return v + QMetaType::User;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return QMetaType::UnknownType;
|
||||
}
|
||||
|
||||
/*! \internal
|
||||
@ -488,11 +486,11 @@ int QMetaType::registerType(const char *typeName, Deleter deleter,
|
||||
|
||||
int previousSize = 0;
|
||||
int previousFlags = 0;
|
||||
if (!idx) {
|
||||
if (idx == UnknownType) {
|
||||
QWriteLocker locker(customTypesLock());
|
||||
idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
|
||||
normalizedTypeName.size());
|
||||
if (!idx) {
|
||||
if (idx == UnknownType) {
|
||||
QCustomTypeInfo inf;
|
||||
inf.typeName = normalizedTypeName;
|
||||
inf.creator = creator;
|
||||
@ -558,12 +556,12 @@ int QMetaType::registerTypedef(const char* typeName, int aliasId)
|
||||
int idx = qMetaTypeStaticType(normalizedTypeName.constData(),
|
||||
normalizedTypeName.size());
|
||||
|
||||
if (!idx) {
|
||||
if (idx == UnknownType) {
|
||||
QWriteLocker locker(customTypesLock());
|
||||
idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
|
||||
normalizedTypeName.size());
|
||||
|
||||
if (!idx) {
|
||||
if (idx == UnknownType) {
|
||||
QCustomTypeInfo inf;
|
||||
inf.typeName = normalizedTypeName;
|
||||
inf.alias = aliasId;
|
||||
@ -592,17 +590,20 @@ int QMetaType::registerTypedef(const char* typeName, int aliasId)
|
||||
*/
|
||||
bool QMetaType::isRegistered(int type)
|
||||
{
|
||||
if (type >= 0 && type < User) {
|
||||
// predefined type
|
||||
if ((type >= FirstCoreType && type <= LastCoreType)
|
||||
|| (type >= FirstGuiType && type <= LastGuiType)
|
||||
|| (type >= FirstWidgetsType && type <= LastWidgetsType)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
QReadLocker locker(customTypesLock());
|
||||
const QVector<QCustomTypeInfo> * const ct = customTypes();
|
||||
return ((type >= User) && (ct && ct->count() > type - User) && !ct->at(type - User).typeName.isEmpty());
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a handle to the type called \a typeName, or 0 if there is
|
||||
Returns a handle to the type called \a typeName, or QMetaType::UnknownType if there is
|
||||
no such type.
|
||||
|
||||
\sa isRegistered(), typeName(), Type
|
||||
@ -611,17 +612,17 @@ int QMetaType::type(const char *typeName)
|
||||
{
|
||||
int length = qstrlen(typeName);
|
||||
if (!length)
|
||||
return 0;
|
||||
return UnknownType;
|
||||
int type = qMetaTypeStaticType(typeName, length);
|
||||
if (!type) {
|
||||
if (type == UnknownType) {
|
||||
QReadLocker locker(customTypesLock());
|
||||
type = qMetaTypeCustomType_unlocked(typeName, length);
|
||||
#ifndef QT_NO_QOBJECT
|
||||
if (!type) {
|
||||
if (type == UnknownType) {
|
||||
const NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
|
||||
type = qMetaTypeStaticType(normalizedTypeName.constData(),
|
||||
normalizedTypeName.size());
|
||||
if (!type) {
|
||||
if (type == UnknownType) {
|
||||
type = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
|
||||
normalizedTypeName.size());
|
||||
}
|
||||
@ -652,6 +653,7 @@ bool QMetaType::save(QDataStream &stream, int type, const void *data)
|
||||
return false;
|
||||
|
||||
switch(type) {
|
||||
case QMetaType::UnknownType:
|
||||
case QMetaType::Void:
|
||||
case QMetaType::VoidStar:
|
||||
case QMetaType::QObjectStar:
|
||||
@ -857,6 +859,7 @@ bool QMetaType::load(QDataStream &stream, int type, void *data)
|
||||
return false;
|
||||
|
||||
switch(type) {
|
||||
case QMetaType::UnknownType:
|
||||
case QMetaType::Void:
|
||||
case QMetaType::VoidStar:
|
||||
case QMetaType::QObjectStar:
|
||||
@ -1154,6 +1157,7 @@ void *QMetaType::create(int type, const void *copy)
|
||||
case QMetaType::QModelIndex:
|
||||
return new NS(QModelIndex)(*static_cast<const NS(QModelIndex)*>(copy));
|
||||
#endif
|
||||
case QMetaType::UnknownType:
|
||||
case QMetaType::Void:
|
||||
return 0;
|
||||
default:
|
||||
@ -1257,6 +1261,7 @@ void *QMetaType::create(int type, const void *copy)
|
||||
case QMetaType::QModelIndex:
|
||||
return new NS(QModelIndex);
|
||||
#endif
|
||||
case QMetaType::UnknownType:
|
||||
case QMetaType::Void:
|
||||
return 0;
|
||||
default:
|
||||
@ -1318,6 +1323,7 @@ public:
|
||||
template<typename T>
|
||||
void delegate(const T *where) { DestroyerImpl<T>::Destroy(m_type, const_cast<T*>(where)); }
|
||||
void delegate(const void *) {}
|
||||
void delegate(const QMetaTypeSwitcher::UnknownType*) {}
|
||||
void delegate(const QMetaTypeSwitcher::NotBuiltinType *where) { customTypeDestroyer(m_type, (void*)where); }
|
||||
|
||||
private:
|
||||
@ -1381,6 +1387,7 @@ public:
|
||||
template<typename T>
|
||||
void *delegate(const T *copy) { return ConstructorImpl<T>::Construct(m_type, m_where, copy); }
|
||||
void *delegate(const void *) { return m_where; }
|
||||
void *delegate(const QMetaTypeSwitcher::UnknownType*) { return m_where; }
|
||||
void *delegate(const QMetaTypeSwitcher::NotBuiltinType *copy) { return customTypeConstructor(m_type, m_where, copy); }
|
||||
|
||||
private:
|
||||
@ -1470,6 +1477,7 @@ public:
|
||||
template<typename T>
|
||||
void delegate(const T *where) { DestructorImpl<T>::Destruct(m_type, const_cast<T*>(where)); }
|
||||
void delegate(const void *) {}
|
||||
void delegate(const QMetaTypeSwitcher::UnknownType*) {}
|
||||
void delegate(const QMetaTypeSwitcher::NotBuiltinType *where) { customTypeDestructor(m_type, (void*)where); }
|
||||
|
||||
private:
|
||||
@ -1539,6 +1547,7 @@ public:
|
||||
|
||||
template<typename T>
|
||||
int delegate(const T*) { return SizeOfImpl<T>::Size(m_type); }
|
||||
int delegate(const QMetaTypeSwitcher::UnknownType*) { return 0; }
|
||||
int delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return customTypeSizeOf(m_type); }
|
||||
private:
|
||||
static int customTypeSizeOf(const int type)
|
||||
@ -1609,13 +1618,14 @@ public:
|
||||
template<typename T>
|
||||
quint32 delegate(const T*) { return FlagsImpl<T>::Flags(m_type); }
|
||||
quint32 delegate(const void*) { return 0; }
|
||||
quint32 delegate(const QMetaTypeSwitcher::UnknownType*) { return 0; }
|
||||
quint32 delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return customTypeFlags(m_type); }
|
||||
private:
|
||||
const int m_type;
|
||||
static quint32 customTypeFlags(const int type)
|
||||
{
|
||||
const QVector<QCustomTypeInfo> * const ct = customTypes();
|
||||
if (Q_UNLIKELY(!ct))
|
||||
if (Q_UNLIKELY(!ct || type < QMetaType::User))
|
||||
return 0;
|
||||
QReadLocker locker(customTypesLock());
|
||||
if (Q_UNLIKELY(ct->count() <= type - QMetaType::User))
|
||||
@ -1796,6 +1806,7 @@ public:
|
||||
template<typename T>
|
||||
void delegate(const T*) { TypeInfoImpl<T>(m_type, info); }
|
||||
void delegate(const void*) {}
|
||||
void delegate(const QMetaTypeSwitcher::UnknownType*) {}
|
||||
void delegate(const QMetaTypeSwitcher::NotBuiltinType*) { customTypeInfo(m_type); }
|
||||
private:
|
||||
void customTypeInfo(const uint type)
|
||||
@ -1816,7 +1827,7 @@ QMetaType QMetaType::typeInfo(const int type)
|
||||
{
|
||||
TypeInfo typeInfo(type);
|
||||
QMetaTypeSwitcher::switcher<void>(typeInfo, type, 0);
|
||||
return typeInfo.info.creator || !type ? QMetaType(QMetaType::NoExtensionFlags
|
||||
return typeInfo.info.creator || type == Void ? QMetaType(QMetaType::NoExtensionFlags
|
||||
, static_cast<const QMetaTypeInterface *>(0) // typeInfo::info is a temporary variable, we can't return address of it.
|
||||
, typeInfo.info.creator
|
||||
, typeInfo.info.deleter
|
||||
@ -1827,27 +1838,24 @@ QMetaType QMetaType::typeInfo(const int type)
|
||||
, typeInfo.info.size
|
||||
, typeInfo.info.flags
|
||||
, type)
|
||||
: QMetaType(-1);
|
||||
: QMetaType(UnknownType);
|
||||
}
|
||||
|
||||
QMetaType::QMetaType(const int typeId)
|
||||
: m_typeId(typeId)
|
||||
{
|
||||
if (Q_UNLIKELY(typeId == -1)) {
|
||||
if (Q_UNLIKELY(typeId == UnknownType)) {
|
||||
// Constructs invalid QMetaType instance.
|
||||
m_extensionFlags = 0xffffffff;
|
||||
Q_ASSERT(!isValid());
|
||||
} else {
|
||||
// TODO it can be better.
|
||||
*this = QMetaType::typeInfo(typeId);
|
||||
if (m_typeId > 0 && !m_creator) {
|
||||
if (m_typeId == UnknownType)
|
||||
m_extensionFlags = 0xffffffff;
|
||||
m_typeId = -1;
|
||||
}
|
||||
if (m_typeId == QMetaType::Void) {
|
||||
else if (m_typeId == QMetaType::Void)
|
||||
m_extensionFlags = CreateEx | DestroyEx | ConstructEx | DestructEx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QMetaType::QMetaType(const QMetaType &other)
|
||||
|
@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
// F is a tuple: (QMetaType::TypeName, QMetaType::TypeNameID, RealType)
|
||||
#define QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)\
|
||||
F(Void, 0, void) \
|
||||
F(Void, 43, void) \
|
||||
F(Bool, 1, bool) \
|
||||
F(Int, 2, int) \
|
||||
F(UInt, 3, uint) \
|
||||
@ -192,8 +192,8 @@ public:
|
||||
// these are merged with QVariant
|
||||
QT_FOR_EACH_STATIC_TYPE(QT_DEFINE_METATYPE_ID)
|
||||
|
||||
FirstCoreType = Void,
|
||||
LastCoreType = QModelIndex,
|
||||
FirstCoreType = Bool,
|
||||
LastCoreType = Void,
|
||||
FirstGuiType = QFont,
|
||||
LastGuiType = QPolygonF,
|
||||
FirstWidgetsType = QIcon,
|
||||
@ -202,6 +202,7 @@ public:
|
||||
|
||||
QReal = sizeof(qreal) == sizeof(double) ? Double : Float,
|
||||
|
||||
UnknownType = 0,
|
||||
User = 256
|
||||
};
|
||||
|
||||
@ -677,7 +678,7 @@ inline QMetaType::~QMetaType()
|
||||
|
||||
inline bool QMetaType::isValid() const
|
||||
{
|
||||
return m_typeId >= 0;
|
||||
return m_typeId != UnknownType;
|
||||
}
|
||||
|
||||
inline bool QMetaType::isRegistered() const
|
||||
|
@ -59,7 +59,8 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
class QMetaTypeSwitcher {
|
||||
public:
|
||||
class NotBuiltinType;
|
||||
class NotBuiltinType; // type is not a built-in type, but it may be a custom type or an unknown type
|
||||
class UnknownType; // type not known to QMetaType system
|
||||
template<class ReturnType, class DelegateObject>
|
||||
static ReturnType switcher(DelegateObject &logic, int type, const void *data);
|
||||
};
|
||||
@ -74,7 +75,11 @@ ReturnType QMetaTypeSwitcher::switcher(DelegateObject &logic, int type, const vo
|
||||
switch (QMetaType::Type(type)) {
|
||||
QT_FOR_EACH_STATIC_TYPE(QT_METATYPE_SWICHER_CASE)
|
||||
|
||||
case QMetaType::UnknownType:
|
||||
return logic.delegate(static_cast<UnknownType const *>(data));
|
||||
default:
|
||||
if (type < QMetaType::User)
|
||||
return logic.delegate(static_cast<UnknownType const *>(data));
|
||||
return logic.delegate(static_cast<NotBuiltinType const *>(data));
|
||||
}
|
||||
}
|
||||
|
@ -105,6 +105,30 @@ static int *queuedConnectionTypes(const QList<QByteArray> &typeNames)
|
||||
return types;
|
||||
}
|
||||
|
||||
static int *queuedConnectionTypes(const QArgumentType *argumentTypes, int argc)
|
||||
{
|
||||
QScopedArrayPointer<int> types(new int [argc + 1]);
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
const QArgumentType &type = argumentTypes[i];
|
||||
if (type.type())
|
||||
types[i] = type.type();
|
||||
else if (type.name().endsWith('*'))
|
||||
types[i] = QMetaType::VoidStar;
|
||||
else
|
||||
types[i] = QMetaType::type(type.name());
|
||||
|
||||
if (!types[i]) {
|
||||
qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
|
||||
"(Make sure '%s' is registered using qRegisterMetaType().)",
|
||||
type.name().constData(), type.name().constData());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
types[argc] = 0;
|
||||
|
||||
return types.take();
|
||||
}
|
||||
|
||||
static QBasicMutex _q_ObjectMutexPool[131];
|
||||
|
||||
/** \internal
|
||||
@ -2179,12 +2203,12 @@ static inline void check_and_warn_compat(const QMetaObject *sender, const QMetaM
|
||||
if (signal.attributes() & QMetaMethod::Compatibility) {
|
||||
if (!(method.attributes() & QMetaMethod::Compatibility))
|
||||
qWarning("QObject::connect: Connecting from COMPAT signal (%s::%s)",
|
||||
sender->className(), signal.signature());
|
||||
sender->className(), signal.methodSignature().constData());
|
||||
} else if ((method.attributes() & QMetaMethod::Compatibility) &&
|
||||
method.methodType() == QMetaMethod::Signal) {
|
||||
qWarning("QObject::connect: Connecting from %s::%s to COMPAT slot (%s::%s)",
|
||||
sender->className(), signal.signature(),
|
||||
receiver->className(), method.signature());
|
||||
sender->className(), signal.methodSignature().constData(),
|
||||
receiver->className(), method.methodSignature().constData());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2283,7 +2307,26 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const char *sign
|
||||
const QMetaObject *smeta = sender->metaObject();
|
||||
const char *signal_arg = signal;
|
||||
++signal; //skip code
|
||||
int signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
|
||||
QByteArray signalName;
|
||||
QArgumentTypeArray signalTypes;
|
||||
int signal_index;
|
||||
if (QMetaObjectPrivate::get(smeta)->revision >= 7) {
|
||||
signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes);
|
||||
signal_index = QMetaObjectPrivate::indexOfSignalRelative(
|
||||
&smeta, signalName, signalTypes.size(), signalTypes.constData());
|
||||
if (signal_index < 0) {
|
||||
// check for normalized signatures
|
||||
tmp_signal_name = QMetaObject::normalizedSignature(signal - 1);
|
||||
signal = tmp_signal_name.constData() + 1;
|
||||
|
||||
signalTypes.clear();
|
||||
signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes);
|
||||
smeta = sender->metaObject();
|
||||
signal_index = QMetaObjectPrivate::indexOfSignalRelative(
|
||||
&smeta, signalName, signalTypes.size(), signalTypes.constData());
|
||||
}
|
||||
} else {
|
||||
signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
|
||||
if (signal_index < 0) {
|
||||
// check for normalized signatures
|
||||
tmp_signal_name = QMetaObject::normalizedSignature(signal - 1);
|
||||
@ -2291,13 +2334,14 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const char *sign
|
||||
|
||||
smeta = sender->metaObject();
|
||||
signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
|
||||
}
|
||||
if (signal_index < 0) {
|
||||
// re-use tmp_signal_name and signal from above
|
||||
|
||||
smeta = sender->metaObject();
|
||||
signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (signal_index < 0) {
|
||||
err_method_notfound(sender, signal_arg, "connect");
|
||||
err_info_about_objects("connect", sender, receiver);
|
||||
@ -2317,8 +2361,42 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const char *sign
|
||||
const char *method_arg = method;
|
||||
++method; // skip code
|
||||
|
||||
QByteArray methodName;
|
||||
QArgumentTypeArray methodTypes;
|
||||
const QMetaObject *rmeta = receiver->metaObject();
|
||||
int method_index_relative = -1;
|
||||
if (QMetaObjectPrivate::get(rmeta)->revision >= 7) {
|
||||
switch (membcode) {
|
||||
case QSLOT_CODE:
|
||||
method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(
|
||||
&rmeta, methodName, methodTypes.size(), methodTypes.constData());
|
||||
break;
|
||||
case QSIGNAL_CODE:
|
||||
method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(
|
||||
&rmeta, methodName, methodTypes.size(), methodTypes.constData());
|
||||
break;
|
||||
}
|
||||
if (method_index_relative < 0) {
|
||||
// check for normalized methods
|
||||
tmp_method_name = QMetaObject::normalizedSignature(method);
|
||||
method = tmp_method_name.constData();
|
||||
|
||||
methodTypes.clear();
|
||||
methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodTypes);
|
||||
// rmeta may have been modified above
|
||||
rmeta = receiver->metaObject();
|
||||
switch (membcode) {
|
||||
case QSLOT_CODE:
|
||||
method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(
|
||||
&rmeta, methodName, methodTypes.size(), methodTypes.constData());
|
||||
break;
|
||||
case QSIGNAL_CODE:
|
||||
method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(
|
||||
&rmeta, methodName, methodTypes.size(), methodTypes.constData());
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (membcode) {
|
||||
case QSLOT_CODE:
|
||||
method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(&rmeta, method, false);
|
||||
@ -2348,6 +2426,7 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const char *sign
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (method_index_relative < 0) {
|
||||
err_method_notfound(receiver, method_arg, "connect");
|
||||
@ -2355,7 +2434,18 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const char *sign
|
||||
return QMetaObject::Connection(0);
|
||||
}
|
||||
|
||||
if (!QMetaObject::checkConnectArgs(signal, method)) {
|
||||
bool compatibleArgs = true;
|
||||
if ((QMetaObjectPrivate::get(smeta)->revision < 7) && (QMetaObjectPrivate::get(rmeta)->revision < 7)) {
|
||||
compatibleArgs = QMetaObject::checkConnectArgs(signal, method);
|
||||
} else {
|
||||
if (signalName.isEmpty())
|
||||
signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes);
|
||||
if (methodName.isEmpty())
|
||||
methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodTypes);
|
||||
compatibleArgs = QMetaObjectPrivate::checkConnectArgs(signalTypes.size(), signalTypes.constData(),
|
||||
methodTypes.size(), methodTypes.constData());
|
||||
}
|
||||
if (!compatibleArgs) {
|
||||
qWarning("QObject::connect: Incompatible sender/receiver arguments"
|
||||
"\n %s::%s --> %s::%s",
|
||||
sender->metaObject()->className(), signal,
|
||||
@ -2365,8 +2455,11 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const char *sign
|
||||
|
||||
int *types = 0;
|
||||
if ((type == Qt::QueuedConnection)
|
||||
&& !(types = queuedConnectionTypes(smeta->method(signal_absolute_index).parameterTypes())))
|
||||
&& ((QMetaObjectPrivate::get(smeta)->revision >= 7)
|
||||
? !(types = queuedConnectionTypes(signalTypes.constData(), signalTypes.size()))
|
||||
: !(types = queuedConnectionTypes(smeta->method(signal_absolute_index).parameterTypes())))) {
|
||||
return QMetaObject::Connection(0);
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
if (warnCompat) {
|
||||
@ -2424,17 +2517,17 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMetho
|
||||
|| method.methodType() == QMetaMethod::Constructor) {
|
||||
qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",
|
||||
sender ? sender->metaObject()->className() : "(null)",
|
||||
signal.signature(),
|
||||
signal.methodSignature().constData(),
|
||||
receiver ? receiver->metaObject()->className() : "(null)",
|
||||
method.signature() );
|
||||
method.methodSignature().constData() );
|
||||
return QMetaObject::Connection(0);
|
||||
}
|
||||
|
||||
// Reconstructing SIGNAL() macro result for signal.signature() string
|
||||
// Reconstructing SIGNAL() macro result for signal.methodSignature() string
|
||||
QByteArray signalSignature;
|
||||
signalSignature.reserve(qstrlen(signal.signature())+1);
|
||||
signalSignature.reserve(signal.methodSignature().size()+1);
|
||||
signalSignature.append((char)(QSIGNAL_CODE + '0'));
|
||||
signalSignature.append(signal.signature());
|
||||
signalSignature.append(signal.methodSignature());
|
||||
|
||||
int signal_index;
|
||||
int method_index;
|
||||
@ -2448,20 +2541,20 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMetho
|
||||
const QMetaObject *rmeta = receiver->metaObject();
|
||||
if (signal_index == -1) {
|
||||
qWarning("QObject::connect: Can't find signal %s on instance of class %s",
|
||||
signal.signature(), smeta->className());
|
||||
signal.methodSignature().constData(), smeta->className());
|
||||
return QMetaObject::Connection(0);
|
||||
}
|
||||
if (method_index == -1) {
|
||||
qWarning("QObject::connect: Can't find method %s on instance of class %s",
|
||||
method.signature(), rmeta->className());
|
||||
method.methodSignature().constData(), rmeta->className());
|
||||
return QMetaObject::Connection(0);
|
||||
}
|
||||
|
||||
if (!QMetaObject::checkConnectArgs(signal.signature(), method.signature())) {
|
||||
if (!QMetaObject::checkConnectArgs(signal.methodSignature().constData(), method.methodSignature().constData())) {
|
||||
qWarning("QObject::connect: Incompatible sender/receiver arguments"
|
||||
"\n %s::%s --> %s::%s",
|
||||
smeta->className(), signal.signature(),
|
||||
rmeta->className(), method.signature());
|
||||
smeta->className(), signal.methodSignature().constData(),
|
||||
rmeta->className(), method.methodSignature().constData());
|
||||
return QMetaObject::Connection(0);
|
||||
}
|
||||
|
||||
@ -2609,12 +2702,25 @@ bool QObject::disconnect(const QObject *sender, const char *signal,
|
||||
*/
|
||||
bool res = false;
|
||||
const QMetaObject *smeta = sender->metaObject();
|
||||
QByteArray signalName;
|
||||
QArgumentTypeArray signalTypes;
|
||||
if (signal && (QMetaObjectPrivate::get(smeta)->revision >= 7))
|
||||
signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes);
|
||||
QByteArray methodName;
|
||||
QArgumentTypeArray methodTypes;
|
||||
if (method && (QMetaObjectPrivate::get(receiver->metaObject())->revision >= 7))
|
||||
methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodTypes);
|
||||
do {
|
||||
int signal_index = -1;
|
||||
if (signal) {
|
||||
if (QMetaObjectPrivate::get(smeta)->revision >= 7) {
|
||||
signal_index = QMetaObjectPrivate::indexOfSignalRelative(
|
||||
&smeta, signalName, signalTypes.size(), signalTypes.constData());
|
||||
} else {
|
||||
signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
|
||||
if (signal_index < 0)
|
||||
signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, true);
|
||||
}
|
||||
if (signal_index < 0)
|
||||
break;
|
||||
signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
|
||||
@ -2629,7 +2735,13 @@ bool QObject::disconnect(const QObject *sender, const char *signal,
|
||||
} else {
|
||||
const QMetaObject *rmeta = receiver->metaObject();
|
||||
do {
|
||||
int method_index = rmeta->indexOfMethod(method);
|
||||
int method_index;
|
||||
if (QMetaObjectPrivate::get(rmeta)->revision >= 7) {
|
||||
method_index = QMetaObjectPrivate::indexOfMethod(
|
||||
rmeta, methodName, methodTypes.size(), methodTypes.constData());
|
||||
} else {
|
||||
method_index = rmeta->indexOfMethod(method);
|
||||
}
|
||||
if (method_index >= 0)
|
||||
while (method_index < rmeta->methodOffset())
|
||||
rmeta = rmeta->superClass();
|
||||
@ -2693,24 +2805,24 @@ bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal,
|
||||
if(signal.methodType() != QMetaMethod::Signal) {
|
||||
qWarning("QObject::%s: Attempt to %s non-signal %s::%s",
|
||||
"disconnect","unbind",
|
||||
sender->metaObject()->className(), signal.signature());
|
||||
sender->metaObject()->className(), signal.methodSignature().constData());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (method.mobj) {
|
||||
if(method.methodType() == QMetaMethod::Constructor) {
|
||||
qWarning("QObject::disconect: cannot use constructor as argument %s::%s",
|
||||
receiver->metaObject()->className(), method.signature());
|
||||
receiver->metaObject()->className(), method.methodSignature().constData());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Reconstructing SIGNAL() macro result for signal.signature() string
|
||||
// Reconstructing SIGNAL() macro result for signal.methodSignature() string
|
||||
QByteArray signalSignature;
|
||||
if (signal.mobj) {
|
||||
signalSignature.reserve(qstrlen(signal.signature())+1);
|
||||
signalSignature.reserve(signal.methodSignature().size()+1);
|
||||
signalSignature.append((char)(QSIGNAL_CODE + '0'));
|
||||
signalSignature.append(signal.signature());
|
||||
signalSignature.append(signal.methodSignature());
|
||||
}
|
||||
|
||||
int signal_index;
|
||||
@ -2724,13 +2836,13 @@ bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal,
|
||||
// is -1 then this signal is not a member of sender.
|
||||
if (signal.mobj && signal_index == -1) {
|
||||
qWarning("QObject::disconect: signal %s not found on class %s",
|
||||
signal.signature(), sender->metaObject()->className());
|
||||
signal.methodSignature().constData(), sender->metaObject()->className());
|
||||
return false;
|
||||
}
|
||||
// If this condition is true then method is not a member of receeiver.
|
||||
if (receiver && method.mobj && method_index == -1) {
|
||||
qWarning("QObject::disconect: method %s not found on class %s",
|
||||
method.signature(), receiver->metaObject()->className());
|
||||
method.methodSignature().constData(), receiver->metaObject()->className());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3045,7 +3157,8 @@ void QMetaObject::connectSlotsByName(QObject *o)
|
||||
Q_ASSERT(mo);
|
||||
const QObjectList list = o->findChildren<QObject *>(QString());
|
||||
for (int i = 0; i < mo->methodCount(); ++i) {
|
||||
const char *slot = mo->method(i).signature();
|
||||
QByteArray slotSignature = mo->method(i).methodSignature();
|
||||
const char *slot = slotSignature.constData();
|
||||
Q_ASSERT(slot);
|
||||
if (slot[0] != 'o' || slot[1] != 'n' || slot[2] != '_')
|
||||
continue;
|
||||
@ -3065,7 +3178,7 @@ void QMetaObject::connectSlotsByName(QObject *o)
|
||||
if (method.methodType() != QMetaMethod::Signal)
|
||||
continue;
|
||||
|
||||
if (!qstrncmp(method.signature(), slot + len + 4, slotlen)) {
|
||||
if (!qstrncmp(method.methodSignature().constData(), slot + len + 4, slotlen)) {
|
||||
int signalOffset, methodOffset;
|
||||
computeOffsets(method.enclosingMetaObject(), &signalOffset, &methodOffset);
|
||||
sigIndex = k + - methodOffset + signalOffset;
|
||||
@ -3311,9 +3424,17 @@ int QObjectPrivate::signalIndex(const char *signalName) const
|
||||
{
|
||||
Q_Q(const QObject);
|
||||
const QMetaObject *base = q->metaObject();
|
||||
int relative_index = QMetaObjectPrivate::indexOfSignalRelative(&base, signalName, false);
|
||||
int relative_index;
|
||||
if (QMetaObjectPrivate::get(base)->revision >= 7) {
|
||||
QArgumentTypeArray types;
|
||||
QByteArray name = QMetaObjectPrivate::decodeMethodSignature(signalName, types);
|
||||
relative_index = QMetaObjectPrivate::indexOfSignalRelative(
|
||||
&base, name, types.size(), types.constData());
|
||||
} else {
|
||||
relative_index = QMetaObjectPrivate::indexOfSignalRelative(&base, signalName, false);
|
||||
if (relative_index < 0)
|
||||
relative_index = QMetaObjectPrivate::indexOfSignalRelative(&base, signalName, true);
|
||||
}
|
||||
if (relative_index < 0)
|
||||
return relative_index;
|
||||
relative_index = QMetaObjectPrivate::originalClone(base, relative_index);
|
||||
@ -3536,7 +3657,7 @@ void QObject::dumpObjectInfo()
|
||||
offset = methodOffset - signalOffset;
|
||||
}
|
||||
const QMetaMethod signal = metaObject()->method(signal_index + offset);
|
||||
qDebug(" signal: %s", signal.signature());
|
||||
qDebug(" signal: %s", signal.methodSignature().constData());
|
||||
|
||||
// receivers
|
||||
const QObjectPrivate::Connection *c =
|
||||
@ -3552,7 +3673,7 @@ void QObject::dumpObjectInfo()
|
||||
qDebug(" --> %s::%s %s",
|
||||
receiverMetaObject->className(),
|
||||
c->receiver->objectName().isEmpty() ? "unnamed" : qPrintable(c->receiver->objectName()),
|
||||
method.signature());
|
||||
method.methodSignature().constData());
|
||||
c = c->nextConnectionList;
|
||||
}
|
||||
}
|
||||
@ -3569,7 +3690,7 @@ void QObject::dumpObjectInfo()
|
||||
qDebug(" <-- %s::%s %s",
|
||||
s->sender->metaObject()->className(),
|
||||
s->sender->objectName().isEmpty() ? "unnamed" : qPrintable(s->sender->objectName()),
|
||||
slot.signature());
|
||||
slot.methodSignature().constData());
|
||||
}
|
||||
} else {
|
||||
qDebug(" <None>");
|
||||
@ -4041,9 +4162,16 @@ QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signa
|
||||
locker.unlock();
|
||||
|
||||
// reconstruct the signature to call connectNotify
|
||||
const char *sig = senderMetaObject->d.stringdata + senderMetaObject->d.data[
|
||||
reinterpret_cast<const QMetaObjectPrivate*>(senderMetaObject->d.data)->methodData
|
||||
QByteArray tmp_sig;
|
||||
const char *sig;
|
||||
if (QMetaObjectPrivate::get(senderMetaObject)->revision >= 7) {
|
||||
tmp_sig = senderMetaObject->method(signal_index - signalOffset + methodOffset).methodSignature();
|
||||
sig = tmp_sig.constData();
|
||||
} else {
|
||||
sig = reinterpret_cast<const char *>(senderMetaObject->d.stringdata)
|
||||
+ senderMetaObject->d.data[QMetaObjectPrivate::get(senderMetaObject)->methodData
|
||||
+ 5 * (signal_index - signalOffset)];
|
||||
}
|
||||
QVarLengthArray<char> signalSignature(qstrlen(sig) + 2);
|
||||
signalSignature.data()[0] = char(QSIGNAL_CODE + '0');
|
||||
strcpy(signalSignature.data() + 1 , sig);
|
||||
|
@ -50,11 +50,12 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
|
||||
class QByteArray;
|
||||
struct QByteArrayData;
|
||||
|
||||
class QString;
|
||||
|
||||
#ifndef Q_MOC_OUTPUT_REVISION
|
||||
#define Q_MOC_OUTPUT_REVISION 64
|
||||
#define Q_MOC_OUTPUT_REVISION 65
|
||||
#endif
|
||||
|
||||
// The following macros are our "extensions" to C++
|
||||
@ -326,6 +327,8 @@ struct Q_CORE_EXPORT QMetaObject
|
||||
QMetaProperty userProperty() const;
|
||||
|
||||
static bool checkConnectArgs(const char *signal, const char *method);
|
||||
static bool checkConnectArgs(const QMetaMethod &signal,
|
||||
const QMetaMethod &method);
|
||||
static QByteArray normalizedSignature(const char *method);
|
||||
static QByteArray normalizedType(const char *type);
|
||||
|
||||
@ -439,7 +442,7 @@ struct Q_CORE_EXPORT QMetaObject
|
||||
|
||||
struct { // private data
|
||||
const QMetaObject *superdata;
|
||||
const char *stringdata;
|
||||
const QByteArrayData *stringdata;
|
||||
const uint *data;
|
||||
const void *extradata;
|
||||
} d;
|
||||
@ -480,9 +483,6 @@ struct QMetaObjectExtraData
|
||||
StaticMetacallFunction static_metacall;
|
||||
};
|
||||
|
||||
inline const char *QMetaObject::className() const
|
||||
{ return d.stringdata; }
|
||||
|
||||
inline const QMetaObject *QMetaObject::superClass() const
|
||||
{ return d.superdata; }
|
||||
|
||||
|
@ -1697,7 +1697,7 @@ void QVariant::load(QDataStream &s)
|
||||
QByteArray name;
|
||||
s >> name;
|
||||
typeId = QMetaType::type(name.constData());
|
||||
if (!typeId) {
|
||||
if (typeId == QMetaType::UnknownType) {
|
||||
s.setStatus(QDataStream::ReadCorruptData);
|
||||
return;
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ class Q_CORE_EXPORT QVariant
|
||||
{
|
||||
public:
|
||||
enum Type {
|
||||
Invalid = QMetaType::Void,
|
||||
Invalid = QMetaType::UnknownType,
|
||||
Bool = QMetaType::Bool,
|
||||
Int = QMetaType::Int,
|
||||
UInt = QMetaType::UInt,
|
||||
|
@ -187,7 +187,11 @@ public:
|
||||
return FilteredComparator<T>::compare(m_a, m_b);
|
||||
}
|
||||
|
||||
bool delegate(const void*) { return true; }
|
||||
bool delegate(const void*) { Q_ASSERT(false); return true; }
|
||||
bool delegate(const QMetaTypeSwitcher::UnknownType*)
|
||||
{
|
||||
return true; // for historical reason invalid variant == invalid variant
|
||||
}
|
||||
bool delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return false; }
|
||||
protected:
|
||||
const QVariant::Private *m_a;
|
||||
@ -281,7 +285,8 @@ public:
|
||||
return CallIsNull<T>::isNull(m_d);
|
||||
}
|
||||
// we need that as sizof(void) is undefined and it is needed in HasIsNullMethod
|
||||
bool delegate(const void *) { return m_d->is_null; }
|
||||
bool delegate(const void *) { Q_ASSERT(false); return m_d->is_null; }
|
||||
bool delegate(const QMetaTypeSwitcher::UnknownType *) { return m_d->is_null; }
|
||||
bool delegate(const QMetaTypeSwitcher::NotBuiltinType *) { return m_d->is_null; }
|
||||
protected:
|
||||
const QVariant::Private *m_d;
|
||||
@ -354,8 +359,18 @@ public:
|
||||
|
||||
void delegate(const void*)
|
||||
{
|
||||
// QMetaType::Void == QVariant::Invalid, creating an invalid value creates invalid QVariant
|
||||
// TODO it might go away, check is needed
|
||||
qWarning("Trying to create a QVariant instance of QMetaType::Void type, an invalid QVariant will be constructed instead");
|
||||
m_x->type = QMetaType::UnknownType;
|
||||
m_x->is_shared = false;
|
||||
m_x->is_null = !m_copy;
|
||||
}
|
||||
|
||||
void delegate(const QMetaTypeSwitcher::UnknownType*)
|
||||
{
|
||||
if (m_x->type != QMetaType::UnknownType) {
|
||||
qWarning("Trying to construct an instance of an invalid type, type id: %i", m_x->type);
|
||||
m_x->type = QMetaType::UnknownType;
|
||||
}
|
||||
m_x->is_shared = false;
|
||||
m_x->is_null = !m_copy;
|
||||
}
|
||||
@ -401,7 +416,8 @@ public:
|
||||
qWarning("Trying to destruct an instance of an invalid type, type id: %i", m_d->type);
|
||||
}
|
||||
// Ignore nonconstructible type
|
||||
void delegate(const void*) {}
|
||||
void delegate(const QMetaTypeSwitcher::UnknownType*) {}
|
||||
void delegate(const void*) { Q_ASSERT(false); }
|
||||
private:
|
||||
QVariant::Private *m_d;
|
||||
};
|
||||
@ -446,10 +462,11 @@ public:
|
||||
{
|
||||
qWarning("Trying to stream an instance of an invalid type, type id: %i", m_d->type);
|
||||
}
|
||||
void delegate(const void*)
|
||||
void delegate(const QMetaTypeSwitcher::UnknownType*)
|
||||
{
|
||||
m_debugStream.nospace() << "QVariant::Invalid";
|
||||
}
|
||||
void delegate(const void*) { Q_ASSERT(false); }
|
||||
private:
|
||||
QDebug m_debugStream;
|
||||
QVariant::Private *m_d;
|
||||
|
@ -1657,7 +1657,7 @@ void QStateMachinePrivate::handleTransitionSignal(QObject *sender, int signalInd
|
||||
|
||||
#ifdef QSTATEMACHINE_DEBUG
|
||||
qDebug() << q_func() << ": sending signal event ( sender =" << sender
|
||||
<< ", signal =" << sender->metaObject()->method(signalIndex).signature() << ')';
|
||||
<< ", signal =" << sender->metaObject()->method(signalIndex).methodSignature().constData() << ')';
|
||||
#endif
|
||||
postInternalEvent(new QStateMachine::SignalEvent(sender, signalIndex, vargs));
|
||||
processEvents(DirectProcessing);
|
||||
@ -2211,10 +2211,29 @@ void QStateMachine::removeDefaultAnimation(QAbstractAnimation *animation)
|
||||
|
||||
|
||||
// Begin moc-generated code -- modify carefully (check "HAND EDIT" parts)!
|
||||
struct qt_meta_stringdata_QSignalEventGenerator_t {
|
||||
QByteArrayData data[3];
|
||||
char stringdata[32];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) { \
|
||||
Q_REFCOUNT_INITIALIZE_STATIC, len, 0, 0, \
|
||||
offsetof(qt_meta_stringdata_QSignalEventGenerator_t, stringdata) + ofs \
|
||||
- idx * sizeof(QByteArrayData) \
|
||||
}
|
||||
static const qt_meta_stringdata_QSignalEventGenerator_t qt_meta_stringdata_QSignalEventGenerator = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 21),
|
||||
QT_MOC_LITERAL(1, 22, 7),
|
||||
QT_MOC_LITERAL(2, 30, 0)
|
||||
},
|
||||
"QSignalEventGenerator\0execute\0\0"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_QSignalEventGenerator[] = {
|
||||
|
||||
// content:
|
||||
6, // revision
|
||||
7, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
1, 14, // methods
|
||||
@ -2224,16 +2243,15 @@ static const uint qt_meta_data_QSignalEventGenerator[] = {
|
||||
0, // flags
|
||||
0, // signalCount
|
||||
|
||||
// slots: signature, parameters, type, tag, flags
|
||||
23, 22, 22, 22, 0x0a,
|
||||
// slots: name, argc, parameters, tag, flags
|
||||
1, 0, 19, 2, 0x0a,
|
||||
|
||||
// slots: parameters
|
||||
QMetaType::Void,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
static const char qt_meta_stringdata_QSignalEventGenerator[] = {
|
||||
"QSignalEventGenerator\0\0execute()\0"
|
||||
};
|
||||
|
||||
void QSignalEventGenerator::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
@ -2252,7 +2270,7 @@ const QMetaObjectExtraData QSignalEventGenerator::staticMetaObjectExtraData = {
|
||||
};
|
||||
|
||||
const QMetaObject QSignalEventGenerator::staticMetaObject = {
|
||||
{ &QObject::staticMetaObject, qt_meta_stringdata_QSignalEventGenerator,
|
||||
{ &QObject::staticMetaObject, qt_meta_stringdata_QSignalEventGenerator.data,
|
||||
qt_meta_data_QSignalEventGenerator, &staticMetaObjectExtraData }
|
||||
};
|
||||
|
||||
@ -2264,7 +2282,7 @@ const QMetaObject *QSignalEventGenerator::metaObject() const
|
||||
void *QSignalEventGenerator::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return 0;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_QSignalEventGenerator))
|
||||
if (!strcmp(_clname, qt_meta_stringdata_QSignalEventGenerator.stringdata))
|
||||
return static_cast<void*>(const_cast< QSignalEventGenerator*>(this));
|
||||
return QObject::qt_metacast(_clname);
|
||||
}
|
||||
|
111
src/corelib/tools/qarraydata.cpp
Normal file
111
src/corelib/tools/qarraydata.cpp
Normal file
@ -0,0 +1,111 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtCore/qarraydata.h>
|
||||
#include <QtCore/private/qtools_p.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
const QArrayData QArrayData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, 0 };
|
||||
|
||||
static const QArrayData qt_array_empty = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, 0 };
|
||||
static const QArrayData qt_array_unsharable_empty = { { Q_BASIC_ATOMIC_INITIALIZER(0) }, 0, 0, 0, 0 };
|
||||
|
||||
QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
|
||||
size_t capacity, AllocationOptions options)
|
||||
{
|
||||
// Alignment is a power of two
|
||||
Q_ASSERT(alignment >= Q_ALIGNOF(QArrayData)
|
||||
&& !(alignment & (alignment - 1)));
|
||||
|
||||
// Don't allocate empty headers
|
||||
if (!(options & RawData) && !capacity)
|
||||
return !(options & Unsharable)
|
||||
? const_cast<QArrayData *>(&qt_array_empty)
|
||||
: const_cast<QArrayData *>(&qt_array_unsharable_empty);
|
||||
|
||||
size_t headerSize = sizeof(QArrayData);
|
||||
|
||||
// Allocate extra (alignment - Q_ALIGNOF(QArrayData)) padding bytes so we
|
||||
// can properly align the data array. This assumes malloc is able to
|
||||
// provide appropriate alignment for the header -- as it should!
|
||||
// Padding is skipped when allocating a header for RawData.
|
||||
if (!(options & RawData))
|
||||
headerSize += (alignment - Q_ALIGNOF(QArrayData));
|
||||
|
||||
// Allocate additional space if array is growing
|
||||
if (options & Grow)
|
||||
capacity = qAllocMore(objectSize * capacity, headerSize) / objectSize;
|
||||
|
||||
size_t allocSize = headerSize + objectSize * capacity;
|
||||
|
||||
QArrayData *header = static_cast<QArrayData *>(::malloc(allocSize));
|
||||
if (header) {
|
||||
quintptr data = (quintptr(header) + sizeof(QArrayData) + alignment - 1)
|
||||
& ~(alignment - 1);
|
||||
|
||||
header->ref.atomic.store(bool(!(options & Unsharable)));
|
||||
header->size = 0;
|
||||
header->alloc = capacity;
|
||||
header->capacityReserved = bool(options & CapacityReserved);
|
||||
header->offset = data - quintptr(header);
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
void QArrayData::deallocate(QArrayData *data, size_t objectSize,
|
||||
size_t alignment)
|
||||
{
|
||||
// Alignment is a power of two
|
||||
Q_ASSERT(alignment >= Q_ALIGNOF(QArrayData)
|
||||
&& !(alignment & (alignment - 1)));
|
||||
Q_UNUSED(objectSize) Q_UNUSED(alignment)
|
||||
|
||||
if (data == &qt_array_unsharable_empty)
|
||||
return;
|
||||
|
||||
::free(data);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
275
src/corelib/tools/qarraydata.h
Normal file
275
src/corelib/tools/qarraydata.h
Normal file
@ -0,0 +1,275 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QARRAYDATA_H
|
||||
#define QARRAYDATA_H
|
||||
|
||||
#include <QtCore/qrefcount.h>
|
||||
#include <string.h>
|
||||
|
||||
QT_BEGIN_HEADER
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
struct Q_CORE_EXPORT QArrayData
|
||||
{
|
||||
QtPrivate::RefCount ref;
|
||||
int size;
|
||||
uint alloc : 31;
|
||||
uint capacityReserved : 1;
|
||||
|
||||
qptrdiff offset; // in bytes from beginning of header
|
||||
|
||||
void *data()
|
||||
{
|
||||
Q_ASSERT(size == 0
|
||||
|| offset < 0 || size_t(offset) >= sizeof(QArrayData));
|
||||
return reinterpret_cast<char *>(this) + offset;
|
||||
}
|
||||
|
||||
const void *data() const
|
||||
{
|
||||
Q_ASSERT(size == 0
|
||||
|| offset < 0 || size_t(offset) >= sizeof(QArrayData));
|
||||
return reinterpret_cast<const char *>(this) + offset;
|
||||
}
|
||||
|
||||
// This refers to array data mutability, not "header data" represented by
|
||||
// data members in QArrayData. Shared data (array and header) must still
|
||||
// follow COW principles.
|
||||
bool isMutable() const
|
||||
{
|
||||
return alloc != 0;
|
||||
}
|
||||
|
||||
enum AllocationOption {
|
||||
CapacityReserved = 0x1,
|
||||
Unsharable = 0x2,
|
||||
RawData = 0x4,
|
||||
Grow = 0x8,
|
||||
|
||||
Default = 0
|
||||
};
|
||||
|
||||
Q_DECLARE_FLAGS(AllocationOptions, AllocationOption)
|
||||
|
||||
AllocationOptions detachFlags() const
|
||||
{
|
||||
AllocationOptions result;
|
||||
if (!ref.isSharable())
|
||||
result |= Unsharable;
|
||||
if (capacityReserved)
|
||||
result |= CapacityReserved;
|
||||
return result;
|
||||
}
|
||||
|
||||
AllocationOptions cloneFlags() const
|
||||
{
|
||||
AllocationOptions result;
|
||||
if (capacityReserved)
|
||||
result |= CapacityReserved;
|
||||
return result;
|
||||
}
|
||||
|
||||
static QArrayData *allocate(size_t objectSize, size_t alignment,
|
||||
size_t capacity, AllocationOptions options = Default)
|
||||
Q_REQUIRED_RESULT;
|
||||
static void deallocate(QArrayData *data, size_t objectSize,
|
||||
size_t alignment);
|
||||
|
||||
static const QArrayData shared_null;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QArrayData::AllocationOptions)
|
||||
|
||||
template <class T>
|
||||
struct QTypedArrayData
|
||||
: QArrayData
|
||||
{
|
||||
typedef T *iterator;
|
||||
typedef const T *const_iterator;
|
||||
|
||||
T *data() { return static_cast<T *>(QArrayData::data()); }
|
||||
const T *data() const { return static_cast<const T *>(QArrayData::data()); }
|
||||
|
||||
T *begin() { return data(); }
|
||||
T *end() { return data() + size; }
|
||||
const T *begin() const { return data(); }
|
||||
const T *end() const { return data() + size; }
|
||||
|
||||
class AlignmentDummy { QArrayData header; T data; };
|
||||
|
||||
static QTypedArrayData *allocate(size_t capacity,
|
||||
AllocationOptions options = Default) Q_REQUIRED_RESULT
|
||||
{
|
||||
return static_cast<QTypedArrayData *>(QArrayData::allocate(sizeof(T),
|
||||
Q_ALIGNOF(AlignmentDummy), capacity, options));
|
||||
}
|
||||
|
||||
static void deallocate(QArrayData *data)
|
||||
{
|
||||
QArrayData::deallocate(data, sizeof(T), Q_ALIGNOF(AlignmentDummy));
|
||||
}
|
||||
|
||||
static QTypedArrayData *fromRawData(const T *data, size_t n,
|
||||
AllocationOptions options = Default)
|
||||
{
|
||||
QTypedArrayData *result = allocate(0, options | RawData);
|
||||
if (result) {
|
||||
Q_ASSERT(!result->ref.isShared()); // No shared empty, please!
|
||||
|
||||
result->offset = reinterpret_cast<const char *>(data)
|
||||
- reinterpret_cast<const char *>(result);
|
||||
result->size = n;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static QTypedArrayData *sharedNull()
|
||||
{
|
||||
return static_cast<QTypedArrayData *>(
|
||||
const_cast<QArrayData *>(&QArrayData::shared_null));
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, size_t N>
|
||||
struct QStaticArrayData
|
||||
{
|
||||
QArrayData header;
|
||||
T data[N];
|
||||
};
|
||||
|
||||
// Support for returning QArrayDataPointer<T> from functions
|
||||
template <class T>
|
||||
struct QArrayDataPointerRef
|
||||
{
|
||||
QTypedArrayData<T> *ptr;
|
||||
};
|
||||
|
||||
#define Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER(type, size) { \
|
||||
Q_REFCOUNT_INITIALIZE_STATIC, size, 0, 0, \
|
||||
(sizeof(QArrayData) + (Q_ALIGNOF(type) - 1)) \
|
||||
& ~(Q_ALIGNOF(type) - 1) } \
|
||||
/**/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Q_ARRAY_LITERAL
|
||||
|
||||
// The idea here is to place a (read-only) copy of header and array data in an
|
||||
// mmappable portion of the executable (typically, .rodata section). This is
|
||||
// accomplished by hiding a static const instance of QStaticArrayData, which is
|
||||
// POD.
|
||||
|
||||
#if defined(Q_COMPILER_VARIADIC_MACROS)
|
||||
#if defined(Q_COMPILER_LAMBDA)
|
||||
// Hide array inside a lambda
|
||||
#define Q_ARRAY_LITERAL(Type, ...) \
|
||||
([]() -> QArrayDataPointerRef<Type> { \
|
||||
/* MSVC 2010 Doesn't support static variables in a lambda, but */ \
|
||||
/* happily accepts them in a static function of a lambda-local */ \
|
||||
/* struct :-) */ \
|
||||
struct StaticWrapper { \
|
||||
static QArrayDataPointerRef<Type> get() \
|
||||
{ \
|
||||
Q_ARRAY_LITERAL_IMPL(Type, __VA_ARGS__) \
|
||||
return ref; \
|
||||
} \
|
||||
}; \
|
||||
return StaticWrapper::get(); \
|
||||
}()) \
|
||||
/**/
|
||||
#elif defined(Q_CC_GNU)
|
||||
// Hide array within GCC's __extension__ {( )} block
|
||||
#define Q_ARRAY_LITERAL(Type, ...) \
|
||||
__extension__ ({ \
|
||||
Q_ARRAY_LITERAL_IMPL(Type, __VA_ARGS__) \
|
||||
ref; \
|
||||
}) \
|
||||
/**/
|
||||
#endif
|
||||
#endif // defined(Q_COMPILER_VARIADIC_MACROS)
|
||||
|
||||
#if defined(Q_ARRAY_LITERAL)
|
||||
#define Q_ARRAY_LITERAL_IMPL(Type, ...) \
|
||||
union { Type type_must_be_POD; } dummy; Q_UNUSED(dummy) \
|
||||
\
|
||||
/* Portable compile-time array size computation */ \
|
||||
Type data[] = { __VA_ARGS__ }; Q_UNUSED(data) \
|
||||
enum { Size = sizeof(data) / sizeof(data[0]) }; \
|
||||
\
|
||||
static const QStaticArrayData<Type, Size> literal = { \
|
||||
Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER(Type, Size), { __VA_ARGS__ } }; \
|
||||
\
|
||||
QArrayDataPointerRef<Type> ref = \
|
||||
{ static_cast<QTypedArrayData<Type> *>( \
|
||||
const_cast<QArrayData *>(&literal.header)) }; \
|
||||
/**/
|
||||
#else
|
||||
// As a fallback, memory is allocated and data copied to the heap.
|
||||
|
||||
// The fallback macro does NOT use variadic macros and does NOT support
|
||||
// variable number of arguments. It is suitable for char arrays.
|
||||
|
||||
namespace QtPrivate {
|
||||
template <class T, size_t N>
|
||||
inline QArrayDataPointerRef<T> qMakeArrayLiteral(const T (&array)[N])
|
||||
{
|
||||
union { T type_must_be_POD; } dummy; Q_UNUSED(dummy)
|
||||
|
||||
QArrayDataPointerRef<T> result = { QTypedArrayData<T>::allocate(N) };
|
||||
Q_CHECK_PTR(result.ptr);
|
||||
|
||||
::memcpy(result.ptr->data(), array, N * sizeof(T));
|
||||
result.ptr->size = N;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
#define Q_ARRAY_LITERAL(Type, Array) \
|
||||
QT_PREPEND_NAMESPACE(QtPrivate::qMakeArrayLiteral)<Type>( Array )
|
||||
#endif // !defined(Q_ARRAY_LITERAL)
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
QT_END_HEADER
|
||||
|
||||
#endif // include guard
|
322
src/corelib/tools/qarraydataops.h
Normal file
322
src/corelib/tools/qarraydataops.h
Normal file
@ -0,0 +1,322 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QARRAYDATAOPS_H
|
||||
#define QARRAYDATAOPS_H
|
||||
|
||||
#include <QtCore/qarraydata.h>
|
||||
|
||||
#include <new>
|
||||
#include <string.h>
|
||||
|
||||
QT_BEGIN_HEADER
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QtPrivate {
|
||||
|
||||
template <class T>
|
||||
struct QPodArrayOps
|
||||
: QTypedArrayData<T>
|
||||
{
|
||||
void copyAppend(const T *b, const T *e)
|
||||
{
|
||||
Q_ASSERT(!this->ref.isShared());
|
||||
Q_ASSERT(b < e);
|
||||
Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
|
||||
|
||||
::memcpy(this->end(), b, (e - b) * sizeof(T));
|
||||
this->size += e - b;
|
||||
}
|
||||
|
||||
void copyAppend(size_t n, const T &t)
|
||||
{
|
||||
Q_ASSERT(!this->ref.isShared());
|
||||
Q_ASSERT(n <= this->alloc - uint(this->size));
|
||||
|
||||
T *iter = this->end();
|
||||
const T *const end = iter + n;
|
||||
for (; iter != end; ++iter)
|
||||
::memcpy(iter, &t, sizeof(T));
|
||||
this->size += n;
|
||||
}
|
||||
|
||||
void destroyAll() // Call from destructors, ONLY!
|
||||
{
|
||||
Q_ASSERT(this->ref.atomic.load() == 0);
|
||||
|
||||
// As this is to be called only from destructor, it doesn't need to be
|
||||
// exception safe; size not updated.
|
||||
}
|
||||
|
||||
void insert(T *where, const T *b, const T *e)
|
||||
{
|
||||
Q_ASSERT(!this->ref.isShared());
|
||||
Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end
|
||||
Q_ASSERT(b < e);
|
||||
Q_ASSERT(e <= where || b > this->end()); // No overlap
|
||||
Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
|
||||
|
||||
::memmove(where + (e - b), where, (this->end() - where) * sizeof(T));
|
||||
::memcpy(where, b, (e - b) * sizeof(T));
|
||||
this->size += (e - b);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct QGenericArrayOps
|
||||
: QTypedArrayData<T>
|
||||
{
|
||||
void copyAppend(const T *b, const T *e)
|
||||
{
|
||||
Q_ASSERT(!this->ref.isShared());
|
||||
Q_ASSERT(b < e);
|
||||
Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
|
||||
|
||||
T *iter = this->end();
|
||||
for (; b != e; ++iter, ++b) {
|
||||
new (iter) T(*b);
|
||||
++this->size;
|
||||
}
|
||||
}
|
||||
|
||||
void copyAppend(size_t n, const T &t)
|
||||
{
|
||||
Q_ASSERT(!this->ref.isShared());
|
||||
Q_ASSERT(n <= this->alloc - uint(this->size));
|
||||
|
||||
T *iter = this->end();
|
||||
const T *const end = iter + n;
|
||||
for (; iter != end; ++iter) {
|
||||
new (iter) T(t);
|
||||
++this->size;
|
||||
}
|
||||
}
|
||||
|
||||
void destroyAll() // Call from destructors, ONLY
|
||||
{
|
||||
// As this is to be called only from destructor, it doesn't need to be
|
||||
// exception safe; size not updated.
|
||||
|
||||
Q_ASSERT(this->ref.atomic.load() == 0);
|
||||
|
||||
const T *const b = this->begin();
|
||||
const T *i = this->end();
|
||||
|
||||
while (i != b)
|
||||
(--i)->~T();
|
||||
}
|
||||
|
||||
void insert(T *where, const T *b, const T *e)
|
||||
{
|
||||
Q_ASSERT(!this->ref.isShared());
|
||||
Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end
|
||||
Q_ASSERT(b < e);
|
||||
Q_ASSERT(e <= where || b > this->end()); // No overlap
|
||||
Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
|
||||
|
||||
// Array may be truncated at where in case of exceptions
|
||||
|
||||
T *const end = this->end();
|
||||
const T *readIter = end;
|
||||
T *writeIter = end + (e - b);
|
||||
|
||||
const T *const step1End = where + qMax(e - b, end - where);
|
||||
|
||||
struct Destructor
|
||||
{
|
||||
Destructor(T *&it)
|
||||
: iter(&it)
|
||||
, end(it)
|
||||
{
|
||||
}
|
||||
|
||||
void commit()
|
||||
{
|
||||
iter = &end;
|
||||
}
|
||||
|
||||
~Destructor()
|
||||
{
|
||||
for (; *iter != end; --*iter)
|
||||
(*iter)->~T();
|
||||
}
|
||||
|
||||
T **iter;
|
||||
T *end;
|
||||
} destroyer(writeIter);
|
||||
|
||||
// Construct new elements in array
|
||||
do {
|
||||
--readIter, --writeIter;
|
||||
new (writeIter) T(*readIter);
|
||||
} while (writeIter != step1End);
|
||||
|
||||
while (writeIter != end) {
|
||||
--e, --writeIter;
|
||||
new (writeIter) T(*e);
|
||||
}
|
||||
|
||||
destroyer.commit();
|
||||
this->size += destroyer.end - end;
|
||||
|
||||
// Copy assign over existing elements
|
||||
while (readIter != where) {
|
||||
--readIter, --writeIter;
|
||||
*writeIter = *readIter;
|
||||
}
|
||||
|
||||
while (writeIter != where) {
|
||||
--e, --writeIter;
|
||||
*writeIter = *e;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct QMovableArrayOps
|
||||
: QGenericArrayOps<T>
|
||||
{
|
||||
// using QGenericArrayOps<T>::copyAppend;
|
||||
// using QGenericArrayOps<T>::destroyAll;
|
||||
|
||||
void insert(T *where, const T *b, const T *e)
|
||||
{
|
||||
Q_ASSERT(!this->ref.isShared());
|
||||
Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end
|
||||
Q_ASSERT(b < e);
|
||||
Q_ASSERT(e <= where || b > this->end()); // No overlap
|
||||
Q_ASSERT(size_t(e - b) <= this->alloc - uint(this->size));
|
||||
|
||||
// Provides strong exception safety guarantee,
|
||||
// provided T::~T() nothrow
|
||||
|
||||
struct ReversibleDisplace
|
||||
{
|
||||
ReversibleDisplace(T *start, T *finish, size_t diff)
|
||||
: begin(start)
|
||||
, end(finish)
|
||||
, displace(diff)
|
||||
{
|
||||
::memmove(begin + displace, begin, (end - begin) * sizeof(T));
|
||||
}
|
||||
|
||||
void commit() { displace = 0; }
|
||||
|
||||
~ReversibleDisplace()
|
||||
{
|
||||
if (displace)
|
||||
::memmove(begin, begin + displace, (end - begin) * sizeof(T));
|
||||
}
|
||||
|
||||
T *const begin;
|
||||
T *const end;
|
||||
size_t displace;
|
||||
|
||||
} displace(where, this->end(), size_t(e - b));
|
||||
|
||||
struct CopyConstructor
|
||||
{
|
||||
CopyConstructor(T *w) : where(w) {}
|
||||
|
||||
void copy(const T *src, const T *const srcEnd)
|
||||
{
|
||||
n = 0;
|
||||
for (; src != srcEnd; ++src) {
|
||||
new (where + n) T(*src);
|
||||
++n;
|
||||
}
|
||||
n = 0;
|
||||
}
|
||||
|
||||
~CopyConstructor()
|
||||
{
|
||||
while (n)
|
||||
where[--n].~T();
|
||||
}
|
||||
|
||||
T *const where;
|
||||
size_t n;
|
||||
} copier(where);
|
||||
|
||||
copier.copy(b, e);
|
||||
displace.commit();
|
||||
this->size += (e - b);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class = void>
|
||||
struct QArrayOpsSelector
|
||||
{
|
||||
typedef QGenericArrayOps<T> Type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct QArrayOpsSelector<T,
|
||||
typename QEnableIf<
|
||||
!QTypeInfo<T>::isComplex && !QTypeInfo<T>::isStatic
|
||||
>::Type>
|
||||
{
|
||||
typedef QPodArrayOps<T> Type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct QArrayOpsSelector<T,
|
||||
typename QEnableIf<
|
||||
QTypeInfo<T>::isComplex && !QTypeInfo<T>::isStatic
|
||||
>::Type>
|
||||
{
|
||||
typedef QMovableArrayOps<T> Type;
|
||||
};
|
||||
|
||||
} // namespace QtPrivate
|
||||
|
||||
template <class T>
|
||||
struct QArrayDataOps
|
||||
: QtPrivate::QArrayOpsSelector<T>::Type
|
||||
{
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
QT_END_HEADER
|
||||
|
||||
#endif // include guard
|
220
src/corelib/tools/qarraydatapointer.h
Normal file
220
src/corelib/tools/qarraydatapointer.h
Normal file
@ -0,0 +1,220 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QARRAYDATAPOINTER_H
|
||||
#define QARRAYDATAPOINTER_H
|
||||
|
||||
#include <QtCore/qarraydataops.h>
|
||||
|
||||
QT_BEGIN_HEADER
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
template <class T>
|
||||
struct QArrayDataPointer
|
||||
{
|
||||
private:
|
||||
typedef QTypedArrayData<T> Data;
|
||||
typedef QArrayDataOps<T> DataOps;
|
||||
|
||||
public:
|
||||
QArrayDataPointer()
|
||||
: d(Data::sharedNull())
|
||||
{
|
||||
}
|
||||
|
||||
QArrayDataPointer(const QArrayDataPointer &other)
|
||||
: d(other.d->ref.ref()
|
||||
? other.d
|
||||
: other.clone(other.d->cloneFlags()))
|
||||
{
|
||||
}
|
||||
|
||||
explicit QArrayDataPointer(QTypedArrayData<T> *ptr)
|
||||
: d(ptr)
|
||||
{
|
||||
Q_CHECK_PTR(ptr);
|
||||
}
|
||||
|
||||
QArrayDataPointer(QArrayDataPointerRef<T> ref)
|
||||
: d(ref.ptr)
|
||||
{
|
||||
}
|
||||
|
||||
QArrayDataPointer &operator=(const QArrayDataPointer &other)
|
||||
{
|
||||
QArrayDataPointer tmp(other);
|
||||
this->swap(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef Q_COMPILER_RVALUE_REFS
|
||||
QArrayDataPointer(QArrayDataPointer &&other)
|
||||
: d(other.d)
|
||||
{
|
||||
other.d = Data::sharedNull();
|
||||
}
|
||||
|
||||
QArrayDataPointer &operator=(QArrayDataPointer &&other)
|
||||
{
|
||||
this->swap(other);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
DataOps &operator*() const
|
||||
{
|
||||
Q_ASSERT(d);
|
||||
return *static_cast<DataOps *>(d);
|
||||
}
|
||||
|
||||
DataOps *operator->() const
|
||||
{
|
||||
Q_ASSERT(d);
|
||||
return static_cast<DataOps *>(d);
|
||||
}
|
||||
|
||||
~QArrayDataPointer()
|
||||
{
|
||||
if (!d->ref.deref()) {
|
||||
(*this)->destroyAll();
|
||||
Data::deallocate(d);
|
||||
}
|
||||
}
|
||||
|
||||
bool isNull() const
|
||||
{
|
||||
return d == Data::sharedNull();
|
||||
}
|
||||
|
||||
Data *data() const
|
||||
{
|
||||
return d;
|
||||
}
|
||||
|
||||
void setSharable(bool sharable)
|
||||
{
|
||||
// Can't call setSharable on static read-only data, like shared_null
|
||||
// and the internal shared-empties.
|
||||
if (d->alloc == 0 && d->size == 0) {
|
||||
d = Data::allocate(0, sharable
|
||||
? QArrayData::Default
|
||||
: QArrayData::Unsharable);
|
||||
return;
|
||||
}
|
||||
|
||||
detach();
|
||||
d->ref.setSharable(sharable);
|
||||
}
|
||||
|
||||
void swap(QArrayDataPointer &other)
|
||||
{
|
||||
qSwap(d, other.d);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
QArrayDataPointer tmp(d);
|
||||
d = Data::sharedNull();
|
||||
}
|
||||
|
||||
bool detach()
|
||||
{
|
||||
if (!d->isMutable() || d->ref.isShared()) {
|
||||
Data *copy = clone(d->detachFlags());
|
||||
QArrayDataPointer old(d);
|
||||
d = copy;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
Data *clone(QArrayData::AllocationOptions options) const Q_REQUIRED_RESULT
|
||||
{
|
||||
QArrayDataPointer copy(Data::allocate(d->alloc ? d->alloc : d->size,
|
||||
options));
|
||||
if (d->size)
|
||||
copy->copyAppend(d->begin(), d->end());
|
||||
|
||||
Data *result = copy.d;
|
||||
copy.d = Data::sharedNull();
|
||||
return result;
|
||||
}
|
||||
|
||||
Data *d;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline bool operator==(const QArrayDataPointer<T> &lhs, const QArrayDataPointer<T> &rhs)
|
||||
{
|
||||
return lhs.data() == rhs.data();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool operator!=(const QArrayDataPointer<T> &lhs, const QArrayDataPointer<T> &rhs)
|
||||
{
|
||||
return lhs.data() != rhs.data();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void qSwap(QArrayDataPointer<T> &p1, QArrayDataPointer<T> &p2)
|
||||
{
|
||||
p1.swap(p2);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <class T>
|
||||
inline void swap(
|
||||
QT_PREPEND_NAMESPACE(QArrayDataPointer)<T> &p1,
|
||||
QT_PREPEND_NAMESPACE(QArrayDataPointer)<T> &p2)
|
||||
{
|
||||
p1.swap(p2);
|
||||
}
|
||||
}
|
||||
|
||||
QT_END_HEADER
|
||||
|
||||
#endif // include guard
|
@ -57,7 +57,7 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define IS_RAW_DATA(d) ((d)->offset != 0)
|
||||
#define IS_RAW_DATA(d) ((d)->offset != sizeof(QByteArrayData))
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@ -69,24 +69,25 @@ int qFindByteArray(
|
||||
|
||||
int qAllocMore(int alloc, int extra)
|
||||
{
|
||||
if (alloc == 0 && extra == 0)
|
||||
return 0;
|
||||
const int page = 1 << 12;
|
||||
int nalloc;
|
||||
alloc += extra;
|
||||
if (alloc < 1<<6) {
|
||||
nalloc = (1<<3) + ((alloc >>3) << 3);
|
||||
} else {
|
||||
// don't do anything if the loop will overflow signed int.
|
||||
if (alloc >= INT_MAX/2)
|
||||
return INT_MAX;
|
||||
nalloc = (alloc < page) ? 1 << 3 : page;
|
||||
while (nalloc < alloc) {
|
||||
if (nalloc <= 0)
|
||||
return INT_MAX;
|
||||
nalloc *= 2;
|
||||
}
|
||||
}
|
||||
Q_ASSERT(alloc >= 0 && extra >= 0);
|
||||
Q_ASSERT(alloc < (1 << 30) - extra);
|
||||
|
||||
unsigned nalloc = alloc + extra;
|
||||
|
||||
// Round up to next power of 2
|
||||
|
||||
// Assuming container is growing, always overshoot
|
||||
//--nalloc;
|
||||
|
||||
nalloc |= nalloc >> 1;
|
||||
nalloc |= nalloc >> 2;
|
||||
nalloc |= nalloc >> 4;
|
||||
nalloc |= nalloc >> 8;
|
||||
nalloc |= nalloc >> 16;
|
||||
++nalloc;
|
||||
|
||||
Q_ASSERT(nalloc > unsigned(alloc + extra));
|
||||
|
||||
return nalloc - extra;
|
||||
}
|
||||
|
||||
@ -554,7 +555,7 @@ QByteArray qUncompress(const uchar* data, int nbytes)
|
||||
}
|
||||
d.take(); // realloc was successful
|
||||
d.reset(p);
|
||||
d->offset = 0;
|
||||
d->offset = sizeof(QByteArrayData);
|
||||
|
||||
int res = ::uncompress((uchar*)d->data(), &len,
|
||||
(uchar*)data+4, nbytes-4);
|
||||
@ -576,11 +577,11 @@ QByteArray qUncompress(const uchar* data, int nbytes)
|
||||
d.take(); // realloc was successful
|
||||
d.reset(p);
|
||||
}
|
||||
d->ref = 1;
|
||||
d->ref.initializeOwned();
|
||||
d->size = len;
|
||||
d->alloc = len;
|
||||
d->capacityReserved = false;
|
||||
d->offset = 0;
|
||||
d->offset = sizeof(QByteArrayData);
|
||||
d->data()[len] = 0;
|
||||
|
||||
return QByteArray(d.take(), 0, 0);
|
||||
@ -614,10 +615,10 @@ static inline char qToLower(char c)
|
||||
return c;
|
||||
}
|
||||
|
||||
const QConstByteArrayData<1> QByteArray::shared_null = { { Q_REFCOUNT_INITIALIZER(-1),
|
||||
0, 0, 0, { 0 } }, { 0 } };
|
||||
const QConstByteArrayData<1> QByteArray::shared_empty = { { Q_REFCOUNT_INITIALIZER(-1),
|
||||
0, 0, 0, { 0 } }, { 0 } };
|
||||
const QStaticByteArrayData<1> QByteArray::shared_null = { { Q_REFCOUNT_INITIALIZE_STATIC,
|
||||
0, 0, 0, sizeof(QByteArrayData) }, { 0 } };
|
||||
const QStaticByteArrayData<1> QByteArray::shared_empty = { { Q_REFCOUNT_INITIALIZE_STATIC,
|
||||
0, 0, 0, sizeof(QByteArrayData) }, { 0 } };
|
||||
|
||||
/*!
|
||||
\class QByteArray
|
||||
@ -904,7 +905,7 @@ QByteArray &QByteArray::operator=(const char *str)
|
||||
x = const_cast<Data *>(&shared_empty.ba);
|
||||
} else {
|
||||
int len = qstrlen(str);
|
||||
if (d->ref != 1 || len > int(d->alloc) || (len < d->size && len < int(d->alloc) >> 1))
|
||||
if (d->ref.isShared() || len > int(d->alloc) || (len < d->size && len < int(d->alloc) >> 1))
|
||||
realloc(len);
|
||||
x = d;
|
||||
memcpy(x->data(), str, len + 1); // include null terminator
|
||||
@ -1289,38 +1290,16 @@ void QByteArray::chop(int n)
|
||||
\sa isEmpty()
|
||||
*/
|
||||
|
||||
/*! \fn QByteArray::QByteArray(const char *str)
|
||||
|
||||
Constructs a byte array initialized with the string \a str.
|
||||
|
||||
QByteArray makes a deep copy of the string data.
|
||||
*/
|
||||
|
||||
QByteArray::QByteArray(const char *str)
|
||||
{
|
||||
if (!str) {
|
||||
d = const_cast<Data *>(&shared_null.ba);
|
||||
} else if (!*str) {
|
||||
d = const_cast<Data *>(&shared_empty.ba);
|
||||
} else {
|
||||
int len = qstrlen(str);
|
||||
d = static_cast<Data *>(malloc(sizeof(Data) + len + 1));
|
||||
Q_CHECK_PTR(d);
|
||||
d->ref = 1;
|
||||
d->size = len;
|
||||
d->alloc = len;
|
||||
d->capacityReserved = false;
|
||||
d->offset = 0;
|
||||
memcpy(d->data(), str, len+1); // include null terminator
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a byte array containing the first \a size bytes of
|
||||
array \a data.
|
||||
|
||||
If \a data is 0, a null byte array is constructed.
|
||||
|
||||
If \a size is negative, \a data is assumed to point to a nul-terminated
|
||||
string and its length is determined dynamically. The terminating
|
||||
nul-character is not considered part of the byte array.
|
||||
|
||||
QByteArray makes a deep copy of the string data.
|
||||
|
||||
\sa fromRawData()
|
||||
@ -1330,19 +1309,23 @@ QByteArray::QByteArray(const char *data, int size)
|
||||
{
|
||||
if (!data) {
|
||||
d = const_cast<Data *>(&shared_null.ba);
|
||||
} else if (size <= 0) {
|
||||
} else {
|
||||
if (size < 0)
|
||||
size = strlen(data);
|
||||
if (!size) {
|
||||
d = const_cast<Data *>(&shared_empty.ba);
|
||||
} else {
|
||||
d = static_cast<Data *>(malloc(sizeof(Data) + size + 1));
|
||||
Q_CHECK_PTR(d);
|
||||
d->ref = 1;
|
||||
d->ref.initializeOwned();
|
||||
d->size = size;
|
||||
d->alloc = size;
|
||||
d->capacityReserved = false;
|
||||
d->offset = 0;
|
||||
d->offset = sizeof(QByteArrayData);
|
||||
memcpy(d->data(), data, size);
|
||||
d->data()[size] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -1359,11 +1342,11 @@ QByteArray::QByteArray(int size, char ch)
|
||||
} else {
|
||||
d = static_cast<Data *>(malloc(sizeof(Data) + size + 1));
|
||||
Q_CHECK_PTR(d);
|
||||
d->ref = 1;
|
||||
d->ref.initializeOwned();
|
||||
d->size = size;
|
||||
d->alloc = size;
|
||||
d->capacityReserved = false;
|
||||
d->offset = 0;
|
||||
d->offset = sizeof(QByteArrayData);
|
||||
memset(d->data(), ch, size);
|
||||
d->data()[size] = '\0';
|
||||
}
|
||||
@ -1379,11 +1362,11 @@ QByteArray::QByteArray(int size, Qt::Initialization)
|
||||
{
|
||||
d = static_cast<Data *>(malloc(sizeof(Data) + size + 1));
|
||||
Q_CHECK_PTR(d);
|
||||
d->ref = 1;
|
||||
d->ref.initializeOwned();
|
||||
d->size = size;
|
||||
d->alloc = size;
|
||||
d->capacityReserved = false;
|
||||
d->offset = 0;
|
||||
d->offset = sizeof(QByteArrayData);
|
||||
d->data()[size] = '\0';
|
||||
}
|
||||
|
||||
@ -1405,7 +1388,7 @@ void QByteArray::resize(int size)
|
||||
if (size < 0)
|
||||
size = 0;
|
||||
|
||||
if (d->offset && d->ref == 1 && size < d->size) {
|
||||
if (IS_RAW_DATA(d) && !d->ref.isShared() && size < d->size) {
|
||||
d->size = size;
|
||||
return;
|
||||
}
|
||||
@ -1426,15 +1409,15 @@ void QByteArray::resize(int size)
|
||||
//
|
||||
Data *x = static_cast<Data *>(malloc(sizeof(Data) + size + 1));
|
||||
Q_CHECK_PTR(x);
|
||||
x->ref = 1;
|
||||
x->ref.initializeOwned();
|
||||
x->size = size;
|
||||
x->alloc = size;
|
||||
x->capacityReserved = false;
|
||||
x->offset = 0;
|
||||
x->offset = sizeof(QByteArrayData);
|
||||
x->data()[size] = '\0';
|
||||
d = x;
|
||||
} else {
|
||||
if (d->ref != 1 || size > int(d->alloc)
|
||||
if (d->ref.isShared() || size > int(d->alloc)
|
||||
|| (!d->capacityReserved && size < d->size && size < int(d->alloc) >> 1))
|
||||
realloc(qAllocMore(size, sizeof(Data)));
|
||||
if (int(d->alloc) >= size) {
|
||||
@ -1465,14 +1448,14 @@ QByteArray &QByteArray::fill(char ch, int size)
|
||||
|
||||
void QByteArray::realloc(int alloc)
|
||||
{
|
||||
if (d->ref != 1 || d->offset) {
|
||||
if (d->ref.isShared() || IS_RAW_DATA(d)) {
|
||||
Data *x = static_cast<Data *>(malloc(sizeof(Data) + alloc + 1));
|
||||
Q_CHECK_PTR(x);
|
||||
x->ref = 1;
|
||||
x->ref.initializeOwned();
|
||||
x->size = qMin(alloc, d->size);
|
||||
x->alloc = alloc;
|
||||
x->capacityReserved = d->capacityReserved;
|
||||
x->offset = 0;
|
||||
x->offset = sizeof(QByteArrayData);
|
||||
::memcpy(x->data(), d->data(), x->size);
|
||||
x->data()[x->size] = '\0';
|
||||
if (!d->ref.deref())
|
||||
@ -1482,7 +1465,7 @@ void QByteArray::realloc(int alloc)
|
||||
Data *x = static_cast<Data *>(::realloc(d, sizeof(Data) + alloc + 1));
|
||||
Q_CHECK_PTR(x);
|
||||
x->alloc = alloc;
|
||||
x->offset = 0;
|
||||
x->offset = sizeof(QByteArrayData);
|
||||
d = x;
|
||||
}
|
||||
}
|
||||
@ -1504,7 +1487,7 @@ void QByteArray::expand(int i)
|
||||
QByteArray QByteArray::nulTerminated() const
|
||||
{
|
||||
// is this fromRawData?
|
||||
if (!d->offset)
|
||||
if (!IS_RAW_DATA(d))
|
||||
return *this; // no, then we're sure we're zero terminated
|
||||
|
||||
QByteArray copy(*this);
|
||||
@ -1566,7 +1549,7 @@ QByteArray &QByteArray::prepend(const char *str)
|
||||
QByteArray &QByteArray::prepend(const char *str, int len)
|
||||
{
|
||||
if (str) {
|
||||
if (d->ref != 1 || d->size + len > int(d->alloc))
|
||||
if (d->ref.isShared() || d->size + len > int(d->alloc))
|
||||
realloc(qAllocMore(d->size + len, sizeof(Data)));
|
||||
memmove(d->data()+len, d->data(), d->size);
|
||||
memcpy(d->data(), str, len);
|
||||
@ -1584,7 +1567,7 @@ QByteArray &QByteArray::prepend(const char *str, int len)
|
||||
|
||||
QByteArray &QByteArray::prepend(char ch)
|
||||
{
|
||||
if (d->ref != 1 || d->size + 1 > int(d->alloc))
|
||||
if (d->ref.isShared() || d->size + 1 > int(d->alloc))
|
||||
realloc(qAllocMore(d->size + 1, sizeof(Data)));
|
||||
memmove(d->data()+1, d->data(), d->size);
|
||||
d->data()[0] = ch;
|
||||
@ -1622,7 +1605,7 @@ QByteArray &QByteArray::append(const QByteArray &ba)
|
||||
if ((d == &shared_null.ba || d == &shared_empty.ba) && !IS_RAW_DATA(ba.d)) {
|
||||
*this = ba;
|
||||
} else if (ba.d != &shared_null.ba) {
|
||||
if (d->ref != 1 || d->size + ba.d->size > int(d->alloc))
|
||||
if (d->ref.isShared() || d->size + ba.d->size > int(d->alloc))
|
||||
realloc(qAllocMore(d->size + ba.d->size, sizeof(Data)));
|
||||
memcpy(d->data() + d->size, ba.d->data(), ba.d->size);
|
||||
d->size += ba.d->size;
|
||||
@ -1656,7 +1639,7 @@ QByteArray& QByteArray::append(const char *str)
|
||||
{
|
||||
if (str) {
|
||||
int len = qstrlen(str);
|
||||
if (d->ref != 1 || d->size + len > int(d->alloc))
|
||||
if (d->ref.isShared() || d->size + len > int(d->alloc))
|
||||
realloc(qAllocMore(d->size + len, sizeof(Data)));
|
||||
memcpy(d->data() + d->size, str, len + 1); // include null terminator
|
||||
d->size += len;
|
||||
@ -1681,7 +1664,7 @@ QByteArray &QByteArray::append(const char *str, int len)
|
||||
if (len < 0)
|
||||
len = qstrlen(str);
|
||||
if (str && len) {
|
||||
if (d->ref != 1 || d->size + len > int(d->alloc))
|
||||
if (d->ref.isShared() || d->size + len > int(d->alloc))
|
||||
realloc(qAllocMore(d->size + len, sizeof(Data)));
|
||||
memcpy(d->data() + d->size, str, len); // include null terminator
|
||||
d->size += len;
|
||||
@ -1698,7 +1681,7 @@ QByteArray &QByteArray::append(const char *str, int len)
|
||||
|
||||
QByteArray& QByteArray::append(char ch)
|
||||
{
|
||||
if (d->ref != 1 || d->size + 1 > int(d->alloc))
|
||||
if (d->ref.isShared() || d->size + 1 > int(d->alloc))
|
||||
realloc(qAllocMore(d->size + 1, sizeof(Data)));
|
||||
d->data()[d->size++] = ch;
|
||||
d->data()[d->size] = '\0';
|
||||
@ -3889,11 +3872,11 @@ QByteArray QByteArray::fromRawData(const char *data, int size)
|
||||
} else {
|
||||
x = static_cast<Data *>(malloc(sizeof(Data) + 1));
|
||||
Q_CHECK_PTR(x);
|
||||
x->ref = 1;
|
||||
x->ref.initializeOwned();
|
||||
x->size = size;
|
||||
x->alloc = 0;
|
||||
x->capacityReserved = false;
|
||||
x->offset = data - (x->d + sizeof(qptrdiff));
|
||||
x->offset = data - reinterpret_cast<char *>(x);
|
||||
}
|
||||
return QByteArray(x, 0, 0);
|
||||
}
|
||||
@ -3914,14 +3897,14 @@ QByteArray QByteArray::fromRawData(const char *data, int size)
|
||||
*/
|
||||
QByteArray &QByteArray::setRawData(const char *data, uint size)
|
||||
{
|
||||
if (d->ref != 1 || d->alloc) {
|
||||
if (d->ref.isShared() || d->alloc) {
|
||||
*this = fromRawData(data, size);
|
||||
} else {
|
||||
if (data) {
|
||||
d->size = size;
|
||||
d->offset = data - (d->d + sizeof(qptrdiff));
|
||||
d->offset = data - reinterpret_cast<char *>(d);
|
||||
} else {
|
||||
d->offset = 0;
|
||||
d->offset = sizeof(QByteArrayData);
|
||||
d->size = 0;
|
||||
*d->data() = 0;
|
||||
}
|
||||
|
@ -124,32 +124,31 @@ struct QByteArrayData
|
||||
int size;
|
||||
uint alloc : 31;
|
||||
uint capacityReserved : 1;
|
||||
union {
|
||||
qptrdiff offset; // will always work as we add/subtract from a ushort ptr
|
||||
char d[sizeof(qptrdiff)];
|
||||
};
|
||||
inline char *data() { return d + sizeof(qptrdiff) + offset; }
|
||||
inline const char *data() const { return d + sizeof(qptrdiff) + offset; }
|
||||
|
||||
qptrdiff offset;
|
||||
|
||||
inline char *data() { return reinterpret_cast<char *>(this) + offset; }
|
||||
inline const char *data() const { return reinterpret_cast<const char *>(this) + offset; }
|
||||
};
|
||||
|
||||
template<int N> struct QConstByteArrayData
|
||||
template<int N> struct QStaticByteArrayData
|
||||
{
|
||||
const QByteArrayData ba;
|
||||
const char data[N + 1];
|
||||
QByteArrayData ba;
|
||||
char data[N + 1];
|
||||
};
|
||||
|
||||
template<int N> struct QConstByteArrayDataPtr
|
||||
template<int N> struct QStaticByteArrayDataPtr
|
||||
{
|
||||
const QConstByteArrayData<N> *ptr;
|
||||
const QStaticByteArrayData<N> *ptr;
|
||||
};
|
||||
|
||||
|
||||
#if defined(Q_COMPILER_LAMBDA)
|
||||
# define QByteArrayLiteral(str) ([]() -> QConstByteArrayDataPtr<sizeof(str) - 1> { \
|
||||
# define QByteArrayLiteral(str) ([]() -> QStaticByteArrayDataPtr<sizeof(str) - 1> { \
|
||||
enum { Size = sizeof(str) - 1 }; \
|
||||
static const QConstByteArrayData<Size> qbytearray_literal = \
|
||||
{ { Q_REFCOUNT_INITIALIZER(-1), Size, 0, 0, { 0 } }, str }; \
|
||||
QConstByteArrayDataPtr<Size> holder = { &qbytearray_literal }; \
|
||||
static const QStaticByteArrayData<Size> qbytearray_literal = \
|
||||
{ { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, sizeof(QByteArrayData) }, str }; \
|
||||
QStaticByteArrayDataPtr<Size> holder = { &qbytearray_literal }; \
|
||||
return holder; }())
|
||||
|
||||
#elif defined(Q_CC_GNU)
|
||||
@ -160,9 +159,9 @@ template<int N> struct QConstByteArrayDataPtr
|
||||
# define QByteArrayLiteral(str) \
|
||||
__extension__ ({ \
|
||||
enum { Size = sizeof(str) - 1 }; \
|
||||
static const QConstByteArrayData<Size> qbytearray_literal = \
|
||||
{ { Q_REFCOUNT_INITIALIZER(-1), Size, 0, 0, { 0 } }, str }; \
|
||||
QConstByteArrayDataPtr<Size> holder = { &qbytearray_literal }; \
|
||||
static const QStaticByteArrayData<Size> qbytearray_literal = \
|
||||
{ { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, sizeof(QByteArrayData) }, str }; \
|
||||
QStaticByteArrayDataPtr<Size> holder = { &qbytearray_literal }; \
|
||||
holder; })
|
||||
#endif
|
||||
|
||||
@ -180,8 +179,7 @@ private:
|
||||
|
||||
public:
|
||||
inline QByteArray();
|
||||
QByteArray(const char *);
|
||||
QByteArray(const char *, int size);
|
||||
QByteArray(const char *, int size = -1);
|
||||
QByteArray(int size, char c);
|
||||
QByteArray(int size, Qt::Initialization);
|
||||
inline QByteArray(const QByteArray &);
|
||||
@ -379,16 +377,16 @@ public:
|
||||
bool isNull() const;
|
||||
|
||||
template <int n>
|
||||
inline QByteArray(const QConstByteArrayData<n> &dd)
|
||||
inline QByteArray(const QStaticByteArrayData<n> &dd)
|
||||
: d(const_cast<QByteArrayData *>(&dd.ba)) {}
|
||||
template <int N>
|
||||
Q_DECL_CONSTEXPR inline QByteArray(QConstByteArrayDataPtr<N> dd)
|
||||
Q_DECL_CONSTEXPR inline QByteArray(QStaticByteArrayDataPtr<N> dd)
|
||||
: d(const_cast<QByteArrayData *>(&dd.ptr->ba)) {}
|
||||
|
||||
private:
|
||||
operator QNoImplicitBoolCast() const;
|
||||
static const QConstByteArrayData<1> shared_null;
|
||||
static const QConstByteArrayData<1> shared_empty;
|
||||
static const QStaticByteArrayData<1> shared_null;
|
||||
static const QStaticByteArrayData<1> shared_empty;
|
||||
Data *d;
|
||||
QByteArray(Data *dd, int /*dummy*/, int /*dummy*/) : d(dd) {}
|
||||
void realloc(int alloc);
|
||||
@ -424,9 +422,9 @@ inline const char *QByteArray::data() const
|
||||
inline const char *QByteArray::constData() const
|
||||
{ return d->data(); }
|
||||
inline void QByteArray::detach()
|
||||
{ if (d->ref != 1 || d->offset) realloc(d->size); }
|
||||
{ if (d->ref.isShared() || (d->offset != sizeof(QByteArrayData))) realloc(d->size); }
|
||||
inline bool QByteArray::isDetached() const
|
||||
{ return d->ref == 1; }
|
||||
{ return !d->ref.isShared(); }
|
||||
inline QByteArray::QByteArray(const QByteArray &a) : d(a.d)
|
||||
{ d->ref.ref(); }
|
||||
|
||||
@ -435,7 +433,7 @@ inline int QByteArray::capacity() const
|
||||
|
||||
inline void QByteArray::reserve(int asize)
|
||||
{
|
||||
if (d->ref != 1 || asize > int(d->alloc))
|
||||
if (d->ref.isShared() || asize > int(d->alloc))
|
||||
realloc(asize);
|
||||
|
||||
if (!d->capacityReserved) {
|
||||
@ -446,11 +444,12 @@ inline void QByteArray::reserve(int asize)
|
||||
|
||||
inline void QByteArray::squeeze()
|
||||
{
|
||||
if (d->ref > 1 || d->size < int(d->alloc))
|
||||
if (d->ref.isShared() || d->size < int(d->alloc))
|
||||
realloc(d->size);
|
||||
|
||||
if (d->capacityReserved) {
|
||||
// cannot set unconditionally, since d could be the shared_null/shared_empty (which is const)
|
||||
// cannot set unconditionally, since d could be shared_null or
|
||||
// otherwise static.
|
||||
d->capacityReserved = false;
|
||||
}
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ static int countBits(int hint)
|
||||
const int MinNumBits = 4;
|
||||
|
||||
const QHashData QHashData::shared_null = {
|
||||
0, 0, Q_REFCOUNT_INITIALIZER(-1), 0, 0, MinNumBits, 0, 0, true, false, 0
|
||||
0, 0, Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, MinNumBits, 0, 0, true, false, 0
|
||||
};
|
||||
|
||||
void *QHashData::allocateNode(int nodeAlign)
|
||||
@ -196,7 +196,7 @@ QHashData *QHashData::detach_helper(void (*node_duplicate)(Node *, void *),
|
||||
d = new QHashData;
|
||||
d->fakeNext = 0;
|
||||
d->buckets = 0;
|
||||
d->ref = 1;
|
||||
d->ref.initializeOwned();
|
||||
d->size = size;
|
||||
d->nodeSize = nodeSize;
|
||||
d->userNumBits = userNumBits;
|
||||
|
@ -288,8 +288,8 @@ public:
|
||||
void reserve(int size);
|
||||
inline void squeeze() { reserve(1); }
|
||||
|
||||
inline void detach() { if (d->ref != 1) detach_helper(); }
|
||||
inline bool isDetached() const { return d->ref == 1; }
|
||||
inline void detach() { if (d->ref.isShared()) detach_helper(); }
|
||||
inline bool isDetached() const { return !d->ref.isShared(); }
|
||||
inline void setSharable(bool sharable) { if (!sharable) detach(); if (d != &QHashData::shared_null) d->sharable = sharable; }
|
||||
inline bool isSharedWith(const QHash<Key, T> &other) const { return d == other.d; }
|
||||
|
||||
|
@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE
|
||||
const QLinkedListData QLinkedListData::shared_null = {
|
||||
const_cast<QLinkedListData *>(&QLinkedListData::shared_null),
|
||||
const_cast<QLinkedListData *>(&QLinkedListData::shared_null),
|
||||
Q_REFCOUNT_INITIALIZER(-1), 0, true
|
||||
Q_REFCOUNT_INITIALIZE_STATIC, 0, true
|
||||
};
|
||||
|
||||
/*! \class QLinkedList
|
||||
|
@ -94,8 +94,8 @@ public:
|
||||
|
||||
inline int size() const { return d->size; }
|
||||
inline void detach()
|
||||
{ if (d->ref != 1) detach_helper(); }
|
||||
inline bool isDetached() const { return d->ref == 1; }
|
||||
{ if (d->ref.isShared()) detach_helper(); }
|
||||
inline bool isDetached() const { return !d->ref.isShared(); }
|
||||
inline void setSharable(bool sharable) { if (!sharable) detach(); if (d != &QLinkedListData::shared_null) d->sharable = sharable; }
|
||||
inline bool isSharedWith(const QLinkedList<T> &other) const { return d == other.d; }
|
||||
|
||||
@ -241,8 +241,6 @@ private:
|
||||
template <typename T>
|
||||
inline QLinkedList<T>::~QLinkedList()
|
||||
{
|
||||
if (!d)
|
||||
return;
|
||||
if (!d->ref.deref())
|
||||
free(d);
|
||||
}
|
||||
@ -252,7 +250,7 @@ void QLinkedList<T>::detach_helper()
|
||||
{
|
||||
union { QLinkedListData *d; Node *e; } x;
|
||||
x.d = new QLinkedListData;
|
||||
x.d->ref = 1;
|
||||
x.d->ref.initializeOwned();
|
||||
x.d->size = d->size;
|
||||
x.d->sharable = true;
|
||||
Node *original = e->n;
|
||||
@ -265,6 +263,7 @@ void QLinkedList<T>::detach_helper()
|
||||
copy = copy->n;
|
||||
} QT_CATCH(...) {
|
||||
copy->n = x.e;
|
||||
Q_ASSERT(!x.d->ref.deref()); // Don't trigger assert in free
|
||||
free(x.d);
|
||||
QT_RETHROW;
|
||||
}
|
||||
@ -281,14 +280,13 @@ void QLinkedList<T>::free(QLinkedListData *x)
|
||||
{
|
||||
Node *y = reinterpret_cast<Node*>(x);
|
||||
Node *i = y->n;
|
||||
if (x->ref == 0) {
|
||||
while(i != y) {
|
||||
Q_ASSERT(x->ref.atomic.load() == 0);
|
||||
while (i != y) {
|
||||
Node *n = i;
|
||||
i = i->n;
|
||||
delete n;
|
||||
}
|
||||
delete x;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE
|
||||
the number of elements in the list.
|
||||
*/
|
||||
|
||||
const QListData::Data QListData::shared_null = { Q_REFCOUNT_INITIALIZER(-1), 0, 0, 0, true, { 0 } };
|
||||
const QListData::Data QListData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, { 0 } };
|
||||
|
||||
static int grow(int size)
|
||||
{
|
||||
@ -87,8 +87,7 @@ QListData::Data *QListData::detach_grow(int *idx, int num)
|
||||
Data* t = static_cast<Data *>(::malloc(DataHeaderSize + alloc * sizeof(void *)));
|
||||
Q_CHECK_PTR(t);
|
||||
|
||||
t->ref = 1;
|
||||
t->sharable = true;
|
||||
t->ref.initializeOwned();
|
||||
t->alloc = alloc;
|
||||
// The space reservation algorithm's optimization is biased towards appending:
|
||||
// Something which looks like an append will put the data at the beginning,
|
||||
@ -129,8 +128,7 @@ QListData::Data *QListData::detach(int alloc)
|
||||
Data* t = static_cast<Data *>(::malloc(DataHeaderSize + alloc * sizeof(void *)));
|
||||
Q_CHECK_PTR(t);
|
||||
|
||||
t->ref = 1;
|
||||
t->sharable = true;
|
||||
t->ref.initializeOwned();
|
||||
t->alloc = alloc;
|
||||
if (!alloc) {
|
||||
t->begin = 0;
|
||||
@ -146,7 +144,7 @@ QListData::Data *QListData::detach(int alloc)
|
||||
|
||||
void QListData::realloc(int alloc)
|
||||
{
|
||||
Q_ASSERT(d->ref == 1);
|
||||
Q_ASSERT(!d->ref.isShared());
|
||||
Data *x = static_cast<Data *>(::realloc(d, DataHeaderSize + alloc * sizeof(void *)));
|
||||
Q_CHECK_PTR(x);
|
||||
|
||||
@ -159,7 +157,7 @@ void QListData::realloc(int alloc)
|
||||
// ensures that enough space is available to append n elements
|
||||
void **QListData::append(int n)
|
||||
{
|
||||
Q_ASSERT(d->ref == 1);
|
||||
Q_ASSERT(!d->ref.isShared());
|
||||
int e = d->end;
|
||||
if (e + n > d->alloc) {
|
||||
int b = d->begin;
|
||||
@ -190,7 +188,7 @@ void **QListData::append(const QListData& l)
|
||||
|
||||
void **QListData::prepend()
|
||||
{
|
||||
Q_ASSERT(d->ref == 1);
|
||||
Q_ASSERT(!d->ref.isShared());
|
||||
if (d->begin == 0) {
|
||||
if (d->end >= d->alloc / 3)
|
||||
realloc(grow(d->alloc + 1));
|
||||
@ -208,7 +206,7 @@ void **QListData::prepend()
|
||||
|
||||
void **QListData::insert(int i)
|
||||
{
|
||||
Q_ASSERT(d->ref == 1);
|
||||
Q_ASSERT(!d->ref.isShared());
|
||||
if (i <= 0)
|
||||
return prepend();
|
||||
int size = d->end - d->begin;
|
||||
@ -247,7 +245,7 @@ void **QListData::insert(int i)
|
||||
|
||||
void QListData::remove(int i)
|
||||
{
|
||||
Q_ASSERT(d->ref == 1);
|
||||
Q_ASSERT(!d->ref.isShared());
|
||||
i += d->begin;
|
||||
if (i - d->begin < d->end - i) {
|
||||
if (int offset = i - d->begin)
|
||||
@ -262,7 +260,7 @@ void QListData::remove(int i)
|
||||
|
||||
void QListData::remove(int i, int n)
|
||||
{
|
||||
Q_ASSERT(d->ref == 1);
|
||||
Q_ASSERT(!d->ref.isShared());
|
||||
i += d->begin;
|
||||
int middle = i + n/2;
|
||||
if (middle - d->begin < d->end - middle) {
|
||||
@ -278,7 +276,7 @@ void QListData::remove(int i, int n)
|
||||
|
||||
void QListData::move(int from, int to)
|
||||
{
|
||||
Q_ASSERT(d->ref == 1);
|
||||
Q_ASSERT(!d->ref.isShared());
|
||||
if (from == to)
|
||||
return;
|
||||
|
||||
@ -318,7 +316,7 @@ void QListData::move(int from, int to)
|
||||
|
||||
void **QListData::erase(void **xi)
|
||||
{
|
||||
Q_ASSERT(d->ref == 1);
|
||||
Q_ASSERT(!d->ref.isShared());
|
||||
int i = xi - (d->array + d->begin);
|
||||
remove(i);
|
||||
return d->array + d->begin + i;
|
||||
|
@ -71,7 +71,6 @@ struct Q_CORE_EXPORT QListData {
|
||||
struct Data {
|
||||
QtPrivate::RefCount ref;
|
||||
int alloc, begin, end;
|
||||
uint sharable : 1;
|
||||
void *array[1];
|
||||
};
|
||||
enum { DataHeaderSize = sizeof(Data) - sizeof(void *) };
|
||||
@ -114,7 +113,7 @@ class QList
|
||||
|
||||
public:
|
||||
inline QList() : d(const_cast<QListData::Data *>(&QListData::shared_null)) { }
|
||||
inline QList(const QList<T> &l) : d(l.d) { d->ref.ref(); if (!d->sharable) detach_helper(); }
|
||||
QList(const QList<T> &l);
|
||||
~QList();
|
||||
QList<T> &operator=(const QList<T> &l);
|
||||
#ifdef Q_COMPILER_RVALUE_REFS
|
||||
@ -132,17 +131,25 @@ public:
|
||||
|
||||
inline int size() const { return p.size(); }
|
||||
|
||||
inline void detach() { if (d->ref != 1) detach_helper(); }
|
||||
inline void detach() { if (d->ref.isShared()) detach_helper(); }
|
||||
|
||||
inline void detachShared()
|
||||
{
|
||||
// The "this->" qualification is needed for GCCE.
|
||||
if (d->ref != 1 && this->d != &QListData::shared_null)
|
||||
if (d->ref.isShared() && this->d != &QListData::shared_null)
|
||||
detach_helper();
|
||||
}
|
||||
|
||||
inline bool isDetached() const { return d->ref == 1; }
|
||||
inline void setSharable(bool sharable) { if (!sharable) detach(); if (d != &QListData::shared_null) d->sharable = sharable; }
|
||||
inline bool isDetached() const { return !d->ref.isShared(); }
|
||||
inline void setSharable(bool sharable)
|
||||
{
|
||||
if (sharable == d->ref.isSharable())
|
||||
return;
|
||||
if (!sharable)
|
||||
detach();
|
||||
if (d != &QListData::shared_null)
|
||||
d->ref.setSharable(sharable);
|
||||
}
|
||||
inline bool isSharedWith(const QList<T> &other) const { return d == other.d; }
|
||||
|
||||
inline bool isEmpty() const { return p.isEmpty(); }
|
||||
@ -419,13 +426,8 @@ template <typename T>
|
||||
Q_INLINE_TEMPLATE QList<T> &QList<T>::operator=(const QList<T> &l)
|
||||
{
|
||||
if (d != l.d) {
|
||||
QListData::Data *o = l.d;
|
||||
o->ref.ref();
|
||||
if (!d->ref.deref())
|
||||
dealloc(d);
|
||||
d = o;
|
||||
if (!d->sharable)
|
||||
detach_helper();
|
||||
QList<T> tmp(l);
|
||||
tmp.swap(*this);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@ -478,7 +480,7 @@ template <typename T>
|
||||
Q_OUTOFLINE_TEMPLATE void QList<T>::reserve(int alloc)
|
||||
{
|
||||
if (d->alloc < alloc) {
|
||||
if (d->ref != 1)
|
||||
if (d->ref.isShared())
|
||||
detach_helper(alloc);
|
||||
else
|
||||
p.realloc(alloc);
|
||||
@ -488,7 +490,7 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::reserve(int alloc)
|
||||
template <typename T>
|
||||
Q_OUTOFLINE_TEMPLATE void QList<T>::append(const T &t)
|
||||
{
|
||||
if (d->ref != 1) {
|
||||
if (d->ref.isShared()) {
|
||||
Node *n = detach_helper_grow(INT_MAX, 1);
|
||||
QT_TRY {
|
||||
node_construct(n, t);
|
||||
@ -522,7 +524,7 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::append(const T &t)
|
||||
template <typename T>
|
||||
inline void QList<T>::prepend(const T &t)
|
||||
{
|
||||
if (d->ref != 1) {
|
||||
if (d->ref.isShared()) {
|
||||
Node *n = detach_helper_grow(0, 1);
|
||||
QT_TRY {
|
||||
node_construct(n, t);
|
||||
@ -556,7 +558,7 @@ inline void QList<T>::prepend(const T &t)
|
||||
template <typename T>
|
||||
inline void QList<T>::insert(int i, const T &t)
|
||||
{
|
||||
if (d->ref != 1) {
|
||||
if (d->ref.isShared()) {
|
||||
Node *n = detach_helper_grow(i, 1);
|
||||
QT_TRY {
|
||||
node_construct(n, t);
|
||||
@ -707,6 +709,28 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper()
|
||||
detach_helper(d->alloc);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Q_OUTOFLINE_TEMPLATE QList<T>::QList(const QList<T> &l)
|
||||
: d(l.d)
|
||||
{
|
||||
if (!d->ref.ref()) {
|
||||
p.detach(d->alloc);
|
||||
|
||||
struct Cleanup
|
||||
{
|
||||
Cleanup(QListData::Data *d) : d_(d) {}
|
||||
~Cleanup() { if (d_) qFree(d_); }
|
||||
|
||||
QListData::Data *d_;
|
||||
} tryCatch(d);
|
||||
|
||||
node_copy(reinterpret_cast<Node *>(p.begin()),
|
||||
reinterpret_cast<Node *>(p.end()),
|
||||
reinterpret_cast<Node *>(l.p.begin()));
|
||||
tryCatch.d_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Q_OUTOFLINE_TEMPLATE QList<T>::~QList()
|
||||
{
|
||||
@ -802,7 +826,7 @@ Q_OUTOFLINE_TEMPLATE QList<T> &QList<T>::operator+=(const QList<T> &l)
|
||||
if (isEmpty()) {
|
||||
*this = l;
|
||||
} else {
|
||||
Node *n = (d->ref != 1)
|
||||
Node *n = (d->ref.isShared())
|
||||
? detach_helper_grow(INT_MAX, l.size())
|
||||
: reinterpret_cast<Node *>(p.append(l.p));
|
||||
QT_TRY {
|
||||
|
@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE
|
||||
const QMapData QMapData::shared_null = {
|
||||
const_cast<QMapData *>(&shared_null),
|
||||
{ const_cast<QMapData *>(&shared_null), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
Q_REFCOUNT_INITIALIZER(-1), 0, 0, 0, false, true, false, 0
|
||||
Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, false, true, false, 0
|
||||
};
|
||||
|
||||
QMapData *QMapData::createData(int alignment)
|
||||
@ -63,7 +63,7 @@ QMapData *QMapData::createData(int alignment)
|
||||
Node *e = reinterpret_cast<Node *>(d);
|
||||
e->backward = e;
|
||||
e->forward[0] = e;
|
||||
d->ref = 1;
|
||||
d->ref.initializeOwned();
|
||||
d->topLevel = 0;
|
||||
d->size = 0;
|
||||
d->randomBits = 0;
|
||||
|
@ -179,7 +179,7 @@ public:
|
||||
inline QMap() : d(const_cast<QMapData *>(&QMapData::shared_null)) { }
|
||||
inline QMap(const QMap<Key, T> &other) : d(other.d)
|
||||
{ d->ref.ref(); if (!d->sharable) detach(); }
|
||||
inline ~QMap() { if (!d) return; if (!d->ref.deref()) freeData(d); }
|
||||
inline ~QMap() { if (!d->ref.deref()) freeData(d); }
|
||||
|
||||
QMap<Key, T> &operator=(const QMap<Key, T> &other);
|
||||
#ifdef Q_COMPILER_RVALUE_REFS
|
||||
@ -199,8 +199,8 @@ public:
|
||||
|
||||
inline bool isEmpty() const { return d->size == 0; }
|
||||
|
||||
inline void detach() { if (d->ref != 1) detach_helper(); }
|
||||
inline bool isDetached() const { return d->ref == 1; }
|
||||
inline void detach() { if (d->ref.isShared()) detach_helper(); }
|
||||
inline bool isDetached() const { return !d->ref.isShared(); }
|
||||
inline void setSharable(bool sharable) { if (!sharable) detach(); if (d != &QMapData::shared_null) d->sharable = sharable; }
|
||||
inline bool isSharedWith(const QMap<Key, T> &other) const { return d == other.d; }
|
||||
inline void setInsertInOrder(bool ordered) { if (ordered) detach(); if (d != &QMapData::shared_null) d->insertInOrder = ordered; }
|
||||
|
@ -55,37 +55,61 @@ namespace QtPrivate
|
||||
class RefCount
|
||||
{
|
||||
public:
|
||||
inline void ref() {
|
||||
if (atomic.load() > 0)
|
||||
inline bool ref() {
|
||||
int count = atomic.load();
|
||||
if (count == 0) // !isSharable
|
||||
return false;
|
||||
if (count != -1) // !isStatic
|
||||
atomic.ref();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool deref() {
|
||||
if (atomic.load() <= 0)
|
||||
int count = atomic.load();
|
||||
if (count == 0) // !isSharable
|
||||
return false;
|
||||
if (count == -1) // isStatic
|
||||
return true;
|
||||
return atomic.deref();
|
||||
}
|
||||
|
||||
inline bool operator==(int value) const
|
||||
{ return atomic.load() == value; }
|
||||
inline bool operator!=(int value) const
|
||||
{ return atomic.load() != value; }
|
||||
inline bool operator!() const
|
||||
{ return !atomic.load(); }
|
||||
inline operator int() const
|
||||
{ return atomic.load(); }
|
||||
inline RefCount &operator=(int value)
|
||||
{ atomic.store(value); return *this; }
|
||||
inline RefCount &operator=(const RefCount &other)
|
||||
{ atomic.store(other.atomic.load()); return *this; }
|
||||
bool setSharable(bool sharable)
|
||||
{
|
||||
Q_ASSERT(!isShared());
|
||||
if (sharable)
|
||||
return atomic.testAndSetRelaxed(0, 1);
|
||||
else
|
||||
return atomic.testAndSetRelaxed(1, 0);
|
||||
}
|
||||
|
||||
bool isStatic() const
|
||||
{
|
||||
// Persistent object, never deleted
|
||||
return atomic.load() == -1;
|
||||
}
|
||||
|
||||
bool isSharable() const
|
||||
{
|
||||
// Sharable === Shared ownership.
|
||||
return atomic.load() != 0;
|
||||
}
|
||||
|
||||
bool isShared() const
|
||||
{
|
||||
int count = atomic.load();
|
||||
return (count != 1) && (count != 0);
|
||||
}
|
||||
|
||||
void initializeOwned() { atomic.store(1); }
|
||||
void initializeUnsharable() { atomic.store(0); }
|
||||
|
||||
QBasicAtomicInt atomic;
|
||||
};
|
||||
|
||||
#define Q_REFCOUNT_INITIALIZER(a) { Q_BASIC_ATOMIC_INITIALIZER(a) }
|
||||
|
||||
}
|
||||
|
||||
#define Q_REFCOUNT_INITIALIZE_STATIC { Q_BASIC_ATOMIC_INITIALIZER(-1) }
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
QT_END_HEADER
|
||||
|
@ -94,6 +94,8 @@
|
||||
#define ULLONG_MAX quint64_C(18446744073709551615)
|
||||
#endif
|
||||
|
||||
#define IS_RAW_DATA(d) ((d)->offset != sizeof(QStringData))
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
#ifdef QT_USE_ICU
|
||||
@ -793,8 +795,8 @@ const QString::Null QString::null = { };
|
||||
\sa split()
|
||||
*/
|
||||
|
||||
const QConstStringData<1> QString::shared_null = { { Q_REFCOUNT_INITIALIZER(-1), 0, 0, false, { 0 } }, { 0 } };
|
||||
const QConstStringData<1> QString::shared_empty = { { Q_REFCOUNT_INITIALIZER(-1), 0, 0, false, { 0 } }, { 0 } };
|
||||
const QStaticStringData<1> QString::shared_null = { { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, false, sizeof(QStringData) }, { 0 } };
|
||||
const QStaticStringData<1> QString::shared_empty = { { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, false, sizeof(QStringData) }, { 0 } };
|
||||
|
||||
int QString::grow(int size)
|
||||
{
|
||||
@ -1015,62 +1017,43 @@ int QString::toUcs4_helper(const ushort *uc, int length, uint *out)
|
||||
Constructs a string initialized with the first \a size characters
|
||||
of the QChar array \a unicode.
|
||||
|
||||
If \a unicode is 0, a null string is constructed.
|
||||
|
||||
If \a size is negative, \a unicode is assumed to point to a nul-terminated
|
||||
array and its length is determined dynamically. The terminating
|
||||
nul-character is not considered part of the string.
|
||||
|
||||
QString makes a deep copy of the string data. The unicode data is copied as
|
||||
is and the Byte Order Mark is preserved if present.
|
||||
|
||||
\sa fromRawData()
|
||||
*/
|
||||
QString::QString(const QChar *unicode, int size)
|
||||
{
|
||||
if (!unicode) {
|
||||
d = const_cast<Data *>(&shared_null.str);
|
||||
} else if (size <= 0) {
|
||||
d = const_cast<Data *>(&shared_empty.str);
|
||||
} else {
|
||||
d = (Data*) ::malloc(sizeof(Data)+(size+1)*sizeof(QChar));
|
||||
Q_CHECK_PTR(d);
|
||||
d->ref = 1;
|
||||
d->size = size;
|
||||
d->alloc = (uint) size;
|
||||
d->capacityReserved = false;
|
||||
d->offset = 0;
|
||||
memcpy(d->data(), unicode, size * sizeof(QChar));
|
||||
d->data()[size] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 4.7
|
||||
|
||||
Constructs a string initialized with the characters of the QChar array
|
||||
\a unicode, which must be terminated with a 0.
|
||||
|
||||
QString makes a deep copy of the string data. The unicode data is copied as
|
||||
is and the Byte Order Mark is preserved if present.
|
||||
*/
|
||||
QString::QString(const QChar *unicode)
|
||||
{
|
||||
if (!unicode) {
|
||||
d = const_cast<Data *>(&shared_null.str);
|
||||
} else {
|
||||
int size = 0;
|
||||
if (size < 0) {
|
||||
size = 0;
|
||||
while (unicode[size] != 0)
|
||||
++size;
|
||||
}
|
||||
if (!size) {
|
||||
d = const_cast<Data *>(&shared_empty.str);
|
||||
} else {
|
||||
d = (Data*) ::malloc(sizeof(Data)+(size+1)*sizeof(QChar));
|
||||
Q_CHECK_PTR(d);
|
||||
d->ref = 1;
|
||||
d->ref.initializeOwned();
|
||||
d->size = size;
|
||||
d->alloc = (uint) size;
|
||||
d->capacityReserved = false;
|
||||
d->offset = 0;
|
||||
d->offset = sizeof(QStringData);
|
||||
memcpy(d->data(), unicode, size * sizeof(QChar));
|
||||
d->data()[size] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Constructs a string of the given \a size with every character set
|
||||
to \a ch.
|
||||
@ -1084,11 +1067,11 @@ QString::QString(int size, QChar ch)
|
||||
} else {
|
||||
d = (Data*) ::malloc(sizeof(Data)+(size+1)*sizeof(QChar));
|
||||
Q_CHECK_PTR(d);
|
||||
d->ref = 1;
|
||||
d->ref.initializeOwned();
|
||||
d->size = size;
|
||||
d->alloc = (uint) size;
|
||||
d->capacityReserved = false;
|
||||
d->offset = 0;
|
||||
d->offset = sizeof(QStringData);
|
||||
d->data()[size] = '\0';
|
||||
ushort *i = d->data() + size;
|
||||
ushort *b = d->data();
|
||||
@ -1108,11 +1091,11 @@ QString::QString(int size, Qt::Initialization)
|
||||
{
|
||||
d = (Data*) ::malloc(sizeof(Data)+(size+1)*sizeof(QChar));
|
||||
Q_CHECK_PTR(d);
|
||||
d->ref = 1;
|
||||
d->ref.initializeOwned();
|
||||
d->size = size;
|
||||
d->alloc = (uint) size;
|
||||
d->capacityReserved = false;
|
||||
d->offset = 0;
|
||||
d->offset = sizeof(QStringData);
|
||||
d->data()[size] = '\0';
|
||||
}
|
||||
|
||||
@ -1130,11 +1113,11 @@ QString::QString(QChar ch)
|
||||
{
|
||||
d = (Data *) ::malloc(sizeof(Data) + 2*sizeof(QChar));
|
||||
Q_CHECK_PTR(d);
|
||||
d->ref = 1;
|
||||
d->ref.initializeOwned();
|
||||
d->size = 1;
|
||||
d->alloc = 1;
|
||||
d->capacityReserved = false;
|
||||
d->offset = 0;
|
||||
d->offset = sizeof(QStringData);
|
||||
d->data()[0] = ch.unicode();
|
||||
d->data()[1] = '\0';
|
||||
}
|
||||
@ -1232,7 +1215,7 @@ void QString::resize(int size)
|
||||
if (size < 0)
|
||||
size = 0;
|
||||
|
||||
if (d->offset && d->ref == 1 && size < d->size) {
|
||||
if (IS_RAW_DATA(d) && !d->ref.isShared() && size < d->size) {
|
||||
d->size = size;
|
||||
return;
|
||||
}
|
||||
@ -1243,7 +1226,7 @@ void QString::resize(int size)
|
||||
QString::free(d);
|
||||
d = x;
|
||||
} else {
|
||||
if (d->ref != 1 || size > int(d->alloc) ||
|
||||
if (d->ref.isShared() || size > int(d->alloc) ||
|
||||
(!d->capacityReserved && size < d->size && size < int(d->alloc) >> 1))
|
||||
realloc(grow(size));
|
||||
if (int(d->alloc) >= size) {
|
||||
@ -1306,14 +1289,14 @@ void QString::resize(int size)
|
||||
// ### Qt 5: rename reallocData() to avoid confusion. 197625
|
||||
void QString::realloc(int alloc)
|
||||
{
|
||||
if (d->ref != 1 || d->offset) {
|
||||
if (d->ref.isShared() || IS_RAW_DATA(d)) {
|
||||
Data *x = static_cast<Data *>(::malloc(sizeof(Data) + (alloc+1) * sizeof(QChar)));
|
||||
Q_CHECK_PTR(x);
|
||||
x->ref = 1;
|
||||
x->ref.initializeOwned();
|
||||
x->size = qMin(alloc, d->size);
|
||||
x->alloc = (uint) alloc;
|
||||
x->capacityReserved = d->capacityReserved;
|
||||
x->offset =0;
|
||||
x->offset = sizeof(QStringData);
|
||||
::memcpy(x->data(), d->data(), x->size * sizeof(QChar));
|
||||
x->data()[x->size] = 0;
|
||||
if (!d->ref.deref())
|
||||
@ -1324,7 +1307,7 @@ void QString::realloc(int alloc)
|
||||
Q_CHECK_PTR(p);
|
||||
d = p;
|
||||
d->alloc = alloc;
|
||||
d->offset = 0;
|
||||
d->offset = sizeof(QStringData);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1536,7 +1519,7 @@ QString &QString::append(const QString &str)
|
||||
if (d == &shared_null.str) {
|
||||
operator=(str);
|
||||
} else {
|
||||
if (d->ref != 1 || d->size + str.d->size > int(d->alloc))
|
||||
if (d->ref.isShared() || d->size + str.d->size > int(d->alloc))
|
||||
realloc(grow(d->size + str.d->size));
|
||||
memcpy(d->data() + d->size, str.d->data(), str.d->size * sizeof(QChar));
|
||||
d->size += str.d->size;
|
||||
@ -1556,7 +1539,7 @@ QString &QString::append(const QLatin1String &str)
|
||||
const uchar *s = (const uchar *)str.latin1();
|
||||
if (s) {
|
||||
int len = str.size();
|
||||
if (d->ref != 1 || d->size + len > int(d->alloc))
|
||||
if (d->ref.isShared() || d->size + len > int(d->alloc))
|
||||
realloc(grow(d->size + len));
|
||||
ushort *i = d->data() + d->size;
|
||||
while ((*i++ = *s++))
|
||||
@ -1599,7 +1582,7 @@ QString &QString::append(const QLatin1String &str)
|
||||
*/
|
||||
QString &QString::append(QChar ch)
|
||||
{
|
||||
if (d->ref != 1 || d->size + 1 > int(d->alloc))
|
||||
if (d->ref.isShared() || d->size + 1 > int(d->alloc))
|
||||
realloc(grow(d->size + 1));
|
||||
d->data()[d->size++] = ch.unicode();
|
||||
d->data()[d->size] = '\0';
|
||||
@ -3390,15 +3373,11 @@ QString QString::right(int n) const
|
||||
|
||||
QString QString::mid(int position, int n) const
|
||||
{
|
||||
if (d == &shared_null.str || position > d->size)
|
||||
if (position > d->size)
|
||||
return QString();
|
||||
if (n < 0)
|
||||
n = d->size - position;
|
||||
if (position < 0) {
|
||||
n += position;
|
||||
if (position < 0)
|
||||
position = 0;
|
||||
}
|
||||
if (n + position > d->size)
|
||||
if (n < 0 || n > d->size - position)
|
||||
n = d->size - position;
|
||||
if (position == 0 && n == d->size)
|
||||
return *this;
|
||||
@ -3753,11 +3732,11 @@ QString::Data *QString::fromLatin1_helper(const char *str, int size)
|
||||
size = qstrlen(str);
|
||||
d = static_cast<Data *>(::malloc(sizeof(Data) + (size+1) * sizeof(QChar)));
|
||||
Q_CHECK_PTR(d);
|
||||
d->ref = 1;
|
||||
d->ref.initializeOwned();
|
||||
d->size = size;
|
||||
d->alloc = (uint) size;
|
||||
d->capacityReserved = false;
|
||||
d->offset = 0;
|
||||
d->offset = sizeof(QStringData);
|
||||
d->data()[size] = '\0';
|
||||
ushort *dst = d->data();
|
||||
/* SIMD:
|
||||
@ -4765,7 +4744,7 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1,
|
||||
|
||||
const ushort *QString::utf16() const
|
||||
{
|
||||
if (d->offset)
|
||||
if (IS_RAW_DATA(d))
|
||||
const_cast<QString*>(this)->realloc(); // ensure '\\0'-termination for ::fromRawData strings
|
||||
return d->data();
|
||||
}
|
||||
@ -7067,11 +7046,11 @@ QString QString::fromRawData(const QChar *unicode, int size)
|
||||
} else {
|
||||
x = static_cast<Data *>(::malloc(sizeof(Data) + sizeof(ushort)));
|
||||
Q_CHECK_PTR(x);
|
||||
x->ref = 1;
|
||||
x->ref.initializeOwned();
|
||||
x->size = size;
|
||||
x->alloc = 0;
|
||||
x->capacityReserved = false;
|
||||
x->offset = (const ushort *)unicode - (x->d + sizeof(qptrdiff)/sizeof(ushort));
|
||||
x->offset = reinterpret_cast<const char *>(unicode) - reinterpret_cast<char *>(x);
|
||||
}
|
||||
return QString(x, 0);
|
||||
}
|
||||
@ -7092,14 +7071,14 @@ QString QString::fromRawData(const QChar *unicode, int size)
|
||||
*/
|
||||
QString &QString::setRawData(const QChar *unicode, int size)
|
||||
{
|
||||
if (d->ref != 1 || d->alloc) {
|
||||
if (d->ref.isShared() || d->alloc) {
|
||||
*this = fromRawData(unicode, size);
|
||||
} else {
|
||||
if (unicode) {
|
||||
d->size = size;
|
||||
d->offset = (const ushort *)unicode - (d->d + sizeof(qptrdiff)/sizeof(ushort));
|
||||
d->offset = reinterpret_cast<const char *>(unicode) - reinterpret_cast<char *>(d);
|
||||
} else {
|
||||
d->offset = 0;
|
||||
d->offset = sizeof(QStringData);
|
||||
d->size = 0;
|
||||
}
|
||||
}
|
||||
@ -8059,15 +8038,11 @@ QStringRef QString::rightRef(int n) const
|
||||
|
||||
QStringRef QString::midRef(int position, int n) const
|
||||
{
|
||||
if (d == &shared_null.str || position > d->size)
|
||||
if (position > d->size)
|
||||
return QStringRef();
|
||||
if (n < 0)
|
||||
n = d->size - position;
|
||||
if (position < 0) {
|
||||
n += position;
|
||||
if (position < 0)
|
||||
position = 0;
|
||||
}
|
||||
if (n + position > d->size)
|
||||
if (n < 0 || n > d->size - position)
|
||||
n = d->size - position;
|
||||
return QStringRef(this, position, n);
|
||||
}
|
||||
|
@ -75,25 +75,24 @@ struct QStringData {
|
||||
int size;
|
||||
uint alloc : 31;
|
||||
uint capacityReserved : 1;
|
||||
union {
|
||||
qptrdiff offset; // will always work as we add/subtract from a ushort ptr
|
||||
ushort d[sizeof(qptrdiff)/sizeof(ushort)];
|
||||
};
|
||||
inline ushort *data() { return d + sizeof(qptrdiff)/sizeof(ushort) + offset; }
|
||||
inline const ushort *data() const { return d + sizeof(qptrdiff)/sizeof(ushort) + offset; }
|
||||
|
||||
qptrdiff offset;
|
||||
|
||||
inline ushort *data() { return reinterpret_cast<ushort *>(reinterpret_cast<char *>(this) + offset); }
|
||||
inline const ushort *data() const { return reinterpret_cast<const ushort *>(reinterpret_cast<const char *>(this) + offset); }
|
||||
};
|
||||
|
||||
template<int N> struct QConstStringData;
|
||||
template<int N> struct QConstStringDataPtr
|
||||
template<int N> struct QStaticStringData;
|
||||
template<int N> struct QStaticStringDataPtr
|
||||
{
|
||||
const QConstStringData<N> *ptr;
|
||||
const QStaticStringData<N> *ptr;
|
||||
};
|
||||
|
||||
#if defined(Q_COMPILER_UNICODE_STRINGS)
|
||||
template<int N> struct QConstStringData
|
||||
template<int N> struct QStaticStringData
|
||||
{
|
||||
const QStringData str;
|
||||
const char16_t data[N + 1];
|
||||
QStringData str;
|
||||
char16_t data[N + 1];
|
||||
};
|
||||
|
||||
#define QT_UNICODE_LITERAL_II(str) u"" str
|
||||
@ -102,10 +101,10 @@ template<int N> struct QConstStringData
|
||||
|| (defined(__SIZEOF_WCHAR_T__) && __SIZEOF_WCHAR_T__ == 2) \
|
||||
|| (!defined(__SIZEOF_WCHAR_T__) && defined(WCHAR_MAX) && (WCHAR_MAX - 0 < 65536))
|
||||
// wchar_t is 2 bytes
|
||||
template<int N> struct QConstStringData
|
||||
template<int N> struct QStaticStringData
|
||||
{
|
||||
const QStringData str;
|
||||
const wchar_t data[N + 1];
|
||||
QStringData str;
|
||||
wchar_t data[N + 1];
|
||||
};
|
||||
|
||||
#if defined(Q_CC_MSVC)
|
||||
@ -115,21 +114,21 @@ template<int N> struct QConstStringData
|
||||
#endif
|
||||
|
||||
#else
|
||||
template<int N> struct QConstStringData
|
||||
template<int N> struct QStaticStringData
|
||||
{
|
||||
const QStringData str;
|
||||
const ushort data[N + 1];
|
||||
QStringData str;
|
||||
ushort data[N + 1];
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(QT_UNICODE_LITERAL_II)
|
||||
# define QT_UNICODE_LITERAL(str) QT_UNICODE_LITERAL_II(str)
|
||||
# if defined(Q_COMPILER_LAMBDA)
|
||||
# define QStringLiteral(str) ([]() -> QConstStringDataPtr<sizeof(QT_UNICODE_LITERAL(str))/2 - 1> { \
|
||||
# define QStringLiteral(str) ([]() -> QStaticStringDataPtr<sizeof(QT_UNICODE_LITERAL(str))/2 - 1> { \
|
||||
enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
|
||||
static const QConstStringData<Size> qstring_literal = \
|
||||
{ { Q_REFCOUNT_INITIALIZER(-1), Size, 0, 0, { 0 } }, QT_UNICODE_LITERAL(str) }; \
|
||||
QConstStringDataPtr<Size> holder = { &qstring_literal }; \
|
||||
static const QStaticStringData<Size> qstring_literal = \
|
||||
{ { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, sizeof(QStringData) }, QT_UNICODE_LITERAL(str) }; \
|
||||
QStaticStringDataPtr<Size> holder = { &qstring_literal }; \
|
||||
return holder; }())
|
||||
|
||||
# elif defined(Q_CC_GNU)
|
||||
@ -140,9 +139,9 @@ template<int N> struct QConstStringData
|
||||
# define QStringLiteral(str) \
|
||||
__extension__ ({ \
|
||||
enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
|
||||
static const QConstStringData<Size> qstring_literal = \
|
||||
{ { Q_REFCOUNT_INITIALIZER(-1), Size, 0, 0, { 0 } }, QT_UNICODE_LITERAL(str) }; \
|
||||
QConstStringDataPtr<Size> holder = { &qstring_literal }; \
|
||||
static const QStaticStringData<Size> qstring_literal = \
|
||||
{ { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, sizeof(QStringData) }, QT_UNICODE_LITERAL(str) }; \
|
||||
QStaticStringDataPtr<Size> holder = { &qstring_literal }; \
|
||||
holder; })
|
||||
# endif
|
||||
#endif
|
||||
@ -160,8 +159,7 @@ public:
|
||||
typedef QStringData Data;
|
||||
|
||||
inline QString();
|
||||
QString(const QChar *unicode, int size); // Qt5: don't cap size < 0
|
||||
explicit QString(const QChar *unicode); // Qt5: merge with the above
|
||||
explicit QString(const QChar *unicode, int size = -1);
|
||||
QString(QChar c);
|
||||
QString(int size, QChar c);
|
||||
inline QString(const QLatin1String &latin1);
|
||||
@ -340,7 +338,7 @@ public:
|
||||
inline QString &prepend(const QLatin1String &s) { return insert(0, s); }
|
||||
|
||||
inline QString &operator+=(QChar c) {
|
||||
if (d->ref != 1 || d->size + 1 > int(d->alloc))
|
||||
if (d->ref.isShared() || d->size + 1 > int(d->alloc))
|
||||
realloc(grow(d->size + 1));
|
||||
d->data()[d->size++] = c.unicode();
|
||||
d->data()[d->size] = '\0';
|
||||
@ -592,9 +590,9 @@ public:
|
||||
|
||||
QString(int size, Qt::Initialization);
|
||||
template <int n>
|
||||
inline QString(const QConstStringData<n> &dd) : d(const_cast<QStringData *>(&dd.str)) {}
|
||||
inline QString(const QStaticStringData<n> &dd) : d(const_cast<QStringData *>(&dd.str)) {}
|
||||
template <int N>
|
||||
Q_DECL_CONSTEXPR inline QString(QConstStringDataPtr<N> dd) : d(const_cast<QStringData *>(&dd.ptr->str)) {}
|
||||
Q_DECL_CONSTEXPR inline QString(QStaticStringDataPtr<N> dd) : d(const_cast<QStringData *>(&dd.ptr->str)) {}
|
||||
|
||||
private:
|
||||
#if defined(QT_NO_CAST_FROM_ASCII) && !defined(Q_NO_DECLARED_NOT_DEFINED)
|
||||
@ -606,8 +604,8 @@ private:
|
||||
QString &operator=(const QByteArray &a);
|
||||
#endif
|
||||
|
||||
static const QConstStringData<1> shared_null;
|
||||
static const QConstStringData<1> shared_empty;
|
||||
static const QStaticStringData<1> shared_null;
|
||||
static const QStaticStringData<1> shared_empty;
|
||||
Data *d;
|
||||
inline QString(Data *dd, int /*dummy*/) : d(dd) {}
|
||||
|
||||
@ -709,9 +707,9 @@ inline QChar *QString::data()
|
||||
inline const QChar *QString::constData() const
|
||||
{ return reinterpret_cast<const QChar*>(d->data()); }
|
||||
inline void QString::detach()
|
||||
{ if (d->ref != 1 || d->offset) realloc(); }
|
||||
{ if (d->ref.isShared() || (d->offset != sizeof(QStringData))) realloc(); }
|
||||
inline bool QString::isDetached() const
|
||||
{ return d->ref == 1; }
|
||||
{ return !d->ref.isShared(); }
|
||||
inline QString &QString::operator=(const QLatin1String &s)
|
||||
{
|
||||
*this = fromLatin1(s.latin1(), s.size());
|
||||
@ -874,7 +872,7 @@ inline QString::~QString() { if (!d->ref.deref()) free(d); }
|
||||
|
||||
inline void QString::reserve(int asize)
|
||||
{
|
||||
if (d->ref != 1 || asize > int(d->alloc))
|
||||
if (d->ref.isShared() || asize > int(d->alloc))
|
||||
realloc(asize);
|
||||
|
||||
if (!d->capacityReserved) {
|
||||
@ -885,11 +883,12 @@ inline void QString::reserve(int asize)
|
||||
|
||||
inline void QString::squeeze()
|
||||
{
|
||||
if (d->ref > 1 || d->size < int(d->alloc))
|
||||
if (d->ref.isShared() || d->size < int(d->alloc))
|
||||
realloc();
|
||||
|
||||
if (d->capacityReserved) {
|
||||
// cannot set unconditionally, since d could be the shared_null/shared_empty (which is const)
|
||||
// cannot set unconditionally, since d could be shared_null or
|
||||
// otherwise static.
|
||||
d->capacityReserved = false;
|
||||
}
|
||||
}
|
||||
|
@ -219,9 +219,9 @@ template <> struct QConcatenable<QString> : private QAbstractConcatenable
|
||||
}
|
||||
};
|
||||
|
||||
template <int N> struct QConcatenable<QConstStringDataPtr<N> > : private QAbstractConcatenable
|
||||
template <int N> struct QConcatenable<QStaticStringDataPtr<N> > : private QAbstractConcatenable
|
||||
{
|
||||
typedef QConstStringDataPtr<N> type;
|
||||
typedef QStaticStringDataPtr<N> type;
|
||||
typedef QString ConvertTo;
|
||||
enum { ExactSize = true };
|
||||
static int size(const type &) { return N; }
|
||||
@ -324,9 +324,9 @@ template <> struct QConcatenable<QByteArray> : private QAbstractConcatenable
|
||||
}
|
||||
};
|
||||
|
||||
template <int N> struct QConcatenable<QConstByteArrayDataPtr<N> > : private QAbstractConcatenable
|
||||
template <int N> struct QConcatenable<QStaticByteArrayDataPtr<N> > : private QAbstractConcatenable
|
||||
{
|
||||
typedef QConstByteArrayDataPtr<N> type;
|
||||
typedef QStaticByteArrayDataPtr<N> type;
|
||||
typedef QByteArray ConvertTo;
|
||||
enum { ExactSize = false };
|
||||
static int size(const type &) { return N; }
|
||||
@ -338,9 +338,8 @@ template <int N> struct QConcatenable<QConstByteArrayDataPtr<N> > : private QAbs
|
||||
#endif
|
||||
static inline void appendTo(const type &ba, char *&out)
|
||||
{
|
||||
const char *a = ba.ptr->data;
|
||||
while (*a)
|
||||
*out++ = *a++;
|
||||
::memcpy(out, ba.ptr->data, N);
|
||||
out += N;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -54,15 +54,7 @@ static inline int alignmentThreshold()
|
||||
return 2 * sizeof(void*);
|
||||
}
|
||||
|
||||
const QVectorData QVectorData::shared_null = { Q_REFCOUNT_INITIALIZER(-1), 0, 0, true, false, 0 };
|
||||
|
||||
QVectorData *QVectorData::malloc(int sizeofTypedData, int size, int sizeofT, QVectorData *init)
|
||||
{
|
||||
QVectorData* p = (QVectorData *)::malloc(sizeofTypedData + (size - 1) * sizeofT);
|
||||
Q_CHECK_PTR(p);
|
||||
::memcpy(p, init, sizeofTypedData + (qMin(size, init->alloc) - 1) * sizeofT);
|
||||
return p;
|
||||
}
|
||||
const QVectorData QVectorData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, false, 0 };
|
||||
|
||||
QVectorData *QVectorData::allocate(int size, int alignment)
|
||||
{
|
||||
@ -84,11 +76,9 @@ void QVectorData::free(QVectorData *x, int alignment)
|
||||
::free(x);
|
||||
}
|
||||
|
||||
int QVectorData::grow(int sizeofTypedData, int size, int sizeofT, bool excessive)
|
||||
int QVectorData::grow(int sizeOfHeader, int size, int sizeOfT)
|
||||
{
|
||||
if (excessive)
|
||||
return size + size / 2;
|
||||
return qAllocMore(size * sizeofT, sizeofTypedData - sizeofT) / sizeofT;
|
||||
return qAllocMore(size * sizeOfT, sizeOfHeader) / sizeOfT;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -65,37 +65,28 @@ QT_BEGIN_NAMESPACE
|
||||
struct Q_CORE_EXPORT QVectorData
|
||||
{
|
||||
QtPrivate::RefCount ref;
|
||||
int alloc;
|
||||
int size;
|
||||
#if defined(Q_PROCESSOR_SPARC) && defined(Q_CC_GNU) && defined(__LP64__) && defined(QT_BOOTSTRAPPED)
|
||||
// workaround for bug in gcc 3.4.2
|
||||
uint sharable;
|
||||
uint capacity;
|
||||
uint reserved;
|
||||
#else
|
||||
uint sharable : 1;
|
||||
uint capacity : 1;
|
||||
uint reserved : 30;
|
||||
#endif
|
||||
uint alloc : 31;
|
||||
uint capacityReserved : 1;
|
||||
|
||||
qptrdiff offset;
|
||||
|
||||
void* data() { return reinterpret_cast<char *>(this) + this->offset; }
|
||||
|
||||
static const QVectorData shared_null;
|
||||
// ### Qt 5: rename to 'allocate()'. The current name causes problems for
|
||||
// some debugges when the QVector is member of a class within an unnamed namespace.
|
||||
// ### Qt 5: can be removed completely. (Ralf)
|
||||
static QVectorData *malloc(int sizeofTypedData, int size, int sizeofT, QVectorData *init);
|
||||
static QVectorData *allocate(int size, int alignment);
|
||||
static QVectorData *reallocate(QVectorData *old, int newsize, int oldsize, int alignment);
|
||||
static void free(QVectorData *data, int alignment);
|
||||
static int grow(int sizeofTypedData, int size, int sizeofT, bool excessive);
|
||||
static int grow(int sizeOfHeader, int size, int sizeOfT);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct QVectorTypedData : private QVectorData
|
||||
{ // private inheritance as we must not access QVectorData member thought QVectorTypedData
|
||||
// as this would break strict aliasing rules. (in the case of shared_null)
|
||||
T array[1];
|
||||
struct QVectorTypedData : QVectorData
|
||||
{
|
||||
T* begin() { return reinterpret_cast<T *>(this->data()); }
|
||||
T* end() { return begin() + this->size; }
|
||||
|
||||
static inline void free(QVectorTypedData<T> *x, int alignment) { QVectorData::free(static_cast<QVectorData *>(x), alignment); }
|
||||
static QVectorTypedData *sharedNull() { return static_cast<QVectorTypedData *>(const_cast<QVectorData *>(&QVectorData::shared_null)); }
|
||||
};
|
||||
|
||||
class QRegion;
|
||||
@ -104,27 +95,30 @@ template <typename T>
|
||||
class QVector
|
||||
{
|
||||
typedef QVectorTypedData<T> Data;
|
||||
union {
|
||||
QVectorData *d;
|
||||
#if defined(Q_CC_SUN) && (__SUNPRO_CC <= 0x550)
|
||||
QVectorTypedData<T> *p;
|
||||
#else
|
||||
Data *p;
|
||||
#endif
|
||||
};
|
||||
Data *d;
|
||||
|
||||
public:
|
||||
// ### Qt 5: Consider making QVector non-shared to get at least one
|
||||
// "really fast" container. See tests/benchmarks/corelib/tools/qvector/
|
||||
inline QVector() : d(const_cast<QVectorData *>(&QVectorData::shared_null)) { }
|
||||
inline QVector() : d(Data::sharedNull()) { }
|
||||
explicit QVector(int size);
|
||||
QVector(int size, const T &t);
|
||||
inline QVector(const QVector<T> &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); }
|
||||
inline ~QVector() { if (!d) return; if (!d->ref.deref()) free(p); }
|
||||
inline QVector(const QVector<T> &v)
|
||||
{
|
||||
if (v.d->ref.ref()) {
|
||||
d = v.d;
|
||||
} else {
|
||||
d = Data::sharedNull();
|
||||
realloc(0, int(v.d->alloc));
|
||||
qCopy(v.d->begin(), v.d->end(), d->begin());
|
||||
d->size = v.d->size;
|
||||
d->capacityReserved = v.d->capacityReserved;
|
||||
}
|
||||
}
|
||||
|
||||
inline ~QVector() { if (!d->ref.deref()) free(d); }
|
||||
QVector<T> &operator=(const QVector<T> &v);
|
||||
#ifdef Q_COMPILER_RVALUE_REFS
|
||||
inline QVector<T> operator=(QVector<T> &&other)
|
||||
{ qSwap(p, other.p); return *this; }
|
||||
{ qSwap(d, other.d); return *this; }
|
||||
#endif
|
||||
inline void swap(QVector<T> &other) { qSwap(d, other.d); }
|
||||
#ifdef Q_COMPILER_INITIALIZER_LISTS
|
||||
@ -139,18 +133,27 @@ public:
|
||||
|
||||
void resize(int size);
|
||||
|
||||
inline int capacity() const { return d->alloc; }
|
||||
inline int capacity() const { return int(d->alloc); }
|
||||
void reserve(int size);
|
||||
inline void squeeze() { realloc(d->size, d->size); d->capacity = 0; }
|
||||
inline void squeeze() { realloc(d->size, d->size); d->capacityReserved = 0; }
|
||||
|
||||
inline void detach() { if (!isDetached()) detach_helper(); }
|
||||
inline bool isDetached() const { return !d->ref.isShared(); }
|
||||
inline void setSharable(bool sharable)
|
||||
{
|
||||
if (sharable == d->ref.isSharable())
|
||||
return;
|
||||
if (!sharable)
|
||||
detach();
|
||||
if (d != Data::sharedNull())
|
||||
d->ref.setSharable(sharable);
|
||||
}
|
||||
|
||||
inline void detach() { if (d->ref != 1) detach_helper(); }
|
||||
inline bool isDetached() const { return d->ref == 1; }
|
||||
inline void setSharable(bool sharable) { if (!sharable) detach(); if (d != &QVectorData::shared_null) d->sharable = sharable; }
|
||||
inline bool isSharedWith(const QVector<T> &other) const { return d == other.d; }
|
||||
|
||||
inline T *data() { detach(); return p->array; }
|
||||
inline const T *data() const { return p->array; }
|
||||
inline const T *constData() const { return p->array; }
|
||||
inline T *data() { detach(); return d->begin(); }
|
||||
inline const T *data() const { return d->begin(); }
|
||||
inline const T *constData() const { return d->begin(); }
|
||||
void clear();
|
||||
|
||||
const T &at(int i) const;
|
||||
@ -243,12 +246,12 @@ public:
|
||||
typedef T* iterator;
|
||||
typedef const T* const_iterator;
|
||||
#endif
|
||||
inline iterator begin() { detach(); return p->array; }
|
||||
inline const_iterator begin() const { return p->array; }
|
||||
inline const_iterator constBegin() const { return p->array; }
|
||||
inline iterator end() { detach(); return p->array + d->size; }
|
||||
inline const_iterator end() const { return p->array + d->size; }
|
||||
inline const_iterator constEnd() const { return p->array + d->size; }
|
||||
inline iterator begin() { detach(); return d->begin(); }
|
||||
inline const_iterator begin() const { return d->begin(); }
|
||||
inline const_iterator constBegin() const { return d->begin(); }
|
||||
inline iterator end() { detach(); return d->end(); }
|
||||
inline const_iterator end() const { return d->end(); }
|
||||
inline const_iterator constEnd() const { return d->end(); }
|
||||
iterator insert(iterator before, int n, const T &x);
|
||||
inline iterator insert(iterator before, const T &x) { return insert(before, 1, x); }
|
||||
iterator erase(iterator begin, iterator end);
|
||||
@ -313,46 +316,49 @@ private:
|
||||
friend class QRegion; // Optimization for QRegion::rects()
|
||||
|
||||
void detach_helper();
|
||||
QVectorData *malloc(int alloc);
|
||||
Data *malloc(int alloc);
|
||||
void realloc(int size, int alloc);
|
||||
void free(Data *d);
|
||||
int sizeOfTypedData() {
|
||||
// this is more or less the same as sizeof(Data), except that it doesn't
|
||||
// count the padding at the end
|
||||
return reinterpret_cast<const char *>(&(reinterpret_cast<const Data *>(this))->array[1]) - reinterpret_cast<const char *>(this);
|
||||
|
||||
class AlignmentDummy { QVectorData header; T array[1]; };
|
||||
|
||||
static Q_DECL_CONSTEXPR int offsetOfTypedData()
|
||||
{
|
||||
// (non-POD)-safe offsetof(AlignmentDummy, array)
|
||||
return (sizeof(QVectorData) + (alignOfTypedData() - 1)) & ~(alignOfTypedData() - 1);
|
||||
}
|
||||
inline int alignOfTypedData() const
|
||||
static Q_DECL_CONSTEXPR int alignOfTypedData()
|
||||
{
|
||||
#ifdef Q_ALIGNOF
|
||||
return qMax<int>(sizeof(void*), Q_ALIGNOF(Data));
|
||||
return Q_ALIGNOF(AlignmentDummy);
|
||||
#else
|
||||
return 0;
|
||||
return sizeof(void *);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void QVector<T>::detach_helper()
|
||||
{ realloc(d->size, d->alloc); }
|
||||
{ realloc(d->size, int(d->alloc)); }
|
||||
template <typename T>
|
||||
void QVector<T>::reserve(int asize)
|
||||
{ if (asize > d->alloc) realloc(d->size, asize); if (d->ref == 1) d->capacity = 1; }
|
||||
{ if (asize > int(d->alloc)) realloc(d->size, asize); if (isDetached()) d->capacityReserved = 1; }
|
||||
template <typename T>
|
||||
void QVector<T>::resize(int asize)
|
||||
{ realloc(asize, (asize > d->alloc || (!d->capacity && asize < d->size && asize < (d->alloc >> 1))) ?
|
||||
QVectorData::grow(sizeOfTypedData(), asize, sizeof(T), QTypeInfo<T>::isStatic)
|
||||
: d->alloc); }
|
||||
{ realloc(asize, (asize > int(d->alloc) || (!d->capacityReserved && asize < d->size && asize < int(d->alloc >> 1))) ?
|
||||
QVectorData::grow(offsetOfTypedData(), asize, sizeof(T))
|
||||
: int(d->alloc)); }
|
||||
template <typename T>
|
||||
inline void QVector<T>::clear()
|
||||
{ *this = QVector<T>(); }
|
||||
template <typename T>
|
||||
inline const T &QVector<T>::at(int i) const
|
||||
{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::at", "index out of range");
|
||||
return p->array[i]; }
|
||||
return d->begin()[i]; }
|
||||
template <typename T>
|
||||
inline const T &QVector<T>::operator[](int i) const
|
||||
{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::operator[]", "index out of range");
|
||||
return p->array[i]; }
|
||||
return d->begin()[i]; }
|
||||
template <typename T>
|
||||
inline T &QVector<T>::operator[](int i)
|
||||
{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::operator[]", "index out of range");
|
||||
@ -388,39 +394,37 @@ inline void QVector<T>::replace(int i, const T &t)
|
||||
template <typename T>
|
||||
QVector<T> &QVector<T>::operator=(const QVector<T> &v)
|
||||
{
|
||||
QVectorData *o = v.d;
|
||||
o->ref.ref();
|
||||
if (!d->ref.deref())
|
||||
free(p);
|
||||
d = o;
|
||||
if (!d->sharable)
|
||||
detach_helper();
|
||||
if (v.d != d) {
|
||||
QVector<T> tmp(v);
|
||||
tmp.swap(*this);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline QVectorData *QVector<T>::malloc(int aalloc)
|
||||
inline typename QVector<T>::Data *QVector<T>::malloc(int aalloc)
|
||||
{
|
||||
QVectorData *vectordata = QVectorData::allocate(sizeOfTypedData() + (aalloc - 1) * sizeof(T), alignOfTypedData());
|
||||
QVectorData *vectordata = QVectorData::allocate(offsetOfTypedData() + aalloc * sizeof(T), alignOfTypedData());
|
||||
Q_CHECK_PTR(vectordata);
|
||||
return vectordata;
|
||||
return static_cast<Data *>(vectordata);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
QVector<T>::QVector(int asize)
|
||||
{
|
||||
d = malloc(asize);
|
||||
d->ref = 1;
|
||||
d->alloc = d->size = asize;
|
||||
d->sharable = true;
|
||||
d->capacity = false;
|
||||
d->ref.initializeOwned();
|
||||
d->size = asize;
|
||||
d->alloc = uint(d->size);
|
||||
d->capacityReserved = false;
|
||||
d->offset = offsetOfTypedData();
|
||||
if (QTypeInfo<T>::isComplex) {
|
||||
T* b = p->array;
|
||||
T* i = p->array + d->size;
|
||||
T* b = d->begin();
|
||||
T* i = d->end();
|
||||
while (i != b)
|
||||
new (--i) T;
|
||||
} else {
|
||||
qMemSet(p->array, 0, asize * sizeof(T));
|
||||
qMemSet(d->begin(), 0, asize * sizeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
@ -428,12 +432,13 @@ template <typename T>
|
||||
QVector<T>::QVector(int asize, const T &t)
|
||||
{
|
||||
d = malloc(asize);
|
||||
d->ref = 1;
|
||||
d->alloc = d->size = asize;
|
||||
d->sharable = true;
|
||||
d->capacity = false;
|
||||
T* i = p->array + d->size;
|
||||
while (i != p->array)
|
||||
d->ref.initializeOwned();
|
||||
d->size = asize;
|
||||
d->alloc = uint(d->size);
|
||||
d->capacityReserved = false;
|
||||
d->offset = offsetOfTypedData();
|
||||
T* i = d->end();
|
||||
while (i != d->begin())
|
||||
new (--i) T(t);
|
||||
}
|
||||
|
||||
@ -442,14 +447,22 @@ template <typename T>
|
||||
QVector<T>::QVector(std::initializer_list<T> args)
|
||||
{
|
||||
d = malloc(int(args.size()));
|
||||
d->ref = 1;
|
||||
d->alloc = d->size = int(args.size());
|
||||
d->sharable = true;
|
||||
d->capacity = false;
|
||||
T* i = p->array + d->size;
|
||||
auto it = args.end();
|
||||
while (i != p->array)
|
||||
new (--i) T(*(--it));
|
||||
d->ref.initializeOwned();
|
||||
d->size = int(args.size());
|
||||
d->alloc = uint(d->size);
|
||||
d->capacityReserved = false;
|
||||
d->offset = offsetOfTypedData();
|
||||
if (QTypeInfo<T>::isComplex) {
|
||||
T* b = d->begin();
|
||||
T* i = d->end();
|
||||
const T* s = args.end();
|
||||
while (i != b)
|
||||
new(--i) T(*--s);
|
||||
} else {
|
||||
// std::initializer_list<T>::iterator is guaranteed to be
|
||||
// const T* ([support.initlist]/1), so can be memcpy'ed away from:
|
||||
::memcpy(d->begin(), args.begin(), args.size() * sizeof(T));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -457,14 +470,12 @@ template <typename T>
|
||||
void QVector<T>::free(Data *x)
|
||||
{
|
||||
if (QTypeInfo<T>::isComplex) {
|
||||
T* b = x->array;
|
||||
union { QVectorData *d; Data *p; } u;
|
||||
u.p = x;
|
||||
T* i = b + u.d->size;
|
||||
T* b = x->begin();
|
||||
T* i = b + x->size;
|
||||
while (i-- != b)
|
||||
i->~T();
|
||||
}
|
||||
x->free(x, alignOfTypedData());
|
||||
Data::free(x, alignOfTypedData());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -473,84 +484,82 @@ void QVector<T>::realloc(int asize, int aalloc)
|
||||
Q_ASSERT(asize <= aalloc);
|
||||
T *pOld;
|
||||
T *pNew;
|
||||
union { QVectorData *d; Data *p; } x;
|
||||
x.d = d;
|
||||
Data *x = d;
|
||||
|
||||
if (QTypeInfo<T>::isComplex && asize < d->size && d->ref == 1 ) {
|
||||
if (QTypeInfo<T>::isComplex && asize < d->size && isDetached()) {
|
||||
// call the destructor on all objects that need to be
|
||||
// destroyed when shrinking
|
||||
pOld = p->array + d->size;
|
||||
pNew = p->array + asize;
|
||||
pOld = d->begin() + d->size;
|
||||
pNew = d->begin() + asize;
|
||||
while (asize < d->size) {
|
||||
(--pOld)->~T();
|
||||
d->size--;
|
||||
}
|
||||
}
|
||||
|
||||
if (aalloc != d->alloc || d->ref != 1) {
|
||||
if (aalloc != int(d->alloc) || !isDetached()) {
|
||||
// (re)allocate memory
|
||||
if (QTypeInfo<T>::isStatic) {
|
||||
x.d = malloc(aalloc);
|
||||
Q_CHECK_PTR(x.p);
|
||||
x.d->size = 0;
|
||||
} else if (d->ref != 1) {
|
||||
x.d = malloc(aalloc);
|
||||
Q_CHECK_PTR(x.p);
|
||||
x = malloc(aalloc);
|
||||
Q_CHECK_PTR(x);
|
||||
x->size = 0;
|
||||
} else if (!isDetached()) {
|
||||
x = malloc(aalloc);
|
||||
Q_CHECK_PTR(x);
|
||||
if (QTypeInfo<T>::isComplex) {
|
||||
x.d->size = 0;
|
||||
x->size = 0;
|
||||
} else {
|
||||
::memcpy(x.p, p, sizeOfTypedData() + (qMin(aalloc, d->alloc) - 1) * sizeof(T));
|
||||
x.d->size = d->size;
|
||||
::memcpy(x, d, offsetOfTypedData() + qMin(uint(aalloc), d->alloc) * sizeof(T));
|
||||
x->size = d->size;
|
||||
}
|
||||
} else {
|
||||
QT_TRY {
|
||||
QVectorData *mem = QVectorData::reallocate(d, sizeOfTypedData() + (aalloc - 1) * sizeof(T),
|
||||
sizeOfTypedData() + (d->alloc - 1) * sizeof(T), alignOfTypedData());
|
||||
QVectorData *mem = QVectorData::reallocate(d, offsetOfTypedData() + aalloc * sizeof(T),
|
||||
offsetOfTypedData() + d->alloc * sizeof(T), alignOfTypedData());
|
||||
Q_CHECK_PTR(mem);
|
||||
x.d = d = mem;
|
||||
x.d->size = d->size;
|
||||
x = d = static_cast<Data *>(mem);
|
||||
x->size = d->size;
|
||||
} QT_CATCH (const std::bad_alloc &) {
|
||||
if (aalloc > d->alloc) // ignore the error in case we are just shrinking.
|
||||
if (aalloc > int(d->alloc)) // ignore the error in case we are just shrinking.
|
||||
QT_RETHROW;
|
||||
}
|
||||
}
|
||||
x.d->ref = 1;
|
||||
x.d->alloc = aalloc;
|
||||
x.d->sharable = true;
|
||||
x.d->capacity = d->capacity;
|
||||
x.d->reserved = 0;
|
||||
x->ref.initializeOwned();
|
||||
x->alloc = uint(aalloc);
|
||||
x->capacityReserved = d->capacityReserved;
|
||||
x->offset = offsetOfTypedData();
|
||||
}
|
||||
|
||||
if (QTypeInfo<T>::isComplex) {
|
||||
QT_TRY {
|
||||
pOld = p->array + x.d->size;
|
||||
pNew = x.p->array + x.d->size;
|
||||
pOld = d->begin() + x->size;
|
||||
pNew = x->begin() + x->size;
|
||||
// copy objects from the old array into the new array
|
||||
const int toMove = qMin(asize, d->size);
|
||||
while (x.d->size < toMove) {
|
||||
while (x->size < toMove) {
|
||||
new (pNew++) T(*pOld++);
|
||||
x.d->size++;
|
||||
x->size++;
|
||||
}
|
||||
// construct all new objects when growing
|
||||
while (x.d->size < asize) {
|
||||
while (x->size < asize) {
|
||||
new (pNew++) T;
|
||||
x.d->size++;
|
||||
x->size++;
|
||||
}
|
||||
} QT_CATCH (...) {
|
||||
free(x.p);
|
||||
free(x);
|
||||
QT_RETHROW;
|
||||
}
|
||||
|
||||
} else if (asize > x.d->size) {
|
||||
} else if (asize > x->size) {
|
||||
// initialize newly allocated memory to 0
|
||||
qMemSet(x.p->array + x.d->size, 0, (asize - x.d->size) * sizeof(T));
|
||||
qMemSet(x->end(), 0, (asize - x->size) * sizeof(T));
|
||||
}
|
||||
x.d->size = asize;
|
||||
x->size = asize;
|
||||
|
||||
if (d != x.d) {
|
||||
if (d != x) {
|
||||
if (!d->ref.deref())
|
||||
free(p);
|
||||
d = x.d;
|
||||
free(d);
|
||||
d = x;
|
||||
}
|
||||
}
|
||||
|
||||
@ -560,31 +569,31 @@ Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i) const
|
||||
if (i < 0 || i >= d->size) {
|
||||
return T();
|
||||
}
|
||||
return p->array[i];
|
||||
return d->begin()[i];
|
||||
}
|
||||
template<typename T>
|
||||
Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i, const T &defaultValue) const
|
||||
{
|
||||
return ((i < 0 || i >= d->size) ? defaultValue : p->array[i]);
|
||||
return ((i < 0 || i >= d->size) ? defaultValue : d->begin()[i]);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void QVector<T>::append(const T &t)
|
||||
{
|
||||
if (d->ref != 1 || d->size + 1 > d->alloc) {
|
||||
if (!isDetached() || d->size + 1 > int(d->alloc)) {
|
||||
const T copy(t);
|
||||
realloc(d->size, (d->size + 1 > d->alloc) ?
|
||||
QVectorData::grow(sizeOfTypedData(), d->size + 1, sizeof(T), QTypeInfo<T>::isStatic)
|
||||
: d->alloc);
|
||||
realloc(d->size, (d->size + 1 > int(d->alloc)) ?
|
||||
QVectorData::grow(offsetOfTypedData(), d->size + 1, sizeof(T))
|
||||
: int(d->alloc));
|
||||
if (QTypeInfo<T>::isComplex)
|
||||
new (p->array + d->size) T(copy);
|
||||
new (d->end()) T(copy);
|
||||
else
|
||||
p->array[d->size] = copy;
|
||||
*d->end() = copy;
|
||||
} else {
|
||||
if (QTypeInfo<T>::isComplex)
|
||||
new (p->array + d->size) T(t);
|
||||
new (d->end()) T(t);
|
||||
else
|
||||
p->array[d->size] = t;
|
||||
*d->end() = t;
|
||||
}
|
||||
++d->size;
|
||||
}
|
||||
@ -592,27 +601,26 @@ void QVector<T>::append(const T &t)
|
||||
template <typename T>
|
||||
typename QVector<T>::iterator QVector<T>::insert(iterator before, size_type n, const T &t)
|
||||
{
|
||||
int offset = int(before - p->array);
|
||||
int offset = int(before - d->begin());
|
||||
if (n != 0) {
|
||||
const T copy(t);
|
||||
if (d->ref != 1 || d->size + n > d->alloc)
|
||||
realloc(d->size, QVectorData::grow(sizeOfTypedData(), d->size + n, sizeof(T),
|
||||
QTypeInfo<T>::isStatic));
|
||||
if (!isDetached() || d->size + n > int(d->alloc))
|
||||
realloc(d->size, QVectorData::grow(offsetOfTypedData(), d->size + n, sizeof(T)));
|
||||
if (QTypeInfo<T>::isStatic) {
|
||||
T *b = p->array + d->size;
|
||||
T *i = p->array + d->size + n;
|
||||
T *b = d->end();
|
||||
T *i = d->end() + n;
|
||||
while (i != b)
|
||||
new (--i) T;
|
||||
i = p->array + d->size;
|
||||
i = d->end();
|
||||
T *j = i + n;
|
||||
b = p->array + offset;
|
||||
b = d->begin() + offset;
|
||||
while (i != b)
|
||||
*--j = *--i;
|
||||
i = b+n;
|
||||
while (i != b)
|
||||
*--i = copy;
|
||||
} else {
|
||||
T *b = p->array + offset;
|
||||
T *b = d->begin() + offset;
|
||||
T *i = b + n;
|
||||
memmove(i, b, (d->size - offset) * sizeof(T));
|
||||
while (i != b)
|
||||
@ -620,29 +628,29 @@ typename QVector<T>::iterator QVector<T>::insert(iterator before, size_type n, c
|
||||
}
|
||||
d->size += n;
|
||||
}
|
||||
return p->array + offset;
|
||||
return d->begin() + offset;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename QVector<T>::iterator QVector<T>::erase(iterator abegin, iterator aend)
|
||||
{
|
||||
int f = int(abegin - p->array);
|
||||
int l = int(aend - p->array);
|
||||
int f = int(abegin - d->begin());
|
||||
int l = int(aend - d->begin());
|
||||
int n = l - f;
|
||||
detach();
|
||||
if (QTypeInfo<T>::isComplex) {
|
||||
qCopy(p->array+l, p->array+d->size, p->array+f);
|
||||
T *i = p->array+d->size;
|
||||
T* b = p->array+d->size-n;
|
||||
qCopy(d->begin()+l, d->end(), d->begin()+f);
|
||||
T *i = d->end();
|
||||
T* b = d->end()-n;
|
||||
while (i != b) {
|
||||
--i;
|
||||
i->~T();
|
||||
}
|
||||
} else {
|
||||
memmove(p->array + f, p->array + l, (d->size-l)*sizeof(T));
|
||||
memmove(d->begin() + f, d->begin() + l, (d->size-l)*sizeof(T));
|
||||
}
|
||||
d->size -= n;
|
||||
return p->array + f;
|
||||
return d->begin() + f;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -652,9 +660,9 @@ bool QVector<T>::operator==(const QVector<T> &v) const
|
||||
return false;
|
||||
if (d == v.d)
|
||||
return true;
|
||||
T* b = p->array;
|
||||
T* b = d->begin();
|
||||
T* i = b + d->size;
|
||||
T* j = v.p->array + d->size;
|
||||
T* j = v.d->end();
|
||||
while (i != b)
|
||||
if (!(*--i == *--j))
|
||||
return false;
|
||||
@ -667,8 +675,8 @@ QVector<T> &QVector<T>::fill(const T &from, int asize)
|
||||
const T copy(from);
|
||||
resize(asize < 0 ? d->size : asize);
|
||||
if (d->size) {
|
||||
T *i = p->array + d->size;
|
||||
T *b = p->array;
|
||||
T *i = d->end();
|
||||
T *b = d->begin();
|
||||
while (i != b)
|
||||
*--i = copy;
|
||||
}
|
||||
@ -681,9 +689,9 @@ QVector<T> &QVector<T>::operator+=(const QVector &l)
|
||||
int newSize = d->size + l.d->size;
|
||||
realloc(d->size, newSize);
|
||||
|
||||
T *w = p->array + newSize;
|
||||
T *i = l.p->array + l.d->size;
|
||||
T *b = l.p->array;
|
||||
T *w = d->begin() + newSize;
|
||||
T *i = l.d->end();
|
||||
T *b = l.d->begin();
|
||||
while (i != b) {
|
||||
if (QTypeInfo<T>::isComplex)
|
||||
new (--w) T(*--i);
|
||||
@ -700,11 +708,11 @@ int QVector<T>::indexOf(const T &t, int from) const
|
||||
if (from < 0)
|
||||
from = qMax(from + d->size, 0);
|
||||
if (from < d->size) {
|
||||
T* n = p->array + from - 1;
|
||||
T* e = p->array + d->size;
|
||||
T* n = d->begin() + from - 1;
|
||||
T* e = d->end();
|
||||
while (++n != e)
|
||||
if (*n == t)
|
||||
return n - p->array;
|
||||
return n - d->begin();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@ -717,8 +725,8 @@ int QVector<T>::lastIndexOf(const T &t, int from) const
|
||||
else if (from >= d->size)
|
||||
from = d->size-1;
|
||||
if (from >= 0) {
|
||||
T* b = p->array;
|
||||
T* n = p->array + from + 1;
|
||||
T* b = d->begin();
|
||||
T* n = d->begin() + from + 1;
|
||||
while (n != b) {
|
||||
if (*--n == t)
|
||||
return n - b;
|
||||
@ -730,8 +738,8 @@ int QVector<T>::lastIndexOf(const T &t, int from) const
|
||||
template <typename T>
|
||||
bool QVector<T>::contains(const T &t) const
|
||||
{
|
||||
T* b = p->array;
|
||||
T* i = p->array + d->size;
|
||||
T* b = d->begin();
|
||||
T* i = d->end();
|
||||
while (i != b)
|
||||
if (*--i == t)
|
||||
return true;
|
||||
@ -742,8 +750,8 @@ template <typename T>
|
||||
int QVector<T>::count(const T &t) const
|
||||
{
|
||||
int c = 0;
|
||||
T* b = p->array;
|
||||
T* i = p->array + d->size;
|
||||
T* b = d->begin();
|
||||
T* i = d->end();
|
||||
while (i != b)
|
||||
if (*--i == t)
|
||||
++c;
|
||||
|
@ -2,6 +2,9 @@
|
||||
|
||||
HEADERS += \
|
||||
tools/qalgorithms.h \
|
||||
tools/qarraydata.h \
|
||||
tools/qarraydataops.h \
|
||||
tools/qarraydatapointer.h \
|
||||
tools/qbitarray.h \
|
||||
tools/qbytearray.h \
|
||||
tools/qbytearraymatcher.h \
|
||||
@ -56,6 +59,7 @@ HEADERS += \
|
||||
|
||||
|
||||
SOURCES += \
|
||||
tools/qarraydata.cpp \
|
||||
tools/qbitarray.cpp \
|
||||
tools/qbytearray.cpp \
|
||||
tools/qbytearraymatcher.cpp \
|
||||
|
@ -181,7 +181,7 @@ void QDBusAbstractAdaptor::setAutoRelaySignals(bool enable)
|
||||
continue;
|
||||
|
||||
// try to connect/disconnect to a signal on the parent that has the same method signature
|
||||
QByteArray sig = QMetaObject::normalizedSignature(mm.signature());
|
||||
QByteArray sig = QMetaObject::normalizedSignature(mm.methodSignature().constData());
|
||||
if (them->indexOfSignal(sig) == -1)
|
||||
continue;
|
||||
sig.prepend(QSIGNAL_CODE + '0');
|
||||
@ -307,7 +307,7 @@ void QDBusAdaptorConnector::relay(QObject *senderObj, int lastSignalIdx, void **
|
||||
// invalid signal signature
|
||||
// qDBusParametersForMethod has not yet complained about this one
|
||||
qWarning("QDBusAbstractAdaptor: Cannot relay signal %s::%s",
|
||||
senderMetaObject->className(), mm.signature());
|
||||
senderMetaObject->className(), mm.methodSignature().constData());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -323,10 +323,38 @@ void QDBusAdaptorConnector::relay(QObject *senderObj, int lastSignalIdx, void **
|
||||
// modify carefully: this has been hand-edited!
|
||||
// the relaySlot slot gets called with the void** array
|
||||
|
||||
struct qt_meta_stringdata_QDBusAdaptorConnector_t {
|
||||
QByteArrayData data[10];
|
||||
char stringdata[96];
|
||||
};
|
||||
#define QT_MOC_LITERAL(idx, ofs, len) { \
|
||||
Q_REFCOUNT_INITIALIZE_STATIC, len, 0, 0, \
|
||||
offsetof(qt_meta_stringdata_QDBusAdaptorConnector_t, stringdata) + ofs \
|
||||
- idx * sizeof(QByteArrayData) \
|
||||
}
|
||||
static const qt_meta_stringdata_QDBusAdaptorConnector_t qt_meta_stringdata_QDBusAdaptorConnector = {
|
||||
{
|
||||
QT_MOC_LITERAL(0, 0, 21),
|
||||
QT_MOC_LITERAL(1, 22, 11),
|
||||
QT_MOC_LITERAL(2, 34, 0),
|
||||
QT_MOC_LITERAL(3, 35, 3),
|
||||
QT_MOC_LITERAL(4, 39, 18),
|
||||
QT_MOC_LITERAL(5, 58, 10),
|
||||
QT_MOC_LITERAL(6, 69, 3),
|
||||
QT_MOC_LITERAL(7, 73, 4),
|
||||
QT_MOC_LITERAL(8, 78, 9),
|
||||
QT_MOC_LITERAL(9, 88, 6)
|
||||
},
|
||||
"QDBusAdaptorConnector\0relaySignal\0\0"
|
||||
"obj\0const QMetaObject*\0metaObject\0sid\0"
|
||||
"args\0relaySlot\0polish\0"
|
||||
};
|
||||
#undef QT_MOC_LITERAL
|
||||
|
||||
static const uint qt_meta_data_QDBusAdaptorConnector[] = {
|
||||
|
||||
// content:
|
||||
6, // revision
|
||||
7, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
3, 14, // methods
|
||||
@ -336,22 +364,23 @@ static const uint qt_meta_data_QDBusAdaptorConnector[] = {
|
||||
0, // flags
|
||||
1, // signalCount
|
||||
|
||||
// signals: signature, parameters, type, tag, flags
|
||||
47, 23, 22, 22, 0x05,
|
||||
// signals: name, argc, parameters, tag, flags
|
||||
1, 4, 29, 2, 0x05,
|
||||
|
||||
// slots: signature, parameters, type, tag, flags
|
||||
105, 22, 22, 22, 0x0a,
|
||||
117, 22, 22, 22, 0x0a,
|
||||
// slots: name, argc, parameters, tag, flags
|
||||
8, 0, 38, 2, 0x0a,
|
||||
9, 0, 39, 2, 0x0a,
|
||||
|
||||
// signals: parameters
|
||||
QMetaType::Void, QMetaType::QObjectStar, 0x80000000 | 4, QMetaType::Int, QMetaType::QVariantList, 3, 5, 6, 7,
|
||||
|
||||
// slots: parameters
|
||||
QMetaType::Void,
|
||||
QMetaType::Void,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
static const char qt_meta_stringdata_QDBusAdaptorConnector[] = {
|
||||
"QDBusAdaptorConnector\0\0obj,metaObject,sid,args\0"
|
||||
"relaySignal(QObject*,const QMetaObject*,int,QVariantList)\0"
|
||||
"relaySlot()\0polish()\0"
|
||||
};
|
||||
|
||||
void QDBusAdaptorConnector::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
{
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
@ -371,7 +400,7 @@ const QMetaObjectExtraData QDBusAdaptorConnector::staticMetaObjectExtraData = {
|
||||
};
|
||||
|
||||
const QMetaObject QDBusAdaptorConnector::staticMetaObject = {
|
||||
{ &QObject::staticMetaObject, qt_meta_stringdata_QDBusAdaptorConnector,
|
||||
{ &QObject::staticMetaObject, qt_meta_stringdata_QDBusAdaptorConnector.data,
|
||||
qt_meta_data_QDBusAdaptorConnector, &staticMetaObjectExtraData }
|
||||
};
|
||||
|
||||
@ -383,7 +412,7 @@ const QMetaObject *QDBusAdaptorConnector::metaObject() const
|
||||
void *QDBusAdaptorConnector::qt_metacast(const char *_clname)
|
||||
{
|
||||
if (!_clname) return 0;
|
||||
if (!strcmp(_clname, qt_meta_stringdata_QDBusAdaptorConnector))
|
||||
if (!strcmp(_clname, qt_meta_stringdata_QDBusAdaptorConnector.stringdata))
|
||||
return static_cast<void*>(const_cast< QDBusAdaptorConnector*>(this));
|
||||
return QObject::qt_metacast(_clname);
|
||||
}
|
||||
|
@ -446,7 +446,7 @@ QDBusMessage QDBusAbstractInterface::callWithArgumentList(QDBus::CallMode mode,
|
||||
|
||||
for (int i = staticMetaObject.methodCount(); i < mo->methodCount(); ++i) {
|
||||
QMetaMethod mm = mo->method(i);
|
||||
if (QByteArray(mm.signature()).startsWith(match)) {
|
||||
if (mm.methodSignature().startsWith(match)) {
|
||||
// found a method with the same name as what we're looking for
|
||||
// hopefully, nobody is overloading asynchronous and synchronous methods with
|
||||
// the same name
|
||||
|
@ -640,7 +640,7 @@ static int findSlot(const QMetaObject *mo, const QByteArray &name, int flags,
|
||||
continue;
|
||||
|
||||
// check name:
|
||||
QByteArray slotname = mm.signature();
|
||||
QByteArray slotname = mm.methodSignature();
|
||||
int paren = slotname.indexOf('(');
|
||||
if (paren != name.length() || !slotname.startsWith(name))
|
||||
continue;
|
||||
@ -686,7 +686,7 @@ static int findSlot(const QMetaObject *mo, const QByteArray &name, int flags,
|
||||
++i;
|
||||
|
||||
// make sure that the output parameters have signatures too
|
||||
if (returnType != 0 && QDBusMetaType::typeToSignature(returnType) == 0)
|
||||
if (returnType != QMetaType::UnknownType && returnType != QMetaType::Void && QDBusMetaType::typeToSignature(returnType) == 0)
|
||||
continue;
|
||||
|
||||
bool ok = true;
|
||||
@ -919,7 +919,7 @@ void QDBusConnectionPrivate::deliverCall(QObject *object, int /*flags*/, const Q
|
||||
// output arguments
|
||||
QVariantList outputArgs;
|
||||
void *null = 0;
|
||||
if (metaTypes[0] != QMetaType::Void) {
|
||||
if (metaTypes[0] != QMetaType::Void && metaTypes[0] != QMetaType::UnknownType) {
|
||||
QVariant arg(metaTypes[0], null);
|
||||
outputArgs.append( arg );
|
||||
params[0] = const_cast<void*>(outputArgs.at( outputArgs.count() - 1 ).constData());
|
||||
@ -1188,7 +1188,7 @@ void QDBusConnectionPrivate::relaySignal(QObject *obj, const QMetaObject *mo, in
|
||||
QString interface = qDBusInterfaceFromMetaObject(mo);
|
||||
|
||||
QMetaMethod mm = mo->method(signalId);
|
||||
QByteArray memberName = mm.signature();
|
||||
QByteArray memberName = mm.methodSignature();
|
||||
memberName.truncate(memberName.indexOf('('));
|
||||
|
||||
// check if it's scriptable
|
||||
|
@ -280,7 +280,7 @@ int QDBusInterfacePrivate::metacall(QMetaObject::Call c, int id, void **argv)
|
||||
} else if (mm.methodType() == QMetaMethod::Slot || mm.methodType() == QMetaMethod::Method) {
|
||||
// method call relay from Qt world to D-Bus world
|
||||
// get D-Bus equivalent signature
|
||||
QString methodName = QLatin1String(metaObject->dbusNameForMethod(id));
|
||||
QString methodName = QString::fromLatin1(mm.name());
|
||||
const int *inputTypes = metaObject->inputTypesForMethod(id);
|
||||
int inputTypesCount = *inputTypes;
|
||||
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "qdbusabstractinterface_p.h"
|
||||
|
||||
#include <private/qmetaobject_p.h>
|
||||
#include <private/qmetaobjectbuilder_p.h>
|
||||
|
||||
#ifndef QT_NO_DBUS
|
||||
|
||||
@ -69,8 +70,7 @@ public:
|
||||
|
||||
private:
|
||||
struct Method {
|
||||
QByteArray parameters;
|
||||
QByteArray typeName;
|
||||
QList<QByteArray> parameterNames;
|
||||
QByteArray tag;
|
||||
QByteArray name;
|
||||
QVarLengthArray<int, 4> inputTypes;
|
||||
@ -103,10 +103,12 @@ private:
|
||||
void parseMethods();
|
||||
void parseSignals();
|
||||
void parseProperties();
|
||||
|
||||
static int aggregateParameterCount(const QMap<QByteArray, Method> &map);
|
||||
};
|
||||
|
||||
static const int intsPerProperty = 2;
|
||||
static const int intsPerMethod = 3;
|
||||
static const int intsPerMethod = 2;
|
||||
|
||||
struct QDBusMetaObjectPrivate : public QMetaObjectPrivate
|
||||
{
|
||||
@ -132,6 +134,30 @@ QDBusMetaObjectGenerator::findType(const QByteArray &signature,
|
||||
const QDBusIntrospection::Annotations &annotations,
|
||||
const char *direction, int id)
|
||||
{
|
||||
struct QDBusRawTypeHandler {
|
||||
static void destroy(void *)
|
||||
{
|
||||
qFatal("Cannot destroy placeholder type QDBusRawType");
|
||||
}
|
||||
|
||||
static void *create(const void *)
|
||||
{
|
||||
qFatal("Cannot create placeholder type QDBusRawType");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void destruct(void *)
|
||||
{
|
||||
qFatal("Cannot destruct placeholder type QDBusRawType");
|
||||
}
|
||||
|
||||
static void *construct(void *, const void *)
|
||||
{
|
||||
qFatal("Cannot construct placeholder type QDBusRawType");
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
Type result;
|
||||
result.id = QVariant::Invalid;
|
||||
|
||||
@ -157,8 +183,13 @@ QDBusMetaObjectGenerator::findType(const QByteArray &signature,
|
||||
if (type == QVariant::Invalid || signature != QDBusMetaType::typeToSignature(type)) {
|
||||
// type is still unknown or doesn't match back to the signature that it
|
||||
// was expected to, so synthesize a fake type
|
||||
type = QMetaType::VoidStar;
|
||||
typeName = "QDBusRawType<0x" + signature.toHex() + ">*";
|
||||
type = QMetaType::registerType(typeName, QDBusRawTypeHandler::destroy,
|
||||
QDBusRawTypeHandler::create,
|
||||
QDBusRawTypeHandler::destruct,
|
||||
QDBusRawTypeHandler::construct,
|
||||
sizeof(void *),
|
||||
QMetaType::MovableType);
|
||||
}
|
||||
|
||||
result.name = typeName;
|
||||
@ -215,8 +246,7 @@ void QDBusMetaObjectGenerator::parseMethods()
|
||||
|
||||
mm.inputTypes.append(type.id);
|
||||
|
||||
mm.parameters.append(arg.name.toLatin1());
|
||||
mm.parameters.append(',');
|
||||
mm.parameterNames.append(arg.name.toLatin1());
|
||||
|
||||
prototype.append(type.name);
|
||||
prototype.append(',');
|
||||
@ -235,13 +265,9 @@ void QDBusMetaObjectGenerator::parseMethods()
|
||||
|
||||
mm.outputTypes.append(type.id);
|
||||
|
||||
if (i == 0) {
|
||||
// return value
|
||||
mm.typeName = type.name;
|
||||
} else {
|
||||
if (i != 0) {
|
||||
// non-const ref parameter
|
||||
mm.parameters.append(arg.name.toLatin1());
|
||||
mm.parameters.append(',');
|
||||
mm.parameterNames.append(arg.name.toLatin1());
|
||||
|
||||
prototype.append(type.name);
|
||||
prototype.append("&,");
|
||||
@ -250,12 +276,10 @@ void QDBusMetaObjectGenerator::parseMethods()
|
||||
if (!ok) continue;
|
||||
|
||||
// convert the last commas:
|
||||
if (!mm.parameters.isEmpty()) {
|
||||
mm.parameters.truncate(mm.parameters.length() - 1);
|
||||
if (!mm.parameterNames.isEmpty())
|
||||
prototype[prototype.length() - 1] = ')';
|
||||
} else {
|
||||
else
|
||||
prototype.append(')');
|
||||
}
|
||||
|
||||
// check the async tag
|
||||
if (m.annotations.value(QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true"))
|
||||
@ -295,8 +319,7 @@ void QDBusMetaObjectGenerator::parseSignals()
|
||||
|
||||
mm.inputTypes.append(type.id);
|
||||
|
||||
mm.parameters.append(arg.name.toLatin1());
|
||||
mm.parameters.append(',');
|
||||
mm.parameterNames.append(arg.name.toLatin1());
|
||||
|
||||
prototype.append(type.name);
|
||||
prototype.append(',');
|
||||
@ -304,12 +327,10 @@ void QDBusMetaObjectGenerator::parseSignals()
|
||||
if (!ok) continue;
|
||||
|
||||
// convert the last commas:
|
||||
if (!mm.parameters.isEmpty()) {
|
||||
mm.parameters.truncate(mm.parameters.length() - 1);
|
||||
if (!mm.parameterNames.isEmpty())
|
||||
prototype[prototype.length() - 1] = ')';
|
||||
} else {
|
||||
else
|
||||
prototype.append(')');
|
||||
}
|
||||
|
||||
// meta method flags
|
||||
mm.flags = AccessProtected | MethodSignal | MethodScriptable;
|
||||
@ -342,49 +363,27 @@ void QDBusMetaObjectGenerator::parseProperties()
|
||||
if (p.access != QDBusIntrospection::Property::Read)
|
||||
mp.flags |= Writable;
|
||||
|
||||
if (mp.typeName == "QDBusVariant")
|
||||
mp.flags |= QMetaType::QVariant << 24;
|
||||
else if (mp.type < 0xff)
|
||||
// encode the type in the flags
|
||||
mp.flags |= mp.type << 24;
|
||||
|
||||
// add the property:
|
||||
properties.insert(name, mp);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the sum of all parameters (including return type) for the given
|
||||
// \a map of methods. This is needed for calculating the size of the methods'
|
||||
// parameter type/name meta-data.
|
||||
int QDBusMetaObjectGenerator::aggregateParameterCount(const QMap<QByteArray, Method> &map)
|
||||
{
|
||||
int sum = 0;
|
||||
QMap<QByteArray, Method>::const_iterator it;
|
||||
for (it = map.constBegin(); it != map.constEnd(); ++it) {
|
||||
const Method &m = it.value();
|
||||
sum += m.inputTypes.size() + qMax(1, m.outputTypes.size());
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
|
||||
{
|
||||
class MetaStringTable
|
||||
{
|
||||
public:
|
||||
typedef QHash<QByteArray, int> Entries; // string --> offset mapping
|
||||
typedef Entries::const_iterator const_iterator;
|
||||
Entries::const_iterator constBegin() const
|
||||
{ return m_entries.constBegin(); }
|
||||
Entries::const_iterator constEnd() const
|
||||
{ return m_entries.constEnd(); }
|
||||
|
||||
MetaStringTable() : m_offset(0) {}
|
||||
|
||||
int enter(const QByteArray &value)
|
||||
{
|
||||
Entries::iterator it = m_entries.find(value);
|
||||
if (it != m_entries.end())
|
||||
return it.value();
|
||||
int pos = m_offset;
|
||||
m_entries.insert(value, pos);
|
||||
m_offset += value.size() + 1;
|
||||
return pos;
|
||||
}
|
||||
|
||||
int arraySize() const { return m_offset; }
|
||||
|
||||
private:
|
||||
Entries m_entries;
|
||||
int m_offset;
|
||||
};
|
||||
|
||||
// this code here is mostly copied from qaxbase.cpp
|
||||
// with a few modifications to make it cleaner
|
||||
|
||||
@ -396,8 +395,14 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
|
||||
QVarLengthArray<int> idata;
|
||||
idata.resize(sizeof(QDBusMetaObjectPrivate) / sizeof(int));
|
||||
|
||||
int methodParametersDataSize =
|
||||
((aggregateParameterCount(signals_)
|
||||
+ aggregateParameterCount(methods)) * 2) // types and parameter names
|
||||
- signals_.count() // return "parameters" don't have names
|
||||
- methods.count(); // ditto
|
||||
|
||||
QDBusMetaObjectPrivate *header = reinterpret_cast<QDBusMetaObjectPrivate *>(idata.data());
|
||||
Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 6, "QtDBus meta-object generator should generate the same version as moc");
|
||||
Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 7, "QtDBus meta-object generator should generate the same version as moc");
|
||||
header->revision = QMetaObjectPrivate::OutputRevision;
|
||||
header->className = 0;
|
||||
header->classInfoCount = 0;
|
||||
@ -405,7 +410,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
|
||||
header->methodCount = signals_.count() + methods.count();
|
||||
header->methodData = idata.size();
|
||||
header->propertyCount = properties.count();
|
||||
header->propertyData = header->methodData + header->methodCount * 5;
|
||||
header->propertyData = header->methodData + header->methodCount * 5 + methodParametersDataSize;
|
||||
header->enumeratorCount = 0;
|
||||
header->enumeratorData = 0;
|
||||
header->constructorCount = 0;
|
||||
@ -417,7 +422,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
|
||||
header->methodDBusData = header->propertyDBusData + header->propertyCount * intsPerProperty;
|
||||
|
||||
int data_size = idata.size() +
|
||||
(header->methodCount * (5+intsPerMethod)) +
|
||||
(header->methodCount * (5+intsPerMethod)) + methodParametersDataSize +
|
||||
(header->propertyCount * (3+intsPerProperty));
|
||||
foreach (const Method &mm, signals_)
|
||||
data_size += 2 + mm.inputTypes.count() + mm.outputTypes.count();
|
||||
@ -425,10 +430,11 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
|
||||
data_size += 2 + mm.inputTypes.count() + mm.outputTypes.count();
|
||||
idata.resize(data_size + 1);
|
||||
|
||||
MetaStringTable strings;
|
||||
QMetaStringTable strings;
|
||||
strings.enter(className.toLatin1());
|
||||
|
||||
int offset = header->methodData;
|
||||
int parametersOffset = offset + header->methodCount * 5;
|
||||
int signatureOffset = header->methodDBusData;
|
||||
int typeidOffset = header->methodDBusData + header->methodCount * intsPerMethod;
|
||||
idata[typeidOffset++] = 0; // eod
|
||||
@ -439,16 +445,45 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
|
||||
QMap<QByteArray, Method> &map = (x == 0) ? signals_ : methods;
|
||||
for (QMap<QByteArray, Method>::ConstIterator it = map.constBegin();
|
||||
it != map.constEnd(); ++it) {
|
||||
// form "prototype\0parameters\0typeName\0tag\0methodname\0"
|
||||
const Method &mm = it.value();
|
||||
|
||||
idata[offset++] = strings.enter(it.key()); // prototype
|
||||
idata[offset++] = strings.enter(mm.parameters);
|
||||
idata[offset++] = strings.enter(mm.typeName);
|
||||
int argc = mm.inputTypes.size() + qMax(0, mm.outputTypes.size() - 1);
|
||||
|
||||
idata[offset++] = strings.enter(mm.name);
|
||||
idata[offset++] = argc;
|
||||
idata[offset++] = parametersOffset;
|
||||
idata[offset++] = strings.enter(mm.tag);
|
||||
idata[offset++] = mm.flags;
|
||||
|
||||
idata[signatureOffset++] = strings.enter(mm.name);
|
||||
// Parameter types
|
||||
for (int i = -1; i < argc; ++i) {
|
||||
int type;
|
||||
QByteArray typeName;
|
||||
if (i < 0) { // Return type
|
||||
if (!mm.outputTypes.isEmpty())
|
||||
type = mm.outputTypes.first();
|
||||
else
|
||||
type = QMetaType::Void;
|
||||
} else if (i < mm.inputTypes.size()) {
|
||||
type = mm.inputTypes.at(i);
|
||||
} else {
|
||||
Q_ASSERT(mm.outputTypes.size() > 1);
|
||||
type = mm.outputTypes.at(i - mm.inputTypes.size() + 1);
|
||||
// Output parameters are references; type id not available
|
||||
typeName = QMetaType::typeName(type);
|
||||
typeName.append('&');
|
||||
}
|
||||
Q_ASSERT(type != QMetaType::UnknownType);
|
||||
int typeInfo;
|
||||
if (!typeName.isEmpty())
|
||||
typeInfo = IsUnresolvedType | strings.enter(typeName);
|
||||
else
|
||||
typeInfo = type;
|
||||
idata[parametersOffset++] = typeInfo;
|
||||
}
|
||||
// Parameter names
|
||||
for (int i = 0; i < argc; ++i)
|
||||
idata[parametersOffset++] = strings.enter(mm.parameterNames.at(i));
|
||||
|
||||
idata[signatureOffset++] = typeidOffset;
|
||||
idata[typeidOffset++] = mm.inputTypes.count();
|
||||
@ -462,9 +497,12 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
|
||||
}
|
||||
}
|
||||
|
||||
Q_ASSERT(offset == header->propertyData);
|
||||
Q_ASSERT(offset == header->methodData + header->methodCount * 5);
|
||||
Q_ASSERT(parametersOffset = header->propertyData);
|
||||
Q_ASSERT(signatureOffset == header->methodDBusData + header->methodCount * intsPerMethod);
|
||||
Q_ASSERT(typeidOffset == idata.size());
|
||||
offset += methodParametersDataSize;
|
||||
Q_ASSERT(offset == header->propertyData);
|
||||
|
||||
// add each property
|
||||
signatureOffset = header->propertyDBusData;
|
||||
@ -472,9 +510,10 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
|
||||
it != properties.constEnd(); ++it) {
|
||||
const Property &mp = it.value();
|
||||
|
||||
// form is "name\0typeName\0signature\0"
|
||||
// form is name, typeinfo, flags
|
||||
idata[offset++] = strings.enter(it.key()); // name
|
||||
idata[offset++] = strings.enter(mp.typeName);
|
||||
Q_ASSERT(mp.type != QMetaType::UnknownType);
|
||||
idata[offset++] = mp.type;
|
||||
idata[offset++] = mp.flags;
|
||||
|
||||
idata[signatureOffset++] = strings.enter(mp.signature);
|
||||
@ -484,14 +523,8 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
|
||||
Q_ASSERT(offset == header->propertyDBusData);
|
||||
Q_ASSERT(signatureOffset == header->methodDBusData);
|
||||
|
||||
char *string_data = new char[strings.arraySize()];
|
||||
{
|
||||
MetaStringTable::const_iterator it;
|
||||
for (it = strings.constBegin(); it != strings.constEnd(); ++it) {
|
||||
memcpy(string_data + it.value(), it.key().constData(), it.key().size());
|
||||
string_data[it.value() + it.key().size()] = '\0';
|
||||
}
|
||||
}
|
||||
char *string_data = new char[strings.blobSize()];
|
||||
strings.writeBlob(string_data);
|
||||
|
||||
uint *uint_data = new uint[idata.size()];
|
||||
memcpy(uint_data, idata.data(), idata.size() * sizeof(int));
|
||||
@ -499,7 +532,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
|
||||
// put the metaobject together
|
||||
obj->d.data = uint_data;
|
||||
obj->d.extradata = 0;
|
||||
obj->d.stringdata = string_data;
|
||||
obj->d.stringdata = reinterpret_cast<const QByteArrayData *>(string_data);
|
||||
obj->d.superdata = &QDBusAbstractInterface::staticMetaObject;
|
||||
}
|
||||
|
||||
@ -613,22 +646,12 @@ static inline const QDBusMetaObjectPrivate *priv(const uint* data)
|
||||
return reinterpret_cast<const QDBusMetaObjectPrivate *>(data);
|
||||
}
|
||||
|
||||
const char *QDBusMetaObject::dbusNameForMethod(int id) const
|
||||
{
|
||||
//id -= methodOffset();
|
||||
if (id >= 0 && id < priv(d.data)->methodCount) {
|
||||
int handle = priv(d.data)->methodDBusData + id*intsPerMethod;
|
||||
return d.stringdata + d.data[handle];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int *QDBusMetaObject::inputTypesForMethod(int id) const
|
||||
{
|
||||
//id -= methodOffset();
|
||||
if (id >= 0 && id < priv(d.data)->methodCount) {
|
||||
int handle = priv(d.data)->methodDBusData + id*intsPerMethod;
|
||||
return reinterpret_cast<const int*>(d.data + d.data[handle + 1]);
|
||||
return reinterpret_cast<const int*>(d.data + d.data[handle]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -638,7 +661,7 @@ const int *QDBusMetaObject::outputTypesForMethod(int id) const
|
||||
//id -= methodOffset();
|
||||
if (id >= 0 && id < priv(d.data)->methodCount) {
|
||||
int handle = priv(d.data)->methodDBusData + id*intsPerMethod;
|
||||
return reinterpret_cast<const int*>(d.data + d.data[handle + 2]);
|
||||
return reinterpret_cast<const int*>(d.data + d.data[handle + 1]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -71,12 +71,11 @@ struct Q_DBUS_EXPORT QDBusMetaObject: public QMetaObject
|
||||
QDBusError &error);
|
||||
~QDBusMetaObject()
|
||||
{
|
||||
delete [] d.stringdata;
|
||||
delete [] reinterpret_cast<const char *>(d.stringdata);
|
||||
delete [] d.data;
|
||||
}
|
||||
|
||||
// methods (slots & signals):
|
||||
const char *dbusNameForMethod(int id) const;
|
||||
const int *inputTypesForMethod(int id) const;
|
||||
const int *outputTypesForMethod(int id) const;
|
||||
|
||||
|
@ -311,7 +311,7 @@ bool QDBusMetaType::demarshall(const QDBusArgument &arg, int id, void *data)
|
||||
int QDBusMetaType::signatureToType(const char *signature)
|
||||
{
|
||||
if (!signature)
|
||||
return QVariant::Invalid;
|
||||
return QMetaType::UnknownType;
|
||||
|
||||
QDBusMetaTypeId::init();
|
||||
switch (signature[0])
|
||||
@ -378,7 +378,7 @@ int QDBusMetaType::signatureToType(const char *signature)
|
||||
}
|
||||
// fall through
|
||||
default:
|
||||
return QVariant::Invalid;
|
||||
return QMetaType::UnknownType;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,7 +141,7 @@ int qDBusParametersForMethod(const QMetaMethod &mm, QList<int>& metaTypes)
|
||||
for ( ; it != end; ++it) {
|
||||
const QByteArray &type = *it;
|
||||
if (type.endsWith('*')) {
|
||||
//qWarning("Could not parse the method '%s'", mm.signature());
|
||||
//qWarning("Could not parse the method '%s'", mm.methodSignature().constData());
|
||||
// pointer?
|
||||
return -1;
|
||||
}
|
||||
@ -152,7 +152,7 @@ int qDBusParametersForMethod(const QMetaMethod &mm, QList<int>& metaTypes)
|
||||
|
||||
int id = QMetaType::type(basictype);
|
||||
if (id == 0) {
|
||||
//qWarning("Could not parse the method '%s'", mm.signature());
|
||||
//qWarning("Could not parse the method '%s'", mm.methodSignature().constData());
|
||||
// invalid type in method parameter list
|
||||
return -1;
|
||||
} else if (QDBusMetaType::typeToSignature(id) == 0)
|
||||
@ -164,14 +164,14 @@ int qDBusParametersForMethod(const QMetaMethod &mm, QList<int>& metaTypes)
|
||||
}
|
||||
|
||||
if (seenMessage) { // && !type.endsWith('&')
|
||||
//qWarning("Could not parse the method '%s'", mm.signature());
|
||||
//qWarning("Could not parse the method '%s'", mm.methodSignature().constData());
|
||||
// non-output parameters after message or after output params
|
||||
return -1; // not allowed
|
||||
}
|
||||
|
||||
int id = QMetaType::type(type);
|
||||
if (id == 0) {
|
||||
//qWarning("Could not parse the method '%s'", mm.signature());
|
||||
if (id == QMetaType::UnknownType) {
|
||||
//qWarning("Could not parse the method '%s'", mm.methodSignature().constData());
|
||||
// invalid type in method parameter list
|
||||
return -1;
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ static QString generateInterfaceXml(const QMetaObject *mo, int flags, int method
|
||||
// now add methods:
|
||||
for (int i = methodOffset; i < mo->methodCount(); ++i) {
|
||||
QMetaMethod mm = mo->method(i);
|
||||
QByteArray signature = mm.signature();
|
||||
QByteArray signature = mm.methodSignature();
|
||||
int paren = signature.indexOf('(');
|
||||
|
||||
bool isSignal;
|
||||
|
@ -78,10 +78,10 @@ QList<QByteArray> QAccessibleObjectPrivate::actionList() const
|
||||
continue;
|
||||
|
||||
if (!qstrcmp(member.tag(), "QACCESSIBLE_SLOT")) {
|
||||
if (member.signature() == defaultAction)
|
||||
if (member.methodSignature() == defaultAction)
|
||||
actionList.prepend(defaultAction);
|
||||
else
|
||||
actionList << member.signature();
|
||||
actionList << member.methodSignature();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ enum { IndentSpacesCount = 4 };
|
||||
|
||||
static QByteArray memberName(const QMetaMethod &member)
|
||||
{
|
||||
QByteArray ba = member.signature();
|
||||
QByteArray ba = member.methodSignature();
|
||||
return ba.left(ba.indexOf('('));
|
||||
}
|
||||
|
||||
@ -112,7 +112,8 @@ static void qSignalDumperCallback(QObject *caller, int method_index, void **argv
|
||||
|
||||
quintptr addr = quintptr(*reinterpret_cast<void **>(argv[i + 1]));
|
||||
str.append(QByteArray::number(addr, 16));
|
||||
} else if (typeId != QMetaType::Void) {
|
||||
} else if (typeId != QMetaType::UnknownType) {
|
||||
Q_ASSERT(typeId != QMetaType::Void); // void parameter => metaobject is corrupt
|
||||
str.append(arg)
|
||||
.append('(')
|
||||
.append(QVariant(typeId, argv[i + 1]).toString().toLocal8Bit())
|
||||
@ -152,7 +153,7 @@ static void qSignalDumperCallbackSlot(QObject *caller, int method_index, void **
|
||||
str += QByteArray::number(quintptr(caller), 16);
|
||||
|
||||
str += ") ";
|
||||
str += member.signature();
|
||||
str += member.methodSignature();
|
||||
qPrintMessage(str);
|
||||
}
|
||||
|
||||
|
@ -122,9 +122,11 @@ private:
|
||||
QList<QByteArray> params = member.parameterTypes();
|
||||
for (int i = 0; i < params.count(); ++i) {
|
||||
int tp = QMetaType::type(params.at(i).constData());
|
||||
if (tp == QMetaType::Void)
|
||||
if (tp == QMetaType::UnknownType) {
|
||||
Q_ASSERT(tp != QMetaType::Void); // void parameter => metaobject is corrupt
|
||||
qWarning("Don't know how to handle '%s', use qRegisterMetaType to register it.",
|
||||
params.at(i).constData());
|
||||
}
|
||||
args << tp;
|
||||
}
|
||||
}
|
||||
|
@ -1061,7 +1061,8 @@ static bool isValidSlot(const QMetaMethod &sl)
|
||||
if (sl.access() != QMetaMethod::Private || !sl.parameterTypes().isEmpty()
|
||||
|| qstrlen(sl.typeName()) || sl.methodType() != QMetaMethod::Slot)
|
||||
return false;
|
||||
const char *sig = sl.signature();
|
||||
QByteArray signature = sl.methodSignature();
|
||||
const char *sig = signature.constData();
|
||||
int len = qstrlen(sig);
|
||||
if (len < 2)
|
||||
return false;
|
||||
@ -1084,7 +1085,7 @@ static void qPrintTestSlots(FILE *stream)
|
||||
for (int i = 0; i < QTest::currentTestObject->metaObject()->methodCount(); ++i) {
|
||||
QMetaMethod sl = QTest::currentTestObject->metaObject()->method(i);
|
||||
if (isValidSlot(sl))
|
||||
fprintf(stream, "%s\n", sl.signature());
|
||||
fprintf(stream, "%s\n", sl.methodSignature().constData());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1109,7 +1110,7 @@ static void qPrintDataTags(FILE *stream)
|
||||
// Retrieve local tags:
|
||||
QStringList localTags;
|
||||
QTestTable table;
|
||||
char *slot = qstrdup(tf.signature());
|
||||
char *slot = qstrdup(tf.methodSignature().constData());
|
||||
slot[strlen(slot) - 2] = '\0';
|
||||
QByteArray member;
|
||||
member.resize(qstrlen(slot) + qstrlen("_data()") + 1);
|
||||
@ -1781,7 +1782,7 @@ static void qInvokeTestMethods(QObject *testObject)
|
||||
|
||||
if (QTest::testFuncs) {
|
||||
for (int i = 0; i != QTest::testFuncCount; i++) {
|
||||
if (!qInvokeTestMethod(metaObject->method(QTest::testFuncs[i].function()).signature(),
|
||||
if (!qInvokeTestMethod(metaObject->method(QTest::testFuncs[i].function()).methodSignature().constData(),
|
||||
QTest::testFuncs[i].data())) {
|
||||
break;
|
||||
}
|
||||
@ -1795,7 +1796,7 @@ static void qInvokeTestMethods(QObject *testObject)
|
||||
for (int i = 0; i != methodCount; i++) {
|
||||
if (!isValidSlot(testMethods[i]))
|
||||
continue;
|
||||
if (!qInvokeTestMethod(testMethods[i].signature()))
|
||||
if (!qInvokeTestMethod(testMethods[i].methodSignature().constData()))
|
||||
break;
|
||||
}
|
||||
delete[] testMethods;
|
||||
|
@ -54,30 +54,37 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
uint qvariant_nameToType(const QByteArray &name)
|
||||
uint nameToBuiltinType(const QByteArray &name)
|
||||
{
|
||||
if (name.isEmpty())
|
||||
return 0;
|
||||
|
||||
uint tp = QMetaType::type(name.constData());
|
||||
return tp < QMetaType::User ? tp : 0;
|
||||
return tp < uint(QMetaType::User) ? tp : QMetaType::UnknownType;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns true if the type is a QVariant types.
|
||||
Returns true if the type is a built-in type.
|
||||
*/
|
||||
bool isVariantType(const QByteArray &type)
|
||||
{
|
||||
return qvariant_nameToType(type) != 0;
|
||||
bool isBuiltinType(const QByteArray &type)
|
||||
{
|
||||
int id = QMetaType::type(type.constData());
|
||||
if (id == QMetaType::UnknownType)
|
||||
return false;
|
||||
return (id < QMetaType::User);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if the type is qreal.
|
||||
*/
|
||||
static bool isQRealType(const QByteArray &type)
|
||||
{
|
||||
return (type == "qreal");
|
||||
}
|
||||
static const char *metaTypeEnumValueString(int type)
|
||||
{
|
||||
#define RETURN_METATYPENAME_STRING(MetaTypeName, MetaTypeId, RealType) \
|
||||
case QMetaType::MetaTypeName: return #MetaTypeName;
|
||||
|
||||
switch (type) {
|
||||
QT_FOR_EACH_STATIC_TYPE(RETURN_METATYPENAME_STRING)
|
||||
}
|
||||
#undef RETURN_METATYPENAME_STRING
|
||||
return 0;
|
||||
}
|
||||
|
||||
Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, FILE *outfile)
|
||||
: out(outfile), cdef(classDef), metaTypes(metaTypes)
|
||||
@ -109,24 +116,28 @@ static inline int lengthOfEscapeSequence(const QByteArray &s, int i)
|
||||
return i - startPos;
|
||||
}
|
||||
|
||||
int Generator::strreg(const QByteArray &s)
|
||||
void Generator::strreg(const QByteArray &s)
|
||||
{
|
||||
int idx = 0;
|
||||
for (int i = 0; i < strings.size(); ++i) {
|
||||
const QByteArray &str = strings.at(i);
|
||||
if (str == s)
|
||||
return idx;
|
||||
idx += str.length() + 1;
|
||||
for (int i = 0; i < str.length(); ++i) {
|
||||
if (str.at(i) == '\\') {
|
||||
int cnt = lengthOfEscapeSequence(str, i) - 1;
|
||||
idx -= cnt;
|
||||
i += cnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!strings.contains(s))
|
||||
strings.append(s);
|
||||
return idx;
|
||||
}
|
||||
|
||||
int Generator::stridx(const QByteArray &s)
|
||||
{
|
||||
int i = strings.indexOf(s);
|
||||
Q_ASSERT_X(i != -1, Q_FUNC_INFO, "We forgot to register some strings");
|
||||
return i;
|
||||
}
|
||||
|
||||
// Returns the sum of all parameters (including return type) for the given
|
||||
// \a list of methods. This is needed for calculating the size of the methods'
|
||||
// parameter type/name meta-data.
|
||||
static int aggregateParameterCount(const QList<FunctionDef> &list)
|
||||
{
|
||||
int sum = 0;
|
||||
for (int i = 0; i < list.count(); ++i)
|
||||
sum += list.at(i).arguments.count() + 1; // +1 for return type
|
||||
return sum;
|
||||
}
|
||||
|
||||
void Generator::generateCode()
|
||||
@ -135,10 +146,6 @@ void Generator::generateCode()
|
||||
bool isQObject = (cdef->classname == "QObject");
|
||||
bool isConstructible = !cdef->constructorList.isEmpty();
|
||||
|
||||
//
|
||||
// build the data array
|
||||
//
|
||||
|
||||
// filter out undeclared enumerators and sets
|
||||
{
|
||||
QList<EnumDef> enumList;
|
||||
@ -156,95 +163,71 @@ void Generator::generateCode()
|
||||
cdef->enumList = enumList;
|
||||
}
|
||||
|
||||
//
|
||||
// Register all strings used in data section
|
||||
//
|
||||
strreg(cdef->qualified);
|
||||
registerClassInfoStrings();
|
||||
registerFunctionStrings(cdef->signalList);
|
||||
registerFunctionStrings(cdef->slotList);
|
||||
registerFunctionStrings(cdef->methodList);
|
||||
registerFunctionStrings(cdef->constructorList);
|
||||
registerPropertyStrings();
|
||||
registerEnumStrings();
|
||||
|
||||
QByteArray qualifiedClassNameIdentifier = cdef->qualified;
|
||||
qualifiedClassNameIdentifier.replace(':', '_');
|
||||
|
||||
int index = MetaObjectPrivateFieldCount;
|
||||
fprintf(out, "static const uint qt_meta_data_%s[] = {\n", qualifiedClassNameIdentifier.constData());
|
||||
fprintf(out, "\n // content:\n");
|
||||
fprintf(out, " %4d, // revision\n", int(QMetaObjectPrivate::OutputRevision));
|
||||
fprintf(out, " %4d, // classname\n", strreg(cdef->qualified));
|
||||
fprintf(out, " %4d, %4d, // classinfo\n", cdef->classInfoList.count(), cdef->classInfoList.count() ? index : 0);
|
||||
index += cdef->classInfoList.count() * 2;
|
||||
|
||||
int methodCount = cdef->signalList.count() + cdef->slotList.count() + cdef->methodList.count();
|
||||
fprintf(out, " %4d, %4d, // methods\n", methodCount, methodCount ? index : 0);
|
||||
index += methodCount * 5;
|
||||
if (cdef->revisionedMethods)
|
||||
index += methodCount;
|
||||
fprintf(out, " %4d, %4d, // properties\n", cdef->propertyList.count(), cdef->propertyList.count() ? index : 0);
|
||||
index += cdef->propertyList.count() * 3;
|
||||
if(cdef->notifyableProperties)
|
||||
index += cdef->propertyList.count();
|
||||
if (cdef->revisionedProperties)
|
||||
index += cdef->propertyList.count();
|
||||
fprintf(out, " %4d, %4d, // enums/sets\n", cdef->enumList.count(), cdef->enumList.count() ? index : 0);
|
||||
|
||||
int enumsIndex = index;
|
||||
for (int i = 0; i < cdef->enumList.count(); ++i)
|
||||
index += 4 + (cdef->enumList.at(i).values.count() * 2);
|
||||
fprintf(out, " %4d, %4d, // constructors\n", isConstructible ? cdef->constructorList.count() : 0,
|
||||
isConstructible ? index : 0);
|
||||
|
||||
fprintf(out, " %4d, // flags\n", 0);
|
||||
fprintf(out, " %4d, // signalCount\n", cdef->signalList.count());
|
||||
|
||||
|
||||
//
|
||||
// Build classinfo array
|
||||
// Build stringdata struct
|
||||
//
|
||||
generateClassInfos();
|
||||
|
||||
//
|
||||
// Build signals array first, otherwise the signal indices would be wrong
|
||||
//
|
||||
generateFunctions(cdef->signalList, "signal", MethodSignal);
|
||||
|
||||
//
|
||||
// Build slots array
|
||||
//
|
||||
generateFunctions(cdef->slotList, "slot", MethodSlot);
|
||||
|
||||
//
|
||||
// Build method array
|
||||
//
|
||||
generateFunctions(cdef->methodList, "method", MethodMethod);
|
||||
|
||||
//
|
||||
// Build method version arrays
|
||||
//
|
||||
if (cdef->revisionedMethods) {
|
||||
generateFunctionRevisions(cdef->signalList, "signal");
|
||||
generateFunctionRevisions(cdef->slotList, "slot");
|
||||
generateFunctionRevisions(cdef->methodList, "method");
|
||||
fprintf(out, "struct qt_meta_stringdata_%s_t {\n", qualifiedClassNameIdentifier.constData());
|
||||
fprintf(out, " QByteArrayData data[%d];\n", strings.size());
|
||||
{
|
||||
int len = 0;
|
||||
for (int i = 0; i < strings.size(); ++i)
|
||||
len += strings.at(i).length() + 1;
|
||||
fprintf(out, " char stringdata[%d];\n", len + 1);
|
||||
}
|
||||
fprintf(out, "};\n");
|
||||
|
||||
//
|
||||
// Build property array
|
||||
//
|
||||
generateProperties();
|
||||
// Macro that expands into a QByteArrayData. The offset member is
|
||||
// calculated from 1) the offset of the actual characters in the
|
||||
// stringdata.stringdata member, and 2) the stringdata.data index of the
|
||||
// QByteArrayData being defined. This calculation relies on the
|
||||
// QByteArrayData::data() implementation returning simply "this + offset".
|
||||
fprintf(out, "#define QT_MOC_LITERAL(idx, ofs, len) { \\\n"
|
||||
" Q_REFCOUNT_INITIALIZE_STATIC, len, 0, 0, \\\n"
|
||||
" offsetof(qt_meta_stringdata_%s_t, stringdata) + ofs \\\n"
|
||||
" - idx * sizeof(QByteArrayData) \\\n"
|
||||
" }\n",
|
||||
qualifiedClassNameIdentifier.constData());
|
||||
|
||||
//
|
||||
// Build enums array
|
||||
//
|
||||
generateEnums(enumsIndex);
|
||||
|
||||
//
|
||||
// Build constructors array
|
||||
//
|
||||
if (isConstructible)
|
||||
generateFunctions(cdef->constructorList, "constructor", MethodConstructor);
|
||||
|
||||
//
|
||||
// Terminate data array
|
||||
//
|
||||
fprintf(out, "\n 0 // eod\n};\n\n");
|
||||
fprintf(out, "static const qt_meta_stringdata_%s_t qt_meta_stringdata_%s = {\n",
|
||||
qualifiedClassNameIdentifier.constData(), qualifiedClassNameIdentifier.constData());
|
||||
fprintf(out, " {\n");
|
||||
{
|
||||
int idx = 0;
|
||||
for (int i = 0; i < strings.size(); ++i) {
|
||||
if (i)
|
||||
fprintf(out, ",\n");
|
||||
const QByteArray &str = strings.at(i);
|
||||
fprintf(out, "QT_MOC_LITERAL(%d, %d, %d)", i, idx, str.length());
|
||||
idx += str.length() + 1;
|
||||
for (int j = 0; j < str.length(); ++j) {
|
||||
if (str.at(j) == '\\') {
|
||||
int cnt = lengthOfEscapeSequence(str, j) - 1;
|
||||
idx -= cnt;
|
||||
j += cnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(out, "\n },\n");
|
||||
}
|
||||
|
||||
//
|
||||
// Build stringdata array
|
||||
//
|
||||
fprintf(out, "static const char qt_meta_stringdata_%s[] = {\n", qualifiedClassNameIdentifier.constData());
|
||||
fprintf(out, " \"");
|
||||
int col = 0;
|
||||
int len = 0;
|
||||
@ -279,7 +262,113 @@ void Generator::generateCode()
|
||||
fputs("\\0", out);
|
||||
col += len + 2;
|
||||
}
|
||||
fprintf(out, "\"\n};\n\n");
|
||||
|
||||
// Terminate stringdata struct
|
||||
fprintf(out, "\"\n};\n");
|
||||
fprintf(out, "#undef QT_MOC_LITERAL\n\n");
|
||||
|
||||
//
|
||||
// build the data array
|
||||
//
|
||||
|
||||
int index = MetaObjectPrivateFieldCount;
|
||||
fprintf(out, "static const uint qt_meta_data_%s[] = {\n", qualifiedClassNameIdentifier.constData());
|
||||
fprintf(out, "\n // content:\n");
|
||||
fprintf(out, " %4d, // revision\n", int(QMetaObjectPrivate::OutputRevision));
|
||||
fprintf(out, " %4d, // classname\n", stridx(cdef->qualified));
|
||||
fprintf(out, " %4d, %4d, // classinfo\n", cdef->classInfoList.count(), cdef->classInfoList.count() ? index : 0);
|
||||
index += cdef->classInfoList.count() * 2;
|
||||
|
||||
int methodCount = cdef->signalList.count() + cdef->slotList.count() + cdef->methodList.count();
|
||||
fprintf(out, " %4d, %4d, // methods\n", methodCount, methodCount ? index : 0);
|
||||
index += methodCount * 5;
|
||||
if (cdef->revisionedMethods)
|
||||
index += methodCount;
|
||||
int paramsIndex = index;
|
||||
int totalParameterCount = aggregateParameterCount(cdef->signalList)
|
||||
+ aggregateParameterCount(cdef->slotList)
|
||||
+ aggregateParameterCount(cdef->methodList)
|
||||
+ aggregateParameterCount(cdef->constructorList);
|
||||
index += totalParameterCount * 2 // types and parameter names
|
||||
- methodCount // return "parameters" don't have names
|
||||
- cdef->constructorList.count(); // "this" parameters don't have names
|
||||
|
||||
fprintf(out, " %4d, %4d, // properties\n", cdef->propertyList.count(), cdef->propertyList.count() ? index : 0);
|
||||
index += cdef->propertyList.count() * 3;
|
||||
if(cdef->notifyableProperties)
|
||||
index += cdef->propertyList.count();
|
||||
if (cdef->revisionedProperties)
|
||||
index += cdef->propertyList.count();
|
||||
fprintf(out, " %4d, %4d, // enums/sets\n", cdef->enumList.count(), cdef->enumList.count() ? index : 0);
|
||||
|
||||
int enumsIndex = index;
|
||||
for (int i = 0; i < cdef->enumList.count(); ++i)
|
||||
index += 4 + (cdef->enumList.at(i).values.count() * 2);
|
||||
fprintf(out, " %4d, %4d, // constructors\n", isConstructible ? cdef->constructorList.count() : 0,
|
||||
isConstructible ? index : 0);
|
||||
|
||||
fprintf(out, " %4d, // flags\n", 0);
|
||||
fprintf(out, " %4d, // signalCount\n", cdef->signalList.count());
|
||||
|
||||
|
||||
//
|
||||
// Build classinfo array
|
||||
//
|
||||
generateClassInfos();
|
||||
|
||||
//
|
||||
// Build signals array first, otherwise the signal indices would be wrong
|
||||
//
|
||||
generateFunctions(cdef->signalList, "signal", MethodSignal, paramsIndex);
|
||||
|
||||
//
|
||||
// Build slots array
|
||||
//
|
||||
generateFunctions(cdef->slotList, "slot", MethodSlot, paramsIndex);
|
||||
|
||||
//
|
||||
// Build method array
|
||||
//
|
||||
generateFunctions(cdef->methodList, "method", MethodMethod, paramsIndex);
|
||||
|
||||
//
|
||||
// Build method version arrays
|
||||
//
|
||||
if (cdef->revisionedMethods) {
|
||||
generateFunctionRevisions(cdef->signalList, "signal");
|
||||
generateFunctionRevisions(cdef->slotList, "slot");
|
||||
generateFunctionRevisions(cdef->methodList, "method");
|
||||
}
|
||||
|
||||
//
|
||||
// Build method parameters array
|
||||
//
|
||||
generateFunctionParameters(cdef->signalList, "signal");
|
||||
generateFunctionParameters(cdef->slotList, "slot");
|
||||
generateFunctionParameters(cdef->methodList, "method");
|
||||
if (isConstructible)
|
||||
generateFunctionParameters(cdef->constructorList, "constructor");
|
||||
|
||||
//
|
||||
// Build property array
|
||||
//
|
||||
generateProperties();
|
||||
|
||||
//
|
||||
// Build enums array
|
||||
//
|
||||
generateEnums(enumsIndex);
|
||||
|
||||
//
|
||||
// Build constructors array
|
||||
//
|
||||
if (isConstructible)
|
||||
generateFunctions(cdef->constructorList, "constructor", MethodConstructor, paramsIndex);
|
||||
|
||||
//
|
||||
// Terminate data array
|
||||
//
|
||||
fprintf(out, "\n 0 // eod\n};\n\n");
|
||||
|
||||
//
|
||||
// Generate internal qt_static_metacall() function
|
||||
@ -293,7 +382,7 @@ void Generator::generateCode()
|
||||
QList<QByteArray> extraList;
|
||||
for (int i = 0; i < cdef->propertyList.count(); ++i) {
|
||||
const PropertyDef &p = cdef->propertyList.at(i);
|
||||
if (!isVariantType(p.type) && !metaTypes.contains(p.type) && !p.type.contains('*') &&
|
||||
if (!isBuiltinType(p.type) && !metaTypes.contains(p.type) && !p.type.contains('*') &&
|
||||
!p.type.contains('<') && !p.type.contains('>')) {
|
||||
int s = p.type.lastIndexOf("::");
|
||||
if (s > 0) {
|
||||
@ -356,8 +445,9 @@ void Generator::generateCode()
|
||||
fprintf(out, " { &%s::staticMetaObject, ", purestSuperClass.constData());
|
||||
else
|
||||
fprintf(out, " { 0, ");
|
||||
fprintf(out, "qt_meta_stringdata_%s,\n qt_meta_data_%s, ",
|
||||
qualifiedClassNameIdentifier.constData(), qualifiedClassNameIdentifier.constData());
|
||||
fprintf(out, "qt_meta_stringdata_%s.data,\n"
|
||||
" qt_meta_data_%s, ", qualifiedClassNameIdentifier.constData(),
|
||||
qualifiedClassNameIdentifier.constData());
|
||||
if (!hasExtraData)
|
||||
fprintf(out, "0 }\n");
|
||||
else
|
||||
@ -379,7 +469,7 @@ void Generator::generateCode()
|
||||
//
|
||||
fprintf(out, "\nvoid *%s::qt_metacast(const char *_clname)\n{\n", cdef->qualified.constData());
|
||||
fprintf(out, " if (!_clname) return 0;\n");
|
||||
fprintf(out, " if (!strcmp(_clname, qt_meta_stringdata_%s))\n"
|
||||
fprintf(out, " if (!strcmp(_clname, qt_meta_stringdata_%s.stringdata))\n"
|
||||
" return static_cast<void*>(const_cast< %s*>(this));\n",
|
||||
qualifiedClassNameIdentifier.constData(), cdef->classname.constData());
|
||||
for (int i = 1; i < cdef->superclassList.size(); ++i) { // for all superclasses but the first one
|
||||
@ -430,6 +520,15 @@ void Generator::generateCode()
|
||||
}
|
||||
|
||||
|
||||
void Generator::registerClassInfoStrings()
|
||||
{
|
||||
for (int i = 0; i < cdef->classInfoList.size(); ++i) {
|
||||
const ClassInfoDef &c = cdef->classInfoList.at(i);
|
||||
strreg(c.name);
|
||||
strreg(c.value);
|
||||
}
|
||||
}
|
||||
|
||||
void Generator::generateClassInfos()
|
||||
{
|
||||
if (cdef->classInfoList.isEmpty())
|
||||
@ -439,32 +538,37 @@ void Generator::generateClassInfos()
|
||||
|
||||
for (int i = 0; i < cdef->classInfoList.size(); ++i) {
|
||||
const ClassInfoDef &c = cdef->classInfoList.at(i);
|
||||
fprintf(out, " %4d, %4d,\n", strreg(c.name), strreg(c.value));
|
||||
fprintf(out, " %4d, %4d,\n", stridx(c.name), stridx(c.value));
|
||||
}
|
||||
}
|
||||
|
||||
void Generator::generateFunctions(const QList<FunctionDef>& list, const char *functype, int type)
|
||||
void Generator::registerFunctionStrings(const QList<FunctionDef>& list)
|
||||
{
|
||||
if (list.isEmpty())
|
||||
return;
|
||||
fprintf(out, "\n // %ss: signature, parameters, type, tag, flags\n", functype);
|
||||
|
||||
for (int i = 0; i < list.count(); ++i) {
|
||||
const FunctionDef &f = list.at(i);
|
||||
|
||||
QByteArray sig = f.name + '(';
|
||||
QByteArray arguments;
|
||||
strreg(f.name);
|
||||
if (!isBuiltinType(f.normalizedType))
|
||||
strreg(f.normalizedType);
|
||||
strreg(f.tag);
|
||||
|
||||
for (int j = 0; j < f.arguments.count(); ++j) {
|
||||
const ArgumentDef &a = f.arguments.at(j);
|
||||
if (j) {
|
||||
sig += ",";
|
||||
arguments += ",";
|
||||
if (!isBuiltinType(a.normalizedType))
|
||||
strreg(a.normalizedType);
|
||||
strreg(a.name);
|
||||
}
|
||||
sig += a.normalizedType;
|
||||
arguments += a.name;
|
||||
}
|
||||
sig += ')';
|
||||
}
|
||||
|
||||
void Generator::generateFunctions(const QList<FunctionDef>& list, const char *functype, int type, int ¶msIndex)
|
||||
{
|
||||
if (list.isEmpty())
|
||||
return;
|
||||
fprintf(out, "\n // %ss: name, argc, parameters, tag, flags\n", functype);
|
||||
|
||||
for (int i = 0; i < list.count(); ++i) {
|
||||
const FunctionDef &f = list.at(i);
|
||||
|
||||
unsigned char flags = type;
|
||||
if (f.access == FunctionDef::Private)
|
||||
@ -487,8 +591,12 @@ void Generator::generateFunctions(const QList<FunctionDef>& list, const char *fu
|
||||
flags |= MethodScriptable;
|
||||
if (f.revision > 0)
|
||||
flags |= MethodRevisioned;
|
||||
fprintf(out, " %4d, %4d, %4d, %4d, 0x%02x,\n", strreg(sig),
|
||||
strreg(arguments), strreg(f.normalizedType), strreg(f.tag), flags);
|
||||
|
||||
int argc = f.arguments.count();
|
||||
fprintf(out, " %4d, %4d, %4d, %4d, 0x%02x,\n",
|
||||
stridx(f.name), argc, paramsIndex, stridx(f.tag), flags);
|
||||
|
||||
paramsIndex += 1 + argc * 2;
|
||||
}
|
||||
}
|
||||
|
||||
@ -502,6 +610,54 @@ void Generator::generateFunctionRevisions(const QList<FunctionDef>& list, const
|
||||
}
|
||||
}
|
||||
|
||||
void Generator::generateFunctionParameters(const QList<FunctionDef>& list, const char *functype)
|
||||
{
|
||||
if (list.isEmpty())
|
||||
return;
|
||||
fprintf(out, "\n // %ss: parameters\n", functype);
|
||||
for (int i = 0; i < list.count(); ++i) {
|
||||
const FunctionDef &f = list.at(i);
|
||||
fprintf(out, " ");
|
||||
|
||||
// Types
|
||||
for (int j = -1; j < f.arguments.count(); ++j) {
|
||||
if (j > -1)
|
||||
fputc(' ', out);
|
||||
const QByteArray &typeName = (j < 0) ? f.normalizedType : f.arguments.at(j).normalizedType;
|
||||
if (isBuiltinType(typeName)) {
|
||||
int type = nameToBuiltinType(typeName);
|
||||
const char *valueString = metaTypeEnumValueString(type);
|
||||
if (valueString)
|
||||
fprintf(out, "QMetaType::%s", valueString);
|
||||
else
|
||||
fprintf(out, "%4d", type);
|
||||
} else {
|
||||
Q_ASSERT(!typeName.isEmpty() || f.isConstructor);
|
||||
fprintf(out, "0x%.8x | %d", IsUnresolvedType, stridx(typeName));
|
||||
}
|
||||
fputc(',', out);
|
||||
}
|
||||
|
||||
// Parameter names
|
||||
for (int j = 0; j < f.arguments.count(); ++j) {
|
||||
const ArgumentDef &arg = f.arguments.at(j);
|
||||
fprintf(out, " %4d,", stridx(arg.name));
|
||||
}
|
||||
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
void Generator::registerPropertyStrings()
|
||||
{
|
||||
for (int i = 0; i < cdef->propertyList.count(); ++i) {
|
||||
const PropertyDef &p = cdef->propertyList.at(i);
|
||||
strreg(p.name);
|
||||
if (!isBuiltinType(p.type))
|
||||
strreg(p.type);
|
||||
}
|
||||
}
|
||||
|
||||
void Generator::generateProperties()
|
||||
{
|
||||
//
|
||||
@ -513,11 +669,8 @@ void Generator::generateProperties()
|
||||
for (int i = 0; i < cdef->propertyList.count(); ++i) {
|
||||
const PropertyDef &p = cdef->propertyList.at(i);
|
||||
uint flags = Invalid;
|
||||
if (!isVariantType(p.type)) {
|
||||
if (!isBuiltinType(p.type))
|
||||
flags |= EnumOrFlag;
|
||||
} else if (!isQRealType(p.type)) {
|
||||
flags |= qvariant_nameToType(p.type) << 24;
|
||||
}
|
||||
if (!p.read.isEmpty())
|
||||
flags |= Readable;
|
||||
if (!p.write.isEmpty()) {
|
||||
@ -567,12 +720,20 @@ void Generator::generateProperties()
|
||||
if (p.final)
|
||||
flags |= Final;
|
||||
|
||||
fprintf(out, " %4d, %4d, ",
|
||||
strreg(p.name),
|
||||
strreg(p.type));
|
||||
if (!(flags >> 24) && isQRealType(p.type))
|
||||
fprintf(out, "(QMetaType::QReal << 24) | ");
|
||||
fprintf(out, "0x%.8x,\n", flags);
|
||||
fprintf(out, " %4d, ", stridx(p.name));
|
||||
|
||||
if (isBuiltinType(p.type)) {
|
||||
int type = nameToBuiltinType(p.type);
|
||||
const char *valueString = metaTypeEnumValueString(type);
|
||||
if (valueString)
|
||||
fprintf(out, "QMetaType::%s", valueString);
|
||||
else
|
||||
fprintf(out, "%4d", type);
|
||||
} else {
|
||||
fprintf(out, "0x%.8x | %d", IsUnresolvedType, stridx(p.type));
|
||||
}
|
||||
|
||||
fprintf(out, ", 0x%.8x,\n", flags);
|
||||
}
|
||||
|
||||
if(cdef->notifyableProperties) {
|
||||
@ -596,6 +757,16 @@ void Generator::generateProperties()
|
||||
}
|
||||
}
|
||||
|
||||
void Generator::registerEnumStrings()
|
||||
{
|
||||
for (int i = 0; i < cdef->enumList.count(); ++i) {
|
||||
const EnumDef &e = cdef->enumList.at(i);
|
||||
strreg(e.name);
|
||||
for (int j = 0; j < e.values.count(); ++j)
|
||||
strreg(e.values.at(j));
|
||||
}
|
||||
}
|
||||
|
||||
void Generator::generateEnums(int index)
|
||||
{
|
||||
if (cdef->enumDeclarations.isEmpty())
|
||||
@ -607,7 +778,7 @@ void Generator::generateEnums(int index)
|
||||
for (i = 0; i < cdef->enumList.count(); ++i) {
|
||||
const EnumDef &e = cdef->enumList.at(i);
|
||||
fprintf(out, " %4d, 0x%.1x, %4d, %4d,\n",
|
||||
strreg(e.name),
|
||||
stridx(e.name),
|
||||
cdef->enumDeclarations.value(e.name) ? 1 : 0,
|
||||
e.values.count(),
|
||||
index);
|
||||
@ -624,7 +795,7 @@ void Generator::generateEnums(int index)
|
||||
code += "::" + e.name;
|
||||
code += "::" + val;
|
||||
fprintf(out, " %4d, uint(%s),\n",
|
||||
strreg(val), code.constData());
|
||||
stridx(val), code.constData());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -926,8 +1097,9 @@ void Generator::generateStaticMetacall()
|
||||
fprintf(out, " switch (_id) {\n");
|
||||
for (int methodindex = 0; methodindex < methodList.size(); ++methodindex) {
|
||||
const FunctionDef &f = methodList.at(methodindex);
|
||||
Q_ASSERT(!f.normalizedType.isEmpty());
|
||||
fprintf(out, " case %d: ", methodindex);
|
||||
if (f.normalizedType.size())
|
||||
if (f.normalizedType != "void")
|
||||
fprintf(out, "{ %s _r = ", noRef(f.normalizedType).constData());
|
||||
fprintf(out, "_t->");
|
||||
if (f.inPrivateClass.size())
|
||||
@ -942,7 +1114,7 @@ void Generator::generateStaticMetacall()
|
||||
isUsed_a = true;
|
||||
}
|
||||
fprintf(out, ");");
|
||||
if (f.normalizedType.size()) {
|
||||
if (f.normalizedType != "void") {
|
||||
fprintf(out, "\n if (_a[0]) *reinterpret_cast< %s*>(_a[0]) = _r; } ",
|
||||
noRef(f.normalizedType).constData());
|
||||
isUsed_a = true;
|
||||
@ -1021,7 +1193,8 @@ void Generator::generateSignal(FunctionDef *def,int index)
|
||||
constQualifier = "const";
|
||||
}
|
||||
|
||||
if (def->arguments.isEmpty() && def->normalizedType.isEmpty()) {
|
||||
Q_ASSERT(!def->normalizedType.isEmpty());
|
||||
if (def->arguments.isEmpty() && def->normalizedType == "void") {
|
||||
fprintf(out, ")%s\n{\n"
|
||||
" QMetaObject::activate(%s, &staticMetaObject, %d, 0);\n"
|
||||
"}\n", constQualifier, thisPtr.constData(), index);
|
||||
@ -1036,11 +1209,11 @@ void Generator::generateSignal(FunctionDef *def,int index)
|
||||
fprintf(out, "%s _t%d%s", a.type.name.constData(), offset++, a.rightType.constData());
|
||||
}
|
||||
fprintf(out, ")%s\n{\n", constQualifier);
|
||||
if (def->type.name.size() && def->normalizedType.size())
|
||||
if (def->type.name.size() && def->normalizedType != "void")
|
||||
fprintf(out, " %s _t0 = %s();\n", noRef(def->normalizedType).constData(), noRef(def->normalizedType).constData());
|
||||
|
||||
fprintf(out, " void *_a[] = { ");
|
||||
if (def->normalizedType.isEmpty()) {
|
||||
if (def->normalizedType == "void") {
|
||||
fprintf(out, "0");
|
||||
} else {
|
||||
if (def->returnTypeIsVolatile)
|
||||
@ -1056,7 +1229,7 @@ void Generator::generateSignal(FunctionDef *def,int index)
|
||||
fprintf(out, ", const_cast<void*>(reinterpret_cast<const void*>(&_t%d))", i);
|
||||
fprintf(out, " };\n");
|
||||
fprintf(out, " QMetaObject::activate(%s, &staticMetaObject, %d, _a);\n", thisPtr.constData(), index);
|
||||
if (def->normalizedType.size())
|
||||
if (def->normalizedType != "void")
|
||||
fprintf(out, " return _t0;\n");
|
||||
fprintf(out, "}\n");
|
||||
}
|
||||
|
@ -55,17 +55,23 @@ public:
|
||||
Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, FILE *outfile = 0);
|
||||
void generateCode();
|
||||
private:
|
||||
void registerClassInfoStrings();
|
||||
void generateClassInfos();
|
||||
void generateFunctions(const QList<FunctionDef> &list, const char *functype, int type);
|
||||
void registerFunctionStrings(const QList<FunctionDef> &list);
|
||||
void generateFunctions(const QList<FunctionDef> &list, const char *functype, int type, int ¶msIndex);
|
||||
void generateFunctionRevisions(const QList<FunctionDef>& list, const char *functype);
|
||||
void generateFunctionParameters(const QList<FunctionDef> &list, const char *functype);
|
||||
void registerEnumStrings();
|
||||
void generateEnums(int index);
|
||||
void registerPropertyStrings();
|
||||
void generateProperties();
|
||||
void generateMetacall();
|
||||
void generateStaticMetacall();
|
||||
void generateSignal(FunctionDef *def, int index);
|
||||
void generatePluginMetaData();
|
||||
|
||||
int strreg(const QByteArray &); // registers a string and returns its id
|
||||
void strreg(const QByteArray &); // registers a string
|
||||
int stridx(const QByteArray &); // returns a string's id
|
||||
QList<QByteArray> strings;
|
||||
QByteArray purestSuperClass;
|
||||
QList<QByteArray> metaTypes;
|
||||
|
@ -75,9 +75,7 @@ static QByteArray normalizeType(const QByteArray &ba, bool fixScope = false)
|
||||
}
|
||||
}
|
||||
*d = '\0';
|
||||
QByteArray result;
|
||||
if (strncmp("void", buf, d - buf) != 0)
|
||||
result = normalizeTypeInternal(buf, d, fixScope);
|
||||
QByteArray result = normalizeTypeInternal(buf, d, fixScope);
|
||||
if (buf != stackbuf)
|
||||
delete [] buf;
|
||||
return result;
|
||||
@ -822,8 +820,8 @@ void Moc::generate(FILE *out)
|
||||
if (classList.size() && classList.first().classname == "Qt")
|
||||
fprintf(out, "#include <QtCore/qobject.h>\n");
|
||||
|
||||
if (mustIncludeQMetaTypeH)
|
||||
fprintf(out, "#include <QtCore/qmetatype.h>\n");
|
||||
fprintf(out, "#include <QtCore/qbytearray.h>\n"); // For QByteArrayData
|
||||
fprintf(out, "#include <QtCore/qmetatype.h>\n"); // For QMetaType::Type
|
||||
if (mustIncludeQPluginH)
|
||||
fprintf(out, "#include <QtCore/qplugin.h>\n");
|
||||
|
||||
@ -981,8 +979,6 @@ void Moc::createPropertyDef(PropertyDef &propDef)
|
||||
type = "qlonglong";
|
||||
else if (type == "ULongLong")
|
||||
type = "qulonglong";
|
||||
else if (type == "qreal")
|
||||
mustIncludeQMetaTypeH = true;
|
||||
|
||||
propDef.type = type;
|
||||
|
||||
|
@ -200,7 +200,7 @@ class Moc : public Parser
|
||||
public:
|
||||
Moc(Preprocessor &p)
|
||||
: preprocessor(p), noInclude(false), generatedCode(false),
|
||||
mustIncludeQMetaTypeH(false), mustIncludeQPluginH(false)
|
||||
mustIncludeQPluginH(false)
|
||||
{}
|
||||
|
||||
QByteArray filename;
|
||||
@ -208,7 +208,6 @@ public:
|
||||
Preprocessor &preprocessor;
|
||||
bool noInclude;
|
||||
bool generatedCode;
|
||||
bool mustIncludeQMetaTypeH;
|
||||
bool mustIncludeQPluginH;
|
||||
QByteArray includePath;
|
||||
QList<QByteArray> includeFiles;
|
||||
|
@ -43,6 +43,6 @@
|
||||
#define OUTPUTREVISION_H
|
||||
|
||||
// if the output revision changes, you MUST change it in qobjectdefs.h too
|
||||
enum { mocOutputRevision = 64 }; // moc format output revision
|
||||
enum { mocOutputRevision = 65 }; // moc format output revision
|
||||
|
||||
#endif // OUTPUTREVISION_H
|
||||
|
@ -223,7 +223,7 @@ void tst_QMetaMethod::method_data()
|
||||
|
||||
QTest::newRow("MethodTestObject()")
|
||||
<< QByteArray("MethodTestObject()")
|
||||
<< int(QMetaType::Void) << QByteArray("")
|
||||
<< int(QMetaType::UnknownType) << QByteArray("")
|
||||
<< (QList<int>())
|
||||
<< (QList<QByteArray>())
|
||||
<< (QList<QByteArray>())
|
||||
@ -259,7 +259,7 @@ void tst_QMetaMethod::method_data()
|
||||
|
||||
QTest::newRow("MethodTestObject(int)")
|
||||
<< QByteArray("MethodTestObject(int)")
|
||||
<< int(QMetaType::Void) << QByteArray("")
|
||||
<< int(QMetaType::UnknownType) << QByteArray("")
|
||||
<< (QList<int>() << int(QMetaType::Int))
|
||||
<< (QList<QByteArray>() << QByteArray("int"))
|
||||
<< (QList<QByteArray>() << QByteArray("constructorIntArg"))
|
||||
@ -295,7 +295,7 @@ void tst_QMetaMethod::method_data()
|
||||
|
||||
QTest::newRow("MethodTestObject(qreal)")
|
||||
<< QByteArray("MethodTestObject(qreal)")
|
||||
<< int(QMetaType::Void) << QByteArray("")
|
||||
<< int(QMetaType::UnknownType) << QByteArray("")
|
||||
<< (QList<int>() << qMetaTypeId<qreal>())
|
||||
<< (QList<QByteArray>() << QByteArray("qreal"))
|
||||
<< (QList<QByteArray>() << QByteArray("constructorQRealArg"))
|
||||
@ -331,7 +331,7 @@ void tst_QMetaMethod::method_data()
|
||||
|
||||
QTest::newRow("MethodTestObject(QString)")
|
||||
<< QByteArray("MethodTestObject(QString)")
|
||||
<< int(QMetaType::Void) << QByteArray("")
|
||||
<< int(QMetaType::UnknownType) << QByteArray("")
|
||||
<< (QList<int>() << int(QMetaType::QString))
|
||||
<< (QList<QByteArray>() << QByteArray("QString"))
|
||||
<< (QList<QByteArray>() << QByteArray("constructorQStringArg"))
|
||||
@ -367,7 +367,7 @@ void tst_QMetaMethod::method_data()
|
||||
|
||||
QTest::newRow("MethodTestObject(CustomType)")
|
||||
<< QByteArray("MethodTestObject(CustomType)")
|
||||
<< int(QMetaType::Void) << QByteArray("")
|
||||
<< int(QMetaType::UnknownType) << QByteArray("")
|
||||
<< (QList<int>() << qMetaTypeId<CustomType>())
|
||||
<< (QList<QByteArray>() << QByteArray("CustomType"))
|
||||
<< (QList<QByteArray>() << QByteArray("constructorCustomTypeArg"))
|
||||
@ -403,7 +403,7 @@ void tst_QMetaMethod::method_data()
|
||||
|
||||
QTest::newRow("MethodTestObject(CustomUnregisteredType)")
|
||||
<< QByteArray("MethodTestObject(CustomUnregisteredType)")
|
||||
<< int(QMetaType::Void) << QByteArray("")
|
||||
<< int(QMetaType::UnknownType) << QByteArray("")
|
||||
<< (QList<int>() << 0)
|
||||
<< (QList<QByteArray>() << QByteArray("CustomUnregisteredType"))
|
||||
<< (QList<QByteArray>() << QByteArray("constructorCustomUnregisteredTypeArg"))
|
||||
@ -536,7 +536,7 @@ void tst_QMetaMethod::method_data()
|
||||
|
||||
QTest::newRow("MethodTestObject(bool,int,uint,qlonglong,qulonglong,double,long,short,char,ulong,ushort,uchar,float)")
|
||||
<< QByteArray("MethodTestObject(bool,int,uint,qlonglong,qulonglong,double,long,short,char,ulong,ushort,uchar,float)")
|
||||
<< int(QMetaType::Void) << QByteArray("")
|
||||
<< int(QMetaType::UnknownType) << QByteArray("")
|
||||
<< parameterTypes << parameterTypeNames << parameterNames
|
||||
<< QMetaMethod::Public
|
||||
<< QMetaMethod::Constructor;
|
||||
@ -571,7 +571,7 @@ void tst_QMetaMethod::method_data()
|
||||
|
||||
QTest::newRow("MethodTestObject(bool,int)")
|
||||
<< QByteArray("MethodTestObject(bool,int)")
|
||||
<< int(QMetaType::Void) << QByteArray("")
|
||||
<< int(QMetaType::UnknownType) << QByteArray("")
|
||||
<< (QList<int>() << int(QMetaType::Bool) << int(QMetaType::Int))
|
||||
<< (QList<QByteArray>() << QByteArray("bool") << QByteArray("int"))
|
||||
<< (QList<QByteArray>() << QByteArray("") << QByteArray(""))
|
||||
@ -603,15 +603,50 @@ void tst_QMetaMethod::method()
|
||||
QCOMPARE(method.methodType(), methodType);
|
||||
QCOMPARE(method.access(), access);
|
||||
|
||||
QCOMPARE(method.signature(), signature.constData());
|
||||
QVERIFY(!method.methodSignature().isEmpty());
|
||||
if (method.methodSignature() != signature) {
|
||||
// QMetaMethod should always produce a semantically equivalent signature
|
||||
int signatureIndex = (methodType == QMetaMethod::Constructor)
|
||||
? mo->indexOfConstructor(method.methodSignature())
|
||||
: mo->indexOfMethod(method.methodSignature());
|
||||
QCOMPARE(signatureIndex, index);
|
||||
}
|
||||
|
||||
QByteArray computedName = signature.left(signature.indexOf('('));
|
||||
QCOMPARE(method.name(), computedName);
|
||||
|
||||
QCOMPARE(method.tag(), "");
|
||||
QCOMPARE(method.returnType(), returnType);
|
||||
if (QByteArray(method.typeName()) != returnTypeName) {
|
||||
// QMetaMethod should always produce a semantically equivalent typename
|
||||
QCOMPARE(QMetaType::type(method.typeName()), QMetaType::type(returnTypeName));
|
||||
}
|
||||
|
||||
QCOMPARE(method.typeName(), returnTypeName.constData());
|
||||
QCOMPARE(QMetaType::type(method.typeName()), returnType);
|
||||
|
||||
QCOMPARE(method.parameterTypes(), parameterTypeNames);
|
||||
if (method.parameterTypes() != parameterTypeNames) {
|
||||
// QMetaMethod should always produce semantically equivalent typenames
|
||||
QList<QByteArray> actualTypeNames = method.parameterTypes();
|
||||
QCOMPARE(actualTypeNames.size(), parameterTypeNames.size());
|
||||
for (int i = 0; i < parameterTypeNames.size(); ++i) {
|
||||
QCOMPARE(QMetaType::type(actualTypeNames.at(i)),
|
||||
QMetaType::type(parameterTypeNames.at(i)));
|
||||
}
|
||||
}
|
||||
QCOMPARE(method.parameterNames(), parameterNames);
|
||||
|
||||
QCOMPARE(method.parameterCount(), parameterTypes.size());
|
||||
for (int i = 0; i < parameterTypes.size(); ++i)
|
||||
QCOMPARE(method.parameterType(i), parameterTypes.at(i));
|
||||
|
||||
{
|
||||
QVector<int> actualParameterTypes(parameterTypes.size());
|
||||
method.getParameterTypes(actualParameterTypes.data());
|
||||
for (int i = 0; i < parameterTypes.size(); ++i)
|
||||
QCOMPARE(actualParameterTypes.at(i), parameterTypes.at(i));
|
||||
}
|
||||
|
||||
// Bogus indexes
|
||||
QCOMPARE(method.parameterType(-1), 0);
|
||||
QCOMPARE(method.parameterType(parameterTypes.size()), 0);
|
||||
}
|
||||
|
||||
void tst_QMetaMethod::invalidMethod()
|
||||
|
@ -978,25 +978,25 @@ void tst_QMetaObject::propertyNotify()
|
||||
QVERIFY(prop.isValid());
|
||||
QVERIFY(prop.hasNotifySignal());
|
||||
QMetaMethod signal = prop.notifySignal();
|
||||
QCOMPARE(signal.signature(), "value6Changed()");
|
||||
QCOMPARE(signal.methodSignature(), QByteArray("value6Changed()"));
|
||||
|
||||
prop = mo->property(mo->indexOfProperty("value7"));
|
||||
QVERIFY(prop.isValid());
|
||||
QVERIFY(prop.hasNotifySignal());
|
||||
signal = prop.notifySignal();
|
||||
QCOMPARE(signal.signature(), "value7Changed(QString)");
|
||||
QCOMPARE(signal.methodSignature(), QByteArray("value7Changed(QString)"));
|
||||
|
||||
prop = mo->property(mo->indexOfProperty("value8"));
|
||||
QVERIFY(prop.isValid());
|
||||
QVERIFY(!prop.hasNotifySignal());
|
||||
signal = prop.notifySignal();
|
||||
QCOMPARE(signal.signature(), (const char *)0);
|
||||
QCOMPARE(signal.methodSignature(), QByteArray());
|
||||
|
||||
prop = mo->property(mo->indexOfProperty("value"));
|
||||
QVERIFY(prop.isValid());
|
||||
QVERIFY(!prop.hasNotifySignal());
|
||||
signal = prop.notifySignal();
|
||||
QCOMPARE(signal.signature(), (const char *)0);
|
||||
QCOMPARE(signal.methodSignature(), QByteArray());
|
||||
}
|
||||
|
||||
void tst_QMetaObject::propertyConstant()
|
||||
@ -1114,7 +1114,7 @@ void tst_QMetaObject::indexOfMethod()
|
||||
QFETCH(bool, isSignal);
|
||||
int idx = object->metaObject()->indexOfMethod(name);
|
||||
QVERIFY(idx >= 0);
|
||||
QCOMPARE(object->metaObject()->method(idx).signature(), name.constData());
|
||||
QCOMPARE(object->metaObject()->method(idx).methodSignature(), name);
|
||||
QCOMPARE(object->metaObject()->indexOfSlot(name), isSignal ? -1 : idx);
|
||||
QCOMPARE(object->metaObject()->indexOfSignal(name), !isSignal ? -1 : idx);
|
||||
}
|
||||
|
@ -217,6 +217,7 @@ void tst_QMetaObjectBuilder::method()
|
||||
QCOMPARE(nullMethod.signature(), QByteArray());
|
||||
QVERIFY(nullMethod.methodType() == QMetaMethod::Method);
|
||||
QVERIFY(nullMethod.returnType().isEmpty());
|
||||
QVERIFY(nullMethod.parameterTypes().isEmpty());
|
||||
QVERIFY(nullMethod.parameterNames().isEmpty());
|
||||
QVERIFY(nullMethod.tag().isEmpty());
|
||||
QVERIFY(nullMethod.access() == QMetaMethod::Public);
|
||||
@ -229,6 +230,7 @@ void tst_QMetaObjectBuilder::method()
|
||||
QCOMPARE(method1.signature(), QByteArray("foo(QString,int)"));
|
||||
QVERIFY(method1.methodType() == QMetaMethod::Method);
|
||||
QVERIFY(method1.returnType().isEmpty());
|
||||
QCOMPARE(method1.parameterTypes(), QList<QByteArray>() << "QString" << "int");
|
||||
QVERIFY(method1.parameterNames().isEmpty());
|
||||
QVERIFY(method1.tag().isEmpty());
|
||||
QVERIFY(method1.access() == QMetaMethod::Public);
|
||||
@ -242,6 +244,7 @@ void tst_QMetaObjectBuilder::method()
|
||||
QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
|
||||
QVERIFY(method2.methodType() == QMetaMethod::Method);
|
||||
QCOMPARE(method2.returnType(), QByteArray("int"));
|
||||
QCOMPARE(method2.parameterTypes(), QList<QByteArray>() << "QString");
|
||||
QVERIFY(method2.parameterNames().isEmpty());
|
||||
QVERIFY(method2.tag().isEmpty());
|
||||
QVERIFY(method2.access() == QMetaMethod::Public);
|
||||
@ -267,6 +270,7 @@ void tst_QMetaObjectBuilder::method()
|
||||
QCOMPARE(method1.signature(), QByteArray("foo(QString,int)"));
|
||||
QVERIFY(method1.methodType() == QMetaMethod::Method);
|
||||
QCOMPARE(method1.returnType(), QByteArray("int"));
|
||||
QCOMPARE(method1.parameterTypes(), QList<QByteArray>() << "QString" << "int");
|
||||
QCOMPARE(method1.parameterNames(), QList<QByteArray>() << "a" << "b");
|
||||
QCOMPARE(method1.tag(), QByteArray("tag"));
|
||||
QVERIFY(method1.access() == QMetaMethod::Private);
|
||||
@ -276,6 +280,7 @@ void tst_QMetaObjectBuilder::method()
|
||||
QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
|
||||
QVERIFY(method2.methodType() == QMetaMethod::Method);
|
||||
QCOMPARE(method2.returnType(), QByteArray("int"));
|
||||
QCOMPARE(method2.parameterTypes(), QList<QByteArray>() << "QString");
|
||||
QVERIFY(method2.parameterNames().isEmpty());
|
||||
QVERIFY(method2.tag().isEmpty());
|
||||
QVERIFY(method2.access() == QMetaMethod::Public);
|
||||
@ -296,6 +301,7 @@ void tst_QMetaObjectBuilder::method()
|
||||
QCOMPARE(method1.signature(), QByteArray("foo(QString,int)"));
|
||||
QVERIFY(method1.methodType() == QMetaMethod::Method);
|
||||
QCOMPARE(method1.returnType(), QByteArray("int"));
|
||||
QCOMPARE(method1.parameterTypes(), QList<QByteArray>() << "QString" << "int");
|
||||
QCOMPARE(method1.parameterNames(), QList<QByteArray>() << "a" << "b");
|
||||
QCOMPARE(method1.tag(), QByteArray("tag"));
|
||||
QVERIFY(method1.access() == QMetaMethod::Private);
|
||||
@ -305,6 +311,7 @@ void tst_QMetaObjectBuilder::method()
|
||||
QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
|
||||
QVERIFY(method2.methodType() == QMetaMethod::Method);
|
||||
QCOMPARE(method2.returnType(), QByteArray("QString"));
|
||||
QCOMPARE(method2.parameterTypes(), QList<QByteArray>() << "QString");
|
||||
QCOMPARE(method2.parameterNames(), QList<QByteArray>() << "c");
|
||||
QCOMPARE(method2.tag(), QByteArray("Q_FOO"));
|
||||
QVERIFY(method2.access() == QMetaMethod::Protected);
|
||||
@ -320,6 +327,7 @@ void tst_QMetaObjectBuilder::method()
|
||||
QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
|
||||
QVERIFY(method2.methodType() == QMetaMethod::Method);
|
||||
QCOMPARE(method2.returnType(), QByteArray("QString"));
|
||||
QCOMPARE(method2.parameterTypes(), QList<QByteArray>() << "QString");
|
||||
QCOMPARE(method2.parameterNames(), QList<QByteArray>() << "c");
|
||||
QCOMPARE(method2.tag(), QByteArray("Q_FOO"));
|
||||
QVERIFY(method2.access() == QMetaMethod::Protected);
|
||||
@ -347,6 +355,7 @@ void tst_QMetaObjectBuilder::slot()
|
||||
QCOMPARE(method1.signature(), QByteArray("foo(QString,int)"));
|
||||
QVERIFY(method1.methodType() == QMetaMethod::Slot);
|
||||
QVERIFY(method1.returnType().isEmpty());
|
||||
QCOMPARE(method1.parameterTypes(), QList<QByteArray>() << "QString" << "int");
|
||||
QVERIFY(method1.parameterNames().isEmpty());
|
||||
QVERIFY(method1.tag().isEmpty());
|
||||
QVERIFY(method1.access() == QMetaMethod::Public);
|
||||
@ -359,6 +368,7 @@ void tst_QMetaObjectBuilder::slot()
|
||||
QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
|
||||
QVERIFY(method2.methodType() == QMetaMethod::Slot);
|
||||
QVERIFY(method2.returnType().isEmpty());
|
||||
QCOMPARE(method2.parameterTypes(), QList<QByteArray>() << "QString");
|
||||
QVERIFY(method2.parameterNames().isEmpty());
|
||||
QVERIFY(method2.tag().isEmpty());
|
||||
QVERIFY(method2.access() == QMetaMethod::Public);
|
||||
@ -384,6 +394,7 @@ void tst_QMetaObjectBuilder::signal()
|
||||
QCOMPARE(method1.signature(), QByteArray("foo(QString,int)"));
|
||||
QVERIFY(method1.methodType() == QMetaMethod::Signal);
|
||||
QVERIFY(method1.returnType().isEmpty());
|
||||
QCOMPARE(method1.parameterTypes(), QList<QByteArray>() << "QString" << "int");
|
||||
QVERIFY(method1.parameterNames().isEmpty());
|
||||
QVERIFY(method1.tag().isEmpty());
|
||||
QVERIFY(method1.access() == QMetaMethod::Protected);
|
||||
@ -396,6 +407,7 @@ void tst_QMetaObjectBuilder::signal()
|
||||
QCOMPARE(method2.signature(), QByteArray("bar(QString)"));
|
||||
QVERIFY(method2.methodType() == QMetaMethod::Signal);
|
||||
QVERIFY(method2.returnType().isEmpty());
|
||||
QCOMPARE(method2.parameterTypes(), QList<QByteArray>() << "QString");
|
||||
QVERIFY(method2.parameterNames().isEmpty());
|
||||
QVERIFY(method2.tag().isEmpty());
|
||||
QVERIFY(method2.access() == QMetaMethod::Protected);
|
||||
@ -421,6 +433,7 @@ void tst_QMetaObjectBuilder::constructor()
|
||||
QCOMPARE(ctor1.signature(), QByteArray("foo(QString,int)"));
|
||||
QVERIFY(ctor1.methodType() == QMetaMethod::Constructor);
|
||||
QVERIFY(ctor1.returnType().isEmpty());
|
||||
QCOMPARE(ctor1.parameterTypes(), QList<QByteArray>() << "QString" << "int");
|
||||
QVERIFY(ctor1.parameterNames().isEmpty());
|
||||
QVERIFY(ctor1.tag().isEmpty());
|
||||
QVERIFY(ctor1.access() == QMetaMethod::Public);
|
||||
@ -433,6 +446,7 @@ void tst_QMetaObjectBuilder::constructor()
|
||||
QCOMPARE(ctor2.signature(), QByteArray("bar(QString)"));
|
||||
QVERIFY(ctor2.methodType() == QMetaMethod::Constructor);
|
||||
QVERIFY(ctor2.returnType().isEmpty());
|
||||
QCOMPARE(ctor2.parameterTypes(), QList<QByteArray>() << "QString");
|
||||
QVERIFY(ctor2.parameterNames().isEmpty());
|
||||
QVERIFY(ctor2.tag().isEmpty());
|
||||
QVERIFY(ctor2.access() == QMetaMethod::Public);
|
||||
@ -458,6 +472,7 @@ void tst_QMetaObjectBuilder::constructor()
|
||||
QCOMPARE(ctor1.signature(), QByteArray("foo(QString,int)"));
|
||||
QVERIFY(ctor1.methodType() == QMetaMethod::Constructor);
|
||||
QCOMPARE(ctor1.returnType(), QByteArray("int"));
|
||||
QCOMPARE(ctor1.parameterTypes(), QList<QByteArray>() << "QString" << "int");
|
||||
QCOMPARE(ctor1.parameterNames(), QList<QByteArray>() << "a" << "b");
|
||||
QCOMPARE(ctor1.tag(), QByteArray("tag"));
|
||||
QVERIFY(ctor1.access() == QMetaMethod::Private);
|
||||
@ -466,6 +481,7 @@ void tst_QMetaObjectBuilder::constructor()
|
||||
QCOMPARE(ctor2.signature(), QByteArray("bar(QString)"));
|
||||
QVERIFY(ctor2.methodType() == QMetaMethod::Constructor);
|
||||
QVERIFY(ctor2.returnType().isEmpty());
|
||||
QCOMPARE(ctor2.parameterTypes(), QList<QByteArray>() << "QString");
|
||||
QVERIFY(ctor2.parameterNames().isEmpty());
|
||||
QVERIFY(ctor2.tag().isEmpty());
|
||||
QVERIFY(ctor2.access() == QMetaMethod::Public);
|
||||
@ -484,6 +500,7 @@ void tst_QMetaObjectBuilder::constructor()
|
||||
QCOMPARE(ctor1.signature(), QByteArray("foo(QString,int)"));
|
||||
QVERIFY(ctor1.methodType() == QMetaMethod::Constructor);
|
||||
QCOMPARE(ctor1.returnType(), QByteArray("int"));
|
||||
QCOMPARE(ctor1.parameterTypes(), QList<QByteArray>() << "QString" << "int");
|
||||
QCOMPARE(ctor1.parameterNames(), QList<QByteArray>() << "a" << "b");
|
||||
QCOMPARE(ctor1.tag(), QByteArray("tag"));
|
||||
QVERIFY(ctor1.access() == QMetaMethod::Private);
|
||||
@ -492,6 +509,7 @@ void tst_QMetaObjectBuilder::constructor()
|
||||
QCOMPARE(ctor2.signature(), QByteArray("bar(QString)"));
|
||||
QVERIFY(ctor2.methodType() == QMetaMethod::Constructor);
|
||||
QCOMPARE(ctor2.returnType(), QByteArray("QString"));
|
||||
QCOMPARE(ctor2.parameterTypes(), QList<QByteArray>() << "QString");
|
||||
QCOMPARE(ctor2.parameterNames(), QList<QByteArray>() << "c");
|
||||
QCOMPARE(ctor2.tag(), QByteArray("Q_FOO"));
|
||||
QVERIFY(ctor2.access() == QMetaMethod::Protected);
|
||||
@ -506,6 +524,7 @@ void tst_QMetaObjectBuilder::constructor()
|
||||
QCOMPARE(ctor2.signature(), QByteArray("bar(QString)"));
|
||||
QVERIFY(ctor2.methodType() == QMetaMethod::Constructor);
|
||||
QCOMPARE(ctor2.returnType(), QByteArray("QString"));
|
||||
QCOMPARE(ctor2.parameterTypes(), QList<QByteArray>() << "QString");
|
||||
QCOMPARE(ctor2.parameterNames(), QList<QByteArray>() << "c");
|
||||
QCOMPARE(ctor2.tag(), QByteArray("Q_FOO"));
|
||||
QVERIFY(ctor2.access() == QMetaMethod::Protected);
|
||||
@ -525,6 +544,7 @@ void tst_QMetaObjectBuilder::constructor()
|
||||
QCOMPARE(prototypeConstructor.signature(), QByteArray("SomethingOfEverything()"));
|
||||
QVERIFY(prototypeConstructor.methodType() == QMetaMethod::Constructor);
|
||||
QCOMPARE(prototypeConstructor.returnType(), QByteArray());
|
||||
QVERIFY(prototypeConstructor.parameterTypes().isEmpty());
|
||||
QVERIFY(prototypeConstructor.access() == QMetaMethod::Public);
|
||||
QCOMPARE(prototypeConstructor.index(), 1);
|
||||
|
||||
@ -1161,12 +1181,15 @@ bool tst_QMetaObjectBuilder::checkForSideEffects
|
||||
|
||||
static bool sameMethod(const QMetaMethod& method1, const QMetaMethod& method2)
|
||||
{
|
||||
if (QByteArray(method1.signature()) != QByteArray(method2.signature()))
|
||||
if (method1.methodSignature() != method2.methodSignature())
|
||||
return false;
|
||||
|
||||
if (QByteArray(method1.typeName()) != QByteArray(method2.typeName()))
|
||||
return false;
|
||||
|
||||
if (method1.parameterTypes() != method2.parameterTypes())
|
||||
return false;
|
||||
|
||||
if (method1.parameterNames() != method2.parameterNames())
|
||||
return false;
|
||||
|
||||
@ -1466,7 +1489,7 @@ void TestObject::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id,
|
||||
if (_a[0]) *reinterpret_cast<QObject**>(_a[0]) = _r; } break;
|
||||
default: {
|
||||
QMetaMethod ctor = _o->metaObject()->constructor(_id);
|
||||
qFatal("You forgot to add a case for CreateInstance %s", ctor.signature());
|
||||
qFatal("You forgot to add a case for CreateInstance %s", ctor.methodSignature().constData());
|
||||
}
|
||||
}
|
||||
} else if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
@ -1478,7 +1501,7 @@ void TestObject::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id,
|
||||
case 2: *reinterpret_cast<QVariantList(*)>(_a[0]) = _t->listInvokableQRealQString(*reinterpret_cast<qreal(*)>(_a[1]), *reinterpret_cast<QString(*)>(_a[2])); break;
|
||||
default: {
|
||||
QMetaMethod method = _o->metaObject()->method(_o->metaObject()->methodOffset() + _id);
|
||||
qFatal("You forgot to add a case for InvokeMetaMethod %s", method.signature());
|
||||
qFatal("You forgot to add a case for InvokeMetaMethod %s", method.methodSignature().constData());
|
||||
}
|
||||
}
|
||||
} else if (_c == QMetaObject::IndexOfMethod) {
|
||||
|
@ -332,6 +332,7 @@ void tst_QMetaType::typeName_data()
|
||||
|
||||
QT_FOR_EACH_STATIC_TYPE(TYPENAME_DATA)
|
||||
QT_FOR_EACH_STATIC_ALIAS_TYPE(TYPENAME_DATA_ALIAS)
|
||||
QTest::newRow("QMetaType::UnknownType") << QMetaType::UnknownType << static_cast<const char*>(0);
|
||||
}
|
||||
|
||||
void tst_QMetaType::typeName()
|
||||
@ -642,6 +643,8 @@ void tst_QMetaType::sizeOf_data()
|
||||
{
|
||||
QTest::addColumn<QMetaType::Type>("type");
|
||||
QTest::addColumn<int>("size");
|
||||
|
||||
QTest::newRow("QMetaType::UnknownType") << QMetaType::UnknownType << 0;
|
||||
#define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \
|
||||
QTest::newRow(#RealType) << QMetaType::MetaTypeName << int(QTypeInfo<RealType>::sizeOf);
|
||||
FOR_EACH_CORE_METATYPE(ADD_METATYPE_TEST_ROW)
|
||||
@ -1040,6 +1043,7 @@ void tst_QMetaType::isRegistered_data()
|
||||
QTest::newRow("-1") << -1 << false;
|
||||
QTest::newRow("-42") << -42 << false;
|
||||
QTest::newRow("IsRegisteredDummyType + 1") << (dummyTypeId + 1) << false;
|
||||
QTest::newRow("QMetaType::UnknownType") << int(QMetaType::UnknownType) << false;
|
||||
}
|
||||
|
||||
void tst_QMetaType::isRegistered()
|
||||
|
@ -90,7 +90,7 @@ static const char qt_meta_stringdata_OldNormalizeObject[] = {
|
||||
};
|
||||
|
||||
const QMetaObject OldNormalizeObject::staticMetaObject = {
|
||||
{ &QObject::staticMetaObject, qt_meta_stringdata_OldNormalizeObject,
|
||||
{ &QObject::staticMetaObject, reinterpret_cast<const QByteArrayData *>(qt_meta_stringdata_OldNormalizeObject),
|
||||
qt_meta_data_OldNormalizeObject, 0 }
|
||||
};
|
||||
|
||||
|
@ -1793,56 +1793,56 @@ void tst_QObject::metamethod()
|
||||
QMetaMethod m;
|
||||
|
||||
m = mobj->method(mobj->indexOfMethod("invoke1()"));
|
||||
QVERIFY(QByteArray(m.signature()) == "invoke1()");
|
||||
QVERIFY(m.methodSignature() == "invoke1()");
|
||||
QVERIFY(m.methodType() == QMetaMethod::Method);
|
||||
QVERIFY(m.access() == QMetaMethod::Public);
|
||||
QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
|
||||
QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
|
||||
|
||||
m = mobj->method(mobj->indexOfMethod("sinvoke1()"));
|
||||
QVERIFY(QByteArray(m.signature()) == "sinvoke1()");
|
||||
QVERIFY(m.methodSignature() == "sinvoke1()");
|
||||
QVERIFY(m.methodType() == QMetaMethod::Method);
|
||||
QVERIFY(m.access() == QMetaMethod::Public);
|
||||
QVERIFY((m.attributes() & QMetaMethod::Scriptable));
|
||||
QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
|
||||
|
||||
m = mobj->method(mobj->indexOfMethod("invoke2()"));
|
||||
QVERIFY(QByteArray(m.signature()) == "invoke2()");
|
||||
QVERIFY(m.methodSignature() == "invoke2()");
|
||||
QVERIFY(m.methodType() == QMetaMethod::Method);
|
||||
QVERIFY(m.access() == QMetaMethod::Protected);
|
||||
QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
|
||||
QVERIFY((m.attributes() & QMetaMethod::Compatibility));
|
||||
|
||||
m = mobj->method(mobj->indexOfMethod("sinvoke2()"));
|
||||
QVERIFY(QByteArray(m.signature()) == "sinvoke2()");
|
||||
QVERIFY(m.methodSignature() == "sinvoke2()");
|
||||
QVERIFY(m.methodType() == QMetaMethod::Method);
|
||||
QVERIFY(m.access() == QMetaMethod::Protected);
|
||||
QVERIFY((m.attributes() & QMetaMethod::Scriptable));
|
||||
QVERIFY((m.attributes() & QMetaMethod::Compatibility));
|
||||
|
||||
m = mobj->method(mobj->indexOfMethod("invoke3()"));
|
||||
QVERIFY(QByteArray(m.signature()) == "invoke3()");
|
||||
QVERIFY(m.methodSignature() == "invoke3()");
|
||||
QVERIFY(m.methodType() == QMetaMethod::Method);
|
||||
QVERIFY(m.access() == QMetaMethod::Private);
|
||||
QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
|
||||
QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
|
||||
|
||||
m = mobj->method(mobj->indexOfMethod("sinvoke3()"));
|
||||
QVERIFY(QByteArray(m.signature()) == "sinvoke3()");
|
||||
QVERIFY(m.methodSignature() == "sinvoke3()");
|
||||
QVERIFY(m.methodType() == QMetaMethod::Method);
|
||||
QVERIFY(m.access() == QMetaMethod::Private);
|
||||
QVERIFY((m.attributes() & QMetaMethod::Scriptable));
|
||||
QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
|
||||
|
||||
m = mobj->method(mobj->indexOfMethod("signal5()"));
|
||||
QVERIFY(QByteArray(m.signature()) == "signal5()");
|
||||
QVERIFY(m.methodSignature() == "signal5()");
|
||||
QVERIFY(m.methodType() == QMetaMethod::Signal);
|
||||
QVERIFY(m.access() == QMetaMethod::Protected);
|
||||
QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
|
||||
QVERIFY((m.attributes() & QMetaMethod::Compatibility));
|
||||
|
||||
m = mobj->method(mobj->indexOfMethod("aPublicSlot()"));
|
||||
QVERIFY(QByteArray(m.signature()) == "aPublicSlot()");
|
||||
QVERIFY(m.methodSignature() == "aPublicSlot()");
|
||||
QVERIFY(m.methodType() == QMetaMethod::Slot);
|
||||
QVERIFY(m.access() == QMetaMethod::Public);
|
||||
QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
|
||||
|
@ -3557,6 +3557,10 @@ void tst_QVariant::loadQVariantFromDataStream(QDataStream::Version version)
|
||||
stream >> typeName >> loadedVariant;
|
||||
|
||||
const int id = QMetaType::type(typeName.toLatin1());
|
||||
if (id == QMetaType::Void) {
|
||||
// Void type is not supported by QVariant
|
||||
return;
|
||||
}
|
||||
|
||||
QVariant constructedVariant(static_cast<QVariant::Type>(id));
|
||||
QCOMPARE(constructedVariant.userType(), id);
|
||||
@ -3576,6 +3580,10 @@ void tst_QVariant::saveQVariantFromDataStream(QDataStream::Version version)
|
||||
dataFileStream >> typeName;
|
||||
QByteArray data = file.readAll();
|
||||
const int id = QMetaType::type(typeName.toLatin1());
|
||||
if (id == QMetaType::Void) {
|
||||
// Void type is not supported by QVariant
|
||||
return;
|
||||
}
|
||||
|
||||
QBuffer buffer;
|
||||
buffer.open(QIODevice::ReadWrite);
|
||||
@ -3636,8 +3644,10 @@ void tst_QVariant::debugStream_data()
|
||||
const char *tagName = QMetaType::typeName(id);
|
||||
if (!tagName)
|
||||
continue;
|
||||
if (id != QMetaType::Void) {
|
||||
QTest::newRow(tagName) << QVariant(static_cast<QVariant::Type>(id)) << id;
|
||||
}
|
||||
}
|
||||
QTest::newRow("QBitArray(111)") << QVariant(QBitArray(3, true)) << qMetaTypeId<QBitArray>();
|
||||
QTest::newRow("CustomStreamableClass") << QVariant(qMetaTypeId<CustomStreamableClass>(), 0) << qMetaTypeId<CustomStreamableClass>();
|
||||
QTest::newRow("MyClass") << QVariant(qMetaTypeId<MyClass>(), 0) << qMetaTypeId<MyClass>();
|
||||
|
5
tests/auto/corelib/tools/qarraydata/qarraydata.pro
Normal file
5
tests/auto/corelib/tools/qarraydata/qarraydata.pro
Normal file
@ -0,0 +1,5 @@
|
||||
TARGET = tst_qarraydata
|
||||
SOURCES += tst_qarraydata.cpp
|
||||
HEADERS += simplevector.h
|
||||
QT = core testlib
|
||||
CONFIG += testcase parallel_test
|
341
tests/auto/corelib/tools/qarraydata/simplevector.h
Normal file
341
tests/auto/corelib/tools/qarraydata/simplevector.h
Normal file
@ -0,0 +1,341 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the test suite of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef QARRAY_TEST_SIMPLE_VECTOR_H
|
||||
#define QARRAY_TEST_SIMPLE_VECTOR_H
|
||||
|
||||
#include <QtCore/qarraydata.h>
|
||||
#include <QtCore/qarraydatapointer.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
template <class T>
|
||||
struct SimpleVector
|
||||
{
|
||||
private:
|
||||
typedef QTypedArrayData<T> Data;
|
||||
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef typename Data::iterator iterator;
|
||||
typedef typename Data::const_iterator const_iterator;
|
||||
|
||||
SimpleVector()
|
||||
{
|
||||
}
|
||||
|
||||
SimpleVector(size_t n, const T &t)
|
||||
: d(Data::allocate(n))
|
||||
{
|
||||
if (n)
|
||||
d->copyAppend(n, t);
|
||||
}
|
||||
|
||||
SimpleVector(const T *begin, const T *end)
|
||||
: d(Data::allocate(end - begin))
|
||||
{
|
||||
if (end - begin)
|
||||
d->copyAppend(begin, end);
|
||||
}
|
||||
|
||||
SimpleVector(QArrayDataPointerRef<T> ptr)
|
||||
: d(ptr)
|
||||
{
|
||||
}
|
||||
|
||||
explicit SimpleVector(Data *ptr)
|
||||
: d(ptr)
|
||||
{
|
||||
}
|
||||
|
||||
bool empty() const { return d->size == 0; }
|
||||
bool isNull() const { return d.isNull(); }
|
||||
bool isEmpty() const { return this->empty(); }
|
||||
|
||||
bool isStatic() const { return d->ref.isStatic(); }
|
||||
bool isShared() const { return d->ref.isShared(); }
|
||||
bool isSharedWith(const SimpleVector &other) const { return d == other.d; }
|
||||
bool isSharable() const { return d->ref.isSharable(); }
|
||||
|
||||
void setSharable(bool sharable) { d.setSharable(sharable); }
|
||||
|
||||
size_t size() const { return d->size; }
|
||||
size_t capacity() const { return d->alloc; }
|
||||
|
||||
iterator begin() { detach(); return d->begin(); }
|
||||
iterator end() { detach(); return d->end(); }
|
||||
|
||||
const_iterator begin() const { return d->begin(); }
|
||||
const_iterator end() const { return d->end(); }
|
||||
|
||||
const_iterator constBegin() const { return begin(); }
|
||||
const_iterator constEnd() const { return end(); }
|
||||
|
||||
T &operator[](size_t i) { Q_ASSERT(i < size_t(d->size)); detach(); return begin()[i]; }
|
||||
T &at(size_t i) { Q_ASSERT(i < size_t(d->size)); detach(); return begin()[i]; }
|
||||
|
||||
const T &operator[](size_t i) const { Q_ASSERT(i < size_t(d->size)); return begin()[i]; }
|
||||
const T &at(size_t i) const { Q_ASSERT(i < size_t(d->size)); return begin()[i]; }
|
||||
|
||||
T &front()
|
||||
{
|
||||
Q_ASSERT(!isEmpty());
|
||||
detach();
|
||||
return *begin();
|
||||
}
|
||||
|
||||
T &back()
|
||||
{
|
||||
Q_ASSERT(!isEmpty());
|
||||
detach();
|
||||
return *(end() - 1);
|
||||
}
|
||||
|
||||
const T &front() const
|
||||
{
|
||||
Q_ASSERT(!isEmpty());
|
||||
return *begin();
|
||||
}
|
||||
|
||||
const T &back() const
|
||||
{
|
||||
Q_ASSERT(!isEmpty());
|
||||
return *(end() - 1);
|
||||
}
|
||||
|
||||
void reserve(size_t n)
|
||||
{
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
if (n <= capacity()) {
|
||||
if (d->capacityReserved)
|
||||
return;
|
||||
if (!d->ref.isShared()) {
|
||||
d->capacityReserved = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SimpleVector detached(Data::allocate(qMax(n, size()),
|
||||
d->detachFlags() | Data::CapacityReserved));
|
||||
if (size())
|
||||
detached.d->copyAppend(constBegin(), constEnd());
|
||||
detached.swap(*this);
|
||||
}
|
||||
|
||||
void prepend(const_iterator first, const_iterator last)
|
||||
{
|
||||
if (!d->size) {
|
||||
append(first, last);
|
||||
return;
|
||||
}
|
||||
|
||||
if (first == last)
|
||||
return;
|
||||
|
||||
T *const begin = d->begin();
|
||||
if (d->ref.isShared()
|
||||
|| capacity() - size() < size_t(last - first)) {
|
||||
SimpleVector detached(Data::allocate(
|
||||
qMax(capacity(), size() + (last - first)),
|
||||
d->detachFlags() | Data::Grow));
|
||||
|
||||
detached.d->copyAppend(first, last);
|
||||
detached.d->copyAppend(begin, begin + d->size);
|
||||
detached.swap(*this);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
d->insert(begin, first, last);
|
||||
}
|
||||
|
||||
void append(const_iterator first, const_iterator last)
|
||||
{
|
||||
if (first == last)
|
||||
return;
|
||||
|
||||
if (d->ref.isShared()
|
||||
|| capacity() - size() < size_t(last - first)) {
|
||||
SimpleVector detached(Data::allocate(
|
||||
qMax(capacity(), size() + (last - first)),
|
||||
d->detachFlags() | Data::Grow));
|
||||
|
||||
if (d->size) {
|
||||
const T *const begin = constBegin();
|
||||
detached.d->copyAppend(begin, begin + d->size);
|
||||
}
|
||||
detached.d->copyAppend(first, last);
|
||||
detached.swap(*this);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
d->copyAppend(first, last);
|
||||
}
|
||||
|
||||
void insert(int position, const_iterator first, const_iterator last)
|
||||
{
|
||||
if (position < 0)
|
||||
position += d->size + 1;
|
||||
|
||||
if (position <= 0) {
|
||||
prepend(first, last);
|
||||
return;
|
||||
}
|
||||
|
||||
if (size_t(position) >= size()) {
|
||||
append(first, last);
|
||||
return;
|
||||
}
|
||||
|
||||
if (first == last)
|
||||
return;
|
||||
|
||||
T *const begin = d->begin();
|
||||
T *const where = begin + position;
|
||||
const T *const end = begin + d->size;
|
||||
if (d->ref.isShared()
|
||||
|| capacity() - size() < size_t(last - first)) {
|
||||
SimpleVector detached(Data::allocate(
|
||||
qMax(capacity(), size() + (last - first)),
|
||||
d->detachFlags() | Data::Grow));
|
||||
|
||||
if (position)
|
||||
detached.d->copyAppend(begin, where);
|
||||
detached.d->copyAppend(first, last);
|
||||
detached.d->copyAppend(where, end);
|
||||
detached.swap(*this);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((first >= where && first < end)
|
||||
|| (last > where && last <= end)) {
|
||||
// Copy overlapping data first and only then shuffle it into place
|
||||
T *start = d->begin() + position;
|
||||
T *middle = d->end();
|
||||
|
||||
d->copyAppend(first, last);
|
||||
std::rotate(start, middle, d->end());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
d->insert(where, first, last);
|
||||
}
|
||||
|
||||
void swap(SimpleVector &other)
|
||||
{
|
||||
qSwap(d, other.d);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
d.clear();
|
||||
}
|
||||
|
||||
void detach()
|
||||
{
|
||||
d.detach();
|
||||
}
|
||||
|
||||
static SimpleVector fromRawData(const T *data, size_t size,
|
||||
QArrayData::AllocationOptions options = Data::Default)
|
||||
{
|
||||
return SimpleVector(Data::fromRawData(data, size, options));
|
||||
}
|
||||
|
||||
private:
|
||||
QArrayDataPointer<T> d;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
bool operator==(const SimpleVector<T> &lhs, const SimpleVector<T> &rhs)
|
||||
{
|
||||
if (lhs.isSharedWith(rhs))
|
||||
return true;
|
||||
if (lhs.size() != rhs.size())
|
||||
return false;
|
||||
return std::equal(lhs.begin(), lhs.end(), rhs.begin());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool operator!=(const SimpleVector<T> &lhs, const SimpleVector<T> &rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool operator<(const SimpleVector<T> &lhs, const SimpleVector<T> &rhs)
|
||||
{
|
||||
return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool operator>(const SimpleVector<T> &lhs, const SimpleVector<T> &rhs)
|
||||
{
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool operator<=(const SimpleVector<T> &lhs, const SimpleVector<T> &rhs)
|
||||
{
|
||||
return !(rhs < lhs);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool operator>=(const SimpleVector<T> &lhs, const SimpleVector<T> &rhs)
|
||||
{
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
namespace std {
|
||||
template <class T>
|
||||
void swap(SimpleVector<T> &v1, SimpleVector<T> &v2)
|
||||
{
|
||||
v1.swap(v2);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // include guard
|
1464
tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
Normal file
1464
tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -1078,18 +1078,25 @@ void tst_QByteArray::toULongLong()
|
||||
// global function defined in qbytearray.cpp
|
||||
void tst_QByteArray::qAllocMore()
|
||||
{
|
||||
static const int t[] = {
|
||||
INT_MIN, INT_MIN + 1, -1234567, -66000, -1025,
|
||||
-3, -1, 0, +1, +3, +1025, +66000, +1234567, INT_MAX - 1, INT_MAX,
|
||||
INT_MAX/3
|
||||
};
|
||||
static const int N = sizeof(t)/sizeof(t[0]);
|
||||
using QT_PREPEND_NAMESPACE(qAllocMore);
|
||||
|
||||
// make sure qAllocMore() doesn't loop infinitely on any input
|
||||
for (int i = 0; i < N; ++i) {
|
||||
for (int j = 0; j < N; ++j) {
|
||||
::qAllocMore(t[i], t[j]);
|
||||
}
|
||||
// Not very important, but please behave :-)
|
||||
QVERIFY(qAllocMore(0, 0) >= 0);
|
||||
|
||||
for (int i = 1; i < 1 << 8; i <<= 1)
|
||||
QVERIFY(qAllocMore(i, 0) >= i);
|
||||
|
||||
for (int i = 1 << 8; i < 1 << 30; i <<= 1) {
|
||||
const int alloc = qAllocMore(i, 0);
|
||||
|
||||
QVERIFY(alloc >= i);
|
||||
QCOMPARE(qAllocMore(i - 8, 8), alloc - 8);
|
||||
QCOMPARE(qAllocMore(i - 16, 16), alloc - 16);
|
||||
QCOMPARE(qAllocMore(i - 24, 24), alloc - 24);
|
||||
QCOMPARE(qAllocMore(i - 32, 32), alloc - 32);
|
||||
|
||||
QVERIFY(qAllocMore(i - 1, 0) >= i - 1);
|
||||
QVERIFY(qAllocMore(i + 1, 0) >= i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1587,8 +1594,8 @@ void tst_QByteArray::literals()
|
||||
|
||||
QVERIFY(str.length() == 4);
|
||||
QVERIFY(str == "abcd");
|
||||
QVERIFY(str.data_ptr()->ref == -1);
|
||||
QVERIFY(str.data_ptr()->offset == 0);
|
||||
QVERIFY(str.data_ptr()->ref.isStatic());
|
||||
QVERIFY(str.data_ptr()->offset == sizeof(QByteArrayData));
|
||||
|
||||
const char *s = str.constData();
|
||||
QByteArray str2 = str;
|
||||
|
@ -54,6 +54,9 @@ class tst_QList : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void init();
|
||||
void cleanup();
|
||||
|
||||
void length() const;
|
||||
void lengthSignature() const;
|
||||
void append() const;
|
||||
@ -90,8 +93,100 @@ private slots:
|
||||
void initializeList() const;
|
||||
|
||||
void const_shared_null() const;
|
||||
void setSharable1_data() const;
|
||||
void setSharable1() const;
|
||||
void setSharable2_data() const;
|
||||
void setSharable2() const;
|
||||
|
||||
private:
|
||||
int dummyForGuard;
|
||||
};
|
||||
|
||||
struct Complex
|
||||
{
|
||||
Complex(int val)
|
||||
: value(val)
|
||||
, checkSum(this)
|
||||
{
|
||||
++liveCount;
|
||||
}
|
||||
|
||||
Complex(Complex const &other)
|
||||
: value(other.value)
|
||||
, checkSum(this)
|
||||
{
|
||||
++liveCount;
|
||||
}
|
||||
|
||||
Complex &operator=(Complex const &other)
|
||||
{
|
||||
check(); other.check();
|
||||
|
||||
value = other.value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~Complex()
|
||||
{
|
||||
--liveCount;
|
||||
check();
|
||||
}
|
||||
|
||||
operator int() const { return value; }
|
||||
|
||||
bool operator==(Complex const &other) const
|
||||
{
|
||||
check(); other.check();
|
||||
return value == other.value;
|
||||
}
|
||||
|
||||
bool check() const
|
||||
{
|
||||
if (this != checkSum) {
|
||||
++errorCount;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
struct Guard
|
||||
{
|
||||
Guard() : initialLiveCount(liveCount) {}
|
||||
~Guard() { if (liveCount != initialLiveCount) ++errorCount; }
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(Guard);
|
||||
int initialLiveCount;
|
||||
};
|
||||
|
||||
static void resetErrors() { errorCount = 0; }
|
||||
static int errors() { return errorCount; }
|
||||
|
||||
private:
|
||||
static int errorCount;
|
||||
static int liveCount;
|
||||
|
||||
int value;
|
||||
void *checkSum;
|
||||
};
|
||||
|
||||
int Complex::errorCount = 0;
|
||||
int Complex::liveCount = 0;
|
||||
|
||||
void tst_QList::init()
|
||||
{
|
||||
Complex::resetErrors();
|
||||
new (&dummyForGuard) Complex::Guard();
|
||||
}
|
||||
|
||||
void tst_QList::cleanup()
|
||||
{
|
||||
QCOMPARE(Complex::errors(), 0);
|
||||
|
||||
reinterpret_cast<Complex::Guard *>(&dummyForGuard)->~Guard();
|
||||
QCOMPARE(Complex::errors(), 0);
|
||||
}
|
||||
|
||||
void tst_QList::length() const
|
||||
{
|
||||
/* Empty list. */
|
||||
@ -696,5 +791,82 @@ void tst_QList::const_shared_null() const
|
||||
QVERIFY(!list2.isDetached());
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(QList<int>);
|
||||
Q_DECLARE_METATYPE(QList<Complex>);
|
||||
|
||||
template <class T>
|
||||
void generateSetSharableData()
|
||||
{
|
||||
QTest::addColumn<QList<T> >("list");
|
||||
QTest::addColumn<int>("size");
|
||||
|
||||
QTest::newRow("null") << QList<T>() << 0;
|
||||
QTest::newRow("non-empty") << (QList<T>() << T(0) << T(1) << T(2) << T(3) << T(4)) << 5;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void runSetSharableTest()
|
||||
{
|
||||
QFETCH(QList<T>, list);
|
||||
QFETCH(int, size);
|
||||
|
||||
QVERIFY(!list.isDetached()); // Shared with QTest
|
||||
|
||||
list.setSharable(true);
|
||||
|
||||
QCOMPARE(list.size(), size);
|
||||
|
||||
{
|
||||
QList<T> copy(list);
|
||||
QVERIFY(!copy.isDetached());
|
||||
QVERIFY(copy.isSharedWith(list));
|
||||
}
|
||||
|
||||
list.setSharable(false);
|
||||
QVERIFY(list.isDetached() || list.isSharedWith(QList<T>()));
|
||||
|
||||
{
|
||||
QList<T> copy(list);
|
||||
|
||||
QVERIFY(copy.isDetached() || copy.isSharedWith(QList<T>()));
|
||||
QCOMPARE(copy.size(), size);
|
||||
QCOMPARE(copy, list);
|
||||
}
|
||||
|
||||
list.setSharable(true);
|
||||
|
||||
{
|
||||
QList<T> copy(list);
|
||||
|
||||
QVERIFY(!copy.isDetached());
|
||||
QVERIFY(copy.isSharedWith(list));
|
||||
}
|
||||
|
||||
for (int i = 0; i < list.size(); ++i)
|
||||
QCOMPARE(int(list[i]), i);
|
||||
|
||||
QCOMPARE(list.size(), size);
|
||||
}
|
||||
|
||||
void tst_QList::setSharable1_data() const
|
||||
{
|
||||
generateSetSharableData<int>();
|
||||
}
|
||||
|
||||
void tst_QList::setSharable2_data() const
|
||||
{
|
||||
generateSetSharableData<Complex>();
|
||||
}
|
||||
|
||||
void tst_QList::setSharable1() const
|
||||
{
|
||||
runSetSharableTest<int>();
|
||||
}
|
||||
|
||||
void tst_QList::setSharable2() const
|
||||
{
|
||||
runSetSharableTest<Complex>();
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_QList)
|
||||
#include "tst_qlist.moc"
|
||||
|
@ -1421,16 +1421,51 @@ void tst_QString::mid()
|
||||
QVERIFY(a.mid(9999).isNull());
|
||||
QVERIFY(a.mid(9999,1).isNull());
|
||||
|
||||
QCOMPARE(a.mid(-1, 6), QString("ABCDEF"));
|
||||
QCOMPARE(a.mid(-100, 6), QString("ABCDEF"));
|
||||
QVERIFY(a.mid(INT_MAX).isNull());
|
||||
QVERIFY(a.mid(INT_MAX, INT_MAX).isNull());
|
||||
QCOMPARE(a.mid(-5, INT_MAX), a);
|
||||
QCOMPARE(a.mid(-1, INT_MAX), a);
|
||||
QCOMPARE(a.mid(0, INT_MAX), a);
|
||||
QCOMPARE(a.mid(1, INT_MAX), QString("BCDEFGHIEfGEFG"));
|
||||
QCOMPARE(a.mid(5, INT_MAX), QString("FGHIEfGEFG"));
|
||||
QVERIFY(a.mid(20, INT_MAX).isNull());
|
||||
QCOMPARE(a.mid(-1, -1), a);
|
||||
|
||||
QString n;
|
||||
QVERIFY(n.mid(3,3).isNull());
|
||||
QVERIFY(n.mid(0,0).isNull());
|
||||
QVERIFY(n.mid(9999,0).isNull());
|
||||
QVERIFY(n.mid(9999,1).isNull());
|
||||
|
||||
QVERIFY(n.mid(-1, 6).isNull());
|
||||
QVERIFY(n.mid(-100, 6).isNull());
|
||||
QVERIFY(n.mid(INT_MAX).isNull());
|
||||
QVERIFY(n.mid(INT_MAX, INT_MAX).isNull());
|
||||
QVERIFY(n.mid(-5, INT_MAX).isNull());
|
||||
QVERIFY(n.mid(-1, INT_MAX).isNull());
|
||||
QVERIFY(n.mid(0, INT_MAX).isNull());
|
||||
QVERIFY(n.mid(1, INT_MAX).isNull());
|
||||
QVERIFY(n.mid(5, INT_MAX).isNull());
|
||||
QVERIFY(n.mid(20, INT_MAX).isNull());
|
||||
QVERIFY(n.mid(-1, -1).isNull());
|
||||
|
||||
QString x = "Nine pineapples";
|
||||
QCOMPARE(x.mid(5, 4), QString("pine"));
|
||||
QCOMPARE(x.mid(5), QString("pineapples"));
|
||||
|
||||
QCOMPARE(x.mid(-1, 6), QString("Nine p"));
|
||||
QCOMPARE(x.mid(-100, 6), QString("Nine p"));
|
||||
QVERIFY(x.mid(INT_MAX).isNull());
|
||||
QVERIFY(x.mid(INT_MAX, INT_MAX).isNull());
|
||||
QCOMPARE(x.mid(-5, INT_MAX), x);
|
||||
QCOMPARE(x.mid(-1, INT_MAX), x);
|
||||
QCOMPARE(x.mid(0, INT_MAX), x);
|
||||
QCOMPARE(x.mid(1, INT_MAX), QString("ine pineapples"));
|
||||
QCOMPARE(x.mid(5, INT_MAX), QString("pineapples"));
|
||||
QVERIFY(x.mid(20, INT_MAX).isNull());
|
||||
QCOMPARE(x.mid(-1, -1), x);
|
||||
}
|
||||
|
||||
void tst_QString::midRef()
|
||||
@ -1447,16 +1482,51 @@ void tst_QString::midRef()
|
||||
QVERIFY(a.midRef(9999).toString().isEmpty());
|
||||
QVERIFY(a.midRef(9999,1).toString().isEmpty());
|
||||
|
||||
QCOMPARE(a.midRef(-1, 6).toString(), QString("ABCDEF"));
|
||||
QCOMPARE(a.midRef(-100, 6).toString(), QString("ABCDEF"));
|
||||
QVERIFY(a.midRef(INT_MAX).isNull());
|
||||
QVERIFY(a.midRef(INT_MAX, INT_MAX).isNull());
|
||||
QCOMPARE(a.midRef(-5, INT_MAX).toString(), a);
|
||||
QCOMPARE(a.midRef(-1, INT_MAX).toString(), a);
|
||||
QCOMPARE(a.midRef(0, INT_MAX).toString(), a);
|
||||
QCOMPARE(a.midRef(1, INT_MAX).toString(), QString("BCDEFGHIEfGEFG"));
|
||||
QCOMPARE(a.midRef(5, INT_MAX).toString(), QString("FGHIEfGEFG"));
|
||||
QVERIFY(a.midRef(20, INT_MAX).isNull());
|
||||
QCOMPARE(a.midRef(-1, -1).toString(), a);
|
||||
|
||||
QString n;
|
||||
QVERIFY(n.midRef(3,3).toString().isEmpty());
|
||||
QVERIFY(n.midRef(0,0).toString().isEmpty());
|
||||
QVERIFY(n.midRef(9999,0).toString().isEmpty());
|
||||
QVERIFY(n.midRef(9999,1).toString().isEmpty());
|
||||
|
||||
QVERIFY(n.midRef(-1, 6).isNull());
|
||||
QVERIFY(n.midRef(-100, 6).isNull());
|
||||
QVERIFY(n.midRef(INT_MAX).isNull());
|
||||
QVERIFY(n.midRef(INT_MAX, INT_MAX).isNull());
|
||||
QVERIFY(n.midRef(-5, INT_MAX).isNull());
|
||||
QVERIFY(n.midRef(-1, INT_MAX).isNull());
|
||||
QVERIFY(n.midRef(0, INT_MAX).isNull());
|
||||
QVERIFY(n.midRef(1, INT_MAX).isNull());
|
||||
QVERIFY(n.midRef(5, INT_MAX).isNull());
|
||||
QVERIFY(n.midRef(20, INT_MAX).isNull());
|
||||
QVERIFY(n.midRef(-1, -1).isNull());
|
||||
|
||||
QString x = "Nine pineapples";
|
||||
QCOMPARE(x.midRef(5, 4).toString(), QString("pine"));
|
||||
QCOMPARE(x.midRef(5).toString(), QString("pineapples"));
|
||||
|
||||
QCOMPARE(x.midRef(-1, 6).toString(), QString("Nine p"));
|
||||
QCOMPARE(x.midRef(-100, 6).toString(), QString("Nine p"));
|
||||
QVERIFY(x.midRef(INT_MAX).isNull());
|
||||
QVERIFY(x.midRef(INT_MAX, INT_MAX).isNull());
|
||||
QCOMPARE(x.midRef(-5, INT_MAX).toString(), x);
|
||||
QCOMPARE(x.midRef(-1, INT_MAX).toString(), x);
|
||||
QCOMPARE(x.midRef(0, INT_MAX).toString(), x);
|
||||
QCOMPARE(x.midRef(1, INT_MAX).toString(), QString("ine pineapples"));
|
||||
QCOMPARE(x.midRef(5, INT_MAX).toString(), QString("pineapples"));
|
||||
QVERIFY(x.midRef(20, INT_MAX).isNull());
|
||||
QCOMPARE(x.midRef(-1, -1).toString(), x);
|
||||
}
|
||||
|
||||
void tst_QString::stringRef()
|
||||
@ -5056,8 +5126,8 @@ void tst_QString::literals()
|
||||
|
||||
QVERIFY(str.length() == 4);
|
||||
QVERIFY(str == QLatin1String("abcd"));
|
||||
QVERIFY(str.data_ptr()->ref == -1);
|
||||
QVERIFY(str.data_ptr()->offset == 0);
|
||||
QVERIFY(str.data_ptr()->ref.isStatic());
|
||||
QVERIFY(str.data_ptr()->offset == sizeof(QStringData));
|
||||
|
||||
const QChar *s = str.constData();
|
||||
QString str2 = str;
|
||||
|
@ -85,6 +85,8 @@ private slots:
|
||||
void initializeList();
|
||||
|
||||
void const_shared_null();
|
||||
void setSharable_data();
|
||||
void setSharable();
|
||||
};
|
||||
|
||||
void tst_QVector::constructors() const
|
||||
@ -946,5 +948,97 @@ void tst_QVector::const_shared_null()
|
||||
QVERIFY(!v2.isDetached());
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(QVector<int>);
|
||||
|
||||
void tst_QVector::setSharable_data()
|
||||
{
|
||||
QTest::addColumn<QVector<int> >("vector");
|
||||
QTest::addColumn<int>("size");
|
||||
QTest::addColumn<int>("capacity");
|
||||
QTest::addColumn<bool>("isCapacityReserved");
|
||||
|
||||
QVector<int> null;
|
||||
QVector<int> empty(0, 5);
|
||||
QVector<int> emptyReserved;
|
||||
QVector<int> nonEmpty;
|
||||
QVector<int> nonEmptyReserved;
|
||||
|
||||
emptyReserved.reserve(10);
|
||||
nonEmptyReserved.reserve(15);
|
||||
|
||||
nonEmpty << 0 << 1 << 2 << 3 << 4;
|
||||
nonEmptyReserved << 0 << 1 << 2 << 3 << 4 << 5 << 6;
|
||||
|
||||
QVERIFY(emptyReserved.capacity() >= 10);
|
||||
QVERIFY(nonEmptyReserved.capacity() >= 15);
|
||||
|
||||
QTest::newRow("null") << null << 0 << 0 << false;
|
||||
QTest::newRow("empty") << empty << 0 << 0 << false;
|
||||
QTest::newRow("empty, Reserved") << emptyReserved << 0 << 10 << true;
|
||||
QTest::newRow("non-empty") << nonEmpty << 5 << 0 << false;
|
||||
QTest::newRow("non-empty, Reserved") << nonEmptyReserved << 7 << 15 << true;
|
||||
}
|
||||
|
||||
void tst_QVector::setSharable()
|
||||
{
|
||||
QFETCH(QVector<int>, vector);
|
||||
QFETCH(int, size);
|
||||
QFETCH(int, capacity);
|
||||
QFETCH(bool, isCapacityReserved);
|
||||
|
||||
QVERIFY(!vector.isDetached()); // Shared with QTest
|
||||
|
||||
vector.setSharable(true);
|
||||
|
||||
QCOMPARE(vector.size(), size);
|
||||
if (isCapacityReserved)
|
||||
QVERIFY2(vector.capacity() >= capacity,
|
||||
qPrintable(QString("Capacity is %1, expected at least %2.")
|
||||
.arg(vector.capacity())
|
||||
.arg(capacity)));
|
||||
|
||||
{
|
||||
QVector<int> copy(vector);
|
||||
|
||||
QVERIFY(!copy.isDetached());
|
||||
QVERIFY(copy.isSharedWith(vector));
|
||||
}
|
||||
|
||||
vector.setSharable(false);
|
||||
QVERIFY(vector.isDetached() || vector.isSharedWith(QVector<int>()));
|
||||
|
||||
{
|
||||
QVector<int> copy(vector);
|
||||
|
||||
QVERIFY(copy.isDetached() || copy.isSharedWith(QVector<int>()));
|
||||
QCOMPARE(copy.size(), size);
|
||||
if (isCapacityReserved)
|
||||
QVERIFY2(copy.capacity() >= capacity,
|
||||
qPrintable(QString("Capacity is %1, expected at least %2.")
|
||||
.arg(vector.capacity())
|
||||
.arg(capacity)));
|
||||
QCOMPARE(copy, vector);
|
||||
}
|
||||
|
||||
vector.setSharable(true);
|
||||
|
||||
{
|
||||
QVector<int> copy(vector);
|
||||
|
||||
QVERIFY(!copy.isDetached());
|
||||
QVERIFY(copy.isSharedWith(vector));
|
||||
}
|
||||
|
||||
for (int i = 0; i < vector.size(); ++i)
|
||||
QCOMPARE(vector[i], i);
|
||||
|
||||
QCOMPARE(vector.size(), size);
|
||||
if (isCapacityReserved)
|
||||
QVERIFY2(vector.capacity() >= capacity,
|
||||
qPrintable(QString("Capacity is %1, expected at least %2.")
|
||||
.arg(vector.capacity())
|
||||
.arg(capacity)));
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_QVector)
|
||||
#include "tst_qvector.moc"
|
||||
|
@ -1,6 +1,7 @@
|
||||
TEMPLATE=subdirs
|
||||
SUBDIRS=\
|
||||
qalgorithms \
|
||||
qarraydata \
|
||||
qbitarray \
|
||||
qbytearray \
|
||||
qbytearraymatcher \
|
||||
|
@ -397,16 +397,21 @@ void tst_QDBusMetaObject::types()
|
||||
for (int i = metaobject->methodOffset(); i < metaobject->methodCount(); ++i) {
|
||||
QMetaMethod expected = metaobject->method(i);
|
||||
|
||||
int methodIdx = result->indexOfMethod(expected.signature());
|
||||
int methodIdx = result->indexOfMethod(expected.methodSignature().constData());
|
||||
QVERIFY(methodIdx != -1);
|
||||
QMetaMethod constructed = result->method(methodIdx);
|
||||
|
||||
QCOMPARE(int(constructed.access()), int(expected.access()));
|
||||
QCOMPARE(int(constructed.methodType()), int(expected.methodType()));
|
||||
QCOMPARE(constructed.name(), expected.name());
|
||||
QCOMPARE(constructed.parameterCount(), expected.parameterCount());
|
||||
QCOMPARE(constructed.parameterNames(), expected.parameterNames());
|
||||
QCOMPARE(constructed.parameterTypes(), expected.parameterTypes());
|
||||
for (int j = 0; j < constructed.parameterCount(); ++j)
|
||||
QCOMPARE(constructed.parameterType(j), expected.parameterType(j));
|
||||
QCOMPARE(constructed.tag(), expected.tag());
|
||||
QCOMPARE(constructed.typeName(), expected.typeName());
|
||||
QCOMPARE(constructed.returnType(), expected.returnType());
|
||||
}
|
||||
|
||||
for (int i = metaobject->propertyOffset(); i < metaobject->propertyCount(); ++i) {
|
||||
@ -427,6 +432,8 @@ void tst_QDBusMetaObject::types()
|
||||
QCOMPARE(constructed.isUser(), expected.isUser());
|
||||
QCOMPARE(constructed.isWritable(), expected.isWritable());
|
||||
QCOMPARE(constructed.typeName(), expected.typeName());
|
||||
QCOMPARE(constructed.type(), expected.type());
|
||||
QCOMPARE(constructed.userType(), expected.userType());
|
||||
}
|
||||
}
|
||||
|
||||
@ -667,6 +674,204 @@ const char PropertyTest4_xml[] =
|
||||
"<annotation name=\"com.trolltech.QtDBus.QtTypeName\" value=\"Struct1\"/>"
|
||||
"</property>";
|
||||
|
||||
class PropertyTest_b: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool property READ property WRITE setProperty)
|
||||
public:
|
||||
bool property() { return false; }
|
||||
void setProperty(bool) { }
|
||||
};
|
||||
const char PropertyTest_b_xml[] =
|
||||
"<property name=\"property\" type=\"b\" access=\"readwrite\"/>";
|
||||
|
||||
class PropertyTest_y: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(uchar property READ property WRITE setProperty)
|
||||
public:
|
||||
uchar property() { return 0; }
|
||||
void setProperty(uchar) { }
|
||||
};
|
||||
const char PropertyTest_y_xml[] =
|
||||
"<property name=\"property\" type=\"y\" access=\"readwrite\"/>";
|
||||
|
||||
class PropertyTest_n: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(short property READ property WRITE setProperty)
|
||||
public:
|
||||
short property() { return 0; }
|
||||
void setProperty(short) { }
|
||||
};
|
||||
const char PropertyTest_n_xml[] =
|
||||
"<property name=\"property\" type=\"n\" access=\"readwrite\"/>";
|
||||
|
||||
class PropertyTest_q: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(ushort property READ property WRITE setProperty)
|
||||
public:
|
||||
ushort property() { return 0; }
|
||||
void setProperty(ushort) { }
|
||||
};
|
||||
const char PropertyTest_q_xml[] =
|
||||
"<property name=\"property\" type=\"q\" access=\"readwrite\"/>";
|
||||
|
||||
class PropertyTest_u: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(uint property READ property WRITE setProperty)
|
||||
public:
|
||||
uint property() { return 0; }
|
||||
void setProperty(uint) { }
|
||||
};
|
||||
const char PropertyTest_u_xml[] =
|
||||
"<property name=\"property\" type=\"u\" access=\"readwrite\"/>";
|
||||
|
||||
class PropertyTest_x: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(qlonglong property READ property WRITE setProperty)
|
||||
public:
|
||||
qlonglong property() { return 0; }
|
||||
void setProperty(qlonglong) { }
|
||||
};
|
||||
const char PropertyTest_x_xml[] =
|
||||
"<property name=\"property\" type=\"x\" access=\"readwrite\"/>";
|
||||
|
||||
class PropertyTest_t: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(qulonglong property READ property WRITE setProperty)
|
||||
public:
|
||||
qulonglong property() { return 0; }
|
||||
void setProperty(qulonglong) { }
|
||||
};
|
||||
const char PropertyTest_t_xml[] =
|
||||
"<property name=\"property\" type=\"t\" access=\"readwrite\"/>";
|
||||
|
||||
class PropertyTest_d: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(double property READ property WRITE setProperty)
|
||||
public:
|
||||
double property() { return 0; }
|
||||
void setProperty(double) { }
|
||||
};
|
||||
const char PropertyTest_d_xml[] =
|
||||
"<property name=\"property\" type=\"d\" access=\"readwrite\"/>";
|
||||
|
||||
class PropertyTest_s: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString property READ property WRITE setProperty)
|
||||
public:
|
||||
QString property() { return QString(); }
|
||||
void setProperty(QString) { }
|
||||
};
|
||||
const char PropertyTest_s_xml[] =
|
||||
"<property name=\"property\" type=\"s\" access=\"readwrite\"/>";
|
||||
|
||||
class PropertyTest_v: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QDBusVariant property READ property WRITE setProperty)
|
||||
public:
|
||||
QDBusVariant property() { return QDBusVariant(); }
|
||||
void setProperty(QDBusVariant) { }
|
||||
};
|
||||
const char PropertyTest_v_xml[] =
|
||||
"<property name=\"property\" type=\"v\" access=\"readwrite\"/>";
|
||||
|
||||
class PropertyTest_o: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QDBusObjectPath property READ property WRITE setProperty)
|
||||
public:
|
||||
QDBusObjectPath property() { return QDBusObjectPath(); }
|
||||
void setProperty(QDBusObjectPath) { }
|
||||
};
|
||||
const char PropertyTest_o_xml[] =
|
||||
"<property name=\"property\" type=\"o\" access=\"readwrite\"/>";
|
||||
|
||||
class PropertyTest_g: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QDBusSignature property READ property WRITE setProperty)
|
||||
public:
|
||||
QDBusSignature property() { return QDBusSignature(); }
|
||||
void setProperty(QDBusSignature) { }
|
||||
};
|
||||
const char PropertyTest_g_xml[] =
|
||||
"<property name=\"property\" type=\"g\" access=\"readwrite\"/>";
|
||||
|
||||
class PropertyTest_h: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QDBusUnixFileDescriptor property READ property WRITE setProperty)
|
||||
public:
|
||||
QDBusUnixFileDescriptor property() { return QDBusUnixFileDescriptor(); }
|
||||
void setProperty(QDBusUnixFileDescriptor) { }
|
||||
};
|
||||
const char PropertyTest_h_xml[] =
|
||||
"<property name=\"property\" type=\"h\" access=\"readwrite\"/>";
|
||||
|
||||
class PropertyTest_ay: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QByteArray property READ property WRITE setProperty)
|
||||
public:
|
||||
QByteArray property() { return QByteArray(); }
|
||||
void setProperty(QByteArray) { }
|
||||
};
|
||||
const char PropertyTest_ay_xml[] =
|
||||
"<property name=\"property\" type=\"ay\" access=\"readwrite\"/>";
|
||||
|
||||
class PropertyTest_as: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QStringList property READ property WRITE setProperty)
|
||||
public:
|
||||
QStringList property() { return QStringList(); }
|
||||
void setProperty(QStringList) { }
|
||||
};
|
||||
const char PropertyTest_as_xml[] =
|
||||
"<property name=\"property\" type=\"as\" access=\"readwrite\"/>";
|
||||
|
||||
class PropertyTest_av: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QVariantList property READ property WRITE setProperty)
|
||||
public:
|
||||
QVariantList property() { return QVariantList(); }
|
||||
void setProperty(QVariantList) { }
|
||||
};
|
||||
const char PropertyTest_av_xml[] =
|
||||
"<property name=\"property\" type=\"av\" access=\"readwrite\"/>";
|
||||
|
||||
class PropertyTest_ao: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QList<QDBusObjectPath> property READ property WRITE setProperty)
|
||||
public:
|
||||
QList<QDBusObjectPath> property() { return QList<QDBusObjectPath>(); }
|
||||
void setProperty(QList<QDBusObjectPath>) { }
|
||||
};
|
||||
const char PropertyTest_ao_xml[] =
|
||||
"<property name=\"property\" type=\"ao\" access=\"readwrite\"/>";
|
||||
|
||||
class PropertyTest_ag: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QList<QDBusSignature> property READ property WRITE setProperty)
|
||||
public:
|
||||
QList<QDBusSignature> property() { return QList<QDBusSignature>(); }
|
||||
void setProperty(QList<QDBusSignature>) { }
|
||||
};
|
||||
const char PropertyTest_ag_xml[] =
|
||||
"<property name=\"property\" type=\"ag\" access=\"readwrite\"/>";
|
||||
|
||||
void tst_QDBusMetaObject::properties_data()
|
||||
{
|
||||
QTest::addColumn<const QMetaObject *>("metaobject");
|
||||
@ -676,6 +881,25 @@ void tst_QDBusMetaObject::properties_data()
|
||||
QTest::newRow("readwrite") << &PropertyTest2::staticMetaObject << QString(PropertyTest2_xml);
|
||||
QTest::newRow("write") << &PropertyTest3::staticMetaObject << QString(PropertyTest3_xml);
|
||||
QTest::newRow("customtype") << &PropertyTest4::staticMetaObject << QString(PropertyTest4_xml);
|
||||
|
||||
QTest::newRow("bool") << &PropertyTest_b::staticMetaObject << QString(PropertyTest_b_xml);
|
||||
QTest::newRow("byte") << &PropertyTest_y::staticMetaObject << QString(PropertyTest_y_xml);
|
||||
QTest::newRow("short") << &PropertyTest_n::staticMetaObject << QString(PropertyTest_n_xml);
|
||||
QTest::newRow("ushort") << &PropertyTest_q::staticMetaObject << QString(PropertyTest_q_xml);
|
||||
QTest::newRow("uint") << &PropertyTest_u::staticMetaObject << QString(PropertyTest_u_xml);
|
||||
QTest::newRow("qlonglong") << &PropertyTest_x::staticMetaObject << QString(PropertyTest_x_xml);
|
||||
QTest::newRow("qulonglong") << &PropertyTest_t::staticMetaObject << QString(PropertyTest_t_xml);
|
||||
QTest::newRow("double") << &PropertyTest_d::staticMetaObject << QString(PropertyTest_d_xml);
|
||||
QTest::newRow("QString") << &PropertyTest_s::staticMetaObject << QString(PropertyTest_s_xml);
|
||||
QTest::newRow("QDBusVariant") << &PropertyTest_v::staticMetaObject << QString(PropertyTest_v_xml);
|
||||
QTest::newRow("QDBusObjectPath") << &PropertyTest_o::staticMetaObject << QString(PropertyTest_o_xml);
|
||||
QTest::newRow("QDBusSignature") << &PropertyTest_g::staticMetaObject << QString(PropertyTest_g_xml);
|
||||
QTest::newRow("QDBusUnixFileDescriptor") << &PropertyTest_h::staticMetaObject << QString(PropertyTest_h_xml);
|
||||
QTest::newRow("QByteArray") << &PropertyTest_ay::staticMetaObject << QString(PropertyTest_ay_xml);
|
||||
QTest::newRow("QStringList") << &PropertyTest_as::staticMetaObject << QString(PropertyTest_as_xml);
|
||||
QTest::newRow("QVariantList") << &PropertyTest_av::staticMetaObject << QString(PropertyTest_av_xml);
|
||||
QTest::newRow("QList<QDBusObjectPath>") << &PropertyTest_ao::staticMetaObject << QString(PropertyTest_ao_xml);
|
||||
QTest::newRow("QList<QDBusSignature>") << &PropertyTest_ag::staticMetaObject << QString(PropertyTest_ag_xml);
|
||||
}
|
||||
|
||||
void tst_QDBusMetaObject::properties()
|
||||
|
@ -748,7 +748,7 @@ void tst_Moc::classinfoWithEscapes()
|
||||
QCOMPARE(mobj->methodCount() - mobj->methodOffset(), 1);
|
||||
|
||||
QMetaMethod mm = mobj->method(mobj->methodOffset());
|
||||
QCOMPARE(mm.signature(), "slotWithAReallyLongName(int)");
|
||||
QCOMPARE(mm.methodSignature(), QByteArray("slotWithAReallyLongName(int)"));
|
||||
}
|
||||
|
||||
void tst_Moc::trNoopInClassInfo()
|
||||
@ -1093,14 +1093,14 @@ void tst_Moc::invokable()
|
||||
{
|
||||
const QMetaObject &mobj = InvokableBeforeReturnType::staticMetaObject;
|
||||
QCOMPARE(mobj.methodCount(), 6);
|
||||
QVERIFY(mobj.method(5).signature() == QByteArray("foo()"));
|
||||
QVERIFY(mobj.method(5).methodSignature() == QByteArray("foo()"));
|
||||
}
|
||||
|
||||
{
|
||||
const QMetaObject &mobj = InvokableBeforeInline::staticMetaObject;
|
||||
QCOMPARE(mobj.methodCount(), 7);
|
||||
QVERIFY(mobj.method(5).signature() == QByteArray("foo()"));
|
||||
QVERIFY(mobj.method(6).signature() == QByteArray("bar()"));
|
||||
QVERIFY(mobj.method(5).methodSignature() == QByteArray("foo()"));
|
||||
QVERIFY(mobj.method(6).methodSignature() == QByteArray("bar()"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1109,22 +1109,22 @@ void tst_Moc::singleFunctionKeywordSignalAndSlot()
|
||||
{
|
||||
const QMetaObject &mobj = SingleFunctionKeywordBeforeReturnType::staticMetaObject;
|
||||
QCOMPARE(mobj.methodCount(), 7);
|
||||
QVERIFY(mobj.method(5).signature() == QByteArray("mySignal()"));
|
||||
QVERIFY(mobj.method(6).signature() == QByteArray("mySlot()"));
|
||||
QVERIFY(mobj.method(5).methodSignature() == QByteArray("mySignal()"));
|
||||
QVERIFY(mobj.method(6).methodSignature() == QByteArray("mySlot()"));
|
||||
}
|
||||
|
||||
{
|
||||
const QMetaObject &mobj = SingleFunctionKeywordBeforeInline::staticMetaObject;
|
||||
QCOMPARE(mobj.methodCount(), 7);
|
||||
QVERIFY(mobj.method(5).signature() == QByteArray("mySignal()"));
|
||||
QVERIFY(mobj.method(6).signature() == QByteArray("mySlot()"));
|
||||
QVERIFY(mobj.method(5).methodSignature() == QByteArray("mySignal()"));
|
||||
QVERIFY(mobj.method(6).methodSignature() == QByteArray("mySlot()"));
|
||||
}
|
||||
|
||||
{
|
||||
const QMetaObject &mobj = SingleFunctionKeywordAfterInline::staticMetaObject;
|
||||
QCOMPARE(mobj.methodCount(), 7);
|
||||
QVERIFY(mobj.method(5).signature() == QByteArray("mySignal()"));
|
||||
QVERIFY(mobj.method(6).signature() == QByteArray("mySlot()"));
|
||||
QVERIFY(mobj.method(5).methodSignature() == QByteArray("mySignal()"));
|
||||
QVERIFY(mobj.method(6).methodSignature() == QByteArray("mySlot()"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1231,7 +1231,7 @@ void tst_Moc::constructors()
|
||||
QMetaMethod mm = mo->constructor(0);
|
||||
QCOMPARE(mm.access(), QMetaMethod::Public);
|
||||
QCOMPARE(mm.methodType(), QMetaMethod::Constructor);
|
||||
QCOMPARE(mm.signature(), "CtorTestClass(QObject*)");
|
||||
QCOMPARE(mm.methodSignature(), QByteArray("CtorTestClass(QObject*)"));
|
||||
QCOMPARE(mm.typeName(), "");
|
||||
QList<QByteArray> paramNames = mm.parameterNames();
|
||||
QCOMPARE(paramNames.size(), 1);
|
||||
@ -1244,7 +1244,7 @@ void tst_Moc::constructors()
|
||||
QMetaMethod mm = mo->constructor(1);
|
||||
QCOMPARE(mm.access(), QMetaMethod::Public);
|
||||
QCOMPARE(mm.methodType(), QMetaMethod::Constructor);
|
||||
QCOMPARE(mm.signature(), "CtorTestClass()");
|
||||
QCOMPARE(mm.methodSignature(), QByteArray("CtorTestClass()"));
|
||||
QCOMPARE(mm.typeName(), "");
|
||||
QCOMPARE(mm.parameterNames().size(), 0);
|
||||
QCOMPARE(mm.parameterTypes().size(), 0);
|
||||
@ -1253,7 +1253,7 @@ void tst_Moc::constructors()
|
||||
QMetaMethod mm = mo->constructor(2);
|
||||
QCOMPARE(mm.access(), QMetaMethod::Public);
|
||||
QCOMPARE(mm.methodType(), QMetaMethod::Constructor);
|
||||
QCOMPARE(mm.signature(), "CtorTestClass(QString)");
|
||||
QCOMPARE(mm.methodSignature(), QByteArray("CtorTestClass(QString)"));
|
||||
QCOMPARE(mm.typeName(), "");
|
||||
QList<QByteArray> paramNames = mm.parameterNames();
|
||||
QCOMPARE(paramNames.size(), 1);
|
||||
|
@ -1275,7 +1275,7 @@ static int numberOfConnectedSignals(MySubWindow *subWindow)
|
||||
QMetaMethod method = subWindow->metaObject()->method(i);
|
||||
if (method.methodType() == QMetaMethod::Signal) {
|
||||
QString signature(QLatin1String("2"));
|
||||
signature += QLatin1String(method.signature());
|
||||
signature += QLatin1String(method.methodSignature().constData());
|
||||
numConnectedSignals += subWindow->receivers(signature.toLatin1());
|
||||
}
|
||||
}
|
||||
|
@ -174,7 +174,7 @@ void tst_qmetaobject::indexOfMethod_data()
|
||||
const QMetaObject *mo = &QTreeView::staticMetaObject;
|
||||
for (int i = 0; i < mo->methodCount(); ++i) {
|
||||
QMetaMethod method = mo->method(i);
|
||||
QByteArray sig = method.signature();
|
||||
QByteArray sig = method.methodSignature();
|
||||
QTest::newRow(sig) << sig;
|
||||
}
|
||||
}
|
||||
@ -197,7 +197,7 @@ void tst_qmetaobject::indexOfSignal_data()
|
||||
QMetaMethod method = mo->method(i);
|
||||
if (method.methodType() != QMetaMethod::Signal)
|
||||
continue;
|
||||
QByteArray sig = method.signature();
|
||||
QByteArray sig = method.methodSignature();
|
||||
QTest::newRow(sig) << sig;
|
||||
}
|
||||
}
|
||||
@ -220,7 +220,7 @@ void tst_qmetaobject::indexOfSlot_data()
|
||||
QMetaMethod method = mo->method(i);
|
||||
if (method.methodType() != QMetaMethod::Slot)
|
||||
continue;
|
||||
QByteArray sig = method.signature();
|
||||
QByteArray sig = method.methodSignature();
|
||||
QTest::newRow(sig) << sig;
|
||||
}
|
||||
}
|
||||
|
@ -66,24 +66,18 @@ QT_BEGIN_NAMESPACE
|
||||
template <typename T>
|
||||
class QRawVector
|
||||
{
|
||||
struct Data : QVectorData { T array[1]; };
|
||||
typedef QVectorTypedData<T> Data;
|
||||
|
||||
T *m_begin;
|
||||
int m_size;
|
||||
int m_alloc;
|
||||
|
||||
public:
|
||||
//static Data dummy;
|
||||
//int headerOffset() { return (char*)&dummy.array - (char*)&dummy; }
|
||||
inline int headerOffset() const {
|
||||
// gcc complains about: return offsetof(Data, array); and also
|
||||
// does not like '0' in the expression below.
|
||||
return (char *)&(((Data *)(1))->array) - (char *)1;
|
||||
}
|
||||
inline Data *toBase(T *begin) const
|
||||
{ return (Data*)((char*)begin - headerOffset()); }
|
||||
inline T *fromBase(void *d) const
|
||||
{ return (T*)((char*)d + headerOffset()); }
|
||||
static Data *toBase(T *begin)
|
||||
{ return (Data*)((char*)begin - offsetOfTypedData()); }
|
||||
static T *fromBase(void *d)
|
||||
{ return (T*)((char*)d + offsetOfTypedData()); }
|
||||
|
||||
inline QRawVector()
|
||||
{ m_begin = fromBase(0); m_alloc = m_size = 0; realloc(m_size, m_alloc, true); }
|
||||
explicit QRawVector(int size);
|
||||
@ -270,17 +264,20 @@ private:
|
||||
T *allocate(int alloc);
|
||||
void realloc(int size, int alloc, bool ref);
|
||||
void free(T *begin, int size);
|
||||
int sizeOfTypedData() {
|
||||
// this is more or less the same as sizeof(Data), except that it doesn't
|
||||
// count the padding at the end
|
||||
return reinterpret_cast<const char *>(&(reinterpret_cast<const Data *>(this))->array[1]) - reinterpret_cast<const char *>(this);
|
||||
|
||||
class AlignmentDummy { QVectorData header; T array[1]; };
|
||||
|
||||
static Q_DECL_CONSTEXPR int offsetOfTypedData()
|
||||
{
|
||||
// (non-POD)-safe offsetof(AlignmentDummy, array)
|
||||
return (sizeof(QVectorData) + (alignOfTypedData() - 1)) & ~(alignOfTypedData() - 1);
|
||||
}
|
||||
static inline int alignOfTypedData()
|
||||
static Q_DECL_CONSTEXPR int alignOfTypedData()
|
||||
{
|
||||
#ifdef Q_ALIGNOF
|
||||
return qMax<int>(sizeof(void*), Q_ALIGNOF(Data));
|
||||
return Q_ALIGNOF(AlignmentDummy);
|
||||
#else
|
||||
return 0;
|
||||
return sizeof(void *);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -288,11 +285,11 @@ public:
|
||||
QVector<T> mutateToVector()
|
||||
{
|
||||
Data *d = toBase(m_begin);
|
||||
d->ref = 1;
|
||||
d->ref.initializeOwned();
|
||||
d->alloc = m_alloc;
|
||||
d->size = m_size;
|
||||
d->sharable = 0;
|
||||
d->capacity = 0;
|
||||
d->capacityReserved = 0;
|
||||
d->offset = offsetOfTypedData();
|
||||
|
||||
QVector<T> v;
|
||||
*reinterpret_cast<QVectorData **>(&v) = d;
|
||||
@ -309,7 +306,7 @@ void QRawVector<T>::reserve(int asize)
|
||||
template <typename T>
|
||||
void QRawVector<T>::resize(int asize)
|
||||
{ realloc(asize, (asize > m_alloc || (asize < m_size && asize < (m_alloc >> 1)))
|
||||
? QVectorData::grow(sizeOfTypedData(), asize, sizeof(T), QTypeInfo<T>::isStatic)
|
||||
? QVectorData::grow(offsetOfTypedData(), asize, sizeof(T))
|
||||
: m_alloc, false); }
|
||||
template <typename T>
|
||||
inline void QRawVector<T>::clear()
|
||||
@ -370,7 +367,7 @@ QRawVector<T> &QRawVector<T>::operator=(const QRawVector<T> &v)
|
||||
template <typename T>
|
||||
inline T *QRawVector<T>::allocate(int aalloc)
|
||||
{
|
||||
QVectorData *d = QVectorData::allocate(sizeOfTypedData() + (aalloc - 1) * sizeof(T), alignOfTypedData());
|
||||
QVectorData *d = QVectorData::allocate(offsetOfTypedData() + aalloc * sizeof(T), alignOfTypedData());
|
||||
Q_CHECK_PTR(d);
|
||||
return fromBase(d);
|
||||
}
|
||||
@ -446,10 +443,9 @@ void QRawVector<T>::realloc(int asize, int aalloc, bool ref)
|
||||
changed = true;
|
||||
} else {
|
||||
QT_TRY {
|
||||
QVectorData *mem = QVectorData::reallocate(
|
||||
toBase(m_begin), sizeOfTypedData() + (aalloc - 1) * sizeof(T),
|
||||
sizeOfTypedData()
|
||||
+ (xalloc - 1) * sizeof(T), alignOfTypedData());
|
||||
QVectorData *mem = QVectorData::reallocate(toBase(m_begin),
|
||||
offsetOfTypedData() + aalloc * sizeof(T),
|
||||
offsetOfTypedData() + xalloc * sizeof(T), alignOfTypedData());
|
||||
Q_CHECK_PTR(mem);
|
||||
xbegin = fromBase(mem);
|
||||
xsize = m_size;
|
||||
@ -511,8 +507,7 @@ void QRawVector<T>::append(const T &t)
|
||||
{
|
||||
if (m_size + 1 > m_alloc) {
|
||||
const T copy(t);
|
||||
realloc(m_size, QVectorData::grow(sizeOfTypedData(), m_size + 1, sizeof(T),
|
||||
QTypeInfo<T>::isStatic), false);
|
||||
realloc(m_size, QVectorData::grow(offsetOfTypedData(), m_size + 1, sizeof(T)), false);
|
||||
if (QTypeInfo<T>::isComplex)
|
||||
new (m_begin + m_size) T(copy);
|
||||
else
|
||||
@ -533,8 +528,7 @@ typename QRawVector<T>::iterator QRawVector<T>::insert(iterator before, size_typ
|
||||
if (n != 0) {
|
||||
const T copy(t);
|
||||
if (m_size + n > m_alloc)
|
||||
realloc(m_size, QVectorData::grow(sizeOfTypedData(), m_size + n, sizeof(T),
|
||||
QTypeInfo<T>::isStatic), false);
|
||||
realloc(m_size, QVectorData::grow(offsetOfTypedData(), m_size + n, sizeof(T)), false);
|
||||
if (QTypeInfo<T>::isStatic) {
|
||||
T *b = m_begin + m_size;
|
||||
T *i = m_begin + m_size + n;
|
||||
|
Loading…
Reference in New Issue
Block a user