Commit 15c7f4b7 authored by Gauthier Quesnel's avatar Gauthier Quesnel
Browse files

to merge with array

parent 3e486920
......@@ -39,26 +39,79 @@
namespace bits {
using ID = std::int32_t;
constexpr ID ID_index_mask = 0x0000ffff;
constexpr ID ID_key_mask = 0xffff0000;
using ID = std::int64_t;
using IDs = std::int32_t;
constexpr int
get_index(ID id) noexcept
{
return id & ID_index_mask;
return static_cast<int>(id & 0x00000000ffffffff);
}
constexpr ID
get_id(ID id) noexcept
{
return id & 0xffffffff00000000;
}
template<typename T>
constexpr T
get_max_id() noexcept;
template<>
constexpr ID
get_max_id<ID>() noexcept
{
return 0xffffffff00000000;
}
template<>
constexpr IDs
get_max_id<IDs>() noexcept
{
return 0xffff0000;
}
template<typename T>
constexpr int
get_key(ID id) noexcept
size() noexcept;
template<>
constexpr int
size<ID>() noexcept
{
return id & ID_key_mask;
return INT32_MAX;
}
inline constexpr bool
template<>
constexpr int
size<IDs>() noexcept
{
return INT16_MAX;
}
constexpr bool
is_valid(ID id) noexcept
{
return get_key(id) != 0;
return (id & 0xffffffff00000000) != 0;
}
constexpr int
get_index(IDs id) noexcept
{
return id & 0x0000ffff;
}
constexpr int
get_id(IDs id) noexcept
{
return id & 0xffff0000;
}
constexpr bool
is_valid(IDs id) noexcept
{
return (id & 0xffff0000) != 0;
}
/**
......@@ -72,18 +125,18 @@ is_valid(ID id) noexcept
*
* @tparam T The type of object the data_array holds.
*/
template<typename T>
template<typename T, typename Identifier>
struct data_array
{
using identifier_type = Identifier;
struct item
{
T item;
ID id; // (key << 16 | index) for alloced entries, (0 | nextFreeIndex)
// for free list entries.
Identifier id;
};
using this_type = data_array<T>;
using this_type = data_array<T, Identifier>;
using value_type = T;
using reference = value_type&;
using const_reference = const value_type&;
......@@ -115,10 +168,12 @@ struct data_array
// puts entry on free list (uses id to store next)
void free(T&);
void free(Identifier id);
// accessor to the id part if Item
int get_id(T&);
T& get(ID id); // return item[id & 0xFFFF];
T& get(Identifier id); // return item[id & 0xFFFF];
/**
* @brief Get a T from an ID.
......@@ -127,7 +182,7 @@ struct data_array
* cases like AI references and others where 'the thing might have been
* deleted out from under me.
*/
T* try_to_get(ID id);
T* try_to_get(Identifier id);
/**
* @brief Return next item where id & 0xFFFF0000 != 0 (ie items not on free
......@@ -164,24 +219,24 @@ struct data_array
int free_head = -1; // index of first free entry
};
template<typename T>
data_array<T>::~data_array()
template<typename T, typename Identifier>
data_array<T, Identifier>::~data_array()
{
if (items)
::free(items);
}
template<typename T>
template<typename T, typename Identifier>
bool
data_array<T>::init(int capacity_)
data_array<T, Identifier>::init(int capacity_)
{
clear();
if (capacity_ < 0 || capacity_ > ID_index_mask)
if (capacity_ < 0 || capacity_ > size<ID>())
return false;
items = (data_array<T>::item*)::malloc(static_cast<size_t>(capacity) *
sizeof(item));
items = (data_array<T, Identifier>::item*)::malloc(
static_cast<size_t>(capacity) * sizeof(item));
max_size = 0;
max_used = 0;
capacity = capacity_;
......@@ -191,16 +246,21 @@ data_array<T>::init(int capacity_)
return true;
}
template<typename T>
template<typename T, typename Identifier>
void
Do_clear(typename data_array<T>::item* items, const int size, std::true_type)
Do_clear(typename data_array<T, Identifier>::item* items,
const int size,
std::true_type)
{
std::memset(items, 0, sizeof(typename data_array<T>::item) * size);
std::memset(
items, 0, sizeof(typename data_array<T, Identifier>::item) * size);
}
template<typename T>
template<typename T, typename Identifier>
void
Do_clear(typename data_array<T>::item* items, const int size, std::false_type)
Do_clear(typename data_array<T, Identifier>::item* items,
const int size,
std::false_type)
{
for (int i = 0; i != size; ++i) {
if (is_valid(items[i].id)) {
......@@ -210,11 +270,11 @@ Do_clear(typename data_array<T>::item* items, const int size, std::false_type)
}
}
template<typename T>
template<typename T, typename Identifier>
void
data_array<T>::clear()
data_array<T, Identifier>::clear()
{
Do_clear<T>(items, max_size, std::is_trivial<T>());
Do_clear<T, Identifier>(items, max_size, std::is_trivial<T>());
items = nullptr;
max_size = 0;
max_used = 0;
......@@ -223,23 +283,23 @@ data_array<T>::clear()
free_head = -1;
}
template<typename T>
template<typename T, typename Identifier>
void
Do_alloc(T& /*t*/, std::true_type)
{
// std::memset(&t, 0, sizeof(T));
}
template<typename T>
template<typename T, typename Identifier>
void
Do_alloc(T& t, std::false_type)
{
t.T::T();
new (&t) T();
}
template<typename T>
template<typename T, typename Identifier>
T&
data_array<T>::alloc()
data_array<T, Identifier>::alloc()
{
int new_index;
......@@ -253,9 +313,9 @@ data_array<T>::alloc()
new_index = max_used++;
}
Do_alloc<T>(items[new_index].item, std::is_trivial<T>());
Do_alloc<T, Identifier>(items[new_index].item, std::is_trivial<T>());
if (next_key == ID_key_mask)
if (next_key == get_max_id<Identifier>())
next_key = 1;
items[new_index].id = (next_key++ << 16) | new_index;
......@@ -264,23 +324,26 @@ data_array<T>::alloc()
return items[new_index].item;
}
template<typename T>
template<typename T, typename Identifier>
void
Do_free(T& /*t*/, std::true_type)
{
// Really reset memory?
// std::memset(&t, 0, sizeof(T));
}
template<typename T>
template<typename T, typename Identifier>
void
Do_free(T& t, std::false_type)
{
// Will catch all exception?
t.~T();
}
template<typename T>
template<typename T, typename Identifier>
void
data_array<T>::free(T& t)
data_array<T, Identifier>::free(T& t)
{
auto id = get_id(t);
auto index = get_index(id);
......@@ -289,7 +352,7 @@ data_array<T>::free(T& t)
assert(items[index].id == id);
assert(is_valid(id));
Do_free<T>(items[index].item, std::is_trivial<T>());
Do_free<T, Identifier>(items[index].item, std::is_trivial<T>());
items[index].id = free_head;
free_head = index;
......@@ -297,26 +360,44 @@ data_array<T>::free(T& t)
--max_size;
}
template<typename T>
template<typename T, typename Identifier>
void
data_array<T, Identifier>::free(Identifier id)
{
auto index = get_index(id);
assert(items[index].id == id);
assert(is_valid(id));
Do_free<T, Identifier>(items[index].item, std::is_trivial<T>());
items[index].id = free_head;
free_head = index;
--max_size;
}
template<typename T, typename Identifier>
T&
data_array<T>::get(ID id)
data_array<T, Identifier>::get(Identifier id)
{
return items[get_index(id)];
}
template<typename T>
template<typename T, typename Identifier>
int
data_array<T>::get_id(T& t)
data_array<T, Identifier>::get_id(T& t)
{
auto offset = offsetof(data_array<T>::item, id);
using type = data_array<T, Identifier>::item;
auto offset = offsetof(type, id);
auto* ptr = reinterpret_cast<char*>(&t);
ptr += offset;
return static_cast<int>(*reinterpret_cast<int*>(ptr));
}
template<typename T>
template<typename T, typename Identifier>
T*
data_array<T>::try_to_get(ID id)
data_array<T, Identifier>::try_to_get(Identifier id)
{
if (get_key(id)) {
auto index = get_index(id);
......@@ -326,9 +407,9 @@ data_array<T>::try_to_get(ID id)
return nullptr;
}
template<typename T>
template<typename T, typename Identifier>
bool
data_array<T>::next(T*& t)
data_array<T, Identifier>::next(T*& t)
{
if (t) {
int id = get_id(*t);
......@@ -346,93 +427,93 @@ data_array<T>::next(T*& t)
return false;
}
template<typename T>
inline typename data_array<T>::iterator
data_array<T>::begin() noexcept
template<typename T, typename Identifier>
inline typename data_array<T, Identifier>::iterator
data_array<T, Identifier>::begin() noexcept
{
return items;
}
template<typename T>
inline typename data_array<T>::const_iterator
data_array<T>::begin() const noexcept
template<typename T, typename Identifier>
inline typename data_array<T, Identifier>::const_iterator
data_array<T, Identifier>::begin() const noexcept
{
return items;
}
template<typename T>
inline typename data_array<T>::const_iterator
data_array<T>::cbegin() const noexcept
template<typename T, typename Identifier>
inline typename data_array<T, Identifier>::const_iterator
data_array<T, Identifier>::cbegin() const noexcept
{
return items;
}
template<typename T>
inline typename data_array<T>::iterator
data_array<T>::end() noexcept
template<typename T, typename Identifier>
inline typename data_array<T, Identifier>::iterator
data_array<T, Identifier>::end() noexcept
{
return items + max_used;
}
template<typename T>
inline typename data_array<T>::const_iterator
data_array<T>::end() const noexcept
template<typename T, typename Identifier>
inline typename data_array<T, Identifier>::const_iterator
data_array<T, Identifier>::end() const noexcept
{
return items + max_used;
}
template<typename T>
inline typename data_array<T>::const_iterator
data_array<T>::cend() const noexcept
template<typename T, typename Identifier>
inline typename data_array<T, Identifier>::const_iterator
data_array<T, Identifier>::cend() const noexcept
{
return items + max_used;
}
template<typename T>
inline typename data_array<T>::reverse_iterator
data_array<T>::rbegin() noexcept
template<typename T, typename Identifier>
inline typename data_array<T, Identifier>::reverse_iterator
data_array<T, Identifier>::rbegin() noexcept
{
return reverse_iterator(items + max_used);
}
template<typename T>
inline typename data_array<T>::const_reverse_iterator
data_array<T>::rbegin() const noexcept
template<typename T, typename Identifier>
inline typename data_array<T, Identifier>::const_reverse_iterator
data_array<T, Identifier>::rbegin() const noexcept
{
return const_reverse_iterator(items + max_used);
}
template<typename T>
inline typename data_array<T>::const_reverse_iterator
data_array<T>::crbegin() const noexcept
template<typename T, typename Identifier>
inline typename data_array<T, Identifier>::const_reverse_iterator
data_array<T, Identifier>::crbegin() const noexcept
{
return const_reverse_iterator(items + max_used);
}
template<typename T>
inline typename data_array<T>::reverse_iterator
data_array<T>::rend() noexcept
template<typename T, typename Identifier>
inline typename data_array<T, Identifier>::reverse_iterator
data_array<T, Identifier>::rend() noexcept
{
return reverse_iterator(items);
}
template<typename T>
inline typename data_array<T>::const_reverse_iterator
data_array<T>::rend() const noexcept
template<typename T, typename Identifier>
inline typename data_array<T, Identifier>::const_reverse_iterator
data_array<T, Identifier>::rend() const noexcept
{
return const_reverse_iterator(items);
}
template<typename T>
inline typename data_array<T>::const_reverse_iterator
data_array<T>::crend() const noexcept
template<typename T, typename Identifier>
inline typename data_array<T, Identifier>::const_reverse_iterator
data_array<T, Identifier>::crend() const noexcept
{
return const_reverse_iterator(items);
}
template<typename T>
template<typename T, typename Identifier>
bool
data_array<T>::full() const noexcept
data_array<T, Identifier>::full() const noexcept
{
return free_head == -1 && max_used == capacity;
}
......
......@@ -36,7 +36,7 @@ check_array()
float x;
};
bits::data_array<position> array;
bits::data_array<position, bits::IDs> array;
Ensures(array.items == nullptr);
Ensures(array.max_size == 0);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment