1// Copyright (C) 2022 Intel Corporation.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#ifndef QTIPCCOMMON_H
6#define QTIPCCOMMON_H
7
8#include <QtCore/qglobal.h>
9#include <QtCore/qtcore-config.h>
10
11#if QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore)
12# include <QtCore/qstring.h>
13# include <QtCore/qobjectdefs.h>
14
15QT_BEGIN_NAMESPACE
16
17class QNativeIpcKeyPrivate;
18class QNativeIpcKey
19{
20 Q_GADGET_EXPORT(Q_CORE_EXPORT)
21public:
22 enum class Type : quint16 {
23 // 0 is reserved for the invalid type
24 // keep 1 through 0xff free, except for SystemV
25 SystemV = 0x51, // 'Q'
26
27 PosixRealtime = 0x100,
28 Windows,
29 };
30 Q_ENUM(Type)
31
32 static constexpr Type DefaultTypeForOs =
33#ifdef Q_OS_WIN
34 Type::Windows
35#else
36 Type::PosixRealtime
37#endif
38 ;
39 static Type legacyDefaultTypeForOs() noexcept;
40
41 constexpr QNativeIpcKey() noexcept = default;
42
43 explicit constexpr QNativeIpcKey(Type type) noexcept
44 : typeAndFlags{.type: type}
45 {
46 }
47
48 Q_IMPLICIT QNativeIpcKey(const QString &k, Type type = DefaultTypeForOs)
49 : key(k), typeAndFlags{.type: type}
50 {
51 }
52
53 QNativeIpcKey(const QNativeIpcKey &other)
54 : d(other.d), key(other.key), typeAndFlags(other.typeAndFlags)
55 {
56 if (isSlowPath())
57 copy_internal(other);
58 }
59
60 QNativeIpcKey(QNativeIpcKey &&other) noexcept
61 : d(std::exchange(obj&: other.d, new_val: nullptr)), key(std::move(other.key)),
62 typeAndFlags(std::move(other.typeAndFlags))
63 {
64 if (isSlowPath())
65 move_internal(other: std::move(other));
66 }
67
68 ~QNativeIpcKey()
69 {
70 if (isSlowPath())
71 destroy_internal();
72 }
73
74 QNativeIpcKey &operator=(const QNativeIpcKey &other)
75 {
76 typeAndFlags = other.typeAndFlags;
77 key = other.key;
78 if (isSlowPath() || other.isSlowPath())
79 return assign_internal(other);
80 Q_ASSERT(!d);
81 return *this;
82 }
83
84 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QNativeIpcKey)
85 void swap(QNativeIpcKey &other) noexcept
86 {
87 std::swap(a&: d, b&: other.d);
88 key.swap(other&: other.key);
89 typeAndFlags.swap(other&: other.typeAndFlags);
90 }
91
92 bool isEmpty() const noexcept
93 {
94 return key.isEmpty();
95 }
96
97 bool isValid() const noexcept
98 {
99 return type() != Type{};
100 }
101
102 constexpr Type type() const noexcept
103 {
104 return typeAndFlags.type;
105 }
106
107 constexpr void setType(Type type)
108 {
109 if (isSlowPath())
110 return setType_internal(type);
111 typeAndFlags.type = type;
112 }
113
114 QString nativeKey() const noexcept
115 {
116 return key;
117 }
118 void setNativeKey(const QString &newKey)
119 {
120 key = newKey;
121 if (isSlowPath())
122 setNativeKey_internal(newKey);
123 }
124
125 Q_CORE_EXPORT QString toString() const;
126 Q_CORE_EXPORT static QNativeIpcKey fromString(const QString &string);
127
128private:
129 struct TypeAndFlags {
130 Type type = DefaultTypeForOs;
131 quint16 reserved1 = {};
132 quint32 reserved2 = {};
133
134 void swap(TypeAndFlags &other) noexcept
135 {
136 std::swap(a&: type, b&: other.type);
137 std::swap(a&: reserved1, b&: other.reserved1);
138 std::swap(a&: reserved2, b&: other.reserved2);
139 }
140
141 friend constexpr bool operator==(const TypeAndFlags &lhs, const TypeAndFlags &rhs) noexcept
142 {
143 return lhs.type == rhs.type &&
144 lhs.reserved1 == rhs.reserved1 &&
145 lhs.reserved2 == rhs.reserved2;
146 }
147 };
148
149 QNativeIpcKeyPrivate *d = nullptr;
150 QString key;
151 TypeAndFlags typeAndFlags;
152
153 friend class QNativeIpcKeyPrivate;
154 constexpr bool isSlowPath() const noexcept
155 { return Q_UNLIKELY(d); }
156
157#ifdef Q_QDOC
158 friend size_t qHash(const QNativeIpcKey &ipcKey, size_t seed = 0) noexcept { return 0; }
159#else
160 friend Q_CORE_EXPORT size_t qHash(const QNativeIpcKey &ipcKey, size_t seed) noexcept;
161 friend size_t qHash(const QNativeIpcKey &ipcKey) noexcept
162 { return qHash(ipcKey, seed: 0); }
163#endif
164
165 Q_CORE_EXPORT void copy_internal(const QNativeIpcKey &other);
166 Q_CORE_EXPORT void move_internal(QNativeIpcKey &&other) noexcept;
167 Q_CORE_EXPORT QNativeIpcKey &assign_internal(const QNativeIpcKey &other);
168 Q_CORE_EXPORT void destroy_internal() noexcept;
169 Q_CORE_EXPORT void setType_internal(Type);
170 Q_CORE_EXPORT void setNativeKey_internal(const QString &);
171 Q_DECL_PURE_FUNCTION Q_CORE_EXPORT static int
172 compare_internal(const QNativeIpcKey &lhs, const QNativeIpcKey &rhs) noexcept;
173
174#ifdef Q_OS_DARWIN
175 Q_DECL_CONST_FUNCTION Q_CORE_EXPORT static Type defaultTypeForOs_internal() noexcept;
176#endif
177 friend bool comparesEqual(const QNativeIpcKey &lhs, const QNativeIpcKey &rhs) noexcept
178 {
179 if (!(lhs.typeAndFlags == rhs.typeAndFlags))
180 return false;
181 if (lhs.key != rhs.key)
182 return false;
183 if (lhs.d == rhs.d)
184 return true;
185 return compare_internal(lhs, rhs) == 0;
186 }
187 Q_DECLARE_EQUALITY_COMPARABLE(QNativeIpcKey)
188};
189
190// not a shared type, exactly, but this works too
191Q_DECLARE_SHARED(QNativeIpcKey)
192
193inline auto QNativeIpcKey::legacyDefaultTypeForOs() noexcept -> Type
194{
195#if defined(Q_OS_WIN)
196 return Type::Windows;
197#elif defined(QT_POSIX_IPC)
198 return Type::PosixRealtime;
199#elif defined(Q_OS_DARWIN)
200 return defaultTypeForOs_internal();
201#else
202 return Type::SystemV;
203#endif
204}
205
206QT_END_NAMESPACE
207
208#endif // QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore)
209
210
211#endif // QTIPCCOMMON_H
212

source code of qtbase/src/corelib/ipc/qtipccommon.h