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 _libcxx_assert(m_index < m_map->m_size);
63 return m_map->m_items[m_index];
65 value_type* operator->() {
66 _libcxx_assert(m_index < m_map->m_size);
67 return &m_map->m_items[m_index];
73 template <class Key, class T, class Compare=less<Key>, class Alloc=allocator<pair<const Key,T> > >
76 typedef map this_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;
92 friend class ::std::_bits::map_iterator<value_type, this_type>;
93 friend class ::std::_bits::map_iterator<const value_type, this_type>;
96 allocator_type m_alloc;
97 value_type* m_items; // sorted array
102 map(const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type()):
105 m_items(0), m_size(0), m_capacity(0)
108 template <class InputInterator>
109 map(InputInterator first, InputInterator last):
115 map(x.m_comp, x.m_alloc)
123 map& operator=(const map& x) {
126 for( size_type i = 0; i < x.m_size; i ++ ) {
127 emplace_hint( end(), x.m_items[i] );
134 return iterator(this, 0);
136 const_iterator begin() const {
137 return const_iterator(this, 0);
140 return iterator(this, m_size);
142 const_iterator end() const {
143 return const_iterator(this, m_size);
146 const_iterator cbegin() const {
147 return const_iterator(this, 0);
149 const_iterator cend() const {
150 return const_iterator(this, m_size);
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;
164 size_type size() const {
167 size_type max_size() const {
168 return (size_type)-1 / sizeof(value_type);
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()) );
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");
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");
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);
201 void erase(iterator position);
202 size_type erase(const key_type& k);
203 void erase(iterator first, iterator last);
208 for( size_type i = 0; i < m_size; i ++ ) {
209 m_alloc.destroy( &m_items[i] );
215 template <class... Args>
216 pair<iterator,bool> emplace(Args&&... args) {
217 return emplace_hint(begin(), args...);
219 template <class... Args>
220 pair<iterator,bool> emplace_hint(iterator position, Args&&... args);
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
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
238 size_type count(const key_type& k) {
239 if( find(k) == end() )
243 iterator lower_bound(const key_type& k) {
245 if( _search(k, idx) ) {
246 // found, return direct iterator
247 return iterator(this, idx);
250 // not found, return iterator to before
251 if( idx == 0 ) return begin();
252 return iterator(this, idx-1);
255 const_iterator lower_bound(const key_type& k) const {
257 if( _search(k, idx) ) {
258 // found, return direct iterator
259 return iterator(this, idx);
262 // not found, return iterator to before
263 if( idx == 0 ) return begin();
264 return iterator(this, idx-1);
267 iterator upper_bound(const key_type& k) {
270 // idx == item or just after it
271 return iterator(this, idx);
273 const_iterator upper_bound(const key_type& k) const {
276 return const_iterator(this, idx);
278 pair<iterator,iterator> equal_range(const key_type& k);
279 pair<const_iterator,const_iterator> equal_range(const key_type& k) const;
282 // Change reservation to fit 'n' items
283 // - NOTE: Will also resize down
284 void reserve(size_type n) {
287 throw ::std::length_error("::std::map::reserve");
288 if( n != m_capacity )
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);
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 {
306 size_type pos = m_size / 2;
307 size_type step = m_size / 4;
309 const key_type& item_key = m_items[pos].first;
310 if( m_comp(item_key, k) )
312 else if( m_comp(k, item_key) )
323 //::_sys::debug("map::_search (m_size=%i)", m_size);
324 for( size_type pos = 0; pos < m_size; pos ++ )
326 const key_type& item_key = m_items[pos].first;
327 if( m_comp(item_key, k) ) {
330 else if( m_comp(k, item_key) ) {
331 //::_sys::debug("map::_search - Passed %i", pos);
336 //::_sys::debug("map::_search - Found %i", pos);
341 //::_sys::debug("map::_search - Off end %i", m_size);
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) );
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);
357 void shift_items(value_type *start, value_type *end, size_type count) {
359 for( size_type i = count; i --; ) {
360 #if _CXX11_AVAIL && 0
361 m_alloc.construct(&end[i], ::std::move(start[i]));
363 m_alloc.construct(&end[i], start[i]);
364 m_alloc.destroy(&start[i]);
369 for( size_type i = 0; i < count; i ++ ) {