~loic.molinari/+junk/qtdeclarative-shadereffectsource-changes

« back to all changes in this revision

Viewing changes to src/qml/qml/ftw/qhashedstring_p.h

  • Committer: Loïc Molinari
  • Date: 2012-04-21 17:59:51 UTC
  • Revision ID: loic.molinari@canonical.com-20120421175951-bqx68caaf5zrp76l
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/
 
5
**
 
6
** This file is part of the QtQml module of the Qt Toolkit.
 
7
**
 
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.
 
16
**
 
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.
 
20
**
 
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.
 
28
**
 
29
** Other Usage
 
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.
 
32
**
 
33
**
 
34
**
 
35
**
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
 
 
42
#ifndef QHASHEDSTRING_P_H
 
43
#define QHASHEDSTRING_P_H
 
44
 
 
45
//
 
46
//  W A R N I N G
 
47
//  -------------
 
48
//
 
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.
 
52
//
 
53
// We mean it.
 
54
//
 
55
 
 
56
#include <QtCore/qglobal.h>
 
57
#include <QtCore/qstring.h>
 
58
#include <private/qv8_p.h>
 
59
 
 
60
#include <private/qflagpointer_p.h>
 
61
 
 
62
#if defined(Q_OS_QNX)
 
63
#include <stdlib.h>
 
64
#endif
 
65
 
 
66
QT_BEGIN_NAMESPACE
 
67
 
 
68
// Enable this to debug hash linking assumptions.
 
69
// #define QSTRINGHASH_LINK_DEBUG
 
70
 
 
71
class QHashedStringRef;
 
72
class Q_AUTOTEST_EXPORT QHashedString : public QString
 
73
{
 
74
public:
 
75
    inline QHashedString();
 
76
    inline QHashedString(const QString &string);
 
77
    inline QHashedString(const QString &string, quint32);
 
78
    inline QHashedString(const QHashedString &string);
 
79
 
 
80
    inline QHashedString &operator=(const QHashedString &string);
 
81
    inline bool operator==(const QHashedString &string) const;
 
82
    inline bool operator==(const QHashedStringRef &string) const;
 
83
 
 
84
    inline quint32 hash() const;
 
85
    inline quint32 existingHash() const;
 
86
 
 
87
    static inline bool isUpper(const QChar &);
 
88
 
 
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);
 
92
private:
 
93
    friend class QHashedStringRef;
 
94
    friend class QStringHashNode;
 
95
 
 
96
    void computeHash() const;
 
97
    mutable quint32 m_hash;
 
98
};
 
99
 
 
100
class Q_AUTOTEST_EXPORT QHashedV8String 
 
101
{
 
102
public:
 
103
    inline QHashedV8String();
 
104
    explicit inline QHashedV8String(v8::Handle<v8::String>);
 
105
    inline QHashedV8String(const QHashedV8String &string);
 
106
    inline QHashedV8String &operator=(const QHashedV8String &other);
 
107
 
 
108
    inline bool operator==(const QHashedV8String &string);
 
109
 
 
110
    inline quint32 hash() const;
 
111
    inline int length() const; 
 
112
    inline quint32 symbolId() const;
 
113
 
 
114
    inline v8::Handle<v8::String> string() const;
 
115
 
 
116
    inline QString toString() const;
 
117
 
 
118
private:
 
119
    v8::String::CompleteHashData m_hash;
 
120
    v8::Handle<v8::String> m_string;
 
121
};
 
122
 
 
123
class QHashedCStringRef;
 
124
class Q_AUTOTEST_EXPORT QHashedStringRef 
 
125
{
 
126
public:
 
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 &);
 
135
 
 
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;
 
144
 
 
145
    inline quint32 hash() const;
 
146
 
 
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;
 
152
 
 
153
    inline bool isEmpty() const;
 
154
    inline int length() const;
 
155
    inline bool startsWithUpper() const;
 
156
 
 
157
    QString toString() const;
 
158
 
 
159
    inline int utf8length() const;
 
160
    QByteArray toUtf8() const;
 
161
    void writeUtf8(char *) const;
 
162
private:
 
163
    friend class QHashedString;
 
164
 
 
165
    void computeHash() const;
 
166
    void computeUtf8Length() const;
 
167
 
 
168
    const QChar *m_data;
 
169
    int m_length;
 
170
    mutable int m_utf8length;
 
171
    mutable quint32 m_hash;
 
172
};
 
173
 
 
174
class Q_AUTOTEST_EXPORT QHashedCStringRef
 
175
{
 
176
public:
 
177
    inline QHashedCStringRef();
 
178
    inline QHashedCStringRef(const char *, int);
 
179
    inline QHashedCStringRef(const char *, int, quint32);
 
180
    inline QHashedCStringRef(const QHashedCStringRef &);
 
181
 
 
182
    inline quint32 hash() const;
 
183
 
 
184
    inline const char *constData() const;
 
185
    inline int length() const;
 
186
 
 
187
    QString toUtf16() const;
 
188
    inline int utf16length() const;
 
189
    inline void writeUtf16(QChar *) const;
 
190
    inline void writeUtf16(uint16_t *) const;
 
191
private:
 
192
    friend class QHashedStringRef;
 
193
 
 
194
    void computeHash() const;
 
195
 
 
196
    const char *m_data;
 
197
    int m_length;
 
198
    mutable quint32 m_hash;
 
199
};
 
200
 
 
201
class QStringHashData;
 
202
class Q_AUTOTEST_EXPORT QStringHashNode
 
203
{
 
204
public:
 
205
    QStringHashNode()
 
206
    : length(0), hash(0), symbolId(0), ckey(0)
 
207
    {
 
208
    }
 
209
 
 
210
    QStringHashNode(const QHashedString &key)
 
211
    : length(key.length()), hash(key.hash()), symbolId(0)
 
212
    {
 
213
        strData = const_cast<QHashedString &>(key).data_ptr();
 
214
        setQString(true);
 
215
        strData->ref.ref();
 
216
    }
 
217
 
 
218
    QStringHashNode(const QHashedCStringRef &key)
 
219
    : length(key.length()), hash(key.hash()), symbolId(0), ckey(key.constData())
 
220
    {
 
221
    }
 
222
 
 
223
    QStringHashNode(const QStringHashNode &o)
 
224
    : length(o.length), hash(o.hash), symbolId(o.symbolId), ckey(o.ckey)
 
225
    {
 
226
        setQString(o.isQString());
 
227
        if (isQString()) { strData->ref.ref(); }
 
228
    }
 
229
 
 
230
    ~QStringHashNode()
 
231
    {
 
232
        if (isQString()) { if (!strData->ref.deref()) free(strData); }
 
233
    }
 
234
 
 
235
    QFlagPointer<QStringHashNode> next;
 
236
 
 
237
    qint32 length;
 
238
    quint32 hash;
 
239
    quint32 symbolId;
 
240
 
 
241
    union {
 
242
        const char *ckey;
 
243
        QStringData *strData;
 
244
    };
 
245
 
 
246
    bool isQString() const { return next.flag(); }
 
247
    void setQString(bool v) { if (v) next.setFlag(); else next.clearFlag(); }
 
248
 
 
249
    inline char *cStrData() const { return (char *)ckey; }
 
250
    inline uint16_t *utf16Data() const { return (uint16_t *)strData->data(); }
 
251
 
 
252
    inline bool equals(v8::Handle<v8::String> string) {
 
253
        return isQString()?string->Equals(utf16Data(), length):
 
254
                           string->Equals(cStrData(), length);
 
255
    }
 
256
 
 
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()));
 
261
    }
 
262
 
 
263
    inline bool equals(const QHashedV8String &string) {
 
264
        return length == string.length() && hash == string.hash() && 
 
265
               equals(string.string());
 
266
    }
 
267
 
 
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));
 
273
    }
 
274
 
 
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));
 
280
    }
 
281
};
 
282
 
 
283
class Q_AUTOTEST_EXPORT QStringHashData
 
284
{
 
285
public:
 
286
    QStringHashData() 
 
287
    : buckets(0), numBuckets(0), size(0), numBits(0)
 
288
#ifdef QSTRINGHASH_LINK_DEBUG
 
289
      , linkCount(0)
 
290
#endif
 
291
    {}
 
292
 
 
293
    QStringHashNode **buckets;
 
294
    int numBuckets;
 
295
    int size;
 
296
    short numBits;
 
297
#ifdef QSTRINGHASH_LINK_DEBUG
 
298
    int linkCount;
 
299
#endif
 
300
 
 
301
    struct IteratorData {
 
302
        IteratorData() : n(0), p(0) {}
 
303
        QStringHashNode *n;
 
304
        void *p;
 
305
    };
 
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);
 
310
 
 
311
private:
 
312
    QStringHashData(const QStringHashData &);
 
313
    QStringHashData &operator=(const QStringHashData &);
 
314
};
 
315
 
 
316
template<class T>
 
317
class QStringHash
 
318
{
 
319
public:
 
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) {}
 
324
        Node() {}
 
325
        T value;
 
326
    };
 
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;
 
332
    };
 
333
    struct ReservedNodePool
 
334
    {
 
335
        ReservedNodePool() : count(0), used(0), nodes(0) {}
 
336
        ~ReservedNodePool() { delete [] nodes; }
 
337
        int count;
 
338
        int used;
 
339
        Node *nodes;
 
340
    };
 
341
 
 
342
    QStringHashData data;
 
343
    NewedNode *newedNodes;
 
344
    ReservedNodePool *nodePool;
 
345
    const QStringHash<T> *link;
 
346
 
 
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 &);
 
356
 
 
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);
 
360
 
 
361
    inline void copy(const QStringHash<T> &);
 
362
 
 
363
    inline QStringHashData::IteratorData iterateFirst() const;
 
364
    static inline QStringHashData::IteratorData iterateNext(const QStringHashData::IteratorData &);
 
365
 
 
366
public:
 
367
    inline QStringHash();
 
368
    inline QStringHash(const QStringHash &);
 
369
    inline ~QStringHash();
 
370
 
 
371
    QStringHash &operator=(const QStringHash<T> &);
 
372
 
 
373
    void copyAndReserve(const QStringHash<T> &other, int additionalReserve);
 
374
    void linkAndReserve(const QStringHash<T> &other, int additionalReserve);
 
375
 
 
376
    inline bool isEmpty() const;
 
377
    inline void clear();
 
378
    inline int count() const;
 
379
 
 
380
    inline int numBuckets() const;
 
381
    inline bool isLinked() const;
 
382
 
 
383
    class ConstIterator {
 
384
    public:
 
385
        inline ConstIterator();
 
386
        inline ConstIterator(const QStringHashData::IteratorData &);
 
387
 
 
388
        inline ConstIterator &operator++();
 
389
 
 
390
        inline bool operator==(const ConstIterator &o) const;
 
391
        inline bool operator!=(const ConstIterator &o) const;
 
392
 
 
393
        inline QHashedString key() const;
 
394
        inline const T &value() const;
 
395
        inline const T &operator*() const;
 
396
 
 
397
        inline Node *node() const;
 
398
    private:
 
399
        QStringHashData::IteratorData d;
 
400
    };
 
401
 
 
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  &);
 
407
 
 
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;
 
414
 
 
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;
 
420
 
 
421
    inline T &operator[](const QString &);
 
422
    inline T &operator[](const QHashedString &);
 
423
    inline T &operator[](const QHashedStringRef &);
 
424
    inline T &operator[](const QHashedCStringRef &);
 
425
 
 
426
    inline ConstIterator begin() const;
 
427
    inline ConstIterator end() const;
 
428
 
 
429
    inline void reserve(int);
 
430
};
 
431
 
 
432
template<class T>
 
433
QStringHash<T>::QStringHash()
 
434
: newedNodes(0), nodePool(0), link(0)
 
435
{
 
436
}
 
437
 
 
438
template<class T>
 
439
QStringHash<T>::QStringHash(const QStringHash<T> &other)
 
440
: newedNodes(0), nodePool(0), link(0)
 
441
{
 
442
    data.numBits = other.data.numBits;
 
443
    data.size = other.data.size;
 
444
    reserve(other.count());
 
445
    copy(other);
 
446
}
 
447
 
 
448
template<class T>
 
449
QStringHash<T> &QStringHash<T>::operator=(const QStringHash<T> &other)
 
450
{
 
451
    if (&other == this)
 
452
        return *this;
 
453
 
 
454
    clear();
 
455
 
 
456
    data.numBits = other.data.numBits;
 
457
    data.size = other.data.size;
 
458
    reserve(other.count());
 
459
    copy(other);
 
460
 
 
461
    return *this;
 
462
}
 
463
 
 
464
template<class T>
 
465
void QStringHash<T>::copyAndReserve(const QStringHash<T> &other, int additionalReserve)
 
466
{
 
467
    clear();
 
468
    data.numBits = other.data.numBits;
 
469
    reserve(other.count() + additionalReserve);
 
470
    copy(other);
 
471
}
 
472
 
 
473
template<class T>
 
474
void QStringHash<T>::linkAndReserve(const QStringHash<T> &other, int additionalReserve)
 
475
{
 
476
    clear();
 
477
 
 
478
    if (other.count()) {
 
479
        data.size = other.data.size;
 
480
        data.rehashToSize(other.count() + additionalReserve, iterateFirst(), iterateNext);
 
481
 
 
482
        if (data.numBuckets == other.data.numBuckets) {
 
483
            nodePool = new ReservedNodePool;
 
484
            nodePool->count = additionalReserve;
 
485
            nodePool->used = 0;
 
486
            nodePool->nodes = new Node[additionalReserve];
 
487
 
 
488
#ifdef QSTRINGHASH_LINK_DEBUG
 
489
            data.linkCount++;
 
490
            const_cast<QStringHash<T>&>(other).data.linkCount++;
 
491
#endif
 
492
 
 
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;
 
497
            }
 
498
 
 
499
            link = &other;
 
500
            return;
 
501
        }
 
502
 
 
503
        data.size = 0;
 
504
    }
 
505
 
 
506
    data.numBits = other.data.numBits;
 
507
    reserve(other.count() + additionalReserve);
 
508
    copy(other);
 
509
}
 
510
 
 
511
template<class T>
 
512
QStringHash<T>::~QStringHash()
 
513
{
 
514
    clear();
 
515
}
 
516
 
 
517
template<class T>
 
518
void QStringHash<T>::clear()
 
519
{
 
520
#ifdef QSTRINGHASH_LINK_DEBUG
 
521
    if (link) {
 
522
        data.linkCount--;
 
523
        const_cast<QStringHash<T> *>(link)->data.linkCount--;
 
524
    }
 
525
 
 
526
    if (data.linkCount)
 
527
        qFatal("QStringHash: Illegal attempt to clear a linked hash.");
 
528
#endif
 
529
 
 
530
    // Delete the individually allocated nodes
 
531
    NewedNode *n = newedNodes;
 
532
    while (n) {
 
533
        NewedNode *c = n;
 
534
        n = c->nextNewed;
 
535
        delete c;
 
536
    }
 
537
    // Delete the pool allocated nodes
 
538
    if (nodePool) delete nodePool; 
 
539
    delete [] data.buckets;
 
540
 
 
541
    data.buckets = 0;
 
542
    data.numBuckets = 0;
 
543
    data.numBits = 0;
 
544
    data.size = 0;
 
545
 
 
546
    newedNodes = 0;
 
547
    nodePool = 0;
 
548
    link = 0;
 
549
}
 
550
 
 
551
template<class T>
 
552
bool QStringHash<T>::isEmpty() const
 
553
{
 
554
    return data.size== 0;
 
555
}
 
556
 
 
557
template<class T>
 
558
int QStringHash<T>::count() const
 
559
{
 
560
    return data.size;
 
561
}
 
562
 
 
563
template<class T>
 
564
int QStringHash<T>::numBuckets() const
 
565
{
 
566
    return data.numBuckets;
 
567
}
 
568
 
 
569
template<class T>
 
570
bool QStringHash<T>::isLinked() const
 
571
{
 
572
    return link != 0;
 
573
}
 
574
 
 
575
template<class T>
 
576
typename QStringHash<T>::Node *QStringHash<T>::takeNode(const QHashedString &key, const T &value)
 
577
{
 
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);
 
585
        rv->value = value;
 
586
        return rv;
 
587
    } else {
 
588
        NewedNode *rv = new NewedNode(key, value);
 
589
        rv->nextNewed = newedNodes;
 
590
        newedNodes = rv;
 
591
        return rv;
 
592
    }
 
593
}
 
594
 
 
595
template<class T>
 
596
typename QStringHash<T>::Node *QStringHash<T>::takeNode(const QHashedCStringRef &key, const T &value)
 
597
{
 
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();
 
603
        rv->value = value;
 
604
        return rv;
 
605
    } else {
 
606
        NewedNode *rv = new NewedNode(key, value);
 
607
        rv->nextNewed = newedNodes;
 
608
        newedNodes = rv;
 
609
        return rv;
 
610
    }
 
611
}
 
612
 
 
613
template<class T>
 
614
typename QStringHash<T>::Node *QStringHash<T>::takeNode(const Node &o)
 
615
{
 
616
    if (nodePool && nodePool->used != nodePool->count) {
 
617
        Node *rv = nodePool->nodes + nodePool->used++;
 
618
        rv->length = o.length;
 
619
        rv->hash = o.hash;
 
620
        if (o.isQString()) {
 
621
            rv->strData = o.strData;
 
622
            rv->strData->ref.ref();
 
623
            rv->setQString(true);
 
624
        } else {
 
625
            rv->ckey = o.ckey;
 
626
        }
 
627
        rv->symbolId = o.symbolId;
 
628
        rv->value = o.value;
 
629
        return rv;
 
630
    } else {
 
631
        NewedNode *rv = new NewedNode(o);
 
632
        rv->nextNewed = newedNodes;
 
633
        newedNodes = rv;
 
634
        return rv;
 
635
    }
 
636
}
 
637
 
 
638
template<class T>
 
639
void QStringHash<T>::copy(const QStringHash<T> &other)
 
640
{
 
641
    Q_ASSERT(data.size == 0);
 
642
 
 
643
    data.size = other.data.size;
 
644
 
 
645
    // Ensure buckets array is created
 
646
    data.rehashToBits(data.numBits, iterateFirst(), iterateNext);
 
647
 
 
648
    if (other.link) {
 
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));
 
653
            if (!n) {
 
654
                Node *mynode = takeNode(*o);
 
655
                int bucket = mynode->hash % data.numBuckets;
 
656
                mynode->next = data.buckets[bucket];
 
657
                data.buckets[bucket] = mynode;
 
658
            }
 
659
        }
 
660
    } else {
 
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;
 
667
        }
 
668
    }
 
669
}
 
670
 
 
671
template<class T>
 
672
QStringHashData::IteratorData
 
673
QStringHash<T>::iterateNext(const QStringHashData::IteratorData &d)
 
674
{
 
675
    QStringHash<T> *This = (QStringHash<T> *)d.p;
 
676
    Node *node = (Node *)d.n;
 
677
 
 
678
    if (This->nodePool && node >= This->nodePool->nodes &&
 
679
        node < (This->nodePool->nodes + This->nodePool->used)) {
 
680
        node--;
 
681
        if (node < This->nodePool->nodes)
 
682
            node = 0;
 
683
    } else {
 
684
        NewedNode *nn = (NewedNode *)node;
 
685
        node = nn->nextNewed;
 
686
 
 
687
        if (node == 0 && This->nodePool && This->nodePool->used)
 
688
            node = This->nodePool->nodes + This->nodePool->used - 1;
 
689
    }
 
690
 
 
691
    if (node == 0 && This->link)
 
692
        return This->link->iterateFirst();
 
693
 
 
694
    QStringHashData::IteratorData rv;
 
695
    rv.n = node;
 
696
    rv.p = d.p;
 
697
    return rv;
 
698
}
 
699
 
 
700
template<class T>
 
701
QStringHashData::IteratorData QStringHash<T>::iterateFirst() const
 
702
{
 
703
    Node *n = 0;
 
704
    if (newedNodes)
 
705
        n = newedNodes;
 
706
    else if (nodePool && nodePool->used)
 
707
        n = nodePool->nodes + nodePool->used - 1;
 
708
 
 
709
    if (n == 0 && link)
 
710
        return link->iterateFirst();
 
711
 
 
712
    QStringHashData::IteratorData rv;
 
713
    rv.n = n;
 
714
    rv.p = const_cast<QStringHash<T> *>(this);
 
715
    return rv;
 
716
}
 
717
 
 
718
template<class T>
 
719
typename QStringHash<T>::Node *QStringHash<T>::createNode(const Node &o)
 
720
{
 
721
    Node *n = takeNode(o);
 
722
 
 
723
    if (data.size >= data.numBuckets)
 
724
        data.rehashToBits(data.numBits + 1, iterateFirst(), iterateNext, n);
 
725
 
 
726
    int bucket = n->hash % data.numBuckets;
 
727
    n->next = data.buckets[bucket];
 
728
    data.buckets[bucket] = n;
 
729
 
 
730
    data.size++;
 
731
 
 
732
    return n;
 
733
}
 
734
 
 
735
template<class T>
 
736
typename QStringHash<T>::Node *QStringHash<T>::createNode(const QHashedString &key, const T &value)
 
737
{
 
738
    Node *n = takeNode(key, value);
 
739
 
 
740
    if (data.size >= data.numBuckets)
 
741
        data.rehashToBits(data.numBits + 1, iterateFirst(), iterateNext, n);
 
742
 
 
743
    int bucket = key.hash() % data.numBuckets;
 
744
    n->next = data.buckets[bucket];
 
745
    data.buckets[bucket] = n;
 
746
 
 
747
    data.size++;
 
748
 
 
749
    return n;
 
750
}
 
751
 
 
752
template<class T>
 
753
typename QStringHash<T>::Node *QStringHash<T>::createNode(const QHashedCStringRef &key, const T &value)
 
754
{
 
755
    Node *n = takeNode(key, value);
 
756
 
 
757
    if (data.size >= data.numBuckets)
 
758
        data.rehashToBits(data.numBits + 1, iterateFirst(), iterateNext, n);
 
759
 
 
760
    int bucket = key.hash() % data.numBuckets;
 
761
    n->next = data.buckets[bucket];
 
762
    data.buckets[bucket] = n;
 
763
 
 
764
    data.size++; 
 
765
 
 
766
    return n;
 
767
}
 
768
 
 
769
template<class T>
 
770
void QStringHash<T>::insert(const QString &key, const T &value)
 
771
{
 
772
    QHashedStringRef ch(key);
 
773
    // If this is a linked hash, we can't rely on owning the node, so we always
 
774
    // create a new one.
 
775
    Node *n = link?0:findNode(key);
 
776
    if (n) n->value = value;
 
777
    else createNode(QHashedString(key, ch.hash()), value);
 
778
}
 
779
 
 
780
template<class T>
 
781
void QStringHash<T>::insert(const QHashedString &key, const T &value)
 
782
{
 
783
    // If this is a linked hash, we can't rely on owning the node, so we always
 
784
    // create a new one.
 
785
    Node *n = link?0:findNode(key);
 
786
    if (n) n->value = value;
 
787
    else createNode(key, value);
 
788
}
 
789
 
 
790
template<class T>
 
791
void QStringHash<T>::insert(const QHashedStringRef &key, const T &value)
 
792
{
 
793
    // If this is a linked hash, we can't rely on owning the node, so we always
 
794
    // create a new one.
 
795
    Node *n = link?0:findNode(key);
 
796
    if (n) n->value = value;
 
797
    else createNode(key, value);
 
798
}
 
799
 
 
800
template<class T>
 
801
void QStringHash<T>::insert(const QHashedCStringRef &key, const T &value)
 
802
{
 
803
    // If this is a linked hash, we can't rely on owning the node, so we always
 
804
    // create a new one.
 
805
    Node *n = link?0:findNode(key);
 
806
    if (n) n->value = value;
 
807
    else createNode(key, value);
 
808
}
 
809
 
 
810
template<class T>
 
811
void QStringHash<T>::insert(const ConstIterator &key)
 
812
{
 
813
    // If this is a linked hash, we can't rely on owning the node, so we always
 
814
    // create a new one.
 
815
    if (key.node()->isQString()) {
 
816
        QHashedStringRef str((QChar *)key.node()->strData->data(), key.node()->length,
 
817
                             key.node()->hash);
 
818
 
 
819
        Node *n = link?0:findNode(str);
 
820
        if (n) n->value = key.node()->value;
 
821
        else createNode(*key.node());
 
822
    } else {
 
823
        QHashedCStringRef str(key.node()->ckey, key.node()->length, key.node()->hash);
 
824
 
 
825
        Node *n = link?0:findNode(str);
 
826
        if (n) n->value = key.node()->value;
 
827
        else createNode(str, key.node()->value);
 
828
    }
 
829
}
 
830
 
 
831
template<class T>
 
832
typename QStringHash<T>::Node *QStringHash<T>::findNode(const QString &string) const
 
833
{
 
834
    return findNode(QHashedStringRef(string));
 
835
}
 
836
 
 
837
template<class T>
 
838
typename QStringHash<T>::Node *QStringHash<T>::findNode(const QHashedString &string) const
 
839
{
 
840
    return findNode(QHashedStringRef(string.constData(), string.length(), string.hash()));
 
841
}
 
842
 
 
843
template<class T>
 
844
typename QStringHash<T>::Node *QStringHash<T>::findNode(const QHashedStringRef &string) const
 
845
{
 
846
    QStringHashNode *node = data.numBuckets?data.buckets[string.hash() % data.numBuckets]:0;
 
847
    while (node && !node->equals(string))
 
848
        node = (*node->next);
 
849
 
 
850
    return (Node *)node;
 
851
}
 
852
 
 
853
template<class T>
 
854
typename QStringHash<T>::Node *QStringHash<T>::findNode(const QHashedCStringRef &string) const
 
855
{
 
856
    QStringHashNode *node = data.numBuckets?data.buckets[string.hash() % data.numBuckets]:0;
 
857
    while (node && !node->equals(string))
 
858
        node = (*node->next);
 
859
 
 
860
    return (Node *)node;
 
861
}
 
862
 
 
863
template<class T>
 
864
typename QStringHash<T>::Node *QStringHash<T>::findNode(const QHashedV8String &string) const
 
865
{
 
866
    QStringHashNode *node = data.numBuckets?data.buckets[string.hash() % data.numBuckets]:0;
 
867
    while (node && !node->equals(string))
 
868
        node = (*node->next);
 
869
 
 
870
    return (Node *)node;
 
871
}
 
872
 
 
873
template<class T>
 
874
typename QStringHash<T>::Node *QStringHash<T>::findSymbolNode(const QHashedV8String &string) const
 
875
{
 
876
    Q_ASSERT(string.symbolId() != 0);
 
877
 
 
878
    QStringHashNode *node = data.numBuckets?data.buckets[string.hash() % data.numBuckets]:0;
 
879
    while (node && !node->symbolEquals(string))
 
880
        node = (*node->next);
 
881
 
 
882
    if (node)
 
883
        node->symbolId = string.symbolId();
 
884
 
 
885
    return (Node *)node;
 
886
}
 
887
 
 
888
template<class T>
 
889
T *QStringHash<T>::value(const QString &key) const
 
890
{
 
891
    Node *n = findNode(key);
 
892
    return n?&n->value:0;
 
893
}
 
894
 
 
895
template<class T>
 
896
T *QStringHash<T>::value(const QHashedString &key) const
 
897
{
 
898
    Node *n = findNode(key);
 
899
    return n?&n->value:0;
 
900
}
 
901
 
 
902
template<class T>
 
903
T *QStringHash<T>::value(const QHashedStringRef &key) const
 
904
{
 
905
    Node *n = findNode(key);
 
906
    return n?&n->value:0;
 
907
}
 
908
 
 
909
template<class T>
 
910
T *QStringHash<T>::value(const QHashedCStringRef &key) const
 
911
{
 
912
    Node *n = findNode(key);
 
913
    return n?&n->value:0;
 
914
}
 
915
 
 
916
template<class T>
 
917
T *QStringHash<T>::value(const ConstIterator &iter) const
 
918
{
 
919
    Node *n = iter.node();
 
920
    if (n->isQString())
 
921
        return value(QHashedStringRef((QChar *)n->strData->data(), n->length, n->hash));
 
922
    else
 
923
        return value(QHashedCStringRef(n->ckey, n->length, n->hash));
 
924
}
 
925
 
 
926
template<class T>
 
927
T *QStringHash<T>::value(const QHashedV8String &string) const
 
928
{
 
929
    Node *n = string.symbolId()?findSymbolNode(string):findNode(string);
 
930
    return n?&n->value:0;
 
931
}
 
932
 
 
933
template<class T>
 
934
bool QStringHash<T>::contains(const QString &s) const
 
935
{
 
936
    return 0 != value(s);
 
937
}
 
938
 
 
939
template<class T>
 
940
bool QStringHash<T>::contains(const QHashedString &s) const
 
941
{
 
942
    return 0 != value(s);
 
943
}
 
944
 
 
945
template<class T>
 
946
bool QStringHash<T>::contains(const QHashedStringRef &s) const
 
947
{
 
948
    return 0 != value(s);
 
949
}
 
950
 
 
951
template<class T>
 
952
bool QStringHash<T>::contains(const QHashedCStringRef &s) const
 
953
{
 
954
    return 0 != value(s);
 
955
}
 
956
 
 
957
template<class T>
 
958
bool QStringHash<T>::contains(const ConstIterator &s) const
 
959
{
 
960
    return 0 != value(s);
 
961
}
 
962
 
 
963
template<class T>
 
964
T &QStringHash<T>::operator[](const QString &key)
 
965
{
 
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;
 
970
}
 
971
 
 
972
template<class T>
 
973
T &QStringHash<T>::operator[](const QHashedString &key)
 
974
{
 
975
    Node *n = findNode(key);
 
976
    if (n) return n->value;
 
977
    else return createNode(key, T())->value;
 
978
}
 
979
 
 
980
template<class T>
 
981
T &QStringHash<T>::operator[](const QHashedStringRef &key)
 
982
{
 
983
    Node *n = findNode(key);
 
984
    if (n) return n->value;
 
985
    else return createNode(key, T())->value;
 
986
}
 
987
 
 
988
template<class T>
 
989
T &QStringHash<T>::operator[](const QHashedCStringRef &key)
 
990
{
 
991
    Node *n = findNode(key);
 
992
    if (n) return n->value;
 
993
    else return createNode(key, T())->value;
 
994
}
 
995
 
 
996
template<class T>
 
997
void QStringHash<T>::reserve(int n)
 
998
{
 
999
    if (nodePool || 0 == n)
 
1000
        return;
 
1001
 
 
1002
    nodePool = new ReservedNodePool;
 
1003
    nodePool->count = n;
 
1004
    nodePool->used = 0;
 
1005
    nodePool->nodes = new Node[n];
 
1006
 
 
1007
    data.rehashToSize(n, iterateFirst(), iterateNext);
 
1008
}
 
1009
 
 
1010
template<class T>
 
1011
QStringHash<T>::ConstIterator::ConstIterator()
 
1012
{
 
1013
}
 
1014
 
 
1015
template<class T>
 
1016
QStringHash<T>::ConstIterator::ConstIterator(const QStringHashData::IteratorData &d)
 
1017
: d(d)
 
1018
{
 
1019
}
 
1020
 
 
1021
template<class T>
 
1022
typename QStringHash<T>::ConstIterator &QStringHash<T>::ConstIterator::operator++()
 
1023
{
 
1024
    d = QStringHash<T>::iterateNext(d);
 
1025
    return *this;
 
1026
}
 
1027
 
 
1028
template<class T>
 
1029
bool QStringHash<T>::ConstIterator::operator==(const ConstIterator &o) const
 
1030
{
 
1031
    return d.n == o.d.n;
 
1032
}
 
1033
 
 
1034
template<class T>
 
1035
bool QStringHash<T>::ConstIterator::operator!=(const ConstIterator &o) const
 
1036
{
 
1037
    return d.n != o.d.n;
 
1038
}
 
1039
 
 
1040
template<class T>
 
1041
QHashedString QStringHash<T>::ConstIterator::key() const
 
1042
{
 
1043
    Node *n = (Node *)d.n;
 
1044
    if (n->isQString()) {
 
1045
        return QHashedString(QString((QChar *)n->strData->data(), n->length), n->hash);
 
1046
    } else {
 
1047
        return QHashedString(QString::fromLatin1(n->ckey, n->length), n->hash);
 
1048
    }
 
1049
}
 
1050
template<class T>
 
1051
const T &QStringHash<T>::ConstIterator::value() const
 
1052
{
 
1053
    Node *n = (Node *)d.n;
 
1054
    return n->value;
 
1055
}
 
1056
 
 
1057
template<class T>
 
1058
const T &QStringHash<T>::ConstIterator::operator*() const
 
1059
{
 
1060
    Node *n = (Node *)d.n;
 
1061
    return n->value;
 
1062
}
 
1063
 
 
1064
template<class T>
 
1065
typename QStringHash<T>::Node *QStringHash<T>::ConstIterator::node() const
 
1066
{
 
1067
    Node *n = (Node *)d.n;
 
1068
    return n;
 
1069
}
 
1070
 
 
1071
template<class T>
 
1072
typename QStringHash<T>::ConstIterator QStringHash<T>::begin() const
 
1073
{
 
1074
    return ConstIterator(iterateFirst());
 
1075
}
 
1076
 
 
1077
template<class T>
 
1078
typename QStringHash<T>::ConstIterator QStringHash<T>::end() const
 
1079
{
 
1080
    return ConstIterator();
 
1081
}
 
1082
 
 
1083
inline uint qHash(const QHashedString &string) 
 
1084
 
1085
    return uint(string.hash()); 
 
1086
}
 
1087
 
 
1088
inline uint qHash(const QHashedStringRef &string) 
 
1089
 
1090
    return uint(string.hash()); 
 
1091
}
 
1092
 
 
1093
QHashedString::QHashedString() 
 
1094
: QString(), m_hash(0) 
 
1095
{
 
1096
}
 
1097
 
 
1098
QHashedString::QHashedString(const QString &string) 
 
1099
: QString(string), m_hash(0) 
 
1100
{
 
1101
}
 
1102
 
 
1103
QHashedString::QHashedString(const QString &string, quint32 hash) 
 
1104
: QString(string), m_hash(hash) 
 
1105
{
 
1106
}
 
1107
 
 
1108
QHashedString::QHashedString(const QHashedString &string) 
 
1109
: QString(string), m_hash(string.m_hash) 
 
1110
{
 
1111
}
 
1112
 
 
1113
QHashedString &QHashedString::operator=(const QHashedString &string)
 
1114
{
 
1115
    static_cast<QString &>(*this) = string;
 
1116
    m_hash = string.m_hash;
 
1117
    return *this;
 
1118
}
 
1119
 
 
1120
bool QHashedString::operator==(const QHashedString &string) const
 
1121
{
 
1122
    return (string.m_hash == m_hash || !string.m_hash || !m_hash) && 
 
1123
           static_cast<const QString &>(*this) == static_cast<const QString &>(string);
 
1124
}
 
1125
 
 
1126
bool QHashedString::operator==(const QHashedStringRef &string) const
 
1127
{
 
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);
 
1131
}
 
1132
 
 
1133
quint32 QHashedString::hash() const
 
1134
 
1135
    if (!m_hash) computeHash();
 
1136
    return m_hash;
 
1137
}
 
1138
 
 
1139
quint32 QHashedString::existingHash() const
 
1140
 
1141
    return m_hash;
 
1142
}
 
1143
 
 
1144
bool QHashedString::isUpper(const QChar &qc)
 
1145
{
 
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));
 
1150
}
 
1151
 
 
1152
QHashedV8String::QHashedV8String()
 
1153
{
 
1154
}
 
1155
 
 
1156
QHashedV8String::QHashedV8String(v8::Handle<v8::String> string)
 
1157
: m_hash(string->CompleteHash()), m_string(string)
 
1158
{
 
1159
    Q_ASSERT(!m_string.IsEmpty());
 
1160
}
 
1161
 
 
1162
QHashedV8String::QHashedV8String(const QHashedV8String &string)
 
1163
: m_hash(string.m_hash), m_string(string.m_string)
 
1164
{
 
1165
}
 
1166
 
 
1167
QHashedV8String &QHashedV8String::operator=(const QHashedV8String &other)
 
1168
{
 
1169
    m_hash = other.m_hash;
 
1170
    m_string = other.m_string;
 
1171
    return *this;
 
1172
}
 
1173
 
 
1174
bool QHashedV8String::operator==(const QHashedV8String &string)
 
1175
{
 
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));
 
1179
}
 
1180
 
 
1181
quint32 QHashedV8String::hash() const
 
1182
{
 
1183
    return m_hash.hash;
 
1184
}
 
1185
 
 
1186
int QHashedV8String::length() const
 
1187
{
 
1188
    return m_hash.length;
 
1189
}
 
1190
 
 
1191
quint32 QHashedV8String::symbolId() const
 
1192
{
 
1193
    return m_hash.symbol_id;
 
1194
}
 
1195
 
 
1196
v8::Handle<v8::String> QHashedV8String::string() const
 
1197
{
 
1198
    return m_string;
 
1199
}
 
1200
 
 
1201
QString QHashedV8String::toString() const
 
1202
{
 
1203
    QString result;
 
1204
    result.reserve(m_hash.length);
 
1205
 
 
1206
    for (int i = 0; i < m_hash.length; ++i)
 
1207
        result.append(m_string->GetCharacter(i));
 
1208
 
 
1209
    return result;
 
1210
}
 
1211
 
 
1212
QHashedStringRef::QHashedStringRef() 
 
1213
: m_data(0), m_length(0), m_utf8length(-1), m_hash(0) 
 
1214
{
 
1215
}
 
1216
 
 
1217
QHashedStringRef::QHashedStringRef(const QString &str)
 
1218
: m_data(str.constData()), m_length(str.length()), m_utf8length(0), m_hash(0)
 
1219
{
 
1220
}
 
1221
 
 
1222
QHashedStringRef::QHashedStringRef(const QStringRef &str)
 
1223
: m_data(str.constData()), m_length(str.length()), m_utf8length(0), m_hash(0)
 
1224
{
 
1225
}
 
1226
 
 
1227
QHashedStringRef::QHashedStringRef(const QChar *data, int length)
 
1228
: m_data(data), m_length(length), m_utf8length(0), m_hash(0)
 
1229
{
 
1230
}
 
1231
 
 
1232
QHashedStringRef::QHashedStringRef(const QChar *data, int length, quint32 hash)
 
1233
: m_data(data), m_length(length), m_utf8length(0), m_hash(hash)
 
1234
{
 
1235
}
 
1236
 
 
1237
QHashedStringRef::QHashedStringRef(const QHashedString &string)
 
1238
: m_data(string.constData()), m_length(string.length()), m_utf8length(0), m_hash(string.m_hash)
 
1239
{
 
1240
}
 
1241
 
 
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)
 
1245
{
 
1246
}
 
1247
 
 
1248
QHashedStringRef &QHashedStringRef::operator=(const QHashedStringRef &o)
 
1249
{
 
1250
    m_data = o.m_data;
 
1251
    m_length = o.m_length;
 
1252
    m_utf8length = o.m_utf8length;
 
1253
    m_hash = o.m_hash;
 
1254
    return *this;
 
1255
}
 
1256
 
 
1257
bool QHashedStringRef::operator==(const QString &string) const
 
1258
{
 
1259
    return m_length == string.length() &&
 
1260
           QHashedString::compare(string.constData(), m_data, m_length);
 
1261
}
 
1262
 
 
1263
bool QHashedStringRef::operator==(const QHashedString &string) const
 
1264
{
 
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);
 
1268
}
 
1269
 
 
1270
bool QHashedStringRef::operator==(const QHashedStringRef &string) const
 
1271
{
 
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);
 
1275
}
 
1276
 
 
1277
bool QHashedStringRef::operator==(const QHashedCStringRef &string) const
 
1278
{
 
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);
 
1282
}
 
1283
 
 
1284
bool QHashedStringRef::operator!=(const QString &string) const
 
1285
{
 
1286
    return m_length != string.length() ||
 
1287
           !QHashedString::compare(string.constData(), m_data, m_length);
 
1288
}
 
1289
 
 
1290
bool QHashedStringRef::operator!=(const QHashedString &string) const
 
1291
{
 
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);
 
1295
}
 
1296
 
 
1297
bool QHashedStringRef::operator!=(const QHashedStringRef &string) const
 
1298
{
 
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);
 
1302
}
 
1303
 
 
1304
bool QHashedStringRef::operator!=(const QHashedCStringRef &string) const
 
1305
{
 
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);
 
1309
}
 
1310
 
 
1311
const QChar &QHashedStringRef::at(int index) const
 
1312
{
 
1313
    Q_ASSERT(index < m_length);
 
1314
    return m_data[index];
 
1315
}
 
1316
 
 
1317
const QChar *QHashedStringRef::constData() const
 
1318
{
 
1319
    return m_data;
 
1320
}
 
1321
 
 
1322
bool QHashedStringRef::isEmpty() const
 
1323
{
 
1324
    return m_length == 0;
 
1325
}
 
1326
 
 
1327
int QHashedStringRef::length() const
 
1328
{
 
1329
    return m_length;
 
1330
}
 
1331
 
 
1332
int QHashedStringRef::utf8length() const
 
1333
{
 
1334
    if (m_utf8length < m_length)
 
1335
        computeUtf8Length();
 
1336
    return m_utf8length;
 
1337
}
 
1338
 
 
1339
bool QHashedStringRef::startsWithUpper() const
 
1340
{
 
1341
    if (m_length < 1) return false;
 
1342
    return QHashedString::isUpper(m_data[0]);
 
1343
}
 
1344
 
 
1345
quint32 QHashedStringRef::hash() const
 
1346
 
1347
    if (!m_hash) computeHash();
 
1348
    return m_hash;
 
1349
}
 
1350
 
 
1351
QHashedCStringRef::QHashedCStringRef()
 
1352
: m_data(0), m_length(0), m_hash(0)
 
1353
{
 
1354
}
 
1355
 
 
1356
QHashedCStringRef::QHashedCStringRef(const char *data, int length)
 
1357
: m_data(data), m_length(length), m_hash(0)
 
1358
{
 
1359
}
 
1360
 
 
1361
QHashedCStringRef::QHashedCStringRef(const char *data, int length, quint32 hash)
 
1362
: m_data(data), m_length(length), m_hash(hash)
 
1363
{
 
1364
}
 
1365
 
 
1366
QHashedCStringRef::QHashedCStringRef(const QHashedCStringRef &o)
 
1367
: m_data(o.m_data), m_length(o.m_length), m_hash(o.m_hash)
 
1368
{
 
1369
}
 
1370
 
 
1371
quint32 QHashedCStringRef::hash() const
 
1372
{
 
1373
    if (!m_hash) computeHash();
 
1374
    return m_hash;
 
1375
}
 
1376
 
 
1377
const char *QHashedCStringRef::constData() const
 
1378
{
 
1379
    return m_data;
 
1380
}
 
1381
 
 
1382
int QHashedCStringRef::length() const
 
1383
{
 
1384
    return m_length;
 
1385
}
 
1386
 
 
1387
int QHashedCStringRef::utf16length() const
 
1388
{
 
1389
    return m_length;
 
1390
}
 
1391
 
 
1392
void QHashedCStringRef::writeUtf16(QChar *output) const
 
1393
{
 
1394
    writeUtf16((uint16_t *)output);
 
1395
}
 
1396
 
 
1397
void QHashedCStringRef::writeUtf16(uint16_t *output) const
 
1398
{
 
1399
    int l = m_length;
 
1400
    const char *d = m_data;
 
1401
    while (l--) 
 
1402
        *output++ = *d++;
 
1403
}
 
1404
 
 
1405
bool QHashedString::compare(const QChar *lhs, const char *rhs, int length) 
 
1406
{
 
1407
    Q_ASSERT(lhs && rhs);
 
1408
    const quint16 *l = (const quint16*)lhs;
 
1409
    while (length--) 
 
1410
        if (*l++ != *rhs++) return false;
 
1411
    return true;
 
1412
}
 
1413
 
 
1414
bool QHashedString::compare(const char *lhs, const char *rhs, int length) 
 
1415
{
 
1416
    Q_ASSERT(lhs && rhs);
 
1417
    return 0 == ::memcmp(lhs, rhs, length);
 
1418
}
 
1419
 
 
1420
QT_END_NAMESPACE
 
1421
 
 
1422
#endif // QHASHEDSTRING_P_H