From 231273b130d4cc213158ce858262b7f1b7b6fcdd Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 28 Jun 2018 15:09:23 +0200 Subject: JSON: Add qHash functions for JSON and CBOR types This way we can easily use them as keys in QHash and QSet. Change-Id: Ie744c3b5ad1176ba2ab035c7e650af483757a0c9 Reviewed-by: Thiago Macieira --- src/corelib/serialization/qcborarray.cpp | 5 ++++ src/corelib/serialization/qcborarray.h | 2 ++ src/corelib/serialization/qcbormap.cpp | 5 ++++ src/corelib/serialization/qcbormap.h | 2 ++ src/corelib/serialization/qcborvalue.cpp | 47 +++++++++++++++++++++++++++++++ src/corelib/serialization/qcborvalue.h | 2 ++ src/corelib/serialization/qjsonarray.cpp | 4 +++ src/corelib/serialization/qjsonarray.h | 2 ++ src/corelib/serialization/qjsonobject.cpp | 11 ++++++++ src/corelib/serialization/qjsonobject.h | 2 ++ src/corelib/serialization/qjsonvalue.cpp | 22 +++++++++++++++ src/corelib/serialization/qjsonvalue.h | 2 ++ src/corelib/tools/qhashfunctions.h | 5 ++++ 13 files changed, 111 insertions(+) diff --git a/src/corelib/serialization/qcborarray.cpp b/src/corelib/serialization/qcborarray.cpp index 506fb052be..05403795b0 100644 --- a/src/corelib/serialization/qcborarray.cpp +++ b/src/corelib/serialization/qcborarray.cpp @@ -1181,6 +1181,11 @@ void QCborArray::detach(qsizetype reserved) Returns the offset of this iterator relative to \a other. */ +uint qHash(const QCborArray &array, uint seed) +{ + return qHashRange(array.begin(), array.end(), seed); +} + #if !defined(QT_NO_DEBUG_STREAM) QDebug operator<<(QDebug dbg, const QCborArray &a) { diff --git a/src/corelib/serialization/qcborarray.h b/src/corelib/serialization/qcborarray.h index 4e9f7cf9b5..6b07b52a02 100644 --- a/src/corelib/serialization/qcborarray.h +++ b/src/corelib/serialization/qcborarray.h @@ -286,6 +286,8 @@ inline QCborArray QCborValueRef::toArray(const QCborArray &a) const return concrete().toArray(a); } +Q_CORE_EXPORT uint qHash(const QCborArray &array, uint seed = 0); + #if !defined(QT_NO_DEBUG_STREAM) Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborArray &a); #endif diff --git a/src/corelib/serialization/qcbormap.cpp b/src/corelib/serialization/qcbormap.cpp index f9b000393c..b18945ded1 100644 --- a/src/corelib/serialization/qcbormap.cpp +++ b/src/corelib/serialization/qcbormap.cpp @@ -1734,6 +1734,11 @@ void QCborMap::detach(qsizetype reserved) \sa operator+=(), operator-() */ +uint qHash(const QCborMap &map, uint seed) +{ + return qHashRange(map.begin(), map.end(), seed); +} + #if !defined(QT_NO_DEBUG_STREAM) QDebug operator<<(QDebug dbg, const QCborMap &m) { diff --git a/src/corelib/serialization/qcbormap.h b/src/corelib/serialization/qcbormap.h index 2e9422cf94..c895abfa59 100644 --- a/src/corelib/serialization/qcbormap.h +++ b/src/corelib/serialization/qcbormap.h @@ -337,6 +337,8 @@ inline QCborMap QCborValueRef::toMap(const QCborMap &m) const return concrete().toMap(m); } +Q_CORE_EXPORT uint qHash(const QCborMap &map, uint seed = 0); + #if !defined(QT_NO_DEBUG_STREAM) Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborMap &m); #endif diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index c1d78ef738..077a4754dc 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -2365,6 +2365,53 @@ inline QCborMap::QCborMap(QCborContainerPrivate &dd) noexcept { } +uint qHash(const QCborValue &value, uint seed) +{ + switch (value.type()) { + case QCborValue::Integer: + return qHash(value.toInteger(), seed); + case QCborValue::ByteArray: + return qHash(value.toByteArray(), seed); + case QCborValue::String: + return qHash(value.toString(), seed); + case QCborValue::Array: + return qHash(value.toArray(), seed); + case QCborValue::Map: + return qHash(value.toMap(), seed); + case QCborValue::Tag: { + QtPrivate::QHashCombine hash; + seed = hash(seed, value.tag()); + seed = hash(seed, value.taggedValue()); + return seed; + } + case QCborValue::SimpleType: + break; + case QCborValue::False: + return qHash(false, seed); + case QCborValue::True: + return qHash(true, seed); + case QCborValue::Null: + return qHash(nullptr, seed); + case QCborValue::Undefined: + return seed; + case QCborValue::Double: + return qHash(value.toDouble(), seed); + case QCborValue::DateTime: + return qHash(value.toDateTime(), seed); + case QCborValue::Url: + return qHash(value.toUrl(), seed); + case QCborValue::RegularExpression: + return qHash(value.toRegularExpression(), seed); + case QCborValue::Uuid: + return qHash(value.toUuid(), seed); + case QCborValue::Invalid: + return seed; + } + + Q_ASSERT(value.isSimpleType()); + return qHash(value.toSimpleType(), seed); +} + #if !defined(QT_NO_DEBUG_STREAM) static QDebug debugContents(QDebug &dbg, const QCborValue &v) { diff --git a/src/corelib/serialization/qcborvalue.h b/src/corelib/serialization/qcborvalue.h index f0bfa23392..6d9ed0810a 100644 --- a/src/corelib/serialization/qcborvalue.h +++ b/src/corelib/serialization/qcborvalue.h @@ -451,6 +451,8 @@ private: qsizetype i; }; +Q_CORE_EXPORT uint qHash(const QCborValue &value, uint seed = 0); + #if !defined(QT_NO_DEBUG_STREAM) Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborValue &v); #endif diff --git a/src/corelib/serialization/qjsonarray.cpp b/src/corelib/serialization/qjsonarray.cpp index 8ee9ce0de7..1187bb03a3 100644 --- a/src/corelib/serialization/qjsonarray.cpp +++ b/src/corelib/serialization/qjsonarray.cpp @@ -1237,6 +1237,10 @@ void QJsonArray::compact() a = static_cast(d->header->root()); } +uint qHash(const QJsonArray &array, uint seed) +{ + return qHashRange(array.begin(), array.end(), seed); +} #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) QDebug operator<<(QDebug dbg, const QJsonArray &a) diff --git a/src/corelib/serialization/qjsonarray.h b/src/corelib/serialization/qjsonarray.h index 8d41138c97..5dff4a0aa9 100644 --- a/src/corelib/serialization/qjsonarray.h +++ b/src/corelib/serialization/qjsonarray.h @@ -265,6 +265,8 @@ private: Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonArray) +Q_CORE_EXPORT uint qHash(const QJsonArray &array, uint seed = 0); + #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonArray &); #endif diff --git a/src/corelib/serialization/qjsonobject.cpp b/src/corelib/serialization/qjsonobject.cpp index 4a316c8a6f..950bec535b 100644 --- a/src/corelib/serialization/qjsonobject.cpp +++ b/src/corelib/serialization/qjsonobject.cpp @@ -1292,6 +1292,17 @@ void QJsonObject::setValueAt(int i, const QJsonValue &val) insert(e->key(), val); } +uint qHash(const QJsonObject &object, uint seed) +{ + QtPrivate::QHashCombine hash; + for (auto it = object.begin(), end = object.end(); it != end; ++it) { + const QString key = it.key(); + const QJsonValue value = it.value(); + seed = hash(seed, std::pair(key, value)); + } + return seed; +} + #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) QDebug operator<<(QDebug dbg, const QJsonObject &o) { diff --git a/src/corelib/serialization/qjsonobject.h b/src/corelib/serialization/qjsonobject.h index 610bce694c..be42d3747a 100644 --- a/src/corelib/serialization/qjsonobject.h +++ b/src/corelib/serialization/qjsonobject.h @@ -262,6 +262,8 @@ private: Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonObject) +Q_CORE_EXPORT uint qHash(const QJsonObject &object, uint seed = 0); + #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonObject &); #endif diff --git a/src/corelib/serialization/qjsonvalue.cpp b/src/corelib/serialization/qjsonvalue.cpp index 4469302e31..2c04da4885 100644 --- a/src/corelib/serialization/qjsonvalue.cpp +++ b/src/corelib/serialization/qjsonvalue.cpp @@ -876,6 +876,28 @@ QJsonValue QJsonValueRef::toValue() const return o->valueAt(index); } +uint qHash(const QJsonValue &value, uint seed) +{ + switch (value.type()) { + case QJsonValue::Null: + return qHash(nullptr, seed); + case QJsonValue::Bool: + return qHash(value.toBool(), seed); + case QJsonValue::Double: + return qHash(value.toDouble(), seed); + case QJsonValue::String: + return qHash(value.toString(), seed); + case QJsonValue::Array: + return qHash(value.toArray(), seed); + case QJsonValue::Object: + return qHash(value.toObject(), seed); + case QJsonValue::Undefined: + return seed; + } + Q_UNREACHABLE(); + return 0; +} + #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) QDebug operator<<(QDebug dbg, const QJsonValue &o) { diff --git a/src/corelib/serialization/qjsonvalue.h b/src/corelib/serialization/qjsonvalue.h index 316d3fdf45..d8e121524d 100644 --- a/src/corelib/serialization/qjsonvalue.h +++ b/src/corelib/serialization/qjsonvalue.h @@ -247,6 +247,8 @@ public: Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonValue) +Q_CORE_EXPORT uint qHash(const QJsonValue &value, uint seed = 0); + #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonValue &); #endif diff --git a/src/corelib/tools/qhashfunctions.h b/src/corelib/tools/qhashfunctions.h index e6ae7a0b85..d013c26d66 100644 --- a/src/corelib/tools/qhashfunctions.h +++ b/src/corelib/tools/qhashfunctions.h @@ -104,6 +104,11 @@ Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QBitArray &key, uint seed = Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(QLatin1String key, uint seed = 0) Q_DECL_NOTHROW; Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qt_hash(QStringView key, uint chained = 0) Q_DECL_NOTHROW; +Q_DECL_CONST_FUNCTION inline uint qHash(std::nullptr_t, uint seed = 0) Q_DECL_NOTHROW +{ + return qHash(reinterpret_cast(nullptr), seed); +} + template inline uint qHash(const T *key, uint seed = 0) Q_DECL_NOTHROW { return qHash(reinterpret_cast(key), seed); -- cgit v1.2.3