mirror of
https://github.com/BlackMATov/ecs.hpp.git
synced 2025-12-16 22:19:21 +07:00
sparse containers refactoring
This commit is contained in:
107
ecs.hpp
107
ecs.hpp
@@ -212,7 +212,8 @@ namespace ecs_hpp
|
|||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template < typename T
|
template < typename T
|
||||||
, bool = std::is_unsigned<T>::value && sizeof(T) <= sizeof(std::size_t) >
|
, bool = std::is_unsigned<T>::value
|
||||||
|
&& sizeof(T) <= sizeof(std::size_t) >
|
||||||
struct sparse_unsigned_indexer {
|
struct sparse_unsigned_indexer {
|
||||||
std::size_t operator()(const T v) const noexcept {
|
std::size_t operator()(const T v) const noexcept {
|
||||||
return static_cast<std::size_t>(v);
|
return static_cast<std::size_t>(v);
|
||||||
@@ -250,8 +251,7 @@ namespace ecs_hpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
iterator end() noexcept {
|
iterator end() noexcept {
|
||||||
using dt = typename std::iterator_traits<iterator>::difference_type;
|
return dense_.end();
|
||||||
return begin() + static_cast<dt>(size_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator begin() const noexcept {
|
const_iterator begin() const noexcept {
|
||||||
@@ -259,8 +259,7 @@ namespace ecs_hpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
const_iterator end() const noexcept {
|
const_iterator end() const noexcept {
|
||||||
using dt = typename std::iterator_traits<const_iterator>::difference_type;
|
return dense_.end();
|
||||||
return begin() + static_cast<dt>(size_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator cbegin() const noexcept {
|
const_iterator cbegin() const noexcept {
|
||||||
@@ -268,8 +267,7 @@ namespace ecs_hpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
const_iterator cend() const noexcept {
|
const_iterator cend() const noexcept {
|
||||||
using dt = typename std::iterator_traits<const_iterator>::difference_type;
|
return dense_.cend();
|
||||||
return cbegin() + static_cast<dt>(size_);
|
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
sparse_set(const Indexer& indexer = Indexer())
|
sparse_set(const Indexer& indexer = Indexer())
|
||||||
@@ -280,12 +278,11 @@ namespace ecs_hpp
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const std::size_t vi = indexer_(v);
|
const std::size_t vi = indexer_(v);
|
||||||
if ( vi >= capacity_ ) {
|
if ( vi >= sparse_.size() ) {
|
||||||
reserve(new_capacity_for_(vi + 1u));
|
sparse_.resize(new_sparse_size_for_(vi + 1u));
|
||||||
}
|
}
|
||||||
dense_[size_] = std::move(v);
|
dense_.push_back(std::move(v));
|
||||||
sparse_[vi] = size_;
|
sparse_[vi] = dense_.size() - 1u;
|
||||||
++size_;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,12 +291,11 @@ namespace ecs_hpp
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const std::size_t vi = indexer_(v);
|
const std::size_t vi = indexer_(v);
|
||||||
if ( vi >= capacity_ ) {
|
if ( vi >= sparse_.size() ) {
|
||||||
reserve(new_capacity_for_(vi + 1u));
|
sparse_.resize(new_sparse_size_for_(vi + 1u));
|
||||||
}
|
}
|
||||||
dense_[size_] = v;
|
dense_.push_back(v);
|
||||||
sparse_[vi] = size_;
|
sparse_[vi] = dense_.size() - 1u;
|
||||||
++size_;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,21 +311,21 @@ namespace ecs_hpp
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const std::size_t vi = indexer_(v);
|
const std::size_t vi = indexer_(v);
|
||||||
const std::size_t index = sparse_[vi];
|
const std::size_t dense_index = sparse_[vi];
|
||||||
dense_[index] = std::move(dense_[size_ - 1u]);
|
dense_[dense_index] = std::move(dense_.back());
|
||||||
sparse_[indexer_(dense_[index])] = index;
|
sparse_[indexer_(dense_[dense_index])] = dense_index;
|
||||||
--size_;
|
dense_.pop_back();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() noexcept {
|
void clear() noexcept {
|
||||||
size_ = 0u;
|
dense_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has(const T& v) const noexcept {
|
bool has(const T& v) const noexcept {
|
||||||
const std::size_t vi = indexer_(v);
|
const std::size_t vi = indexer_(v);
|
||||||
return vi < capacity_
|
return vi < sparse_.size()
|
||||||
&& sparse_[vi] < size_
|
&& sparse_[vi] < dense_.size()
|
||||||
&& dense_[sparse_[vi]] == v;
|
&& dense_[sparse_[vi]] == v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,49 +351,27 @@ namespace ecs_hpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool empty() const noexcept {
|
bool empty() const noexcept {
|
||||||
return size_ == 0u;
|
return dense_.empty();
|
||||||
}
|
|
||||||
|
|
||||||
void reserve(std::size_t ncapacity) {
|
|
||||||
if ( ncapacity > capacity_ ) {
|
|
||||||
std::vector<T> ndense(ncapacity);
|
|
||||||
std::vector<std::size_t> nsparse(ncapacity);
|
|
||||||
std::copy(dense_.begin(), dense_.end(), ndense.begin());
|
|
||||||
std::copy(sparse_.begin(), sparse_.end(), nsparse.begin());
|
|
||||||
ndense.swap(dense_);
|
|
||||||
nsparse.swap(sparse_);
|
|
||||||
capacity_ = ncapacity;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t size() const noexcept {
|
std::size_t size() const noexcept {
|
||||||
return size_;
|
return dense_.size();
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t max_size() const noexcept {
|
|
||||||
return std::min(dense_.max_size(), sparse_.max_size());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t capacity() const noexcept {
|
|
||||||
return capacity_;
|
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
std::size_t new_capacity_for_(std::size_t nsize) const {
|
std::size_t new_sparse_size_for_(std::size_t nsize) const {
|
||||||
const std::size_t ms = max_size();
|
const std::size_t ms = sparse_.max_size();
|
||||||
if ( nsize > ms ) {
|
if ( nsize > ms ) {
|
||||||
throw std::length_error("ecs_hpp::sparse_set");
|
throw std::length_error("ecs_hpp::sparse_set");
|
||||||
}
|
}
|
||||||
if ( capacity_ >= ms / 2u ) {
|
if ( sparse_.size() >= ms / 2u ) {
|
||||||
return ms;
|
return ms;
|
||||||
}
|
}
|
||||||
return std::max(capacity_ * 2u, nsize);
|
return std::max(sparse_.size() * 2u, nsize);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
Indexer indexer_;
|
Indexer indexer_;
|
||||||
std::vector<T> dense_;
|
std::vector<T> dense_;
|
||||||
std::vector<std::size_t> sparse_;
|
std::vector<std::size_t> sparse_;
|
||||||
std::size_t size_{0u};
|
|
||||||
std::size_t capacity_{0u};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -494,8 +468,8 @@ namespace ecs_hpp
|
|||||||
if ( !keys_.has(k) ) {
|
if ( !keys_.has(k) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const std::size_t index = keys_.get_dense_index(k);
|
const std::size_t value_index = keys_.get_dense_index(k);
|
||||||
values_[index] = std::move(values_.back());
|
values_[value_index] = std::move(values_.back());
|
||||||
values_.pop_back();
|
values_.pop_back();
|
||||||
keys_.unordered_erase(k);
|
keys_.unordered_erase(k);
|
||||||
return true;
|
return true;
|
||||||
@@ -519,16 +493,16 @@ namespace ecs_hpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
T* find(const K& k) noexcept {
|
T* find(const K& k) noexcept {
|
||||||
const auto ip = keys_.find_dense_index(k);
|
const auto value_index_p = keys_.find_dense_index(k);
|
||||||
return ip.second
|
return value_index_p.second
|
||||||
? &values_[ip.first]
|
? &values_[value_index_p.first]
|
||||||
: nullptr;
|
: nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const T* find(const K& k) const noexcept {
|
const T* find(const K& k) const noexcept {
|
||||||
const auto ip = keys_.find_dense_index(k);
|
const auto value_index_p = keys_.find_dense_index(k);
|
||||||
return ip.second
|
return value_index_p.second
|
||||||
? &values_[ip.first]
|
? &values_[value_index_p.first]
|
||||||
: nullptr;
|
: nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -536,22 +510,9 @@ namespace ecs_hpp
|
|||||||
return values_.empty();
|
return values_.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void reserve(std::size_t ncapacity) {
|
|
||||||
keys_.reserve(ncapacity);
|
|
||||||
values_.reserve(ncapacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t size() const noexcept {
|
std::size_t size() const noexcept {
|
||||||
return values_.size();
|
return values_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t max_size() const noexcept {
|
|
||||||
return std::min(keys_.max_size(), values_.max_size());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t capacity() const noexcept {
|
|
||||||
return values_.capacity();
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
sparse_set<K, Indexer> keys_;
|
sparse_set<K, Indexer> keys_;
|
||||||
std::vector<T> values_;
|
std::vector<T> values_;
|
||||||
|
|||||||
@@ -112,7 +112,6 @@ TEST_CASE("detail") {
|
|||||||
|
|
||||||
REQUIRE(s.empty());
|
REQUIRE(s.empty());
|
||||||
REQUIRE_FALSE(s.size());
|
REQUIRE_FALSE(s.size());
|
||||||
REQUIRE(s.capacity() == 0u);
|
|
||||||
REQUIRE_FALSE(s.has(42u));
|
REQUIRE_FALSE(s.has(42u));
|
||||||
REQUIRE(s.find(42u) == s.end());
|
REQUIRE(s.find(42u) == s.end());
|
||||||
REQUIRE_FALSE(s.find_dense_index(42u).second);
|
REQUIRE_FALSE(s.find_dense_index(42u).second);
|
||||||
@@ -122,7 +121,6 @@ TEST_CASE("detail") {
|
|||||||
|
|
||||||
REQUIRE_FALSE(s.empty());
|
REQUIRE_FALSE(s.empty());
|
||||||
REQUIRE(s.size() == 1u);
|
REQUIRE(s.size() == 1u);
|
||||||
REQUIRE(s.capacity() == 85u);
|
|
||||||
REQUIRE(s.has(42u));
|
REQUIRE(s.has(42u));
|
||||||
REQUIRE_FALSE(s.has(84u));
|
REQUIRE_FALSE(s.has(84u));
|
||||||
|
|
||||||
@@ -146,7 +144,6 @@ TEST_CASE("detail") {
|
|||||||
REQUIRE_FALSE(s.has(84u));
|
REQUIRE_FALSE(s.has(84u));
|
||||||
REQUIRE(s.empty());
|
REQUIRE(s.empty());
|
||||||
REQUIRE_FALSE(s.size());
|
REQUIRE_FALSE(s.size());
|
||||||
REQUIRE(s.capacity() == 85u * 2);
|
|
||||||
|
|
||||||
s.insert(42u);
|
s.insert(42u);
|
||||||
s.insert(84u);
|
s.insert(84u);
|
||||||
@@ -200,7 +197,6 @@ TEST_CASE("detail") {
|
|||||||
|
|
||||||
REQUIRE(m.empty());
|
REQUIRE(m.empty());
|
||||||
REQUIRE_FALSE(m.size());
|
REQUIRE_FALSE(m.size());
|
||||||
REQUIRE(m.capacity() == 0u);
|
|
||||||
REQUIRE_FALSE(m.has(42u));
|
REQUIRE_FALSE(m.has(42u));
|
||||||
REQUIRE_THROWS(m.get(42u));
|
REQUIRE_THROWS(m.get(42u));
|
||||||
REQUIRE_THROWS(as_const(m).get(42u));
|
REQUIRE_THROWS(as_const(m).get(42u));
|
||||||
@@ -223,7 +219,6 @@ TEST_CASE("detail") {
|
|||||||
|
|
||||||
REQUIRE_FALSE(m.empty());
|
REQUIRE_FALSE(m.empty());
|
||||||
REQUIRE(m.size() == 3u);
|
REQUIRE(m.size() == 3u);
|
||||||
REQUIRE(m.capacity() >= 3u);
|
|
||||||
REQUIRE(m.has(21u));
|
REQUIRE(m.has(21u));
|
||||||
REQUIRE(m.has(42u));
|
REQUIRE(m.has(42u));
|
||||||
REQUIRE(m.has(84u));
|
REQUIRE(m.has(84u));
|
||||||
|
|||||||
Reference in New Issue
Block a user