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