Fix for UBSan build
[platform/upstream/doxygen.git] / qtools / qmap.h
1 /****************************************************************************
2 ** 
3 **
4 ** Definition of QMap class
5 **
6 ** Created : 990406
7 **
8 ** Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
9 **
10 ** This file is part of the tools module of the Qt GUI Toolkit.
11 **
12 ** This file may be distributed under the terms of the Q Public License
13 ** as defined by Trolltech AS of Norway and appearing in the file
14 ** LICENSE.QPL included in the packaging of this file.
15 **
16 ** This file may be distributed and/or modified under the terms of the
17 ** GNU General Public License version 2 as published by the Free Software
18 ** Foundation and appearing in the file LICENSE.GPL included in the
19 ** packaging of this file.
20 **
21 ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22 ** licenses may use this file in accordance with the Qt Commercial License
23 ** Agreement provided with the Software.
24 **
25 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27 **
28 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29 **   information about Qt Commercial License Agreements.
30 ** See http://www.trolltech.com/qpl/ for QPL licensing information.
31 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
32 **
33 ** Contact info@trolltech.com if any conditions of this licensing are
34 ** not clear to you.
35 **
36 **********************************************************************/
37
38 #ifndef QMAP_H
39 #define QMAP_H
40
41 #ifndef QT_H
42 #include "qshared.h"
43 #include "qdatastream.h"
44 #endif // QT_H
45
46
47 struct QMapNodeBase
48 {
49     enum Color { Red, Black };
50
51     QMapNodeBase* left;
52     QMapNodeBase* right;
53     QMapNodeBase* parent;
54
55     Color color;
56
57     QMapNodeBase* minimum() {
58         QMapNodeBase* x = this;
59         while ( x->left )
60             x = x->left;
61         return x;
62     }
63
64     QMapNodeBase* maximum() {
65         QMapNodeBase* x = this;
66         while ( x->right )
67             x = x->right;
68         return x;
69     }
70 };
71
72
73 template <class K, class T>
74 struct QMapNode : public QMapNodeBase
75 {
76     QMapNode( const K& _key, const T& _data ) { data = _data; key = _key; }
77     QMapNode( const K& _key )      { key = _key; }
78     QMapNode( const QMapNode<K,T>& _n ) { key = _n.key; data = _n.data; }
79     QMapNode() { }
80     T data;
81     K key;
82 };
83
84
85 template<class K, class T>
86 class Q_EXPORT QMapIterator
87 {
88  public:
89     /**
90      * Typedefs
91      */
92     typedef QMapNode< K, T >* NodePtr;
93
94     /**
95      * Variables
96      */
97     QMapNode<K,T>* node;
98
99     /**
100      * Functions
101      */
102     QMapIterator() : node( 0 ) {}
103     QMapIterator( QMapNode<K,T>* p ) : node( p ) {}
104     QMapIterator( const QMapIterator<K,T>& it ) : node( it.node ) {}
105
106     bool operator==( const QMapIterator<K,T>& it ) const { return node == it.node; }
107     bool operator!=( const QMapIterator<K,T>& it ) const { return node != it.node; }
108     T& operator*() { return node->data; }
109     const T& operator*() const { return node->data; }
110
111     // Cannot have this - some compilers are too stupid
112     //T* operator->() const { return &(node->data); }
113
114     const K& key() const { return node->key; }
115     T& data() { return node->data; }
116     const T& data() const { return node->data; }
117
118 private:
119     int inc() {
120         QMapNodeBase* tmp = node;
121         if ( tmp->right ) {
122             tmp = tmp->right;
123             while ( tmp->left )
124                 tmp = tmp->left;
125         } else {
126             QMapNodeBase* y = tmp->parent;
127             while (tmp == y->right) {
128                 tmp = y;
129                 y = y->parent;
130             }
131             if (tmp->right != y)
132                 tmp = y;
133         }
134         node = (NodePtr)tmp;
135         return 0;
136     }
137
138     int dec() {
139         QMapNodeBase* tmp = node;
140         if (tmp->color == QMapNodeBase::Red &&
141             tmp->parent->parent == tmp ) {
142             tmp = tmp->right;
143         } else if (tmp->left != 0) {
144             QMapNodeBase* y = tmp->left;
145             while ( y->right )
146                 y = y->right;
147             tmp = y;
148         } else {
149             QMapNodeBase* y = tmp->parent;
150             while (tmp == y->left) {
151                 tmp = y;
152                 y = y->parent;
153             }
154             tmp = y;
155         }
156         node = (NodePtr)tmp;
157         return 0;
158     }
159
160 public:
161     QMapIterator<K,T>& operator++() {
162         inc();
163         return *this;
164     }
165
166     QMapIterator<K,T> operator++(int) {
167         QMapIterator<K,T> tmp = *this;
168         inc();
169         return tmp;
170     }
171
172     QMapIterator<K,T>& operator--() {
173         dec();
174         return *this;
175     }
176
177     QMapIterator<K,T> operator--(int) {
178         QMapIterator<K,T> tmp = *this;
179         dec();
180         return tmp;
181     }
182 };
183
184 template<class K, class T>
185 class Q_EXPORT QMapConstIterator
186 {
187  public:
188     /**
189      * Typedefs
190      */
191     typedef QMapNode< K, T >* NodePtr;
192
193     /**
194      * Variables
195      */
196     QMapNode<K,T>* node;
197
198     /**
199      * Functions
200      */
201     QMapConstIterator() : node( 0 ) {}
202     QMapConstIterator( QMapNode<K,T>* p ) : node( p ) {}
203     QMapConstIterator( const QMapConstIterator<K,T>& it ) : node( it.node ) {}
204     QMapConstIterator( const QMapIterator<K,T>& it ) : node( it.node ) {}
205
206     bool operator==( const QMapConstIterator<K,T>& it ) const { return node == it.node; }
207     bool operator!=( const QMapConstIterator<K,T>& it ) const { return node != it.node; }
208     const T& operator*()  const { return node->data; }
209
210     // Cannot have this - some compilers are too stupid
211     //const T* operator->() const { return &(node->data); }
212
213     const K& key() const { return node->key; }
214     const T& data() const { return node->data; }
215
216 private:
217     int inc() {
218         QMapNodeBase* tmp = node;
219         if ( tmp->right ) {
220             tmp = tmp->right;
221             while ( tmp->left )
222                 tmp = tmp->left;
223         } else {
224             QMapNodeBase* y = tmp->parent;
225             while (tmp == y->right) {
226                 tmp = y;
227                 y = y->parent;
228             }
229             if (tmp->right != y)
230                 tmp = y;
231         }
232         node = (NodePtr)tmp;
233         return 0;
234     }
235
236     int dec() {
237         QMapNodeBase* tmp = node;
238         if (tmp->color == QMapNodeBase::Red &&
239             tmp->parent->parent == tmp ) {
240             tmp = tmp->right;
241         } else if (tmp->left != 0) {
242             QMapNodeBase* y = tmp->left;
243             while ( y->right )
244                 y = y->right;
245             tmp = y;
246         } else {
247             QMapNodeBase* y = tmp->parent;
248             while (tmp == y->left) {
249                 tmp = y;
250                 y = y->parent;
251             }
252             tmp = y;
253         }
254         node = (NodePtr)tmp;
255         return 0;
256     }
257
258 public:
259     QMapConstIterator<K,T>& operator++() {
260         inc();
261         return *this;
262     }
263
264     QMapConstIterator<K,T> operator++(int) {
265         QMapConstIterator<K,T> tmp = *this;
266         inc();
267         return tmp;
268     }
269
270     QMapConstIterator<K,T>& operator--() {
271         dec();
272         return *this;
273     }
274
275     QMapConstIterator<K,T> operator--(int) {
276         QMapConstIterator<K,T> tmp = *this;
277         dec();
278         return tmp;
279     }
280 };
281
282
283 class Q_EXPORT QMapPrivateBase : public QShared
284 {
285 public:
286     QMapPrivateBase() {
287         node_count = 0;
288     }
289     QMapPrivateBase( const QMapPrivateBase* _map) {
290         node_count = _map->node_count;
291     }
292
293     /**
294      * Implementations of basic tree algorithms
295      */
296     void rotateLeft( QMapNodeBase* x, QMapNodeBase*& root);
297     void rotateRight( QMapNodeBase* x, QMapNodeBase*& root );
298     void rebalance( QMapNodeBase* x, QMapNodeBase*& root );
299     QMapNodeBase* removeAndRebalance( QMapNodeBase* z, QMapNodeBase*& root,
300                                       QMapNodeBase*& leftmost,
301                                       QMapNodeBase*& rightmost );
302
303     /**
304      * Variables
305      */
306     int node_count;
307 };
308
309
310 template <class Key, class T>
311 class QMapPrivate : public QMapPrivateBase
312 {
313 public:
314     /**
315      * Typedefs
316      */
317     typedef QMapIterator< Key, T > Iterator;
318     typedef QMapConstIterator< Key, T > ConstIterator;
319     typedef QMapNode< Key, T > Node;
320     typedef QMapNode< Key, T >* NodePtr;
321
322     /**
323      * Functions
324      */
325     QMapPrivate() {
326         header = new Node;
327         header->color = QMapNodeBase::Red; // Mark the header
328         header->parent = 0;
329         header->left = header->right = header;
330     }
331     QMapPrivate( const QMapPrivate< Key, T >* _map ) : QMapPrivateBase( _map ) {
332         header = new Node;
333         header->color = QMapNodeBase::Red; // Mark the header
334         if ( _map->header->parent == 0 ) {
335             header->parent = 0;
336             header->left = header->right = header;
337         } else {
338             header->parent = copy( (NodePtr)(_map->header->parent) );
339             header->parent->parent = header;
340             header->left = header->parent->minimum();
341             header->right = header->parent->maximum();
342         }
343     }
344     ~QMapPrivate() { clear(); delete header; }
345
346     NodePtr copy( NodePtr p ) {
347         if ( !p )
348             return 0;
349         NodePtr n = new Node( *p );
350         n->color = p->color;
351         if ( p->left ) {
352             n->left = copy( (NodePtr)(p->left) );
353             n->left->parent = n;
354         } else {
355             n->left = 0;
356         }
357         if ( p->right ) {
358             n->right = copy( (NodePtr)(p->right) );
359             n->right->parent = n;
360         } else {
361             n->right = 0;
362         }
363         return n;
364     }
365
366     void clear() {
367         clear( (NodePtr)(header->parent) );
368         header->color = QMapNodeBase::Red;
369         header->parent = 0;
370         header->left = header->right = header;
371         node_count = 0;
372     }
373
374     void clear( NodePtr p ) {
375         while ( p != 0 ) {
376             clear( (NodePtr)p->right );
377             NodePtr y = (NodePtr)p->left;
378             delete p;
379             p = y;
380         }
381     }
382
383     Iterator begin()    { return Iterator( (NodePtr)(header->left ) ); }
384     Iterator end()      { return Iterator( header ); }
385     ConstIterator begin() const { return ConstIterator( (NodePtr)(header->left ) ); }
386     ConstIterator end() const { return ConstIterator( header ); }
387
388     ConstIterator find(const Key& k) const {
389         QMapNodeBase* y = header;        // Last node
390         QMapNodeBase* x = header->parent; // Root node.
391
392         while ( x != 0 ) {
393             // If as k <= key(x) go left
394             if ( !( key(x) < k ) ) {
395                 y = x;
396                 x = x->left;
397             } else {
398                 x = x->right;
399             }
400         }
401
402         // Was k bigger/smaller then the biggest/smallest
403         // element of the tree ? Return end()
404         if ( y == header || k < key(y) )
405             return ConstIterator( header );
406         return ConstIterator( (NodePtr)y );
407     }
408
409     void remove( Iterator it ) {
410         NodePtr del = (NodePtr) removeAndRebalance( it.node, header->parent, header->left, header->right );
411         delete del;
412         --node_count;
413     }
414
415 #ifdef QT_QMAP_DEBUG
416     void inorder( QMapNodeBase* x = 0, int level = 0 ){
417         if ( !x )
418             x = header->parent;
419         if ( x->left )
420             inorder( x->left, level + 1 );
421     //cout << level << " Key=" << key(x) << " Value=" << ((NodePtr)x)->data << endl;
422         if ( x->right )
423             inorder( x->right, level + 1 );
424     }
425 #endif
426
427     Iterator insertMulti(const Key& v){
428         QMapNodeBase* y = header;
429         QMapNodeBase* x = header->parent;
430         while (x != 0){
431             y = x;
432             x = ( v < key(x) ) ? x->left : x->right;
433         }
434         return insert(x, y, v);
435     }
436
437     Iterator insertSingle( const Key& k ) {
438         // Search correct position in the tree
439         QMapNodeBase* y = header;
440         QMapNodeBase* x = header->parent;
441         bool result = TRUE;
442         while ( x != 0 ) {
443             result = ( k < key(x) );
444             y = x;
445             x = result ? x->left : x->right;
446         }
447         // Get iterator on the last not empty one
448         Iterator j( (NodePtr)y );
449         if ( result ) {
450             // Smaller then the leftmost one ?
451             if ( j == begin() ) {
452                 return insert(x, y, k );
453             } else {
454                 // Perhaps daddy is the right one ?
455                 --j;
456             }
457         }
458         // Really bigger ?
459         if ( (j.node->key) < k )
460             return insert(x, y, k );
461         // We are going to replace a node
462         return j;
463     }
464
465     Iterator insert( QMapNodeBase* x, QMapNodeBase* y, const Key& k ) {
466         NodePtr z = new Node( k );
467         if (y == header || x != 0 || k < key(y) ) {
468             y->left = z;                // also makes leftmost = z when y == header
469             if ( y == header ) {
470                 header->parent = z;
471                 header->right = z;
472             } else if ( y == header->left )
473                 header->left = z;           // maintain leftmost pointing to min node
474         } else {
475             y->right = z;
476             if ( y == header->right )
477                 header->right = z;          // maintain rightmost pointing to max node
478         }
479         z->parent = y;
480         z->left = 0;
481         z->right = 0;
482         rebalance( z, header->parent );
483         ++node_count;
484         return Iterator(z);
485     }
486
487 protected:
488     /**
489      * Helpers
490      */
491     const Key& key( QMapNodeBase* b ) const { return ((NodePtr)b)->key; }
492
493     /**
494      * Variables
495      */
496     NodePtr header;
497 };
498
499
500 template<class Key, class T>
501 class Q_EXPORT QMap
502 {
503 public:
504     /**
505      * Typedefs
506      */
507     typedef QMapIterator< Key, T > Iterator;
508     typedef QMapConstIterator< Key, T > ConstIterator;
509     typedef T ValueType;
510     typedef QMapPrivate< Key, T > Priv;
511
512     /**
513      * API
514      */
515     QMap() { sh = new QMapPrivate< Key, T >; }
516     QMap( const QMap<Key,T>& m ) { sh = m.sh; sh->ref(); }
517     ~QMap() { if ( sh->deref() ) delete sh; }
518
519     QMap<Key,T>& operator= ( const QMap<Key,T>& m )
520       { m.sh->ref(); if ( sh->deref() ) delete sh; sh = m.sh; return *this; }
521
522     Iterator begin() { detach(); return sh->begin(); }
523     Iterator end() { detach(); return sh->end(); }
524     ConstIterator begin() const { return ((const Priv*)sh)->begin(); }
525     ConstIterator end() const { return ((const Priv*)sh)->end(); }
526
527     Iterator find ( const Key& k )
528         { detach(); return Iterator( sh->find( k ).node ); }
529     ConstIterator find ( const Key& k ) const
530         { return sh->find( k ); }
531     T& operator[] ( const Key& k ) {
532         detach(); QMapNode<Key,T>* p = sh->find( k ).node;
533         if ( p != sh->end().node ) return p->data;
534         return insert( k, T() ).data(); }
535     const T& operator[] ( const Key& k ) const
536         { return sh->find( k ).data(); }
537     bool contains ( const Key& k ) const
538         { return find( k ) != end(); }
539         //{ return sh->find( k ) != ((const Priv*)sh)->end(); }
540
541     uint count() const { return sh->node_count; }
542
543     bool isEmpty() const { return sh->node_count == 0; }
544
545     Iterator insert( const Key& key, const T& value ) {
546         detach();
547         Iterator it = sh->insertSingle( key );
548         it.data() = value;
549         return it;
550     }
551
552     void remove( Iterator it ) { detach(); sh->remove( it ); }
553     void remove( const Key& k ) {
554         detach();
555         Iterator it( sh->find( k ).node );
556         if ( it != end() )
557             sh->remove( it );
558     }
559
560     Iterator replace( const Key& k, const T& v ) {
561         remove( k );
562         return insert( k, v );
563     }
564
565     void clear() { if ( sh->count == 1 ) sh->clear(); else { sh->deref(); sh = new QMapPrivate<Key,T>; } }
566
567 #if defined(Q_FULL_TEMPLATE_INSTANTIATION)
568     bool operator==( const QMap<Key,T>& ) const { return FALSE; }
569 #endif
570
571 protected:
572     /**
573      * Helpers
574      */
575     void detach() { if ( sh->count > 1 ) { sh->deref(); sh = new QMapPrivate<Key,T>( sh ); } }
576
577     Priv* sh;
578 };
579
580
581 #ifndef QT_NO_DATASTREAM
582 template<class Key, class T>
583 inline QDataStream& operator>>( QDataStream& s, QMap<Key,T>& m ) {
584     m.clear();
585     Q_UINT32 c;
586     s >> c;
587     for( Q_UINT32 i = 0; i < c; ++i ) {
588         Key k; T t;
589         s >> k >> t;
590         m.insert( k, t );
591     }
592     return s;
593 }
594
595
596 template<class Key, class T>
597 inline QDataStream& operator<<( QDataStream& s, const QMap<Key,T>& m ) {
598     s << (Q_UINT32)m.count();
599     QMapConstIterator<Key,T> it = m.begin();
600     for( ; it != m.end(); ++it )
601         s << it.key() << it.data();
602     return s;
603 }
604 #endif
605
606 #endif // QMAP_H