General Purpose library for Freestanding C++ and POSIX systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

129 lines
2.1 KiB

#pragma once
#include <gp/utils/iterators/iterator_properties.hpp>
#include <cstddef>
#include <cstdint>
namespace gp {
struct index_to_1 {
size_t value;
index_to_1(size_t v) : value{v + 1}
{}
void left() {
value <<= 1;
}
void right() {
value = (value << 1) + 1;
}
void up() {
value >>= 1;
}
bool is_right() const {
return value & 1;
}
bool is_left() const {
return !(value & 1);
}
bool is_root() const {
return value == 1;
}
operator size_t() {
return value - 1;
}
};
template<typename reflect, typename T, int sign = 1>
struct flat_tree_iterator {
reflect& tree;
size_t index;
bool has_right(index_to_1 v) const {
v.right();
return (v < tree.data().size()) && (tree.data()[v].has_value());
}
bool has_left(index_to_1 v) const {
v.left();
return (v < tree.data().size()) && (tree.data()[v].has_value());
}
flat_tree_iterator& operator++() {
index = next();
return *this;
}
flat_tree_iterator operator++(int) {
auto cpy = *this;
index = next();
return cpy;
}
size_t next() const {
index_to_1 it{index};
enum class cases {
right_climber,
left_climber,
descender,
starter
};
const cases current_case = [&](){
if(index == (size_t)-1) {
return cases::starter;
} else if(has_right(it)) {
return cases::descender;
} else if(it.is_left()) {
return cases::left_climber;
} else {
return cases::right_climber;
}
}();
switch(current_case) {
case cases::starter: {
it = index_to_1{0};
while(has_left(it)) {
it.left();
}
} break;
case cases::descender: {
it.right();
while(has_left(it)) {
it.left();
}
} break;
case cases::left_climber: {
it.up();
} break;
case cases::right_climber: {
while(it.is_right()) {
it.up();
}
if(it.is_root()) {
it.value = -1;
}
} break;
}
return it;
}
bool operator!=(flat_tree_iterator rhs) {
return index != rhs.index;
}
T& operator*() {
return tree.data_[index].value();
}
};
}