Improve QStringHash
[profile/ivi/qtdeclarative.git] / src / declarative / qml / ftw / qhashedstring_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
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 QT_BEGIN_NAMESPACE
61
62 class QHashedStringRef;
63 class QHashedString : public QString
64 {
65 public:
66     inline QHashedString();
67     inline QHashedString(const QString &string);
68     inline QHashedString(const QString &string, quint32);
69     inline QHashedString(const QHashedString &string);
70
71     inline QHashedString &operator=(const QHashedString &string);
72     inline bool operator==(const QHashedString &string) const;
73     inline bool operator==(const QHashedStringRef &string) const;
74
75     inline quint32 hash() const;
76     inline quint32 existingHash() const;
77
78     static inline bool isUpper(const QChar &);
79 private:
80     friend class QHashedStringRef;
81
82     void computeHash() const;
83     mutable quint32 m_hash;
84 };
85
86 class QHashedV8String 
87 {
88 public:
89     inline QHashedV8String();
90     explicit inline QHashedV8String(v8::Handle<v8::String>);
91     inline QHashedV8String(const QHashedV8String &string);
92     inline QHashedV8String &operator=(const QHashedV8String &other);
93
94     inline bool operator==(const QHashedV8String &string);
95
96     inline quint32 hash() const;
97     inline int length() const; 
98     inline quint32 symbolId() const;
99
100     inline v8::Handle<v8::String> string() const;
101
102 private:
103     v8::String::CompleteHashData m_hash;
104     v8::Handle<v8::String> m_string;
105 };
106
107 class QHashedStringRef 
108 {
109 public:
110     inline QHashedStringRef();
111     inline QHashedStringRef(const QString &);
112     inline QHashedStringRef(const QChar *, int);
113     inline QHashedStringRef(const QChar *, int, quint32);
114     inline QHashedStringRef(const QHashedString &);
115     inline QHashedStringRef(const QHashedStringRef &);
116
117     inline bool operator==(const QHashedString &string) const;
118     inline bool operator==(const QHashedStringRef &string) const;
119
120     inline quint32 hash() const;
121
122     inline const QChar *constData() const;
123     inline int length() const;
124     inline bool startsWithUpper() const;
125
126 private:
127     friend class QHashedString;
128
129     void computeHash() const;
130
131     const QChar *m_data;
132     int m_length;
133     mutable quint32 m_hash;
134 };
135
136 class QHashedCStringRef
137 {
138 public:
139     inline QHashedCStringRef();
140     inline QHashedCStringRef(const char *, int);
141     inline QHashedCStringRef(const char *, int, quint32);
142     inline QHashedCStringRef(const QHashedCStringRef &);
143
144     inline quint32 hash() const;
145
146     inline const char *constData() const;
147     inline int length() const;
148 private:
149     void computeHash() const;
150
151     const char *m_data;
152     int m_length;
153     mutable quint32 m_hash;
154 };
155
156 class QStringHashData;
157 class QStringHashNode
158 {
159 public:
160     QStringHashNode()
161     : nlist(0), next(0), length(0), hash(0), pooled(0), ckey(0), symbolId()
162     {
163     }
164
165     QStringHashNode(const QHashedString &key)
166     : nlist(0), next(0), length(key.length()), hash(key.hash()), pooled(0), ckey(0), key(key), symbolId(0) {
167     }
168
169     QStringHashNode(const QHashedCStringRef &key)
170     : nlist(0), next(0), length(key.length()), hash(key.hash()), pooled(0), ckey(key.constData()), symbolId(0) {
171     }
172
173     QStringHashNode(const QStringHashNode &o)
174     : nlist(0), next(0), length(o.length), hash(o.hash), pooled(0), ckey(o.ckey), key(o.key), symbolId(o.symbolId) {
175     }
176
177     QStringHashNode *nlist;
178     QStringHashNode *next;
179     qint32 length;
180     quint32 hash;
181
182     quint32 pooled:1;
183     const char *ckey;
184     QString key;
185     
186     quint32 symbolId;
187
188     inline bool equals(v8::Handle<v8::String> string) {
189         return ckey?string->Equals((char*)ckey, length):
190                     string->Equals((uint16_t*)key.constData(), length);
191     }
192
193     inline bool symbolEquals(const QHashedV8String &string) {
194         Q_ASSERT(string.symbolId() != 0);
195         return length == string.length() && hash == string.hash() && 
196                (string.symbolId() == symbolId || equals(string.string()));
197     }
198
199     inline bool equals(const QHashedV8String &string) {
200         return length == string.length() && hash == string.hash() && 
201                equals(string.string());
202     }
203
204     inline bool equals(const QHashedStringRef &string) {
205         return length == string.length() && 
206             hash == string.hash() && 
207                ckey?(cstrCompare(string.constData(), ckey, length)):
208                        (0 == ::memcmp(string.constData(), key.constData(), length * sizeof(QChar)));
209     }
210
211     inline bool equals(const QHashedCStringRef &string) {
212         return length == string.length() && 
213             hash == string.hash() && 
214                ckey?(0 == ::memcmp(string.constData(), ckey, length)):
215                     (cstrCompare(key.constData(), string.constData(), length));
216     }
217
218 private:
219     static inline bool cstrCompare(const QChar *lhsChar, const char *rhs, int length) {
220         Q_ASSERT(lhsChar && rhs);
221         const uint16_t *lhs = (const uint16_t*)lhsChar;
222         while (length--) 
223             if (*lhs++ != *rhs++) return false;
224         return true;
225     }
226 };
227
228 struct QStringHashData
229 {
230 public:
231     QStringHashData() 
232     : nodes(0), buckets(0), numBuckets(0), size(0), numBits(0) {}
233
234     QStringHashNode *nodes;
235     QStringHashNode **buckets;
236     int numBuckets;
237     int size;
238     short numBits;
239
240     void rehash();
241 };
242
243 template<class T>
244 class QStringHash
245 {
246 private:
247     struct Node : public QStringHashNode {
248         Node(const QHashedString &key, const T &value) : QStringHashNode(key), value(value) {}
249         Node(const QHashedCStringRef &key, const T &value) : QStringHashNode(key), value(value) {}
250         Node(const Node &o) : QStringHashNode(o), value(o.value) {}
251         Node() {}
252         T value;
253     };
254     struct ReservedNodePool
255     {
256         ReservedNodePool() : count(0), used(0), nodes(0) {}
257         ~ReservedNodePool() { delete [] nodes; }
258         int count;
259         int used;
260         Node *nodes;
261     };
262
263     QStringHashData data;
264     ReservedNodePool *nodePool;
265
266     inline Node *findNode(const QHashedStringRef &) const;
267     inline Node *findNode(const QHashedCStringRef &) const;
268     inline Node *findNode(const QHashedV8String &) const;
269     inline Node *findSymbolNode(const QHashedV8String &) const;
270     inline Node *createNode(const QHashedString &, const T &);
271     inline Node *createNode(const QHashedCStringRef &, const T &);
272
273     inline Node *takeNode(const QHashedString &key, const T &value);
274     inline Node *takeNode(const QHashedCStringRef &key, const T &value);
275     inline Node *takeNode(const Node &o);
276
277     inline void copy(const QStringHash<T> &);
278 public:
279     inline QStringHash();
280     inline QStringHash(const QStringHash &);
281     inline ~QStringHash();
282
283     QStringHash &operator=(const QStringHash<T> &);
284
285     void copyAndReserve(const QStringHash<T> &other, int additionalReserve);
286
287     inline bool isEmpty() const;
288     inline void clear();
289     inline int count() const;
290
291     inline void insert(const QString &, const T &);
292     inline void insert(const QHashedString &, const T &);
293     inline void insert(const QHashedStringRef &, const T &);
294     inline void insert(const QHashedCStringRef &, const T &);
295
296     inline T *value(const QString &) const;
297     inline T *value(const QHashedString &) const;
298     inline T *value(const QHashedStringRef &) const;
299     inline T *value(const QHashedV8String &) const;
300     inline T *value(const QHashedCStringRef &) const;
301
302     inline bool contains(const QString &) const;
303     inline bool contains(const QHashedString &) const;
304     inline bool contains(const QHashedStringRef &) const;
305     inline bool contains(const QHashedCStringRef &) const;
306
307     T &operator[](const QString &);
308     T &operator[](const QHashedString &);
309     T &operator[](const QHashedStringRef &);
310     T &operator[](const QHashedCStringRef &);
311
312     class ConstIterator {
313     public:
314         ConstIterator() : n(0) {}
315         ConstIterator(Node *n) : n(n) {}
316
317         ConstIterator &operator++() { n = (Node *)n->nlist; return *this; }
318         bool operator==(const ConstIterator &o) const { return n == o.n; }
319         bool operator!=(const ConstIterator &o) const { return n != o.n; }
320
321         QHashedString key() const { 
322             if (n->ckey) {
323                 return QHashedString(QString::fromLatin1(n->ckey, n->length), n->hash);
324             } else {
325                 return QHashedString(n->key, n->hash);
326             }
327         }
328         const T &value() const { return n->value; }
329         const T &operator*() const { return n->value; }
330     private:
331         Node *n;
332     };
333
334     ConstIterator begin() const { return ConstIterator((Node *)data.nodes); }
335     ConstIterator end() const { return ConstIterator(); }
336
337     inline void reserve(int);
338 };
339
340 template<class T>
341 QStringHash<T>::QStringHash()
342 : nodePool(0)
343 {
344 }
345
346 template<class T>
347 QStringHash<T>::QStringHash(const QStringHash<T> &other)
348 : data(other.data), nodePool(0)
349 {
350     reserve(other.count());
351     copy(other);
352 }
353
354 template<class T>
355 QStringHash<T> &QStringHash<T>::operator=(const QStringHash<T> &other)
356 {
357     if (&other == this)
358         return *this;
359
360     clear();
361
362     data = other.data;
363     reserve(other.count());
364     copy(other);
365
366     return *this;
367 }
368
369 template<class T>
370 void QStringHash<T>::copyAndReserve(const QStringHash<T> &other, int additionalReserve)
371 {
372     clear();
373
374     data = other.data;
375     reserve(other.count() + additionalReserve);
376     copy(other);
377 }
378
379 template<class T>
380 QStringHash<T>::~QStringHash()
381 {
382     clear();
383 }
384
385 template<class T>
386 void QStringHash<T>::clear() 
387 {
388     // If all the nodes were allocated from the node pool, we
389     // don't need to clean them individually
390     if (!nodePool || data.size != nodePool->used) {
391         QStringHashNode *n = data.nodes;
392         while (n) {
393             Node *o = (Node *)n;
394             n = n->nlist;
395             if (!o->pooled) delete o;
396         }
397     }
398     if (nodePool) delete nodePool; 
399     delete [] data.buckets;
400
401     data = QStringHashData();
402     nodePool = 0;
403 }
404
405 template<class T>
406 bool QStringHash<T>::isEmpty() const
407 {
408     return data.nodes == 0;
409 }
410
411 template<class T>
412 int QStringHash<T>::count() const
413 {
414     return data.size;
415 }
416
417 template<class T>
418 typename QStringHash<T>::Node *QStringHash<T>::takeNode(const QHashedString &key, const T &value)
419 {
420     if (nodePool && nodePool->used != nodePool->count) {
421         Node *rv = nodePool->nodes + nodePool->used++;
422         rv->length = key.length();
423         rv->hash = key.hash();
424         rv->key = key;
425         rv->pooled = 1;
426         rv->value = value;
427         return rv;
428     } else {
429         return new Node(key, value);
430     }
431 }
432
433 template<class T>
434 typename QStringHash<T>::Node *QStringHash<T>::takeNode(const QHashedCStringRef &key, const T &value)
435 {
436     if (nodePool && nodePool->used != nodePool->count) {
437         Node *rv = nodePool->nodes + nodePool->used++;
438         rv->length = key.length();
439         rv->hash = key.hash();
440         rv->ckey = key.constData();
441         rv->pooled = 1;
442         rv->value = value;
443         return rv;
444     } else {
445         return new Node(key, value);
446     }
447 }
448
449 template<class T>
450 typename QStringHash<T>::Node *QStringHash<T>::takeNode(const Node &o)
451 {
452     if (nodePool && nodePool->used != nodePool->count) {
453         Node *rv = nodePool->nodes + nodePool->used++;
454         rv->length = o.length;
455         rv->hash = o.hash;
456         rv->ckey = o.ckey;
457         rv->key = o.key;
458         rv->pooled = 1;
459         rv->symbolId = o.symbolId;
460         rv->value = o.value;
461         return rv;
462     } else {
463         return new Node(o);
464     }
465 }
466
467 template<class T>
468 void QStringHash<T>::copy(const QStringHash<T> &other)
469 {
470     data.nodes = 0;
471     data.buckets = 0;
472
473     QStringHashNode *n = other.data.nodes;
474     while (n) {
475         Node *o = (Node *)n;
476         Node *mynode = takeNode(*o);
477         mynode->nlist = data.nodes;
478         data.nodes = mynode;
479         n = o->nlist;
480     }
481
482     data.rehash();
483 }
484
485 template<class T>
486 typename QStringHash<T>::Node *QStringHash<T>::createNode(const QHashedString &key, const T &value)
487 {
488     if (data.size == data.numBuckets) 
489         data.rehash();
490
491     Node *n = takeNode(key, value);
492     n->nlist = data.nodes;
493     data.nodes = n;
494
495     int bucket = key.hash() % data.numBuckets;
496     n->next = data.buckets[bucket];
497     data.buckets[bucket] = n;
498
499     data.size++; 
500
501     return n;
502 }
503
504 template<class T>
505 typename QStringHash<T>::Node *QStringHash<T>::createNode(const QHashedCStringRef &key, const T &value)
506 {
507     if (data.size == data.numBuckets) 
508         data.rehash();
509
510     Node *n = takeNode(key, value);
511     n->nlist = data.nodes;
512     data.nodes = n;
513
514     int bucket = key.hash() % data.numBuckets;
515     n->next = data.buckets[bucket];
516     data.buckets[bucket] = n;
517
518     data.size++; 
519
520     return n;
521 }
522
523 template<class T>
524 void QStringHash<T>::insert(const QString &key, const T &value)
525 {
526     QHashedStringRef ch(key);
527     Node *n = findNode(key);
528     if (n) n->value = value;
529     else createNode(QHashedString(key, ch.hash()), value);
530 }
531
532 template<class T>
533 void QStringHash<T>::insert(const QHashedString &key, const T &value)
534 {
535     Node *n = findNode(key);
536     if (n) n->value = value;
537     else createNode(key, value);
538 }
539
540 template<class T>
541 void QStringHash<T>::insert(const QHashedStringRef &key, const T &value)
542 {
543     Node *n = findNode(key);
544     if (n) n->value = value;
545     else createNode(key, value);
546 }
547
548 template<class T>
549 void QStringHash<T>::insert(const QHashedCStringRef &key, const T &value)
550 {
551     Node *n = findNode(key);
552     if (n) n->value = value;
553     else createNode(key, value);
554 }
555
556 template<class T>
557 typename QStringHash<T>::Node *QStringHash<T>::findNode(const QHashedStringRef &string) const
558 {
559     QStringHashNode *node = 0;
560     if (data.numBuckets) {
561         node = data.buckets[string.hash() % data.numBuckets];
562         while (node && !node->equals(string))
563             node = node->next;
564     } 
565
566     return (Node *)node;
567 }
568
569 template<class T>
570 typename QStringHash<T>::Node *QStringHash<T>::findNode(const QHashedCStringRef &string) const
571 {
572     QStringHashNode *node = 0;
573     if (data.numBuckets) {
574         node = data.buckets[string.hash() % data.numBuckets];
575         while (node && !node->equals(string))
576             node = node->next;
577     } 
578
579     return (Node *)node;
580 }
581
582 template<class T>
583 typename QStringHash<T>::Node *QStringHash<T>::findNode(const QHashedV8String &string) const
584 {
585     QStringHashNode *node = 0;
586     if (data.numBuckets) {
587         quint32 hash = string.hash();
588         node = data.buckets[hash % data.numBuckets];
589         while (node && !node->equals(string))
590             node = node->next;
591     } 
592
593     return (Node *)node;
594 }
595
596 template<class T>
597 typename QStringHash<T>::Node *QStringHash<T>::findSymbolNode(const QHashedV8String &string) const
598 {
599     Q_ASSERT(string.symbolId() != 0);
600
601     QStringHashNode *node = 0;
602     if (data.numBuckets) {
603         quint32 hash = string.hash();
604         node = data.buckets[hash % data.numBuckets];
605         while (node && !node->symbolEquals(string))
606             node = node->next;
607
608         if (node)
609             node->symbolId = string.symbolId();
610     } 
611
612     return (Node *)node;
613 }
614
615 template<class T>
616 T *QStringHash<T>::value(const QString &key) const
617 {
618     Node *n = findNode(key);
619     return n?&n->value:0;
620 }
621
622 template<class T>
623 T *QStringHash<T>::value(const QHashedString &key) const
624 {
625     Node *n = findNode(key);
626     return n?&n->value:0;
627 }
628
629 template<class T>
630 T *QStringHash<T>::value(const QHashedStringRef &key) const
631 {
632     Node *n = findNode(key);
633     return n?&n->value:0;
634 }
635
636 template<class T>
637 T *QStringHash<T>::value(const QHashedCStringRef &key) const
638 {
639     Node *n = findNode(key);
640     return n?&n->value:0;
641 }
642
643 template<class T>
644 T *QStringHash<T>::value(const QHashedV8String &string) const
645 {
646     Node *n = string.symbolId()?findSymbolNode(string):findNode(string);
647     return n?&n->value:0;
648 }
649
650 template<class T>
651 bool QStringHash<T>::contains(const QString &s) const
652 {
653     return 0 != value(s);
654 }
655
656 template<class T>
657 bool QStringHash<T>::contains(const QHashedString &s) const
658 {
659     return 0 != value(s);
660 }
661
662 template<class T>
663 bool QStringHash<T>::contains(const QHashedStringRef &s) const
664 {
665     return 0 != value(s);
666 }
667
668 template<class T>
669 bool QStringHash<T>::contains(const QHashedCStringRef &s) const
670 {
671     return 0 != value(s);
672 }
673
674 template<class T>
675 T &QStringHash<T>::operator[](const QString &key) 
676 {
677     QHashedStringRef cs(key);
678     Node *n = findNode(cs);
679     if (n) return n->value;
680     else return createNode(QHashedString(key, cs.hash()), T())->value;
681 }
682
683 template<class T>
684 T &QStringHash<T>::operator[](const QHashedString &key)
685 {
686     Node *n = findNode(key);
687     if (n) return n->value;
688     else return createNode(key, T())->value;
689 }
690
691 template<class T>
692 T &QStringHash<T>::operator[](const QHashedStringRef &key) 
693 {
694     Node *n = findNode(key);
695     if (n) return n->value;
696     else return createNode(key, T())->value;
697 }
698
699 template<class T>
700 T &QStringHash<T>::operator[](const QHashedCStringRef &key) 
701 {
702     Node *n = findNode(key);
703     if (n) return n->value;
704     else return createNode(key, T())->value;
705 }
706
707 template<class T>
708 void QStringHash<T>::reserve(int n)
709 {
710     if (nodePool || 0 == n)
711         return;
712     nodePool = new ReservedNodePool;
713     nodePool->count = n;
714     nodePool->used = 0;
715     nodePool->nodes = new Node[n];
716 }
717
718 inline uint qHash(const QHashedString &string) 
719
720     return uint(string.hash()); 
721 }
722
723 inline uint qHash(const QHashedStringRef &string) 
724
725     return uint(string.hash()); 
726 }
727
728 QHashedString::QHashedString() 
729 : QString(), m_hash(0) 
730 {
731 }
732
733 QHashedString::QHashedString(const QString &string) 
734 : QString(string), m_hash(0) 
735 {
736 }
737
738 QHashedString::QHashedString(const QString &string, quint32 hash) 
739 : QString(string), m_hash(hash) 
740 {
741 }
742
743 QHashedString::QHashedString(const QHashedString &string) 
744 : QString(string), m_hash(string.m_hash) 
745 {
746 }
747
748 QHashedString &QHashedString::operator=(const QHashedString &string)
749 {
750     static_cast<QString &>(*this) = string;
751     m_hash = string.m_hash;
752     return *this;
753 }
754
755 bool QHashedString::operator==(const QHashedString &string) const
756 {
757     return (string.m_hash == m_hash || !string.m_hash || !m_hash) && 
758            static_cast<const QString &>(*this) == static_cast<const QString &>(string);
759 }
760
761 bool QHashedString::operator==(const QHashedStringRef &string) const
762 {
763     return length() == string.m_length &&
764            (string.m_hash == m_hash || !string.m_hash || !m_hash) && 
765            0 == ::memcmp(constData(), string.m_data, string.m_length * sizeof(QChar));
766 }
767
768 quint32 QHashedString::hash() const
769
770     if (!m_hash) computeHash();
771     return m_hash;
772 }
773
774 quint32 QHashedString::existingHash() const
775
776     return m_hash;
777 }
778
779 bool QHashedString::isUpper(const QChar &qc)
780 {
781     ushort c = qc.unicode();
782     // Optimize for _, a-z and A-Z.
783     return ((c != '_' ) && (!(c >= 'a' && c <= 'z')) &&
784            ((c >= 'A' && c <= 'Z') || QChar::category(c) == QChar::Letter_Uppercase));
785 }
786
787 QHashedV8String::QHashedV8String()
788 {
789 }
790
791 QHashedV8String::QHashedV8String(v8::Handle<v8::String> string)
792 : m_hash(string->CompleteHash()), m_string(string)
793 {
794     Q_ASSERT(!m_string.IsEmpty());
795 }
796
797 QHashedV8String::QHashedV8String(const QHashedV8String &string)
798 : m_hash(string.m_hash), m_string(string.m_string)
799 {
800 }
801
802 QHashedV8String &QHashedV8String::operator=(const QHashedV8String &other)
803 {
804     m_hash = other.m_hash;
805     m_string = other.m_string;
806     return *this;
807 }
808
809 bool QHashedV8String::operator==(const QHashedV8String &string)
810 {
811     return m_hash.hash == string.m_hash.hash && m_hash.length == string.m_hash.length &&
812            m_string.IsEmpty() == m_string.IsEmpty() && 
813            (m_string.IsEmpty() || m_string->StrictEquals(string.m_string));
814 }
815
816 quint32 QHashedV8String::hash() const
817 {
818     return m_hash.hash;
819 }
820
821 int QHashedV8String::length() const
822 {
823     return m_hash.length;
824 }
825
826 quint32 QHashedV8String::symbolId() const
827 {
828     return m_hash.symbol_id;
829 }
830
831 v8::Handle<v8::String> QHashedV8String::string() const
832 {
833     return m_string;
834 }
835
836 QHashedStringRef::QHashedStringRef() 
837 : m_data(0), m_length(0), m_hash(0) 
838 {
839 }
840
841 QHashedStringRef::QHashedStringRef(const QString &str)
842 : m_data(str.constData()), m_length(str.length()), m_hash(0)
843 {
844 }
845
846 QHashedStringRef::QHashedStringRef(const QChar *data, int length)
847 : m_data(data), m_length(length), m_hash(0)
848 {
849 }
850
851 QHashedStringRef::QHashedStringRef(const QChar *data, int length, quint32 hash)
852 : m_data(data), m_length(length), m_hash(hash)
853 {
854 }
855
856 QHashedStringRef::QHashedStringRef(const QHashedString &string)
857 : m_data(string.constData()), m_length(string.length()), m_hash(string.m_hash)
858 {
859 }
860
861 QHashedStringRef::QHashedStringRef(const QHashedStringRef &string)
862 : m_data(string.m_data), m_length(string.m_length), m_hash(string.m_hash)
863 {
864 }
865
866 bool QHashedStringRef::operator==(const QHashedString &string) const
867 {
868     return m_length == string.length() && 
869            (m_hash == string.m_hash || !m_hash || !string.m_hash) &&
870            0 == ::memcmp(string.constData(), m_data, m_length * sizeof(QChar));
871 }
872
873 bool QHashedStringRef::operator==(const QHashedStringRef &string) const
874 {
875     return m_length == string.m_length && 
876            (m_hash == string.m_hash || !m_hash || !string.m_hash) &&
877            0 == ::memcmp(string.m_data, m_data, m_length * sizeof(QChar));
878 }
879
880 const QChar *QHashedStringRef::constData() const
881 {
882     return m_data;
883 }
884
885 int QHashedStringRef::length() const
886 {
887     return m_length;
888 }
889
890 bool QHashedStringRef::startsWithUpper() const
891 {
892     if (m_length < 1) return false;
893     return QHashedString::isUpper(m_data[0]);
894 }
895
896 quint32 QHashedStringRef::hash() const
897
898     if (!m_hash) computeHash();
899     return m_hash;
900 }
901
902 QHashedCStringRef::QHashedCStringRef()
903 : m_data(0), m_length(0), m_hash(0)
904 {
905 }
906
907 QHashedCStringRef::QHashedCStringRef(const char *data, int length)
908 : m_data(data), m_length(length), m_hash(0)
909 {
910 }
911
912 QHashedCStringRef::QHashedCStringRef(const char *data, int length, quint32 hash)
913 : m_data(data), m_length(length), m_hash(hash)
914 {
915 }
916
917 QHashedCStringRef::QHashedCStringRef(const QHashedCStringRef &o)
918 : m_data(o.m_data), m_length(o.m_length), m_hash(o.m_hash)
919 {
920 }
921
922 quint32 QHashedCStringRef::hash() const
923 {
924     if (!m_hash) computeHash();
925     return m_hash;
926 }
927
928 const char *QHashedCStringRef::constData() const
929 {
930     return m_data;
931 }
932
933 int QHashedCStringRef::length() const
934 {
935     return m_length;
936 }
937
938
939 QT_END_NAMESPACE
940
941 #endif // QHASHEDSTRING_P_H