3 * - By John Hodge (thePowersGang)
11 #include "_libcxx_helpers.h"
16 #include <functional> // less
22 template <class Val, class Map>
24 public ::std::iterator< ::std::bidirectional_iterator_tag, Val >
27 typedef Val value_type;
35 map_iterator(Map *map, typename Map::size_type ofs):
36 m_map(map), m_index(ofs)
39 map_iterator(const map_iterator& x) {
42 map_iterator& operator=(const map_iterator& x) {
48 map_iterator& operator++() {
51 map_iterator& operator--() {
55 bool operator==(const map_iterator& x) const {
56 return m_index == x.m_index;
58 bool operator!=(const map_iterator& x) const {
61 value_type& operator*() {
62 return m_map->m_items[m_index];
64 value_type* operator->() {
65 return &m_map->m_items[m_index];
71 template <class Key, class T, class Compare=less<Key>, class Alloc=allocator<pair<const Key,T> > >
74 typedef map this_type;
77 typedef T mapped_type;
78 typedef pair<const Key, T> value_type;
79 typedef Compare key_compare;
80 typedef Alloc allocator_type;
81 typedef typename allocator_type::reference reference;
82 typedef typename allocator_type::const_reference const_reference;
83 typedef typename allocator_type::pointer pointer;
84 typedef typename allocator_type::const_pointer const_pointer;
85 typedef _bits::map_iterator<value_type,this_type> iterator;
86 typedef _bits::map_iterator<const value_type,this_type> const_iterator;
87 typedef size_t size_type;
90 friend class ::std::_bits::map_iterator<value_type, this_type>;
91 friend class ::std::_bits::map_iterator<const value_type, this_type>;
94 allocator_type m_alloc;
95 value_type* m_items; // sorted array
100 map(const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type()):
103 m_items(0), m_size(0), m_capacity(0)
106 template <class InputInterator>
107 map(InputInterator first, InputInterator last):
113 map(x.m_comp, x.m_alloc)
121 map& operator=(const map& x) {
124 for( size_type i = 0; i < x.m_size; i ++ ) {
125 emplace_hint( end(), x.m_items[i] );
132 return iterator(this, 0);
134 const_iterator begin() const {
135 return const_iterator(this, 0);
138 return iterator(this, m_size);
140 const_iterator end() const {
141 return const_iterator(this, m_size);
144 const_iterator cbegin() const {
145 return const_iterator(this, 0);
147 const_iterator cend() const {
148 return const_iterator(this, m_size);
151 //reverse_iterator rbegin();
152 //const_reverse_iterator rbegin() const;
153 //const_reverse_iterator crbegin() const;
154 //reverse_iterator rend();
155 //const reverse_iterator rend() const;
156 //const reverse_iterator crend() const;
162 size_type size() const {
165 size_type max_size() const {
166 return (size_type)-1 / sizeof(value_type);
170 mapped_type& operator[](const key_type& k) {
171 iterator it = upper_bound(k);
172 if( it == end() || m_comp(k, it->first) ) { // if k < it->first, no match
173 insert_at(it.m_index, value_type(k,mapped_type()) );
179 mapped_type& at(const key_type& k) {
180 iterator it = lower_bound(k);
181 if( it == end() || m_comp(it->first, k) )
182 throw ::std::out_of_range("::std:map::at");
185 const mapped_type& at(const key_type& k) const {
186 iterator it = lower_bound(k);
187 if( it == end() || m_comp(it->first, k) )
188 throw ::std::out_of_range("::std:map::at");
195 pair<iterator,bool> insert(const value_type& val);
196 iterator insert(iterator position, const value_type& val);
197 template <class InputInterator>
198 void insert(InputInterator first, InputInterator last);
200 void erase(iterator position);
201 size_type erase(const key_type& k);
202 void erase(iterator first, iterator last);
207 for( size_type i = 0; i < m_size; i ++ ) {
208 m_alloc.destroy( &m_items[i] );
214 template <class... Args>
215 pair<iterator,bool> emplace(Args&&... args) {
216 return emplace_hint(begin(), args...);
218 template <class... Args>
219 pair<iterator,bool> emplace_hint(iterator position, Args&&... args);
225 iterator find(const key_type& k) {
226 iterator it = lower_bound(k);
227 if( it == end() || m_comp(it->first, k) ) // if it->first < k
231 const_iterator find(const key_type& k) const {
232 const_iterator it = lower_bound(k);
233 if( it == end() || m_comp(it->first, k) ) // if it->first < k
237 size_type count(const key_type& k) {
238 if( find(k) == end() )
242 iterator lower_bound(const key_type& k) {
244 if( _search(k, idx) ) {
245 // found, return direct iterator
246 return iterator(this, idx);
249 // not found, return iterator to before
250 if( idx == 0 ) return begin();
251 return iterator(this, idx-1);
254 const_iterator lower_bound(const key_type& k) const {
256 if( _search(k, idx) ) {
257 // found, return direct iterator
258 return iterator(this, idx);
261 // not found, return iterator to before
262 if( idx == 0 ) return begin();
263 return iterator(this, idx-1);
266 iterator upper_bound(const key_type& k) {
269 // idx == item or just after it
270 return iterator(this, idx);
272 const_iterator upper_bound(const key_type& k) const {
275 return const_iterator(this, idx);
277 pair<iterator,iterator> equal_range(const key_type& k);
278 pair<const_iterator,const_iterator> equal_range(const key_type& k) const;
281 // Change reservation to fit 'n' items
282 // - NOTE: Will also resize down
283 void reserve(size_type n) {
286 throw ::std::length_error("::std::map::reserve");
287 if( n != m_capacity )
289 auto new_area = m_alloc.allocate(n);
290 for( size_type i = 0; i < m_size && i < n; i ++ )
291 m_alloc.construct(&new_area[i], m_items[i]);
292 for( size_type i = n; i < m_size; i ++ )
293 m_alloc.destroy( &m_items[i] );
294 m_alloc.deallocate(m_items, m_capacity);
301 // Returns the index above or equal to 'k'
302 // - TODO: Reimplement as a binary search
303 bool _search(const key_type& k, size_type &pos_out) const {
305 size_type pos = m_size / 2;
306 size_type step = m_size / 4;
308 const key_type& item_key = m_items[pos].first;
309 if( m_comp(item_key, k) )
311 else if( m_comp(k, item_key) )
322 for( size_type pos = 0; pos < m_size; pos ++ )
324 const key_type& item_key = m_items[pos].first;
325 if( m_comp(item_key, k) ) {
328 else if( m_comp(k, item_key) ) {
341 void insert_at(size_type ofs, const value_type& val) {
342 //assert( ofs == 0 || m_comp(m_items[ofs-1].first, val.first) );
343 //assert( ofs == m_size || m_comp(m_items[ofs].first, val.first) );
344 ::_sys::debug("map::insert_at(%i,)", ofs);
346 reserve( m_size + 1 );
347 // Move following items up
348 shift_items(&m_items[ofs], &m_items[ofs+1], m_size-ofs);
349 // Construct new item
350 m_alloc.construct(&m_items[ofs], val);
353 void shift_items(value_type *start, value_type *end, size_type count) {
355 for( size_type i = count; i --; ) {
356 #if _CXX11_AVAIL && 0
357 m_alloc.construct(&end[i], ::std::move(start[i]));
359 m_alloc.construct(&end[i], start[i]);
360 m_alloc.destroy(&start[i]);
365 for( size_type i = 0; i < count; i ++ ) {