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