yfast 0.6.1
Loading...
Searching...
No Matches
fastmap.h
1#ifndef _YFAST_FASTMAP_H
2#define _YFAST_FASTMAP_H
3
4#include <functional>
5#include <initializer_list>
6#include <iterator>
7#include <memory>
8#include <stdexcept>
9#include <utility>
10
11#include <yfast/impl/yfast.h>
12#include <yfast/internal/concepts.h>
13#include <yfast/internal/default_hash.h>
14#include <yfast/internal/fastmap.h>
15#include <yfast/internal/bit_extractor.h>
16#include <yfast/utils/maybe_const.h>
17
18namespace yfast {
19
30template <
31 typename Key,
32 typename Value,
33 unsigned int H,
35 internal::MapGeneric<typename BitExtractor::ShiftResult, std::uintptr_t> Hash = internal::DefaultHash<typename BitExtractor::ShiftResult, std::uintptr_t>,
36 typename Compare = std::less<Key>,
37 typename ArbitraryAllocator = std::allocator<std::pair<Key, Value>>
38>
39class fastmap {
40public:
44 typedef Key key_type;
45
49 typedef Value value_type;
50
54 static constexpr unsigned int KeyLength = H;
55
56private:
57 typedef internal::YFastLeaf<Key, Value> YFastLeaf;
58
59 typedef typename std::allocator_traits<ArbitraryAllocator>::template rebind_alloc<YFastLeaf> Alloc;
60
62
63 template <bool Const>
64 class IteratorBase: private YFastTrie::Where {
65 friend class fastmap;
66
67 using YFastTrie::Where::leaf;
68 using YFastTrie::Where::xleaf;
69 using YFastTrie::Where::trie;
70
71 unsigned int _last_rebuild = 0;
72
73 public:
74 typedef const typename YFastLeaf::Key key_type;
76
77 typedef std::bidirectional_iterator_tag iterator_category; // TODO: random access
78 typedef std::ptrdiff_t difference_type;
79 typedef value_type* pointer;
80 typedef value_type& reference;
81
82 protected:
83 IteratorBase() = default;
84 explicit IteratorBase(const typename YFastTrie::Where& where): YFastTrie::Where(where), _last_rebuild(trie->rebuilds()) {}
85
86 template <bool Const_>
87 bool same_as(const IteratorBase<Const_>& other) const {
88 return trie == other.trie && leaf == other.leaf;
89 }
90
91 void forward() {
92 auto succ = YFastTrie::Value::succ(leaf);
93 if (succ != nullptr) {
94 leaf = succ;
95 }
96 else {
97 if (trie->rebuilds() > _last_rebuild) {
98 auto where = trie->find(leaf->key);
99 xleaf = where.xleaf;
100 _last_rebuild = trie->rebuilds();
101 }
102 xleaf = xleaf->nxt;
103 if (xleaf != nullptr) {
104 leaf = xleaf->value.leftmost();
105 }
106 else {
107 leaf = nullptr;
108 }
109 }
110 }
111
112 void backward() {
113 auto pred = YFastTrie::Value::pred(leaf);
114 if (pred != nullptr) {
115 leaf = pred;
116 }
117 else {
118 if (trie->rebuilds() > _last_rebuild) {
119 auto where = trie->find(leaf->key);
120 xleaf = where.xleaf;
121 _last_rebuild = trie->rebuilds();
122 }
123 xleaf = xleaf->prv;
124 if (xleaf != nullptr) {
125 leaf = xleaf->value.rightmost();
126 }
127 else {
128 leaf = nullptr;
129 }
130 }
131 }
132
133 public:
134 key_type& key() const {
135 if (leaf == nullptr) {
136 throw std::out_of_range("yfast::fastmap::iterator");
137 }
138 return leaf->key;
139 }
140
141 value_type& value() const {
142 if (leaf == nullptr) {
143 throw std::out_of_range("yfast::fastmap::iterator");
144 }
145 return leaf->deref();
146 }
147
148 value_type& operator * () const {
149 if (leaf == nullptr) {
150 throw std::out_of_range("yfast::fastmap::iterator");
151 }
152 return leaf->deref();
153 }
154
155 value_type* operator -> () const {
156 if (leaf == nullptr) {
157 throw std::out_of_range("yfast::fastmap::iterator");
158 }
159 return &leaf->deref();
160 }
161 };
162
163 template <bool Const>
164 class ForwardIteratorBase: public IteratorBase<Const> {
165 friend class fastmap;
166
167 using IteratorBase<Const>::leaf;
168 using IteratorBase<Const>::trie;
169 using IteratorBase<Const>::same_as;
170 using IteratorBase<Const>::forward;
171 using IteratorBase<Const>::backward;
172
173 protected:
174 ForwardIteratorBase() = default;
175 explicit ForwardIteratorBase(const typename YFastTrie::Where& where): IteratorBase<Const>(where) {}
176
177 void inc() {
178 if (leaf != nullptr) {
179 forward();
180 }
181 }
182
183 void dec() {
184 if (leaf != nullptr) {
185 backward();
186 }
187 else {
188 *this = ForwardIteratorBase(trie->rightmost());
189 }
190 }
191
192 public:
193 template <bool Const_>
194 bool operator == (const ForwardIteratorBase<Const_>& other) const {
195 return same_as(other);
196 }
197
198 template <bool Const_>
199 bool operator != (const ForwardIteratorBase<Const_>& other) const {
200 return !same_as(other);
201 }
202 };
203
204 template <bool Const>
205 class ReverseIteratorBase: public IteratorBase<Const> {
206 friend class fastmap;
207
208 using IteratorBase<Const>::leaf;
209 using IteratorBase<Const>::trie;
210 using IteratorBase<Const>::same_as;
211 using IteratorBase<Const>::forward;
212 using IteratorBase<Const>::backward;
213
214 protected:
215 ReverseIteratorBase() = default;
216 explicit ReverseIteratorBase(const typename YFastTrie::Where& where): IteratorBase<Const>(where) {}
217
218 void inc() {
219 if (leaf != nullptr) {
220 backward();
221 }
222 }
223
224 void dec() {
225 if (leaf != nullptr) {
226 forward();
227 }
228 else {
229 *this = ReverseIteratorBase(trie->leftmost());
230 }
231 }
232
233 public:
234 template <bool Const_>
235 bool operator == (const ReverseIteratorBase<Const_>& other) const {
236 return same_as(other);
237 }
238
239 template <bool Const_>
240 bool operator != (const ReverseIteratorBase<Const_>& other) const {
241 return !same_as(other);
242 }
243 };
244
245public:
246 class reverse_iterator;
248
252 class iterator: public ForwardIteratorBase<false> {
253 friend class fastmap;
254
255 using ForwardIteratorBase<false>::inc;
256 using ForwardIteratorBase<false>::dec;
257
258 explicit iterator(const typename YFastTrie::Where& where): ForwardIteratorBase<false>(where) {}
259
260 public:
261 iterator() = default;
262 iterator(const iterator& other) = default;
263
264 iterator& operator ++ () {
265 inc();
266 return *this;
267 }
268
269 iterator operator ++ (int) {
270 auto i = *this;
271 inc();
272 return i;
273 }
274
275 iterator& operator -- () {
276 dec();
277 return *this;
278 }
279
280 iterator operator -- (int) {
281 auto i = *this;
282 dec();
283 return i;
284 }
285
291 auto i = *this;
292 const typename YFastTrie::Where& where = --i;
293 return reverse_iterator(where);
294 }
295 };
296
300 class const_iterator: public ForwardIteratorBase<true> {
301 friend class fastmap;
302
303 using ForwardIteratorBase<true>::inc;
304 using ForwardIteratorBase<true>::dec;
305
306 explicit const_iterator(const typename YFastTrie::Where& where): ForwardIteratorBase<true>(where) {}
307
308 public:
309 const_iterator() = default;
310 const_iterator(const const_iterator& other) = default;
311 const_iterator(const iterator& other): ForwardIteratorBase<true>(other) {}
312
313 const_iterator& operator ++ () {
314 inc();
315 return *this;
316 }
317
318 const_iterator operator ++ (int) {
319 auto i = *this;
320 inc();
321 return i;
322 }
323
324 const_iterator& operator -- () {
325 dec();
326 return *this;
327 }
328
329 const_iterator operator -- (int) {
330 auto i = *this;
331 dec();
332 return i;
333 }
334
340 auto i = *this;
341 const typename YFastTrie::Where& where = --i;
342 return const_reverse_iterator(where);
343 }
344 };
345
349 class reverse_iterator: public ReverseIteratorBase<false> {
350 friend class fastmap;
351
352 using ReverseIteratorBase<false>::inc;
353 using ReverseIteratorBase<false>::dec;
354
355 explicit reverse_iterator(const typename YFastTrie::Where& where): ReverseIteratorBase<false>(where) {}
356
357 public:
358 reverse_iterator() = default;
359 reverse_iterator(const reverse_iterator& other) = default;
360
361 reverse_iterator& operator ++ () {
362 inc();
363 return *this;
364 }
365
366 reverse_iterator operator ++ (int) {
367 auto i = *this;
368 inc();
369 return i;
370 }
371
372 reverse_iterator& operator -- () {
373 dec();
374 return *this;
375 }
376
377 reverse_iterator operator -- (int) {
378 auto i = *this;
379 dec();
380 return i;
381 }
382 };
383
387 class const_reverse_iterator: public ReverseIteratorBase<true> {
388 friend class fastmap;
389
390 using ReverseIteratorBase<true>::inc;
391 using ReverseIteratorBase<true>::dec;
392
393 explicit const_reverse_iterator(const typename YFastTrie::Where& where): ReverseIteratorBase<true>(where) {}
394
395 public:
396 const_reverse_iterator() = default;
397 const_reverse_iterator(const const_reverse_iterator& other) = default;
398 const_reverse_iterator(const reverse_iterator& other): ReverseIteratorBase<true>(other) {}
399
400 const_reverse_iterator& operator ++ () {
401 inc();
402 return *this;
403 }
404
405 const_reverse_iterator operator ++ (int) {
406 auto i = *this;
407 inc();
408 return i;
409 }
410
411 const_reverse_iterator& operator -- () {
412 dec();
413 return *this;
414 }
415
416 const_reverse_iterator operator -- (int) {
417 auto i = *this;
418 dec();
419 return i;
420 }
421 };
422
423private:
424 Alloc _alloc;
425 YFastTrie _trie;
426
427public:
428 explicit fastmap(BitExtractor bx = BitExtractor(), Compare cmp = Compare(), ArbitraryAllocator alloc = ArbitraryAllocator()): _alloc(alloc), _trie(bx, cmp, alloc) {}
429 fastmap(std::initializer_list<std::pair<Key, Value>> array, BitExtractor bx = BitExtractor(), Compare cmp = Compare(), ArbitraryAllocator alloc = ArbitraryAllocator()): _alloc(alloc), _trie(bx, cmp, alloc) {
430 for (auto& pair: array) {
431 insert(pair.first, pair.second);
432 }
433 }
434 fastmap(const fastmap& other) = delete;
435 fastmap(fastmap&& other) noexcept = default;
436
437 ~fastmap() { clear(); }
438
442 [[nodiscard]] std::size_t size() const { return _trie.size(); }
443
447 [[nodiscard]] bool empty() const { return _trie.size() == 0; }
448
453 return iterator(_trie.leftmost());
454 }
455
460 return iterator(_trie.nowhere);
461 }
462
467 return const_iterator(_trie.leftmost());
468 }
469
474 return const_iterator(_trie.nowhere);
475 }
476
481 return const_iterator(_trie.leftmost());
482 }
483
488 return const_iterator(_trie.nowhere);
489 }
490
495 return reverse_iterator(_trie.rightmost());
496 }
497
502 return reverse_iterator(_trie.nowhere);
503 }
504
509 return const_reverse_iterator(_trie.rightmost());
510 }
511
516 return const_reverse_iterator(_trie.nowhere);
517 }
518
523 return const_reverse_iterator(_trie.rightmost());
524 }
525
530 return const_reverse_iterator(_trie.nowhere);
531 }
532
538 iterator find(const Key& key) {
539 auto where = _trie.find(key);
540 return iterator(where);
541 }
542
548 const_iterator find(const Key& key) const {
549 auto where = _trie.find(key);
550 return const_iterator(where);
551 }
552
559 iterator pred(const Key& key, bool strict = false) {
560 auto where = _trie.pred(key, strict);
561 return iterator(where);
562 }
563
570 const_iterator pred(const Key& key, bool strict = false) const {
571 auto where = _trie.pred(key, strict);
572 return const_iterator(where);
573 }
574
581 iterator succ(const Key& key, bool strict = false) {
582 auto where = _trie.succ(key, strict);
583 return iterator(where);
584 }
585
592 const_iterator succ(const Key& key, bool strict = false) const {
593 auto where = _trie.succ(key, strict);
594 return const_iterator(where);
595 }
596
602 iterator lower_bound(const Key& key) {
603 return succ(key);
604 }
605
611 const_iterator lower_bound(const Key& key) const {
612 return succ(key);
613 }
614
620 iterator upper_bound(const Key& key) {
621 return succ(key, true);
622 }
623
629 const_iterator upper_bound(const Key& key) const {
630 return succ(key, true);
631 }
632
638 typename iterator::value_type& operator [] (const Key& key) {
639 auto i = find(key);
640 if (i == end()) {
641 YFastLeaf* leaf = std::allocator_traits<Alloc>::allocate(_alloc, 1);
642 std::allocator_traits<Alloc>::construct(_alloc, leaf, key);
643 auto where = _trie.insert(leaf);
644 where.leaf = leaf;
645 i = iterator(where);
646 }
647 return *i;
648 }
649
655 typename const_iterator::value_type& at(const Key& key) const {
656 auto i = find(key);
657 if (i == end()) {
658 throw std::out_of_range("yfast::fastmap::at");
659 }
660 return *i;
661 }
662
669 template <typename ... Args>
670 iterator insert(const Key& key, Args ... args) {
671 YFastLeaf* leaf = std::allocator_traits<Alloc>::allocate(_alloc, 1);
672 std::allocator_traits<Alloc>::construct(_alloc, leaf, key, args ...);
673 auto where = _trie.insert(leaf);
674 if (where.leaf != nullptr) {
675 std::allocator_traits<Alloc>::destroy(_alloc, where.leaf);
676 std::allocator_traits<Alloc>::deallocate(_alloc, where.leaf, 1);
677 }
678 where.leaf = leaf;
679 return iterator(where);
680 }
681
687 template <typename Iterator>
688 Iterator erase(const Iterator& i) {
689 if (i.trie != &_trie) {
690 throw std::invalid_argument("yfast::fastmap::erase");
691 }
692 if (i.leaf == nullptr) {
693 return i;
694 }
695 auto j = i;
696 ++j;
697 _trie.remove(i.leaf, i.xleaf);
698 std::allocator_traits<Alloc>::destroy(_alloc, i.leaf);
699 std::allocator_traits<Alloc>::deallocate(_alloc, i.leaf, 1);
700 return j;
701 }
702
708 bool erase(const Key& key) {
709 auto i = find(key);
710 if (i == end()) {
711 return false;
712 }
713 _trie.remove(i);
714 return true;
715 }
716
720 void clear() {
721 typename YFastTrie::XFastLeaf* xleaf = _trie.leftmost().xleaf;
722 while (xleaf != nullptr) {
723 destroy_subtree(xleaf->value.root());
724 xleaf = xleaf->nxt;
725 }
726 _trie.clear();
727 }
728
729private:
730 void destroy_subtree(YFastLeaf* leaf) {
731 if (leaf != nullptr) {
732 destroy_subtree(leaf->left());
733 destroy_subtree(leaf->right());
734 std::allocator_traits<Alloc>::destroy(_alloc, leaf);
735 std::allocator_traits<Alloc>::deallocate(_alloc, leaf, 1);
736 }
737 }
738};
739
740}
741
742#endif
Definition fastmap.h:300
const_reverse_iterator make_reverse() const
Definition fastmap.h:339
Definition fastmap.h:252
reverse_iterator make_reverse() const
Definition fastmap.h:290
Definition fastmap.h:349
Definition fastmap.h:39
const_iterator::value_type & at(const Key &key) const
Definition fastmap.h:655
const_iterator lower_bound(const Key &key) const
Definition fastmap.h:611
void clear()
Definition fastmap.h:720
iterator insert(const Key &key, Args ... args)
Definition fastmap.h:670
Key key_type
Definition fastmap.h:44
const_reverse_iterator rbegin() const
Definition fastmap.h:508
iterator find(const Key &key)
Definition fastmap.h:538
iterator succ(const Key &key, bool strict=false)
Definition fastmap.h:581
const_iterator cend() const
Definition fastmap.h:487
const_reverse_iterator crend() const
Definition fastmap.h:529
const_iterator find(const Key &key) const
Definition fastmap.h:548
const_reverse_iterator rend() const
Definition fastmap.h:515
const_iterator cbegin() const
Definition fastmap.h:480
iterator begin()
Definition fastmap.h:452
bool empty() const
Definition fastmap.h:447
Iterator erase(const Iterator &i)
Definition fastmap.h:688
static constexpr unsigned int KeyLength
Definition fastmap.h:54
iterator upper_bound(const Key &key)
Definition fastmap.h:620
iterator pred(const Key &key, bool strict=false)
Definition fastmap.h:559
const_iterator begin() const
Definition fastmap.h:466
reverse_iterator rbegin()
Definition fastmap.h:494
iterator::value_type & operator[](const Key &key)
Definition fastmap.h:638
std::size_t size() const
Definition fastmap.h:442
iterator end()
Definition fastmap.h:459
bool erase(const Key &key)
Definition fastmap.h:708
reverse_iterator rend()
Definition fastmap.h:501
const_reverse_iterator crbegin() const
Definition fastmap.h:522
const_iterator end() const
Definition fastmap.h:473
const_iterator succ(const Key &key, bool strict=false) const
Definition fastmap.h:592
const_iterator upper_bound(const Key &key) const
Definition fastmap.h:629
Value value_type
Definition fastmap.h:49
const_iterator pred(const Key &key, bool strict=false) const
Definition fastmap.h:570
iterator lower_bound(const Key &key)
Definition fastmap.h:602
Definition yfast.h:32
Definition bit_extractor.h:14
Definition concepts.h:18
Definition concepts.h:9
Definition fastmap.h:14
Definition maybe_const.h:7