Revision control

++ // Copyright (C) 2022 Intel Corporation.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++ // Qt-Security score:significant reason:default
++
++ #ifndef QTIPCCOMMON_H
++ #define QTIPCCOMMON_H
++
++ #include <QtCore/qglobal.h>
++ #include <QtCore/qtcore-config.h>
++
++ #if QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore)
++ # include <QtCore/qstring.h>
++ # include <QtCore/qobjectdefs.h>
++
++ QT_BEGIN_NAMESPACE
++
++ class QNativeIpcKeyPrivate;
++ class QNativeIpcKey
++ {
++ Q_GADGET_EXPORT(Q_CORE_EXPORT)
++ public:
++ enum class Type : quint16 {
++ // 0 is reserved for the invalid type
++ // keep 1 through 0xff free, except for SystemV
++ SystemV = 0x51, // 'Q'
++
++ PosixRealtime = 0x100,
++ Windows,
++ };
++ Q_ENUM(Type)
++
++ static constexpr Type DefaultTypeForOs =
++ #ifdef Q_OS_WIN
++ Type::Windows
++ #else
++ Type::PosixRealtime
++ #endif
++ ;
++ static Type legacyDefaultTypeForOs() noexcept;
++
++ constexpr QNativeIpcKey() noexcept = default;
++
++ explicit constexpr QNativeIpcKey(Type type) noexcept
++ : typeAndFlags{type}
++ {
++ }
++
++ Q_IMPLICIT QNativeIpcKey(const QString &k, Type type = DefaultTypeForOs)
++ : key(k), typeAndFlags{type}
++ {
++ }
++
++ QNativeIpcKey(const QNativeIpcKey &other)
++ : d(other.d), key(other.key), typeAndFlags(other.typeAndFlags)
++ {
++ if (isSlowPath())
++ copy_internal(other);
++ }
++
++ QNativeIpcKey(QNativeIpcKey &&other) noexcept
++ : d(std::exchange(other.d, nullptr)), key(std::move(other.key)),
++ typeAndFlags(other.typeAndFlags)
++ {
++ if (isSlowPath())
++ move_internal(std::move(other));
++ }
++
++ ~QNativeIpcKey()
++ {
++ if (isSlowPath())
++ destroy_internal();
++ }
++
++ QNativeIpcKey &operator=(const QNativeIpcKey &other)
++ {
++ typeAndFlags = other.typeAndFlags;
++ key = other.key;
++ if (isSlowPath() || other.isSlowPath())
++ return assign_internal(other);
++ Q_ASSERT(!d);
++ return *this;
++ }
++
++ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QNativeIpcKey)
++ void swap(QNativeIpcKey &other) noexcept
++ {
++ std::swap(d, other.d);
++ key.swap(other.key);
++ typeAndFlags.swap(other.typeAndFlags);
++ }
++
++ bool isEmpty() const noexcept
++ {
++ return key.isEmpty();
++ }
++
++ bool isValid() const noexcept
++ {
++ return type() != Type{};
++ }
++
++ constexpr Type type() const noexcept
++ {
++ return typeAndFlags.type;
++ }
++
++ constexpr void setType(Type type)
++ {
++ if (isSlowPath())
++ return setType_internal(type);
++ typeAndFlags.type = type;
++ }
++
++ QString nativeKey() const noexcept
++ {
++ return key;
++ }
++ void setNativeKey(const QString &newKey)
++ {
++ key = newKey;
++ if (isSlowPath())
++ setNativeKey_internal(newKey);
++ }
++
++ Q_CORE_EXPORT QString toString() const;
++ Q_CORE_EXPORT static QNativeIpcKey fromString(const QString &string);
++
++ private:
++ struct TypeAndFlags {
++ Type type = DefaultTypeForOs;
++ quint16 reserved1 = {};
++ quint32 reserved2 = {};
++
++ void swap(TypeAndFlags &other) noexcept
++ {
++ std::swap(type, other.type);
++ std::swap(reserved1, other.reserved1);
++ std::swap(reserved2, other.reserved2);
++ }
++
++ friend constexpr bool operator==(const TypeAndFlags &lhs, const TypeAndFlags &rhs) noexcept
++ {
++ return lhs.type == rhs.type &&
++ lhs.reserved1 == rhs.reserved1 &&
++ lhs.reserved2 == rhs.reserved2;
++ }
++ };
++
++ QNativeIpcKeyPrivate *d = nullptr;
++ QString key;
++ TypeAndFlags typeAndFlags;
++
++ friend class QNativeIpcKeyPrivate;
++ constexpr bool isSlowPath() const noexcept
++ { return Q_UNLIKELY(d); }
++
++ #ifdef Q_QDOC
++ friend size_t qHash(const QNativeIpcKey &ipcKey, size_t seed = 0) noexcept { return 0; }
++ #else
++ friend Q_CORE_EXPORT size_t qHash(const QNativeIpcKey &ipcKey, size_t seed) noexcept;
++ friend size_t qHash(const QNativeIpcKey &ipcKey) noexcept
++ { return qHash(ipcKey, 0); }
++ #endif
++
++ Q_CORE_EXPORT void copy_internal(const QNativeIpcKey &other);
++ Q_CORE_EXPORT void move_internal(QNativeIpcKey &&other) noexcept;
++ Q_CORE_EXPORT QNativeIpcKey &assign_internal(const QNativeIpcKey &other);
++ Q_CORE_EXPORT void destroy_internal() noexcept;
++ Q_CORE_EXPORT void setType_internal(Type);
++ Q_CORE_EXPORT void setNativeKey_internal(const QString &);
++ Q_DECL_PURE_FUNCTION Q_CORE_EXPORT static int
++ compare_internal(const QNativeIpcKey &lhs, const QNativeIpcKey &rhs) noexcept;
++
++ #ifdef Q_OS_DARWIN
++ Q_DECL_CONST_FUNCTION Q_CORE_EXPORT static Type defaultTypeForOs_internal() noexcept;
++ #endif
++ friend bool comparesEqual(const QNativeIpcKey &lhs, const QNativeIpcKey &rhs) noexcept
++ {
++ if (!(lhs.typeAndFlags == rhs.typeAndFlags))
++ return false;
++ if (lhs.key != rhs.key)
++ return false;
++ if (lhs.d == rhs.d)
++ return true;
++ return compare_internal(lhs, rhs) == 0;
++ }
++ Q_DECLARE_EQUALITY_COMPARABLE(QNativeIpcKey)
++ };
++
++ // not a shared type, exactly, but this works too
++ Q_DECLARE_SHARED(QNativeIpcKey)
++
++ inline auto QNativeIpcKey::legacyDefaultTypeForOs() noexcept -> Type
++ {
++ #if defined(Q_OS_WIN)
++ return Type::Windows;
++ #elif defined(QT_POSIX_IPC) || defined(Q_OS_HARMONY)
++ return Type::PosixRealtime;
++ #elif defined(Q_OS_DARWIN)
++ return defaultTypeForOs_internal();
++ #else
++ return Type::SystemV;
++ #endif
++ }
++
++ QT_END_NAMESPACE
++
++ #endif // QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore)
++
++
++ #endif // QTIPCCOMMON_H