Compare commits

...

2 Commits

Author SHA1 Message Date
7ea2710ee0 List Data Structure 2025-07-23 13:26:50 -04:00
f9de242b87 Adjusted Platform Structure 2025-07-23 12:12:29 -04:00
14 changed files with 300 additions and 56 deletions

View File

@@ -174,6 +174,8 @@ add_library(fennec STATIC
include/fennec/lang/type_operators.h include/fennec/lang/type_operators.h
include/fennec/containers/tuple.h include/fennec/containers/tuple.h
include/fennec/containers/detail/__tuple.h include/fennec/containers/detail/__tuple.h
include/fennec/platform/linux/wayland/window.h
include/fennec/containers/list.h
) )
add_dependencies(fennec metaprogramming) add_dependencies(fennec metaprogramming)

View File

@@ -47,12 +47,12 @@ public:
/// ///
/// \brief Default Constructor, initializes an empty allocation. /// \brief Default Constructor, initializes an empty allocation.
dynarray() : _alloc(8), _size(0) {} constexpr dynarray() : _alloc(8), _size(0) {}
/// ///
/// \brief Alloc Constructor, initialize empty allocation with allocator instance. /// \brief Alloc Constructor, initialize empty allocation with allocator instance.
/// \param alloc An allocator object to copy, for instances where the allocator needs to be initialized with some data. /// \param alloc An allocator object to copy, for instances where the allocator needs to be initialized with some data.
dynarray(const alloc_t& alloc) constexpr dynarray(const alloc_t& alloc)
: _alloc(8, alloc) : _alloc(8, alloc)
, _size(0) { , _size(0) {
@@ -60,7 +60,7 @@ public:
/// ///
/// \brief Sized Allocation, create an allocation with a size of `n` elements, initialized with the default constructor. /// \brief Sized Allocation, create an allocation with a size of `n` elements, initialized with the default constructor.
dynarray(size_t n) constexpr dynarray(size_t n)
: _alloc(n) : _alloc(n)
, _size(n) , _size(n)
{ {
@@ -74,7 +74,7 @@ public:
/// \brief /// \brief
/// \param n /// \param n
/// \param alloc /// \param alloc
dynarray(size_t n, const alloc_t& alloc) constexpr dynarray(size_t n, const alloc_t& alloc)
: _alloc(n, alloc) : _alloc(n, alloc)
, _size(n) { , _size(n) {
element_t* addr = _alloc.data(); element_t* addr = _alloc.data();
@@ -86,7 +86,7 @@ public:
/// ///
/// \brief Create an allocation of size `n`, with each element constructed using the copy constructor /// \brief Create an allocation of size `n`, with each element constructed using the copy constructor
/// \brief n the number of elements /// \brief n the number of elements
dynarray(size_t n, const TypeT& val) constexpr dynarray(size_t n, const TypeT& val)
: _alloc(n) : _alloc(n)
, _size(n) { , _size(n) {
element_t* addr = _alloc.data(); element_t* addr = _alloc.data();
@@ -96,37 +96,49 @@ public:
} }
template<typename...ArgsT> template<typename...ArgsT>
dynarray(size_t n, ArgsT&&...args) { constexpr dynarray(size_t n, ArgsT&&...args) {
element_t* addr = _alloc.data(); element_t* addr = _alloc.data();
for(; n > 0; --n, ++addr) { for(; n > 0; --n, ++addr) {
fennec::construct(addr, fennec::forward<ArgsT>(args)...); fennec::construct(addr, fennec::forward<ArgsT>(args)...);
} }
} }
~dynarray() { constexpr ~dynarray() {
element_t* addr = _alloc.data(); element_t* addr = _alloc.data();
for(int n = _size; n > 0; --n, ++addr) { for(int n = _size; n > 0; --n, ++addr) {
fennec::destruct(addr); fennec::destruct(addr);
} }
} }
size_t size() const { constexpr size_t size() const {
return _size; return _size;
} }
size_t capacity() const { constexpr size_t capacity() const {
return _alloc.capacity(); return _alloc.capacity();
} }
TypeT& operator[](size_t i) { constexpr bool empty() const {
return _size == 0;
}
constexpr TypeT& operator[](size_t i) {
assertd(i < _size, "Array Out of Bounds"); return _alloc.data()[i]; assertd(i < _size, "Array Out of Bounds"); return _alloc.data()[i];
} }
const TypeT& operator[](size_t i) const { constexpr const TypeT& operator[](size_t i) const {
assertd(i < _size, "Array Out of Bounds"); return _alloc.data()[i]; assertd(i < _size, "Array Out of Bounds"); return _alloc.data()[i];
} }
void insert(size_t i, const TypeT& val) { constexpr TypeT& back() {
return this->operator[](size() - 1);
}
constexpr const TypeT& back() const {
return this->operator[](size() - 1);
}
constexpr void insert(size_t i, const TypeT& val) {
// Grow if the size has reached the capacity of the allocation // Grow if the size has reached the capacity of the allocation
if(_size == capacity()) { if(_size == capacity()) {
@@ -146,7 +158,7 @@ public:
++_size; ++_size;
} }
void insert(size_t i, TypeT&& val) { constexpr void insert(size_t i, TypeT&& val) {
// Grow if the size has reached the capacity of the allocation // Grow if the size has reached the capacity of the allocation
if(_size == capacity()) { if(_size == capacity()) {
@@ -167,7 +179,7 @@ public:
} }
template<typename...ArgsT> template<typename...ArgsT>
void emplace(size_t i, ArgsT&&...args) { constexpr void emplace(size_t i, ArgsT&&...args) {
// Grow if the size has reached the capacity of the allocation // Grow if the size has reached the capacity of the allocation
if(_size == capacity()) { if(_size == capacity()) {
@@ -187,24 +199,29 @@ public:
++_size; ++_size;
} }
void push_back(const TypeT& val) { constexpr void push_back(const TypeT& val) {
dynarray::insert(_size, val); dynarray::insert(_size, val);
} }
void push_back(TypeT&& val) { constexpr void push_back(TypeT&& val) {
dynarray::insert(_size, fennec::forward<TypeT>(val)); dynarray::insert(_size, fennec::forward<TypeT>(val));
} }
template<typename...ArgsT> void emplace_back(ArgsT...args) { constexpr void pop_back() {
_alloc[_size--].~TypeT();
}
template<typename...ArgsT>
constexpr void emplace_back(ArgsT...args) {
dynarray::emplace(_size, fennec::forward<ArgsT>(args)...); dynarray::emplace(_size, fennec::forward<ArgsT>(args)...);
} }
void resize(size_t n) { constexpr void resize(size_t n) {
_alloc.reallocate(n); _alloc.reallocate(n);
} }
private: private:
void _grow() { constexpr void _grow() {
_alloc.reallocate(_alloc.capacity() * 2); _alloc.reallocate(_alloc.capacity() * 2);
} }

View File

@@ -0,0 +1,205 @@
// =====================================================================================================================
// 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_LIST_H
#define FENNEC_CONTAINERS_LIST_H
#include <fennec/containers/dynarray.h>
#include <fennec/containers/optional.h>
#include <fennec/memory/allocator.h>
namespace fennec
{
template<class TypeT, class Alloc = allocator<TypeT>>
struct list {
public:
using alloc_t = typename allocator_traits<Alloc>::template rebind<TypeT>;
using value_t = TypeT;
static constexpr size_t npos = -1;
private:
struct node {
optional<value_t> data;
size_t prev, next;
constexpr node()
: data()
, prev(npos)
, next(npos) {
}
constexpr node(size_t p, size_t n)
: data()
, prev(p)
, next(n) {
}
constexpr node(size_t p, size_t n, value_t&& val)
: data(fennec::forward<value_t>(val))
, prev(p)
, next(n) {
}
constexpr ~node() = default;
constexpr void clear() {
data = nullopt;
prev = npos;
next = npos;
}
};
size_t _next(size_t n) {
return _table[n].next;
}
size_t _prev(size_t n) {
return _table[n].prev;
}
size_t _walk(size_t i) {
size_t n = _root;
if (n == npos) return n;
while (i > 0 && n != npos) {
n = _next(n); --i;
}
return n;
}
size_t _next_free(size_t i) {
if (not _freed.empty()) {
size_t n = _freed.back();
_freed.pop_back();
return n;
}
_table[_size];
}
public:
using elem_t = node;
constexpr list()
: _table(), _root(npos), _last(npos), _freed(), _size(0) {
}
constexpr ~list() = default;
constexpr bool size() const { return _size; }
constexpr bool capacity() const { return _table.capacity(); }
constexpr bool empty() const { return _root == npos; }
constexpr value_t& operator[](int i) {
assertd(i >= 0, "Index out of Bounds");
size_t n = _walk(i);
assertd(n != npos, "Index out of Bounds");
return _table[n].data;
}
constexpr const value_t& operator[](int i) const {
assertd(i >= 0, "Index out of Bounds");
size_t n = _walk(i);
assertd(n != npos, "Index out of Bounds");
return _table[n].data;
}
void insert(size_t i, value_t&& x) {
assert(i <= size(), "Index out of Bounds");
if (size() == capacity()) {
_expand();
}
size_t n = _walk(min(i, size() - 1));
size_t p = _next_free(i);
if (n == npos) {
_root = p;
_table[p].data = fennec::forward<value_t>(x);
return;
}
_table[p].data = fennec::forward<value_t>(x);
_table[p].next = n;
_table[p].prev = _prev(p);
_table[n].prev = p;
++_size;
_last = (n == npos) ? p : _last;
}
void insert(size_t i, const value_t& x) {
this->insert(i, elem_t(x));
}
void push_front(const value_t& x) {
this->insert(0, x);
}
void push_front(value_t&& x) {
this->insert(0, fennec::forward<value_t>(x));
}
void push_back(const value_t& x) {
this->insert(_size, x);
}
void push_back(value_t&& x) {
this->insert(_size, fennec::forward<value_t>(x));
}
void erase(size_t i) {
size_t j = _walk(i);
if (j == npos) return;
if (not _table[j].data) return;
// Get the prev and next indices
size_t p = _prev(j);
size_t n = _next(j);
// clear the node
_table[j].data = nullopt;
_table[j].prev = npos;
_table[j].next = npos;
// Fix prev and next nodes
if (p != npos) _table[p].next = n;
if (n != npos) _table[n].prev = p;
else _last = j;
// Mark node as freed
_freed.push_back(j);
}
void pop_front() {
erase(0);
}
void pop_back() {
erase(_size - 1);
}
private:
allocation<elem_t, alloc_t> _table;
dynarray<size_t> _freed;
size_t _root, _last, _size;
constexpr void _expand() {
_table.reallocate(_table.capacity() * 2);
}
};
}
#endif // FENNEC_CONTAINERS_LIST_H

View File

@@ -52,30 +52,30 @@ struct pair {
constexpr pair(const pair&) = default; constexpr pair(const pair&) = default;
constexpr pair(pair&&) noexcept = default; constexpr pair(pair&&) noexcept = default;
pair& operator=(const pair&) = default; constexpr pair& operator=(const pair&) = default;
pair& operator=(pair&&) noexcept = default; constexpr pair& operator=(pair&&) noexcept = default;
bool operator==(const pair& p) const { constexpr bool operator==(const pair& p) const {
return first == p.first and second == p.second; return first == p.first and second == p.second;
} }
bool operator!=(const pair& p) const { constexpr bool operator!=(const pair& p) const {
return first != p.first or second != p.second; return first != p.first or second != p.second;
} }
bool operator<(const pair& p) const { constexpr bool operator<(const pair& p) const {
return first < p.first or (first == p.first and second < p.second); return first < p.first or (first == p.first and second < p.second);
} }
bool operator<=(const pair& p) const { constexpr bool operator<=(const pair& p) const {
return first < p.first or (first == p.first and second <= p.second); return first < p.first or (first == p.first and second <= p.second);
} }
bool operator>(const pair& p) const { constexpr bool operator>(const pair& p) const {
return first > p.first or (first == p.first and second > p.second); return first > p.first or (first == p.first and second > p.second);
} }
bool operator>=(const pair& p) const { constexpr bool operator>=(const pair& p) const {
return first > p.first or (first == p.first and second >= p.second); return first > p.first or (first == p.first and second >= p.second);
} }

View File

@@ -152,7 +152,7 @@ public:
if (_equal(*_alloc[i].value, val)) { // Check to see if this element is already inserted if (_equal(*_alloc[i].value, val)) { // Check to see if this element is already inserted
return; return;
} }
if (psl >= _alloc[i].psl) { // When psl is higher, swap if (psl > _alloc[i].psl) { // When psl is higher, swap
fennec::swap(*_alloc[i].value, value); fennec::swap(*_alloc[i].value, value);
fennec::swap(_alloc[i].psl, psl); fennec::swap(_alloc[i].psl, psl);
} }

View File

@@ -31,14 +31,14 @@ template<typename...TypesT> struct tuple;
template<size_t i, typename...TypesT> template<size_t i, typename...TypesT>
typename tuple<TypesT...>::template elem_t<i>& get(tuple<TypesT...>& x) { constexpr typename tuple<TypesT...>::template elem_t<i>& get(tuple<TypesT...>& x) {
using elem_t = typename tuple<TypesT...>::template elem_t<i>; using elem_t = typename tuple<TypesT...>::template elem_t<i>;
auto it = static_cast<detail::__tuple_leaf<i, elem_t>>(x); auto& it = static_cast<detail::__tuple_leaf<i, elem_t>>(x);
return it; return it;
} }
template<size_t i, typename...TypesT> template<size_t i, typename...TypesT>
const typename tuple<TypesT...>::template elem_t<i>& get(tuple<TypesT...>& x) { constexpr const typename tuple<TypesT...>::template elem_t<i>& get(tuple<TypesT...>& x) {
using elem_t = typename tuple<TypesT...>::template elem_t<i>; using elem_t = typename tuple<TypesT...>::template elem_t<i>;
auto& it = static_cast<detail::__tuple_leaf<i, elem_t>>(x); auto& it = static_cast<detail::__tuple_leaf<i, elem_t>>(x);
return it; return it;
@@ -55,7 +55,7 @@ public:
using elem_t = nth_element<i, TypesT...>; using elem_t = nth_element<i, TypesT...>;
template<typename...ArgsT> template<typename...ArgsT>
tuple(ArgsT&&...args) : base_t(args...) { constexpr tuple(ArgsT&&...args) : base_t(args...) {
} }
}; };

View File

@@ -34,8 +34,6 @@ public:
}; };
virtual bool connected() const = 0; virtual bool connected() const = 0;
protected:
virtual ~display() = default; virtual ~display() = default;
private: private:

View File

@@ -28,9 +28,6 @@
namespace fennec namespace fennec
{ {
namespace wayland
{
class wayland_display : public display { class wayland_display : public display {
public: public:
wayland_display(linux_platform* platform); wayland_display(linux_platform* platform);
@@ -46,6 +43,4 @@ private:
} }
}
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_DISPLAY_H #endif // FENNEC_PLATFORM_LINUX_WAYLAND_DISPLAY_H

View File

@@ -24,7 +24,7 @@
namespace fennec namespace fennec
{ {
namespace wayland namespace libwayland
{ {
bool load_symbols(linux_platform* platform); bool load_symbols(linux_platform* platform);

View File

@@ -0,0 +1,33 @@
// =====================================================================================================================
// 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_PLATFORM_LINUX_WAYLAND_WINDOW_H
#define FENNEC_PLATFORM_LINUX_WAYLAND_WINDOW_H
namespace fennec
{
class wayland_window {
public:
private:
};
}
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_WINDOW_H

View File

@@ -28,8 +28,6 @@
namespace fennec namespace fennec
{ {
using namespace wayland;
linux_platform::linux_platform(user _type) linux_platform::linux_platform(user _type)
: platform(_type) : platform(_type)
, _display_driver(display_none) { , _display_driver(display_none) {
@@ -45,7 +43,10 @@ linux_platform::linux_platform(user _type)
} }
linux_platform::~linux_platform() { linux_platform::~linux_platform() {
if (_display) {
delete _display;
_display = nullptr;
}
} }
shared_object* linux_platform::load_object(const cstring& file) { shared_object* linux_platform::load_object(const cstring& file) {
@@ -77,10 +78,10 @@ display* linux_platform::get_display() {
void linux_platform::_runtime_client_checks() { void linux_platform::_runtime_client_checks() {
#ifdef FENNEC_LIB_WAYLAND #ifdef FENNEC_LIB_WAYLAND
if (wayland::load_symbols(this)) { if (libwayland::load_symbols(this)) {
_display_driver = display_wayland; _display_driver = display_wayland;
_display = new wayland_display(this); _display = new wayland_display(this);
wayland::unload_symbols(this); // Doesn't actually unload symbols, just resets ref counter to only consider libwayland::unload_symbols(this); // Doesn't actually unload symbols, just resets ref counter to only consider
// the created display // the created display
} }
#endif #endif

View File

@@ -23,14 +23,11 @@
namespace fennec namespace fennec
{ {
namespace wayland
{
wayland_display::wayland_display(linux_platform* platform) wayland_display::wayland_display(linux_platform* platform)
: display() : display()
, _handle() , _handle()
, _platform(platform) { , _platform(platform) {
load_symbols(_platform); libwayland::load_symbols(_platform);
_handle = wl_display_connect(nullptr); _handle = wl_display_connect(nullptr);
} }
@@ -38,13 +35,13 @@ wayland_display::wayland_display(linux_platform* platform, const cstring& drv)
: display() : display()
, _handle() , _handle()
, _platform(platform) { , _platform(platform) {
load_symbols(_platform); libwayland::load_symbols(_platform);
_handle = wl_display_connect(drv); _handle = wl_display_connect(drv);
} }
wayland_display::~wayland_display() { wayland_display::~wayland_display() {
wl_display_disconnect(_handle); wl_display_disconnect(_handle);
unload_symbols(_platform); libwayland::unload_symbols(_platform);
_handle = nullptr; _handle = nullptr;
_platform = nullptr; _platform = nullptr;
} }
@@ -53,6 +50,4 @@ bool wayland_display::connected() const {
return _handle != nullptr; return _handle != nullptr;
} }
}
} }

View File

@@ -22,7 +22,7 @@
namespace fennec namespace fennec
{ {
namespace wayland namespace libwayland
{ {
using shared_lib = platform::shared_lib; using shared_lib = platform::shared_lib;

View File

@@ -25,8 +25,6 @@
namespace fennec::test namespace fennec::test
{ {
using namespace wayland;
inline void fennec_test_platform_linux_wayland(linux_platform& platform) { inline void fennec_test_platform_linux_wayland(linux_platform& platform) {
wayland_display* display = static_cast<wayland_display*>(platform.get_display()); wayland_display* display = static_cast<wayland_display*>(platform.get_display());