00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #ifndef QMAP_H
00043 #define QMAP_H
00044
00045 #include <QtCore/qatomic.h>
00046 #include <QtCore/qiterator.h>
00047 #include <QtCore/qlist.h>
00048
00049 #ifndef QT_NO_STL
00050 #include <map>
00051 #endif
00052
00053 #include <new>
00054
00055 QT_BEGIN_HEADER
00056
00057 QT_BEGIN_NAMESPACE
00058
00059 QT_MODULE(Core)
00060
00061 struct Q_CORE_EXPORT QMapData
00062 {
00063 struct Node {
00064 Node *backward;
00065 Node *forward[1];
00066 };
00067 enum { LastLevel = 11, Sparseness = 3 };
00068
00069 QMapData *backward;
00070 QMapData *forward[QMapData::LastLevel + 1];
00071 QBasicAtomicInt ref;
00072 int topLevel;
00073 int size;
00074 uint randomBits;
00075 uint insertInOrder : 1;
00076 uint sharable : 1;
00077 uint strictAlignment : 1;
00078 uint reserved : 29;
00079
00080 static QMapData *createData();
00081 static QMapData *createData(int alignment);
00082 void continueFreeData(int offset);
00083 Node *node_create(Node *update[], int offset);
00084 Node *node_create(Node *update[], int offset, int alignment);
00085 void node_delete(Node *update[], int offset, Node *node);
00086 #ifdef QT_QMAP_DEBUG
00087 uint adjust_ptr(Node *node);
00088 void dump();
00089 #endif
00090
00091 static QMapData shared_null;
00092 };
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 template <class Key> inline bool qMapLessThanKey(const Key &key1, const Key &key2)
00106 {
00107 return key1 < key2;
00108 }
00109
00110 #ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION
00111 template <class Ptr> inline bool qMapLessThanKey(Ptr *key1, Ptr *key2)
00112 {
00113 Q_ASSERT(sizeof(quintptr) == sizeof(Ptr *));
00114 return quintptr(key1) < quintptr(key2);
00115 }
00116
00117 template <class Ptr> inline bool qMapLessThanKey(const Ptr *key1, const Ptr *key2)
00118 {
00119 Q_ASSERT(sizeof(quintptr) == sizeof(const Ptr *));
00120 return quintptr(key1) < quintptr(key2);
00121 }
00122 #endif // QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION
00123
00124 template <class Key, class T>
00125 struct QMapNode {
00126 Key key;
00127 T value;
00128
00129 private:
00130
00131
00132 QMapData::Node *backward;
00133 QMapData::Node *forward[1];
00134 };
00135
00136 template <class Key, class T>
00137 struct QMapPayloadNode
00138 {
00139 Key key;
00140 T value;
00141
00142 private:
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 QMapData::Node *backward;
00158 };
00159
00160 template <class Key, class T>
00161 class QMap
00162 {
00163 typedef QMapNode<Key, T> Node;
00164 typedef QMapPayloadNode<Key, T> PayloadNode;
00165
00166 union {
00167 QMapData *d;
00168 QMapData::Node *e;
00169 };
00170
00171 static inline int payload() { return sizeof(PayloadNode) - sizeof(QMapData::Node *); }
00172 static inline int alignment() {
00173 #ifdef Q_ALIGNOF
00174 return int(qMax(sizeof(void*), Q_ALIGNOF(Node)));
00175 #else
00176 return 0;
00177 #endif
00178 }
00179 static inline Node *concrete(QMapData::Node *node) {
00180 return reinterpret_cast<Node *>(reinterpret_cast<char *>(node) - payload());
00181 }
00182
00183 public:
00184 inline QMap() : d(&QMapData::shared_null) { d->ref.ref(); }
00185 inline QMap(const QMap<Key, T> &other) : d(other.d)
00186 { d->ref.ref(); if (!d->sharable) detach(); }
00187 inline ~QMap() { if (!d) return; if (!d->ref.deref()) freeData(d); }
00188
00189 QMap<Key, T> &operator=(const QMap<Key, T> &other);
00190 #ifndef QT_NO_STL
00191 explicit QMap(const typename std::map<Key, T> &other);
00192 std::map<Key, T> toStdMap() const;
00193 #endif
00194
00195 bool operator==(const QMap<Key, T> &other) const;
00196 inline bool operator!=(const QMap<Key, T> &other) const { return !(*this == other); }
00197
00198 inline int size() const { return d->size; }
00199
00200 inline bool isEmpty() const { return d->size == 0; }
00201
00202 inline void detach() { if (d->ref != 1) detach_helper(); }
00203 inline bool isDetached() const { return d->ref == 1; }
00204 inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; }
00205 inline bool isSharedWith(const QMap<Key, T> &other) const { return d == other.d; }
00206 inline void setInsertInOrder(bool ordered) { d->insertInOrder = ordered; }
00207
00208 void clear();
00209
00210 int remove(const Key &key);
00211 T take(const Key &key);
00212
00213 bool contains(const Key &key) const;
00214 const Key key(const T &value) const;
00215 const Key key(const T &value, const Key &defaultKey) const;
00216 const T value(const Key &key) const;
00217 const T value(const Key &key, const T &defaultValue) const;
00218 T &operator[](const Key &key);
00219 const T operator[](const Key &key) const;
00220
00221 QList<Key> uniqueKeys() const;
00222 QList<Key> keys() const;
00223 QList<Key> keys(const T &value) const;
00224 QList<T> values() const;
00225 QList<T> values(const Key &key) const;
00226 int count(const Key &key) const;
00227
00228 class const_iterator;
00229
00230 class iterator
00231 {
00232 friend class const_iterator;
00233 QMapData::Node *i;
00234
00235 public:
00236 typedef std::bidirectional_iterator_tag iterator_category;
00237 typedef qptrdiff difference_type;
00238 typedef T value_type;
00239 typedef T *pointer;
00240 typedef T &reference;
00241
00242
00243 inline operator QMapData::Node *() const { return i; }
00244 inline iterator() : i(0) { }
00245 inline iterator(QMapData::Node *node) : i(node) { }
00246
00247 inline const Key &key() const { return concrete(i)->key; }
00248 inline T &value() const { return concrete(i)->value; }
00249 #ifdef QT3_SUPPORT
00250 inline QT3_SUPPORT T &data() const { return concrete(i)->value; }
00251 #endif
00252 inline T &operator*() const { return concrete(i)->value; }
00253 inline T *operator->() const { return &concrete(i)->value; }
00254 inline bool operator==(const iterator &o) const { return i == o.i; }
00255 inline bool operator!=(const iterator &o) const { return i != o.i; }
00256
00257 inline iterator &operator++() {
00258 i = i->forward[0];
00259 return *this;
00260 }
00261 inline iterator operator++(int) {
00262 iterator r = *this;
00263 i = i->forward[0];
00264 return r;
00265 }
00266 inline iterator &operator--() {
00267 i = i->backward;
00268 return *this;
00269 }
00270 inline iterator operator--(int) {
00271 iterator r = *this;
00272 i = i->backward;
00273 return r;
00274 }
00275 inline iterator operator+(int j) const
00276 { iterator r = *this; if (j > 0) while (j--) ++r; else while (j++) --r; return r; }
00277 inline iterator operator-(int j) const { return operator+(-j); }
00278 inline iterator &operator+=(int j) { return *this = *this + j; }
00279 inline iterator &operator-=(int j) { return *this = *this - j; }
00280
00281
00282 #ifdef QT_STRICT_ITERATORS
00283 private:
00284 #else
00285 public:
00286 #endif
00287 inline bool operator==(const const_iterator &o) const
00288 { return i == o.i; }
00289 inline bool operator!=(const const_iterator &o) const
00290 { return i != o.i; }
00291
00292 private:
00293
00294 inline operator bool() const { return false; }
00295 };
00296 friend class iterator;
00297
00298 class const_iterator
00299 {
00300 friend class iterator;
00301 QMapData::Node *i;
00302
00303 public:
00304 typedef std::bidirectional_iterator_tag iterator_category;
00305 typedef qptrdiff difference_type;
00306 typedef T value_type;
00307 typedef const T *pointer;
00308 typedef const T &reference;
00309
00310
00311 inline operator QMapData::Node *() const { return i; }
00312 inline const_iterator() : i(0) { }
00313 inline const_iterator(QMapData::Node *node) : i(node) { }
00314 #ifdef QT_STRICT_ITERATORS
00315 explicit inline const_iterator(const iterator &o)
00316 #else
00317 inline const_iterator(const iterator &o)
00318 #endif
00319 { i = o.i; }
00320
00321 inline const Key &key() const { return concrete(i)->key; }
00322 inline const T &value() const { return concrete(i)->value; }
00323 #ifdef QT3_SUPPORT
00324 inline QT3_SUPPORT const T &data() const { return concrete(i)->value; }
00325 #endif
00326 inline const T &operator*() const { return concrete(i)->value; }
00327 inline const T *operator->() const { return &concrete(i)->value; }
00328 inline bool operator==(const const_iterator &o) const { return i == o.i; }
00329 inline bool operator!=(const const_iterator &o) const { return i != o.i; }
00330
00331 inline const_iterator &operator++() {
00332 i = i->forward[0];
00333 return *this;
00334 }
00335 inline const_iterator operator++(int) {
00336 const_iterator r = *this;
00337 i = i->forward[0];
00338 return r;
00339 }
00340 inline const_iterator &operator--() {
00341 i = i->backward;
00342 return *this;
00343 }
00344 inline const_iterator operator--(int) {
00345 const_iterator r = *this;
00346 i = i->backward;
00347 return r;
00348 }
00349 inline const_iterator operator+(int j) const
00350 { const_iterator r = *this; if (j > 0) while (j--) ++r; else while (j++) --r; return r; }
00351 inline const_iterator operator-(int j) const { return operator+(-j); }
00352 inline const_iterator &operator+=(int j) { return *this = *this + j; }
00353 inline const_iterator &operator-=(int j) { return *this = *this - j; }
00354
00355
00356 #ifdef QT_STRICT_ITERATORS
00357 private:
00358 inline bool operator==(const iterator &o) { return operator==(const_iterator(o)); }
00359 inline bool operator!=(const iterator &o) { return operator!=(const_iterator(o)); }
00360 #endif
00361
00362 private:
00363
00364 inline operator bool() const { return false; }
00365 };
00366 friend class const_iterator;
00367
00368
00369 inline iterator begin() { detach(); return iterator(e->forward[0]); }
00370 inline const_iterator begin() const { return const_iterator(e->forward[0]); }
00371 inline const_iterator constBegin() const { return const_iterator(e->forward[0]); }
00372 inline iterator end() {
00373 detach();
00374 return iterator(e);
00375 }
00376 inline const_iterator end() const { return const_iterator(e); }
00377 inline const_iterator constEnd() const { return const_iterator(e); }
00378 iterator erase(iterator it);
00379 #ifdef QT3_SUPPORT
00380 inline QT3_SUPPORT iterator remove(iterator it) { return erase(it); }
00381 inline QT3_SUPPORT void erase(const Key &aKey) { remove(aKey); }
00382 #endif
00383
00384
00385 typedef iterator Iterator;
00386 typedef const_iterator ConstIterator;
00387 inline int count() const { return d->size; }
00388 iterator find(const Key &key);
00389 const_iterator find(const Key &key) const;
00390 const_iterator constFind(const Key &key) const;
00391 iterator lowerBound(const Key &key);
00392 const_iterator lowerBound(const Key &key) const;
00393 iterator upperBound(const Key &key);
00394 const_iterator upperBound(const Key &key) const;
00395 iterator insert(const Key &key, const T &value);
00396 #ifdef QT3_SUPPORT
00397 QT3_SUPPORT iterator insert(const Key &key, const T &value, bool overwrite);
00398 #endif
00399 iterator insertMulti(const Key &key, const T &value);
00400 #ifdef QT3_SUPPORT
00401 inline QT3_SUPPORT iterator replace(const Key &aKey, const T &aValue) { return insert(aKey, aValue); }
00402 #endif
00403 QMap<Key, T> &unite(const QMap<Key, T> &other);
00404
00405
00406 typedef Key key_type;
00407 typedef T mapped_type;
00408 typedef qptrdiff difference_type;
00409 typedef int size_type;
00410 inline bool empty() const { return isEmpty(); }
00411
00412 #ifdef QT_QMAP_DEBUG
00413 inline void dump() const { d->dump(); }
00414 #endif
00415
00416 private:
00417 void detach_helper();
00418 void freeData(QMapData *d);
00419 QMapData::Node *findNode(const Key &key) const;
00420 QMapData::Node *mutableFindNode(QMapData::Node *update[], const Key &key) const;
00421 QMapData::Node *node_create(QMapData *d, QMapData::Node *update[], const Key &key,
00422 const T &value);
00423 };
00424
00425 template <class Key, class T>
00426 Q_INLINE_TEMPLATE QMap<Key, T> &QMap<Key, T>::operator=(const QMap<Key, T> &other)
00427 {
00428 if (d != other.d) {
00429 QMapData* o = other.d;
00430 o->ref.ref();
00431 if (!d->ref.deref())
00432 freeData(d);
00433 d = o;
00434 if (!d->sharable)
00435 detach_helper();
00436 }
00437 return *this;
00438 }
00439
00440 template <class Key, class T>
00441 Q_INLINE_TEMPLATE void QMap<Key, T>::clear()
00442 {
00443 *this = QMap<Key, T>();
00444 }
00445
00446 template <class Key, class T>
00447 Q_INLINE_TEMPLATE typename QMapData::Node *
00448 QMap<Key, T>::node_create(QMapData *adt, QMapData::Node *aupdate[], const Key &akey, const T &avalue)
00449 {
00450 QMapData::Node *abstractNode = adt->node_create(aupdate, payload(), alignment());
00451 QT_TRY {
00452 Node *concreteNode = concrete(abstractNode);
00453 new (&concreteNode->key) Key(akey);
00454 QT_TRY {
00455 new (&concreteNode->value) T(avalue);
00456 } QT_CATCH(...) {
00457 concreteNode->key.~Key();
00458 QT_RETHROW;
00459 }
00460 } QT_CATCH(...) {
00461 adt->node_delete(aupdate, payload(), abstractNode);
00462 QT_RETHROW;
00463 }
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474 return abstractNode;
00475 }
00476
00477 template <class Key, class T>
00478 Q_INLINE_TEMPLATE QMapData::Node *QMap<Key, T>::findNode(const Key &akey) const
00479 {
00480 QMapData::Node *cur = e;
00481 QMapData::Node *next = e;
00482
00483 for (int i = d->topLevel; i >= 0; i--) {
00484 while ((next = cur->forward[i]) != e && qMapLessThanKey<Key>(concrete(next)->key, akey))
00485 cur = next;
00486 }
00487
00488 if (next != e && !qMapLessThanKey<Key>(akey, concrete(next)->key)) {
00489 return next;
00490 } else {
00491 return e;
00492 }
00493 }
00494
00495 template <class Key, class T>
00496 Q_INLINE_TEMPLATE const T QMap<Key, T>::value(const Key &akey) const
00497 {
00498 QMapData::Node *node;
00499 if (d->size == 0 || (node = findNode(akey)) == e) {
00500 return T();
00501 } else {
00502 return concrete(node)->value;
00503 }
00504 }
00505
00506 template <class Key, class T>
00507 Q_INLINE_TEMPLATE const T QMap<Key, T>::value(const Key &akey, const T &adefaultValue) const
00508 {
00509 QMapData::Node *node;
00510 if (d->size == 0 || (node = findNode(akey)) == e) {
00511 return adefaultValue;
00512 } else {
00513 return concrete(node)->value;
00514 }
00515 }
00516
00517 template <class Key, class T>
00518 Q_INLINE_TEMPLATE const T QMap<Key, T>::operator[](const Key &akey) const
00519 {
00520 return value(akey);
00521 }
00522
00523 template <class Key, class T>
00524 Q_INLINE_TEMPLATE T &QMap<Key, T>::operator[](const Key &akey)
00525 {
00526 detach();
00527
00528 QMapData::Node *update[QMapData::LastLevel + 1];
00529 QMapData::Node *node = mutableFindNode(update, akey);
00530 if (node == e)
00531 node = node_create(d, update, akey, T());
00532 return concrete(node)->value;
00533 }
00534
00535 template <class Key, class T>
00536 Q_INLINE_TEMPLATE int QMap<Key, T>::count(const Key &akey) const
00537 {
00538 int cnt = 0;
00539 QMapData::Node *node = findNode(akey);
00540 if (node != e) {
00541 do {
00542 ++cnt;
00543 node = node->forward[0];
00544 } while (node != e && !qMapLessThanKey<Key>(akey, concrete(node)->key));
00545 }
00546 return cnt;
00547 }
00548
00549 template <class Key, class T>
00550 Q_INLINE_TEMPLATE bool QMap<Key, T>::contains(const Key &akey) const
00551 {
00552 return findNode(akey) != e;
00553 }
00554
00555 template <class Key, class T>
00556 Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::insert(const Key &akey,
00557 const T &avalue)
00558 {
00559 detach();
00560
00561 QMapData::Node *update[QMapData::LastLevel + 1];
00562 QMapData::Node *node = mutableFindNode(update, akey);
00563 if (node == e) {
00564 node = node_create(d, update, akey, avalue);
00565 } else {
00566 concrete(node)->value = avalue;
00567 }
00568 return iterator(node);
00569 }
00570
00571 #ifdef QT3_SUPPORT
00572 template <class Key, class T>
00573 Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::insert(const Key &akey,
00574 const T &avalue,
00575 bool aoverwrite)
00576 {
00577 detach();
00578
00579 QMapData::Node *update[QMapData::LastLevel + 1];
00580 QMapData::Node *node = mutableFindNode(update, akey);
00581 if (node == e) {
00582 node = node_create(d, update, akey, avalue);
00583 } else {
00584 if (aoverwrite)
00585 concrete(node)->value = avalue;
00586 }
00587 return iterator(node);
00588 }
00589 #endif
00590
00591 template <class Key, class T>
00592 Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::insertMulti(const Key &akey,
00593 const T &avalue)
00594 {
00595 detach();
00596
00597 QMapData::Node *update[QMapData::LastLevel + 1];
00598 mutableFindNode(update, akey);
00599 return iterator(node_create(d, update, akey, avalue));
00600 }
00601
00602 template <class Key, class T>
00603 Q_INLINE_TEMPLATE typename QMap<Key, T>::const_iterator QMap<Key, T>::find(const Key &akey) const
00604 {
00605 return const_iterator(findNode(akey));
00606 }
00607
00608 template <class Key, class T>
00609 Q_INLINE_TEMPLATE typename QMap<Key, T>::const_iterator QMap<Key, T>::constFind(const Key &akey) const
00610 {
00611 return const_iterator(findNode(akey));
00612 }
00613
00614 template <class Key, class T>
00615 Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::find(const Key &akey)
00616 {
00617 detach();
00618 return iterator(findNode(akey));
00619 }
00620
00621 template <class Key, class T>
00622 Q_INLINE_TEMPLATE QMap<Key, T> &QMap<Key, T>::unite(const QMap<Key, T> &other)
00623 {
00624 QMap<Key, T> copy(other);
00625 const_iterator it = copy.constEnd();
00626 const const_iterator b = copy.constBegin();
00627 while (it != b) {
00628 --it;
00629 insertMulti(it.key(), it.value());
00630 }
00631 return *this;
00632 }
00633
00634 template <class Key, class T>
00635 Q_OUTOFLINE_TEMPLATE void QMap<Key, T>::freeData(QMapData *x)
00636 {
00637 if (QTypeInfo<Key>::isComplex || QTypeInfo<T>::isComplex) {
00638 QMapData *cur = x;
00639 QMapData *next = cur->forward[0];
00640 while (next != x) {
00641 cur = next;
00642 next = cur->forward[0];
00643 #if defined(_MSC_VER) && (_MSC_VER >= 1300)
00644 #pragma warning(disable:4189)
00645 #endif
00646 Node *concreteNode = concrete(reinterpret_cast<QMapData::Node *>(cur));
00647 concreteNode->key.~Key();
00648 concreteNode->value.~T();
00649 #if defined(_MSC_VER) && (_MSC_VER >= 1300)
00650 #pragma warning(default:4189)
00651 #endif
00652 }
00653 }
00654 x->continueFreeData(payload());
00655 }
00656
00657 template <class Key, class T>
00658 Q_OUTOFLINE_TEMPLATE int QMap<Key, T>::remove(const Key &akey)
00659 {
00660 detach();
00661
00662 QMapData::Node *update[QMapData::LastLevel + 1];
00663 QMapData::Node *cur = e;
00664 QMapData::Node *next = e;
00665 int oldSize = d->size;
00666
00667 for (int i = d->topLevel; i >= 0; i--) {
00668 while ((next = cur->forward[i]) != e && qMapLessThanKey<Key>(concrete(next)->key, akey))
00669 cur = next;
00670 update[i] = cur;
00671 }
00672
00673 if (next != e && !qMapLessThanKey<Key>(akey, concrete(next)->key)) {
00674 bool deleteNext = true;
00675 do {
00676 cur = next;
00677 next = cur->forward[0];
00678 deleteNext = (next != e && !qMapLessThanKey<Key>(concrete(cur)->key, concrete(next)->key));
00679 concrete(cur)->key.~Key();
00680 concrete(cur)->value.~T();
00681 d->node_delete(update, payload(), cur);
00682 } while (deleteNext);
00683 }
00684 return oldSize - d->size;
00685 }
00686
00687 template <class Key, class T>
00688 Q_OUTOFLINE_TEMPLATE T QMap<Key, T>::take(const Key &akey)
00689 {
00690 detach();
00691
00692 QMapData::Node *update[QMapData::LastLevel + 1];
00693 QMapData::Node *cur = e;
00694 QMapData::Node *next = e;
00695
00696 for (int i = d->topLevel; i >= 0; i--) {
00697 while ((next = cur->forward[i]) != e && qMapLessThanKey<Key>(concrete(next)->key, akey))
00698 cur = next;
00699 update[i] = cur;
00700 }
00701
00702 if (next != e && !qMapLessThanKey<Key>(akey, concrete(next)->key)) {
00703 T t = concrete(next)->value;
00704 concrete(next)->key.~Key();
00705 concrete(next)->value.~T();
00706 d->node_delete(update, payload(), next);
00707 return t;
00708 }
00709 return T();
00710 }
00711
00712 template <class Key, class T>
00713 Q_OUTOFLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::erase(iterator it)
00714 {
00715 QMapData::Node *update[QMapData::LastLevel + 1];
00716 QMapData::Node *cur = e;
00717 QMapData::Node *next = e;
00718
00719 if (it == iterator(e))
00720 return it;
00721
00722 for (int i = d->topLevel; i >= 0; i--) {
00723 while ((next = cur->forward[i]) != e && qMapLessThanKey<Key>(concrete(next)->key, it.key()))
00724 cur = next;
00725 update[i] = cur;
00726 }
00727
00728 while (next != e) {
00729 cur = next;
00730 next = cur->forward[0];
00731 if (cur == it) {
00732 concrete(cur)->key.~Key();
00733 concrete(cur)->value.~T();
00734 d->node_delete(update, payload(), cur);
00735 return iterator(next);
00736 }
00737
00738 for (int i = 0; i <= d->topLevel; ++i) {
00739 if (update[i]->forward[i] != cur)
00740 break;
00741 update[i] = cur;
00742 }
00743 }
00744 return end();
00745 }
00746
00747 template <class Key, class T>
00748 Q_OUTOFLINE_TEMPLATE void QMap<Key, T>::detach_helper()
00749 {
00750 union { QMapData *d; QMapData::Node *e; } x;
00751 x.d = QMapData::createData(alignment());
00752 if (d->size) {
00753 x.d->insertInOrder = true;
00754 QMapData::Node *update[QMapData::LastLevel + 1];
00755 QMapData::Node *cur = e->forward[0];
00756 update[0] = x.e;
00757 while (cur != e) {
00758 QT_TRY {
00759 Node *concreteNode = concrete(cur);
00760 node_create(x.d, update, concreteNode->key, concreteNode->value);
00761 } QT_CATCH(...) {
00762 freeData(x.d);
00763 QT_RETHROW;
00764 }
00765 cur = cur->forward[0];
00766 }
00767 x.d->insertInOrder = false;
00768 }
00769 if (!d->ref.deref())
00770 freeData(d);
00771 d = x.d;
00772 }
00773
00774 template <class Key, class T>
00775 Q_OUTOFLINE_TEMPLATE QMapData::Node *QMap<Key, T>::mutableFindNode(QMapData::Node *aupdate[],
00776 const Key &akey) const
00777 {
00778 QMapData::Node *cur = e;
00779 QMapData::Node *next = e;
00780
00781 for (int i = d->topLevel; i >= 0; i--) {
00782 while ((next = cur->forward[i]) != e && qMapLessThanKey<Key>(concrete(next)->key, akey))
00783 cur = next;
00784 aupdate[i] = cur;
00785 }
00786 if (next != e && !qMapLessThanKey<Key>(akey, concrete(next)->key)) {
00787 return next;
00788 } else {
00789 return e;
00790 }
00791 }
00792
00793 template <class Key, class T>
00794 Q_OUTOFLINE_TEMPLATE QList<Key> QMap<Key, T>::uniqueKeys() const
00795 {
00796 QList<Key> res;
00797 res.reserve(size());
00798 const_iterator i = begin();
00799 if (i != end()) {
00800 for (;;) {
00801 const Key &aKey = i.key();
00802 res.append(aKey);
00803 do {
00804 if (++i == end())
00805 goto break_out_of_outer_loop;
00806 } while (!(aKey < i.key()));
00807 }
00808 }
00809 break_out_of_outer_loop:
00810 return res;
00811 }
00812
00813 template <class Key, class T>
00814 Q_OUTOFLINE_TEMPLATE QList<Key> QMap<Key, T>::keys() const
00815 {
00816 QList<Key> res;
00817 res.reserve(size());
00818 const_iterator i = begin();
00819 while (i != end()) {
00820 res.append(i.key());
00821 ++i;
00822 }
00823 return res;
00824 }
00825
00826 template <class Key, class T>
00827 Q_OUTOFLINE_TEMPLATE QList<Key> QMap<Key, T>::keys(const T &avalue) const
00828 {
00829 QList<Key> res;
00830 const_iterator i = begin();
00831 while (i != end()) {
00832 if (i.value() == avalue)
00833 res.append(i.key());
00834 ++i;
00835 }
00836 return res;
00837 }
00838
00839 template <class Key, class T>
00840 Q_OUTOFLINE_TEMPLATE const Key QMap<Key, T>::key(const T &avalue) const
00841 {
00842 return key(avalue, Key());
00843 }
00844
00845 template <class Key, class T>
00846 Q_OUTOFLINE_TEMPLATE const Key QMap<Key, T>::key(const T &avalue, const Key &defaultKey) const
00847 {
00848 const_iterator i = begin();
00849 while (i != end()) {
00850 if (i.value() == avalue)
00851 return i.key();
00852 ++i;
00853 }
00854
00855 return defaultKey;
00856 }
00857
00858 template <class Key, class T>
00859 Q_OUTOFLINE_TEMPLATE QList<T> QMap<Key, T>::values() const
00860 {
00861 QList<T> res;
00862 res.reserve(size());
00863 const_iterator i = begin();
00864 while (i != end()) {
00865 res.append(i.value());
00866 ++i;
00867 }
00868 return res;
00869 }
00870
00871 template <class Key, class T>
00872 Q_OUTOFLINE_TEMPLATE QList<T> QMap<Key, T>::values(const Key &akey) const
00873 {
00874 QList<T> res;
00875 QMapData::Node *node = findNode(akey);
00876 if (node != e) {
00877 do {
00878 res.append(concrete(node)->value);
00879 node = node->forward[0];
00880 } while (node != e && !qMapLessThanKey<Key>(akey, concrete(node)->key));
00881 }
00882 return res;
00883 }
00884
00885 template <class Key, class T>
00886 Q_INLINE_TEMPLATE typename QMap<Key, T>::const_iterator
00887 QMap<Key, T>::lowerBound(const Key &akey) const
00888 {
00889 QMapData::Node *update[QMapData::LastLevel + 1];
00890 mutableFindNode(update, akey);
00891 return const_iterator(update[0]->forward[0]);
00892 }
00893
00894 template <class Key, class T>
00895 Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::lowerBound(const Key &akey)
00896 {
00897 detach();
00898 return static_cast<QMapData::Node *>(const_cast<const QMap *>(this)->lowerBound(akey));
00899 }
00900
00901 template <class Key, class T>
00902 Q_INLINE_TEMPLATE typename QMap<Key, T>::const_iterator
00903 QMap<Key, T>::upperBound(const Key &akey) const
00904 {
00905 QMapData::Node *update[QMapData::LastLevel + 1];
00906 mutableFindNode(update, akey);
00907 QMapData::Node *node = update[0]->forward[0];
00908 while (node != e && !qMapLessThanKey<Key>(akey, concrete(node)->key))
00909 node = node->forward[0];
00910 return const_iterator(node);
00911 }
00912
00913 template <class Key, class T>
00914 Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::upperBound(const Key &akey)
00915 {
00916 detach();
00917 return static_cast<QMapData::Node *>(const_cast<const QMap *>(this)->upperBound(akey));
00918 }
00919
00920 template <class Key, class T>
00921 Q_OUTOFLINE_TEMPLATE bool QMap<Key, T>::operator==(const QMap<Key, T> &other) const
00922 {
00923 if (size() != other.size())
00924 return false;
00925 if (d == other.d)
00926 return true;
00927
00928 const_iterator it1 = begin();
00929 const_iterator it2 = other.begin();
00930
00931 while (it1 != end()) {
00932 if (!(it1.value() == it2.value()) || qMapLessThanKey(it1.key(), it2.key()) || qMapLessThanKey(it2.key(), it1.key()))
00933 return false;
00934 ++it2;
00935 ++it1;
00936 }
00937 return true;
00938 }
00939
00940 #ifndef QT_NO_STL
00941 template <class Key, class T>
00942 Q_OUTOFLINE_TEMPLATE QMap<Key, T>::QMap(const std::map<Key, T> &other)
00943 {
00944 d = QMapData::createData(alignment());
00945 d->insertInOrder = true;
00946 typename std::map<Key,T>::const_iterator it = other.end();
00947 while (it != other.begin()) {
00948 --it;
00949 insert((*it).first, (*it).second);
00950 }
00951 d->insertInOrder = false;
00952 }
00953
00954 template <class Key, class T>
00955 Q_OUTOFLINE_TEMPLATE std::map<Key, T> QMap<Key, T>::toStdMap() const
00956 {
00957 std::map<Key, T> map;
00958 const_iterator it = end();
00959 while (it != begin()) {
00960 --it;
00961 map.insert(std::pair<Key, T>(it.key(), it.value()));
00962 }
00963 return map;
00964 }
00965
00966 #endif // QT_NO_STL
00967
00968 template <class Key, class T>
00969 class QMultiMap : public QMap<Key, T>
00970 {
00971 public:
00972 QMultiMap() {}
00973 QMultiMap(const QMap<Key, T> &other) : QMap<Key, T>(other) {}
00974
00975 inline typename QMap<Key, T>::iterator replace(const Key &key, const T &value)
00976 { return QMap<Key, T>::insert(key, value); }
00977 inline typename QMap<Key, T>::iterator insert(const Key &key, const T &value)
00978 { return QMap<Key, T>::insertMulti(key, value); }
00979
00980 inline QMultiMap &operator+=(const QMultiMap &other)
00981 { this->unite(other); return *this; }
00982 inline QMultiMap operator+(const QMultiMap &other) const
00983 { QMultiMap result = *this; result += other; return result; }
00984
00985 #if !defined(Q_NO_USING_KEYWORD) && !defined(Q_CC_RVCT)
00986
00987 using QMap<Key, T>::contains;
00988 using QMap<Key, T>::remove;
00989 using QMap<Key, T>::count;
00990 using QMap<Key, T>::find;
00991 using QMap<Key, T>::constFind;
00992 #else
00993 inline bool contains(const Key &key) const
00994 { return QMap<Key, T>::contains(key); }
00995 inline int remove(const Key &key)
00996 { return QMap<Key, T>::remove(key); }
00997 inline int count(const Key &key) const
00998 { return QMap<Key, T>::count(key); }
00999 inline int count() const
01000 { return QMap<Key, T>::count(); }
01001 inline typename QMap<Key, T>::iterator find(const Key &key)
01002 { return QMap<Key, T>::find(key); }
01003 inline typename QMap<Key, T>::const_iterator find(const Key &key) const
01004 { return QMap<Key, T>::find(key); }
01005 inline typename QMap<Key, T>::const_iterator constFind(const Key &key) const
01006 { return QMap<Key, T>::constFind(key); }
01007 #endif
01008
01009 bool contains(const Key &key, const T &value) const;
01010
01011 int remove(const Key &key, const T &value);
01012
01013 int count(const Key &key, const T &value) const;
01014
01015 typename QMap<Key, T>::iterator find(const Key &key, const T &value) {
01016 typename QMap<Key, T>::iterator i(find(key));
01017 typename QMap<Key, T>::iterator end(this->end());
01018 while (i != end && !qMapLessThanKey<Key>(key, i.key())) {
01019 if (i.value() == value)
01020 return i;
01021 ++i;
01022 }
01023 return end;
01024 }
01025 typename QMap<Key, T>::const_iterator find(const Key &key, const T &value) const {
01026 typename QMap<Key, T>::const_iterator i(constFind(key));
01027 typename QMap<Key, T>::const_iterator end(QMap<Key, T>::constEnd());
01028 while (i != end && !qMapLessThanKey<Key>(key, i.key())) {
01029 if (i.value() == value)
01030 return i;
01031 ++i;
01032 }
01033 return end;
01034 }
01035 typename QMap<Key, T>::const_iterator constFind(const Key &key, const T &value) const
01036 { return find(key, value); }
01037 private:
01038 T &operator[](const Key &key);
01039 const T operator[](const Key &key) const;
01040 };
01041
01042 template <class Key, class T>
01043 Q_INLINE_TEMPLATE bool QMultiMap<Key, T>::contains(const Key &key, const T &value) const
01044 {
01045 return constFind(key, value) != QMap<Key, T>::constEnd();
01046 }
01047
01048 template <class Key, class T>
01049 Q_INLINE_TEMPLATE int QMultiMap<Key, T>::remove(const Key &key, const T &value)
01050 {
01051 int n = 0;
01052 typename QMap<Key, T>::iterator i(find(key));
01053 typename QMap<Key, T>::iterator end(QMap<Key, T>::end());
01054 while (i != end && !qMapLessThanKey<Key>(key, i.key())) {
01055 if (i.value() == value) {
01056 i = this->erase(i);
01057 ++n;
01058 } else {
01059 ++i;
01060 }
01061 }
01062 return n;
01063 }
01064
01065 template <class Key, class T>
01066 Q_INLINE_TEMPLATE int QMultiMap<Key, T>::count(const Key &key, const T &value) const
01067 {
01068 int n = 0;
01069 typename QMap<Key, T>::const_iterator i(constFind(key));
01070 typename QMap<Key, T>::const_iterator end(QMap<Key, T>::constEnd());
01071 while (i != end && !qMapLessThanKey<Key>(key, i.key())) {
01072 if (i.value() == value)
01073 ++n;
01074 ++i;
01075 }
01076 return n;
01077 }
01078
01079 Q_DECLARE_ASSOCIATIVE_ITERATOR(Map)
01080 Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(Map)
01081
01082 QT_END_NAMESPACE
01083
01084 QT_END_HEADER
01085
01086 #endif // QMAP_H