Usermode/libc++ - Fix off by one in map indexing
[tpg/acess2.git] / Usermode / Libraries / libc++.so_src / include_exp / map
1 /*
2  * Acess2 C++ Library
3  * - By John Hodge (thePowersGang)
4  *
5  * map (header)
6  * - C++'s map type
7  */
8 #ifndef _LIBCXX_MAP_
9 #define _LIBCXX_MAP_
10
11 #include "_libcxx_helpers.h"
12 #include <allocator>
13 #include <stdexcept>
14 #include <iterator>
15 #include <utility>
16 #include <functional>   // less
17
18 namespace std {
19
20 namespace _bits {
21
22 template <class Val, class Map>
23 class map_iterator:
24         public ::std::iterator< ::std::bidirectional_iterator_tag, Val >
25 {
26         friend Map;
27         typedef Val     value_type;
28         Map     *m_map;
29         size_t  m_index;
30 public:
31         map_iterator():
32                 m_map(0), m_index(0)
33         {
34         }
35         map_iterator(Map *map, typename Map::size_type ofs):
36                 m_map(map), m_index(ofs)
37         {
38         }
39         map_iterator(const map_iterator& x) {
40                 *this = x;
41         }
42         map_iterator& operator=(const map_iterator& x) {
43                 m_map = x.m_map;
44                 m_index = x.m_index;
45                 return *this;
46         }
47         
48         map_iterator& operator++() {
49                 m_index ++;
50         }
51         map_iterator& operator--() {
52                 m_index --;
53         }
54         
55         bool operator==(const map_iterator& x) const {
56                 return m_index == x.m_index;
57         }
58         bool operator!=(const map_iterator& x) const {
59                 return !(*this == x);
60         }
61         value_type& operator*() {
62                 _libcxx_assert(m_index < m_map->m_size);
63                 return m_map->m_items[m_index];
64         }
65         value_type* operator->() {
66                 _libcxx_assert(m_index < m_map->m_size);
67                 return &m_map->m_items[m_index];
68         }
69 };
70
71 }       // namespace _bits
72
73 template <class Key, class T, class Compare=less<Key>, class Alloc=allocator<pair<const Key,T> > >
74 class map
75 {
76         typedef map     this_type;
77 public:
78         typedef Key     key_type;
79         typedef T       mapped_type;
80         typedef pair<const Key, T>      value_type;
81         typedef Compare key_compare;
82         typedef Alloc   allocator_type;
83         typedef typename allocator_type::reference      reference;
84         typedef typename allocator_type::const_reference        const_reference;
85         typedef typename allocator_type::pointer        pointer;
86         typedef typename allocator_type::const_pointer  const_pointer;
87         typedef _bits::map_iterator<value_type,this_type>       iterator;
88         typedef _bits::map_iterator<const value_type,this_type> const_iterator;
89         typedef size_t  size_type;
90
91 private:
92         friend class ::std::_bits::map_iterator<value_type, this_type>;
93         friend class ::std::_bits::map_iterator<const value_type, this_type>;
94
95         key_compare     m_comp;
96         allocator_type  m_alloc;
97         value_type*     m_items;        // sorted array
98         size_type       m_size;
99         size_type       m_capacity;
100
101 public:
102         map(const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type()):
103                 m_comp(comp),
104                 m_alloc(alloc),
105                 m_items(0), m_size(0), m_capacity(0)
106         {
107         }
108         template <class InputInterator>
109         map(InputInterator first, InputInterator last):
110                 map()
111         {
112                 insert(first, last);
113         }
114         map(const map& x):
115                 map(x.m_comp, x.m_alloc)
116         {
117                 *this = x;
118         }
119         ~map() {
120                 clear();
121                 reserve(0);
122         }
123         map& operator=(const map& x) {
124                 clear();
125                 reserve(x.m_size);
126                 for( size_type i = 0; i < x.m_size; i ++ ) {
127                         emplace_hint( end(), x.m_items[i] );
128                 }
129                 return *this;
130         }
131         
132         // Iterators
133         iterator begin() {
134                 return iterator(this, 0);
135         }
136         const_iterator begin() const {
137                 return const_iterator(this, 0);
138         }
139         iterator end() {
140                 return iterator(this, m_size);
141         }
142         const_iterator end() const {
143                 return const_iterator(this, m_size);
144         }
145         #if _CXX11_AVAIL
146         const_iterator cbegin() const {
147                 return const_iterator(this, 0);
148         }
149         const_iterator cend() const {
150                 return const_iterator(this, m_size);
151         }
152         #endif
153         //reverse_iterator rbegin();
154         //const_reverse_iterator rbegin() const;
155         //const_reverse_iterator crbegin() const;
156         //reverse_iterator rend();
157         //const reverse_iterator rend() const;
158         //const reverse_iterator crend() const;
159         
160         // Capacity
161         bool empty() const {
162                 return m_size == 0;
163         }
164         size_type size() const {
165                 return m_size;
166         }
167         size_type max_size() const {
168                 return (size_type)-1 / sizeof(value_type);
169         }
170         
171         // Element access
172         mapped_type& operator[](const key_type& k) {
173                 iterator it = upper_bound(k);
174                 if( it == end() || m_comp(k, it->first) ) {     // if k < it->first, no match
175                         insert_at(it.m_index, value_type(k,mapped_type()) );
176                 }
177                 return it->second;
178         }
179         #if _CXX11_AVAIL
180         mapped_type& at(const key_type& k) {
181                 iterator it = lower_bound(k);
182                 if( it == end() || m_comp(it->first, k) )
183                         throw ::std::out_of_range("::std:map::at");
184                 return it->second;
185         }
186         const mapped_type& at(const key_type& k) const {
187                 iterator it = lower_bound(k);
188                 if( it == end() || m_comp(it->first, k) )
189                         throw ::std::out_of_range("::std:map::at");
190                 return it->second;
191         }
192         #endif
193         
194         // Modifiers
195         // - insert
196         pair<iterator,bool> insert(const value_type& val);
197         iterator insert(iterator position, const value_type& val);
198         template <class InputInterator>
199         void insert(InputInterator first, InputInterator last);
200         // - erase
201         void erase(iterator position);
202         size_type erase(const key_type& k);
203         void erase(iterator first, iterator last);
204         // - swap
205         void swap(map& x);
206         // - clear
207         void clear() {
208                 for( size_type i = 0; i < m_size; i ++ ) {
209                         m_alloc.destroy( &m_items[i] );
210                 }
211                 m_size = 0;
212         }
213         // - emplace
214         #if _CXX11_AVAIL
215         template <class... Args>
216         pair<iterator,bool> emplace(Args&&... args) {
217                 return emplace_hint(begin(), args...);
218         }
219         template <class... Args>
220         pair<iterator,bool> emplace_hint(iterator position, Args&&... args);
221         #endif
222         
223         // TODO: Observers
224         
225         // Operators
226         iterator find(const key_type& k) {
227                 iterator it = lower_bound(k);
228                 if( it == end() || m_comp(it->first, k) )       // if it->first < k
229                         return end();
230                 return it;
231         }
232         const_iterator find(const key_type& k) const {
233                 const_iterator it = lower_bound(k);
234                 if( it == end() || m_comp(it->first, k) )       // if it->first < k
235                         return end();
236                 return it;
237         }
238         size_type count(const key_type& k) {
239                 if( find(k) == end() )
240                         return 0;
241                 return 1;
242         }
243         iterator lower_bound(const key_type& k) {
244                 size_type idx;
245                 if( _search(k, idx) ) {
246                         // found, return direct iterator
247                         return iterator(this, idx);
248                 }
249                 else {
250                         // not found, return iterator to before
251                         if( idx == 0 )  return begin();
252                         return iterator(this, idx-1);
253                 }
254         }
255         const_iterator lower_bound(const key_type& k) const {
256                 size_type idx;
257                 if( _search(k, idx) ) {
258                         // found, return direct iterator
259                         return iterator(this, idx);
260                 }
261                 else {
262                         // not found, return iterator to before
263                         if( idx == 0 )  return begin();
264                         return iterator(this, idx-1);
265                 }
266         }
267         iterator upper_bound(const key_type& k) {
268                 size_type idx;
269                 _search(k, idx);
270                 // idx == item or just after it
271                 return iterator(this, idx);
272         }
273         const_iterator upper_bound(const key_type& k) const {
274                 size_type idx;
275                 _search(k, idx);
276                 return const_iterator(this, idx);
277         }
278         pair<iterator,iterator> equal_range(const key_type& k);
279         pair<const_iterator,const_iterator> equal_range(const key_type& k) const;
280
281 private:
282         // Change reservation to fit 'n' items
283         // - NOTE: Will also resize down
284         void reserve(size_type n) {
285                 n = (n + 31) & ~31;
286                 if( n > max_size() )
287                         throw ::std::length_error("::std::map::reserve");
288                 if( n != m_capacity )
289                 {
290                         auto new_area = m_alloc.allocate(n);
291                         for( size_type i = 0; i < m_size && i < n; i ++ )
292                                 m_alloc.construct(&new_area[i], m_items[i]);
293                         for( size_type i = n; i < m_size; i ++ )
294                                 m_alloc.destroy( &m_items[i] );
295                         m_alloc.deallocate(m_items, m_capacity);
296                         m_items = new_area;
297                         m_capacity = n;
298                         if(m_size > n)
299                                 m_size = n;
300                 }
301         }
302         // Returns the index above or equal to 'k'
303         // - TODO: Reimplement as a binary search
304         bool _search(const key_type& k, size_type &pos_out) const {
305                 #if 0
306                 size_type pos = m_size / 2;
307                 size_type step = m_size / 4;
308                 while( step > 0 ) {
309                         const key_type& item_key = m_items[pos].first;
310                         if( m_comp(item_key, k) )
311                                 pos += step;
312                         else if( m_comp(k, item_key) )
313                                 pos -= step;
314                         else {
315                                 pos_out = pos;
316                                 return true;
317                         }
318                         step /= 2;
319                 }
320                 pos_out = pos;
321                 return false;
322                 #else
323                 //::_sys::debug("map::_search (m_size=%i)", m_size);
324                 for( size_type pos = 0; pos < m_size; pos ++ )
325                 {
326                         const key_type& item_key = m_items[pos].first;
327                         if( m_comp(item_key, k) ) {
328                                 continue;
329                         }
330                         else if( m_comp(k, item_key) ) {
331                                 //::_sys::debug("map::_search - Passed %i", pos);
332                                 pos_out = pos;
333                                 return false;
334                         }
335                         else {
336                                 //::_sys::debug("map::_search - Found %i", pos);
337                                 pos_out = pos;
338                                 return true;
339                         }
340                 }
341                 //::_sys::debug("map::_search - Off end %i", m_size);
342                 pos_out = m_size;
343                 return false;
344                 #endif
345         }
346         void insert_at(size_type ofs, const value_type& val) {
347                 //_libcxx_assert( ofs == 0 || m_comp(m_items[ofs-1].first, val.first) );
348                 //_libcxx_assert( ofs == m_size || m_comp(m_items[ofs].first, val.first) );
349                 // Resize up
350                 reserve( m_size + 1 );
351                 // Move following items up
352                 shift_items(&m_items[ofs], &m_items[ofs+1], m_size-ofs);
353                 // Construct new item
354                 m_alloc.construct(&m_items[ofs], val);
355                 m_size ++;
356         }
357         void shift_items(value_type *start, value_type *end, size_type count) {
358                 if( start < end ) {
359                         for( size_type i = count; i --; ) {
360                                 #if _CXX11_AVAIL && 0
361                                 m_alloc.construct(&end[i], ::std::move(start[i]));
362                                 #else
363                                 m_alloc.construct(&end[i], start[i]);
364                                 m_alloc.destroy(&start[i]);
365                                 #endif
366                         }
367                 }
368                 else {
369                         for( size_type i = 0; i < count; i ++ ) {
370                         }
371                 }
372         }
373 };
374
375 }       // namespace std
376
377 #endif
378
379 // vim: ft=cpp
380

UCC git Repository :: git.ucc.asn.au