1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtCore module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
45 #include <QtCore/qiterator.h>
46 #include <QtCore/qlist.h>
47 #include <QtCore/qrefcount.h>
48 #include <QtCore/qpair.h>
51 #include <QtCore/qdebug.h>
62 QMap uses qMapLessThanKey() to compare keys. The default
63 implementation uses operator<(). For pointer types,
64 qMapLessThanKey() casts the pointers to integers before it
65 compares them, because operator<() is undefined on pointers
66 that come from different memory blocks. (In practice, this
67 is only a problem when running a program such as
71 template <class Key> inline bool qMapLessThanKey(const Key &key1, const Key &key2)
76 template <class Ptr> inline bool qMapLessThanKey(const Ptr *key1, const Ptr *key2)
78 Q_STATIC_ASSERT(sizeof(quintptr) == sizeof(const Ptr *));
79 return quintptr(key1) < quintptr(key2);
83 template <class Key, class T> struct QMapData;
85 struct Q_CORE_EXPORT QMapNodeBase
91 enum Color { Red = 0, Black = 1 };
92 enum { Mask = 3 }; // reserve the second bit as well
94 const QMapNodeBase *nextNode() const;
95 QMapNodeBase *nextNode() { return const_cast<QMapNodeBase *>(const_cast<const QMapNodeBase *>(this)->nextNode()); }
96 const QMapNodeBase *previousNode() const;
97 QMapNodeBase *previousNode() { return const_cast<QMapNodeBase *>(const_cast<const QMapNodeBase *>(this)->previousNode()); }
99 Color color() const { return Color(p & 1); }
100 void setColor(Color c) { if (c == Black) p |= Black; else p &= ~Black; }
101 QMapNodeBase *parent() const { return reinterpret_cast<QMapNodeBase *>(p & ~Mask); }
102 void setParent(QMapNodeBase *pp) { p = (p & Mask) | quintptr(pp); }
104 QMapNodeBase *minimumNode() { QMapNodeBase *n = this; while (n->left) n = n->left; return n; }
105 QMapNodeBase *maximumNode() { QMapNodeBase *n = this; while (n->right) n = n->right; return n; }
106 const QMapNodeBase *minimumNode() const { const QMapNodeBase *n = this; while (n->left) n = n->left; return n; }
107 const QMapNodeBase *maximumNode() const { const QMapNodeBase *n = this; while (n->right) n = n->right; return n; }
110 template <class Key, class T>
111 struct QMapNode : public QMapNodeBase
116 inline QMapNode *leftNode() const { return static_cast<QMapNode *>(left); }
117 inline QMapNode *rightNode() const { return static_cast<QMapNode *>(right); }
119 inline const QMapNode *nextNode() const { return static_cast<const QMapNode *>(QMapNodeBase::nextNode()); }
120 inline const QMapNode *previousNode() const { return static_cast<const QMapNode *>(QMapNodeBase::previousNode()); }
121 inline QMapNode *nextNode() { return static_cast<QMapNode *>(QMapNodeBase::nextNode()); }
122 inline QMapNode *previousNode() { return static_cast<QMapNode *>(QMapNodeBase::previousNode()); }
124 QMapNode *minimumNode() { return static_cast<QMapNode *>(QMapNodeBase::minimumNode()); }
125 QMapNode *maximumNode() { return static_cast<QMapNode *>(QMapNodeBase::maximumNode()); }
126 const QMapNode *minimumNode() const { return static_cast<QMapNode *>(QMapNodeBase::minimumNode()); }
127 const QMapNode *maximumNode() const { return static_cast<QMapNode *>(QMapNodeBase::maximumNode()); }
129 QMapNode<Key, T> *copy(QMapData<Key, T> *d) const;
131 void destroySubTree();
133 QMapNode<Key, T> *lowerBound(const Key &key);
134 QMapNode<Key, T> *upperBound(const Key &key);
137 QMapNode() Q_DECL_EQ_DELETE;
138 Q_DISABLE_COPY(QMapNode)
141 template <class Key, class T>
142 inline QMapNode<Key, T> *QMapNode<Key, T>::lowerBound(const Key &akey)
144 QMapNode<Key, T> *n = this;
145 QMapNode<Key, T> *last = 0;
147 if (!qMapLessThanKey(n->key, akey)) {
157 template <class Key, class T>
158 inline QMapNode<Key, T> *QMapNode<Key, T>::upperBound(const Key &akey)
160 QMapNode<Key, T> *n = this;
161 QMapNode<Key, T> *last = 0;
163 if (qMapLessThanKey(akey, n->key)) {
175 struct Q_CORE_EXPORT QMapDataBase
177 QtPrivate::RefCount ref;
181 void rotateLeft(QMapNodeBase *x);
182 void rotateRight(QMapNodeBase *x);
183 void rebalance(QMapNodeBase *x);
184 void freeNodeAndRebalance(QMapNodeBase *z);
186 QMapNodeBase *createNode(int size, int alignment, QMapNodeBase *parent, bool left);
187 void freeTree(QMapNodeBase *root, int alignment);
189 static const QMapDataBase shared_null;
191 static QMapDataBase *createData();
192 static void freeData(QMapDataBase *d);
195 template <class Key, class T>
196 struct QMapData : public QMapDataBase
198 typedef QMapNode<Key, T> Node;
200 Node *root() const { return static_cast<Node *>(header.left); }
202 const Node *end() const { return static_cast<const Node *>(&header); }
203 Node *end() { return static_cast<Node *>(&header); }
204 const Node *begin() const { if (root()) return root()->minimumNode(); return end(); }
205 Node *begin() { if (root()) return root()->minimumNode(); return end(); }
207 void deleteNode(Node *z);
208 Node *findNode(const Key &akey) const;
209 void nodeRange(const Key &akey, Node **first, Node **last);
211 Node *createNode(const Key &k, const T &v, Node *parent = 0, bool left = false)
213 Node *n = static_cast<Node *>(QMapDataBase::createNode(sizeof(Node), Q_ALIGNOF(Node),
216 new (&n->key) Key(k);
218 new (&n->value) T(v);
224 QMapDataBase::freeNodeAndRebalance(n);
230 static QMapData *create() {
231 return static_cast<QMapData *>(createData());
236 root()->destroySubTree();
237 freeTree(header.left, Q_ALIGNOF(Node));
243 template <class Key, class T>
244 QMapNode<Key, T> *QMapNode<Key, T>::copy(QMapData<Key, T> *d) const
246 QMapNode<Key, T> *n = d->createNode(key, value);
247 n->setColor(color());
249 n->left = leftNode()->copy(d);
250 n->left->setParent(n);
255 n->right = rightNode()->copy(d);
256 n->right->setParent(n);
263 template <class Key, class T>
264 void QMapNode<Key, T>::destroySubTree()
266 if (QTypeInfo<Key>::isComplex)
268 if (QTypeInfo<T>::isComplex)
270 if (QTypeInfo<Key>::isComplex || QTypeInfo<T>::isComplex) {
272 leftNode()->destroySubTree();
274 rightNode()->destroySubTree();
278 template <class Key, class T>
279 void QMapData<Key, T>::deleteNode(QMapNode<Key, T> *z)
281 if (QTypeInfo<Key>::isComplex)
283 if (QTypeInfo<T>::isComplex)
285 freeNodeAndRebalance(z);
288 template <class Key, class T>
289 QMapNode<Key, T> *QMapData<Key, T>::findNode(const Key &akey) const
291 Node *lb = root()->lowerBound(akey);
292 if (lb && !qMapLessThanKey(akey, lb->key))
298 template <class Key, class T>
299 void QMapData<Key, T>::nodeRange(const Key &akey, QMapNode<Key, T> **first, QMapNode<Key, T> **last)
304 if (qMapLessThanKey(akey, n->key)) {
307 } else if (qMapLessThanKey(n->key, akey)) {
310 *first = n->leftNode()->lowerBound(akey);
313 *last = n->rightNode()->upperBound(akey);
323 template <class Key, class T>
326 typedef QMapNode<Key, T> Node;
331 inline QMap() : d(static_cast<QMapData<Key, T> *>(const_cast<QMapDataBase *>(&QMapDataBase::shared_null))) { }
332 QMap(const QMap<Key, T> &other);
334 inline ~QMap() { if (!d->ref.deref()) d->free(); }
336 QMap<Key, T> &operator=(const QMap<Key, T> &other);
337 #ifdef Q_COMPILER_RVALUE_REFS
338 inline QMap(QMap<Key, T> &&other)
341 other.d = static_cast<QMapData<Key, T> *>(
342 const_cast<QMapDataBase *>(&QMapDataBase::shared_null));
345 inline QMap<Key, T> &operator=(QMap<Key, T> &&other)
346 { qSwap(d, other.d); return *this; }
348 inline void swap(QMap<Key, T> &other) { qSwap(d, other.d); }
349 explicit QMap(const typename std::map<Key, T> &other);
350 std::map<Key, T> toStdMap() const;
352 bool operator==(const QMap<Key, T> &other) const;
353 inline bool operator!=(const QMap<Key, T> &other) const { return !(*this == other); }
355 inline int size() const { return d->size; }
357 inline bool isEmpty() const { return d->size == 0; }
359 inline void detach() { if (d->ref.isShared()) detach_helper(); }
360 inline bool isDetached() const { return !d->ref.isShared(); }
361 inline void setSharable(bool sharable)
363 if (sharable == d->ref.isSharable())
367 // Don't call on shared_null
368 d->ref.setSharable(sharable);
370 inline bool isSharedWith(const QMap<Key, T> &other) const { return d == other.d; }
374 int remove(const Key &key);
375 T take(const Key &key);
377 bool contains(const Key &key) const;
378 const Key key(const T &value, const Key &defaultKey = Key()) const;
379 const T value(const Key &key, const T &defaultValue = T()) const;
380 T &operator[](const Key &key);
381 const T operator[](const Key &key) const;
383 QList<Key> uniqueKeys() const;
384 QList<Key> keys() const;
385 QList<Key> keys(const T &value) const;
386 QList<T> values() const;
387 QList<T> values(const Key &key) const;
388 int count(const Key &key) const;
390 class const_iterator;
394 friend class const_iterator;
398 typedef std::bidirectional_iterator_tag iterator_category;
399 typedef qptrdiff difference_type;
400 typedef T value_type;
402 typedef T &reference;
404 inline iterator() : i(0) { }
405 inline iterator(Node *node) : i(node) { }
407 inline const Key &key() const { return i->key; }
408 inline T &value() const { return i->value; }
409 inline T &operator*() const { return i->value; }
410 inline T *operator->() const { return &i->value; }
411 inline bool operator==(const iterator &o) const { return i == o.i; }
412 inline bool operator!=(const iterator &o) const { return i != o.i; }
414 inline iterator &operator++() {
418 inline iterator operator++(int) {
423 inline iterator &operator--() {
424 i = i->previousNode();
427 inline iterator operator--(int) {
429 i = i->previousNode();
432 inline iterator operator+(int j) const
433 { iterator r = *this; if (j > 0) while (j--) ++r; else while (j++) --r; return r; }
434 inline iterator operator-(int j) const { return operator+(-j); }
435 inline iterator &operator+=(int j) { return *this = *this + j; }
436 inline iterator &operator-=(int j) { return *this = *this - j; }
438 #ifdef QT_STRICT_ITERATORS
443 inline bool operator==(const const_iterator &o) const
445 inline bool operator!=(const const_iterator &o) const
447 friend class QMap<Key, T>;
449 friend class iterator;
453 friend class iterator;
457 typedef std::bidirectional_iterator_tag iterator_category;
458 typedef qptrdiff difference_type;
459 typedef T value_type;
460 typedef const T *pointer;
461 typedef const T &reference;
463 inline const_iterator() : i(0) { }
464 inline const_iterator(const Node *node) : i(node) { }
465 #ifdef QT_STRICT_ITERATORS
466 explicit inline const_iterator(const iterator &o)
468 inline const_iterator(const iterator &o)
472 inline const Key &key() const { return i->key; }
473 inline const T &value() const { return i->value; }
474 inline const T &operator*() const { return i->value; }
475 inline const T *operator->() const { return &i->value; }
476 inline bool operator==(const const_iterator &o) const { return i == o.i; }
477 inline bool operator!=(const const_iterator &o) const { return i != o.i; }
479 inline const_iterator &operator++() {
483 inline const_iterator operator++(int) {
484 const_iterator r = *this;
488 inline const_iterator &operator--() {
489 i = i->previousNode();
492 inline const_iterator operator--(int) {
493 const_iterator r = *this;
494 i = i->previousNode();
497 inline const_iterator operator+(int j) const
498 { const_iterator r = *this; if (j > 0) while (j--) ++r; else while (j++) --r; return r; }
499 inline const_iterator operator-(int j) const { return operator+(-j); }
500 inline const_iterator &operator+=(int j) { return *this = *this + j; }
501 inline const_iterator &operator-=(int j) { return *this = *this - j; }
503 #ifdef QT_STRICT_ITERATORS
505 inline bool operator==(const iterator &o) const { return operator==(const_iterator(o)); }
506 inline bool operator!=(const iterator &o) const { return operator!=(const_iterator(o)); }
508 friend class QMap<Key, T>;
510 friend class const_iterator;
513 inline iterator begin() { detach(); return iterator(d->begin()); }
514 inline const_iterator begin() const { return const_iterator(d->begin()); }
515 inline const_iterator constBegin() const { return const_iterator(d->begin()); }
516 inline const_iterator cbegin() const { return const_iterator(d->begin()); }
517 inline iterator end() { detach(); return iterator(d->end()); }
518 inline const_iterator end() const { return const_iterator(d->end()); }
519 inline const_iterator constEnd() const { return const_iterator(d->end()); }
520 inline const_iterator cend() const { return const_iterator(d->end()); }
521 iterator erase(iterator it);
524 typedef iterator Iterator;
525 typedef const_iterator ConstIterator;
526 inline int count() const { return d->size; }
527 iterator find(const Key &key);
528 const_iterator find(const Key &key) const;
529 const_iterator constFind(const Key &key) const;
530 iterator lowerBound(const Key &key);
531 const_iterator lowerBound(const Key &key) const;
532 iterator upperBound(const Key &key);
533 const_iterator upperBound(const Key &key) const;
534 iterator insert(const Key &key, const T &value);
535 iterator insertMulti(const Key &key, const T &value);
536 QMap<Key, T> &unite(const QMap<Key, T> &other);
539 typedef Key key_type;
540 typedef T mapped_type;
541 typedef qptrdiff difference_type;
542 typedef int size_type;
543 inline bool empty() const { return isEmpty(); }
544 QPair<iterator, iterator> equal_range(const Key &akey);
551 void detach_helper();
554 template <class Key, class T>
555 inline QMap<Key, T>::QMap(const QMap<Key, T> &other)
557 if (other.d->ref.ref()) {
560 d = QMapData<Key, T>::create();
561 if (other.d->header.left) {
562 d->header.left = static_cast<Node *>(other.d->header.left)->copy(d);
563 d->header.left->setParent(&d->header);
568 template <class Key, class T>
569 Q_INLINE_TEMPLATE QMap<Key, T> &QMap<Key, T>::operator=(const QMap<Key, T> &other)
572 QMap<Key, T> tmp(other);
578 template <class Key, class T>
579 Q_INLINE_TEMPLATE void QMap<Key, T>::clear()
581 *this = QMap<Key, T>();
585 template <class Key, class T>
586 Q_INLINE_TEMPLATE const T QMap<Key, T>::value(const Key &akey, const T &adefaultValue) const
588 Node *n = d->findNode(akey);
589 return n ? n->value : adefaultValue;
592 template <class Key, class T>
593 Q_INLINE_TEMPLATE const T QMap<Key, T>::operator[](const Key &akey) const
598 template <class Key, class T>
599 Q_INLINE_TEMPLATE T &QMap<Key, T>::operator[](const Key &akey)
602 Node *n = d->findNode(akey);
604 return *insert(akey, T());
608 template <class Key, class T>
609 Q_INLINE_TEMPLATE int QMap<Key, T>::count(const Key &akey) const
613 d->nodeRange(akey, &firstNode, &lastNode);
615 const_iterator first(firstNode);
616 const const_iterator last(lastNode);
618 while (first != last) {
625 template <class Key, class T>
626 Q_INLINE_TEMPLATE bool QMap<Key, T>::contains(const Key &akey) const
628 return d->findNode(akey) != 0;
631 template <class Key, class T>
632 Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::insert(const Key &akey, const T &avalue)
641 if (!qMapLessThanKey(n->key, akey)) {
650 if (last && !qMapLessThanKey(akey, last->key)) {
651 last->value = avalue;
652 return iterator(last);
654 Node *z = d->createNode(akey, avalue, y, left);
658 template <class Key, class T>
659 Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::insertMulti(const Key &akey,
664 Node* x = static_cast<Node *>(d->root());
667 left = !qMapLessThanKey(x->key, akey);
669 x = left ? x->leftNode() : x->rightNode();
671 Node *z = d->createNode(akey, avalue, y, left);
675 template <class Key, class T>
676 Q_INLINE_TEMPLATE typename QMap<Key, T>::const_iterator QMap<Key, T>::constFind(const Key &akey) const
678 Node *n = d->findNode(akey);
679 return const_iterator(n ? n : d->end());
682 template <class Key, class T>
683 Q_INLINE_TEMPLATE typename QMap<Key, T>::const_iterator QMap<Key, T>::find(const Key &akey) const
685 return constFind(akey);
688 template <class Key, class T>
689 Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::find(const Key &akey)
692 Node *n = d->findNode(akey);
693 return iterator(n ? n : d->end());
696 template <class Key, class T>
697 Q_INLINE_TEMPLATE QMap<Key, T> &QMap<Key, T>::unite(const QMap<Key, T> &other)
699 QMap<Key, T> copy(other);
700 const_iterator it = copy.constEnd();
701 const const_iterator b = copy.constBegin();
704 insertMulti(it.key(), it.value());
709 template <class Key, class T>
710 QPair<typename QMap<Key, T>::iterator, typename QMap<Key, T>::iterator> QMap<Key, T>::equal_range(const Key &akey)
714 d->nodeRange(akey, &first, &last);
715 return QPair<iterator, iterator>(iterator(first), iterator(last));
719 template <class Key, class T>
720 void QMap<Key, T>::dump() const
722 const_iterator it = begin();
723 qDebug() << "map dump:";
724 while (it != end()) {
725 const QMapNodeBase *n = it.i;
727 while (n && n != d->root()) {
731 QByteArray space(4*depth, ' ');
732 qDebug() << space << (it.i->color() == Node::Red ? "Red " : "Black") << it.i << it.i->left << it.i->right
733 << it.key() << it.value();
736 qDebug() << "---------";
740 template <class Key, class T>
741 Q_OUTOFLINE_TEMPLATE int QMap<Key, T>::remove(const Key &akey)
745 while (Node *node = d->findNode(akey)) {
752 template <class Key, class T>
753 Q_OUTOFLINE_TEMPLATE T QMap<Key, T>::take(const Key &akey)
757 Node *node = d->findNode(akey);
766 template <class Key, class T>
767 Q_OUTOFLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::erase(iterator it)
769 if (it == iterator(d->end()))
778 template <class Key, class T>
779 Q_OUTOFLINE_TEMPLATE void QMap<Key, T>::detach_helper()
781 QMapData<Key, T> *x = QMapData<Key, T>::create();
782 if (d->header.left) {
783 x->header.left = static_cast<Node *>(d->header.left)->copy(x);
784 x->header.left->setParent(&x->header);
791 template <class Key, class T>
792 Q_OUTOFLINE_TEMPLATE QList<Key> QMap<Key, T>::uniqueKeys() const
795 res.reserve(size()); // May be too much, but assume short lifetime
796 const_iterator i = begin();
799 const Key &aKey = i.key();
803 goto break_out_of_outer_loop;
804 } while (!qMapLessThanKey(aKey, i.key())); // loop while (key == i.key())
807 break_out_of_outer_loop:
811 template <class Key, class T>
812 Q_OUTOFLINE_TEMPLATE QList<Key> QMap<Key, T>::keys() const
816 const_iterator i = begin();
824 template <class Key, class T>
825 Q_OUTOFLINE_TEMPLATE QList<Key> QMap<Key, T>::keys(const T &avalue) const
828 const_iterator i = begin();
830 if (i.value() == avalue)
837 template <class Key, class T>
838 Q_OUTOFLINE_TEMPLATE const Key QMap<Key, T>::key(const T &avalue, const Key &defaultKey) const
840 const_iterator i = begin();
842 if (i.value() == avalue)
850 template <class Key, class T>
851 Q_OUTOFLINE_TEMPLATE QList<T> QMap<Key, T>::values() const
855 const_iterator i = begin();
857 res.append(i.value());
863 template <class Key, class T>
864 Q_OUTOFLINE_TEMPLATE QList<T> QMap<Key, T>::values(const Key &akey) const
867 Node *n = d->findNode(akey);
869 const_iterator it(n);
873 } while (it != constEnd() && !qMapLessThanKey<Key>(akey, it.key()));
878 template <class Key, class T>
879 Q_INLINE_TEMPLATE typename QMap<Key, T>::const_iterator QMap<Key, T>::lowerBound(const Key &akey) const
881 Node *lb = d->root()->lowerBound(akey);
884 return const_iterator(lb);
887 template <class Key, class T>
888 Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::lowerBound(const Key &akey)
891 Node *lb = d->root()->lowerBound(akey);
897 template <class Key, class T>
898 Q_INLINE_TEMPLATE typename QMap<Key, T>::const_iterator
899 QMap<Key, T>::upperBound(const Key &akey) const
901 Node *ub = d->root()->upperBound(akey);
904 return const_iterator(ub);
907 template <class Key, class T>
908 Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::upperBound(const Key &akey)
911 Node *ub = d->root()->upperBound(akey);
917 template <class Key, class T>
918 Q_OUTOFLINE_TEMPLATE bool QMap<Key, T>::operator==(const QMap<Key, T> &other) const
920 if (size() != other.size())
925 const_iterator it1 = begin();
926 const_iterator it2 = other.begin();
928 while (it1 != end()) {
929 if (!(it1.value() == it2.value()) || qMapLessThanKey(it1.key(), it2.key()) || qMapLessThanKey(it2.key(), it1.key()))
937 template <class Key, class T>
938 Q_OUTOFLINE_TEMPLATE QMap<Key, T>::QMap(const std::map<Key, T> &other)
940 d = QMapData<Key, T>::create();
941 typename std::map<Key,T>::const_iterator it = other.end();
942 while (it != other.begin()) {
944 insert((*it).first, (*it).second);
948 template <class Key, class T>
949 Q_OUTOFLINE_TEMPLATE std::map<Key, T> QMap<Key, T>::toStdMap() const
951 std::map<Key, T> map;
952 const_iterator it = end();
953 while (it != begin()) {
955 map.insert(std::pair<Key, T>(it.key(), it.value()));
960 template <class Key, class T>
961 class QMultiMap : public QMap<Key, T>
965 QMultiMap(const QMap<Key, T> &other) : QMap<Key, T>(other) {}
966 inline void swap(QMultiMap<Key, T> &other) { QMap<Key, T>::swap(other); }
968 inline typename QMap<Key, T>::iterator replace(const Key &key, const T &value)
969 { return QMap<Key, T>::insert(key, value); }
970 inline typename QMap<Key, T>::iterator insert(const Key &key, const T &value)
971 { return QMap<Key, T>::insertMulti(key, value); }
973 inline QMultiMap &operator+=(const QMultiMap &other)
974 { this->unite(other); return *this; }
975 inline QMultiMap operator+(const QMultiMap &other) const
976 { QMultiMap result = *this; result += other; return result; }
978 #if !defined(Q_NO_USING_KEYWORD) && !defined(Q_CC_RVCT)
979 // RVCT compiler doesn't handle using-keyword right when used functions are overloaded in child class
980 using QMap<Key, T>::contains;
981 using QMap<Key, T>::remove;
982 using QMap<Key, T>::count;
983 using QMap<Key, T>::find;
984 using QMap<Key, T>::constFind;
986 inline bool contains(const Key &key) const
987 { return QMap<Key, T>::contains(key); }
988 inline int remove(const Key &key)
989 { return QMap<Key, T>::remove(key); }
990 inline int count(const Key &key) const
991 { return QMap<Key, T>::count(key); }
992 inline int count() const
993 { return QMap<Key, T>::count(); }
994 inline typename QMap<Key, T>::iterator find(const Key &key)
995 { return QMap<Key, T>::find(key); }
996 inline typename QMap<Key, T>::const_iterator find(const Key &key) const
997 { return QMap<Key, T>::find(key); }
998 inline typename QMap<Key, T>::const_iterator constFind(const Key &key) const
999 { return QMap<Key, T>::constFind(key); }
1002 bool contains(const Key &key, const T &value) const;
1004 int remove(const Key &key, const T &value);
1006 int count(const Key &key, const T &value) const;
1008 typename QMap<Key, T>::iterator find(const Key &key, const T &value) {
1009 typename QMap<Key, T>::iterator i(find(key));
1010 typename QMap<Key, T>::iterator end(this->end());
1011 while (i != end && !qMapLessThanKey<Key>(key, i.key())) {
1012 if (i.value() == value)
1018 typename QMap<Key, T>::const_iterator find(const Key &key, const T &value) const {
1019 typename QMap<Key, T>::const_iterator i(constFind(key));
1020 typename QMap<Key, T>::const_iterator end(QMap<Key, T>::constEnd());
1021 while (i != end && !qMapLessThanKey<Key>(key, i.key())) {
1022 if (i.value() == value)
1028 typename QMap<Key, T>::const_iterator constFind(const Key &key, const T &value) const
1029 { return find(key, value); }
1031 T &operator[](const Key &key);
1032 const T operator[](const Key &key) const;
1035 template <class Key, class T>
1036 Q_INLINE_TEMPLATE bool QMultiMap<Key, T>::contains(const Key &key, const T &value) const
1038 return constFind(key, value) != QMap<Key, T>::constEnd();
1041 template <class Key, class T>
1042 Q_INLINE_TEMPLATE int QMultiMap<Key, T>::remove(const Key &key, const T &value)
1045 typename QMap<Key, T>::iterator i(find(key));
1046 typename QMap<Key, T>::iterator end(QMap<Key, T>::end());
1047 while (i != end && !qMapLessThanKey<Key>(key, i.key())) {
1048 if (i.value() == value) {
1058 template <class Key, class T>
1059 Q_INLINE_TEMPLATE int QMultiMap<Key, T>::count(const Key &key, const T &value) const
1062 typename QMap<Key, T>::const_iterator i(constFind(key));
1063 typename QMap<Key, T>::const_iterator end(QMap<Key, T>::constEnd());
1064 while (i != end && !qMapLessThanKey<Key>(key, i.key())) {
1065 if (i.value() == value)
1072 Q_DECLARE_ASSOCIATIVE_ITERATOR(Map)
1073 Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(Map)