Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qcache.h
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
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 QCACHE_H
6#define QCACHE_H
7
8#include <QtCore/qhash.h>
9
11
12
13template <class Key, class T>
14class QCache
15{
16 struct Value
17 {
18 T *t = nullptr;
19 qsizetype cost = 0;
20 Value() noexcept = default;
21 Value(T *tt, qsizetype c) noexcept
22 : t(tt), cost(c)
23 {}
24 Value(Value &&other) noexcept
25 : t(other.t),
26 cost(other.cost)
27 {
28 other.t = nullptr;
29 }
30 Value &operator=(Value &&other) noexcept
31 {
32 qt_ptr_swap(t, other.t);
33 std::swap(cost, other.cost);
34 return *this;
35 }
36 ~Value() { delete t; }
37
38 private:
39 Q_DISABLE_COPY(Value)
40 };
41
42 struct Chain
43 {
44 Chain() noexcept : prev(this), next(this) { }
45 Chain *prev;
46 Chain *next;
47 };
48
49 struct Node : public Chain
50 {
51 using KeyType = Key;
52 using ValueType = Value;
53
54 Key key;
55 Value value;
56
57 Node(const Key &k, Value &&t) noexcept(std::is_nothrow_move_assignable_v<Key>)
58 : Chain(),
59 key(k),
60 value(std::move(t))
61 {
62 }
63 Node(Key &&k, Value &&t) noexcept(std::is_nothrow_move_assignable_v<Key>)
64 : Chain(),
65 key(std::move(k)),
66 value(std::move(t))
67 {
68 }
69 static void createInPlace(Node *n, const Key &k, T *o, qsizetype cost)
70 {
71 new (n) Node{ Key(k), Value(o, cost) };
72 }
73 void emplace(T *o, qsizetype cost)
74 {
75 value = Value(o, cost);
76 }
77
78 Node(Node &&other)
79 : Chain(other),
80 key(std::move(other.key)),
81 value(std::move(other.value))
82 {
83 Q_ASSERT(this->prev);
84 Q_ASSERT(this->next);
85 this->prev->next = this;
86 this->next->prev = this;
87 }
88 private:
89 Q_DISABLE_COPY(Node)
90 };
91
92 using Data = QHashPrivate::Data<Node>;
93
94 mutable Chain chain;
95 Data d;
96 qsizetype mx = 0;
97 qsizetype total = 0;
98
99 void unlink(Node *n) noexcept(std::is_nothrow_destructible_v<Node>)
100 {
101 Q_ASSERT(n->prev);
102 Q_ASSERT(n->next);
103 n->prev->next = n->next;
104 n->next->prev = n->prev;
105 total -= n->value.cost;
106 auto it = d.findBucket(n->key);
107 d.erase(it);
108 }
109 T *relink(const Key &key) const noexcept
110 {
111 if (isEmpty())
112 return nullptr;
113 Node *n = d.findNode(key);
114 if (!n)
115 return nullptr;
116
117 if (chain.next != n) {
118 Q_ASSERT(n->prev);
119 Q_ASSERT(n->next);
120 n->prev->next = n->next;
121 n->next->prev = n->prev;
122 n->next = chain.next;
123 chain.next->prev = n;
124 n->prev = &chain;
125 chain.next = n;
126 }
127 return n->value.t;
128 }
129
130 void trim(qsizetype m) noexcept(std::is_nothrow_destructible_v<Node>)
131 {
132 while (chain.prev != &chain && total > m) {
133 Node *n = static_cast<Node *>(chain.prev);
134 unlink(n);
135 }
136 }
137
138
139 Q_DISABLE_COPY(QCache)
140
141public:
142 inline explicit QCache(qsizetype maxCost = 100) noexcept
143 : mx(maxCost)
144 {
145 }
146 inline ~QCache()
147 {
148 static_assert(std::is_nothrow_destructible_v<Key>, "Types with throwing destructors are not supported in Qt containers.");
149 static_assert(std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
150
151 clear();
152 }
153
154 inline qsizetype maxCost() const noexcept { return mx; }
155 void setMaxCost(qsizetype m) noexcept(std::is_nothrow_destructible_v<Node>)
156 {
157 mx = m;
158 trim(mx);
159 }
160 inline qsizetype totalCost() const noexcept { return total; }
161
162 inline qsizetype size() const noexcept { return qsizetype(d.size); }
163 inline qsizetype count() const noexcept { return qsizetype(d.size); }
164 inline bool isEmpty() const noexcept { return !d.size; }
165 inline QList<Key> keys() const
166 {
167 QList<Key> k;
168 if (size()) {
169 k.reserve(size());
170 for (auto it = d.begin(); it != d.end(); ++it)
171 k << it.node()->key;
172 }
173 Q_ASSERT(k.size() == size());
174 return k;
175 }
176
177 void clear() noexcept(std::is_nothrow_destructible_v<Node>)
178 {
179 d.clear();
180 total = 0;
181 chain.next = &chain;
182 chain.prev = &chain;
183 }
184
185 bool insert(const Key &key, T *object, qsizetype cost = 1)
186 {
187 if (cost > mx) {
188 remove(key);
189 delete object;
190 return false;
191 }
192 trim(mx - cost);
193 auto result = d.findOrInsert(key);
194 Node *n = result.it.node();
195 if (result.initialized) {
196 auto prevCost = n->value.cost;
197 result.it.node()->emplace(object, cost);
198 cost -= prevCost;
199 relink(key);
200 } else {
201 Node::createInPlace(n, key, object, cost);
202 n->prev = &chain;
203 n->next = chain.next;
204 chain.next->prev = n;
205 chain.next = n;
206 }
207 total += cost;
208 return true;
209 }
210 T *object(const Key &key) const noexcept
211 {
212 return relink(key);
213 }
214 T *operator[](const Key &key) const noexcept
215 {
216 return relink(key);
217 }
218 inline bool contains(const Key &key) const noexcept
219 {
220 return !isEmpty() && d.findNode(key) != nullptr;
221 }
222
223 bool remove(const Key &key) noexcept(std::is_nothrow_destructible_v<Node>)
224 {
225 if (isEmpty())
226 return false;
227 Node *n = d.findNode(key);
228 if (!n) {
229 return false;
230 } else {
231 unlink(n);
232 return true;
233 }
234 }
235
236 T *take(const Key &key) noexcept(std::is_nothrow_destructible_v<Key>)
237 {
238 if (isEmpty())
239 return nullptr;
240 Node *n = d.findNode(key);
241 if (!n)
242 return nullptr;
243
244 T *t = n->value.t;
245 n->value.t = nullptr;
246 unlink(n);
247 return t;
248 }
249
250};
251
252QT_END_NAMESPACE
253
254#endif // QCACHE_H
static bool readIniSection(const QSettingsKey &section, QByteArrayView data, ParsedSettingsMap *settingsMap)
void set(const QString &key, const QVariant &value) override
QStringList children(const QString &prefix, ChildSpec spec) const override
virtual void initAccess()
bool readIniFile(QByteArrayView data, UnparsedSettingsMap *unparsedIniSections)
bool isWritable() const override
QString fileName() const override
QConfFileSettingsPrivate(QSettings::Format format, QSettings::Scope scope, const QString &organization, const QString &application)
void remove(const QString &key) override
QConfFileSettingsPrivate(const QString &fileName, QSettings::Format format)
const QList< QConfFile * > & getConfFiles() const
static bool readIniLine(QByteArrayView data, qsizetype &dataPos, qsizetype &lineStart, qsizetype &lineLen, qsizetype &equalsPos)
std::optional< QVariant > get(const QString &key) const override
QString name
QAtomicInt ref
UnparsedSettingsMap unparsedIniSections
ParsedSettingsMap originalKeys
qint64 size
bool userPerms
static Q_AUTOTEST_EXPORT void clearCache()
QDateTime timeStamp
QMutex mutex
ParsedSettingsMap removedKeys
ParsedSettingsMap mergedKeyMap() const
static QConfFile * fromName(const QString &name, bool _userPerms)
bool isWritable() const
ParsedSettingsMap addedKeys
\inmodule QtCore
Definition qfile.h:69
\inmodule QtCore
Definition qlockfile.h:19
QSettingsGroup(const QString &s, bool guessArraySize)
Definition qsettings_p.h:88
qsizetype num
Definition qsettings_p.h:99
QString toString() const
QString name() const
Definition qsettings_p.h:91
bool isArray() const
Definition qsettings_p.h:93
qsizetype arraySizeGuess() const
Definition qsettings_p.h:94
qsizetype maxNum
QSettingsGroup(const QString &s)
Definition qsettings_p.h:86
void setArrayIndex(qsizetype i)
Definition qsettings_p.h:95
qsizetype position
QSettingsIniKey(const QString &str, qsizetype pos=-1)
QSettingsKey(const QString &key, Qt::CaseSensitivity cs, qsizetype=-1)
Definition qsettings_p.h:48
QString originalCaseKey() const
Definition qsettings_p.h:51
qsizetype originalKeyPosition() const
Definition qsettings_p.h:52
\inmodule QtCore
Definition qsettings.h:31
Combined button and popup list for selecting options.
static const char charTraits[256]
QMap< QString, QSettingsIniSection > IniMap
QList< QConfFileCustomFormat > CustomFormatVector
Definition qsettings.cpp:89
static bool operator<(const QSettingsIniKey &k1, const QSettingsIniKey &k2)
static constexpr QChar sep
static Path getPath(QSettings::Format format, QSettings::Scope scope)
QMap< QSettingsIniKey, QVariant > IniKeyMap
static int pathHashKey(QSettings::Format format, QSettings::Scope scope)
static QString make_user_path()
static std::unique_lock< QBasicMutex > initDefaultPaths(std::unique_lock< QBasicMutex > locker)
static QString make_user_path_without_qstandard_paths()
QHash< QString, QConfFile * > ConfFileHash
Definition qsettings.cpp:75
QHash< int, Path > PathHash
Definition qsettings.cpp:88
Q_DECLARE_TYPEINFO(QSettingsIniSection, Q_RELOCATABLE_TYPE)
Q_DECLARE_TYPEINFO(QConfFileCustomFormat, Q_RELOCATABLE_TYPE)
Q_DECLARE_TYPEINFO(QSettingsIniKey, Q_RELOCATABLE_TYPE)
QCache< QString, QConfFile > ConfFileCache
Definition qsettings.cpp:76
#define FLUSH_CURRENT_SECTION()
static void iniChopTrailingSpaces(QString &str, qsizetype limit)
Q_DECLARE_TYPEINFO(QSettingsGroup, Q_RELOCATABLE_TYPE)
static const Qt::CaseSensitivity IniCaseSensitivity
Definition qsettings_p.h:43
Q_DECLARE_TYPEINFO(QSettingsKey, Q_RELOCATABLE_TYPE)
QMap< QSettingsKey, QByteArray > UnparsedSettingsMap
Definition qsettings_p.h:78
QMap< QSettingsKey, QVariant > ParsedSettingsMap
Definition qsettings_p.h:79
#define QT_QSETTINGS_ALWAYS_CASE_SENSITIVE_AND_FORGET_ORIGINAL_KEY_ORDER
Definition qsettings_p.h:36
QSettings settings("MyCompany", "MyApp")
[11]
Qt::CaseSensitivity caseSensitivity
Definition qsettings.cpp:71