1
 
/*      Copyright (C) 2007 Garrett A. Kajmowicz
 
2
 
        This file is part of the uClibc++ Library.
 
4
 
        This library is free software; you can redistribute it and/or
 
5
 
        modify it under the terms of the GNU Lesser General Public
 
6
 
        License as published by the Free Software Foundation; either
 
7
 
        version 2.1 of the License, or (at your option) any later version.
 
9
 
        This library is distributed in the hope that it will be useful,
 
10
 
        but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 
        Lesser General Public License for more details.
 
14
 
        You should have received a copy of the GNU Lesser General Public
 
15
 
        License along with this library; if not, write to the Free Software
 
16
 
        Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
28
 
#ifndef __STD_HEADER_ASSOCIATIVE_BASE
 
29
 
#define __STD_HEADER_ASSOCIATIVE_BASE
 
31
 
#pragma GCC visibility push(default)
 
37
 
 *      The basic premise here is that most of the code used by map, multimap, set and
 
38
 
 *      multiset is really common.  There are a number of interface additions, and
 
39
 
 *      considerations about how to address multiple entries with the same key.
 
40
 
 *      The goal is that the tree/storage code should be here, and managing
 
41
 
 *      single or multiple counts will be left to subclasses.
 
42
 
 *      Yes, inheritence for the purpose of code sharing is usually a bad idea.
 
43
 
 *      However, since our goal is to reduce the total amount of code written
 
44
 
 *      and the overall binary size, this seems to be the best approach possible.
 
47
 
template<class Key, class ValueType, class Compare = less<Key>, class Allocator = allocator<ValueType> > class __base_associative;
 
48
 
template<class ValueType, class Compare, class Allocator> class _associative_iter;
 
49
 
template<class ValueType, class Compare, class Allocator> class _associative_citer;
 
51
 
template<class Key, class ValueType, class Compare = less<Key>, class Allocator = allocator<ValueType> > class __single_associative;
 
52
 
template<class Key, class ValueType, class Compare = less<Key>, class Allocator = allocator<ValueType> > class __multi_associative;
 
54
 
template<class Key, class ValueType, class Compare, class Allocator> class _UCXXEXPORT __base_associative{
 
60
 
        typedef ValueType                                               value_type;
 
61
 
        typedef Compare                                                 key_compare;
 
62
 
        typedef Allocator                                               allocator_type;
 
63
 
        typedef typename Allocator::reference                           reference;
 
64
 
        typedef typename Allocator::const_reference                     const_reference;
 
65
 
        typedef typename Allocator::size_type                           size_type;
 
66
 
        typedef typename Allocator::difference_type                     difference_type;
 
67
 
        typedef typename Allocator::pointer                             pointer;
 
68
 
        typedef typename Allocator::const_pointer                       const_pointer;
 
69
 
        typedef __base_associative<Key, ValueType, Compare, Allocator>  associative_type;
 
71
 
        typedef _associative_iter<value_type, Compare, Allocator>       iterator;
 
72
 
        typedef _associative_citer<value_type, Compare, Allocator>      const_iterator;
 
73
 
        typedef typename std::reverse_iterator<iterator>                reverse_iterator;
 
74
 
        typedef typename std::reverse_iterator<const_iterator>          const_reverse_iterator;
 
77
 
        explicit __base_associative(const Compare& comp, const Allocator& A, const key_type (*v_to_k)(const value_type))
 
78
 
                : c(comp), value_to_key(v_to_k) { }
 
80
 
        __base_associative(const associative_type& x)
 
81
 
                : c(x.c), backing(x.backing), value_to_key(x.value_to_key) { }
 
84
 
        ~__base_associative(){
 
88
 
                return backing.empty();
 
90
 
        size_type size() const{
 
91
 
                return backing.size();
 
93
 
        size_type max_size() const{
 
94
 
                return backing.max_size();
 
98
 
                return iterator(backing.begin());
 
101
 
        const_iterator begin() const{
 
102
 
                return const_iterator(backing.begin());
 
106
 
                return iterator(backing.end());
 
109
 
        const_iterator end() const{
 
110
 
                return const_iterator(backing.end());
 
113
 
        reverse_iterator rbegin(){
 
114
 
                return reverse_iterator(end());
 
117
 
        const_reverse_iterator rbegin() const{
 
118
 
                return const_reverse_iterator(end());
 
121
 
        reverse_iterator rend(){
 
122
 
                return reverse_iterator(begin());
 
125
 
        const_reverse_iterator rend() const{
 
126
 
                return const_reverse_iterator(begin());
 
130
 
        iterator lower_bound(const key_type &x);
 
131
 
        const_iterator lower_bound(const key_type &x) const;
 
132
 
        iterator upper_bound(const key_type &x);
 
133
 
        const_iterator upper_bound(const key_type &x) const;
 
135
 
        pair<iterator,iterator> equal_range(const key_type& x){
 
136
 
                pair<iterator, iterator> retval;
 
137
 
                retval.first = lower_bound(x);
 
138
 
                retval.second = retval.first;
 
139
 
                while(retval.second != end() && !c(x, value_to_key(*retval.second))){
 
144
 
        pair<const_iterator,const_iterator> equal_range(const key_type& x) const{
 
145
 
                pair<const_iterator, const_iterator> retval;
 
146
 
                retval.first = lower_bound(x);
 
147
 
                retval.second = retval.first;
 
148
 
                while(retval.second != end() && !c(x, value_to_key(*retval.second))){
 
154
 
        iterator find(const key_type& x){
 
155
 
                iterator retval = lower_bound(x);
 
159
 
                if(c(x, value_to_key(*retval))){
 
164
 
        const_iterator find(const key_type& x) const{
 
165
 
                const_iterator retval = lower_bound(x);
 
169
 
                if(c(x, value_to_key(*retval))){
 
174
 
        size_type count(const key_type& x) const{
 
176
 
                const_iterator first = lower_bound(x);
 
177
 
                while(first != end() && !c(x, value_to_key(*first))){
 
188
 
        void erase(iterator pos){
 
189
 
                backing.erase(pos.base_iterator());
 
191
 
        size_type erase(const key_type& x){
 
193
 
                iterator start = lower_bound(x);
 
194
 
                iterator end = upper_bound(x);
 
196
 
                        start = backing.erase(start.base_iterator());
 
201
 
        void erase(iterator first, iterator last){
 
202
 
                while(first != last){
 
203
 
                        backing.erase(first.base_iterator());
 
208
 
        key_compare key_comp() const{
 
212
 
        __base_associative &operator=(const __base_associative & x){
 
215
 
                value_to_key = x.value_to_key;
 
218
 
        bool operator==(const __base_associative & x){
 
219
 
                return x.backing == backing;
 
221
 
        bool operator!=(const __base_associative & x){
 
222
 
                return !(x.backing == backing);
 
226
 
        void swap(__base_associative & x);
 
229
 
        std::list<value_type> backing;
 
231
 
        const key_type (*value_to_key)(const value_type);
 
237
 
 * Tree iterators for the base associative class
 
240
 
template<class ValueType, class Compare, class Allocator> class _associative_citer
 
241
 
        : public std::iterator<
 
242
 
                bidirectional_iterator_tag,
 
244
 
                typename Allocator::difference_type,
 
250
 
        typedef std::list<ValueType> listtype;
 
252
 
        typename listtype::const_iterator base_iter;
 
253
 
        friend class _associative_iter<ValueType, Compare, Allocator>;
 
255
 
        _associative_citer() { }
 
256
 
        _associative_citer(const _associative_citer & m)
 
257
 
                : base_iter(m.base_iter) { }
 
258
 
        _associative_citer(const typename listtype::const_iterator & m)
 
260
 
        ~_associative_citer() { }
 
261
 
        ValueType operator*() const{
 
264
 
        const ValueType * operator->() const{
 
265
 
                return &(*base_iter);
 
267
 
        _associative_citer & operator=(const _associative_citer & m){
 
268
 
                base_iter = m.base_iter;
 
271
 
        bool operator==(const _associative_citer & m) const{
 
272
 
                return m.base_iter == base_iter;
 
274
 
        bool operator!=(const _associative_citer & m) const{
 
275
 
                return m.base_iter != base_iter;
 
277
 
        _associative_citer & operator++(){
 
281
 
        _associative_citer operator++(int){
 
282
 
                //The following approach ensures that we only need to
 
283
 
                //provide code for ++ in one place (above)
 
284
 
                _associative_citer temp(base_iter);
 
288
 
        _associative_citer & operator--(){
 
292
 
        _associative_citer operator--(int){
 
293
 
                //The following approach ensures that we only need to
 
294
 
                //provide code for -- in one place (above)
 
295
 
                _associative_citer temp(base_iter);
 
300
 
        //This is an implementation-defined function designed to make internals work correctly
 
301
 
        typename listtype::const_iterator base_iterator(){
 
307
 
template<class ValueType, class Compare, class Allocator> class _associative_iter
 
308
 
        : public std::iterator<
 
309
 
                bidirectional_iterator_tag,
 
311
 
                typename Allocator::difference_type,
 
317
 
        typedef std::list<ValueType> listtype;
 
319
 
        typename listtype::iterator base_iter;
 
320
 
        typedef _associative_citer<ValueType, Compare, Allocator> __associative_citer;
 
323
 
        _associative_iter() { }
 
324
 
        _associative_iter(const _associative_iter & m)
 
325
 
                : base_iter(m.base_iter) { }
 
326
 
        _associative_iter(const typename listtype::iterator & m)
 
328
 
        ~_associative_iter() { }
 
329
 
        const ValueType & operator*() const{
 
332
 
        ValueType & operator*(){
 
335
 
        ValueType * operator->(){
 
336
 
                return &(*base_iter);
 
338
 
        const ValueType * operator->() const{
 
339
 
                return &(*base_iter);
 
341
 
        _associative_iter & operator=(const _associative_iter & m){
 
342
 
                base_iter = m.base_iter;
 
345
 
        bool operator==(const _associative_iter & m) const{
 
346
 
                return m.base_iter == base_iter;
 
348
 
        bool operator==(const __associative_citer & m) const{
 
349
 
                return m.base_iter == base_iter;
 
351
 
        bool operator!=(const _associative_iter & m) const{
 
352
 
                return m.base_iter != base_iter;
 
354
 
        bool operator!=(const __associative_citer & m) const{
 
355
 
                return m.base_iter != base_iter;
 
357
 
        _associative_iter & operator++(){
 
361
 
        _associative_iter operator++(int){
 
362
 
                //The following approach ensures that we only need to
 
363
 
                //provide code for ++ in one place (above)
 
364
 
                _associative_iter temp(base_iter);
 
368
 
        _associative_iter & operator--(){
 
372
 
        _associative_iter operator--(int){
 
373
 
                //The following approach ensures that we only need to
 
374
 
                //provide code for -- in one place (above)
 
375
 
                _associative_iter temp(base_iter);
 
379
 
        operator __associative_citer() const{
 
380
 
                return __associative_citer(base_iter);
 
382
 
        typename listtype::iterator base_iterator(){
 
385
 
        const typename listtype::iterator base_iterator() const{
 
392
 
        // The lower_bound code is really crappy linear search.  However, it is a dead
 
393
 
        // simple implementation (easy to audit).  It can also be easily replaced.
 
396
 
        template <class Key, class ValueType, class Compare, class Allocator>
 
397
 
                typename __base_associative<Key, ValueType, Compare, Allocator>::iterator
 
398
 
                __base_associative<Key, ValueType, Compare, Allocator>::lower_bound(const key_type &x)
 
400
 
                iterator retval = begin();
 
401
 
                while(retval != end() && c(value_to_key(*retval), x)){
 
407
 
        template <class Key, class ValueType, class Compare, class Allocator>
 
408
 
                typename __base_associative<Key, ValueType, Compare, Allocator>::const_iterator
 
409
 
                __base_associative<Key, ValueType, Compare, Allocator>::lower_bound(const key_type &x) const
 
411
 
                const_iterator retval = begin();
 
412
 
                while(retval != end() && c(value_to_key(*retval), x)){
 
418
 
        // Upper bound search is linear from the point of lower_bound.  This is likely the best solution
 
419
 
        // in all but the most pathological of cases.
 
421
 
        template <class Key, class ValueType, class Compare, class Allocator>
 
422
 
                typename __base_associative<Key, ValueType, Compare, Allocator>::iterator
 
423
 
                __base_associative<Key, ValueType, Compare, Allocator>::upper_bound(const key_type &x)
 
425
 
                iterator retval = lower_bound(x);
 
426
 
                while(retval != end() && !c(x, value_to_key(*retval))){
 
432
 
        template <class Key, class ValueType, class Compare, class Allocator>
 
433
 
                typename __base_associative<Key, ValueType, Compare, Allocator>::const_iterator
 
434
 
                __base_associative<Key, ValueType, Compare, Allocator>::upper_bound(const key_type &x) const
 
436
 
                const_iterator retval = begin();
 
437
 
                while(retval != end() && !c(x, value_to_key(*retval))){
 
444
 
        template <class Key, class ValueType, class Compare, class Allocator>
 
445
 
                void __base_associative<Key, ValueType, Compare, Allocator>::swap(__base_associative<Key, ValueType, Compare, Allocator>& m)
 
451
 
                m.backing.swap(backing);
 
455
 
template<class Key, class ValueType, class Compare, class Allocator> class _UCXXEXPORT __single_associative :
 
456
 
        public __base_associative<Key, ValueType, Compare, Allocator>
 
459
 
        typedef __base_associative<Key, ValueType, Compare, Allocator> base;
 
465
 
        typedef typename base::key_type                         key_type;
 
466
 
        typedef typename base::value_type                       value_type;
 
467
 
        typedef typename base::key_compare                      key_compare;
 
468
 
        typedef typename base::allocator_type                   allocator_type;
 
469
 
        typedef typename base::reference                        reference;
 
470
 
        typedef typename base::const_reference                  const_reference;
 
471
 
        typedef typename base::iterator                         iterator;
 
472
 
        typedef typename base::const_iterator                   const_iterator;
 
473
 
        typedef typename base::size_type                        size_type;
 
474
 
        typedef typename base::difference_type                  difference_type;
 
475
 
        typedef typename base::pointer                          pointer;
 
476
 
        typedef typename base::const_pointer                    const_pointer;
 
477
 
        typedef typename base::reverse_iterator                 reverse_iterator;
 
478
 
        typedef typename base::const_reverse_iterator           const_reverse_iterator;
 
487
 
        using base::max_size;
 
491
 
        using base::lower_bound;
 
492
 
        using base::upper_bound;
 
493
 
        using base::equal_range;
 
495
 
        using base::operator=;
 
496
 
        using base::operator==;
 
497
 
        using base::operator!=;
 
499
 
        explicit __single_associative(const Compare& comp, const Allocator& A, const key_type (*v_to_k)(const value_type))
 
500
 
                : base(comp, A, v_to_k) { }
 
502
 
        template <class InputIterator> __single_associative(
 
507
 
                const key_type (*v_to_k)(const value_type)
 
508
 
        ) : base(comp, A, v_to_k) {
 
512
 
        pair<iterator, bool> insert(const value_type& x){
 
513
 
                pair<iterator, bool> retval;
 
514
 
                iterator location = lower_bound(value_to_key(x));
 
515
 
                retval.second = true;
 
516
 
                //Empty list or need to insert at end
 
517
 
                if(end() == location){
 
518
 
                        backing.push_back(x);
 
519
 
                        retval.first = --(end());
 
522
 
                //Something in the list
 
523
 
                if(c(value_to_key(x), value_to_key(*location))){
 
524
 
                        location = backing.insert(location.base_iterator(), x);
 
525
 
                        retval.first = location;
 
527
 
                        retval.second = false;
 
528
 
                        retval.first = location;
 
533
 
        iterator insert(iterator position, const value_type& x){
 
534
 
                // FIXME - this is cheating and probably should be more efficient since we are
 
535
 
                // now log(n) to find for inserts
 
536
 
                return insert(x).first;
 
539
 
        template <class InputIterator> void insert(InputIterator first, InputIterator last){
 
540
 
                while(first != last){
 
549
 
template<class Key, class ValueType, class Compare, class Allocator> class _UCXXEXPORT __multi_associative :
 
550
 
        public __base_associative<Key, ValueType, Compare, Allocator>
 
553
 
        typedef __base_associative<Key, ValueType, Compare, Allocator> base;
 
559
 
        typedef typename base::key_type                         key_type;
 
560
 
        typedef typename base::value_type                       value_type;
 
561
 
        typedef typename base::key_compare                      key_compare;
 
562
 
        typedef typename base::allocator_type                   allocator_type;
 
563
 
        typedef typename base::reference                        reference;
 
564
 
        typedef typename base::const_reference                  const_reference;
 
565
 
        typedef typename base::iterator                         iterator;
 
566
 
        typedef typename base::const_iterator                   const_iterator;
 
567
 
        typedef typename base::size_type                        size_type;
 
568
 
        typedef typename base::difference_type                  difference_type;
 
569
 
        typedef typename base::pointer                          pointer;
 
570
 
        typedef typename base::const_pointer                    const_pointer;
 
571
 
        typedef typename base::reverse_iterator                 reverse_iterator;
 
572
 
        typedef typename base::const_reverse_iterator           const_reverse_iterator;
 
581
 
        using base::max_size;
 
585
 
        using base::lower_bound;
 
586
 
        using base::upper_bound;
 
587
 
        using base::equal_range;
 
589
 
        using base::operator=;
 
590
 
        using base::operator==;
 
593
 
        explicit __multi_associative(const Compare& comp, const Allocator& A, const key_type (*v_to_k)(const value_type))
 
594
 
                : base(comp, A, v_to_k) { }
 
596
 
        template <class InputIterator> __multi_associative(
 
601
 
                const key_type (*v_to_k)(const value_type)
 
602
 
        ) : base(comp, A, v_to_k) {
 
606
 
        iterator insert(const value_type& x){
 
607
 
                iterator location = lower_bound(value_to_key(x));
 
609
 
                if(location == begin()){
 
610
 
                        backing.push_front(x);
 
613
 
                        location = backing.insert(location.base_iterator(), x);
 
618
 
        iterator insert(iterator position, const value_type& x){
 
619
 
                // FIXME - this is cheating and probably should be more efficient since we are
 
620
 
                // now log(n) to find for inserts
 
624
 
        template <class InputIterator> void insert(InputIterator first, InputIterator last){
 
625
 
                while(first != last){
 
637
 
#pragma GCC visibility pop
 
639
 
#endif  //__STD_HEADER_ASSOCIATIVE_BASE