- Separated Platform and Compiler Dependent Behaviour into CMake scripts

- Implemented Basic Platform Interfaces
 - Implemented partial Linux platform and Wayland Display.
 - Implemented Dependencies for the above
   - map
     - set
       - optional
     - pair

TODO: threading
This commit is contained in:
2025-07-22 00:59:41 -04:00
parent ab1c7d94be
commit 73333b4c67
86 changed files with 3257 additions and 203 deletions

View File

@@ -38,7 +38,7 @@
namespace fennec
{
template<class TypeT, class Alloc>
template<class TypeT, class Alloc = allocator<TypeT>>
class dynarray
{
public:
@@ -129,7 +129,9 @@ public:
void insert(size_t i, const TypeT& val) {
// Grow if the size has reached the capacity of the allocation
if(_size == capacity()) _grow();
if(_size == capacity()) {
_grow();
}
// Move the data if we are not inserting at the end of the array
if((i = min(i, _size)) < _size) {
@@ -141,30 +143,36 @@ public:
// Insert the element
fennec::construct(_alloc.data() + i, val);
++_size;
}
void insert(size_t i, TypeT&& val) {
// Grow if the size has reached the capacity of the allocation
if(_size == capacity()) _grow();
if(_size == capacity()) {
_grow();
}
// Move the data if we are not inserting at the end of the array
if((i = min(i, _size)) < _size) {
fennec::memmove(
_alloc.data() + i
, _alloc.data() + i + 1
_alloc.data() + i + 1
, _alloc.data() + i
, (_size - i) * sizeof(TypeT));
}
// Insert the element
fennec::construct(_alloc.data() + i, fennec::forward<TypeT>(val));
++_size;
}
template<typename...ArgsT>
void emplace(size_t i, ArgsT&&...args) {
// Grow if the size has reached the capacity of the allocation
if(_size == capacity()) _grow();
if(_size == capacity()) {
_grow();
}
// Move the data if we are not inserting at the end of the array
if((i = min(i, _size)) < _size) {
@@ -176,6 +184,7 @@ public:
// Insert the element
fennec::construct(_alloc.data() + i, fennec::forward<ArgsT>(args)...);
++_size;
}
void push_back(const TypeT& val) {
@@ -190,8 +199,14 @@ public:
dynarray::emplace(_size, fennec::forward<ArgsT>(args)...);
}
void resize(size_t n) {
_alloc.reallocate(n);
}
private:
void _grow() const { _alloc.reallocate(_alloc.capacity() * 2); }
void _grow() {
_alloc.reallocate(_alloc.capacity() * 2);
}
allocation<element_t, alloc_t> _alloc;
size_t _size;

View File

@@ -0,0 +1,50 @@
// =====================================================================================================================
// 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_MAP_H
#define FENNEC_CONTAINERS_MAP_H
#include <fennec/containers/pair.h>
#include <fennec/containers/set.h>
namespace fennec
{
// TODO: Document
template<typename KeyT, typename ValueT, typename Hash = hash<KeyT>, typename Alloc = allocator<pair<KeyT, ValueT>>>
struct map {
public:
using key_t = KeyT;
using value_t = ValueT;
using elem_t = pair<KeyT, ValueT>;
using alloc_t = typename allocator_traits<Alloc>::template rebind<elem_t>;
using hash_t = Hash;
map() = default;
~map() = default;
private:
set<elem_t, hash_t, alloc_t> _set;
};
}
#endif // FENNEC_CONTAINERS_MAP_H

View File

@@ -0,0 +1,247 @@
// =====================================================================================================================
// 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_OPTIONAL_H
#define FENNEC_CONTAINERS_OPTIONAL_H
#include <fennec/lang/utility.h>
#include <fennec/memory/new.h>
#include <fennec/lang/assert.h>
namespace fennec
{
struct nullopt_t {};
constexpr nullopt_t nullopt_v = {};
#define nullopt nullopt_v
///
/// \brief Structure to hold an optional value.
/// \tparam T
template<typename T>
struct optional {
public:
// Constructors ========================================================================================================
///
/// \brief Default Constructor
constexpr optional()
: _root(0)
, _set(false) {
}
///
/// \brief Default Constructor
constexpr optional(nullopt_t)
: _root(0)
, _set(false) {
}
///
/// \brief Fundamental Type Constructor
/// \param val the value to initialize the underlying object with
constexpr optional(T val) requires is_fundamental_v<T>
: _val(val)
, _set(true) {
}
///
/// \brief Type Copy Constructor
/// \param val the value to initialize the underlying object with
constexpr optional(const T& val)
: _val(val)
, _set(true) {
}
///
/// \brief Copy Constructor
/// \param opt the optional to copy
constexpr optional(const optional& opt) requires is_copy_assignable_v<T>
: optional() {
_set = opt._set;
if (_set) {
_val = opt._val;
}
}
///
/// \brief Move Constructor
/// \param opt the optional to move
constexpr optional(optional&& opt) noexcept requires is_move_assignable_v<T>
: optional() {
_set = opt._set;
if (_set) {
_val = fennec::move(opt._val);
}
opt = nullopt;
}
constexpr ~optional() {
if constexpr(is_fundamental_v<T>) {
return;
}
if (_set) {
_val.~T();
}
}
// Assignment Operators ================================================================================================
///
/// \brief Fundamental Type Assignment
/// \val The value to set with
constexpr optional& operator=(nullopt_t) {
if constexpr(not is_fundamental_v<T>) {
if (_set) {
_val.~T();
}
}
_root = '\0';
_set = false;
return *this;
}
///
/// \brief Type Copy Assignment
/// \val The value to set with
constexpr optional& operator=(const T& val) requires is_copy_constructible_v<T> and is_copy_assignable_v<T> {
if (_set) {
_val = val;
} else {
fennec::construct(&_val, val);
_set = true;
}
return *this;
}
///
/// \brief Type Move Assignment
/// \val The value to set with
constexpr optional& operator=(T&& val) requires is_move_constructible_v<T> and is_move_assignable_v<T> {
if (_set) {
_val = fennec::move(val);
} else {
fennec::construct(&_val, fennec::move(val));
_set = true;
}
return *this;
}
///
/// \brief Copy Assignment
/// \val The optional to copy
constexpr optional& operator=(const optional& opt) requires is_copy_constructible_v<T> and is_copy_assignable_v<T> {
if (_set != opt._set) {
_set = opt._set;
if (_set) { // Construct
fennec::construct(&_val, opt._val);
} else { // Destruct
_val.~T();
_root = 0;
}
} else if (_set) { // Copy Assignment
_val = opt._val;
}
return *this;
}
///
/// \brief Move Assignment
/// \val The optional to move
constexpr optional& operator=(optional&& opt) noexcept requires is_move_constructible_v<T> and is_move_assignable_v<T> {
if (_set != opt._set) {
_set = opt._set;
if (_set) { // Construct
fennec::construct(&_val, fennec::move(opt._val));
} else { // Destruct
_val.~T();
_root = 0;
}
} else if (_set) { // Copy Assignment
_val = fennec::move(opt._val);
}
return *this;
}
template<typename...ArgsT>
constexpr T& emplace(ArgsT&&...args) {
if (_set) {
_val = T(fennec::forward<ArgsT>(args)...);
} else {
fennec::construct(&_val, fennec::forward<ArgsT>(args)...);
_set = true;
}
return _val;
}
void reset() {
this->operator=(nullopt);
}
// Operators ===========================================================================================================
constexpr operator bool() const {
return _set;
}
constexpr T* operator->() noexcept {
return _set ? &_val : nullptr;
}
constexpr const T* operator->() const noexcept {
return _set ? &_val : nullptr;
}
constexpr T& operator*() & noexcept {
assertd(_set, "Attempted to reference the value of an unset optional");
return _val;
}
constexpr const T& operator*() const& noexcept {
assertd(_set, "Attempted to reference the value of an unset optional");
return _val;
}
constexpr T&& operator*() && noexcept {
assertd(_set, "Attempted to reference the value of an unset optional");
return _val;
}
constexpr const T&& operator*() const&& noexcept {
assertd(_set, "Attempted to reference the value of an unset optional");
return _val;
}
private:
union {
char _root;
T _val;
};
bool _set;
};
}
#endif // FENNEC_CONTAINERS_OPTIONAL_H

View File

@@ -0,0 +1,91 @@
// =====================================================================================================================
// 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_PAIR_H
#define FENNEC_CONTAINERS_PAIR_H
#include <fennec/lang/hashing.h>
#include <fennec/lang/utility.h>
namespace fennec
{
// TODO: Document
template<typename T0, typename T1>
struct pair {
constexpr pair() = default;
constexpr ~pair() = default;
constexpr pair(const T0& x, const T1& y)
: first(x)
, second(y) {
}
constexpr pair(T0&& x, T1&& y) noexcept
: first(fennec::forward<T0>(x))
, second(fennec::forward<T1>(y)) {
}
constexpr pair(const pair&) = default;
constexpr pair(pair&&) noexcept = default;
pair& operator=(const pair&) = default;
pair& operator=(pair&&) noexcept = default;
bool operator==(const pair& p) const {
return first == p.first and second == p.second;
}
bool operator!=(const pair& p) const {
return first != p.first or second != p.second;
}
bool operator<(const pair& p) const {
return first < p.first or (first == p.first and second < p.second);
}
bool operator<=(const pair& p) const {
return first < p.first or (first == p.first and second <= p.second);
}
bool operator>(const pair& p) const {
return first > p.first or (first == p.first and second > p.second);
}
bool operator>=(const pair& p) const {
return first > p.first or (first == p.first and second >= p.second);
}
T0 first;
T1 second;
};
template<typename T0, typename T1>
struct hash<pair<T0, T1>> : hash<T0>, hash<T1> {
constexpr size_t operator()(const pair<T0, T1>& p) const {
return fennec::pair_hash( // pair the hashes of both elements
hash<T0>::operator()(p.first),
hash<T1>::operator()(p.second)
);
}
};
}
#endif // FENNEC_CONTAINERS_PAIR_H

View File

@@ -0,0 +1,297 @@
// =====================================================================================================================
// 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_SET_H
#define FENNEC_CONTAINERS_SET_H
// https://programming.guide/robin-hood-hashing.html
#include <fennec/containers/optional.h>
#include <fennec/math/ext/primes.h>
#include <fennec/memory/allocator.h>
#include <fennec/lang/hashing.h>
namespace fennec
{
// TODO: Document
template<typename T, class Hash = hash<T>, class Alloc = allocator<T>>
struct set {
public:
using alloc_t = typename allocator_traits<Alloc>::template rebind<T>;
using hash_t = Hash;
using elem_t = T;
class iterator;
static constexpr size_t npos = -1;
private:
struct node {
optional<elem_t> value;
int psl;
constexpr node() = default;
constexpr ~node() = default;
};
public:
constexpr set()
: _alloc()
, _hash()
, _size(0) {
};
constexpr set(const hash_t& hash)
: _alloc()
, _hash(hash)
, _size(0) {
}
constexpr set(hash_t&& hash) noexcept
: _alloc()
, _hash(hash)
, _size(0) {
}
constexpr set(const alloc_t& alloc)
: _alloc(alloc)
, _hash()
, _size(0) {
}
constexpr set(alloc_t&& alloc) noexcept
: _alloc(alloc)
, _hash()
, _size(0) {
}
constexpr set(const hash_t& hash, const alloc_t& alloc)
: _alloc(alloc)
, _hash(hash)
, _size(0) {
}
constexpr set(const hash_t& hash, alloc_t&& alloc) noexcept
: _alloc(alloc)
, _hash(hash)
, _size(0) {
}
constexpr set(hash_t&& hash, alloc_t&& alloc) noexcept
: _alloc(alloc)
, _hash(hash)
, _size(0) {
}
constexpr set(hash_t&& hash, const alloc_t& alloc) noexcept
: _alloc(alloc)
, _hash(hash)
, _size(0) {}
constexpr set(const set& set)
: _alloc(set._alloc)
, _hash(set._hash)
, _size(set._size) {
}
constexpr set(set&& set) noexcept
: _alloc(fennec::move(set._alloc))
, _hash(fennec::move(set._hash))
, _size(fennec::move(set._size)) {
}
constexpr ~set() = default;
constexpr size_t size() const {
return _size;
}
constexpr size_t capacity() const {
return _alloc.capacity();
}
constexpr void insert(elem_t&& val) {
if (_size >= capacity()) { // expand when full
_expand();
}
elem_t value = fennec::forward<elem_t>(val);
size_t i = _hash(value) % capacity(); // Initial search index
int psl = 0;
while (_alloc[i].value) { // Search for empty cell
if (*_alloc[i].value == val) { // Check to see if this element is already inserted
return;
}
if (psl >= _alloc[i].psl) { // When psl is higher, swap
fennec::swap(*_alloc[i].value, value);
fennec::swap(_alloc[i].psl, psl);
}
i = (i + 1) % capacity(); ++psl;
}
_alloc[i].value = fennec::move(value);
_alloc[i].psl = psl;
++_size;
}
constexpr void insert(const elem_t& val) {
elem_t value = val; // Copy Constructor invoked here
this->insert(fennec::move(value)); // Only invokes moves
}
template<typename...ArgsT>
constexpr void emplace(ArgsT&&...args) {
elem_t value = elem_t(fennec::forward<ArgsT>(args)...); // Constructor invoked here
this->insert(fennec::move(value)); // Only invokes moves
}
constexpr iterator find(const elem_t& val) const {
size_t i = _hash(val) % capacity(); // Initial search index
int psl = 0;
// Loop while there is a value and its psl is greater than our probe
while (_alloc[i].value && _alloc[i].psl > psl) {
if (*_alloc[i].value == val) {
return iterator(this, i);
}
i = (i + 1) % capacity(); ++psl;
}
return iterator(this, npos);
}
constexpr bool contains(const elem_t& val) const {
return this->find(val) != end();
}
constexpr void erase(iterator it) {
size_t i = it._i;
if (i >= capacity()) {
return;
} // These are separated due to compilers being inconsistent
if (not _alloc[i].value) {
return;
}
_alloc[i].value = nullopt;
--_size;
size_t p = i;
while (_alloc[i = (i + 1) % capacity()].value) {
size_t psl = _alloc[i].psl;
if (psl == 0) break;
fennec::swap(_alloc[i - 1].value, _alloc[i].value);
_alloc[p].psl = psl - 1;
p = i;
}
}
constexpr void erase(const elem_t& val) {
this->erase(this->find(val));
}
// ITERATOR ============================================================================================================
class iterator {
public:
constexpr iterator(const set* set, size_t i)
: _set(set)
, _i(i) {
}
constexpr ~iterator() {
_set = nullptr;
}
// prefix operator
constexpr friend iterator& operator++(iterator& rhs) {
while (++rhs._i < capacity()) {
if (rhs._set->_alloc[rhs._i]) {
return rhs;
}
}
rhs._i = npos;
return rhs;
}
constexpr friend iterator operator++(iterator& lhs, int) {
iterator prev = lhs;
++lhs;
return prev;
}
constexpr const elem_t& operator*() const {
return *_set->_alloc[_i].value;
}
constexpr bool operator==(const iterator& it) {
return _set == it._set and _i == it._i;
}
constexpr bool operator!=(const iterator& it) {
return _set != it._set or _i != it._i;
}
private:
const set* _set;
size_t _i;
};
constexpr iterator begin() const {
iterator it(this, 0);
if (not _alloc[it._i].value) {
++it;
}
return it;
}
constexpr iterator end() const {
return iterator(this, npos);
}
// PRIVATE =============================================================================================================
private:
constexpr void _expand() {
set cpy; // Create a new set
cpy._alloc.allocate(
fennec::next_prime2(_alloc.capacity())
);
fennec::memset(cpy._alloc.data(), 0, cpy._alloc.size());
// rehash
for (size_t i = 0; i < capacity(); ++i) {
if (_alloc[i].value) {
cpy.insert(fennec::move(*_alloc[i].value));
}
}
// Swap buffers
fennec::swap(_alloc, cpy._alloc);
}
allocation<node, alloc_t> _alloc;
hash_t _hash;
size_t _size;
};
}
#endif // FENNEC_CONTAINERS_SET_H

View File

@@ -99,7 +99,8 @@ public:
/// \details adds additional character for null termination. Ignores whether str is null-terminated.
/// This constructor makes the assumption that `n` is the intended number of characters.
constexpr _string(const char* str, size_t n)
: _str(str, n + 1) {
: _str(n + 1) {
fennec::memcpy(_str.data(), str, n);
_str[n] = '\0';
}
@@ -318,7 +319,7 @@ public:
constexpr void resize(size_t n) {
size_t i = size();
_str.reallocate(n + 1);
if (n > i) fennec::memset(_str.data() + i, '\0', n - i);
if (n > i) fennec::memset(_str.data() + i, '\0', n + 1 - i);
}
///
@@ -387,6 +388,10 @@ public:
return res;
}
friend constexpr _string operator+(char c, _string& str) {
return _string(c, 1) + str;
}
constexpr _string operator+(const cstring& str) const {
_string res(size() + str.size()); // Make a new string with the size of this + str
fennec::memcpy(&res[0], _str.data(), size()); // Copy the contents of this

View File

@@ -46,7 +46,12 @@
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// assert(expr, desc)
/// <td width="50%" style="vertical-align: top">
/// Make an assertion with expression `expr` and provide a description `desc`.
/// Make an assertion with expression `expr` and provide a description `desc`. Only halts in debug mode.
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// assertf(expr, desc)
/// <td width="50%" style="vertical-align: top">
/// Make an assertion with expression `expr` and provide a description `desc`. Always halts.
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// assertd(expr, desc)
@@ -65,15 +70,20 @@
using assert_handler = void (*)(const char *, const char *, int , const char *);
void __assert_impl(const char* expression, const char* file, int line, const char* function, const char* desc);
void __assert_impl(const char* expression, const char* file, int line, const char* function, const char* desc, bool halt);
// flagged unlikely to optimize branch prediction
#define assert(expression, description) \
if(not(expression)) [[unlikely]] { \
__assert_impl(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__, description); \
__assert_impl(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__, description, not FENNEC_RELEASE); \
}
#ifdef NDEBUG
#define assertf(expression, description) \
if(not(expression)) [[unlikely]] { \
__assert_impl(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__, description, true); \
}
#if FENNEC_RELEASE
#define assertd(expression, description) (0)
#else
#define assertd(expression, description) assert(expression, description)

View File

@@ -32,6 +32,8 @@
#ifndef FENNEC_LANG_CONDITIONAL_TYPES_H
#define FENNEC_LANG_CONDITIONAL_TYPES_H
#include <fennec/lang/type_identity.h>
///
/// \page fennec_lang_conditional_types Conditional Types
///
@@ -64,8 +66,6 @@
///
///
#include <fennec/lang/type_transforms.h>
namespace fennec
{
@@ -92,12 +92,12 @@ using conditional_t
// specialization of fennec::conditional for `true` case
template<typename T, typename F>
struct conditional<true, T, F> : type_transform<T>{};
struct conditional<true, T, F> : type_identity<T>{};
// specialization of fennec::conditional for `false` case
template<typename T, typename F>
struct conditional<false, T, F> : type_transform<F>{};
struct conditional<false, T, F> : type_identity<F>{};
// fennec::detect ======================================================================================================

View File

@@ -28,34 +28,34 @@ namespace fennec
namespace detail
{
template<typename> struct __make_unsigned : type_transform<undefined_t> {};
template<typename> struct __make_unsigned : type_identity<undefined_t> {};
template<> struct __make_unsigned<char_t> : type_transform<uchar_t> {};
template<> struct __make_unsigned<uchar_t> : type_transform<uchar_t> {};
template<> struct __make_unsigned<schar_t> : type_transform<uchar_t> {};
template<> struct __make_unsigned<short_t> : type_transform<ushort_t> {};
template<> struct __make_unsigned<ushort_t> : type_transform<ushort_t> {};
template<> struct __make_unsigned<uint_t> : type_transform<uint_t> {};
template<> struct __make_unsigned<int_t> : type_transform<uint_t> {};
template<> struct __make_unsigned<long_t> : type_transform<ulong_t> {};
template<> struct __make_unsigned<ulong_t> : type_transform<ulong_t> {};
template<> struct __make_unsigned<llong_t> : type_transform<ullong_t> {};
template<> struct __make_unsigned<ullong_t> : type_transform<ullong_t> {};
template<> struct __make_unsigned<char_t> : type_identity<uchar_t> {};
template<> struct __make_unsigned<uchar_t> : type_identity<uchar_t> {};
template<> struct __make_unsigned<schar_t> : type_identity<uchar_t> {};
template<> struct __make_unsigned<short_t> : type_identity<ushort_t> {};
template<> struct __make_unsigned<ushort_t> : type_identity<ushort_t> {};
template<> struct __make_unsigned<uint_t> : type_identity<uint_t> {};
template<> struct __make_unsigned<int_t> : type_identity<uint_t> {};
template<> struct __make_unsigned<long_t> : type_identity<ulong_t> {};
template<> struct __make_unsigned<ulong_t> : type_identity<ulong_t> {};
template<> struct __make_unsigned<llong_t> : type_identity<ullong_t> {};
template<> struct __make_unsigned<ullong_t> : type_identity<ullong_t> {};
template<typename> struct __make_signed : type_transform<undefined_t> {};
template<typename> struct __make_signed : type_identity<undefined_t> {};
template<> struct __make_signed<char_t> : type_transform<schar_t> {};
template<> struct __make_signed<uchar_t> : type_transform<schar_t> {};
template<> struct __make_signed<schar_t> : type_transform<schar_t> {};
template<> struct __make_signed<short_t> : type_transform<short_t> {};
template<> struct __make_signed<ushort_t> : type_transform<short_t> {};
template<> struct __make_signed<uint_t> : type_transform<int_t> {};
template<> struct __make_signed<int_t> : type_transform<int_t> {};
template<> struct __make_signed<long_t> : type_transform<long_t> {};
template<> struct __make_signed<ulong_t> : type_transform<long_t> {};
template<> struct __make_signed<llong_t> : type_transform<llong_t> {};
template<> struct __make_signed<ullong_t> : type_transform<llong_t> {};
template<> struct __make_signed<char_t> : type_identity<schar_t> {};
template<> struct __make_signed<uchar_t> : type_identity<schar_t> {};
template<> struct __make_signed<schar_t> : type_identity<schar_t> {};
template<> struct __make_signed<short_t> : type_identity<short_t> {};
template<> struct __make_signed<ushort_t> : type_identity<short_t> {};
template<> struct __make_signed<uint_t> : type_identity<int_t> {};
template<> struct __make_signed<int_t> : type_identity<int_t> {};
template<> struct __make_signed<long_t> : type_identity<long_t> {};
template<> struct __make_signed<ulong_t> : type_identity<long_t> {};
template<> struct __make_signed<llong_t> : type_identity<llong_t> {};
template<> struct __make_signed<ullong_t> : type_identity<llong_t> {};
}

View File

@@ -27,7 +27,7 @@ namespace fennec
namespace detail
{
template<typename FirstT, typename... RestT> struct __first_element : type_transform<FirstT>{};
template<typename FirstT, typename... RestT> struct __first_element : type_identity<FirstT>{};
}

View File

@@ -65,6 +65,9 @@ template<typename> struct __is_floating_point : false_type {};
template<> struct __is_floating_point<float_t> : true_type {};
template<> struct __is_floating_point<double_t> : true_type {};
template<typename> struct __is_pointer : false_type {};
template<typename T> struct __is_pointer<T*> : true_type {};
}
}

View File

@@ -0,0 +1,55 @@
// =====================================================================================================================
// 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_LANG_DETAIL_TYPE_TRANSFORMS_H
#define FENNEC_LANG_DETAIL_TYPE_TRANSFORMS_H
#include <fennec/lang/types.h>
namespace fennec
{
namespace detail
{
template<typename _Tp, typename = void>
struct __add_lvalue_reference {
using type = _Tp;
};
template<typename _Tp>
struct __add_lvalue_reference<_Tp, void_t<_Tp&>> {
using type = _Tp&;
};
template<typename _Tp, typename = void>
struct __add_rvalue_reference {
using type = _Tp;
};
template<typename _Tp>
struct __add_rvalue_reference<_Tp, void_t<_Tp&&>> {
using type = _Tp&&;
};
}
}
#endif // FENNEC_LANG_DETAIL_TYPE_TRANSFORMS_H

View File

@@ -0,0 +1,89 @@
// =====================================================================================================================
// 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_LANG_HASHING_H
#define FENNEC_LANG_HASHING_H
#include <fennec/lang/types.h>
#include <fennec/lang/type_traits.h>
namespace fennec
{
///
/// \brief Struct for hashing types, there is no default hashing function
/// \tparam Key The type to hash
template<typename Key> struct hash;
// Murmur3 Hash for 64-bit ints
template<>
struct hash<uint64_t> {
using type_t = uint64_t;
constexpr size_t operator()(uint64_t x) const {
// Murmur3
x ^= x >> 33U;
x *= 0xff51afd7ed558ccd;
x ^= x >> 33U;
x *= 0xc4ceb9fe1a85ec53;
x ^= x >> 33U;
return x;
}
};
// Wrapper for casting ints
template<typename IntT>
requires is_integral_v<IntT>
struct hash<IntT> : hash<uint64_t> {
using type_t = IntT;
};
// Wrapper for pointers
template<typename PtrT>
requires is_pointer_v<PtrT>
struct hash<PtrT> : hash<uintptr_t> {
};
// Float
template<>
struct hash<float> : hash<uint32_t> {
constexpr size_t operator()(float x) const {
return hash<uint32_t>::operator()(bit_cast<uint32_t>(x));
}
};
template<>
struct hash<double> : hash<uint64_t> {
constexpr size_t operator()(double x) const {
return hash<uint64_t>::operator()(bit_cast<uint64_t>(x));
}
};
///
/// \brief Pairs two hashes
/// \param x first hash
/// \param y second hash
/// \returns a pairing of the two hashes
constexpr size_t pair_hash(size_t x, size_t y) {
// Szudzik Pairing
return (x >= y ? (x * x) + x + y : (y * y) + x);
}
}
#endif // FENNEC_LANG_HASHING_H

View File

@@ -142,14 +142,44 @@
# define FENNEC_HAS_BUILTIN_IS_CLASS
#endif
// CONSTRUCTORS ========================================================================================================
// Difficult and Inconsistent without intrinsics
#if __has_builtin(__is_constructible)
# define FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE 1
# define FENNEC_BUILTIN_IS_CONSTRUCTIBLE(type, ...) __is_constructible(type, __VA_ARGS__)
# define FENNEC_BUILTIN_IS_CONSTRUCTIBLE(type, ...) __is_constructible(type __VA_OPT__(,) __VA_ARGS__)
#else
# define FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE 0
#endif
// Difficult and Inconsistent without intrinsics
#if __has_builtin(__is_trivially_constructible)
# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE 1
# define FENNEC_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE(type) __is_trivially_constructible(type)
#else
# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE 0
#endif
// Difficult and Inconsistent without intrinsics
#if __has_builtin(__has_trivial_destructor)
# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE 1
# define FENNEC_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE(type) __has_trivial_destructor(type)
#else
# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE 0
#endif
// ASSIGNMENTS =========================================================================================================
// Difficult and Inconsistent without intrinsics
#if __has_builtin(__is_assignable)
# define FENNEC_HAS_BUILTIN_IS_ASSIGNABLE 1
# define FENNEC_BUILTIN_IS_ASSIGNABLE(a, b) __is_assignable(a, b)
#else
# define FENNEC_HAS_BUILTIN_IS_ASSIGNABLE 0
#endif
// Type Traits
// can_convert is also very difficult to implement without intrinsics
#if __has_builtin(__is_convertible)

View File

@@ -0,0 +1,57 @@
// =====================================================================================================================
// 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_LANG_TYPE_IDENTITY_H
#define FENNEC_LANG_TYPE_IDENTITY_H
///
/// \page fennec_lang_type_identity Type Identity
///
/// \brief Part of the fennec metaprogramming library. This header defines structures for copying types with different traits
/// or rather, transform them, at compile time.
///
/// \code #include <fennec/lang/type_identity.h> \endcode
///
///
/// <table width="100%" class="fieldtable" id="table_fennec_lang_type_identity">
/// <tr><th style="vertical-align: top">Syntax
/// <th style="vertical-align: top">Description
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::type_identity "type_identity<TypeT>::type"<br>
/// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::type_identity
/// </table>
///
namespace fennec
{
///
/// \brief Base Class for Type Transformations
///
/// \details resembles a transformation from one type to T, the result is stored in the member type_transform::type
/// \tparam T Resultant Type
template<typename T> struct type_identity {
/// \brief the type to transform into
using type = T;
};
}
#endif // FENNEC_LANG_TYPE_IDENTITY_H

View File

@@ -272,6 +272,22 @@ template<typename T> struct is_floating_point
template<typename T> constexpr bool_t is_floating_point_v = is_floating_point<T> {};
// Pointer Types =======================================================================================================
///
/// \brief check if \p T is of a floating point type
///
/// \details Checks if type `T` is a floating point type and store it in `is_same::value`.
/// \tparam T type to check
template<typename T> struct is_pointer
: detail::__is_pointer<remove_cvr_t<T>>{};
///
/// \brief shorthand for ```is_floating_point<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_pointer_v = is_pointer<T> {};
// Arithmetic Types ====================================================================================================
@@ -339,7 +355,7 @@ template<typename FromT, typename ToT> struct is_convertible
template<typename FromT, typename ToT> constexpr bool_t is_convertible_v = is_convertible<FromT, ToT>{};
// fennec::is_constructible ===============================================================================================
// fennec::is_constructible ============================================================================================
///
/// \brief Check if `ClassT` can be constructed with `ArgsT,` i.e. `ClassT(ArgsT...)`.
@@ -354,7 +370,106 @@ template<typename ClassT, typename...ArgsT> struct is_constructible
template<typename ClassT, typename...ArgsT> constexpr bool_t is_constructible_v = is_constructible<ClassT, ArgsT...>{};
// fennec::
///
/// \brief Check if `ClassT` is default constructible
/// \tparam ClassT The class type to test
template<typename ClassT> struct is_default_constructible
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT,)> {};
///
/// \brief Shorthand for `is_default_constructible<ClassT>::value`
template<typename ClassT, typename...ArgsT> constexpr bool_t is_default_constructible_v = is_default_constructible<ClassT>{};
///
/// \brief Check if `ClassT` is copy constructible
/// \tparam ClassT The class type to test
template<typename ClassT> struct is_copy_constructible
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_lvalue_reference_t<const ClassT>)> {};
///
/// \brief Shorthand for `is_copy_constructible<ClassT>::value`
template<typename ClassT, typename...ArgsT> constexpr bool_t is_copy_constructible_v = is_copy_constructible<ClassT>{};
///
/// \brief Check if `ClassT` is copy constructible
/// \tparam ClassT The class type to test
template<typename ClassT> struct is_move_constructible
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_rvalue_reference_t<ClassT>)> {};
///
/// \brief Shorthand for `is_copy_constructible<ClassT>::value`
template<typename ClassT, typename...ArgsT> constexpr bool_t is_move_constructible_v = is_move_constructible<ClassT>{};
///
/// \brief Check if `ClassT` is trivially constructible
/// \tparam ClassT The class type to test
template<typename ClassT> struct is_trivially_constructible
: bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE(ClassT)> {};
///
/// \brief Shorthand for `is_trivially_constructible<ClassT, ArgsT...>::value`
template<typename ClassT> constexpr bool_t is_trivially_constructible_v = is_trivially_constructible<ClassT>{};
// fennec::is_trivially_destructible ===================================================================================
///
/// \brief Check if `ClassT` is trivially destructible
/// \tparam ClassT The class type to test
template<typename ClassT> struct is_trivially_destructible
: bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE(ClassT)> {};
///
/// \brief Shorthand for `is_trivially_destructible<ClassT, ArgsT...>::value`
template<typename ClassT> constexpr bool_t is_trivially_destructible_v = is_trivially_destructible<ClassT>{};
// fennec::is_assignable ===============================================================================================
///
/// \brief Check if `ClassT` can be constructed with `ArgsT,` i.e. `ClassT(ArgsT...)`.
/// This may be read as "is `ClassT` constructible with `ArgsT`"
/// \tparam ClassAT The class type to test
/// \tparam ClassBT The arguments for the specific constructor
template<typename ClassAT, typename ClassBT> struct is_assignable
: bool_constant<FENNEC_BUILTIN_IS_ASSIGNABLE(ClassAT, ClassBT)> {};
///
/// \brief Shorthand for `is_constructible<ClassT, ArgsT...>::value`
template<typename ClassT, typename...ArgsT> constexpr bool_t is_assignable_v = is_assignable<ClassT, ArgsT...>{};
// fennec::is_copy_assignable ==========================================================================================
///
/// \brief Check if `ClassT` is copy assignable
/// \tparam ClassT The class type to test
template<typename ClassT> struct is_copy_assignable
: bool_constant<FENNEC_BUILTIN_IS_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_lvalue_reference_t<const ClassT>)> {};
///
/// \brief Shorthand for `is_copy_assignable<ClassT>::value`
template<typename ClassT> constexpr bool_t is_copy_assignable_v = is_copy_assignable<ClassT>{};
// fennec::is_move_assignable ==========================================================================================
///
/// \brief Check if `ClassT` is move assignable
/// \tparam ClassT The class type to test
template<typename ClassT> struct is_move_assignable
: bool_constant<FENNEC_BUILTIN_IS_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_rvalue_reference_t<ClassT>)> {};
///
/// \brief Shorthand for `is_move_assignable<ClassT>::value`
template<typename ClassT> constexpr bool_t is_move_assignable_v = is_move_assignable<ClassT>{};
//

View File

@@ -31,6 +31,9 @@
#ifndef FENNEC_LANG_TYPE_TRANSFORMS_H
#define FENNEC_LANG_TYPE_TRANSFORMS_H
#include <fennec/lang/type_identity.h>
#include <fennec/lang/detail/__type_transforms.h>
///
/// \page fennec_lang_type_transforms Type Transforms
///
@@ -44,11 +47,6 @@
/// <tr><th style="vertical-align: top">Syntax
/// <th style="vertical-align: top">Description
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::type_transform "type_transform<TypeT>::type"<br>
/// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::type_transform
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::add_pointer "add_pointer<TypeT>::type"<br>
/// \ref fennec::add_pointer_t "add_pointer_t<TypeT>"
/// <td width="50%" style="vertical-align: top">
@@ -127,22 +125,6 @@
namespace fennec
{
// fennec::type_transform ==============================================================================================
///
/// \brief Base Class for Type Transformations
///
/// \details resembles a transformation from one type to T, the result is stored in the member type_transform::type
/// \tparam T Resultant Type
template<typename T> struct type_transform {
///
/// \brief the type to transform into
using type = T;
};
// Pointer Conversions =================================================================================================
///
@@ -150,7 +132,7 @@ template<typename T> struct type_transform {
///
/// \details adds a pointer to the provided type such that `T` becomes `T*`
/// \tparam T Resultant Type
template<typename T> struct add_pointer : type_transform<T*>{};
template<typename T> struct add_pointer : type_identity<T*>{};
///
/// \brief shorthand for `typename add_pointer<T>::type`
@@ -162,10 +144,10 @@ template<typename T> using add_pointer_t = typename add_pointer<T>::type;
///
/// \details removes a pointer from the provided type such that `T*` becomes `T`
/// \tparam T Resultant Type
template<typename T> struct remove_pointer : type_transform<T> {};
template<typename T> struct remove_pointer : type_identity<T> {};
// specialization for T*
template<typename T> struct remove_pointer<T*> : type_transform<T> {};
template<typename T> struct remove_pointer<T*> : type_identity<T> {};
///
/// \brief shorthand for `typename remove_pointer<T>::type`
@@ -180,7 +162,7 @@ template<typename T> using remove_pointer_t = typename remove_pointer<T>::type;
///
/// \details adds a pointer to the provided type such that `T` becomes `T&`
/// \tparam T Resultant Type
template<typename T> struct add_reference : type_transform<T&> {};
template<typename T> struct add_reference : type_identity<T&> {};
///
/// \brief shorthand for `typename add_reference<T>::type`
@@ -192,19 +174,43 @@ template<typename T> using add_reference_t = typename add_reference<T>::type;
///
/// \details removes references from the provided type such that `T&` and `T&&` become `T`
/// \tparam T Reference Type
template<typename T> struct remove_reference : type_transform<T> {};
template<typename T> struct remove_reference : type_identity<T> {};
// specialization for `T&`
template<typename T> struct remove_reference<T&> : type_transform<T> {};
template<typename T> struct remove_reference<T&> : type_identity<T> {};
// specialization for `T&&`
template<typename T> struct remove_reference<T&&> : type_transform<T> {};
template<typename T> struct remove_reference<T&&> : type_identity<T> {};
///
/// \brief shorthand for `typename remove_reference<T>::type`
template<typename T> using remove_reference_t = typename remove_reference<T>::type;
///
/// \brief add a lvalue reference to \p T
///
/// \details adds a lvalue reference to the provided type such that 'T' becomes 'T&'
/// \tparam T Reference Type
template<typename T> struct add_lvalue_reference : detail::__add_lvalue_reference<T> {};
///
/// \brief shorthand for `typename remove_reference<T>::type`
template<typename T> using add_lvalue_reference_t = typename add_lvalue_reference<T>::type;
///
/// \brief add a rvalue reference to \p T
///
/// \details adds a rvalue reference to the provided type such that 'T' becomes 'T&&'
/// \tparam T Reference Type
template<typename T> struct add_rvalue_reference : detail::__add_rvalue_reference<T> {};
///
/// \brief shorthand for `typename remove_reference<T>::type`
template<typename T> using add_rvalue_reference_t = typename add_rvalue_reference<T>::type;
// Const & Volatile Conversions ========================================================================================
@@ -213,14 +219,14 @@ template<typename T> using remove_reference_t = typename remove_reference<T>::t
///
/// \details adds const qualification to the provided type such that `T` becomes `const T`
/// \tparam T Reference Type
template<typename T> struct add_const : type_transform<const T> {};
template<typename T> struct add_const : type_identity<const T> {};
///
/// \brief shorthand for `typename add_const<T>::type`
template<typename T> using add_const_t = typename add_const<T>::type;
// specialization for const types
template<typename T> struct add_const<const T> : type_transform<const T> {};
template<typename T> struct add_const<const T> : type_identity<const T> {};
///
@@ -228,14 +234,14 @@ template<typename T> struct add_const<const T> : type_transform<const T> {};
///
/// \details removes const qualification from the provided type such that `const T` becomes `T`
/// \tparam T Reference Type
template<typename T> struct remove_const : type_transform<T> {};
template<typename T> struct remove_const : type_identity<T> {};
///
/// \brief shorthand for `typename remove_const<T>::type`
template<typename T> using remove_const_t = typename remove_const<T>::type;
// specialization for const types
template<typename T> struct remove_const<const T> : type_transform<T> {};
template<typename T> struct remove_const<const T> : type_identity<T> {};
@@ -244,14 +250,14 @@ template<typename T> struct remove_const<const T> : type_transform<T> {};
///
/// \details removes references from the provided type such that `T` becomes `volatile T`
/// \tparam T Reference Type
template<typename T> struct add_volatile : type_transform<volatile T> {};
template<typename T> struct add_volatile : type_identity<volatile T> {};
///
/// \brief shorthand for `typename add_volatile<T>::type`
template<typename T> using add_volatile_t = typename add_volatile<T>::type;
// specialization for volatile types
template<typename T> struct add_volatile<volatile T> : type_transform<volatile T> {};
template<typename T> struct add_volatile<volatile T> : type_identity<volatile T> {};
///
@@ -259,14 +265,14 @@ template<typename T> struct add_volatile<volatile T> : type_transform<volatile T
///
/// \details removes references from the provided type such that `volatile T` becomes `T`
/// \tparam T Reference Type
template<typename T> struct remove_volatile : type_transform<T> {};
template<typename T> struct remove_volatile : type_identity<T> {};
///
/// \brief shorthand for `typename remove_volatile<T>::type`
template<typename T> using remove_volatile_t = typename remove_volatile<T>::type;
// specialization for volatile types
template<typename T> struct remove_volatile<volatile T> : type_transform<T> {};
template<typename T> struct remove_volatile<volatile T> : type_identity<T> {};
@@ -276,20 +282,20 @@ template<typename T> struct remove_volatile<volatile T> : type_transform<T> {};
/// \details removes references from the provided type such that `T`, `const T`, and `volatile T` become
/// `const volatile T`
/// \tparam T Reference Type
template<typename T> struct add_cv : type_transform<const volatile T> {};
template<typename T> struct add_cv : type_identity<const volatile T> {};
///
/// \brief shorthand for `typename add_cv<T>::type`
template<typename T> using add_cv_t = typename add_cv<T>::type;
// specialization for const types
template<typename T> struct add_cv<const T> : type_transform<const volatile T> {};
template<typename T> struct add_cv<const T> : type_identity<const volatile T> {};
// specialization for volatile types
template<typename T> struct add_cv<volatile T> : type_transform<const volatile T> {};
template<typename T> struct add_cv<volatile T> : type_identity<const volatile T> {};
// specialization for const volatile types
template<typename T> struct add_cv<const volatile T> : type_transform<const volatile T> {};
template<typename T> struct add_cv<const volatile T> : type_identity<const volatile T> {};
@@ -299,16 +305,16 @@ template<typename T> struct add_cv<const volatile T> : type_transform<const vola
/// \details removes const and volatile from the provided type such that `const T`, `volatile T`, and
/// `const volatile T` become `T`
/// \tparam T Reference Type
template<typename T> struct remove_cv : type_transform<T> {};
template<typename T> struct remove_cv : type_identity<T> {};
// specialization for const types
template<typename T> struct remove_cv<const T> : type_transform<T> {};
template<typename T> struct remove_cv<const T> : type_identity<T> {};
// specialization for volatile types
template<typename T> struct remove_cv<volatile T> : type_transform<T> {};
template<typename T> struct remove_cv<volatile T> : type_identity<T> {};
// specialization for const volatile types
template<typename T> struct remove_cv<const volatile T> : type_transform<T> {};
template<typename T> struct remove_cv<const volatile T> : type_identity<T> {};
///
/// \brief shorthand for `typename remove_cv<T>::type`
@@ -321,7 +327,7 @@ template<typename T> using remove_cv_t = typename remove_cv<T>::type;
///
/// \details adds references and const volatile qualifiers to the provided type.
/// \tparam T Reference Type
template<typename T> struct add_cvr : type_transform<add_reference_t<add_cv_t<T>>> {};
template<typename T> struct add_cvr : type_identity<add_reference_t<add_cv_t<T>>> {};
///
/// \brief shorthand for `typename add_cvr<T>::type`
@@ -334,7 +340,7 @@ template<typename T> using add_cvr_t = typename add_cvr<T>::type;
///
/// \details removes const and volatile from the provided type such that
/// \tparam T Reference Type
template<typename T> struct remove_cvr : type_transform<remove_cv_t<remove_reference_t<T>>> {};
template<typename T> struct remove_cvr : type_identity<remove_cv_t<remove_reference_t<T>>> {};
///

View File

@@ -242,7 +242,6 @@ namespace fennec
/// \name Special Types
/// @{
using nullptr_t = decltype(nullptr); ///< \brief Null Pointer Type
using intptr_t = intptr_t; ///< \brief Signed Integer Capable of Holding a Pointer to void
using uintptr_t = uintptr_t; ///< \brief Unsigned Integer Capable of Holding a Pointer to void
@@ -251,6 +250,7 @@ namespace fennec
using size_t = size_t; ///< \brief Unsigned Integer Type Returned By `sizeof`, `sizeof...`, and `alignof`
using ptrdiff_t = __PTRDIFF_TYPE__; ///< \brief Signed Integer Type Returned by the Subtraction of two Pointers
class undefined_t; ///< \brief undefined class for SFINAE
template<typename...> using void_t = void; ///< \brief Void type used for SFINAE
@@ -263,15 +263,15 @@ namespace fennec
/// \name Sized Integer Types
/// @{
using int8_t = schar_t; ///< \brief Signed 8-bit integer
using int16_t = short_t; ///< \brief Signed 16-bit integer
using int32_t = conditional_t<sizeof(int_t) == 4, int_t, long_t>; ///< \brief Signed 32-bit integer
using int64_t = llong_t; ///< \brief Signed 64-bit integer
using int8_t = schar_t; ///< \brief Signed 8-bit integer
using int16_t = short_t; ///< \brief Signed 16-bit integer
using int32_t = conditional_t<sizeof(int_t) == 4, int_t, long_t>; ///< \brief Signed 32-bit integer
using int64_t = conditional_t<sizeof(long_t) == 8, long_t, llong_t>; ///< \brief Signed 64-bit integer
using uint8_t = uchar_t; ///< \brief Unsigned 8-bit integer
using uint16_t = ushort_t; ///< \brief Unsigned 16-bit integer
using uint32_t = conditional_t<sizeof(uint_t) == 4, uint_t, ulong_t>; ///< \brief Unsigned 32-bit integer
using uint64_t = ullong_t; ///< \brief Unsigned 64-bit integer
using uint8_t = uchar_t; ///< \brief Unsigned 8-bit integer
using uint16_t = ushort_t; ///< \brief Unsigned 16-bit integer
using uint32_t = conditional_t<sizeof(uint_t) == 4, uint_t, ulong_t>; ///< \brief Unsigned 32-bit integer
using uint64_t = conditional_t<sizeof(ulong_t) == 8, ulong_t, ullong_t>; ///< \brief Unsigned 64-bit integer
/// @}

View File

@@ -60,6 +60,7 @@
///
#include <fennec/lang/type_transforms.h>
#include <fennec/lang/type_traits.h>
namespace fennec
{
@@ -104,6 +105,29 @@ template<typename T> constexpr const remove_reference_t<T>& copy(T&& x) noexcept
return x;
}
///
/// \brief Swaps x and y
/// \tparam T the fundamental type
/// \param x first value
/// \param y second value
template<typename T> requires is_fundamental_v<T>
constexpr void swap(T& x, T& y) noexcept {
T a = x;
x = y;
y = a;
}
///
/// \brief Swaps x and y without invoking destructor
/// \tparam T the type
/// \param x first value
/// \param y second value
template<typename T> constexpr void swap(T& x, T& y) noexcept {
T a = fennec::move(x);
x = fennec::move(y);
y = fennec::move(a);
}
}
#endif // FENNEC_LANG_UTILITY_H

View File

@@ -88,6 +88,7 @@
///
#include <fennec/math/detail/__math.h>
#include <fennec/math/vector.h>
namespace fennec
{

View File

@@ -0,0 +1,107 @@
// =====================================================================================================================
// 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_MATH_EXT_PRIMES_H
#define FENNEC_MATH_EXT_PRIMES_H
#include <fennec/math/exponential.h>
namespace fennec
{
template<typename genType>
constexpr bool is_prime(genType x) {
// Base Cases Covers
if (x <= 1) return false; // Eliminates 0 and 1
if (x <= 3) return true; // Eliminates 2 and 3
if (x % 2 == 0 or x % 3 == 0) return false; // Eliminates even numbers and numbers divisible by 3
// 4, 6, 8, 9, 10, 12, 14, 15
if (x < 15) return true; // Covers 5, 7, 11, 13
// Due to the property of 15 being divisible by 5 and the nature of primes
// All prime numbers must end in 1, 3, 7, 9
// when x/15 is even, x%15 must be odd
// and when x/15 is odd, x%15 must be even
// To explain, when x/15 is even, 15*x/15 ends in 0, and when odd, ends in 5
// Thus when x/15 is even, 15*x/15 ends in 0, and the results are 1, 3, 7, 11, 13
// And when x/15 is even, 15*x/15 ends in 5, and the results are 2, 4, 8, 14
genType mod15 = x % 15;
genType mod15e = mod15 % 2;
genType div15e = (x / 15) % 2;
if (mod15e == div15e) return false;
// Iterate
genType limit = sqrt(x);
for (genType i = 5; i <= limit; i += 6) {
if (x % i == 0 || x % (i + 2) == 0) {
return false;
}
}
return true;
}
template<typename genType>
constexpr genType next_prime(genType x) {
genType n = (x + 1) / 6 + 1;
while (true) {
x = (n++ * 6) - 1;
if (fennec::is_prime(x)) return x;
if (fennec::is_prime(x += 2)) return x;
}
}
template<typename genType>
constexpr genType next_prime2(genType x) {
genType n = (x + 1) / 6;
n *= 2;
while (true) {
x = (n++ * 6) - 1;
if (fennec::is_prime(x)) return x;
if (fennec::is_prime(x += 2)) return x;
}
}
template<typename genType>
constexpr genType prev_prime(genType x) {
genType n = (x + 1) / 6 - 1;
while (true) {
x = (n-- * 6) - 1;
if (fennec::is_prime(x)) return x;
if (fennec::is_prime(x += 2)) return x;
}
}
template<typename genType>
constexpr genType prev_prime2(genType x) {
genType n = (x + 1) / 6;
n /= 2;
while (true) {
x = (n-- * 6) - 1;
if (fennec::is_prime(x)) return x;
if (fennec::is_prime(x += 2)) return x;
}
}
}
#endif // FENNEC_MATH_EXT_PRIMES_H

View File

@@ -105,7 +105,7 @@ public:
///
/// \brief Component Constructor
/// \param w The real component
/// \param w The scalar component
/// \param x The coefficient of the `i` component
/// \param y The coefficient of the `j` component
/// \param z The coefficient of the `k` component
@@ -113,10 +113,18 @@ public:
data = { x, y, z, w };
}
///
/// \brief Component Constructor
/// \param s The scalar component
/// \param v The vector component
constexpr quaternion(scalar_t s, vec3_t v) {
data = { v.x, v.y, v.z, s };
}
///
/// \brief Vector Constructor
/// \param v A 4d vector
constexpr quaternion(const vec<scalar_t, 4>& v) {
constexpr quaternion(const vec4_t& v) {
data = v.data;
}

View File

@@ -131,7 +131,7 @@ constexpr qua<genType> rotation(const vec<genType, 3>& axis, genType angle) {
vec<genType, 3> a = fennec::normalize(axis);
const genType s = fennec::sin(angle);
return qua<genType>(fennec::cos(angle * genType(0.5)), s * a.x, s * a.y, s * a.z);
return qua<genType>(fennec::cos(angle * genType(0.5)), s * a);
}
/// \brief enum to denote the unit-axis of rotation

View File

@@ -457,14 +457,11 @@ public:
/// \param alloc the allocation to copy
/// \returns a reference to `this`
constexpr allocation& operator=(allocation&& alloc) noexcept {
// Copy contents
_alloc = alloc._alloc;
_data = alloc._data;
_capacity = alloc._capacity;
// Cleanup alloc
alloc._data = nullptr;
alloc._capacity = 0;
// Copy contents
fennec::swap(_alloc, alloc._alloc);
fennec::swap(_data, alloc._data);
fennec::swap(_capacity, alloc._capacity);
return *this;
}
@@ -525,6 +522,11 @@ public:
return _data[i];
}
constexpr value_t operator[](size_t i) const requires is_fundamental_v<value_t> {
assertd(i < size(), "Array Out of Bounds");
return _data[i];
}
constexpr const value_t& operator[](size_t i) const {
assertd(i < size(), "Array Out of Bounds");
return _data[i];

View File

@@ -0,0 +1,188 @@
// =====================================================================================================================
// 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_LANG_BYTES_H
#define FENNEC_LANG_BYTES_H
#include <fennec/lang/assert.h>
#include <fennec/lang/types.h>
#include <fennec/lang/hashing.h>
namespace fennec
{
/// \brief byte type
using byte_t = uint8_t;
///
/// \brief container for handling byte arrays
struct byte_array {
public:
///
/// \brief Default Constructor
constexpr byte_array()
: _carr(nullptr)
, _size(0)
, _const(true) {
}
///
/// \brief Buffer Constructor
/// \param arr the buffer to wrap
/// \param n the size of the buffer in bytes
constexpr byte_array(void* arr, size_t n)
: _arr(static_cast<byte_t*>(arr))
, _size(n)
, _const(false) {
}
///
/// \brief Const Buffer Constructor
/// \param arr the buffer to wrap
/// \param n the size of the buffer in bytes
constexpr byte_array(const void* arr, size_t n)
: _carr(static_cast<const byte_t*>(arr))
, _size(n)
, _const(true) {
}
///
/// \brief Buffer Constructor
/// \param arr the buffer to wrap
/// \tparam n the size of the buffer in elements
template<typename T, size_t n>
constexpr byte_array(T arr[n])
: byte_array(arr, n * sizeof(T)) {
}
///
/// \brief Const Buffer Constructor
/// \param arr the buffer to wrap
/// \tparam n the size of the buffer in elements
template<typename T, size_t n>
constexpr byte_array(const T arr[n])
: byte_array(arr, n * sizeof(T)) {
}
///
/// \returns The size of the array in bytes
constexpr size_t size() const {
return _size;
}
///
/// \brief Array Access Operator
/// \param i the index to access
/// \returns a reference to the byte at `i`
constexpr byte_t& operator[](int i) {
assertd(not _const, "Attempted to Access Const-Qualified Memory as Non-Const");
assertd(i < _size, "Array Out of Bounds");
return _arr[i];
}
///
/// \brief Const Array Access Operator
/// \param i the index to access
/// \returns a copy of the byte at `i`
constexpr byte_t operator[](int i) const {
assertd(not _const, "Attempted to Access Const-Qualified Memory as Non-Const");
assertd(i < _size, "Array Out of Bounds");
return _carr[i];
}
///
/// \brief Cast Function
/// \tparam T type to cast to
/// \returns a pointer to the underlying buffer interpreted as an array of `T`
template<typename T>
constexpr T* cast() {
void* temp = _arr;
return static_cast<T*>(temp);
}
///
/// \brief Const Cast Function
/// \tparam T type to cast to
/// \returns a pointer to the underlying buffer interpreted as an array of `T`
template<typename T>
constexpr const T* cast() const {
const void* temp = _carr;
return static_cast<T*>(temp);
}
private:
union { // hack to allow both const qualified and non-const strings
byte_t* _arr;
const byte_t* _carr;
};
size_t _size;
bool _const;
};
///
/// \brief Byte Array Hash Function
template<>
struct hash<byte_array> {
size_t operator()(const byte_array& bytes) {
// Murmur2
static constexpr uint64_t m = 0xc6a4a7935bd1e995;
static constexpr uint64_t s = 0xff51afd7ed558ccd;
static constexpr uint64_t r = 47;
const uint64_t n = bytes.size();
uint64_t h = s ^ (n * m);
const uint64_t* x = bytes.cast<>();
const uint64_t* y = x + (n / sizeof(uint64_t));
while (x != y) {
uint64_t k = *x++;
k *= m;
k ^= k >> r;
k *= m;
h ^= k;
h *= m;
}
const uint8_t* b = (const uint8_t*)x;
switch (n & 7) {
case 7: h ^= uint64_t(b[6]) << 48;
case 6: h ^= uint64_t(b[5]) << 40;
case 5: h ^= uint64_t(b[4]) << 32;
case 4: h ^= uint64_t(b[3]) << 24;
case 3: h ^= uint64_t(b[2]) << 16;
case 2: h ^= uint64_t(b[1]) << 8;
case 1: h ^= uint64_t(b[0]);
h *= m;
default:
}
h ^= h >> r;
h *= m;
h ^= h >> r;
return h;
}
};
}
#endif // FENNEC_LANG_BYTES_H

View File

@@ -71,7 +71,7 @@ private:
using __diff_t = typename TypeT::diff_t; // Helper to prevent substitution issues with detecting the difference type
template<typename BaseT, typename OElemT> // Helper to prevent substitution issues with detecting a defined rebind
using __rebind_helper = type_transform<typename BaseT::template rebind<OElemT>>;
using __rebind_helper = type_identity<typename BaseT::template rebind<OElemT>>;
public:
using pointer_t = ClassT;

View File

@@ -54,19 +54,19 @@ struct nothrow_t
size_t pagesize();
template<typename TypeT> void construct(TypeT* ptr) {
ptr->TypeT();
new(ptr) TypeT();
}
template<typename TypeT> void construct(TypeT* ptr, const TypeT& val) {
ptr->TypeT(val);
new(ptr) TypeT(val);
}
template<typename TypeT> void construct(TypeT* ptr, TypeT&& val) {
ptr->TypeT(fennec::forward<TypeT>(val));
new(ptr) TypeT(fennec::forward<TypeT>(val));
}
template<typename TypeT, typename...ArgsT> void construct(TypeT* ptr, ArgsT...args) {
ptr->TypeT(fennec::forward<TypeT>(args)...);
template<typename TypeT, typename...ArgsT> void construct(TypeT* ptr, ArgsT&&...args) {
new(ptr) TypeT(fennec::forward<ArgsT>(args)...);
}
template<typename TypeT> void destruct(TypeT* ptr) {

View File

@@ -0,0 +1,22 @@
// =====================================================================================================================
// 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_INTERFACE_DIALOG_H
#define FENNEC_PLATFORM_INTERFACE_DIALOG_H
#endif // FENNEC_PLATFORM_INTERFACE_DIALOG_H

View File

@@ -0,0 +1,47 @@
// =====================================================================================================================
// 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_INTERFACE_DISPLAY_H
#define FENNEC_PLATFORM_INTERFACE_DISPLAY_H
#include <fennec/platform/interface/fwd.h>
namespace fennec
{
///
/// \brief Interface for display management
class display
{
public:
struct config {
};
virtual bool connected() const = 0;
protected:
virtual ~display() = default;
private:
config _config;
};
}
#endif // FENNEC_PLATFORM_INTERFACE_DISPLAY_H

View File

@@ -0,0 +1,30 @@
// =====================================================================================================================
// 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_INTERFACE_FORWARD_H
#define FENNEC_PLATFORM_INTERFACE_FORWARD_H
namespace fennec
{
class window;
class display;
}
#endif // FENNEC_PLATFORM_INTERFACE_FORWARD_H

View File

@@ -0,0 +1,74 @@
// =====================================================================================================================
// 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_INTERFACE_PLATFORM_H
#define FENNEC_PLATFORM_INTERFACE_PLATFORM_H
#include <fennec/fproc/strings/string.h>
#include <fennec/platform/interface/fwd.h>
namespace fennec
{
class platform {
public:
using shared_object = struct shared_object;
using function_pointer = void (*)(void);
struct shared_lib {
shared_object* _lib;
const cstring _name;
};
enum class user {
client,
server
};
struct config {
user type;
};
// Functions with default implementations
virtual string get_environment_variable(const cstring& var);
// Pure Virtual Functions
virtual display* get_display() = 0;
virtual shared_object* load_object(const cstring& file) = 0;
virtual void unload_object(shared_object* obj) = 0;
virtual function_pointer find_symbol(shared_object* hndl, const cstring& name) = 0;
protected:
platform(user t);
virtual ~platform() = default;
private:
config _config;
};
}
#endif // FENNEC_PLATFORM_INTERFACE_PLATFORM_H

View File

@@ -0,0 +1,137 @@
// =====================================================================================================================
// 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_INTERFACE_WINDOW_H
#define FENNEC_PLATFORM_INTERFACE_WINDOW_H
#include <fennec/fproc/strings/string.h>
#include <fennec/platform/interface/fwd.h>
namespace fennec
{
///
/// \brief interface for handling windows
/// \details the interface makes no guarantees about the bit-depth and is completely dependent on the implementation.
class window {
public:
enum class fullscreen_mode {
windowed = 0,
borderless,
fullscreen
};
enum flags_ : uint32_t {
flags_none = 0,
flags_child = 0x1 << 0,
flags_modal = 0x1 << 1,
flags_grab_mouse = 0x1 << 2,
flags_grab_keyboard = 0x1 << 3,
flags_block_screensaver = 0x1 << 4,
};
union bits {
uint32_t depth;
uint8_t r, g, b, a;
};
struct config {
string title;
uint32_t flags;
size_t width, height;
fullscreen_mode fullscreen;
bits bit_depth;
};
virtual bool set_title(const cstring& title) = 0;
virtual bool set_title(const string& title) = 0;
virtual bool set_width(size_t w) = 0;
virtual bool set_height(size_t h) = 0;
virtual bool set_size(size_t w, size_t h) = 0;
virtual bool set_fullscreen_mode(fullscreen_mode mode) = 0;
virtual bool set_resizable(bool e) = 0;
virtual bool grab_keyboard(bool e) = 0;
virtual bool grab_mouse(bool e) = 0;
virtual bool block_screensaver(bool e) = 0;
bool is_child() const {
return _config.flags & flags_child;
}
bool is_modal() const {
return _config.flags & flags_modal;
}
display* get_display() {
return _display;
}
const display* get_display() const {
return _display;
}
const string& get_title() const {
return _config.title;
}
size_t get_width() const {
return _config.width;
}
size_t get_height() const {
return _config.height;
}
fullscreen_mode get_fullscreen_mode() const {
return _config.fullscreen;
}
bool is_keyboard_grabbed() const {
return _config.flags & flags_grab_keyboard;
}
bool is_mouse_grabbed() const {
return _config.flags & flags_grab_mouse;
}
bool is_screensaver_blocked() const {
return _config.flags & flags_block_screensaver;
}
protected:
virtual ~window() = default;
window(display* display, window* parent, bool modal);
display* _display;
window* _parent;
config _config;
private:
};
}
#endif // FENNEC_PLATFORM_INTERFACE_WINDOW_H

View File

@@ -0,0 +1,59 @@
// =====================================================================================================================
// 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_PLATFORM_H
#define FENNEC_PLATFORM_LINUX_PLATFORM_H
#include <fennec/containers/set.h>
#include <fennec/platform/interface/display.h>
#include <fennec/platform/interface/platform.h>
namespace fennec
{
class linux_platform : public platform {
public:
enum display_ : int_t {
display_none = -1,
display_x11 = 0,
display_wayland,
};
linux_platform(user type);
~linux_platform() override;
shared_object* load_object(const cstring& file) override;
void unload_object(shared_object* obj) override;
function_pointer find_symbol(shared_object* hndl, const cstring& name) override;
display* get_display() override;
private:
display* _display;
int_t _display_driver;
void _runtime_client_checks();
void _find_display_driver();
void _runtime_server_checks();
};
}
#endif // FENNEC_PLATFORM_LINUX_PLATFORM_H

View File

@@ -0,0 +1,51 @@
// =====================================================================================================================
// 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_DISPLAY_H
#define FENNEC_PLATFORM_LINUX_WAYLAND_DISPLAY_H
#include <fennec/fproc/strings/cstring.h>
#include <fennec/platform/interface/display.h>
#include <fennec/platform/linux/platform.h>
#include <fennec/platform/linux/wayland/lib/fwd.h>
namespace fennec
{
namespace wayland
{
class wayland_display : public display {
public:
wayland_display(linux_platform* platform);
wayland_display(linux_platform* platform, const cstring& drv);
~wayland_display() override;
bool connected() const override;
private:
struct wl_display* _handle;
linux_platform* _platform;
};
}
}
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_DISPLAY_H

View File

@@ -0,0 +1,37 @@
// =====================================================================================================================
// 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_DYN_H
#define FENNEC_PLATFORM_LINUX_WAYLAND_DYN_H
#include <fennec/platform/linux/platform.h>
namespace fennec
{
namespace wayland
{
bool load_symbols(linux_platform* platform);
void unload_symbols(linux_platform* platform);
}
}
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_DYN_H

View File

@@ -0,0 +1,24 @@
// =====================================================================================================================
// 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_FWD_H
#define FENNEC_PLATFORM_LINUX_WAYLAND_FWD_H
struct wl_display;
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_FWD_H

View File

@@ -0,0 +1,37 @@
// =====================================================================================================================
// 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/>.
// =====================================================================================================================
#include <fennec/platform/linux/wayland/lib/fwd.h>
#ifndef FENNEC_LIB
#define FENNEC_LIB(...)
#endif
#ifndef FENNEC_SYMBOL
#define FENNEC_SYMBOL(...)
#endif
FENNEC_LIB(WAYLAND);
FENNEC_SYMBOL(struct wl_display*, wl_display_connect, const char* name);
FENNEC_SYMBOL(void, wl_display_disconnect, wl_display* name);
#undef FENNEC_LIB
#undef FENNEC_SYMBOL

View File

@@ -0,0 +1,27 @@
// =====================================================================================================================
// 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_SYM_DEF_H
#define FENNEC_PLATFORM_LINUX_WAYLAND_SYM_DEF_H
#define FENNEC_LIB(name) inline bool FENNEC_HAS_LIB_##name = false;
#define FENNEC_SYMBOL(ret, fn, ...) using sym_##fn = ret(*)(__VA_ARGS__); \
inline sym_##fn fn = nullptr;
#include <fennec/platform/linux/wayland/lib/sym.h>
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_SYM_DEF_H