LCOV - code coverage report
Current view: top level - src/immer/detail/hamts - champ_iterator.hpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 52 56 92.9 %
Date: 2025-02-23 09:33:43 Functions: 4 4 100.0 %

          Line data    Source code
       1             : //
       2             : // immer: immutable data structures for C++
       3             : // Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
       4             : //
       5             : // This software is distributed under the Boost Software License, Version 1.0.
       6             : // See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
       7             : //
       8             : 
       9             : #pragma once
      10             : 
      11             : #include <immer/detail/hamts/champ.hpp>
      12             : #include <immer/detail/iterator_facade.hpp>
      13             : 
      14             : namespace immer {
      15             : namespace detail {
      16             : namespace hamts {
      17             : 
      18             : template <typename T, typename Hash, typename Eq, typename MP, bits_t B>
      19             : struct champ_iterator
      20             :     : iterator_facade<champ_iterator<T, Hash, Eq, MP, B>,
      21             :                       std::forward_iterator_tag,
      22             :                       T,
      23             :                       const T&,
      24             :                       std::ptrdiff_t,
      25             :                       const T*>
      26             : {
      27             :     using tree_t = champ<T, Hash, Eq, MP, B>;
      28             :     using node_t = typename tree_t::node_t;
      29             : 
      30             :     struct end_t
      31             :     {};
      32             : 
      33       79356 :     champ_iterator(const tree_t& v)
      34       79356 :         : depth_{0}
      35             :     {
      36       79356 :         if (v.root->datamap()) {
      37       67168 :             cur_ = v.root->values();
      38       67168 :             end_ = v.root->values() + v.root->data_count();
      39             :         } else {
      40       12188 :             cur_ = end_ = nullptr;
      41             :         }
      42       79356 :         path_[0] = &v.root;
      43       79356 :         ensure_valid_();
      44       79356 :     }
      45             : 
      46       79356 :     champ_iterator(const tree_t& v, end_t)
      47             :         : cur_{nullptr}
      48             :         , end_{nullptr}
      49             :         , depth_{0}
      50             :     {
      51             :         path_[0] = &v.root;
      52             :     }
      53             : 
      54             :     champ_iterator(const champ_iterator& other)
      55             :         : cur_{other.cur_}
      56             :         , end_{other.end_}
      57             :         , depth_{other.depth_}
      58             :     {
      59             :         std::copy(other.path_, other.path_ + depth_ + 1, path_);
      60             :     }
      61             : 
      62             : private:
      63             :     friend iterator_core_access;
      64             : 
      65             :     T* cur_;
      66             :     T* end_;
      67             :     count_t depth_;
      68             :     node_t* const* path_[max_depth<B> + 1] = {
      69             :         0,
      70             :     };
      71             : 
      72      350082 :     void increment()
      73             :     {
      74      350082 :         ++cur_;
      75      350082 :         ensure_valid_();
      76             :     }
      77             : 
      78      114914 :     bool step_down()
      79             :     {
      80      114914 :         if (depth_ < max_depth<B>) {
      81      114914 :             auto parent = *path_[depth_];
      82      114914 :             assert(parent);
      83      114914 :             if (parent->nodemap()) {
      84       27422 :                 ++depth_;
      85       27422 :                 path_[depth_] = parent->children();
      86       27422 :                 auto child    = *path_[depth_];
      87       27422 :                 assert(child);
      88       27422 :                 if (depth_ < max_depth<B>) {
      89       27422 :                     if (child->datamap()) {
      90       27422 :                         cur_ = child->values();
      91       27422 :                         end_ = cur_ + child->data_count();
      92             :                     }
      93             :                 } else {
      94           0 :                     cur_ = child->collisions();
      95           0 :                     end_ = cur_ + child->collision_count();
      96             :                 }
      97       27422 :                 return true;
      98             :             }
      99             :         }
     100             :         return false;
     101             :     }
     102             : 
     103       87492 :     bool step_right()
     104             :     {
     105      114892 :         while (depth_ > 0) {
     106       35627 :             auto parent = *path_[depth_ - 1];
     107       35627 :             auto last   = parent->children() + parent->children_count();
     108       35627 :             auto next   = path_[depth_] + 1;
     109       35627 :             if (next < last) {
     110        8227 :                 path_[depth_] = next;
     111        8227 :                 auto child    = *path_[depth_];
     112        8227 :                 assert(child);
     113        8227 :                 if (depth_ < max_depth<B>) {
     114        8227 :                     if (child->datamap()) {
     115        7199 :                         cur_ = child->values();
     116        7199 :                         end_ = cur_ + child->data_count();
     117             :                     }
     118             :                 } else {
     119           0 :                     cur_ = child->collisions();
     120           0 :                     end_ = cur_ + child->collision_count();
     121             :                 }
     122        8227 :                 return true;
     123             :             }
     124       27400 :             --depth_;
     125             :         }
     126             :         return false;
     127             :     }
     128             : 
     129      429438 :     void ensure_valid_()
     130             :     {
     131      437665 :         while (cur_ == end_) {
     132      114914 :             while (step_down())
     133       27422 :                 if (cur_ != end_)
     134             :                     return;
     135       87492 :             if (!step_right()) {
     136             :                 // end of sequence
     137       79265 :                 assert(depth_ == 0);
     138       79265 :                 cur_ = end_ = nullptr;
     139       79265 :                 return;
     140             :             }
     141             :         }
     142             :     }
     143             : 
     144      429438 :     bool equal(const champ_iterator& other) const { return cur_ == other.cur_; }
     145             : 
     146      350173 :     const T& dereference() const { return *cur_; }
     147             : };
     148             : 
     149             : } // namespace hamts
     150             : } // namespace detail
     151             : } // namespace immer

Generated by: LCOV version 1.14