-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
QVariant: use a typedef name when saving user types to QDataStream
Due to the way Qt 5 and 6 registered type names, they end up producing different type names for the same content for a typedef. For example, because Q_DECLARE_METATYPE can't manage a comma (it's a macro), users are forced to write something like: using MyTypeMap = QMap<QString, MyType> Q_DECLARE_METATYPE(MyTypeMap) Qt 5's Q_DECLARE_METATYPE's argument "MyTypeMap" was the only name we knew about the type, so that's what got saved in the stream. However, Qt 6 QtPrivate::typenameHelper is much more clever and obtains the name from the compiler itself, so it "sees through" the typedef and registers "QMap<QString,MyType>" as the official type name. If another library/plugin has a different typedef name for the same type (e.g., StringTypeMap), it's indeterminate which type gets saved and will even change from run to run (depends on the QHash order). [ChangeLog][QtCore][QDataStream] If QDataStream is used with a QDataStream::Version < Qt_6_0 to serialize a user type that was registered via a typedef with the metatype system, the typedef's name is used in the stream instead of the non-typedef name. This restores compatibility with Qt 5, allowing existing content to read the same QDataStreams; reading from older Qt 6 versions should not be affected. (Note: if more than one typedef name is registered, it's indetermine which name gets used) Fixes: QTBUG-96916 Pick-to: 6.3 6.2 Change-Id: I2bbf422288924c198645fffd16a8d811aa58201e Reviewed-by: Qt CI Bot <[email protected]> Reviewed-by: Lars Knoll <[email protected]>
- Loading branch information
1 parent
af36675
commit 46dc8e4
Showing
7 changed files
with
148 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
/**************************************************************************** | ||
** | ||
** Copyright (C) 2016 The Qt Company Ltd. | ||
** Copyright (C) 2021 The Qt Company Ltd. | ||
** Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, [email protected] | ||
** Copyright (C) 2021 Intel Corporation. | ||
** Contact: https://www.qt.io/licensing/ | ||
** | ||
** This file is part of the QtCore module of the Qt Toolkit. | ||
|
@@ -179,6 +181,42 @@ Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry) | |
|
||
} // namespace | ||
|
||
// used by QVariant::save(): returns the name used in the Q_DECLARE_METATYPE | ||
// macro (one of them, indetermine which one) | ||
const char *QtMetaTypePrivate::typedefNameForType(const QtPrivate::QMetaTypeInterface *type_d) | ||
{ | ||
const char *name = nullptr; | ||
QMetaTypeCustomRegistry *r = customTypeRegistry; | ||
if (!r) | ||
return name; | ||
|
||
QByteArrayView officialName(type_d->name); | ||
QReadLocker l(&r->lock); | ||
auto it = r->aliases.constBegin(); | ||
auto end = r->aliases.constEnd(); | ||
for ( ; it != end; ++it) { | ||
if (it.value() != type_d) | ||
continue; | ||
if (it.key() == officialName) | ||
continue; // skip the official name | ||
name = it.key().constData(); | ||
break; | ||
} | ||
|
||
#ifndef QT_NO_DEBUG | ||
QByteArrayList otherNames; | ||
for ( ; it != end; ++it) { | ||
if (it.value() == type_d) | ||
otherNames << it.key(); | ||
} | ||
if (!otherNames.isEmpty()) | ||
qWarning("QMetaType: type %s has more than one typedef alias: %s, %s", | ||
type_d->name, name, otherNames.join(", ").constData()); | ||
#endif | ||
|
||
return name; | ||
} | ||
|
||
/*! | ||
\macro Q_DECLARE_OPAQUE_POINTER(PointerType) | ||
\relates QMetaType | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
/**************************************************************************** | ||
** | ||
** Copyright (C) 2020 The Qt Company Ltd. | ||
** Copyright (C) 2018 Intel Corporation. | ||
** Copyright (C) 2021 The Qt Company Ltd. | ||
** Copyright (C) 2021 Intel Corporation. | ||
** Copyright (C) 2015 Olivier Goffart <[email protected]> | ||
** Contact: https://www.qt.io/licensing/ | ||
** | ||
|
@@ -1314,13 +1314,17 @@ void QVariant::save(QDataStream &s) const | |
} | ||
} | ||
const char *typeName = nullptr; | ||
if (saveAsUserType) | ||
typeName = d.type().name(); | ||
if (saveAsUserType) { | ||
if (s.version() < QDataStream::Qt_6_0) | ||
typeName = QtMetaTypePrivate::typedefNameForType(d.type().d_ptr); | ||
if (!typeName) | ||
typeName = d.type().name(); | ||
} | ||
s << typeId; | ||
if (s.version() >= QDataStream::Qt_4_2) | ||
s << qint8(d.is_null); | ||
if (typeName) | ||
s << d.type().name(); | ||
s << typeName; | ||
|
||
if (!isValid()) { | ||
if (s.version() < QDataStream::Qt_5_0) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53 changes: 53 additions & 0 deletions
53
tests/auto/corelib/serialization/qdatastream/gen_typedefq5.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/**************************************************************************** | ||
** | ||
** Copyright (C) 2021 The Qt Company Ltd. | ||
** Contact: https://www.qt.io/licensing/ | ||
** | ||
** This file is part of the test suite of the Qt Toolkit. | ||
** | ||
** $QT_BEGIN_LICENSE:GPL-EXCEPT$ | ||
** Commercial License Usage | ||
** Licensees holding valid commercial Qt licenses may use this file in | ||
** accordance with the commercial license agreement provided with the | ||
** Software or, alternatively, in accordance with the terms contained in | ||
** a written agreement between you and The Qt Company. For licensing terms | ||
** and conditions see https://www.qt.io/terms-conditions. For further | ||
** information use the contact form at https://www.qt.io/contact-us. | ||
** | ||
** GNU General Public License Usage | ||
** Alternatively, this file may be used under the terms of the GNU | ||
** General Public License version 3 as published by the Free Software | ||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT | ||
** included in the packaging of this file. Please review the following | ||
** information to ensure the GNU General Public License requirements will | ||
** be met: https://www.gnu.org/licenses/gpl-3.0.html. | ||
** | ||
** $QT_END_LICENSE$ | ||
** | ||
****************************************************************************/ | ||
|
||
|
||
#include <QDataStream> | ||
#include <QPair> | ||
#include <QFile> | ||
#include <QVariant> | ||
#include <QDebug> | ||
|
||
using CustomPair = QPair<int, int>; | ||
QDataStream &operator<<(QDataStream &ds, CustomPair pd) | ||
{ return ds << pd.first << pd.second; } | ||
QDataStream &operator>>(QDataStream &ds, CustomPair &pd) | ||
{ return ds >> pd.first >> pd.second; } | ||
Q_DECLARE_METATYPE(CustomPair) | ||
|
||
|
||
int main() { | ||
qRegisterMetaTypeStreamOperators<CustomPair>(); | ||
QFile out("typedef.q5"); | ||
out.open(QIODevice::ReadWrite); | ||
QDataStream stream(&out); | ||
stream.setVersion(QDataStream::Qt_5_15); | ||
CustomPair p {42, 100}; | ||
qDebug() << p.first << p.second; | ||
stream << QVariant::fromValue(p); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.