Merge remote-tracking branch 'origin/containers' into api_changes

Change-Id: Ib8427caca38a14c040850bf45346f3213ffd04b3
This commit is contained in:
João Abecasis 2012-03-08 14:58:00 +01:00
commit 08a993526e
77 changed files with 5851 additions and 1249 deletions

26
dist/changes-5.0.0 vendored
View File

@ -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

View File

@ -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]

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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.

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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));
}
}

View File

@ -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);

View File

@ -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; }

View File

@ -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;
}

View File

@ -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,

View File

@ -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;

View File

@ -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);
}

View 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

View 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

View 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

View 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

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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; }

View File

@ -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

View File

@ -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>

View File

@ -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;

View File

@ -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 {

View File

@ -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;

View File

@ -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; }

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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;
}
};

View File

@ -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;
}
/*!

View File

@ -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;

View File

@ -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 \

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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();
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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 &paramsIndex)
{
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");
}

View File

@ -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 &paramsIndex);
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;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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()

View File

@ -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);
}

View File

@ -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) {

View File

@ -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()

View File

@ -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 }
};

View File

@ -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));

View File

@ -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>();

View File

@ -0,0 +1,5 @@
TARGET = tst_qarraydata
SOURCES += tst_qarraydata.cpp
HEADERS += simplevector.h
QT = core testlib
CONFIG += testcase parallel_test

View 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

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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"

View File

@ -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;

View File

@ -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"

View File

@ -1,6 +1,7 @@
TEMPLATE=subdirs
SUBDIRS=\
qalgorithms \
qarraydata \
qbitarray \
qbytearray \
qbytearraymatcher \

View File

@ -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()

View File

@ -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);

View File

@ -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());
}
}

View File

@ -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;
}
}

View File

@ -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;