8#include <QtCore/qalgorithms.h>
9#include <QtCore/qcontainertools_impl.h>
10#include <QtCore/qhashfunctions.h>
11#include <QtCore/qiterator.h>
12#include <QtCore/qlist.h>
13#include <QtCore/qrefcount.h>
14#include <QtCore/qttypetraits.h>
16#include <initializer_list>
18#include <QtCore/q20type_traits.h>
26 bool operator==(
const QHashDummyValue &)
const noexcept {
return true; }
31template <
typename T,
typename =
void>
39template <
typename T,
typename =
void>
47template <
typename T,
typename =
void>
58 if constexpr (HasQHashOverload<T>) {
59 return qHash(t, seed);
60 }
else if constexpr (HasStdHashSpecializationWithSeed<T>) {
61 return std::hash<T>()(t, seed);
62 }
else if constexpr (HasStdHashSpecializationWithoutSeed<T>) {
64 return std::hash<T>()(t);
66 static_assert(QtPrivate::type_dependent_false<T>(),
"The key type must have a qHash overload or a std::hash specialization");
71template <
typename Key,
typename T>
79 template<
typename ...Args>
81 {
new (n)
Node{
std::move(k), T(
std::forward<Args>(args)...) }; }
82 template<
typename ...Args>
84 {
new (n)
Node{ Key(k), T(
std::forward<Args>(args)...) }; }
85 template<
typename ...Args>
88 value = T(
std::forward<Args>(args)...);
97template <
typename Key>
98struct Node<Key, QHashDummyValue> {
103 template<
typename ...Args>
105 {
new (n)
Node{
std::move(k) }; }
106 template<
typename ...Args>
108 {
new (n)
Node{ k }; }
109 template<
typename ...Args>
127 qsizetype nEntries = 0;
149template <
typename Key,
typename T>
159 template<
typename ...Args>
162 template<
typename ...Args>
187 Chain *chain =
new Chain{ c->value,
nullptr };
200 qsizetype size = n
->value->free();
204 template<
typename ...Args>
207 Chain *e =
new Chain{ T(
std::forward<Args>(args)...),
nullptr };
210 template<
typename ...Args>
213 value->value = T(
std::forward<Args>(args)...);
217template<
typename Node>
220 return QTypeInfo<
typename Node::KeyType>::isRelocatable && QTypeInfo<
typename Node::ValueType>::isRelocatable;
229 static_assert ((NEntries & LocalBucketMask) == 0,
"NEntries must be a power of two.");
240template<
typename Node>
249 struct {
alignas(Node)
unsigned char data[
sizeof(Node)]; } storage;
251 unsigned char &
nextFree() {
return *
reinterpret_cast<
unsigned char *>(&storage); }
252 Node &
node() {
return *
reinterpret_cast<Node *>(&storage); }
261 memset(offsets, SpanConstants::UnusedEntry,
sizeof(offsets));
270 if constexpr (!
std::is_trivially_destructible<Node>::value) {
271 for (
auto o : offsets) {
272 if (o != SpanConstants::UnusedEntry)
273 entries[o].node().~Node();
282 Q_ASSERT(i < SpanConstants::NEntries);
283 Q_ASSERT(offsets[i] == SpanConstants::UnusedEntry);
294 Q_ASSERT(bucket < SpanConstants::NEntries);
295 Q_ASSERT(offsets[bucket] != SpanConstants::UnusedEntry);
297 unsigned char entry = offsets[bucket];
298 offsets[bucket] = SpanConstants::UnusedEntry;
310 return (offsets[i] != SpanConstants::UnusedEntry);
312 Node &
at(size_t i)
noexcept
314 Q_ASSERT(i < SpanConstants::NEntries);
315 Q_ASSERT(offsets[i] != SpanConstants::UnusedEntry);
317 return entries[offsets[i]].node();
319 const Node &
at(size_t i)
const noexcept
321 Q_ASSERT(i < SpanConstants::NEntries);
322 Q_ASSERT(offsets[i] != SpanConstants::UnusedEntry);
324 return entries[offsets[i]].node();
340 Q_ASSERT(offsets[from] != SpanConstants::UnusedEntry);
341 Q_ASSERT(offsets[to] == SpanConstants::UnusedEntry);
342 offsets[to] = offsets[from];
343 offsets[from] = SpanConstants::UnusedEntry;
347 Q_ASSERT(to < SpanConstants::NEntries);
348 Q_ASSERT(offsets[to] == SpanConstants::UnusedEntry);
349 Q_ASSERT(fromIndex < SpanConstants::NEntries);
350 Q_ASSERT(fromSpan.offsets[fromIndex] != SpanConstants::UnusedEntry);
354 offsets[to] = nextFree;
358 size_t fromOffset = fromSpan.offsets[fromIndex];
359 fromSpan.offsets[fromIndex] = SpanConstants::UnusedEntry;
362 if constexpr (isRelocatable<Node>()) {
363 memcpy(&toEntry, &fromEntry,
sizeof(
Entry));
365 new (&toEntry.node()) Node(
std::move(fromEntry.node()));
366 fromEntry.node().~Node();
368 fromEntry.nextFree() = fromSpan
.nextFree;
369 fromSpan
.nextFree =
static_cast<
unsigned char>(fromOffset);
374 Q_ASSERT(
allocated < SpanConstants::NEntries);
389 static_assert(SpanConstants::NEntries % 8 == 0);
391 alloc = SpanConstants::NEntries / 8 * 3;
392 else if (
allocated == SpanConstants::NEntries / 8 * 3)
393 alloc = SpanConstants::NEntries / 8 * 5;
395 alloc =
allocated + SpanConstants::NEntries/8;
399 if constexpr (isRelocatable<Node>()) {
404 new (&newEntries[i].node()) Node(
std::move(
entries[i].node()));
408 for (size_t i =
allocated; i < alloc; ++i) {
409 newEntries[i].nextFree() = uchar(i + 1);
421 constexpr int SizeDigits = std::numeric_limits<size_t>::digits;
425 if (requestedCapacity <= 64)
426 return SpanConstants::NEntries;
434 int count = qCountLeadingZeroBits(requestedCapacity);
436 return (std::numeric_limits<size_t>::max)();
437 return size_t(1) << (SizeDigits - count + 1);
441 return hash & (nBuckets - 1);
445template <
typename Node>
448template <
typename Node>
464 return (std::numeric_limits<ptrdiff_t>::max)() /
sizeof(Span);
475 :
span(d
->spans + (bucket >> SpanConstants::SpanShift)),
484 return ((span - d->spans) << SpanConstants::SpanShift) | index;
493 advance_impl(d,
nullptr);
497 return !span->hasNode(index);
501 return span->offset(index);
505 return span->atOffset(offset);
509 return &span->at(index);
513 return span->insert(index);
519 return lhs.span == rhs.span && lhs.index == rhs.index;
523 void advance_impl(
const Data *d,
Span *whenAtEnd)
noexcept
527 if (Q_UNLIKELY(index == SpanConstants::NEntries)) {
530 if (
span - d
->spans == ptrdiff_t(d->numBuckets >> SpanConstants::SpanShift))
543 constexpr qptrdiff MaxSpanCount = (std::numeric_limits<qptrdiff>::max)() /
sizeof(Span);
544 constexpr size_t MaxBucketCount = MaxSpanCount << SpanConstants::SpanShift;
546 if (numBuckets > MaxBucketCount) {
551 size_t nSpans = numBuckets >> SpanConstants::SpanShift;
552 return R{
new Span[nSpans], nSpans };
557 numBuckets = GrowthPolicy::bucketsForCapacity(reserve);
558 spans = allocateSpans(numBuckets).spans;
559 seed = QHashSeed::globalSeed();
564 template <
bool Resized>
568 for (size_t s = 0; s < nSpans; ++s) {
570 for (size_t index = 0; index < SpanConstants::NEntries; ++index) {
571 if (!span.hasNode(index))
573 const Node &n = span.at(index);
574 auto it = Resized ? findBucket(n.key) :
Bucket {
spans + s, index };
575 Q_ASSERT(it.isUnused());
576 Node *newNode = it.insert();
577 new (newNode) Node(n);
584 auto r = allocateSpans(numBuckets);
586 reallocationHelper<
false>(other, r.nSpans);
590 numBuckets = GrowthPolicy::bucketsForCapacity(qMax(size, reserved));
591 spans = allocateSpans(numBuckets).spans;
592 size_t otherNSpans = other.numBuckets >> SpanConstants::SpanShift;
593 reallocationHelper<
true>(other, otherNSpans);
608 return new Data(size);
625 return iterator{
this, other.bucket};
645 size_t newBucketCount = GrowthPolicy::bucketsForCapacity(sizeHint);
648 size_t oldBucketCount = numBuckets;
649 spans = allocateSpans(newBucketCount).spans;
650 numBuckets = newBucketCount;
651 size_t oldNSpans = oldBucketCount >> SpanConstants::SpanShift;
653 for (size_t s = 0; s < oldNSpans; ++s) {
654 Span &span = oldSpans[s];
655 for (size_t index = 0; index < SpanConstants::NEntries; ++index) {
656 if (!span.hasNode(index))
658 Node &n = span.at(index);
659 auto it = findBucket(n.key);
660 Q_ASSERT(it.isUnused());
661 Node *newNode = it.insert();
662 new (newNode) Node(
std::move(n));
672 if (bucket == numBuckets)
679 return float(size)/numBuckets;
683 return size >= (numBuckets >> 1);
688 size_t hash = QHashPrivate::calculateHash(key, seed);
689 return findBucketWithHash(key, hash);
694 static_assert(std::is_same_v<std::remove_cv_t<Key>, K> ||
695 QHashHeterogeneousSearch<std::remove_cv_t<Key>, K>::value);
696 Q_ASSERT(numBuckets > 0);
697 Bucket bucket(
this, GrowthPolicy::bucketForHash(numBuckets, hash));
701 size_t offset = bucket.offset();
702 if (offset == SpanConstants::UnusedEntry) {
705 Node &n = bucket.nodeAtOffset(offset);
706 if (qHashEquals(n.key, key))
709 bucket.advanceWrapped(
this);
713 template <
typename K> Node *
findNode(
const K &key)
const noexcept
715 auto bucket = findBucket(key);
716 if (bucket.isUnused())
718 return bucket.node();
730 size_t hash = QHashPrivate::calculateHash(key, seed);
731 if (numBuckets > 0) {
732 it = findBucketWithHash(key, hash);
734 return { it.toIterator(
this),
true };
738 it = findBucketWithHash(key, hash);
740 Q_ASSERT(it.span !=
nullptr);
741 Q_ASSERT(it.isUnused());
744 return { it.toIterator(
this),
false };
749 Q_ASSERT(bucket.span->hasNode(bucket.index));
750 bucket.span->erase(bucket.index);
756 next.advanceWrapped(
this);
757 size_t offset = next.offset();
758 if (offset == SpanConstants::UnusedEntry)
760 size_t hash = QHashPrivate::calculateHash(next.nodeAtOffset(offset).key, seed);
761 Bucket newBucket(
this, GrowthPolicy::bucketForHash(numBuckets, hash));
763 if (newBucket == next) {
766 }
else if (newBucket == bucket) {
768 if (next.span == bucket.span) {
769 bucket.span->moveLocal(next.index, bucket.index);
772 bucket.span->moveFromSpan(*next.span, next.index, bucket.index);
777 newBucket.advanceWrapped(
this);
788template <
typename Node>
795 size_t span()
const noexcept {
return bucket >> SpanConstants::SpanShift; }
796 size_t index()
const noexcept {
return bucket & SpanConstants::LocalBucketMask; }
797 inline bool isUnused()
const noexcept {
return !d->spans[span()].hasNode(index()); }
799 inline Node *
node()
const noexcept
802 return &d->spans[span()].at(index());
804 bool atEnd()
const noexcept {
return !
d; }
810 if (bucket == d->numBuckets) {
821 {
return d == other.d && bucket == other.bucket; }
823 {
return !(*
this == other); }
835template <
typename Key,
typename T>
840 friend class QSet<
Key>;
841 friend class QMultiHash<
Key,
T>;
857 : d(
new Data(list.size()))
859 for (
typename std::initializer_list<
std::pair<Key,T> >::const_iterator it = list.begin(); it != list.end(); ++it)
870 static_assert(
std::is_nothrow_destructible_v<Key>,
"Types with throwing destructors are not supported in Qt containers.");
871 static_assert(
std::is_nothrow_destructible_v<T>,
"Types with throwing destructors are not supported in Qt containers.");
873 if (d && !d->ref.deref())
883 if (d && !d->ref.deref())
891 : d(
std::exchange(other.d,
nullptr))
913 for (;
f !=
l; ++
f) {
915 using V =
decltype(
e);
926 static bool compareIterators(
const const_iterator &lhs,
const const_iterator &rhs)
928 return lhs.i.node()->valuesEqual(rhs.i.node());
931 template <
typename AKey = Key,
typename AT = T,
932 QTypeTraits::compare_eq_result_container<QHash, AKey, AT> =
true>
937 if (lhs.size() != rhs.size())
942 if (i == lhs
.end() || !compareIterators(i, it))
948 QT_DECLARE_EQUALITY_OPERATORS_HELPER(
QHash,
QHash, ,
noexcept,
949 template <
typename AKey = Key,
typename AT = T,
950 QTypeTraits::compare_eq_result_container<QHash, AKey, AT> =
true>)
960 inline bool isEmpty()
const noexcept {
return !
d ||
d->
size == 0; }
1058 while (
i !=
end()) {
1085 template <
typename K>
1127 while (
i !=
end()) {
1176 friend class iterator;
1181 friend class iterator;
1182 friend class QHash<Key, T>;
1183 friend class QSet<
Key>;
1185 explicit inline const_iterator(piter it) : i(it) { }
1197 inline const Key &
key()
const noexcept {
return i.node()->key; }
1198 inline const T &
value()
const noexcept {
return i.node()->value; }
1199 inline const T &
operator*()
const noexcept {
return i.node()->value; }
1200 inline const T *
operator->()
const noexcept {
return &i.node()->value; }
1232 const Key &
operator*()
const noexcept {
return i.key(); }
1233 const Key *
operator->()
const noexcept {
return &i.key(); }
1246 inline iterator begin() {
if (!d)
return iterator(); detach();
return iterator(d->begin()); }
1263 auto asKeyValueRange()
const & {
return QtPrivate::QKeyValueRange<
const QHash &>(*
this); }
1265 auto asKeyValueRange()
const && {
return QtPrivate::QKeyValueRange<QHash>(std::move(*
this)); }
1296 iterator i = iterator{d->detachedIterator(it.i)};
1297 typename Data::Bucket bucket(i.i);
1300 if (bucket.toBucketIndex(d) == d->numBuckets - 1 || bucket.isUnused())
1307 return equal_range_impl(*
this, key);
1311 return equal_range_impl(*
this, key);
1314 template <
typename Hash,
typename K>
static auto equal_range_impl(Hash &self,
const K &key)
1316 auto first = self.find(key);
1317 auto second = first;
1318 if (second !=
decltype(first){})
1320 return std::make_pair(first, second);
1323 template <
typename K> iterator findImpl(
const K &key)
1327 auto it = d->findBucket(key);
1328 size_t bucket = it.toBucketIndex(d);
1330 it =
typename Data::Bucket(d, bucket);
1333 return iterator(it.toIterator(d));
1335 template <
typename K>
const_iterator constFindImpl(
const K &key)
const noexcept
1339 auto it = d->findBucket(key);
1351 return findImpl(key);
1355 return constFindImpl(key);
1363 return emplace(key, value);
1368 if (d == hash.d || !hash.d)
1378 emplace(it.key(), it.value());
1381 template <
typename ...Args>
1385 return emplace(
std::move(copy),
std::forward<Args>(args)...);
1388 template <
typename ...Args>
1392 if (d->shouldGrow())
1393 return emplace_helper(
std::move(key), T(
std::forward<Args>(args)...));
1394 return emplace_helper(
std::move(key),
std::forward<Args>(args)...);
1397 const auto copy = *
this;
1399 return emplace_helper(
std::move(key),
std::forward<Args>(args)...);
1402 template <
typename... Args>
1405 return tryEmplace_impl(key,
std::forward<Args>(args)...);
1407 template <
typename... Args>
1410 return tryEmplace_impl(
std::move(key),
std::forward<Args>(args)...);
1415 return tryEmplace_impl(key, value);
1418 template <
typename... Args>
1421 return tryEmplace_impl(key,
std::forward<Args>(args)...);
1423 template <
typename... Args>
1426 return tryEmplace_impl(
std::move(key),
std::forward<Args>(args)...);
1428 template <
typename... Args>
1433 template <
typename... Args>
1440 template <
typename K,
typename... Args>
1447 size_t hash =
QHashPrivate::calculateHash(key, d->seed);
1448 typename Data::Bucket bucket = d->findBucketWithHash(key, hash);
1449 const bool shouldInsert = bucket.isUnused();
1453 if (!isDetached() || (shouldInsert && d->shouldGrow())) {
1454 detachGuard = *
this;
1455 const bool resized = shouldInsert && d->shouldGrow();
1456 const size_t bucketIndex = bucket.toBucketIndex(d);
1459 d = resized ? Data::detached(d, d->size + 1) : Data::detached(d);
1460 bucket = resized ? d->findBucketWithHash(key, hash) :
typename Data::Bucket(d, bucketIndex);
1463 Node *n = bucket.insert();
1464 using ConstructProxy =
typename QHashPrivate::HeterogenousConstructProxy<Key, K>;
1465 Node::createInPlace(n, ConstructProxy(
std::forward<K>(key)),
1466 std::forward<Args>(args)...);
1469 return {iterator(bucket.toIterator(d)), shouldInsert};
1472 template <
typename Value>
1475 return insertOrAssign_impl(key,
std::forward<Value>(value));
1477 template <
typename Value>
1480 return insertOrAssign_impl(
std::move(key),
std::forward<Value>(value));
1482 template <
typename Value>
1485 return insertOrAssign_impl(key,
std::forward<Value>(value));
1487 template <
typename Value>
1490 return insertOrAssign_impl(
std::move(key),
std::forward<Value>(value));
1492 template <
typename Value>
1497 template <
typename Value>
1504 template <
typename K,
typename Value>
1507 auto r = tryEmplace(
std::forward<K>(key),
std::forward<Value>(value));
1509 *r.iterator =
std::forward<Value>(value);
1515 float load_factor()
const noexcept {
return d ? d->loadFactor() : 0; }
1521 inline bool empty()
const noexcept {
return isEmpty(); }
1524 template <
typename ...Args>
1525 iterator emplace_helper(Key &&key, Args &&... args)
1527 auto result = d->findOrInsert(key);
1528 if (!result.initialized)
1529 Node::createInPlace(result.it.node(),
std::move(key),
std::forward<Args>(args)...);
1531 result.it.node()->emplaceValue(
std::forward<Args>(args)...);
1532 return iterator(result.it);
1535 template <
typename K>
1538 template <
typename K>
1542 template <
typename K, if_heterogeneously_searchable<K> =
true>
1545 return removeImpl(key);
1547 template <
typename K, if_heterogeneously_searchable<K> =
true>
1550 return takeImpl(key);
1552 template <
typename K, if_heterogeneously_searchable<K> =
true>
1555 return d ? d->findNode(key) !=
nullptr :
false;
1557 template <
typename K, if_heterogeneously_searchable<K> =
true>
1560 return contains(key) ? 1 : 0;
1562 template <
typename K, if_heterogeneously_searchable<K> =
true>
1565 if (
auto *v = valueImpl(key))
1570 template <
typename K, if_heterogeneously_searchable<K> =
true>
1571 T
value(
const K &key,
const T &defaultValue)
const noexcept
1573 if (
auto *v = valueImpl(key))
1576 return defaultValue;
1578 template <
typename K, if_heterogeneously_searchable<K> =
true, if_key_constructible_from<K> =
true>
1581 return *tryEmplace(key).iterator;
1583 template <
typename K, if_heterogeneously_searchable<K> =
true>
1588 template <
typename K, if_heterogeneously_searchable<K> =
true>
1592 return equal_range_impl(*
this, key);
1594 template <
typename K, if_heterogeneously_searchable<K> =
true>
1598 return equal_range_impl(*
this, key);
1600 template <
typename K, if_heterogeneously_searchable<K> =
true>
1603 return findImpl(key);
1605 template <
typename K, if_heterogeneously_searchable<K> =
true>
1608 return constFindImpl(key);
1610 template <
typename K, if_heterogeneously_searchable<K> =
true>
1615 template <
typename K,
typename... Args, if_heterogeneously_searchable<K> =
true, if_key_constructible_from<K> =
true>
1618 return tryEmplace_impl(
std::forward<K>(key),
std::forward<Args>(args)...);
1620 template <
typename K, if_heterogeneously_searchable<K> =
true, if_key_constructible_from<K> =
true>
1623 return tryEmplace_impl(
std::forward<K>(key), value);
1625 template <
typename K,
typename... Args, if_heterogeneously_searchable<K> =
true, if_key_constructible_from<K> =
true>
1628 return tryEmplace_impl(
std::forward<K>(key),
std::forward<Args>(args)...);
1630 template <
typename K,
typename... Args, if_heterogeneously_searchable<K> =
true, if_key_constructible_from<K> =
true>
1635 template <
typename K,
typename Value, if_heterogeneously_searchable<K> =
true, if_key_constructible_from<K> =
true>
1638 return insertOrAssign_impl(
std::forward<K>(key),
std::forward<Value>(value));
1640 template <
typename K,
typename Value, if_heterogeneously_searchable<K> =
true, if_key_constructible_from<K> =
true>
1643 return insertOrAssign_impl(
std::forward<K>(key),
std::forward<Value>(value));
1645 template <
typename K,
typename Value, if_heterogeneously_searchable<K> =
true, if_key_constructible_from<K> =
true>
1653template <
typename Key,
typename T>
1656 using Node = QHashPrivate::MultiNode<Key, T>;
1657 using Data = QHashPrivate::Data<Node>;
1658 using Chain = QHashPrivate::MultiNodeChain<T>;
1661 qsizetype m_size = 0;
1664 using key_type = Key;
1665 using mapped_type = T;
1666 using value_type = T;
1667 using size_type = qsizetype;
1668 using difference_type = qsizetype;
1669 using reference = T &;
1670 using const_reference =
const T &;
1672 QMultiHash()
noexcept =
default;
1673 inline QMultiHash(std::initializer_list<std::pair<Key,T> > list)
1674 : d(
new Data(list.size()))
1676 for (
typename std::initializer_list<std::pair<Key,T> >::const_iterator it = list.begin(); it != list.end(); ++it)
1677 insert(it->first, it->second);
1680 template <
typename InputIterator>
1681 QMultiHash(InputIterator f, InputIterator l);
1683 template <
typename InputIterator, QtPrivate::IfAssociativeIteratorHasKeyAndValue<InputIterator> =
true>
1684 QMultiHash(InputIterator f, InputIterator l)
1686 QtPrivate::reserveIfForwardIterator(
this, f, l);
1688 insert(f.key(), f.value());
1691 template <
typename InputIterator, QtPrivate::IfAssociativeIteratorHasFirstAndSecond<InputIterator> =
true>
1692 QMultiHash(InputIterator f, InputIterator l)
1694 QtPrivate::reserveIfForwardIterator(
this, f, l);
1695 for (; f != l; ++f) {
1697 using V =
decltype(e);
1698 insert(std::forward<V>(e).first, std::forward<V>(e).second);
1702 QMultiHash(
const QMultiHash &other)
noexcept
1703 : d(other.d), m_size(other.m_size)
1710 static_assert(std::is_nothrow_destructible_v<Key>,
"Types with throwing destructors are not supported in Qt containers.");
1711 static_assert(std::is_nothrow_destructible_v<T>,
"Types with throwing destructors are not supported in Qt containers.");
1713 if (d && !d->ref.deref())
1717 QMultiHash &operator=(
const QMultiHash &other)
noexcept(std::is_nothrow_destructible<Node>::value)
1723 if (d && !d->ref.deref())
1726 m_size = other.m_size;
1730 QMultiHash(QMultiHash &&other)
noexcept
1731 : d(std::exchange(other.d,
nullptr)),
1732 m_size(std::exchange(other.m_size, 0))
1735 QMultiHash &operator=(QMultiHash &&other)
noexcept(std::is_nothrow_destructible<Node>::value)
1737 QMultiHash moved(std::move(other));
1742 explicit QMultiHash(
const QHash<Key, T> &other)
1743 : QMultiHash(other.begin(), other.end())
1746 explicit QMultiHash(QHash<Key, T> &&other)
1748 unite(std::move(other));
1751 void swap(QMultiHash &other)
noexcept
1753 qt_ptr_swap(d, other.d);
1754 std::swap(m_size, other.m_size);
1759 template <
typename AKey = Key,
typename AT = T,
1760 QTypeTraits::compare_eq_result_container<QMultiHash, AKey, AT> =
true>
1761 friend bool comparesEqual(
const QMultiHash &lhs,
const QMultiHash &rhs)
noexcept
1765 if (lhs.m_size != rhs.m_size)
1767 if (lhs.m_size == 0)
1772 if (lhs.d->size != rhs.d->size)
1774 for (
auto it = rhs.d->begin(); it != rhs.d->end(); ++it) {
1775 auto *n = lhs.d->findNode(it.node()->key);
1778 Chain *e = it.node()->value;
1780 Chain *oe = n->value;
1782 if (oe->value == e->value)
1794 QT_DECLARE_EQUALITY_OPERATORS_HELPER(QMultiHash, QMultiHash, ,
noexcept,
1795 template <
typename AKey = Key,
typename AT = T,
1796 QTypeTraits::compare_eq_result_container<QMultiHash, AKey, AT> =
true>)
1799 friend bool operator==(
const QMultiHash &lhs,
const QMultiHash &rhs)
noexcept;
1800 friend bool operator!=(
const QMultiHash &lhs,
const QMultiHash &rhs)
noexcept;
1803 inline qsizetype size()
const noexcept {
return m_size; }
1806 inline bool isEmpty()
const noexcept {
return !m_size; }
1808 inline qsizetype capacity()
const noexcept {
return d ? qsizetype(d->numBuckets >> 1) : 0; }
1809 void reserve(qsizetype size)
1812 if (size && (
this->capacity() >= size))
1817 d = Data::detached(d, size_t(size));
1819 inline void squeeze() { reserve(0); }
1821 inline void detach() {
if (!d || d->ref.isShared()) d = Data::detached(d); }
1822 inline bool isDetached()
const noexcept {
return d && !d->ref.isShared(); }
1823 bool isSharedWith(
const QMultiHash &other)
const noexcept {
return d == other.d; }
1825 void clear()
noexcept(std::is_nothrow_destructible<Node>::value)
1827 if (d && !d->ref.deref())
1833 qsizetype remove(
const Key &key)
1835 return removeImpl(key);
1838 template <
typename K> qsizetype removeImpl(
const K &key)
1842 auto it = d->findBucket(key);
1843 size_t bucket = it.toBucketIndex(d);
1845 it =
typename Data::Bucket(d, bucket);
1849 qsizetype n = Node::freeChain(it.node());
1851 Q_ASSERT(m_size >= 0);
1857 template <
typename Predicate>
1858 qsizetype removeIf(Predicate pred)
1860 return QtPrivate::associative_erase_if(*
this, pred);
1863 T take(
const Key &key)
1865 return takeImpl(key);
1868 template <
typename K> T takeImpl(
const K &key)
1872 auto it = d->findBucket(key);
1873 size_t bucket = it.toBucketIndex(d);
1875 it =
typename Data::Bucket(d, bucket);
1879 Chain *e = it.node()->value;
1881 T t = std::move(e->value);
1883 it.node()->value = e->next;
1890 Q_ASSERT(m_size >= 0);
1895 bool contains(
const Key &key)
const noexcept
1899 return d->findNode(key) !=
nullptr;
1903 const Key *keyImpl(
const T &value)
const noexcept
1906 auto i = d->begin();
1907 while (i != d->end()) {
1908 Chain *e = i.node()->value;
1909 if (e->contains(value))
1910 return &i.node()->key;
1918 Key key(
const T &value)
const noexcept
1920 if (
auto *k = keyImpl(value))
1925 Key key(
const T &value,
const Key &defaultKey)
const noexcept
1927 if (
auto *k = keyImpl(value))
1934 template <
typename K>
1935 T *valueImpl(
const K &key)
const noexcept
1938 Node *n = d->findNode(key);
1941 return &n->value->value;
1947 T value(
const Key &key)
const noexcept
1949 if (
auto *v = valueImpl(key))
1954 T value(
const Key &key,
const T &defaultValue)
const noexcept
1956 if (
auto *v = valueImpl(key))
1959 return defaultValue;
1962 T &operator[](
const Key &key)
1964 return operatorIndexImpl(key);
1967 template <
typename K> T &operatorIndexImpl(
const K &key)
1969 const auto copy = isDetached() ? QMultiHash() : *
this;
1971 auto result = d->findOrInsert(key);
1972 Q_ASSERT(!result.it.atEnd());
1973 if (!result.initialized) {
1974 Node::createInPlace(result.it.node(), Key(key), T());
1977 return result.it.node()->value->value;
1981 const T operator[](
const Key &key)
const noexcept
1986 QList<Key> uniqueKeys()
const
1990 auto i = d->begin();
1991 while (i != d->end()) {
1992 res.append(i.node()->key);
1999 QList<Key> keys()
const {
return QList<Key>(keyBegin(), keyEnd()); }
2000 QList<Key> keys(
const T &value)
const
2003 const_iterator i = begin();
2004 while (i != end()) {
2005 if (i.value() == value)
2006 res.append(i.key());
2012 QList<T> values()
const {
return QList<T>(begin(), end()); }
2013 QList<T> values(
const Key &key)
const
2015 return valuesImpl(key);
2018 template <
typename K> QList<T> valuesImpl(
const K &key)
const
2022 Node *n = d->findNode(key);
2024 Chain *e = n->value;
2026 values.append(e->value);
2035 class const_iterator;
2039 using piter =
typename QHashPrivate::iterator<Node>;
2040 friend class const_iterator;
2041 friend class QMultiHash<Key, T>;
2043 Chain **e =
nullptr;
2044 explicit inline iterator(piter it, Chain **entry =
nullptr)
noexcept : i(it), e(entry)
2046 if (!it.atEnd() && !e) {
2047 e = &it.node()->value;
2053 typedef std::forward_iterator_tag iterator_category;
2054 typedef qptrdiff difference_type;
2055 typedef T value_type;
2057 typedef T &reference;
2059 constexpr iterator()
noexcept =
default;
2061 inline const Key &key()
const noexcept {
return i.node()->key; }
2062 inline T &value()
const noexcept {
return (*e)->value; }
2063 inline T &operator*()
const noexcept {
return (*e)->value; }
2064 inline T *operator->()
const noexcept {
return &(*e)->value; }
2065 inline bool operator==(
const iterator &o)
const noexcept {
return e == o.e; }
2066 inline bool operator!=(
const iterator &o)
const noexcept {
return e != o.e; }
2068 inline iterator &operator++()
noexcept {
2074 e = i.atEnd() ?
nullptr : &i.node()->value;
2078 inline iterator operator++(
int)
noexcept {
2084 inline bool operator==(
const const_iterator &o)
const noexcept {
return e == o.e; }
2085 inline bool operator!=(
const const_iterator &o)
const noexcept {
return e != o.e; }
2087 friend class iterator;
2089 class const_iterator
2091 using piter =
typename QHashPrivate::iterator<Node>;
2092 friend class iterator;
2093 friend class QMultiHash<Key, T>;
2095 Chain **e =
nullptr;
2096 explicit inline const_iterator(piter it, Chain **entry =
nullptr)
noexcept : i(it), e(entry)
2098 if (!it.atEnd() && !e) {
2099 e = &it.node()->value;
2105 typedef std::forward_iterator_tag iterator_category;
2106 typedef qptrdiff difference_type;
2107 typedef T value_type;
2108 typedef const T *pointer;
2109 typedef const T &reference;
2111 constexpr const_iterator()
noexcept =
default;
2112 inline const_iterator(
const iterator &o)
noexcept : i(o.i), e(o.e) { }
2114 inline const Key &key()
const noexcept {
return i.node()->key; }
2115 inline T &value()
const noexcept {
return (*e)->value; }
2116 inline T &operator*()
const noexcept {
return (*e)->value; }
2117 inline T *operator->()
const noexcept {
return &(*e)->value; }
2118 inline bool operator==(
const const_iterator &o)
const noexcept {
return e == o.e; }
2119 inline bool operator!=(
const const_iterator &o)
const noexcept {
return e != o.e; }
2121 inline const_iterator &operator++()
noexcept {
2127 e = i.atEnd() ?
nullptr : &i.node()->value;
2131 inline const_iterator operator++(
int)
noexcept
2133 const_iterator r = *
this;
2138 friend class const_iterator;
2145 typedef typename const_iterator::iterator_category iterator_category;
2146 typedef qptrdiff difference_type;
2147 typedef Key value_type;
2148 typedef const Key *pointer;
2149 typedef const Key &reference;
2151 key_iterator()
noexcept =
default;
2152 explicit key_iterator(const_iterator o)
noexcept : i(o) { }
2154 const Key &operator*()
const noexcept {
return i.key(); }
2155 const Key *operator->()
const noexcept {
return &i.key(); }
2156 bool operator==(key_iterator o)
const noexcept {
return i == o.i; }
2157 bool operator!=(key_iterator o)
const noexcept {
return i != o.i; }
2159 inline key_iterator &operator++()
noexcept { ++i;
return *
this; }
2160 inline key_iterator operator++(
int)
noexcept {
return key_iterator(i++);}
2161 const_iterator base()
const noexcept {
return i; }
2164 typedef QKeyValueIterator<
const Key&,
const T&, const_iterator> const_key_value_iterator;
2165 typedef QKeyValueIterator<
const Key&, T&, iterator> key_value_iterator;
2168 inline iterator begin() {
if (!d)
return iterator(); detach();
return iterator(d->begin()); }
2169 inline const_iterator begin()
const noexcept {
return d ? const_iterator(d->begin()): const_iterator(); }
2170 inline const_iterator cbegin()
const noexcept {
return d ? const_iterator(d->begin()): const_iterator(); }
2171 inline const_iterator constBegin()
const noexcept {
return d ? const_iterator(d->begin()): const_iterator(); }
2172 inline iterator end()
noexcept {
return iterator(); }
2173 inline const_iterator end()
const noexcept {
return const_iterator(); }
2174 inline const_iterator cend()
const noexcept {
return const_iterator(); }
2175 inline const_iterator constEnd()
const noexcept {
return const_iterator(); }
2176 inline key_iterator keyBegin()
const noexcept {
return key_iterator(begin()); }
2177 inline key_iterator keyEnd()
const noexcept {
return key_iterator(end()); }
2178 inline key_value_iterator keyValueBegin()
noexcept {
return key_value_iterator(begin()); }
2179 inline key_value_iterator keyValueEnd()
noexcept {
return key_value_iterator(end()); }
2180 inline const_key_value_iterator keyValueBegin()
const noexcept {
return const_key_value_iterator(begin()); }
2181 inline const_key_value_iterator constKeyValueBegin()
const noexcept {
return const_key_value_iterator(begin()); }
2182 inline const_key_value_iterator keyValueEnd()
const noexcept {
return const_key_value_iterator(end()); }
2183 inline const_key_value_iterator constKeyValueEnd()
const noexcept {
return const_key_value_iterator(end()); }
2184 auto asKeyValueRange() & {
return QtPrivate::QKeyValueRange<QMultiHash &>(*
this); }
2185 auto asKeyValueRange()
const & {
return QtPrivate::QKeyValueRange<
const QMultiHash &>(*
this); }
2186 auto asKeyValueRange() && {
return QtPrivate::QKeyValueRange<QMultiHash>(std::move(*
this)); }
2187 auto asKeyValueRange()
const && {
return QtPrivate::QKeyValueRange<QMultiHash>(std::move(*
this)); }
2189 iterator detach(const_iterator it)
2193 if (d->ref.isShared()) {
2196 Chain *entry = i.node()->value;
2197 while (entry != *it.e) {
2199 entry = entry->next;
2204 i = d->detachedIterator(i);
2205 e = &i.node()->value;
2212 return iterator(i, e);
2215 iterator erase(const_iterator it)
2218 iterator iter = detach(it);
2221 Chain *next = e->next;
2225 if (i.e == &i.i.node()->value) {
2227 typename Data::Bucket bucket(i.i);
2229 if (bucket.toBucketIndex(d) == d->numBuckets - 1 || bucket.isUnused())
2230 i = iterator(++iter.i);
2232 i = iterator(bucket.toIterator(d));
2234 i = iterator(++iter.i);
2238 Q_ASSERT(m_size >= 0);
2243 typedef iterator Iterator;
2244 typedef const_iterator ConstIterator;
2245 inline qsizetype count()
const noexcept {
return size(); }
2248 template <
typename K> iterator findImpl(
const K &key)
2252 auto it = d->findBucket(key);
2253 size_t bucket = it.toBucketIndex(d);
2255 it =
typename Data::Bucket(d, bucket);
2259 return iterator(it.toIterator(d));
2261 template <
typename K> const_iterator constFindImpl(
const K &key)
const noexcept
2265 auto it = d->findBucket(key);
2268 return const_iterator(it.toIterator(d));
2271 iterator find(
const Key &key)
2273 return findImpl(key);
2275 const_iterator constFind(
const Key &key)
const noexcept
2277 return constFindImpl(key);
2279 const_iterator find(
const Key &key)
const noexcept
2281 return constFindImpl(key);
2284 iterator insert(
const Key &key,
const T &value)
2286 return emplace(key, value);
2289 template <
typename ...Args>
2290 iterator emplace(
const Key &key, Args &&... args)
2292 return emplace(Key(key), std::forward<Args>(args)...);
2295 template <
typename ...Args>
2296 iterator emplace(Key &&key, Args &&... args)
2299 if (d->shouldGrow())
2300 return emplace_helper(std::move(key), T(std::forward<Args>(args)...));
2301 return emplace_helper(std::move(key), std::forward<Args>(args)...);
2304 const auto copy = *
this;
2306 return emplace_helper(std::move(key), std::forward<Args>(args)...);
2310 float load_factor()
const noexcept {
return d ? d->loadFactor() : 0; }
2311 static float max_load_factor()
noexcept {
return 0.5; }
2312 size_t bucket_count()
const noexcept {
return d ? d->numBuckets : 0; }
2313 static size_t max_bucket_count()
noexcept {
return Data::maxNumBuckets(); }
2316 inline bool empty()
const noexcept {
return isEmpty(); }
2318 inline iterator replace(
const Key &key,
const T &value)
2320 return emplaceReplace(key, value);
2323 template <
typename ...Args>
2324 iterator emplaceReplace(
const Key &key, Args &&... args)
2326 return emplaceReplace(Key(key), std::forward<Args>(args)...);
2329 template <
typename ...Args>
2330 iterator emplaceReplace(Key &&key, Args &&... args)
2333 if (d->shouldGrow())
2334 return emplaceReplace_helper(std::move(key), T(std::forward<Args>(args)...));
2335 return emplaceReplace_helper(std::move(key), std::forward<Args>(args)...);
2338 const auto copy = *
this;
2340 return emplaceReplace_helper(std::move(key), std::forward<Args>(args)...);
2343 inline QMultiHash &operator+=(
const QMultiHash &other)
2344 {
this->unite(other);
return *
this; }
2345 inline QMultiHash operator+(
const QMultiHash &other)
const
2346 { QMultiHash result = *
this; result += other;
return result; }
2348 bool contains(
const Key &key,
const T &value)
const noexcept
2350 return containsImpl(key, value);
2353 template <
typename K>
bool containsImpl(
const K &key,
const T &value)
const noexcept
2357 auto n = d->findNode(key);
2360 return n->value->contains(value);
2364 qsizetype remove(
const Key &key,
const T &value)
2366 return removeImpl(key, value);
2369 template <
typename K> qsizetype removeImpl(
const K &key,
const T &value)
2373 auto it = d->findBucket(key);
2374 size_t bucket = it.toBucketIndex(d);
2376 it =
typename Data::Bucket(d, bucket);
2381 Chain **e = &it.node()->value;
2384 if (entry->value == value) {
2392 if (!it.node()->value)
2395 Q_ASSERT(m_size >= 0);
2400 qsizetype count(
const Key &key)
const noexcept
2402 return countImpl(key);
2405 template <
typename K> qsizetype countImpl(
const K &key)
const noexcept
2409 auto it = d->findBucket(key);
2413 Chain *e = it.node()->value;
2423 qsizetype count(
const Key &key,
const T &value)
const noexcept
2425 return countImpl(key, value);
2428 template <
typename K> qsizetype countImpl(
const K &key,
const T &value)
const noexcept
2432 auto it = d->findBucket(key);
2436 Chain *e = it.node()->value;
2438 if (e->value == value)
2446 template <
typename K> iterator findImpl(
const K &key,
const T &value)
2450 const auto copy = isDetached() ? QMultiHash() : *
this;
2452 auto it = constFind(key, value);
2453 return iterator(it.i, it.e);
2455 template <
typename K> const_iterator constFindImpl(
const K &key,
const T &value)
const noexcept
2457 const_iterator i(constFind(key));
2458 const_iterator end(constEnd());
2459 while (i != end && i.key() == key) {
2460 if (i.value() == value)
2468 iterator find(
const Key &key,
const T &value)
2470 return findImpl(key, value);
2473 const_iterator constFind(
const Key &key,
const T &value)
const noexcept
2475 return constFindImpl(key, value);
2477 const_iterator find(
const Key &key,
const T &value)
const noexcept
2479 return constFind(key, value);
2482 QMultiHash &unite(
const QMultiHash &other)
2486 }
else if (other.isEmpty()) {
2489 QMultiHash copy(other);
2491 for (
auto cit = copy.cbegin(); cit != copy.cend(); ++cit)
2492 insert(cit.key(), *cit);
2497 QMultiHash &unite(
const QHash<Key, T> &other)
2499 for (
auto cit = other.cbegin(); cit != other.cend(); ++cit)
2500 insert(cit.key(), *cit);
2504 QMultiHash &unite(QHash<Key, T> &&other)
2506 if (!other.isDetached()) {
2510 auto it = other.d->begin();
2511 for (
const auto end = other.d->end(); it != end; ++it)
2512 emplace(std::move(it.node()->key), std::move(it.node()->takeValue()));
2517 std::pair<iterator, iterator> equal_range(
const Key &key)
2519 return equal_range_impl(key);
2522 template <
typename K> std::pair<iterator, iterator> equal_range_impl(
const K &key)
2524 const auto copy = isDetached() ? QMultiHash() : *
this;
2526 auto pair = std::as_const(*
this).equal_range(key);
2527 return {iterator(pair.first.i), iterator(pair.second.i)};
2531 std::pair<const_iterator, const_iterator> equal_range(
const Key &key)
const noexcept
2533 return equal_range_impl(key);
2536 template <
typename K> std::pair<const_iterator, const_iterator> equal_range_impl(
const K &key)
const noexcept
2539 return {end(), end()};
2541 auto bucket = d->findBucket(key);
2542 if (bucket.isUnused())
2543 return {end(), end()};
2544 auto it = bucket.toIterator(d);
2547 return {const_iterator(it), const_iterator(end)};
2550 void detach_helper()
2556 Data *dd =
new Data(*d);
2557 if (!d->ref.deref())
2562 template<
typename... Args>
2563 iterator emplace_helper(Key &&key, Args &&...args)
2565 auto result = d->findOrInsert(key);
2566 if (!result.initialized)
2567 Node::createInPlace(result.it.node(), std::move(key), std::forward<Args>(args)...);
2569 result.it.node()->insertMulti(std::forward<Args>(args)...);
2571 return iterator(result.it);
2574 template<
typename... Args>
2575 iterator emplaceReplace_helper(Key &&key, Args &&...args)
2577 auto result = d->findOrInsert(key);
2578 if (!result.initialized) {
2579 Node::createInPlace(result.it.node(), std::move(key), std::forward<Args>(args)...);
2582 result.it.node()->emplaceValue(std::forward<Args>(args)...);
2584 return iterator(result.it);
2587 template <
typename K>
2588 using if_heterogeneously_searchable = QHashPrivate::if_heterogeneously_searchable_with<Key, K>;
2590 template <
typename K>
2591 using if_key_constructible_from = std::enable_if_t<std::is_constructible_v<Key, K>,
bool>;
2594 template <
typename K, if_heterogeneously_searchable<K> =
true>
2595 qsizetype remove(
const K &key)
2597 return removeImpl(key);
2599 template <
typename K, if_heterogeneously_searchable<K> =
true>
2600 T take(
const K &key)
2602 return takeImpl(key);
2604 template <
typename K, if_heterogeneously_searchable<K> =
true>
2605 bool contains(
const K &key)
const noexcept
2609 return d->findNode(key) !=
nullptr;
2611 template <
typename K, if_heterogeneously_searchable<K> =
true>
2612 T value(
const K &key)
const noexcept
2614 if (
auto *v = valueImpl(key))
2619 template <
typename K, if_heterogeneously_searchable<K> =
true>
2620 T value(
const K &key,
const T &defaultValue)
const noexcept
2622 if (
auto *v = valueImpl(key))
2625 return defaultValue;
2627 template <
typename K, if_heterogeneously_searchable<K> =
true, if_key_constructible_from<K> =
true>
2628 T &operator[](
const K &key)
2630 return operatorIndexImpl(key);
2632 template <
typename K, if_heterogeneously_searchable<K> =
true>
2633 const T operator[](
const K &key)
const noexcept
2637 template <
typename K, if_heterogeneously_searchable<K> =
true>
2638 QList<T> values(
const K &key)
2640 return valuesImpl(key);
2642 template <
typename K, if_heterogeneously_searchable<K> =
true>
2643 iterator find(
const K &key)
2645 return findImpl(key);
2647 template <
typename K, if_heterogeneously_searchable<K> =
true>
2648 const_iterator constFind(
const K &key)
const noexcept
2650 return constFindImpl(key);
2652 template <
typename K, if_heterogeneously_searchable<K> =
true>
2653 const_iterator find(
const K &key)
const noexcept
2655 return constFindImpl(key);
2657 template <
typename K, if_heterogeneously_searchable<K> =
true>
2658 bool contains(
const K &key,
const T &value)
const noexcept
2660 return containsImpl(key, value);
2662 template <
typename K, if_heterogeneously_searchable<K> =
true>
2663 qsizetype remove(
const K &key,
const T &value)
2665 return removeImpl(key, value);
2667 template <
typename K, if_heterogeneously_searchable<K> =
true>
2668 qsizetype count(
const K &key)
const noexcept
2670 return countImpl(key);
2672 template <
typename K, if_heterogeneously_searchable<K> =
true>
2673 qsizetype count(
const K &key,
const T &value)
const noexcept
2675 return countImpl(key, value);
2677 template <
typename K, if_heterogeneously_searchable<K> =
true>
2678 iterator find(
const K &key,
const T &value)
2680 return findImpl(key, value);
2682 template <
typename K, if_heterogeneously_searchable<K> =
true>
2683 const_iterator constFind(
const K &key,
const T &value)
const noexcept
2685 return constFindImpl(key, value);
2687 template <
typename K, if_heterogeneously_searchable<K> =
true>
2688 const_iterator find(
const K &key,
const T &value)
const noexcept
2690 return constFind(key, value);
2692 template <
typename K, if_heterogeneously_searchable<K> =
true>
2693 std::pair<iterator, iterator>
2694 equal_range(
const K &key)
2696 return equal_range_impl(key);
2698 template <
typename K, if_heterogeneously_searchable<K> =
true>
2699 std::pair<const_iterator, const_iterator>
2700 equal_range(
const K &key)
const noexcept
2702 return equal_range_impl(key);
2706Q_DECLARE_ASSOCIATIVE_FORWARD_ITERATOR(Hash)
2707Q_DECLARE_MUTABLE_ASSOCIATIVE_FORWARD_ITERATOR(Hash)
2708Q_DECLARE_ASSOCIATIVE_FORWARD_ITERATOR(MultiHash)
2709Q_DECLARE_MUTABLE_ASSOCIATIVE_FORWARD_ITERATOR(MultiHash)
2711template <
class Key,
class T>
2712size_t qHash(
const QHash<Key, T> &key, size_t seed = 0)
2713 noexcept(
noexcept(qHash(std::declval<Key&>())) &&
noexcept(qHash(std::declval<T&>())))
2715 const QtPrivate::QHashCombine combine(seed);
2717 for (
auto it = key.begin(), end = key.end(); it != end; ++it) {
2718 size_t h = combine(seed, it.key());
2720 hash += combine(h, it.value());
2725template <
class Key,
class T>
2729 const QtPrivate::QHashCombine combine(seed);
2731 for (
auto it = key.begin(), end = key.end(); it != end; ++it) {
2732 size_t h = combine(seed, it.key());
2734 hash += combine(h, it.value());
2739template <
typename Key,
typename T,
typename Predicate>
2742 return QtPrivate::associative_erase_if(hash, pred);
2745template <
typename Key,
typename T,
typename Predicate>
2748 return QtPrivate::associative_erase_if(hash, pred);
The QAbstractFileEngineIterator class provides an iterator interface for custom file engines.
virtual ~QAbstractFileEnginePrivate()
QAbstractFileEnginePrivate(QAbstractFileEngine *q)
QFile::FileError fileError
QAbstractFileEngine *const q_ptr
\inmodule QtCore \reentrant
QDirPrivate(const QDirPrivate ©)
void clearCache(MetaDataClearing mode)
void initFileLists(const QDir &dir) const
QString resolveAbsoluteEntry() const
bool operator()(const QDirSortItem &, const QDirSortItem &) const
QDirSortItemComparator(QDir::SortFlags flags, QCollator *coll=nullptr)
int compareStrings(const QString &a, const QString &b, Qt::CaseSensitivity cs) const
const_iterator & operator++() noexcept
The prefix ++ operator ({++i}) advances the iterator to the next item in the hash and returns an iter...
const_iterator(const iterator &o) noexcept
Constructs a copy of other.
constexpr const_iterator() noexcept=default
Constructs an uninitialized iterator.
const_iterator operator++(int) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
std::forward_iterator_tag iterator_category
const T * operator->() const noexcept
Returns a pointer to the current item's value.
bool operator==(const const_iterator &o) const noexcept
Returns true if other points to the same item as this iterator; otherwise returns false.
const T & value() const noexcept
Returns the current item's value.
const Key & key() const noexcept
Returns the current item's key.
bool operator!=(const const_iterator &o) const noexcept
Returns true if other points to a different item than this iterator; otherwise returns false.
const T & operator*() const noexcept
Returns the current item's value.
key_iterator & operator++() noexcept
The prefix ++ operator ({++i}) advances the iterator to the next item in the hash and returns an iter...
key_iterator() noexcept=default
bool operator!=(key_iterator o) const noexcept
Returns true if other points to a different item than this iterator; otherwise returns false.
key_iterator operator++(int) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
const Key & operator*() const noexcept
Returns the current item's key.
const Key * operator->() const noexcept
Returns a pointer to the current item's key.
key_iterator(const_iterator o) noexcept
bool operator==(key_iterator o) const noexcept
Returns true if other points to the same item as this iterator; otherwise returns false.
const_iterator::iterator_category iterator_category
const_iterator base() const noexcept
Returns the underlying const_iterator this key_iterator is based on.
QHash & operator=(const QHash &other) noexcept(std::is_nothrow_destructible< Node >::value)
Assigns other to this hash and returns a reference to this hash.
key_value_iterator try_emplace(const_iterator, K &&key, Args &&...args)
T & operator[](const K &key)
key_iterator keyEnd() const noexcept
const T operator[](const K &key) const noexcept
std::pair< const_iterator, const_iterator > equal_range(const Key &key) const noexcept
TryEmplaceResult insertOrAssign(const Key &key, Value &&value)
float load_factor() const noexcept
Returns the current load factor of the QHash's internal hash table.
const_iterator constFind(const Key &key) const noexcept
std::pair< key_value_iterator, bool > insert_or_assign(Key &&key, Value &&value)
~QHash()
Destroys the hash.
iterator erase(const_iterator it)
std::pair< key_value_iterator, bool > try_emplace(K &&key, Args &&...args)
iterator emplace(const Key &key, Args &&... args)
key_value_iterator keyValueBegin()
const_iterator constFind(const K &key) const noexcept
T value(const K &key, const T &defaultValue) const noexcept
QHash(const QHash &other) noexcept
Constructs a copy of other.
auto asKeyValueRange() const &&
TryEmplaceResult tryEmplace(K &&key, Args &&...args)
TryEmplaceResult tryInsert(const Key &key, const T &value)
iterator emplace(Key &&key, Args &&... args)
Inserts a new element into the container.
friend bool comparesEqual(const QHash &lhs, const QHash &rhs) noexcept
TryEmplaceResult tryEmplace(const Key &key, Args &&...args)
\variable QHash::TryEmplaceResult::iterator
const_key_value_iterator constKeyValueEnd() const noexcept
bool empty() const noexcept
This function is provided for STL compatibility.
std::pair< key_value_iterator, bool > insert_or_assign(K &&key, Value &&value)
const_iterator cbegin() const noexcept
std::pair< key_value_iterator, bool > try_emplace(const Key &key, Args &&...args)
key_value_iterator insert_or_assign(const_iterator, K &&key, Value &&value)
iterator begin()
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in the hash.
void insert(const QHash &hash)
const_iterator find(const Key &key) const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
std::pair< key_value_iterator, bool > try_emplace(Key &&key, Args &&...args)
static float max_load_factor() noexcept
QKeyValueIterator< const Key &, const T &, const_iterator > const_key_value_iterator
\inmodule QtCore
const_key_value_iterator keyValueBegin() const noexcept
TryEmplaceResult insertOrAssign(K &&key, Value &&value)
key_value_iterator keyValueEnd()
const_iterator end() const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Key key_type
Typedef for Key.
iterator find(const K &key)
const_key_value_iterator constKeyValueBegin() const noexcept
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
qsizetype count(const K &key) const
std::pair< iterator, iterator > equal_range(const K &key)
key_iterator keyBegin() const noexcept
iterator Iterator
Qt-style synonym for QHash::iterator.
key_value_iterator insert_or_assign(const_iterator, const Key &key, Value &&value)
bool contains(const K &key) const
TryEmplaceResult tryInsert(K &&key, const T &value)
std::pair< const_iterator, const_iterator > equal_range(const K &key) const noexcept
size_t bucket_count() const noexcept
const_iterator ConstIterator
Qt-style synonym for QHash::const_iterator.
key_value_iterator try_emplace(const_iterator, Key &&key, Args &&...args)
auto asKeyValueRange() &&
auto asKeyValueRange() const &
const_iterator constBegin() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item in the hash.
qsizetype count() const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
QHash(std::initializer_list< std::pair< Key, T > > list)
T value(const K &key) const noexcept
const_iterator find(const K &key) const noexcept
iterator find(const Key &key)
Returns an iterator pointing to the item with the key in the hash.
iterator end() noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last ...
QHash(QHash &&other) noexcept
Move-constructs a QHash instance, making it point at the same object that other was pointing to.
std::pair< key_value_iterator, bool > insert_or_assign(const Key &key, Value &&value)
std::pair< iterator, iterator > equal_range(const Key &key)
const_iterator cend() const noexcept
key_value_iterator insert_or_assign(const_iterator, Key &&key, Value &&value)
static size_t max_bucket_count() noexcept
bool remove(const K &key)
QKeyValueIterator< const Key &, T &, iterator > key_value_iterator
\inmodule QtCore
TryEmplaceResult insertOrAssign(Key &&key, Value &&value)
QHash() noexcept=default
Constructs an empty hash.
const T & const_reference
TryEmplaceResult tryEmplace(Key &&key, Args &&...args)
key_value_iterator try_emplace(const_iterator, const Key &key, Args &&...args)
T mapped_type
Typedef for T.
const_key_value_iterator keyValueEnd() const noexcept
const_iterator begin() const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
const_iterator constEnd() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the ...
constexpr size_t bucketForHash(size_t nBuckets, size_t hash) noexcept
constexpr size_t bucketsForCapacity(size_t requestedCapacity) noexcept
constexpr bool isRelocatable()
constexpr bool HasStdHashSpecializationWithoutSeed
size_t calculateHash(const T &t, size_t seed=0)
std::conditional_t< std::is_same_v< HashKey, q20::remove_cvref_t< KeyArgument > >, KeyArgument, HashKey > HeterogenousConstructProxy
constexpr bool HasQHashOverload
constexpr bool HasStdHashSpecializationWithSeed
std::unique_ptr< QAbstractFileEngine > qt_custom_file_engine_handler_create(const QString &path)
static void appendIfMatchesNonDirListingFlags(const QDirListing::DirEntry &dirEntry, QDir::Filters filters, QFileInfoList &l)
static qsizetype rootLength(QStringView name, QDirPrivate::PathNormalizations flags)
static bool qt_cleanPath(QString *path)
bool comparesEqual(const QDir &lhs, const QDir &rhs)
static bool treatAsAbsolute(const QString &path)
static bool checkPermissions(const QDirListing::DirEntry &dirEntry, QDir::Filters filters)
bool qt_normalizePathSegments(QString *path, QDirPrivate::PathNormalizations flags)
static bool checkDotOrDotDot(const QDirListing::DirEntry &dirEntry, QDir::Filters filters)
Q_AUTOTEST_EXPORT bool qt_normalizePathSegments(QString *path, QDirPrivate::PathNormalizations flags)
qsizetype erase_if(QMultiHash< Key, T > &hash, Predicate pred)
size_t qHash(const QMultiHash< Key, T > &key, size_t seed=0) noexcept(noexcept(qHash(std::declval< Key & >())) &&noexcept(qHash(std::declval< T & >())))
qsizetype erase_if(QHash< Key, T > &hash, Predicate pred)
QDirSortItem(const QFileInfo &fi, QDir::SortFlags sort)
friend bool operator==(Bucket lhs, Bucket rhs) noexcept
size_t offset() const noexcept
bool isUnused() const noexcept
Bucket(const Data *d, size_t bucket) noexcept
Bucket(Span *s, size_t i) noexcept
void advance(const Data *d) noexcept
Node & nodeAtOffset(size_t offset)
iterator toIterator(const Data *d) const noexcept
friend bool operator!=(Bucket lhs, Bucket rhs) noexcept
void advanceWrapped(const Data *d) noexcept
Bucket(iterator it) noexcept
size_t toBucketIndex(const Data *d) const noexcept
Bucket findBucketWithHash(const K &key, size_t hash) const noexcept
iterator begin() const noexcept
QHashPrivate::Span< Node > Span
size_t nextBucket(size_t bucket) const noexcept
typename Node::ValueType T
InsertionResult findOrInsert(const K &key) noexcept
Node * findNode(const K &key) const noexcept
QHashPrivate::iterator< Node > iterator
static Data * detached(Data *d)
iterator detachedIterator(iterator other) const noexcept
constexpr iterator end() const noexcept
bool shouldGrow() const noexcept
typename Node::KeyType Key
void rehash(size_t sizeHint=0)
Q_ALWAYS_INLINE void reallocationHelper(const Data &other, size_t nSpans)
void erase(Bucket bucket) noexcept(std::is_nothrow_destructible< Node >::value)
static Data * detached(Data *d, size_t size)
float loadFactor() const noexcept
static auto allocateSpans(size_t numBuckets)
Data(const Data &other, size_t reserved)
static constexpr size_t maxNumBuckets() noexcept
Bucket findBucket(const K &key) const noexcept
qsizetype free() noexcept(std::is_nothrow_destructible_v< T >)
bool contains(const T &val) const noexcept
static qsizetype freeChain(MultiNode *n) noexcept(std::is_nothrow_destructible_v< T >)
MultiNode(MultiNode &&other)
void insertMulti(Args &&... args)
MultiNode(const MultiNode &other)
static void createInPlace(MultiNode *n, const Key &k, Args &&... args)
MultiNode(const Key &k, Chain *c)
static void createInPlace(MultiNode *n, Key &&k, Args &&... args)
MultiNode(Key &&k, Chain *c) noexcept(std::is_nothrow_move_assignable_v< Key >)
MultiNodeChain< T > Chain
void emplaceValue(Args &&... args)
static void createInPlace(Node *n, const Key &k, Args &&...)
QHashDummyValue ValueType
void emplaceValue(Args &&...)
bool valuesEqual(const Node *) const
static void createInPlace(Node *n, Key &&k, Args &&...)
void emplaceValue(Args &&... args)
bool valuesEqual(const Node *other) const
static void createInPlace(Node *n, const Key &k, Args &&... args)
static void createInPlace(Node *n, Key &&k, Args &&... args)
T && takeValue() noexcept(std::is_nothrow_move_assignable_v< T >)
static constexpr size_t SpanShift
static constexpr size_t LocalBucketMask
static constexpr size_t UnusedEntry
static constexpr size_t NEntries
unsigned char & nextFree()
unsigned char data[sizeof(Node)]
const Node & at(size_t i) const noexcept
void moveLocal(size_t from, size_t to) noexcept
void freeData() noexcept(std::is_nothrow_destructible< Node >::value)
void erase(size_t bucket) noexcept(std::is_nothrow_destructible< Node >::value)
unsigned char offsets[SpanConstants::NEntries]
Node & atOffset(size_t o) noexcept
size_t offset(size_t i) const noexcept
bool hasNode(size_t i) const noexcept
void moveFromSpan(Span &fromSpan, size_t fromIndex, size_t to) noexcept(std::is_nothrow_move_constructible_v< Node >)
const Node & atOffset(size_t o) const noexcept
Node & at(size_t i) noexcept
Node * node() const noexcept
size_t span() const noexcept
iterator operator++() noexcept
size_t index() const noexcept
QHashPrivate::Span< Node > Span
bool isUnused() const noexcept
bool operator!=(iterator other) const noexcept
bool atEnd() const noexcept
bool operator==(iterator other) const noexcept
TryEmplaceResult(QHash::iterator it, bool b)
TryEmplaceResult()=default