19#include <private/qhashedstring_p.h>
20#include <private/qprimefornumbits_p.h>
22#include <QtCore/qbytearray.h>
23#include <QtCore/qstring.h>
24#include <QtCore/qtaggedpointer.h>
28static inline QString::DataPointer &mutableStringData(
const QHashedString &key)
30 return const_cast<QHashedString &>(key).data_ptr();
44 ,
strData(mutableStringData(key).data())
46 Q_ASSERT(key.size() <= std::numeric_limits<
int>::max());
72 if (isQString() && arrayData && !arrayData->deref())
73 QTypedArrayData<
char16_t>::deallocate(arrayData);
89 const char *
ckey =
nullptr;
98 return QHashedString(QString(QStringPrivate(arrayData, strData, length)), hash);
101 return QHashedString(QString::fromLatin1(ckey, length), hash);
104 bool isQString()
const {
return next.tag() == NodeIsQString; }
105 void setQString(
bool v) {
if (v) next.setTag(NodeIsQString);
else next.setTag(NodeIsCString); }
108 inline const char *
cStrData()
const {
return ckey; }
109 inline const char16_t *
utf16Data()
const {
return strData; }
111 inline bool equals(
const QV4::Value &string)
const {
112 QString s = string.toQStringNoThrow();
116 return QLatin1String(
cStrData(), length) == s;
120 inline bool equals(
const QV4::String *string)
const {
121 if (length != string->d()->length() || hash != string->hashValue())
124 return QStringView(
utf16Data(), length) == string->toQString();
126 return QLatin1String(
cStrData(), length) == string->toQString();
130 inline bool equals(
const QHashedStringRef &string)
const {
131 return length == string.length() &&
132 hash == string.hash() &&
133 (isQString()? string == QStringView {utf16Data(), length}:
134 QHashedString::compare(string.constData(), cStrData(), length));
137 inline bool equals(
const QHashedCStringRef &string)
const {
138 return length == string.length() &&
139 hash == string.hash() &&
140 (isQString()?QHashedString::compare((
const QChar *)utf16Data(), string.constData(), length):
141 QHashedString::compare(string.constData(), cStrData(), length));
153
154
155
163 template<
typename StringHash>
167 template<
typename OtherData>
178 int nb = qPrimeForNumBits(
numBits);
183 ::memset(newBuckets, 0,
sizeof(QStringHashNode *) * nb);
201 while (qPrimeForNumBits(bits) < size)
214 int bucket = node->hash % nb;
215 node->next = newBuckets[bucket];
216 newBuckets[bucket] = node;
224template<>
struct HashedForm<QString> {
typedef QHashedString Type; };
225template<>
struct HashedForm<QStringView> {
typedef QHashedStringRef Type; };
226template<>
struct HashedForm<QHashedString> {
typedef const QHashedString &Type; };
227template<>
struct HashedForm<QV4::String *> {
typedef const QV4::String *Type; };
228template<>
struct HashedForm<
const QV4::String *> {
typedef const QV4::String *Type; };
229template<>
struct HashedForm<QHashedStringRef> {
typedef const QHashedStringRef &Type; };
230template<>
struct HashedForm<QLatin1String> {
typedef QHashedCStringRef Type; };
231template<>
struct HashedForm<QHashedCStringRef> {
typedef const QHashedCStringRef &Type; };
239 Q_ASSERT(s.size() <= std::numeric_limits<
int>::max());
240 return QHashedStringRef(s.constData(),
int(s.size()));
249 Q_ASSERT(s.size() <= std::numeric_limits<
int>::max());
250 return QHashedCStringRef(s.data(),
int(s.size()));
262 static inline quint32 hashOf(
const QHashedStringRef &s) {
return s.hash(); }
264 static inline quint32 hashOf(
const QV4::String *s) {
return s->hashValue(); }
267 static inline quint32 hashOf(
const K &key) {
return hashedString(key).hash(); }
328 template<
typename StringHash,
typename Data>
331 template<
typename Data>
349 template<
typename Data,
typename Value>
365 inline bool equals(
const K &key)
const {
return d.n->equals(key); }
368 inline Value &
value()
const {
return static_cast<
Node *>(d.n)->value; }
369 inline Value &
operator*()
const {
return static_cast<
Node *>(d.n)->value; }
380 inline void insert(
const K &,
const T &);
386 inline T *
value(
const QV4::String *string)
const;
423 data.numBits = other.data.numBits;
424 data.size = other.data.size;
437 data.numBits = other.data.numBits;
438 data.size = other.data.size;
449 data.numBits = other.data.numBits;
472 delete [] data.buckets;
474 data.buckets =
nullptr;
486 return data.size== 0;
498 return data.numBuckets;
504 node->length = key.size();
505 node->hash = key.hash();
506 node->arrayData = mutableStringData(key).d_ptr();
507 node->strData = mutableStringData(key).data();
509 node->arrayData->ref();
510 node->setQString(
true);
516 node->length = key.length();
517 node->hash = key.hash();
518 node->ckey = key.constData();
527 initializeNode(rv, hashedString(key));
543 rv->length = o.length;
545 rv->arrayData = o.arrayData;
547 rv->strData = o.strData;
548 rv->setQString(
true);
550 rv->arrayData->ref();
554 rv->symbolId = o.symbolId;
573 Node *mynode = takeNode(*(
const Node *)otherNode);
574 int bucket = mynode->hash % data.numBuckets;
575 mynode->next = data.buckets[bucket];
576 data.buckets[bucket] = mynode;
582 Q_ASSERT(data.size == 0);
584 data.size = other.data.size;
587 data.rehashToBits(data.numBits);
590 for (
int i = 0; i < other.data.numBuckets; ++i) {
598template<
typename Data>
604 if (This->nodePool && node >= This->nodePool->nodes &&
605 node < (This->nodePool->nodes + This->nodePool->used)) {
607 if (node < This->nodePool->nodes)
611 node = nn->nextNewed;
613 if (node ==
nullptr && This->nodePool && This->nodePool->used)
614 node = This->nodePool->nodes + This->nodePool->used - 1;
624template<
typename StringHash,
typename Data>
627 typename StringHash::Node *n =
nullptr;
628 if (self->newedNodes)
629 n = self->newedNodes;
630 else if (self->nodePool && self->nodePool->used)
631 n = self->nodePool->nodes + self->nodePool->used - 1;
642 Node *n = takeNode(o);
643 return insertNode(n, n->hash);
650 Node *n = takeNode(key, value);
651 return insertNode(n, hashOf(key));
657 if (data.size >= data.numBuckets)
658 data.rehashToBits(data.numBits + 1);
660 int bucket = hash % data.numBuckets;
661 n->next = data.buckets[bucket];
662 data.buckets[bucket] = n;
673 Node *n = findNode(key);
677 createNode(key, value);
683 insert(iter.key(), iter.value());
689 insert(iter.key(), iter.value());
696 QStringHashNode *node = data.numBuckets?data.buckets[hashOf(key) % data.numBuckets]:
nullptr;
698 typename HashedForm<K>::Type hashedKey(hashedString(key));
699 while (node && !node->equals(hashedKey))
700 node = node->next.data();
709 Node *n = findNode(key);
710 return n?&n->value:
nullptr;
716 return value(iter.node()->key());
722 return value(iter.node()->key());
728 Node *n = findNode(string);
729 return n?&n->value:
nullptr;
736 return nullptr != value(key);
743 Node *n = findNode(key);
744 if (n)
return n->value;
745 else return createNode(key, T())->value;
759 data.rehashToSize(n);
790 Node *n = findNode(key);
798 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)