- Fixed a bunch of compilation errors and warnings

- Added frameworks for retrieving specific filesystem information for a target platform
This commit is contained in:
2025-07-10 01:10:13 -04:00
parent cc20af7504
commit 4c0d36c933
22 changed files with 510 additions and 85 deletions

View File

@@ -75,8 +75,9 @@ add_library(fennec STATIC
# MEMORY ===============================================================================================================
include/fennec/memory/new.h source/memory/new.cpp
include/fennec/memory/allocator.h
include/fennec/memory/common.h
include/fennec/memory/allocator.h
include/fennec/memory/memory.h
include/fennec/memory/pointers.h
include/fennec/memory/ptr_traits.h
@@ -118,15 +119,17 @@ add_library(fennec STATIC
# FPROC ================================================================================================================
# Strings
include/fennec/fproc/strings/cstring.h
include/fennec/fproc/strings/locale.h
include/fennec/fproc/strings/string.h
include/fennec/fproc/strings/detail/__ctype.h
include/fennec/fproc/strings/cstring.h
include/fennec/fproc/strings/locale.h
include/fennec/fproc/io/file.h
source/fproc/io/file.cpp
include/fennec/fproc/filesystem/path.h
include/fennec/memory/memory.h
# IO
include/fennec/fproc/io/file.h source/fproc/io/file.cpp
include/fennec/fproc/io/common.h
source/fproc/io/common.cpp
)
# add metaprogramming templates as a dependency and also force documentation to be generated when fennec is compiled

View File

@@ -63,7 +63,7 @@ This however can be achieved using events at different stages of those engines t
- 2D Physics (`physics2d`)
- 2D & 3D Audio (`audio`)
### Security Ramblings:
### File Security Ramblings:
Windows is starting to piss me off, so I am considering dropping official support for MSVC. MinGW and Cygwin
will still work for compiling on Windows if this ends up being the case. The reason for this is that there are
@@ -85,7 +85,7 @@ This issue can be solved using `fopen("<file>", "w+")`, however this specific be
learning how to work with file systems. We can attempt to abstract this away with another wrapper, or simply write
the file structure to handle this behaviour properly. The downside to this method overall is that it will break
common conventions of how humans interpret filesystems and the related control flow logic. What we can do is force the
`'+'` flag to always be present for write operations, and raise an error, when desired, if the file is not empty. This
`'+'` flag to always be present for write operations, and raise an error when desired, if the file is not empty. This
unfortunately would have the downside of being unable to open a file as write only.
Using `"wx"` in this instance would not be sufficient since it would require a second call to fopen, which would
@@ -99,6 +99,38 @@ debugging it, and testing for vulnerabilities. As stated above, this implementat
so we would not have to entirely drop support for Windows. However, MSVC is the most widely used compiler for Windows
applications and is native to Visual Studio and VSCode.
What is probably the best solution is to wrap everything in a file interface that does not allow the direct setting of
these flags. Then we set our own usage type for the file that informs which flags should be used.
We need to be able to handle the following types of files:
- Assets, such as scenes, audio, textures, metadata, meshes, etc.
- Save files, setting files, etc.
One of the nice things about the assets is that they are guaranteed to be read-only once an application is installed
on the computer of the end-user. Therefore, this issue only arises with save files and custom file formats.
When the editor is run, all these files should be opened in read/write mode.
Naming conventions should exist for the types of files and how they are read. For example, in release mode,
most assets should be opened once, and then closed immediately. However, this does not make sense for formats
that are continuous and too large to be kept around in memory, such as video formats.
Perhaps the following conventions:
- Static Asset
- Stream Asset
- Resource
We can turn this into an object-oriented approach by having different formats inherit these base types. We may still
have a base file type that wraps C functionality, but discourage developers from using the interface.
We could also declare the file interface extern so that only internal files know the implementation. However, I would
not be satisfied by doing this since it would prevent developers from implementing custom file type implementations.
Conserving memory is not really an issue here as long as we are smart about our implementation. Files should only be
open when necessary and be closed when it is no longer necessary to have them open.
When built in release mode, we also need to pack static assets into some sort of archive that is mountable to reduce
disk space consumption of a program. I am considering encryption for archives, but there likely is not much of a point.
@@ -186,6 +218,10 @@ fennec should be able to use Doxygen and LaTeX externally. Consider including bi
- Spreadsheets & Tables
- ODS
- CSV
- Audio Formats
- MP3
- WAV
- AAC
- Graphics Formats
- Textures
- BMP
@@ -200,6 +236,11 @@ fennec should be able to use Doxygen and LaTeX externally. Consider including bi
- Models
- FBX
- Wavefront OBJ
- Video Formats
- MP4
- AVI
- MPG
- MOV
**TODO LATER**
* Compilation (`fproc/code`)

View File

@@ -65,24 +65,24 @@ fennec Standards:
called `detail`. Helper functions should be documented with C-Style comments, however it is not necessary to provide
Doxygen documentation.
- **DO NOT USE C++ EXCEPTIONS** they will not be supported because they are shit. No, I won't elaborate.[[1]](#f1)
- **DO NOT USE C++ EXCEPTIONS** they will not be supported because they are shit. No, I won't elaborate.<sup>[[1]](#f1)</sup>
* Most behaviours should be type independent. Specifically interactions with the core systems of the engine.
<br><br>
<a id="f1"></a>
[1] Okay, I will elaborate. If we were to use the exception paradigm for all erroneous behaviour, we couldn't
guarantee that the state will not be corrupted when an exception is thrown. The behaviour afterward is
undefined because of this, and we also don't really know when, how, or where that exception will be handled.
The assertion paradigm is better at handling this because you are defining erroneous behaviour in the code and how
it is handled. In a debug build we can immediately halt the program, we don't care about the state afterward, only
beforehand. Now for a release build, this is first and foremost a game engine, so we want to crash as gracefully as
possible, prevent data loss, and get some debug information for it. fennec defines its own `assert` macro to
be used, defining a hook in the private version of the function. This hook is used to clean up any state information
within the engine and may be used to send immediate events to listeners so that outside functionality may decide
how to handle the impending crash. In Debug Mode there is nothing that can be done to stop the crash, as soon as the branch
finishes, `abort()` will be called.
<sup>[1]</sup> Okay, I will elaborate. If we were to use the exception paradigm for all erroneous behaviour, we couldn't
guarantee that the state will not be corrupted when an exception is thrown. The behaviour afterward is
undefined because of this, and we also don't really know when, how, or where that exception will be handled.
The assertion paradigm is better at handling this because you are defining erroneous behaviour in the code and how
it is handled. In a debug build we can immediately halt the program, we don't care about the state afterward, only
beforehand. Now for a release build, this is first and foremost a game engine, so we want to crash as gracefully as
possible, prevent data loss, and get some debug information for it. fennec defines its own `assert` macro to
be used, defining a hook in the private version of the function. This hook is used to clean up any state information
within the engine and may be used to send immediate events to listeners so that outside functionality may decide
how to handle the impending crash. In Debug Mode there is nothing that can be done to stop the crash, as soon
as the branch finishes, `abort()` will be called.
<br>
@@ -199,6 +199,44 @@ information displayed is correct.
<a id="usage"></a>
## Usage
### Licensing
The following statement is not legal advice, nor is it legally binding, and nor does it change the terms of the license.
fennec is licensed under GPLv3. The primary reason for the choice of license is to dissuade corporations from modifying
fennec and using it in a commercial manner. This of course does not bar them from using fennec commercially, however
it will prevent them from being able to make the derivative work proprietary. You are free to use and redistribute
fennec however you wish according to the terms of the license, which does not bar you from commercializing software
based on fennec.
I encourage those who wish to commercialize derivative works crowdfund rather than use a sales model. I also ask
that you kindly support me as a developer, I will set up a Buy Me a Coffee link at some point.
GPLv3 is bound by fair use; here is the clause, 17 U.S. Code § 107:
```
107. Limitations on exclusive rights: Fair use
Notwithstanding the provisions of sections 106 and 106A, the fair use of a copyrighted work, including such use by
reproduction in copies or phonorecords or by any other means specified by that section, for purposes such as criticism,
comment, news reporting, teaching (including multiple copies for classroom use), scholarship, or research, is not an
infringement of copyright. In determining whether the use made of a work in any particular case is a fair use the
factors to be considered shall include—
(1) the purpose and character of the use, including whether such use is of a commercial nature or is for nonprofit
educational purposes;
(2) the nature of the copyrighted work;
(3) the amount and substantiality of the portion used in relation to the copyrighted work as a whole; and
(4) the effect of the use upon the potential market for or value of the copyrighted work.
The fact that a work is unpublished shall not itself bar a finding of fair use if such finding is made upon
consideration of all the above factors.
```
If you have any questions or concerns, please seek legal council. If you believe someone else has violated the terms
of this license, please contact me at [mslockbo@gmail.com](mailto:mslockbo@gmail.com).
<br>
<br>
@@ -207,5 +245,5 @@ information displayed is correct.
There are some principles to keep in mind when contributing to fennec.
1. You must follow the style guide provided by the [GNU Coding Standard](https://www.gnu.org/prep/standards/html_node/Writing-C.html).
2. Any changes must allow all projects to be forward compatible with newer engine verisons.
1. You must follow the [standards provided above](#coding-standards).
2. Any changes must allow all projects to be forward compatible with newer engine versions.

View File

@@ -0,0 +1,31 @@
// =====================================================================================================================
// 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_FPROC_IO_COMMON_H
#define FENNEC_FPROC_IO_COMMON_H
#include <fennec/fproc/strings/string.h>
namespace fennec
{
string getcwd();
}
#endif // FENNEC_FPROC_IO_COMMON_H

View File

@@ -21,7 +21,6 @@
#include <fennec/fproc/strings/cstring.h>
#include <fennec/fproc/strings/string.h>
#include <fennec/fproc/filesystem/path.h>
struct FILE;
@@ -32,10 +31,10 @@ namespace fennec
/// \brief Mode flags for opening a file
enum fmode : uint8_t
{
read = 0b00000001
, write = 0b00000010
, append = 0b00000100
, no_overwrite = 0b00001000
read = 0b00000001
, write = 0b00000010
, append = 0b00000100
, noexists = 0b00001000
};
class file
@@ -50,7 +49,8 @@ public:
/// \param mode the flags for opening the file
file(const cstring& path, fmode mode);
file(const string& path, fmode mode);
file(const path& path, fmode mode);
file(file&& file);
file(const file&) = delete;
@@ -59,7 +59,6 @@ public:
void open(const cstring& filename, fmode mode);
void open(const string& filename, fmode mode);
void open(const path& filename, fmode mode);
void close();
void commit();
@@ -89,6 +88,8 @@ public:
private:
FILE* _handle;
string _path;
fmode _mode;
};
}

View File

@@ -24,6 +24,8 @@
#include <fennec/lang/assert.h>
#include <fennec/math/common.h>
namespace fennec
{

View File

@@ -42,7 +42,7 @@ using string = _string<>;
/// \brief Struct for wrapping c-style strings
///
/// \details behaviour guarantees that the underlying string is null-terminated
template<typename AllocT = allocator<char>>
template<typename AllocT>
struct _string
{
public:
@@ -120,7 +120,6 @@ public:
/// \param i the index to access
/// \returns a reference to the character
constexpr char& operator[](int i) {
assertd(i >= 0 && i < size(), "Array Out of Bounds");
return _str[i];
}
@@ -284,7 +283,7 @@ public:
/// \param str the string to copy
/// \returns a reference to `this`
constexpr string& operator=(const string& str) {
if (str.size() > size()) string::resize(str.size());
if (str.size() > size()) resize(str.size());
fennec::memcpy(_str, str, str.size());
_str[str.size()] = '\0';
return *this;

View File

@@ -65,7 +65,7 @@
using assert_handler = void (*)(const char *, const char *, int , const char *);
extern 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);
// flagged unlikely to optimize branch prediction
#define assert(expression, description) \

View File

@@ -28,6 +28,7 @@
#pragma push_macro("__cplusplus")
#undef __cplusplus
#include <stddef.h>
#include <stdint.h>
#pragma pop_macro("__cplusplus")

View File

@@ -28,7 +28,7 @@ namespace fennec
namespace detail
{
template<typename> struct __make_unsigned : undefined_t {};
template<typename> struct __make_unsigned : type_transform<undefined_t> {};
template<> struct __make_unsigned<char_t> : type_transform<uchar_t> {};
template<> struct __make_unsigned<uchar_t> : type_transform<uchar_t> {};
@@ -43,7 +43,7 @@ template<> struct __make_unsigned<llong_t> : type_transform<ullong_t> {};
template<> struct __make_unsigned<ullong_t> : type_transform<ullong_t> {};
template<typename> struct __make_signed : undefined_t {};
template<typename> struct __make_signed : type_transform<undefined_t> {};
template<> struct __make_signed<char_t> : type_transform<schar_t> {};
template<> struct __make_signed<uchar_t> : type_transform<schar_t> {};

View File

@@ -191,6 +191,14 @@
# define FENNEC_HAS_BUILTIN_IS_FINAL 0
#endif
// Inconsistent with dynamic intrinsics, requires a massive table for static intrinsics
#if __has_builtin(__is_fundamental)
# define FENNEC_HAS_BUILTIN_IS_FUNDAMENTAL 1
# define FENNEC_BUILTIN_IS_FUNDAMENTAL(arg) __is_fundamental(arg)
#else
# define FENNEC_HAS_BUILTIN_IS_FUNDAMENTAL 0
#endif
// Inconsistent without intrinsics
#if __has_builtin(__is_polymorphic)
# define FENNEC_HAS_BUILTIN_IS_POLYMORPHIC 1

View File

@@ -288,6 +288,21 @@ template<typename T> struct is_arithmetic
/// \tparam T type to check
template<typename T> constexpr bool_t is_arithmetic_v = is_arithmetic<T>::value;
// fennec::is_fundamental ==============================================================================================
///
/// \brief check if \p T is a fundamental type, i.e. arithmetic, void, or nullptr_t
/// \tparam T type to check
template<typename T> struct is_fundamental
: bool_constant<is_arithmetic_v<T> || is_void_v<T> || is_null_pointer_v<T>>{};
///
/// \brief shorthand for ```is_fundamental<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_fundamental_v = is_fundamental<T>::value;
// fennec::is_same =====================================================================================================
///
@@ -306,7 +321,7 @@ template<typename T> struct is_same<T, T> : true_type {};
/// \tparam T type to check
template<typename T0, typename T1> constexpr bool_t is_same_v = is_same<T0, T1> {};
// fennec::can_convert =================================================================================================
// fennec::is_convertible ==============================================================================================
///
/// \brief check if type `T0` can be converted `T1`

View File

@@ -203,6 +203,8 @@
#include <fennec/lang/detail/__int.h>
#include <fennec/lang/conditional_types.h>
namespace fennec
{
// Basic Types =========================================================================================================
@@ -253,12 +255,7 @@ namespace fennec
template<typename...> using void_t = void; ///< \brief Void type used for SFINAE
/// @}
}
#include <fennec/lang/conditional_types.h>
namespace fennec
{
// Sized Arithmetic Types ==============================================================================================

View File

@@ -271,6 +271,8 @@
#include <fennec/math/detail/__math.h>
#include <fennec/lang/limits.h>
#include <fennec/math/vector.h>
#if _MSC_VER
@@ -462,7 +464,7 @@ constexpr vector<genType, i...> trunc(const vector<genType, i...>& x) {
/// \param x input value
template<typename genType>
constexpr genType roundEven(genType x) {
static const genType e = std::numeric_limits<genType>::epsilon();
static const genType e = numeric_limits<genType>::epsilon();
int I = static_cast<int>(x);
genType i = static_cast<genType>(I);
genType f = x - i;

View File

@@ -1,4 +1,4 @@
2// =====================================================================================================================
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright (C) 2025 Medusa Slockbower
//
@@ -33,15 +33,22 @@
#define FENNEC_MEMORY_ALLOCATOR_H
#include <fennec/memory/ptr_traits.h>
#include <fennec/memory/new.h>
#include <fennec/lang/conditional_types.h>
#include <fennec/lang/numeric_transforms.h>
#include <fennec/lang/types.h>
#include <fennec/lang/type_traits.h>
#include <fennec/math/ext/constants.h>
#include <fennec/math/common.h>
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wchanges-meaning"
#endif
namespace fennec
{
@@ -177,14 +184,92 @@ public:
}
/// \brief Allocate a block of memory large enough to hold `n` elements of type `T`
constexpr T* allocate(size_t n) {
return ::operator new(n * sizeof(T));
constexpr T* allocate(size_t n) {
return static_cast<T*>(::operator new(n * sizeof(T)));
}
/// \brief Allocate a block of memory large enough to hold `n` elements of type `T`
constexpr T* allocate(size_t n, align_t align) {
return static_cast<T*>(::operator new(n * sizeof(T), align));
}
/// \brief Deallocate a block of memory with type `T`
constexpr void deallocate(T* ptr) {
return ::operator delete(ptr);
}
/// \brief Deallocate a block of memory with type `T`
constexpr void deallocate(T* ptr, align_t align) {
return ::operator delete(ptr, align);
}
};
///
/// \brief Allocator implementation, uses `new` and `delete` operators.
/// \tparam T The data type to allocate
template<typename T>
class allocator<T[]>
{
public:
/// \brief Alias for the data type used for metaprogramming
using value_t = T;
/// \brief Metaprogramming utility to rebind an allocator to a different data type
template<typename R> using rebind = allocator<R>;
/// \brief Default Constructor
constexpr allocator() = default;
/// \brief Default Destructor
constexpr ~allocator() = default;
/// \brief Copy Constructor
constexpr allocator(const allocator&) = default;
/// \brief Copy Assignment
constexpr allocator& operator=(const allocator&) = default;
/// \brief Equality operator
constexpr bool_t operator==(const allocator&) {
return true;
}
/// \brief Inequality operator
constexpr bool_t operator!=(const allocator&) {
return false;
}
/// \brief Equality operator for allocators of same type but with different data type
template<typename U> constexpr bool_t operator==(const allocator<U>&) {
return true;
}
/// \brief Inequality operator for allocators of same type but with different data type
template<typename U> constexpr bool_t operator!=(const allocator<U>&) {
return true;
}
/// \brief Allocate a block of memory large enough to hold `n` elements of type `T`
constexpr T* allocate(size_t n) {
return static_cast<T*>(::operator new[](n * sizeof(T)));
}
/// \brief Allocate a block of memory large enough to hold `n` elements of type `T`
constexpr T* allocate(size_t n, align_t align) {
return static_cast<T*>(::operator new[](n * sizeof(T), align));
}
/// \brief Deallocate a block of memory with type `T`
constexpr void deallocate(T* ptr) {
return ::operator delete[](ptr);
}
/// \brief Deallocate a block of memory with type `T`
constexpr void deallocate(T* ptr, align_t align) {
return ::operator delete[](ptr, align);
}
};
@@ -211,6 +296,9 @@ public:
/// \brief diff type definition for ptr_traits
using diff_t = ptrdiff_t;
// Cosntructors ========================================================================================================
///
/// \brief Default Constructor, initializes internal data to `null` and the capacity to `0`
constexpr allocation() noexcept
@@ -235,6 +323,24 @@ public:
fennec::memcpy(_data, data, n);
}
///
/// \brief Sized Constructor, initializes the allocation with a block of size `n * sizeof(T)` bytes
/// \param n The number of elements of type `T` to allocate for
constexpr allocation(size_t n, align_t align) noexcept
: _data(nullptr), _capacity(0), _alignment(zero<align_t>()) {
allocate(n, align);
}
///
/// \brief Buffer Copy Constructor, initializes the allocation with a block of size `n * sizeof(T)` bytes.
/// Then, the contents of data are copied into the allocation.
/// \param data the buffer to copy
/// \param n the number of elements
constexpr allocation(const T* data, size_t n, align_t align)
: allocation(n, align) {
fennec::memcpy(_data, data, n);
}
///
/// \brief Allocator Constructor
/// \param alloc The allocation object to copy.
@@ -268,6 +374,30 @@ public:
fennec::memcpy(_data, data, n);
}
///
/// \brief Sized Allocator Constructor
/// \param n The number of elements of type `T` to allocate for
/// \param alloc The allocation object to copy.
///
/// \details This constructor should be used when the type `AllocT` needs internal data.
constexpr allocation(size_t n, align_t align, const alloc_t& alloc) noexcept
: _alloc(alloc), _data(nullptr), _capacity(0), _alignment(zero<align_t>()) {
allocate(n, align);
}
///
/// \brief Buffer Copy Allocator Constructor, initializes the allocation with a block of size `n * sizeof(T)` bytes.
/// Then, the contents of data are copied into the allocation.
/// \param data the buffer to copy
/// \param n the number of elements
/// \param alloc The allocation object to copy.
///
/// \details This constructor should be used when the type `AllocT` needs internal data.
constexpr allocation(const T* data, size_t n, align_t align, const alloc_t& alloc)
: allocation(n, align, alloc) {
fennec::memcpy(_data, data, n);
}
///
/// \brief Copy Constructor, creates an allocation of equal size and performs a byte-wise copy
/// \param alloc The allocation to copy
@@ -292,6 +422,9 @@ public:
if (_data) _alloc.deallocate(_data);
}
// Assignment ==========================================================================================================
///
/// \brief Copy Assignment Operator
/// \param alloc the allocation to copy
@@ -319,37 +452,45 @@ public:
return *this;
}
// Allocation and Deallocation =========================================================================================
///
/// \brief Allocate a block of memory for the allocation.
/// If there is already an allocated block of memory, the previous allocation is released.
/// \param n The number of elements of type `T` to allocate for
constexpr void allocate(size_t n) noexcept {
if (_data) {
_alloc.deallocate(_data);
}
constexpr void allocate(size_t n, align_t align = zero<align_t>()) noexcept {
deallocate();
_data = _alloc.allocate(_capacity = n);
if (_alignment != zero<align_t>()) {
_data = _alloc.allocate(_capacity = n, _alignment = align);
} else {
_data = _alloc.allocate(_capacity = n);
}
}
///
/// \brief Release the block of memory.
constexpr void release() noexcept
{
constexpr void deallocate() noexcept {
if (_data) {
_alloc.deallocate(_data);
if (_alignment != zero<align_t>()) {
_alloc.deallocate(_data, _alignment);
} else {
_alloc.deallocate(_data);
}
}
_data = nullptr;
_capacity = 0;
_alignment = zero<align_t>();
}
///
/// \brief Reallocate the block with a new size.
/// Contents are copied to the new allocation.
constexpr void reallocate(size_t n) noexcept
{
constexpr void reallocate(size_t n, align_t align = zero<align_t>()) noexcept {
if (_data == nullptr) {
return _alloc.allocate(_capacity = n);
allocate(n, align);
}
value_t* old = _data;
@@ -359,6 +500,27 @@ public:
_capacity = n;
}
// Access ==============================================================================================================
constexpr value_t& operator[](size_t i) {
assertd(i < size(), "Array Out of Bounds");
return _data[i];
}
constexpr const value_t operator[](size_t i) const requires requires { is_fundamental_v<value_t> == true; } {
assertd(i < size(), "Array Out of Bounds");
return _data[i];
}
constexpr const value_t& operator[](size_t i) const requires requires { is_fundamental_v<value_t> == false; } {
assertd(i < size(), "Array Out of Bounds");
return _data[i];
}
// Modification ========================================================================================================
///
/// \brief Clear the block of memory, setting all bytes to 0.
constexpr void clear() noexcept {
@@ -387,11 +549,16 @@ public:
}
private:
alloc_t _alloc; // Allocator object
value_t* _data; // Handle for the memory block
size_t _capacity; // Capacity of the memory block in elements.
alloc_t _alloc; // Allocator object
value_t* _data; // Handle for the memory block
size_t _capacity; // Capacity of the memory block in elements.
align_t _alignment; // Alignment information
};
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
}
#endif // FENNEC_MEMORY_ALLOCATOR_H

View File

@@ -36,7 +36,7 @@ struct __ptr_get_element : first_element<ClassT> { }; // Default case, return th
// overload for types that have a member `ClassT::element_t`
template<typename ClassT> requires requires { typename ClassT::element_t; }
struct __ptr_get_element { using type = typename ClassT::element_t; };
struct __ptr_get_element<ClassT, ClassT> { using type = typename ClassT::element_t; };
// helper for generating `pointer_to`
template<typename PtrT, typename ElemT, bool_t = is_void_v<ElemT>>

View File

@@ -19,10 +19,6 @@
#ifndef FENNEC_MEMORY_DETAIL_MEMORY_H
#define FENNEC_MEMORY_DETAIL_MEMORY_H
#include <fennec/lang/types.h>
// deprecated, switched to ISO C implementation
// see https://git.mslockbo.org/mslockbo/fennec/src/commit/0eeb7ae3cff9d78e98dc5d9fc09bcb98b10986b9 for previous
// implementation
@@ -39,6 +35,7 @@
#pragma push_macro("__cplusplus")
#undef __cplusplus
#include <string.h>
#include <wchar.h>
#pragma pop_macro("__cplusplus")
#if __GNUC__

View File

@@ -49,6 +49,10 @@ struct nothrow_t
explicit nothrow_t() noexcept { }
};
///
/// \returns the page size for the current environment
size_t pagesize();
template<typename TypeT> void construct(TypeT* ptr) {
ptr->TypeT();
}
@@ -71,4 +75,31 @@ template<typename TypeT> void destruct(TypeT* ptr) {
}
void* operator new (fennec::size_t size);
void* operator new[](fennec::size_t size);
void* operator new (fennec::size_t size, const fennec::nothrow_t&);
void* operator new[](fennec::size_t size, const fennec::nothrow_t&);
void* operator new (fennec::size_t size, fennec::align_t align);
void* operator new[](fennec::size_t size, fennec::align_t align);
void* operator new (fennec::size_t size, fennec::align_t align, const fennec::nothrow_t&);
void* operator new[](fennec::size_t size, fennec::align_t align, const fennec::nothrow_t&);
void operator delete (void* ptr) noexcept;
void operator delete[](void* ptr) noexcept;
void operator delete (void* ptr, fennec::size_t) noexcept;
void operator delete[](void* ptr, fennec::size_t) noexcept;
void operator delete (void* ptr, const fennec::nothrow_t&) noexcept;
void operator delete[](void* ptr, const fennec::nothrow_t&) noexcept;
void operator delete (void* ptr, fennec::size_t, const fennec::nothrow_t&) noexcept;
void operator delete[](void* ptr, fennec::size_t, const fennec::nothrow_t&) noexcept;
void operator delete (void* ptr, fennec::align_t) noexcept;
void operator delete[](void* ptr, fennec::align_t) noexcept;
void operator delete (void* ptr, fennec::size_t, fennec::align_t) noexcept;
void operator delete[](void* ptr, fennec::size_t, fennec::align_t) noexcept;
void operator delete (void* ptr, fennec::align_t, const fennec::nothrow_t&) noexcept;
void operator delete[](void* ptr, fennec::align_t, const fennec::nothrow_t&) noexcept;
#endif // FENNEC_MEMORY_NEW_H

View File

@@ -0,0 +1,56 @@
// =====================================================================================================================
// 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/fproc/io/common.h>
#ifdef _WIN32
namespace fennec
{
string getcwd() {
char cstr[MAX_PATH];
if (GetCurrentDirectory(sizeof(str), str) == 0) {
return string("");
}
string result(cstr);
return result;
}
}
#else
#include <unistd.h>
#include <linux/limits.h>
namespace fennec
{
string getcwd() {
char cstr[PATH_MAX];
if (::getcwd(cstr, sizeof(cstr)) == NULL) {
return string("");
}
string result(cstr);
return result;
}
#endif
}

View File

@@ -14,4 +14,4 @@
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
// =====================================================================================================================

View File

@@ -20,7 +20,7 @@
using assert_handler = void (*)(const char *, const char *, int , const char *);
extern void __assert_callback(const char* expression, const char* file, int line, const char* function, const char* description);
void __assert_callback(const char* expression, const char* file, int line, const char* function, const char* description);
void __assert_impl(const char* expression, const char* file, int line, const char* function, const char* description)
{

View File

@@ -28,16 +28,14 @@
#else
// Allocation functions
inline void* operator new (fennec::size_t size) { return ::malloc(size); }
inline void* operator new[](fennec::size_t size) { return ::malloc(size); }
inline void* operator new (fennec::size_t size, const fennec::nothrow_t&) { return ::malloc(size); }
inline void* operator new[](fennec::size_t size, const fennec::nothrow_t&) { return ::malloc(size); }
// Aligned allocation & deallocation functions
// Windows does not define ISO C aligned allocation functions
#ifdef _WIN32
inline void operator delete (void* ptr) noexcept { _aligned_free(ptr); }
inline void operator delete[](void* ptr) noexcept { _aligned_free(ptr); }
inline void operator delete (void* ptr, fennec::align_t) noexcept { ::_aligned_free(ptr); }
inline void operator delete[](void* ptr, fennec::align_t) noexcept { ::_aligned_free(ptr); }
inline void operator delete (void* ptr, fennec::size_t, fennec::align_t) noexcept { ::_aligned_free(ptr); }
inline void operator delete[](void* ptr, fennec::size_t, fennec::align_t) noexcept { ::_aligned_free(ptr); }
inline void operator delete (void* ptr, fennec::align_t, const fennec::nothrow_t&) noexcept { _aligned_free(ptr); }
inline void operator delete[](void* ptr, fennec::align_t, const fennec::nothrow_t&) noexcept { _aligned_free(ptr); }
@@ -45,9 +43,15 @@ inline void* operator new (fennec::size_t size, fennec::align_t align)
inline void* operator new[](fennec::size_t size, fennec::align_t align) { return _aligned_malloc(static_cast<size_t>(align), size); }
inline void* operator new (fennec::size_t size, fennec::align_t align, const fennec::nothrow_t&) { return _aligned_malloc(static_cast<size_t>(align), size); }
inline void* operator new[](fennec::size_t size, fennec::align_t align, const fennec::nothrow_t&) { return _aligned_malloc(static_cast<size_t>(align), size); }
#else
inline void operator delete (void* ptr) noexcept { ::free(ptr); }
inline void operator delete[](void* ptr) noexcept { ::free(ptr); }
inline void operator delete (void* ptr, fennec::align_t) noexcept { ::free(ptr); }
inline void operator delete[](void* ptr, fennec::align_t) noexcept { ::free(ptr); }
inline void operator delete (void* ptr, fennec::size_t, fennec::align_t) noexcept { ::free(ptr); }
inline void operator delete[](void* ptr, fennec::size_t, fennec::align_t) noexcept { ::free(ptr); }
inline void operator delete (void* ptr, fennec::align_t, const fennec::nothrow_t&) noexcept { ::free(ptr); }
inline void operator delete[](void* ptr, fennec::align_t, const fennec::nothrow_t&) noexcept { ::free(ptr); }
@@ -55,22 +59,54 @@ inline void* operator new (fennec::size_t size, fennec::align_t align)
inline void* operator new[](fennec::size_t size, fennec::align_t align) { return ::aligned_alloc(static_cast<fennec::size_t>(align), size); }
inline void* operator new (fennec::size_t size, fennec::align_t align, const fennec::nothrow_t&) { return ::aligned_alloc(static_cast<fennec::size_t>(align), size); }
inline void* operator new[](fennec::size_t size, fennec::align_t align, const fennec::nothrow_t&) { return ::aligned_alloc(static_cast<fennec::size_t>(align), size); }
#endif
// Aligned deallocation functions
inline void operator delete (void* ptr, fennec::align_t) noexcept { ::free(ptr); }
inline void operator delete[](void* ptr, fennec::align_t) noexcept { ::free(ptr); }
// Allocation functions
inline void* operator new (fennec::size_t size) { return ::malloc(size); }
inline void* operator new[](fennec::size_t size) { return ::malloc(size); }
inline void* operator new (fennec::size_t size, const fennec::nothrow_t&) { return ::malloc(size); }
inline void* operator new[](fennec::size_t size, const fennec::nothrow_t&) { return ::malloc(size); }
// Sized deallocation functions
inline void operator delete (void* ptr, fennec::size_t) noexcept { ::free(ptr); }
inline void operator delete[](void* ptr, fennec::size_t) noexcept { ::free(ptr); }
inline void operator delete (void* ptr, fennec::size_t, fennec::align_t) noexcept { ::free(ptr); }
inline void operator delete[](void* ptr, fennec::size_t, fennec::align_t) noexcept { ::free(ptr); }
// Non-throwing deallocation functions
// Deallocation Functions
inline void operator delete (void* ptr, fennec::size_t) noexcept { ::free(ptr); }
inline void operator delete[](void* ptr, fennec::size_t) noexcept { ::free(ptr); }
inline void operator delete (void* ptr, const fennec::nothrow_t&) noexcept { ::free(ptr); }
inline void operator delete[](void* ptr, const fennec::nothrow_t&) noexcept { ::free(ptr); }
inline void operator delete (void* ptr, fennec::size_t, const fennec::nothrow_t&) noexcept { ::free(ptr); }
inline void operator delete[](void* ptr, fennec::size_t, const fennec::nothrow_t&) noexcept { ::free(ptr); }
#endif
// Platform specific code
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
namespace fennec
{
size_T pagesize() {
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
return sysInfo.dwPageSize;
}
}
#else
#include <unistd.h>
namespace fennec
{
size_t pagesize() {
return sysconf(_SC_PAGESIZE);
}
}
#endif
#endif