1
/****************************************************************************
3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/
6
** This file is part of the QtQml module of the Qt Toolkit.
8
** $QT_BEGIN_LICENSE:LGPL$
9
** GNU Lesser General Public License Usage
10
** This file may be used under the terms of the GNU Lesser General Public
11
** License version 2.1 as published by the Free Software Foundation and
12
** appearing in the file LICENSE.LGPL included in the packaging of this
13
** file. Please review the following information to ensure the GNU Lesser
14
** General Public License version 2.1 requirements will be met:
15
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17
** In addition, as a special exception, Nokia gives you certain additional
18
** rights. These rights are described in the Nokia Qt LGPL Exception
19
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21
** GNU General Public License Usage
22
** Alternatively, this file may be used under the terms of the GNU General
23
** Public License version 3.0 as published by the Free Software Foundation
24
** and appearing in the file LICENSE.GPL included in the packaging of this
25
** file. Please review the following information to ensure the GNU General
26
** Public License version 3.0 requirements will be met:
27
** http://www.gnu.org/copyleft/gpl.html.
30
** Alternatively, this file may be used in accordance with the terms and
31
** conditions contained in a signed written agreement between you and Nokia.
40
****************************************************************************/
42
#ifndef QHASHEDSTRING_P_H
43
#define QHASHEDSTRING_P_H
49
// This file is not part of the Qt API. It exists purely as an
50
// implementation detail. This header file may change from version to
51
// version without notice, or even be removed.
56
#include <QtCore/qglobal.h>
57
#include <QtCore/qstring.h>
58
#include <private/qv8_p.h>
60
#include <private/qflagpointer_p.h>
68
// Enable this to debug hash linking assumptions.
69
// #define QSTRINGHASH_LINK_DEBUG
71
class QHashedStringRef;
72
class Q_AUTOTEST_EXPORT QHashedString : public QString
75
inline QHashedString();
76
inline QHashedString(const QString &string);
77
inline QHashedString(const QString &string, quint32);
78
inline QHashedString(const QHashedString &string);
80
inline QHashedString &operator=(const QHashedString &string);
81
inline bool operator==(const QHashedString &string) const;
82
inline bool operator==(const QHashedStringRef &string) const;
84
inline quint32 hash() const;
85
inline quint32 existingHash() const;
87
static inline bool isUpper(const QChar &);
89
static bool compare(const QChar *lhs, const QChar *rhs, int length);
90
static inline bool compare(const QChar *lhs, const char *rhs, int length);
91
static inline bool compare(const char *lhs, const char *rhs, int length);
93
friend class QHashedStringRef;
94
friend class QStringHashNode;
96
void computeHash() const;
97
mutable quint32 m_hash;
100
class Q_AUTOTEST_EXPORT QHashedV8String
103
inline QHashedV8String();
104
explicit inline QHashedV8String(v8::Handle<v8::String>);
105
inline QHashedV8String(const QHashedV8String &string);
106
inline QHashedV8String &operator=(const QHashedV8String &other);
108
inline bool operator==(const QHashedV8String &string);
110
inline quint32 hash() const;
111
inline int length() const;
112
inline quint32 symbolId() const;
114
inline v8::Handle<v8::String> string() const;
116
inline QString toString() const;
119
v8::String::CompleteHashData m_hash;
120
v8::Handle<v8::String> m_string;
123
class QHashedCStringRef;
124
class Q_AUTOTEST_EXPORT QHashedStringRef
127
inline QHashedStringRef();
128
inline QHashedStringRef(const QString &);
129
inline QHashedStringRef(const QStringRef &);
130
inline QHashedStringRef(const QChar *, int);
131
inline QHashedStringRef(const QChar *, int, quint32);
132
inline QHashedStringRef(const QHashedString &);
133
inline QHashedStringRef(const QHashedStringRef &);
134
inline QHashedStringRef &operator=(const QHashedStringRef &);
136
inline bool operator==(const QString &string) const;
137
inline bool operator==(const QHashedString &string) const;
138
inline bool operator==(const QHashedStringRef &string) const;
139
inline bool operator==(const QHashedCStringRef &string) const;
140
inline bool operator!=(const QString &string) const;
141
inline bool operator!=(const QHashedString &string) const;
142
inline bool operator!=(const QHashedStringRef &string) const;
143
inline bool operator!=(const QHashedCStringRef &string) const;
145
inline quint32 hash() const;
147
inline const QChar &at(int) const;
148
inline const QChar *constData() const;
149
bool startsWith(const QString &) const;
150
bool endsWith(const QString &) const;
151
QHashedStringRef mid(int, int) const;
153
inline bool isEmpty() const;
154
inline int length() const;
155
inline bool startsWithUpper() const;
157
QString toString() const;
159
inline int utf8length() const;
160
QByteArray toUtf8() const;
161
void writeUtf8(char *) const;
163
friend class QHashedString;
165
void computeHash() const;
166
void computeUtf8Length() const;
170
mutable int m_utf8length;
171
mutable quint32 m_hash;
174
class Q_AUTOTEST_EXPORT QHashedCStringRef
177
inline QHashedCStringRef();
178
inline QHashedCStringRef(const char *, int);
179
inline QHashedCStringRef(const char *, int, quint32);
180
inline QHashedCStringRef(const QHashedCStringRef &);
182
inline quint32 hash() const;
184
inline const char *constData() const;
185
inline int length() const;
187
QString toUtf16() const;
188
inline int utf16length() const;
189
inline void writeUtf16(QChar *) const;
190
inline void writeUtf16(uint16_t *) const;
192
friend class QHashedStringRef;
194
void computeHash() const;
198
mutable quint32 m_hash;
201
class QStringHashData;
202
class Q_AUTOTEST_EXPORT QStringHashNode
206
: length(0), hash(0), symbolId(0), ckey(0)
210
QStringHashNode(const QHashedString &key)
211
: length(key.length()), hash(key.hash()), symbolId(0)
213
strData = const_cast<QHashedString &>(key).data_ptr();
218
QStringHashNode(const QHashedCStringRef &key)
219
: length(key.length()), hash(key.hash()), symbolId(0), ckey(key.constData())
223
QStringHashNode(const QStringHashNode &o)
224
: length(o.length), hash(o.hash), symbolId(o.symbolId), ckey(o.ckey)
226
setQString(o.isQString());
227
if (isQString()) { strData->ref.ref(); }
232
if (isQString()) { if (!strData->ref.deref()) free(strData); }
235
QFlagPointer<QStringHashNode> next;
243
QStringData *strData;
246
bool isQString() const { return next.flag(); }
247
void setQString(bool v) { if (v) next.setFlag(); else next.clearFlag(); }
249
inline char *cStrData() const { return (char *)ckey; }
250
inline uint16_t *utf16Data() const { return (uint16_t *)strData->data(); }
252
inline bool equals(v8::Handle<v8::String> string) {
253
return isQString()?string->Equals(utf16Data(), length):
254
string->Equals(cStrData(), length);
257
inline bool symbolEquals(const QHashedV8String &string) {
258
Q_ASSERT(string.symbolId() != 0);
259
return length == string.length() && hash == string.hash() &&
260
(string.symbolId() == symbolId || equals(string.string()));
263
inline bool equals(const QHashedV8String &string) {
264
return length == string.length() && hash == string.hash() &&
265
equals(string.string());
268
inline bool equals(const QHashedStringRef &string) {
269
return length == string.length() &&
270
hash == string.hash() &&
271
(isQString()?QHashedString::compare(string.constData(), (QChar *)utf16Data(), length):
272
QHashedString::compare(string.constData(), cStrData(), length));
275
inline bool equals(const QHashedCStringRef &string) {
276
return length == string.length() &&
277
hash == string.hash() &&
278
(isQString()?QHashedString::compare((QChar *)utf16Data(), string.constData(), length):
279
QHashedString::compare(string.constData(), cStrData(), length));
283
class Q_AUTOTEST_EXPORT QStringHashData
287
: buckets(0), numBuckets(0), size(0), numBits(0)
288
#ifdef QSTRINGHASH_LINK_DEBUG
293
QStringHashNode **buckets;
297
#ifdef QSTRINGHASH_LINK_DEBUG
301
struct IteratorData {
302
IteratorData() : n(0), p(0) {}
306
void rehashToBits(short, IteratorData, IteratorData (*Iterate)(const IteratorData &),
307
QStringHashNode *skip = 0);
308
void rehashToSize(int, IteratorData, IteratorData (*Iterate)(const IteratorData &),
309
QStringHashNode *skip = 0);
312
QStringHashData(const QStringHashData &);
313
QStringHashData &operator=(const QStringHashData &);
320
struct Node : public QStringHashNode {
321
Node(const QHashedString &key, const T &value) : QStringHashNode(key), value(value) {}
322
Node(const QHashedCStringRef &key, const T &value) : QStringHashNode(key), value(value) {}
323
Node(const Node &o) : QStringHashNode(o), value(o.value) {}
327
struct NewedNode : public Node {
328
NewedNode(const QHashedString &key, const T &value) : Node(key, value), nextNewed(0) {}
329
NewedNode(const QHashedCStringRef &key, const T &value) : Node(key, value), nextNewed(0) {}
330
NewedNode(const Node &o) : Node(o), nextNewed(0) {}
331
NewedNode *nextNewed;
333
struct ReservedNodePool
335
ReservedNodePool() : count(0), used(0), nodes(0) {}
336
~ReservedNodePool() { delete [] nodes; }
342
QStringHashData data;
343
NewedNode *newedNodes;
344
ReservedNodePool *nodePool;
345
const QStringHash<T> *link;
347
inline Node *findNode(const QString &) const;
348
inline Node *findNode(const QHashedString &) const;
349
inline Node *findNode(const QHashedStringRef &) const;
350
inline Node *findNode(const QHashedCStringRef &) const;
351
inline Node *findNode(const QHashedV8String &) const;
352
inline Node *findSymbolNode(const QHashedV8String &) const;
353
inline Node *createNode(const Node &o);
354
inline Node *createNode(const QHashedString &, const T &);
355
inline Node *createNode(const QHashedCStringRef &, const T &);
357
inline Node *takeNode(const QHashedString &key, const T &value);
358
inline Node *takeNode(const QHashedCStringRef &key, const T &value);
359
inline Node *takeNode(const Node &o);
361
inline void copy(const QStringHash<T> &);
363
inline QStringHashData::IteratorData iterateFirst() const;
364
static inline QStringHashData::IteratorData iterateNext(const QStringHashData::IteratorData &);
367
inline QStringHash();
368
inline QStringHash(const QStringHash &);
369
inline ~QStringHash();
371
QStringHash &operator=(const QStringHash<T> &);
373
void copyAndReserve(const QStringHash<T> &other, int additionalReserve);
374
void linkAndReserve(const QStringHash<T> &other, int additionalReserve);
376
inline bool isEmpty() const;
378
inline int count() const;
380
inline int numBuckets() const;
381
inline bool isLinked() const;
383
class ConstIterator {
385
inline ConstIterator();
386
inline ConstIterator(const QStringHashData::IteratorData &);
388
inline ConstIterator &operator++();
390
inline bool operator==(const ConstIterator &o) const;
391
inline bool operator!=(const ConstIterator &o) const;
393
inline QHashedString key() const;
394
inline const T &value() const;
395
inline const T &operator*() const;
397
inline Node *node() const;
399
QStringHashData::IteratorData d;
402
inline void insert(const QString &, const T &);
403
inline void insert(const QHashedString &, const T &);
404
inline void insert(const QHashedStringRef &, const T &);
405
inline void insert(const QHashedCStringRef &, const T &);
406
inline void insert(const ConstIterator &);
408
inline T *value(const QString &) const;
409
inline T *value(const QHashedString &) const;
410
inline T *value(const QHashedStringRef &) const;
411
inline T *value(const QHashedV8String &) const;
412
inline T *value(const QHashedCStringRef &) const;
413
inline T *value(const ConstIterator &) const;
415
inline bool contains(const QString &) const;
416
inline bool contains(const QHashedString &) const;
417
inline bool contains(const QHashedStringRef &) const;
418
inline bool contains(const QHashedCStringRef &) const;
419
inline bool contains(const ConstIterator &) const;
421
inline T &operator[](const QString &);
422
inline T &operator[](const QHashedString &);
423
inline T &operator[](const QHashedStringRef &);
424
inline T &operator[](const QHashedCStringRef &);
426
inline ConstIterator begin() const;
427
inline ConstIterator end() const;
429
inline void reserve(int);
433
QStringHash<T>::QStringHash()
434
: newedNodes(0), nodePool(0), link(0)
439
QStringHash<T>::QStringHash(const QStringHash<T> &other)
440
: newedNodes(0), nodePool(0), link(0)
442
data.numBits = other.data.numBits;
443
data.size = other.data.size;
444
reserve(other.count());
449
QStringHash<T> &QStringHash<T>::operator=(const QStringHash<T> &other)
456
data.numBits = other.data.numBits;
457
data.size = other.data.size;
458
reserve(other.count());
465
void QStringHash<T>::copyAndReserve(const QStringHash<T> &other, int additionalReserve)
468
data.numBits = other.data.numBits;
469
reserve(other.count() + additionalReserve);
474
void QStringHash<T>::linkAndReserve(const QStringHash<T> &other, int additionalReserve)
479
data.size = other.data.size;
480
data.rehashToSize(other.count() + additionalReserve, iterateFirst(), iterateNext);
482
if (data.numBuckets == other.data.numBuckets) {
483
nodePool = new ReservedNodePool;
484
nodePool->count = additionalReserve;
486
nodePool->nodes = new Node[additionalReserve];
488
#ifdef QSTRINGHASH_LINK_DEBUG
490
const_cast<QStringHash<T>&>(other).data.linkCount++;
493
for (int ii = 0; ii < data.numBuckets; ++ii) {
494
data.buckets[ii] = 0;
495
Node *n = (Node *)other.data.buckets[ii];
496
data.buckets[ii] = n;
506
data.numBits = other.data.numBits;
507
reserve(other.count() + additionalReserve);
512
QStringHash<T>::~QStringHash()
518
void QStringHash<T>::clear()
520
#ifdef QSTRINGHASH_LINK_DEBUG
523
const_cast<QStringHash<T> *>(link)->data.linkCount--;
527
qFatal("QStringHash: Illegal attempt to clear a linked hash.");
530
// Delete the individually allocated nodes
531
NewedNode *n = newedNodes;
537
// Delete the pool allocated nodes
538
if (nodePool) delete nodePool;
539
delete [] data.buckets;
552
bool QStringHash<T>::isEmpty() const
554
return data.size== 0;
558
int QStringHash<T>::count() const
564
int QStringHash<T>::numBuckets() const
566
return data.numBuckets;
570
bool QStringHash<T>::isLinked() const
576
typename QStringHash<T>::Node *QStringHash<T>::takeNode(const QHashedString &key, const T &value)
578
if (nodePool && nodePool->used != nodePool->count) {
579
Node *rv = nodePool->nodes + nodePool->used++;
580
rv->length = key.length();
581
rv->hash = key.hash();
582
rv->strData = const_cast<QHashedString &>(key).data_ptr();
583
rv->strData->ref.ref();
584
rv->setQString(true);
588
NewedNode *rv = new NewedNode(key, value);
589
rv->nextNewed = newedNodes;
596
typename QStringHash<T>::Node *QStringHash<T>::takeNode(const QHashedCStringRef &key, const T &value)
598
if (nodePool && nodePool->used != nodePool->count) {
599
Node *rv = nodePool->nodes + nodePool->used++;
600
rv->length = key.length();
601
rv->hash = key.hash();
602
rv->ckey = key.constData();
606
NewedNode *rv = new NewedNode(key, value);
607
rv->nextNewed = newedNodes;
614
typename QStringHash<T>::Node *QStringHash<T>::takeNode(const Node &o)
616
if (nodePool && nodePool->used != nodePool->count) {
617
Node *rv = nodePool->nodes + nodePool->used++;
618
rv->length = o.length;
621
rv->strData = o.strData;
622
rv->strData->ref.ref();
623
rv->setQString(true);
627
rv->symbolId = o.symbolId;
631
NewedNode *rv = new NewedNode(o);
632
rv->nextNewed = newedNodes;
639
void QStringHash<T>::copy(const QStringHash<T> &other)
641
Q_ASSERT(data.size == 0);
643
data.size = other.data.size;
645
// Ensure buckets array is created
646
data.rehashToBits(data.numBits, iterateFirst(), iterateNext);
649
for (ConstIterator iter = other.begin(); iter != other.end(); ++iter) {
650
Node *o = iter.node();
651
Node *n = o->isQString()?findNode(QHashedStringRef((QChar *)o->strData->data(), o->length, o->hash)):
652
findNode(QHashedCStringRef(o->ckey, o->length, o->hash));
654
Node *mynode = takeNode(*o);
655
int bucket = mynode->hash % data.numBuckets;
656
mynode->next = data.buckets[bucket];
657
data.buckets[bucket] = mynode;
661
for (ConstIterator iter = other.begin(); iter != other.end(); ++iter) {
662
Node *o = iter.node();
663
Node *mynode = takeNode(*o);
664
int bucket = mynode->hash % data.numBuckets;
665
mynode->next = data.buckets[bucket];
666
data.buckets[bucket] = mynode;
672
QStringHashData::IteratorData
673
QStringHash<T>::iterateNext(const QStringHashData::IteratorData &d)
675
QStringHash<T> *This = (QStringHash<T> *)d.p;
676
Node *node = (Node *)d.n;
678
if (This->nodePool && node >= This->nodePool->nodes &&
679
node < (This->nodePool->nodes + This->nodePool->used)) {
681
if (node < This->nodePool->nodes)
684
NewedNode *nn = (NewedNode *)node;
685
node = nn->nextNewed;
687
if (node == 0 && This->nodePool && This->nodePool->used)
688
node = This->nodePool->nodes + This->nodePool->used - 1;
691
if (node == 0 && This->link)
692
return This->link->iterateFirst();
694
QStringHashData::IteratorData rv;
701
QStringHashData::IteratorData QStringHash<T>::iterateFirst() const
706
else if (nodePool && nodePool->used)
707
n = nodePool->nodes + nodePool->used - 1;
710
return link->iterateFirst();
712
QStringHashData::IteratorData rv;
714
rv.p = const_cast<QStringHash<T> *>(this);
719
typename QStringHash<T>::Node *QStringHash<T>::createNode(const Node &o)
721
Node *n = takeNode(o);
723
if (data.size >= data.numBuckets)
724
data.rehashToBits(data.numBits + 1, iterateFirst(), iterateNext, n);
726
int bucket = n->hash % data.numBuckets;
727
n->next = data.buckets[bucket];
728
data.buckets[bucket] = n;
736
typename QStringHash<T>::Node *QStringHash<T>::createNode(const QHashedString &key, const T &value)
738
Node *n = takeNode(key, value);
740
if (data.size >= data.numBuckets)
741
data.rehashToBits(data.numBits + 1, iterateFirst(), iterateNext, n);
743
int bucket = key.hash() % data.numBuckets;
744
n->next = data.buckets[bucket];
745
data.buckets[bucket] = n;
753
typename QStringHash<T>::Node *QStringHash<T>::createNode(const QHashedCStringRef &key, const T &value)
755
Node *n = takeNode(key, value);
757
if (data.size >= data.numBuckets)
758
data.rehashToBits(data.numBits + 1, iterateFirst(), iterateNext, n);
760
int bucket = key.hash() % data.numBuckets;
761
n->next = data.buckets[bucket];
762
data.buckets[bucket] = n;
770
void QStringHash<T>::insert(const QString &key, const T &value)
772
QHashedStringRef ch(key);
773
// If this is a linked hash, we can't rely on owning the node, so we always
775
Node *n = link?0:findNode(key);
776
if (n) n->value = value;
777
else createNode(QHashedString(key, ch.hash()), value);
781
void QStringHash<T>::insert(const QHashedString &key, const T &value)
783
// If this is a linked hash, we can't rely on owning the node, so we always
785
Node *n = link?0:findNode(key);
786
if (n) n->value = value;
787
else createNode(key, value);
791
void QStringHash<T>::insert(const QHashedStringRef &key, const T &value)
793
// If this is a linked hash, we can't rely on owning the node, so we always
795
Node *n = link?0:findNode(key);
796
if (n) n->value = value;
797
else createNode(key, value);
801
void QStringHash<T>::insert(const QHashedCStringRef &key, const T &value)
803
// If this is a linked hash, we can't rely on owning the node, so we always
805
Node *n = link?0:findNode(key);
806
if (n) n->value = value;
807
else createNode(key, value);
811
void QStringHash<T>::insert(const ConstIterator &key)
813
// If this is a linked hash, we can't rely on owning the node, so we always
815
if (key.node()->isQString()) {
816
QHashedStringRef str((QChar *)key.node()->strData->data(), key.node()->length,
819
Node *n = link?0:findNode(str);
820
if (n) n->value = key.node()->value;
821
else createNode(*key.node());
823
QHashedCStringRef str(key.node()->ckey, key.node()->length, key.node()->hash);
825
Node *n = link?0:findNode(str);
826
if (n) n->value = key.node()->value;
827
else createNode(str, key.node()->value);
832
typename QStringHash<T>::Node *QStringHash<T>::findNode(const QString &string) const
834
return findNode(QHashedStringRef(string));
838
typename QStringHash<T>::Node *QStringHash<T>::findNode(const QHashedString &string) const
840
return findNode(QHashedStringRef(string.constData(), string.length(), string.hash()));
844
typename QStringHash<T>::Node *QStringHash<T>::findNode(const QHashedStringRef &string) const
846
QStringHashNode *node = data.numBuckets?data.buckets[string.hash() % data.numBuckets]:0;
847
while (node && !node->equals(string))
848
node = (*node->next);
854
typename QStringHash<T>::Node *QStringHash<T>::findNode(const QHashedCStringRef &string) const
856
QStringHashNode *node = data.numBuckets?data.buckets[string.hash() % data.numBuckets]:0;
857
while (node && !node->equals(string))
858
node = (*node->next);
864
typename QStringHash<T>::Node *QStringHash<T>::findNode(const QHashedV8String &string) const
866
QStringHashNode *node = data.numBuckets?data.buckets[string.hash() % data.numBuckets]:0;
867
while (node && !node->equals(string))
868
node = (*node->next);
874
typename QStringHash<T>::Node *QStringHash<T>::findSymbolNode(const QHashedV8String &string) const
876
Q_ASSERT(string.symbolId() != 0);
878
QStringHashNode *node = data.numBuckets?data.buckets[string.hash() % data.numBuckets]:0;
879
while (node && !node->symbolEquals(string))
880
node = (*node->next);
883
node->symbolId = string.symbolId();
889
T *QStringHash<T>::value(const QString &key) const
891
Node *n = findNode(key);
892
return n?&n->value:0;
896
T *QStringHash<T>::value(const QHashedString &key) const
898
Node *n = findNode(key);
899
return n?&n->value:0;
903
T *QStringHash<T>::value(const QHashedStringRef &key) const
905
Node *n = findNode(key);
906
return n?&n->value:0;
910
T *QStringHash<T>::value(const QHashedCStringRef &key) const
912
Node *n = findNode(key);
913
return n?&n->value:0;
917
T *QStringHash<T>::value(const ConstIterator &iter) const
919
Node *n = iter.node();
921
return value(QHashedStringRef((QChar *)n->strData->data(), n->length, n->hash));
923
return value(QHashedCStringRef(n->ckey, n->length, n->hash));
927
T *QStringHash<T>::value(const QHashedV8String &string) const
929
Node *n = string.symbolId()?findSymbolNode(string):findNode(string);
930
return n?&n->value:0;
934
bool QStringHash<T>::contains(const QString &s) const
936
return 0 != value(s);
940
bool QStringHash<T>::contains(const QHashedString &s) const
942
return 0 != value(s);
946
bool QStringHash<T>::contains(const QHashedStringRef &s) const
948
return 0 != value(s);
952
bool QStringHash<T>::contains(const QHashedCStringRef &s) const
954
return 0 != value(s);
958
bool QStringHash<T>::contains(const ConstIterator &s) const
960
return 0 != value(s);
964
T &QStringHash<T>::operator[](const QString &key)
966
QHashedStringRef cs(key);
967
Node *n = findNode(cs);
968
if (n) return n->value;
969
else return createNode(QHashedString(key, cs.hash()), T())->value;
973
T &QStringHash<T>::operator[](const QHashedString &key)
975
Node *n = findNode(key);
976
if (n) return n->value;
977
else return createNode(key, T())->value;
981
T &QStringHash<T>::operator[](const QHashedStringRef &key)
983
Node *n = findNode(key);
984
if (n) return n->value;
985
else return createNode(key, T())->value;
989
T &QStringHash<T>::operator[](const QHashedCStringRef &key)
991
Node *n = findNode(key);
992
if (n) return n->value;
993
else return createNode(key, T())->value;
997
void QStringHash<T>::reserve(int n)
999
if (nodePool || 0 == n)
1002
nodePool = new ReservedNodePool;
1003
nodePool->count = n;
1005
nodePool->nodes = new Node[n];
1007
data.rehashToSize(n, iterateFirst(), iterateNext);
1011
QStringHash<T>::ConstIterator::ConstIterator()
1016
QStringHash<T>::ConstIterator::ConstIterator(const QStringHashData::IteratorData &d)
1022
typename QStringHash<T>::ConstIterator &QStringHash<T>::ConstIterator::operator++()
1024
d = QStringHash<T>::iterateNext(d);
1029
bool QStringHash<T>::ConstIterator::operator==(const ConstIterator &o) const
1031
return d.n == o.d.n;
1035
bool QStringHash<T>::ConstIterator::operator!=(const ConstIterator &o) const
1037
return d.n != o.d.n;
1041
QHashedString QStringHash<T>::ConstIterator::key() const
1043
Node *n = (Node *)d.n;
1044
if (n->isQString()) {
1045
return QHashedString(QString((QChar *)n->strData->data(), n->length), n->hash);
1047
return QHashedString(QString::fromLatin1(n->ckey, n->length), n->hash);
1051
const T &QStringHash<T>::ConstIterator::value() const
1053
Node *n = (Node *)d.n;
1058
const T &QStringHash<T>::ConstIterator::operator*() const
1060
Node *n = (Node *)d.n;
1065
typename QStringHash<T>::Node *QStringHash<T>::ConstIterator::node() const
1067
Node *n = (Node *)d.n;
1072
typename QStringHash<T>::ConstIterator QStringHash<T>::begin() const
1074
return ConstIterator(iterateFirst());
1078
typename QStringHash<T>::ConstIterator QStringHash<T>::end() const
1080
return ConstIterator();
1083
inline uint qHash(const QHashedString &string)
1085
return uint(string.hash());
1088
inline uint qHash(const QHashedStringRef &string)
1090
return uint(string.hash());
1093
QHashedString::QHashedString()
1094
: QString(), m_hash(0)
1098
QHashedString::QHashedString(const QString &string)
1099
: QString(string), m_hash(0)
1103
QHashedString::QHashedString(const QString &string, quint32 hash)
1104
: QString(string), m_hash(hash)
1108
QHashedString::QHashedString(const QHashedString &string)
1109
: QString(string), m_hash(string.m_hash)
1113
QHashedString &QHashedString::operator=(const QHashedString &string)
1115
static_cast<QString &>(*this) = string;
1116
m_hash = string.m_hash;
1120
bool QHashedString::operator==(const QHashedString &string) const
1122
return (string.m_hash == m_hash || !string.m_hash || !m_hash) &&
1123
static_cast<const QString &>(*this) == static_cast<const QString &>(string);
1126
bool QHashedString::operator==(const QHashedStringRef &string) const
1128
return length() == string.m_length &&
1129
(string.m_hash == m_hash || !string.m_hash || !m_hash) &&
1130
QHashedString::compare(constData(), string.m_data, string.m_length);
1133
quint32 QHashedString::hash() const
1135
if (!m_hash) computeHash();
1139
quint32 QHashedString::existingHash() const
1144
bool QHashedString::isUpper(const QChar &qc)
1146
ushort c = qc.unicode();
1147
// Optimize for _, a-z and A-Z.
1148
return ((c != '_' ) && (!(c >= 'a' && c <= 'z')) &&
1149
((c >= 'A' && c <= 'Z') || QChar::category(c) == QChar::Letter_Uppercase));
1152
QHashedV8String::QHashedV8String()
1156
QHashedV8String::QHashedV8String(v8::Handle<v8::String> string)
1157
: m_hash(string->CompleteHash()), m_string(string)
1159
Q_ASSERT(!m_string.IsEmpty());
1162
QHashedV8String::QHashedV8String(const QHashedV8String &string)
1163
: m_hash(string.m_hash), m_string(string.m_string)
1167
QHashedV8String &QHashedV8String::operator=(const QHashedV8String &other)
1169
m_hash = other.m_hash;
1170
m_string = other.m_string;
1174
bool QHashedV8String::operator==(const QHashedV8String &string)
1176
return m_hash.hash == string.m_hash.hash && m_hash.length == string.m_hash.length &&
1177
m_string.IsEmpty() == m_string.IsEmpty() &&
1178
(m_string.IsEmpty() || m_string->StrictEquals(string.m_string));
1181
quint32 QHashedV8String::hash() const
1186
int QHashedV8String::length() const
1188
return m_hash.length;
1191
quint32 QHashedV8String::symbolId() const
1193
return m_hash.symbol_id;
1196
v8::Handle<v8::String> QHashedV8String::string() const
1201
QString QHashedV8String::toString() const
1204
result.reserve(m_hash.length);
1206
for (int i = 0; i < m_hash.length; ++i)
1207
result.append(m_string->GetCharacter(i));
1212
QHashedStringRef::QHashedStringRef()
1213
: m_data(0), m_length(0), m_utf8length(-1), m_hash(0)
1217
QHashedStringRef::QHashedStringRef(const QString &str)
1218
: m_data(str.constData()), m_length(str.length()), m_utf8length(0), m_hash(0)
1222
QHashedStringRef::QHashedStringRef(const QStringRef &str)
1223
: m_data(str.constData()), m_length(str.length()), m_utf8length(0), m_hash(0)
1227
QHashedStringRef::QHashedStringRef(const QChar *data, int length)
1228
: m_data(data), m_length(length), m_utf8length(0), m_hash(0)
1232
QHashedStringRef::QHashedStringRef(const QChar *data, int length, quint32 hash)
1233
: m_data(data), m_length(length), m_utf8length(0), m_hash(hash)
1237
QHashedStringRef::QHashedStringRef(const QHashedString &string)
1238
: m_data(string.constData()), m_length(string.length()), m_utf8length(0), m_hash(string.m_hash)
1242
QHashedStringRef::QHashedStringRef(const QHashedStringRef &string)
1243
: m_data(string.m_data), m_length(string.m_length), m_utf8length(string.m_utf8length),
1244
m_hash(string.m_hash)
1248
QHashedStringRef &QHashedStringRef::operator=(const QHashedStringRef &o)
1251
m_length = o.m_length;
1252
m_utf8length = o.m_utf8length;
1257
bool QHashedStringRef::operator==(const QString &string) const
1259
return m_length == string.length() &&
1260
QHashedString::compare(string.constData(), m_data, m_length);
1263
bool QHashedStringRef::operator==(const QHashedString &string) const
1265
return m_length == string.length() &&
1266
(m_hash == string.m_hash || !m_hash || !string.m_hash) &&
1267
QHashedString::compare(string.constData(), m_data, m_length);
1270
bool QHashedStringRef::operator==(const QHashedStringRef &string) const
1272
return m_length == string.m_length &&
1273
(m_hash == string.m_hash || !m_hash || !string.m_hash) &&
1274
QHashedString::compare(string.m_data, m_data, m_length);
1277
bool QHashedStringRef::operator==(const QHashedCStringRef &string) const
1279
return m_length == string.m_length &&
1280
(m_hash == string.m_hash || !m_hash || !string.m_hash) &&
1281
QHashedString::compare(m_data, string.m_data, m_length);
1284
bool QHashedStringRef::operator!=(const QString &string) const
1286
return m_length != string.length() ||
1287
!QHashedString::compare(string.constData(), m_data, m_length);
1290
bool QHashedStringRef::operator!=(const QHashedString &string) const
1292
return m_length != string.length() ||
1293
(m_hash != string.m_hash && m_hash && string.m_hash) ||
1294
!QHashedString::compare(string.constData(), m_data, m_length);
1297
bool QHashedStringRef::operator!=(const QHashedStringRef &string) const
1299
return m_length != string.m_length ||
1300
(m_hash != string.m_hash && m_hash && string.m_hash) ||
1301
QHashedString::compare(string.m_data, m_data, m_length);
1304
bool QHashedStringRef::operator!=(const QHashedCStringRef &string) const
1306
return m_length != string.m_length ||
1307
(m_hash != string.m_hash && m_hash && string.m_hash) ||
1308
QHashedString::compare(m_data, string.m_data, m_length);
1311
const QChar &QHashedStringRef::at(int index) const
1313
Q_ASSERT(index < m_length);
1314
return m_data[index];
1317
const QChar *QHashedStringRef::constData() const
1322
bool QHashedStringRef::isEmpty() const
1324
return m_length == 0;
1327
int QHashedStringRef::length() const
1332
int QHashedStringRef::utf8length() const
1334
if (m_utf8length < m_length)
1335
computeUtf8Length();
1336
return m_utf8length;
1339
bool QHashedStringRef::startsWithUpper() const
1341
if (m_length < 1) return false;
1342
return QHashedString::isUpper(m_data[0]);
1345
quint32 QHashedStringRef::hash() const
1347
if (!m_hash) computeHash();
1351
QHashedCStringRef::QHashedCStringRef()
1352
: m_data(0), m_length(0), m_hash(0)
1356
QHashedCStringRef::QHashedCStringRef(const char *data, int length)
1357
: m_data(data), m_length(length), m_hash(0)
1361
QHashedCStringRef::QHashedCStringRef(const char *data, int length, quint32 hash)
1362
: m_data(data), m_length(length), m_hash(hash)
1366
QHashedCStringRef::QHashedCStringRef(const QHashedCStringRef &o)
1367
: m_data(o.m_data), m_length(o.m_length), m_hash(o.m_hash)
1371
quint32 QHashedCStringRef::hash() const
1373
if (!m_hash) computeHash();
1377
const char *QHashedCStringRef::constData() const
1382
int QHashedCStringRef::length() const
1387
int QHashedCStringRef::utf16length() const
1392
void QHashedCStringRef::writeUtf16(QChar *output) const
1394
writeUtf16((uint16_t *)output);
1397
void QHashedCStringRef::writeUtf16(uint16_t *output) const
1400
const char *d = m_data;
1405
bool QHashedString::compare(const QChar *lhs, const char *rhs, int length)
1407
Q_ASSERT(lhs && rhs);
1408
const quint16 *l = (const quint16*)lhs;
1410
if (*l++ != *rhs++) return false;
1414
bool QHashedString::compare(const char *lhs, const char *rhs, int length)
1416
Q_ASSERT(lhs && rhs);
1417
return 0 == ::memcmp(lhs, rhs, length);
1422
#endif // QHASHEDSTRING_P_H