- deque, object_pool, and graph data structures + PrettyPrinters
This commit is contained in:
199
include/fennec/containers/deque.h
Normal file
199
include/fennec/containers/deque.h
Normal file
@@ -0,0 +1,199 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_CONTAINERS_DEQUE_H
|
||||
#define FENNEC_CONTAINERS_DEQUE_H
|
||||
|
||||
#include <fennec/memory/allocator.h>
|
||||
|
||||
// TODO: Document
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
template<typename TypeT, typename AllocT = allocator<TypeT>>
|
||||
struct deque {
|
||||
|
||||
// Definitions =========================================================================================================
|
||||
public:
|
||||
using elem_t = TypeT;
|
||||
|
||||
struct node {
|
||||
elem_t value;
|
||||
node *prev, *next;
|
||||
|
||||
template<typename...ArgsT>
|
||||
node(node* prev, node* next, ArgsT&&...args)
|
||||
: value(fennec::forward<ArgsT>(args)...)
|
||||
, prev(prev), next(next) {
|
||||
}
|
||||
|
||||
~node() = default;
|
||||
};
|
||||
|
||||
using alloc_t = allocator_traits<AllocT>::template rebind<node>;
|
||||
|
||||
|
||||
// Constructors ========================================================================================================
|
||||
|
||||
deque()
|
||||
: _alloc()
|
||||
, _first(nullptr)
|
||||
, _last(nullptr) {
|
||||
}
|
||||
|
||||
deque(deque&& deque) noexcept
|
||||
: _alloc(deque._alloc)
|
||||
, _first(deque._first)
|
||||
, _last(deque._last) {
|
||||
deque._first = nullptr;
|
||||
deque._last = nullptr;
|
||||
}
|
||||
|
||||
~deque() {
|
||||
clear();
|
||||
}
|
||||
|
||||
// Properties ==========================================================================================================
|
||||
|
||||
bool empty() const {
|
||||
return _size == 0;
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
|
||||
// Access ==============================================================================================================
|
||||
|
||||
elem_t& front() {
|
||||
assert(not empty(), "Attempted to access an empty deque.");
|
||||
return _first->value;
|
||||
}
|
||||
|
||||
elem_t& back() {
|
||||
assert(not empty(), "Attempted to access an empty deque.");
|
||||
return _last->value;
|
||||
}
|
||||
|
||||
|
||||
// Insertion ===========================================================================================================
|
||||
|
||||
void push_front(elem_t&& elem) {
|
||||
this->_push_front(elem);
|
||||
}
|
||||
|
||||
void push_front(const elem_t& elem) {
|
||||
this->_push_front(elem);
|
||||
}
|
||||
|
||||
template<typename...ArgsT>
|
||||
void emplace_front(ArgsT&&...args) {
|
||||
this->_push_front(fennec::forward<ArgsT>(args)...);
|
||||
}
|
||||
|
||||
void push_back(elem_t&& elem) {
|
||||
this->_push_back(elem);
|
||||
}
|
||||
|
||||
void push_back(const elem_t& elem) {
|
||||
this->_push_back(elem);
|
||||
}
|
||||
|
||||
template<typename...ArgsT>
|
||||
void emplace_back(ArgsT&&...args) {
|
||||
this->_push_back(fennec::forward<ArgsT>(args)...);
|
||||
}
|
||||
|
||||
|
||||
// Deletion ============================================================================================================
|
||||
|
||||
void clear() {
|
||||
node* it = _first;
|
||||
while (it) {
|
||||
node* next = it->next;
|
||||
fennec::destruct(it);
|
||||
_alloc.deallocate(it);
|
||||
it = next;
|
||||
}
|
||||
_first = nullptr;
|
||||
_last = nullptr;
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
void pop_front() {
|
||||
if (_first == nullptr) {
|
||||
return;
|
||||
}
|
||||
node* next = _first->next;
|
||||
fennec::destruct(_first);
|
||||
_alloc.deallocate(_first);
|
||||
_first = next;
|
||||
_last = next ? _last : nullptr;
|
||||
--_size;
|
||||
}
|
||||
|
||||
void pop_back() {
|
||||
if (_last == nullptr) {
|
||||
return;
|
||||
}
|
||||
node* prev = _last->prev;
|
||||
fennec::destruct(_last);
|
||||
_alloc.deallocate(_last);
|
||||
_last = prev;
|
||||
_first = prev ? _first : nullptr;
|
||||
--_size;
|
||||
}
|
||||
|
||||
private:
|
||||
alloc_t _alloc;
|
||||
node *_first, *_last;
|
||||
size_t _size;
|
||||
|
||||
template<typename...ArgsT>
|
||||
void _push_front(ArgsT&&...args) {
|
||||
node* next = _first;
|
||||
_first = _alloc.allocate(1);
|
||||
fennec::construct(_first, nullptr, next, fennec::forward<ArgsT>(args)...);
|
||||
if (next) {
|
||||
next->prev = _first;
|
||||
} else {
|
||||
_last = _first;
|
||||
}
|
||||
++_size;
|
||||
}
|
||||
|
||||
template<typename...ArgsT>
|
||||
void _push_back(ArgsT&&...args) {
|
||||
node* prev = _last;
|
||||
_last = _alloc.allocate(1);
|
||||
fennec::construct(_last, prev, nullptr, fennec::forward<ArgsT>(args)...);
|
||||
if (prev) {
|
||||
prev->next = _last;
|
||||
} else {
|
||||
_first = _last;
|
||||
}
|
||||
++_size;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_CONTAINERS_DEQUE_H
|
||||
@@ -357,7 +357,7 @@ public:
|
||||
/// \brief Resize the dynarray, invoking the default constructor for all new elements
|
||||
/// \param n The new size in elements
|
||||
constexpr void resize(size_t n) {
|
||||
_alloc.reallocate(n);
|
||||
_alloc.creallocate(n);
|
||||
|
||||
while (_size < n) {
|
||||
emplace_back();
|
||||
@@ -366,7 +366,7 @@ public:
|
||||
|
||||
private:
|
||||
constexpr void _grow() {
|
||||
_alloc.reallocate(_alloc.capacity() * 2);
|
||||
_alloc.creallocate(_alloc.capacity() * 2);
|
||||
}
|
||||
|
||||
allocation<element_t, alloc_t> _alloc;
|
||||
|
||||
167
include/fennec/containers/graph.h
Normal file
167
include/fennec/containers/graph.h
Normal file
@@ -0,0 +1,167 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_CONTAINERS_GRAPH_H
|
||||
#define FENNEC_CONTAINERS_GRAPH_H
|
||||
|
||||
#include <fennec/containers/dynarray.h>
|
||||
#include <fennec/containers/list.h>
|
||||
#include <fennec/containers/map.h>
|
||||
#include <fennec/containers/object_pool.h>
|
||||
#include <fennec/containers/set.h>
|
||||
|
||||
/*
|
||||
* With the directed tree we were able to cheat a little, the structure has more rules to it which allows
|
||||
* tighter constraints. A graph is basically no rules whatsoever. Some variants, such as weighted graphs, assign
|
||||
* properties or rules to connections which can simply be an extension to this graph.
|
||||
*
|
||||
* The most effective way to do this is to have a dynarray of lists, however this results in double the
|
||||
* memory being used. This can also result in two connection objects being created.
|
||||
*
|
||||
* There is no nice way to avoid the problem of mapping pins to connections
|
||||
*/
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
template<typename NodeT, typename ConnectionT = nullptr_t>
|
||||
struct graph {
|
||||
public:
|
||||
using weight_t = ConnectionT;
|
||||
using node_t = NodeT;
|
||||
using conn_map_t = dynarray<map<size_t, size_t>>;
|
||||
using node_pool_t = object_pool<node_t>;
|
||||
using conn_pool_t = object_pool<weight_t>;
|
||||
|
||||
static constexpr size_t npos = -1;
|
||||
|
||||
constexpr graph() = default;
|
||||
constexpr ~graph() = default;
|
||||
|
||||
constexpr graph& operator=(const graph& g) = default;
|
||||
constexpr graph& operator=(graph&& g) = default;
|
||||
|
||||
|
||||
// Properties ==========================================================================================================
|
||||
|
||||
constexpr size_t num_nodes() const {
|
||||
return _node_pool.size();
|
||||
}
|
||||
|
||||
constexpr size_t num_connections() const {
|
||||
return _conn_pool.size();
|
||||
}
|
||||
|
||||
constexpr size_t capacity() const {
|
||||
return _node_pool.capacity();
|
||||
}
|
||||
|
||||
constexpr bool empty() const {
|
||||
return num_nodes() == 0;
|
||||
}
|
||||
|
||||
|
||||
// Nodes ===============================================================================================================
|
||||
|
||||
constexpr size_t insert(node_t&& node) {
|
||||
return this->_insert(fennec::forward<node_t>(node));
|
||||
}
|
||||
|
||||
constexpr size_t insert(const node_t& node) {
|
||||
return this->_insert(node);
|
||||
}
|
||||
|
||||
template<typename...ArgsT>
|
||||
constexpr size_t emplace(ArgsT&&...args) {
|
||||
return this->_insert(fennec::forward<ArgsT>(args)...);
|
||||
}
|
||||
|
||||
constexpr void erase(size_t node) {
|
||||
disconnect(node);
|
||||
_node_pool.erase(node);
|
||||
}
|
||||
|
||||
constexpr node_t& operator[](size_t node) {
|
||||
return _node_pool[node];
|
||||
}
|
||||
|
||||
constexpr const node_t& operator[](size_t node) const {
|
||||
return _node_pool[node];
|
||||
}
|
||||
|
||||
// Connections =========================================================================================================
|
||||
|
||||
list<size_t> connections(size_t n) {
|
||||
list<size_t> conns;
|
||||
if (_conn_map.empty()) return conns;
|
||||
|
||||
for (auto it : _conn_map[n]) {
|
||||
conns.push_back(it.first);
|
||||
}
|
||||
return conns;
|
||||
}
|
||||
|
||||
template<typename...ArgsT>
|
||||
constexpr void connect(size_t a, size_t b, ArgsT&&...args) {
|
||||
if (_conn_map.size() < _node_pool.capacity()) {
|
||||
_conn_map.resize(_node_pool.capacity());
|
||||
}
|
||||
|
||||
size_t conn = _conn_pool.emplace(fennec::forward<ArgsT>(args)...);
|
||||
_conn_map[a].emplace(b, conn);
|
||||
_conn_map[b].emplace(a, conn);
|
||||
}
|
||||
|
||||
constexpr void disconnect(size_t a, size_t b) {
|
||||
size_t c = *_conn_map[a][b];
|
||||
_conn_pool.erase(c);
|
||||
_conn_map[a].erase(b);
|
||||
_conn_map[b].erase(a);
|
||||
}
|
||||
|
||||
void disconnect(size_t n) {
|
||||
list<size_t> conns = connections(n);
|
||||
for (size_t conn : conns) {
|
||||
disconnect(n, conn);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr weight_t& operator[](size_t a, size_t b) {
|
||||
return _conn_pool[_conn_map[a][b]];
|
||||
}
|
||||
|
||||
constexpr const weight_t& operator[](size_t a, size_t b) const {
|
||||
return _conn_pool[_conn_map[a][b]];
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
node_pool_t _node_pool;
|
||||
conn_pool_t _conn_pool;
|
||||
conn_map_t _conn_map;
|
||||
|
||||
template<typename...ArgsT>
|
||||
size_t _insert(ArgsT&&...args) {
|
||||
return _node_pool.emplace(fennec::forward<ArgsT>(args)...);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_CONTAINERS_GRAPH_H
|
||||
@@ -62,6 +62,7 @@ public:
|
||||
using alloc_t = typename allocator_traits<Alloc>::template rebind<elem_t>;
|
||||
using hash_t = Hash;
|
||||
using set_t = set<elem_t, key_hash, node_equals, alloc_t>;
|
||||
using iterator = set_t::iterator;
|
||||
|
||||
// We only want to hash the key
|
||||
struct key_hash : hash_t {
|
||||
@@ -181,6 +182,17 @@ public:
|
||||
}
|
||||
|
||||
|
||||
// Iteration ===========================================================================================================
|
||||
|
||||
constexpr iterator begin() {
|
||||
return _set.begin();
|
||||
}
|
||||
|
||||
constexpr iterator end() {
|
||||
return _set.end();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
set_t _set;
|
||||
|
||||
|
||||
126
include/fennec/containers/object_pool.h
Normal file
126
include/fennec/containers/object_pool.h
Normal file
@@ -0,0 +1,126 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_CONTAINERS_OBJECT_POOL_H
|
||||
#define FENNEC_CONTAINERS_OBJECT_POOL_H
|
||||
#include <fennec/containers/dynarray.h>
|
||||
#include <fennec/containers/list.h>
|
||||
#include <fennec/containers/optional.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
///
|
||||
/// \brief Struct which holds a pool of objects associated with ids
|
||||
/// \tparam TypeT The value type
|
||||
/// \tparam AllocT The allocator type
|
||||
template<typename TypeT, typename AllocT = allocator<TypeT>>
|
||||
struct object_pool {
|
||||
public:
|
||||
using value_t = TypeT;
|
||||
using elem_t = optional<TypeT>;
|
||||
using table_t = dynarray<elem_t, AllocT>;
|
||||
|
||||
constexpr object_pool()
|
||||
: _size(0) {
|
||||
};
|
||||
|
||||
///
|
||||
/// \returns The number of active objects in the pool
|
||||
constexpr size_t size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns The capacity of the underlying allocation
|
||||
constexpr size_t capacity() const {
|
||||
return _table.capacity();
|
||||
}
|
||||
|
||||
constexpr bool empty() const {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
constexpr value_t& operator[](size_t i) {
|
||||
assert(i < capacity(), "Index out of Bounds!");
|
||||
assert(_table[i], "Attempted to access Null Object.");
|
||||
return *_table[i];
|
||||
}
|
||||
|
||||
constexpr const value_t& operator[](size_t i) const {
|
||||
assert(i < capacity(), "Index out of Bounds!");
|
||||
assert(_table[i], "Attempted to access Null Object.");
|
||||
return *_table[i];
|
||||
}
|
||||
|
||||
constexpr size_t insert(value_t&& x) {
|
||||
return this->_insert(fennec::forward<value_t>(x));
|
||||
}
|
||||
|
||||
constexpr size_t insert(const value_t& x) {
|
||||
return this->_insert(x);
|
||||
}
|
||||
|
||||
template<typename...ArgsT>
|
||||
constexpr size_t emplace(ArgsT&&...args) {
|
||||
return this->_insert(fennec::forward<ArgsT>(args)...);
|
||||
}
|
||||
|
||||
constexpr void erase(size_t i) {
|
||||
_table[i] = nullopt;
|
||||
_freed.push_back(i);
|
||||
--_size;
|
||||
}
|
||||
|
||||
constexpr size_t next_id() const {
|
||||
size_t next = _size;
|
||||
if (not _freed.empty()) {
|
||||
next = _freed.front();
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
private:
|
||||
dynarray<elem_t, AllocT> _table;
|
||||
list<size_t> _freed;
|
||||
size_t _size;
|
||||
|
||||
size_t _next_free() {
|
||||
size_t next = _size;
|
||||
if (not _freed.empty()) {
|
||||
next = _freed.front();
|
||||
_freed.pop_front();
|
||||
}
|
||||
++_size;
|
||||
return next;
|
||||
}
|
||||
|
||||
template<typename...ArgsT>
|
||||
size_t _insert(ArgsT&&...args) {
|
||||
size_t i = _next_free();
|
||||
if (i >= _table.size()) {
|
||||
_table.emplace_back();
|
||||
}
|
||||
_table[i].emplace(fennec::forward<ArgsT>(args)...);
|
||||
return i;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_CONTAINERS_OBJECT_POOL_H
|
||||
@@ -320,10 +320,17 @@ public:
|
||||
/// \param i0 The id of the first node
|
||||
/// \param i1 The id of the second node
|
||||
constexpr void swap(size_t i0, size_t i1) {
|
||||
assertf(i0 != root and i1 != root, "Cannot Swap With Root");
|
||||
|
||||
size_t p0 = parent(i0);
|
||||
size_t p1 = parent(i1);
|
||||
|
||||
fennec::swap(_table[i0], _table[i1]);
|
||||
fennec::swap(_table[i0].parent, _table[i1].parent);
|
||||
fennec::swap(_table[i0].child, _table[i1].child);
|
||||
fennec::swap(_table[i0].next, _table[i1].next);
|
||||
fennec::swap(_table[i0].prev, _table[i1].prev);
|
||||
fennec::swap(_table[i0].depth, _table[i1].depth);
|
||||
fennec::swap(_table[i0].num_children, _table[i1].num_children);
|
||||
|
||||
if (child(p0) == i0) _table[p0].child = i1;
|
||||
if (child(p1) == i1) _table[p1].child = i0;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
// https://programming.guide/robin-hood-hashing.html
|
||||
|
||||
#include <fennec/containers/multiset.h>
|
||||
#include <fennec/containers/optional.h>
|
||||
#include <fennec/containers/set.h>
|
||||
#include <fennec/lang/compare.h>
|
||||
@@ -295,15 +296,15 @@ public:
|
||||
///
|
||||
/// \brief Move Insertion
|
||||
/// \param val Value to insert
|
||||
constexpr void insert(elem_t&& val) {
|
||||
this->_insert(fennec::forward<elem_t>(val));
|
||||
constexpr iterator insert(elem_t&& val) {
|
||||
return fennec::move(this->_insert(fennec::forward<elem_t>(val)));
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Copy Insertion
|
||||
/// \param val Value to insert
|
||||
constexpr void insert(const elem_t& val) {
|
||||
this->_insert(val);
|
||||
constexpr iterator insert(const elem_t& val) {
|
||||
return fennec::move(this->_insert(val));
|
||||
}
|
||||
|
||||
///
|
||||
@@ -311,8 +312,8 @@ public:
|
||||
/// \tparam ArgsT Argument types
|
||||
/// \param args Arguments to construct with
|
||||
template<typename...ArgsT>
|
||||
constexpr void emplace(ArgsT&&...args) {
|
||||
this->_insert(fennec::forward<ArgsT>(args)...);
|
||||
constexpr iterator emplace(ArgsT&&...args) {
|
||||
return fennec::move(this->_insert(fennec::forward<ArgsT>(args)...));
|
||||
}
|
||||
|
||||
///
|
||||
@@ -354,6 +355,11 @@ public:
|
||||
/// \brief Class for Iterating the Set
|
||||
class iterator {
|
||||
public:
|
||||
constexpr iterator(const set* set, size_t i)
|
||||
: _set(set)
|
||||
, _i(i) {
|
||||
}
|
||||
|
||||
constexpr ~iterator() {
|
||||
_set = nullptr;
|
||||
}
|
||||
@@ -392,15 +398,12 @@ public:
|
||||
return _set != it._set or _i != it._i;
|
||||
}
|
||||
|
||||
constexpr size_t index() const { return _i; }
|
||||
|
||||
private:
|
||||
const set* _set;
|
||||
size_t _i;
|
||||
friend set;
|
||||
|
||||
constexpr iterator(const set* set, size_t i)
|
||||
: _set(set)
|
||||
, _i(i) {
|
||||
}
|
||||
};
|
||||
|
||||
constexpr iterator begin() const {
|
||||
@@ -437,7 +440,7 @@ private:
|
||||
}
|
||||
|
||||
template<typename...ArgsT>
|
||||
constexpr void _insert(ArgsT&&...args) {
|
||||
constexpr iterator _insert(ArgsT&&...args) {
|
||||
if (_size == 0 or double(_size) / capacity() >= _load) { // expand when full
|
||||
_expand();
|
||||
}
|
||||
@@ -447,7 +450,7 @@ private:
|
||||
int psl = 0;
|
||||
while (_alloc[i].value) { // Search for empty cell
|
||||
if (_equal(*_alloc[i].value, value)) { // Check to see if this element is already inserted
|
||||
return;
|
||||
return iterator(this, i);
|
||||
}
|
||||
if (psl > _alloc[i].psl) { // When psl is higher, swap
|
||||
_sumpsl += psl - _alloc[i].psl;
|
||||
@@ -459,6 +462,7 @@ private:
|
||||
_alloc[i].value = fennec::move(value);
|
||||
_sumpsl += (_alloc[i].psl = psl);
|
||||
++_size;
|
||||
return iterator(this, npos);
|
||||
}
|
||||
|
||||
allocation<node, alloc_t> _alloc;
|
||||
|
||||
@@ -310,7 +310,7 @@ public:
|
||||
/// \param n The number of elements of type `T` to allocate for
|
||||
explicit constexpr allocation(size_t n) noexcept
|
||||
: _data(nullptr), _capacity(0), _alignment(zero<align_t>()) {
|
||||
allocate(n);
|
||||
callocate(n);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -320,7 +320,7 @@ public:
|
||||
/// \param n the number of elements
|
||||
constexpr allocation(const T* data, size_t n)
|
||||
: allocation(n) {
|
||||
fennec::memcpy(_data, data, n);
|
||||
fennec::memmove(_data, data, n);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -331,7 +331,7 @@ public:
|
||||
: _data(nullptr)
|
||||
, _capacity(0)
|
||||
, _alignment(align) {
|
||||
allocate(n, align);
|
||||
callocate(n, align);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -342,7 +342,7 @@ public:
|
||||
/// \param align The alignment of the allocation
|
||||
constexpr allocation(const T* data, size_t n, align_t align)
|
||||
: allocation(n, align) {
|
||||
fennec::memcpy(_data, data, n);
|
||||
fennec::memmove(static_cast<void*>(_data), data, n);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -367,7 +367,7 @@ public:
|
||||
: _alloc(alloc)
|
||||
, _data(nullptr)
|
||||
, _capacity(0) {
|
||||
allocate(n);
|
||||
callocate(n);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -380,7 +380,7 @@ public:
|
||||
/// \details This constructor should be used when the type `AllocT` needs internal data.
|
||||
constexpr allocation(const T* data, size_t n, const alloc_t& alloc)
|
||||
: allocation(n, alloc) {
|
||||
fennec::memcpy(_data, data, n);
|
||||
fennec::memmove(static_cast<void*>(_data), data, n);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -395,7 +395,7 @@ public:
|
||||
, _data(nullptr)
|
||||
, _capacity(0)
|
||||
, _alignment(zero<align_t>()) {
|
||||
allocate(n, align);
|
||||
callocate(n, align);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -409,7 +409,7 @@ public:
|
||||
/// \details This constructor should be used when the type `AllocT` needs internal data.
|
||||
constexpr allocation(const T* data, size_t n, align_t align, const alloc_t& alloc)
|
||||
: allocation(n, align, alloc) {
|
||||
fennec::memcpy(_data, data, n);
|
||||
fennec::memmove(_data, data, n);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -420,7 +420,7 @@ public:
|
||||
, _data(_alloc.allocate(alloc._capacity))
|
||||
, _capacity(alloc._capacity)
|
||||
, _alignment(alloc._alignment) {
|
||||
fennec::memcpy(_data, alloc._data, alloc._capacity * sizeof(T));
|
||||
fennec::memmove(static_cast<void*>(_data), alloc._data, alloc._capacity * sizeof(T));
|
||||
}
|
||||
|
||||
///
|
||||
@@ -451,7 +451,7 @@ public:
|
||||
/// \returns a reference to `this`
|
||||
constexpr allocation& operator=(const allocation& alloc) {
|
||||
allocation::allocate(alloc.capacity());
|
||||
fennec::memcpy(_data, alloc, size());
|
||||
fennec::memmove(_data, alloc, size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -528,7 +528,7 @@ public:
|
||||
value_t* old = _data;
|
||||
_data = nullptr;
|
||||
allocate(n, align);
|
||||
fennec::memcpy(static_cast<void*>(_data), old, min(_capacity, n) * sizeof(T));
|
||||
fennec::memmove(static_cast<void*>(_data), old, min(_capacity, n) * sizeof(T));
|
||||
_alloc.deallocate(old);
|
||||
_capacity = n;
|
||||
}
|
||||
@@ -544,7 +544,7 @@ public:
|
||||
value_t* old = _data;
|
||||
_data = nullptr;
|
||||
callocate(n, align);
|
||||
fennec::memcpy(static_cast<void*>(_data), old, min(_capacity, n) * sizeof(T));
|
||||
fennec::memmove(static_cast<void*>(_data), old, min(_capacity, n) * sizeof(T));
|
||||
_alloc.deallocate(old);
|
||||
_capacity = n;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user