source: mainline/uspace/lib/cpp/include/impl/unordered_map.hpp@ cbf9099

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since cbf9099 was 86d1939, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: fixed compilation errors, added bodies of some functions

  • Property mode set to 100644
File size: 19.7 KB
Line 
1/*
2 * Copyright (c) 2018 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef LIBCPP_UNORDERED_MAP
30#define LIBCPP_UNORDERED_MAP
31
32#include <initializer_list>
33#include <internal/hash_table.hpp>
34#include <functional>
35#include <memory>
36#include <utility>
37
38namespace std
39{
40 /**
41 * 23.5.4, class template unordered_map:
42 */
43
44 template<
45 class Key, class Value,
46 class Hash = hash<Key>,
47 class Pred = equal_to<Key>,
48 class Alloc = allocator<pair<const Key, Value>>
49 >
50 class unordered_map
51 {
52 public:
53 using key_type = Key;
54 using mapped_type = Value;
55 using value_type = pair<const key_type, mapped_type>;
56 using hasher = Hash;
57 using key_equal = Pred;
58 using allocator_type = Alloc;
59 using pointer = typename allocator_traits<allocator_type>::pointer;
60 using const_pointer = typename allocator_traits<allocator_type>::const_pointer;
61 using reference = value_type&;
62 using const_reference = const value_type&;
63 using size_type = size_t;
64 using difference_type = ptrdiff_t;
65
66 using iterator = aux::hash_table_iterator<
67 value_type, reference, pointer, size_type
68 >;
69 using const_iterator = aux::hash_table_const_iterator<
70 value_type, const_reference, const_pointer, size_type
71 >;
72 using local_iterator = aux::hash_table_local_iterator<
73 value_type, reference, pointer
74 >;
75 using const_local_iterator = aux::hash_table_const_local_iterator<
76 value_type, const_reference, const_pointer
77 >;
78
79 unordered_map()
80 : unordered_map{default_bucket_count_}
81 { /* DUMMY BODY */ }
82
83 explicit unordered_map(size_type bucket_count,
84 const hasher& hf = hasher{},
85 const key_equal& eql = key_equal{},
86 const allocator_type& alloc = allocator_type{})
87 : table_{bucket_count, hf, eql}, allocator_{alloc}
88 { /* DUMMY BODY */ }
89
90 template<class InputIterator>
91 unordered_map(InputIterator first, InputIterator last,
92 size_type bucket_count = default_bucket_count_,
93 const hasher& hf = hasher{},
94 const key_equal& eql = key_equal{},
95 const allocator_type& alloc = allocator_type{})
96 : unordered_map{bucket_count, hf, eql, alloc}
97 {
98 insert(first, last);
99 }
100
101 unordered_map(const unordered_map& other)
102 : unordered_map{other, other.allocator_}
103 { /* DUMMY BODY */ }
104
105 unordered_map(unordered_map&& other)
106 : table_{move(other.table_)}, allocator_{move(other.allocator_)}
107 { /* DUMMY BODY */ }
108
109 explicit unordered_map(const allocator_type& alloc)
110 : table_{default_bucket_count_}, allocator_{alloc}
111 { /* DUMMY BODY */ }
112
113 unordered_map(const unordered_map& other, const allocator_type& alloc)
114 : table_{other.table_}, allocator_{alloc}
115 { /* DUMMY BODY */ }
116
117 unordered_map(unordered_map&& other, const allocator_type& alloc)
118 : table_{move(other.table_)}, allocator_{alloc}
119 { /* DUMMY BODY */ }
120
121 unordered_map(initializer_list<value_type> init,
122 size_type bucket_count = default_bucket_count_,
123 const hasher& hf = hasher{},
124 const key_equal& eql = key_equal{},
125 const allocator_type& alloc = allocator_type{})
126 : unordered_map{bucket_count, hf, eql, alloc}
127 {
128 insert(init.begin(), init.end());
129 }
130
131 unordered_map(size_type bucket_count, const allocator_type& alloc)
132 : unordered_map{bucket_count, hasher{}, key_equal{}, alloc}
133 { /* DUMMY BODY */ }
134
135 unordered_map(size_type bucket_count, const hasher& hf, const allocator_type& alloc)
136 : unordered_map{bucket_count, hf, key_equal{}, alloc}
137 { /* DUMMY BODY */ }
138
139 template<class InputIterator>
140 unordered_map(InputIterator first, InputIterator last,
141 size_type bucket_count, const allocator_type& alloc)
142 : unordered_map{first, last, bucket_count, hasher{}, key_equal{}, alloc}
143 { /* DUMMY BODY */ }
144
145 template<class InputIterator>
146 unordered_map(InputIterator first, InputIterator last,
147 size_type bucket_count, const hasher& hf, const allocator_type& alloc)
148 : unordered_map{first, last, bucket_count, hf, key_equal{}, alloc}
149 { /* DUMMY BODY */ }
150
151 unordered_map(initializer_list<value_type> init, size_type bucket_count,
152 const allocator_type& alloc)
153 : unordered_map{init, bucket_count, hasher{}, key_equal{}, alloc}
154 { /* DUMMY BODY */ }
155
156 unordered_map(initializer_list<value_type> init, size_type bucket_count,
157 const hasher& hf, const allocator_type& alloc)
158 : unordered_map{init, bucket_count, hf, key_equal{}, alloc}
159 { /* DUMMY BODY */ }
160
161 ~unordered_map()
162 { /* DUMMY BODY */ }
163
164 unordered_map& operator=(const unordered_map& other)
165 {
166 // TODO: implement
167 return *this;
168 }
169
170 unordered_map& operator=(unordered_map&& other)
171 noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
172 is_nothrow_move_assignable<hasher>::value &&
173 is_nothrow_move_assignable<key_equal>::value)
174 {
175 // TODO: implement
176 return *this;
177 }
178
179 unordered_map& operator=(initializer_list<value_type>& init)
180 {
181 table_.clear();
182 table_.reserve(init.size());
183
184 insert(init.begin(), init.end());
185
186 return *this;
187 }
188
189 allocator_type get_allocator() const noexcept
190 {
191 return allocator_;
192 }
193
194 bool empty() const noexcept
195 {
196 return table_.empty();
197 }
198
199 size_type size() const noexcept
200 {
201 return table_.size();
202 }
203
204 size_type max_size() const noexcept
205 {
206 return table_.max_size();
207 }
208
209 iterator begin() noexcept
210 {
211 return table_.begin();
212 }
213
214 const_iterator begin() const noexcept
215 {
216 return table_.begin();
217 }
218
219 iterator end() noexcept
220 {
221 return table_.end();
222 }
223
224 const_iterator end() const noexcept
225 {
226 return table_.end();
227 }
228
229 const_iterator cbegin() const noexcept
230 {
231 return table_.cbegin();
232 }
233
234 const_iterator cend() const noexcept
235 {
236 return table_.cend();
237 }
238
239 template<class... Args>
240 pair<iterator, bool> emplace(Args&&... args)
241 {
242 // TODO: implement
243 }
244
245 template<class... Args>
246 iterator emplace_hint(const_iterator position, Args&&... args)
247 {
248 // TODO: implement
249 }
250
251 pair<iterator, bool> insert(const value_type& val)
252 {
253 // TODO: implement
254 }
255
256 pair<iterator, bool> insert(value_type&& val)
257 {
258 // TODO: implement
259 }
260
261 template<class T>
262 pair<iterator, bool> insert(T&& val)
263 {
264 // TODO: implement
265 }
266
267 iterator insert(const_iterator hint, const value_type& val)
268 {
269 // TODO: implement
270 }
271
272 iterator insert(const_iterator hint, value_type&& val)
273 {
274 // TODO: implement
275 }
276
277 template<class T>
278 iterator insert(const_iterator hint, T&& val)
279 {
280 // TODO: implement
281 }
282
283 template<class InputIterator>
284 void insert(InputIterator first, InputIterator last)
285 {
286 // TODO: implement
287 }
288
289 void insert(initializer_list<value_type> init)
290 {
291 insert(init.begin(), init.end());
292 }
293
294 template<class... Args>
295 pair<iterator, bool> try_emplace(const key_type& key, Args&&... args)
296 {
297 // TODO: implement
298 }
299
300 template<class... Args>
301 pair<iterator, bool> try_emplace(key_type&& key, Args&&... args)
302 {
303 // TODO: implement
304 }
305
306 template<class... Args>
307 iterator try_emplace(const_iterator hint, const key_type& key, Args&&... args)
308 {
309 // TODO: implement
310 }
311
312 template<class... Args>
313 iterator try_emplace(const_iterator hint, key_type&& key, Args&&... args)
314 {
315 // TODO: implement
316 }
317
318 template<class T>
319 pair<iterator, bool> insert_or_assign(const key_type& key, T&& val)
320 {
321 // TODO: implement
322 }
323
324 template<class T>
325 pair<iterator, bool> insert_or_assign(key_type&& key, T&& val)
326 {
327 // TODO: implement
328 }
329
330 template<class T>
331 iterator insert_or_assign(const_iterator hint, const key_type& key, T&& val)
332 {
333 // TODO: implement
334 }
335
336 template<class T>
337 iterator insert_or_assign(const_iterator hint, key_type&& key, T&& val)
338 {
339 // TODO: implement
340 }
341
342 iterator erase(const_iterator position)
343 {
344 return table_.erase(position);
345 }
346
347 size_type erase(const key_type& key)
348 {
349 return table_.erase(key);
350 }
351
352 iterator erase(const_iterator first, const_iterator last)
353 {
354 while (first != last)
355 first = erase(first);
356
357 return iterator{
358 table_.table(), first.idx(),
359 table_.size(), table_.head(first.idx())
360 };
361 }
362
363 void clear() noexcept
364 {
365 table_.clear();
366 }
367
368 void swap(unordered_map& other)
369 noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
370 noexcept(std::swap(declval<hasher>(), declval<hasher>())) &&
371 noexcept(std::swap(declval<key_equal>(), declval<key_equal>())))
372 {
373 table_.swap(other.table_);
374 std::swap(allocator_, other.allocator_);
375 }
376
377 hasher hash_function() const
378 {
379 return table_.hash_function();
380 }
381
382 key_equal key_eq() const
383 {
384 return table_.key_eq();
385 }
386
387 iterator find(const key_type& key)
388 {
389 return table_.find(key);
390 }
391
392 const_iterator find(const key_type& key) const
393 {
394 return table_.find(key);
395 }
396
397 size_type count(const key_type& key) const
398 {
399 return table_.count(key);
400 }
401
402 pair<iterator, iterator> equal_range(const key_type& key)
403 {
404 return table_.equal_range(key);
405 }
406
407 pair<const_iterator, const_iterator> equal_range(const key_type& key) const
408 {
409 return table_.equal_range(key);
410 }
411
412 mapped_type& operator[](const key_type& key)
413 {
414 auto spot = table_.find_insertion_spot(key);
415 auto bucket = get<0>(spot);
416
417 if (bucket->head)
418 {
419 auto head = bucket->head;
420 auto current = bucket->head;
421
422 do
423 {
424 if (table_.keys_equal(key, current->value))
425 return current->value.second;
426 else
427 current = current->next;
428 }
429 while (current != head);
430 }
431
432 bucket->append(new node_type{key, mapped_type{}});
433
434 return bucket->head->value.second;
435 }
436
437 mapped_type& operator[](key_type&& key)
438 {
439 auto spot = table_.find_insertion_spot(key);
440 auto bucket = get<0>(spot);
441
442 if (bucket->head)
443 {
444 auto head = bucket->head;
445 auto current = bucket->head;
446
447 do
448 {
449 if (table_.keys_equal(key, current->value))
450 return current->value.second;
451 else
452 current = current->next;
453 }
454 while (current != head);
455 }
456
457 bucket->append(new node_type{move(key), mapped_type{}});
458
459 return bucket->head->value.second;
460 }
461
462 mapped_type& at(const key_type& key)
463 {
464 // TODO: implement
465 }
466
467 const mapped_type& at(const key_type& key) const
468 {
469 // TODO: implement
470 }
471
472 size_type bucket_count() const noexcept
473 {
474 return table_.bucket_count();
475 }
476
477 size_type max_bucket_count() const noexcept
478 {
479 return table_.max_bucket_count();
480 }
481
482 size_type bucket_size(size_type idx) const
483 {
484 return table_.bucket_size(idx);
485 }
486
487 size_type bucket(const key_type& key) const
488 {
489 return table_.bucket(key);
490 }
491
492 local_iterator begin(size_type idx)
493 {
494 return table_.begin(idx);
495 }
496
497 const_local_iterator begin(size_type idx) const
498 {
499 return table_.begin(idx);
500 }
501
502 local_iterator end(size_type idx)
503 {
504 return table_.end(idx);
505 }
506
507 const_local_iterator end(size_type idx) const
508 {
509 return table_.end(idx);
510 }
511
512 const_local_iterator cbegin(size_type idx) const
513 {
514 return table_.cbegin(idx);
515 }
516
517 const_local_iterator cend(size_type idx) const
518 {
519 return table_.cend(idx);
520 }
521
522 float load_factor() const noexcept
523 {
524 return table_.load_factor();
525 }
526
527 float max_load_factor() const noexcept
528 {
529 return table_.max_load_factor();
530 }
531
532 void max_load_factor(float factor)
533 {
534 table_.max_load_factor(factor);
535 }
536
537 void rehash(size_type bucket_count)
538 {
539 table_.rehash(bucket_count);
540 }
541
542 void reserve(size_type count)
543 {
544 table_.reserve(count);
545 }
546
547 private:
548 using table_type = aux::hash_table<
549 value_type, key_type, aux::key_value_key_extractor<key_type, mapped_type>,
550 hasher, key_equal, allocator_type, size_type,
551 iterator, const_iterator, local_iterator, const_local_iterator,
552 aux::hash_single_policy
553 >;
554 using node_type = typename table_type::node_type;
555
556 table_type table_;
557 allocator_type allocator_;
558
559 static constexpr size_type default_bucket_count_{16};
560 };
561
562 /**
563 * 23.5.5, class template unordered_multimap:
564 */
565
566 template<
567 class Key, class Value,
568 class Hash = hash<Key>,
569 class Pred = equal_to<Key>,
570 class Alloc = allocator<pair<const Key, Value>>
571 >
572 class unordered_multimap;
573
574 template<class Key, class Value, class Hash, class Pred, class Alloc>
575 void swap(unordered_map<Key, Value, Hash, Pred, Alloc>& lhs,
576 unordered_map<Key, Value, Hash, Pred, Alloc>& rhs)
577 noexcept(noexcept(lhs.swap(rhs)))
578 {
579 lhs.swap(rhs);
580 }
581
582 template<class Key, class Value, class Hash, class Pred, class Alloc>
583 void swap(unordered_multimap<Key, Value, Hash, Pred, Alloc>& lhs,
584 unordered_multimap<Key, Value, Hash, Pred, Alloc>& rhs)
585 noexcept(noexcept(lhs.swap(rhs)))
586 {
587 lhs.swap(rhs);
588 }
589
590 template<class Key, class Value, class Hash, class Pred, class Alloc>
591 bool operator==(unordered_map<Key, Value, Hash, Pred, Alloc>& lhs,
592 unordered_map<Key, Value, Hash, Pred, Alloc>& rhs)
593 {
594 // TODO: implement
595 return false;
596 }
597
598 template<class Key, class Value, class Hash, class Pred, class Alloc>
599 bool operator!=(unordered_map<Key, Value, Hash, Pred, Alloc>& lhs,
600 unordered_map<Key, Value, Hash, Pred, Alloc>& rhs)
601 {
602 return !(lhs == rhs);
603 }
604
605 template<class Key, class Value, class Hash, class Pred, class Alloc>
606 bool operator==(unordered_multimap<Key, Value, Hash, Pred, Alloc>& lhs,
607 unordered_multimap<Key, Value, Hash, Pred, Alloc>& rhs)
608 {
609 // TODO: implement
610 return false;
611 }
612
613 template<class Key, class Value, class Hash, class Pred, class Alloc>
614 bool operator!=(unordered_multimap<Key, Value, Hash, Pred, Alloc>& lhs,
615 unordered_multimap<Key, Value, Hash, Pred, Alloc>& rhs)
616 {
617 return !(lhs == rhs);
618 }
619}
620
621#endif
Note: See TracBrowser for help on using the repository browser.