General Purpose library for Freestanding C++ and POSIX systems
Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 

130 righe
2.7 KiB

#pragma once
#include <stddef.h>
#include "gp_config.hpp"
#include "gp/algorithm/move.hpp"
#include "gp/iterator.hpp"
namespace gp{
template<typename T, size_t _capacity>
class indexed_array{
size_t data_top = 0;
size_t available_indexes_top = 0;
size_t remove_top = 0;
T data_table[_capacity];
size_t available_indexes[_capacity];
size_t translation_table[_capacity];
size_t reverse_translation_table[_capacity];
size_t remove_table[_capacity];
public:
indexed_array() {}
size_t push(T&& value) {
size_t index;
gp_config::assertion(data_top+1 != _capacity, "Indexed array capacity exceeded");
if(available_indexes_top) {
available_indexes_top--;
index = available_indexes[available_indexes_top];
} else {
index = data_top;
}
new(&data_table[data_top]) T(gp::move(value));
translation_table[index] = data_top;
reverse_translation_table[data_top] = index;
++data_top;
return index;
}
void pop(size_t idx) {
size_t v_idx = translation_table[idx];
available_indexes[available_indexes_top] = idx;
++available_indexes_top;
translation_table[idx] = -1;
--data_top;
if(v_idx < data_top) {
size_t u_idx = reverse_translation_table[data_top];
data_table[v_idx] = gp::move(data_table[data_top]);
::operator delete(&data_table[data_top], &data_table[data_top]);
data_table[data_top].~T();
translation_table[u_idx] = v_idx;
reverse_translation_table[v_idx] = u_idx;
}
}
void reset() {
auto it = data_table;
auto end = data_table+data_top;
while(it != end) {
::operator delete(it, it);
++it;
}
data_top = 0;
available_indexes_top = 0;
remove_top = 0;
}
void mark_internal_for_removal(size_t i_idx) {
remove_table[remove_top] = reverse_translation_table[i_idx];
++remove_top;
}
void mark_for_removal(size_t idx) {
remove_table[remove_top] = idx;
++remove_top;
}
void sweep_removed() {
auto it = remove_table;
auto end = remove_table+remove_top;
while(it != end) {
pop(*it);
++it;
}
}
bool has(size_t idx) {
if(idx > data_top) return false;
if(translation_table[idx] == -1) return false;
return true;
}
pointer_iterator<T> begin()
{
return data_table;
}
pointer_iterator<T> end()
{
return data_table+data_top;
}
const_pointer_iterator<T> cbegin()
{
return data_table;
}
const_pointer_iterator<T> cend()
{
return data_table+data_top;
}
size_t size() {
return data_top;
}
size_t capacity() {
return _capacity;
}
T& operator[](size_t idx) {
gp_config::assertion(idx < data_top, "Bad indexed array access");
return data_table[translation_table[idx]];
}
};
}