24 namespace _contiguous_map {
26 template<
typename K,
typename V>
28 NodeMeta(
const K& key,
const V& value):
29 pair(std::make_pair(key, value)) {}
31 std::pair<const K, V> pair;
33 bool is_black =
false;
37 int32_t equal_index_ = -1;
38 int32_t last_equal_index_ = -1;
40 int32_t parent_index_ = -1;
41 int32_t left_index_ = -1;
42 int32_t right_index_ = -1;
43 } __attribute__((aligned(8)));
50 enum Result : int8_t {
56 Result operator()(
const T& a,
const T& b)
const {
57 return (a < b) ? RESULT_LESS : (b < a) ? RESULT_GREATER : RESULT_EQUAL;
62 template<
typename K,
typename V,
typename Compare=ThreeWayCompare<K>>
75 current_node_ = map->leftmost_index_;
82 current_node_ = index;
85 auto current = _node(current_node_);
86 if(current->left_index_ > -1) {
87 previous_node_index_ = current->left_index_;
90 previous_node_index_ = -1;
98 return &map_->nodes_[index];
102 if(current_node_ < 0)
return;
104 auto current = _node(current_node_);
107 if(current->equal_index_ > -1 && list_head_index_ == -1) {
108 list_head_index_ = current_node_;
109 current_node_ = current->equal_index_;
111 }
else if(list_head_index_ > -1) {
113 current_node_ = current->equal_index_;
114 if(current_node_ == -1) {
116 current_node_ = list_head_index_;
117 list_head_index_ = -1;
118 current = _node(current_node_);
125 auto previous = current_node_;
127 if(current->right_index_ == -1) {
131 current_node_ = current->parent_index_;
132 while(current_node_ > -1) {
133 current = _node(current_node_);
134 if(previous == current->left_index_) {
138 previous = current_node_;
139 current_node_ = current->parent_index_;
144 current_node_ = current->right_index_;
145 if(current_node_ > -1) {
147 current = _node(current_node_);
148 while(current->left_index_ > -1) {
149 current_node_ = current->left_index_;
150 current = _node(current_node_);
155 previous_node_index_ = previous;
160 map_ == other.map_ &&
161 current_node_ == other.current_node_
165 int32_t current_node_ = -1;
170 int32_t list_head_index_ = -1;
171 int32_t previous_node_index_ = -1;
185 using iterator_category = std::forward_iterator_tag;
186 using value_type = std::pair<const K, V>;
187 using difference_type = uint32_t;
188 using pointer = std::pair<const K, V>*;
189 using reference = std::pair<const K, V>&;
200 bool operator==(
const iterator& other)
const {
201 return this->is_equal(other);
204 bool operator!=(
const iterator& other)
const {
205 return !this->is_equal(other);
208 reference operator*()
const {
209 return this->_node(this->current_node_)->pair;
212 pointer operator->()
const {
213 return &this->_node(this->current_node_)->pair;
229 using iterator_category = std::forward_iterator_tag;
230 using value_type = std::pair<const K, V>;
231 using difference_type = uint32_t;
232 using pointer =
const std::pair<const K, V>*;
233 using reference =
const std::pair<const K, V>&;
245 return this->is_equal(other);
249 return !this->is_equal(other);
252 reference operator*()
const {
253 return this->_node(this->current_node_)->pair;
256 pointer operator->()
const {
257 return &this->_node(this->current_node_)->pair;
265 leftmost_index_(-1) {
266 nodes_.reserve(reserve_count);
272 bool insert(
const K& key, V&& element) {
274 return _insert(std::move(k), std::move(element));
277 bool insert(
const K& key,
const V& element) {
280 return _insert(std::move(k), std::move(v));
286 leftmost_index_ = -1;
289 void shrink_to_fit() {
290 nodes_.shrink_to_fit();
293 std::size_t size()
const {
294 return nodes_.size();
297 void reserve(std::size_t size) {
298 nodes_.reserve(size);
302 return nodes_.empty();
305 iterator find(
const K& key) {
306 int32_t index = _find(key);
310 return iterator(
this, index);
313 const_iterator find(
const K &key)
const {
314 int32_t index = _find(key);
319 return const_iterator(
320 const_cast<ContiguousMultiMap*
>(
this),
325 const_iterator upper_bound(
const K& key)
const {
328 while(it != end() && it->first == key) {
336 return iterator(
this);
343 const_iterator begin()
const {
344 return const_iterator(
345 const_cast<ContiguousMultiMap*
>(
this)
349 const_iterator end()
const {
357 const K& path_key(
const std::string& path)
const {
358 const node_type* node = &nodes_[root_index_];
362 if(node->left_index_ == -1) {
363 throw std::logic_error(
"Hit end of branch");
365 node = &nodes_[node->left_index_];
366 }
else if(c ==
'R') {
367 if(node->right_index_ == -1) {
368 throw std::logic_error(
"Hit end of branch");
370 node = &nodes_[node->right_index_];
372 throw std::logic_error(
"Invalid path");
377 return node->pair.first;
380 friend class iterator_base;
382 iterator end_ = iterator(
this, -1);
383 const_iterator cend_ = const_iterator(
384 const_cast<ContiguousMultiMap*
>(
this), -1
387 int32_t _find(
const K& key)
const {
388 if(root_index_ == -1)
return -1;
390 int32_t current_index = root_index_;
391 const node_type* current = &nodes_[current_index];
394 auto order = compare_(key, current->pair.first);
396 if(order == ThreeWayCompare<K>::RESULT_EQUAL) {
397 return current_index;
398 }
else if(order == ThreeWayCompare<K>::RESULT_LESS) {
399 if(current->left_index_ != -1) {
400 current_index = current->left_index_;
401 current = &nodes_[current_index];
406 if(current->right_index_ != -1) {
407 current_index = current->right_index_;
408 current = &nodes_[current_index];
415 return current_index;
418 void _rotate_left(node_type* node, int32_t node_index, node_type* parent=
nullptr) {
419 int32_t nnew_index = node->right_index_;
420 assert(nnew_index != -1);
423 int32_t parent_index = node->parent_index_;
424 parent = (parent) ? parent : (parent_index == -1) ? nullptr : &nodes_[parent_index];
426 node_type* nnew = &nodes_[nnew_index];
428 node->right_index_ = nnew->left_index_;
429 nnew->left_index_ = node_index;
430 node->parent_index_ = nnew_index;
432 if(node->right_index_ != -1) {
433 nodes_[node->right_index_].parent_index_ = node_index;
437 if(node_index == parent->left_index_) {
438 parent->left_index_ = nnew_index;
439 }
else if(node_index == parent->right_index_) {
440 parent->right_index_ = nnew_index;
444 nnew->parent_index_ = parent_index;
447 void _rotate_right(node_type* node, int32_t node_index, node_type* parent=
nullptr) {
448 int32_t nnew_index = node->left_index_;
449 assert(nnew_index != -1);
452 int32_t parent_index = node->parent_index_;
453 parent = (parent) ? parent : (parent_index == -1) ? nullptr : &nodes_[parent_index];
455 node_type* nnew = &nodes_[nnew_index];
457 node->left_index_ = nnew->right_index_;
458 nnew->right_index_ = node_index;
459 node->parent_index_ = nnew_index;
461 if(node->left_index_ != -1) {
462 nodes_[node->left_index_].parent_index_ = node_index;
466 if(node_index == parent->left_index_) {
467 parent->left_index_ = nnew_index;
468 }
else if(node_index == parent->right_index_) {
469 parent->right_index_ = nnew_index;
473 nnew->parent_index_ = parent_index;
476 void _insert_repair_tree(node_type* node, int32_t node_index) {
479 if(node->parent_index_ == -1) {
480 node->is_black =
true;
484 assert(node->parent_index_ != -1);
485 node_type* parent = &nodes_[node->parent_index_];
488 if(parent->is_black) {
492 node_type* grandparent = (parent->parent_index_ == -1) ?
493 nullptr : &nodes_[parent->parent_index_];
495 int32_t parent_sibling_index = (!grandparent) ? -1 :
496 (grandparent->left_index_ == node->parent_index_) ?
497 grandparent->right_index_ : grandparent->left_index_;
499 node_type* parent_sibling = (parent_sibling_index == -1) ? nullptr : &nodes_[parent_sibling_index];
502 if(parent_sibling && !parent_sibling->is_black) {
504 parent->is_black =
true;
505 parent_sibling->is_black =
true;
506 grandparent->is_black =
false;
509 _insert_repair_tree(grandparent, parent->parent_index_);
512 if(node_index == parent->right_index_ && node->parent_index_ == grandparent->left_index_) {
513 _rotate_left(parent, node->parent_index_, grandparent);
515 node_index = node->left_index_;
516 node = &nodes_[node->left_index_];
518 assert(node->parent_index_ != -1);
519 parent = &nodes_[node->parent_index_];
521 assert(parent->parent_index_ != -1);
522 grandparent = &nodes_[parent->parent_index_];
524 }
else if(node_index == parent->left_index_ && node->parent_index_ == grandparent->right_index_) {
525 _rotate_right(parent, node->parent_index_, grandparent);
527 node_index = node->right_index_;
528 node = &nodes_[node->right_index_];
530 assert(node->parent_index_ != -1);
531 parent = &nodes_[node->parent_index_];
533 assert(parent->parent_index_ != -1);
534 grandparent = &nodes_[parent->parent_index_];
537 if(node_index == parent->left_index_) {
538 _rotate_right(grandparent, parent->parent_index_);
540 _rotate_left(grandparent, parent->parent_index_);
546 parent->is_black =
true;
547 grandparent->is_black =
false;
551 bool _insert(K&& key, V&& value) {
552 if(root_index_ == -1) {
554 leftmost_index_ = root_index_ = new_node(-1, std::move(key), std::move(value));
555 nodes_.back().is_black =
true;
561 bool is_black = _insert_recurse(
562 root_index_, std::move(key), std::move(value), &new_index
565 node_type* inserted = (new_index > -1) ? &nodes_[new_index] :
nullptr;
567 auto ret = new_index > 1;
568 if(new_index > -1 && !is_black) {
570 _insert_repair_tree(inserted, new_index);
573 if(inserted->parent_index_ == -1) {
574 root_index_ = new_index;
576 node_type* parent = inserted;
577 while(parent->parent_index_ != -1) {
578 node_type* next_parent = &nodes_[parent->parent_index_];
580 if(next_parent->parent_index_ == -1) {
581 root_index_ = parent->parent_index_;
585 parent = next_parent;
592 assert(leftmost_index_ > -1);
596 if(inserted && inserted->parent_index_ == leftmost_index_) {
597 node_type* p = &nodes_[inserted->parent_index_];
598 if(p && p->left_index_ == new_index) {
599 leftmost_index_ = new_index;
607 inline int32_t new_node(int32_t parent_index, K&& key, V&& value) {
608 auto ret = (int32_t) nodes_.size();
610 node_type n(key, value);
611 n.parent_index_ = parent_index;
612 nodes_.push_back(std::move(n));
617 bool _insert_recurse(int32_t root_index, K&& key, V&& value, int32_t* new_index) {
618 assert(root_index > -1);
620 node_type* root = &nodes_[root_index];
622 auto order = compare_(key, root->pair.first);
623 if(order == ThreeWayCompare<K>::RESULT_EQUAL) {
627 auto new_idx = new_node(-1, std::move(key), std::move(value));
628 root = &nodes_[root_index];
636 if(root->last_equal_index_ > -1) {
637 left = &nodes_[left->last_equal_index_];
640 left->equal_index_ = new_idx;
641 root->last_equal_index_ = new_idx;
648 *new_index = new_idx;
652 }
else if(order == ThreeWayCompare<K>::RESULT_LESS) {
653 if(root->left_index_ == -1) {
654 auto new_idx = new_node(root_index, std::move(key), std::move(value));
656 root = &nodes_[root_index];
657 root->left_index_ = new_idx;
660 *new_index = new_idx;
663 return root->is_black;
665 return _insert_recurse(
666 root->left_index_, std::move(key), std::move(value), new_index
670 if(root->right_index_ == -1) {
671 auto new_idx = new_node(root_index, std::move(key), std::move(value));
673 root = &nodes_[root_index];
674 root->right_index_ = new_idx;
677 *new_index = new_idx;
680 return root->is_black;
682 return _insert_recurse(
683 root->right_index_, std::move(key), std::move(value), new_index
689 std::vector<node_type> nodes_;
691 int32_t root_index_ = -1;
692 int32_t leftmost_index_ = -1;
698 template<
typename K,
typename V,
typename Compare=ThreeWayCompare<K>>
712 std::size_t size()
const {
716 bool insert(
const K& key, V&& element) {
717 if(map_.find(key) == map_.end()) {
718 map_.insert(key, std::move(element));
725 const V& at(
const K& key)
const {
726 auto it = map_.find(key);
728 if(it == map_.end()) {
729 throw std::out_of_range(
"Key not found");
735 bool insert(
const K& key,
const V& element) {
736 if(map_.find(key) == map_.end()) {
737 map_.insert(key, element);
744 void shrink_to_fit() {
745 map_.shrink_to_fit();
753 return map_.find(key);
757 return map_.find(key);