#pragma once #include #include "gp_config.hpp" #include "gp/algorithm/move.hpp" #include "gp/iterator.hpp" namespace gp{ template 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 begin() { return data_table; } pointer_iterator end() { return data_table+data_top; } const_pointer_iterator cbegin() { return data_table; } const_pointer_iterator 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]]; } }; }