18#include <private/qhashedstring_p.h>
19#include <private/qprimefornumbits_p.h>
21#include <QtCore/qbytearray.h>
22#include <QtCore/qstring.h>
23#include <QtCore/qtaggedpointer.h>
27static inline QString::DataPointer &mutableStringData(
const QHashedString &key)
29 return const_cast<QHashedString &>(key).data_ptr();
43 ,
strData(mutableStringData(key).data())
45 Q_ASSERT(key.size() <= std::numeric_limits<
int>::max());
71 if (isQString() && arrayData && !arrayData->deref())
72 QTypedArrayData<
char16_t>::deallocate(arrayData);
88 const char *
ckey =
nullptr;
97 return QHashedString(QString(QStringPrivate(arrayData, strData, length)), hash);
100 return QHashedString(QString::fromLatin1(ckey, length), hash);
103 bool isQString()
const {
return next.tag() == NodeIsQString; }
104 void setQString(
bool v) {
if (v) next.setTag(NodeIsQString);
else next.setTag(NodeIsCString); }
107 inline const char *
cStrData()
const {
return ckey; }
108 inline const char16_t *
utf16Data()
const {
return strData; }
110 inline bool equals(
const QV4::Value &string)
const {
111 QString s = string.toQStringNoThrow();
113 return QStringView(utf16Data(), length) == s;
115 return QLatin1String(cStrData(), length) == s;
119 inline bool equals(
const QV4::String *string)
const {
120 if (length != string->d()->length() || hash != string->hashValue())
123 return QStringView(utf16Data(), length) == string->toQString();
125 return QLatin1String(cStrData(), length) == string->toQString();
129 inline bool equals(
const QHashedStringRef &string)
const {
130 return length == string.length() &&
131 hash == string.hash() &&
132 (isQString()? string == QStringView {utf16Data(), length}:
133 QHashedString::compare(string.constData(), cStrData(), length));
136 inline bool equals(
const QHashedCStringRef &string)
const {
137 return length == string.length() &&
138 hash == string.hash() &&
139 (isQString()?QHashedString::compare((
const QChar *)utf16Data(), string.constData(), length):
140 QHashedString::compare(string.constData(), cStrData(), length));
152
153
154
162 template<
typename StringHash>
166 template<
typename OtherData>
177 int nb = qPrimeForNumBits(
numBits);
182 ::memset(newBuckets, 0,
sizeof(QStringHashNode *) * nb);
200 while (qPrimeForNumBits(bits) < size)
213 int bucket = node->hash % nb;
214 node->next = newBuckets[bucket];
215 newBuckets[bucket] = node;
223template<>
struct HashedForm<QString> {
typedef QHashedString Type; };
224template<>
struct HashedForm<QStringView> {
typedef QHashedStringRef Type; };
225template<>
struct HashedForm<QHashedString> {
typedef const QHashedString &Type; };
226template<>
struct HashedForm<QV4::String *> {
typedef const QV4::String *Type; };
227template<>
struct HashedForm<
const QV4::String *> {
typedef const QV4::String *Type; };
228template<>
struct HashedForm<QHashedStringRef> {
typedef const QHashedStringRef &Type; };
229template<>
struct HashedForm<QLatin1String> {
typedef QHashedCStringRef Type; };
230template<>
struct HashedForm<QHashedCStringRef> {
typedef const QHashedCStringRef &Type; };
238 Q_ASSERT(s.size() <= std::numeric_limits<
int>::max());
239 return QHashedStringRef(s.constData(),
int(s.size()));
248 Q_ASSERT(s.size() <= std::numeric_limits<
int>::max());
249 return QHashedCStringRef(s.data(),
int(s.size()));
261 static inline quint32 hashOf(
const QHashedStringRef &s) {
return s.hash(); }
263 static inline quint32 hashOf(
const QV4::String *s) {
return s->hashValue(); }
266 static inline quint32 hashOf(
const K &key) {
return hashedString(key).hash(); }
327 template<
typename StringHash,
typename Data>
330 template<
typename Data>
348 template<
typename Data,
typename Value>
364 inline bool equals(
const K &key)
const {
return d.n->equals(key); }
367 inline Value &
value()
const {
return static_cast<
Node *>(d.n)->value; }
368 inline Value &
operator*()
const {
return static_cast<
Node *>(d.n)->value; }
379 inline void insert(
const K &,
const T &);
385 inline T *
value(
const QV4::String *string)
const;
422 data.numBits = other.data.numBits;
423 data.size = other.data.size;
436 data.numBits = other.data.numBits;
437 data.size = other.data.size;
448 data.numBits = other.data.numBits;
471 delete [] data.buckets;
473 data.buckets =
nullptr;
485 return data.size== 0;
497 return data.numBuckets;
503 node->length = key.size();
504 node->hash = key.hash();
505 node->arrayData = mutableStringData(key).d_ptr();
506 node->strData = mutableStringData(key).data();
508 node->arrayData->ref();
509 node->setQString(
true);
515 node->length = key.length();
516 node->hash = key.hash();
517 node->ckey = key.constData();
526 initializeNode(rv, hashedString(key));
542 rv->length = o.length;
544 rv->arrayData = o.arrayData;
546 rv->strData = o.strData;
547 rv->setQString(
true);
549 rv->arrayData->ref();
553 rv->symbolId = o.symbolId;
572 Node *mynode = takeNode(*(
const Node *)otherNode);
573 int bucket = mynode->hash % data.numBuckets;
574 mynode->next = data.buckets[bucket];
575 data.buckets[bucket] = mynode;
581 Q_ASSERT(data.size == 0);
583 data.size = other.data.size;
586 data.rehashToBits(data.numBits);
589 for (
int i = 0; i < other.data.numBuckets; ++i) {
597template<
typename Data>
603 if (This->nodePool && node >= This->nodePool->nodes &&
604 node < (This->nodePool->nodes + This->nodePool->used)) {
606 if (node < This->nodePool->nodes)
610 node = nn->nextNewed;
612 if (node ==
nullptr && This->nodePool && This->nodePool->used)
613 node = This->nodePool->nodes + This->nodePool->used - 1;
623template<
typename StringHash,
typename Data>
626 typename StringHash::Node *n =
nullptr;
627 if (self->newedNodes)
628 n = self->newedNodes;
629 else if (self->nodePool && self->nodePool->used)
630 n = self->nodePool->nodes + self->nodePool->used - 1;
641 Node *n = takeNode(o);
642 return insertNode(n, n->hash);
649 Node *n = takeNode(key, value);
650 return insertNode(n, hashOf(key));
656 if (data.size >= data.numBuckets)
657 data.rehashToBits(data.numBits + 1);
659 int bucket = hash % data.numBuckets;
660 n->next = data.buckets[bucket];
661 data.buckets[bucket] = n;
672 Node *n = findNode(key);
676 createNode(key, value);
682 insert(iter.key(), iter.value());
688 insert(iter.key(), iter.value());
695 QStringHashNode *node = data.numBuckets?data.buckets[hashOf(key) % data.numBuckets]:
nullptr;
697 typename HashedForm<K>::Type hashedKey(hashedString(key));
698 while (node && !node->equals(hashedKey))
699 node = node->next.data();
708 Node *n = findNode(key);
709 return n?&n->value:
nullptr;
715 return value(iter.node()->key());
721 return value(iter.node()->key());
727 Node *n = findNode(string);
728 return n?&n->value:
nullptr;
735 return nullptr != value(key);
742 Node *n = findNode(key);
743 if (n)
return n->value;
744 else return createNode(key, T())->value;
758 data.rehashToSize(n);
789 Node *n = findNode(key);
797 Node *n = findNode(key);
static const QString & toQString(const QString &s)
static HashedForm< constQV4::String * >::Type hashedString(const QV4::String *s)
static quint32 hashOf(const K &key)
static HashedForm< QV4::String * >::Type hashedString(QV4::String *s)
static QString toQString(const QV4::String *s)
static quint32 hashOf(const QHashedStringRef &s)
static HashedForm< QStringView >::Type hashedString(QStringView s)
static quint32 hashOf(const QV4::String *s)
static quint32 hashOf(QV4::String *s)
static HashedForm< QString >::Type hashedString(const QString &s)
void rehashToBits(short bits)
QStringHashNode ** buckets
void rehashToSize(int size)
~QStringHashData()=default
void rehashNode(QStringHashNode **newBuckets, int nb, QStringHashNode *node)
QStringHashNode(const QHashedString &key)
const char16_t * utf16Data() const
QHashedString key() const
const char * cStrData() const
bool equals(const QV4::String *string) const
QTypedArrayData< char16_t > * arrayData
bool equals(const QV4::Value &string) const
QTaggedPointer< QStringHashNode, Tag > next
QStringHashNode(const QStringHashNode &o)
bool equals(const K &key) const
bool operator!=(const Iterator &o) const
bool operator==(const Iterator &o) const
Value & operator*() const
QHashedString key() const
Node * takeNode(const K &key, const T &value)
void copyAndReserve(const QStringHash< T > &other, int additionalReserve)
void initializeNode(Node *, const QHashedString &key)
void copyNode(const QStringHashNode *otherNode)
QStringHashData::IteratorData< const QStringHash< T > > ConstIteratorData
bool contains(const K &) const
ConstIterator end() const
Iterator< MutableIteratorData, T > MutableIterator
MutableIterator find(const K &)
ReservedNodePool * nodePool
Node * findNode(const K &) const
ConstIterator begin() const
static Data iterateFirst(StringHash *self)
T * value(const QV4::String *string) const
QStringHash & operator=(const QStringHash< T > &)
ConstIterator constEnd() const
void copy(const QStringHash< T > &)
Node * insertNode(Node *, quint32)
ConstIterator constBegin() const
T & operator[](const K &)
void insert(const MutableIterator &)
void insert(const K &, const T &)
T * value(const ConstIterator &) const
Iterator< ConstIteratorData, const T > ConstIterator
T * value(const K &) const
ConstIterator find(const K &) const
void insert(const ConstIterator &)
QStringHashData::IteratorData< QStringHash< T > > MutableIteratorData
Node * createNode(const Node &o)
static Data iterateNext(const Data &)
T * value(const MutableIterator &) const
Node * createNode(const K &, const T &)
Node * takeNode(const Node &o)
QStringHash(const QStringHash &)
IteratorData(const OtherData &other)
IteratorData(QStringHashNode *n=nullptr, StringHash *p=nullptr)
NewedNode(const QHashedString &key, const T &value)
Node(const QHashedString &key, const T &value)