diff --git a/CMakeLists.txt b/CMakeLists.txt
index 85123f7..37f6177 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -121,6 +121,9 @@ add_library(fennec STATIC
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
)
# add metaprogramming templates as a dependency and also force documentation to be generated when fennec is compiled
@@ -139,7 +142,7 @@ endif()
target_compile_options(fennec PUBLIC "-mavx" "-mavx2" "-mavx512f") # SIMD Instructions, automatic vectorization will occur
-target_link_options(fennec PRIVATE "-nostdlib -nodefaultlibs -fno-exceptions") # Do not compile base fennec library with c++ stdlib
+target_link_options(fennec PRIVATE "-nostdlib -nodefaultlibs -fno-exceptions -fdiagnostics-all-candidates") # Do not compile base fennec library with c++ stdlib
# fennec does not use the C++ stdlib because it is bloated, difficult to read, and implementation defined.
# This implementation is designed to be as readable as possible, and expose information that would otherwise be obfuscated
diff --git a/include/fennec/fproc/io/file.h b/include/fennec/fproc/io/file.h
new file mode 100644
index 0000000..2d28d9e
--- /dev/null
+++ b/include/fennec/fproc/io/file.h
@@ -0,0 +1,46 @@
+// =====================================================================================================================
+// 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 .
+// =====================================================================================================================
+
+#ifndef FENNEC_FPROC_IO_FILE_H
+#define FENNEC_FPROC_IO_FILE_H
+
+#include
+
+struct FILE;
+
+namespace fennec
+{
+
+class file
+{
+public:
+ file();
+ ~file();
+
+ file(const file&) = delete;
+
+ void open(const cstring& filename, const cstring& mode);
+ void close();
+
+private:
+ FILE* _handle;
+};
+
+}
+
+#endif // FENNEC_FPROC_IO_FILE_H
diff --git a/include/fennec/fproc/strings/cstring.h b/include/fennec/fproc/strings/cstring.h
new file mode 100644
index 0000000..1a03b2e
--- /dev/null
+++ b/include/fennec/fproc/strings/cstring.h
@@ -0,0 +1,222 @@
+// =====================================================================================================================
+// 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 .
+// =====================================================================================================================
+
+#ifndef FENNEC_FPROC_STRINGS_CSTRING_H
+#define FENNEC_FPROC_STRINGS_CSTRING_H
+
+#include
+#include
+
+#include
+
+namespace fennec
+{
+
+// TODO: Document
+
+using ::isalnum;
+using ::isalpha;
+using ::islower;
+using ::isupper;
+using ::isdigit;
+using ::isxdigit;
+using ::iscntrl;
+using ::isgraph;
+using ::isspace;
+using ::isblank;
+using ::isprint;
+using ::ispunct;
+
+using ::tolower;
+using ::toupper;
+
+///
+/// \brief This struct wraps c-style strings
+///
+/// \details Requires that the string is null-terminated.
+/// Prevents const qualified memory blocks from being manipulated.
+/// This struct should be used when fennec::string would make unnecessary dynamic buffers.
+struct cstring
+{
+public:
+
+// Constructors ========================================================================================================
+
+ ///
+ /// \brief Default Constructor, initializes with nullptr
+ constexpr cstring()
+ : _str(nullptr), _len(0), _const(true)
+ { }
+
+ ///
+ /// \brief Buffer Constructor, wraps the provided C-Style string
+ /// \param str the buffer to wrap
+ /// \param n the number of characters in the buffer plus the null terminator
+ constexpr cstring(char* str, size_t n)
+ : _str(str), _len(n - 1), _const(false)
+ { assert(_str[n - 1] == '\0', "Invalid NTBS."); }
+
+ ///
+ /// \brief Buffer Constructor, wraps the provided C-Style string
+ /// \param str the buffer to wrap
+ /// \tparam n the number of characters in the buffer plus the null terminator
+ template
+ constexpr cstring(char(&str)[n])
+ : _str(str), _len(n - 1), _const(false)
+ { assert(_str[n - 1] == '\0', "Invalid NTBS."); }
+
+ ///
+ /// \brief Const Buffer Constructor, wraps the provided C-Style string
+ /// \param str the buffer to wrap
+ /// \param n the number of characters in the buffer plus the null terminator
+ constexpr cstring(const char* str, size_t n)
+ : _cstr(str), _len(n - 1), _const(true)
+ { assert(_cstr[n - 1] == '\0', "Invalid NTBS."); }
+
+ ///
+ /// \brief Buffer Constructor, wraps the provided C-Style string
+ /// \param str the buffer to wrap
+ /// \tparam n the number of characters in the buffer plus the null terminator
+ template
+ constexpr cstring(const char(&str)[n])
+ : _cstr(str), _len(n - 1), _const(true)
+ { assert(_cstr[n - 1] == '\0', "Invalid NTBS."); }
+
+ ///
+ /// \brief Move Constructor
+ /// \param str object to move
+ constexpr cstring(cstring&& str)
+ : _cstr(str._cstr), _len(str._len)
+ { }
+
+ constexpr cstring(const cstring&) = delete;
+ constexpr ~cstring() = default;
+
+ template
+ constexpr cstring& operator=(char(&str)[n]) {
+ assert(_str[n - 1] == '\0', "Invalid NTBS.");
+ _str = str; _len = n - 1; _const = false;
+ return *this;
+ }
+
+ template
+ constexpr cstring& operator=(const char(&str)[n]) {
+ assert(str[n - 1] == '\0', "Invalid NTBS.");
+ _cstr = str; _len = n - 1; _const = true;
+ return *this;
+ }
+
+
+// Properties ==========================================================================================================
+
+ constexpr size_t size() const { return _len; }
+
+
+// Access ==============================================================================================================
+
+ ///
+ /// \brief Array Access Operator
+ /// \param i the index to access
+ /// \returns a reference to the character
+ constexpr char& operator[](size_t i) {
+ assert(i < size(), "Array Out of Bounds");
+ assert(not _const, "Attempted to Access Const-Qualified Memory as Non-Const");
+ return _str[i];
+ }
+
+ ///
+ /// \brief Const-Array Access Operator
+ /// \param i the index to access
+ /// \returns a copy of the character
+ constexpr char operator[](size_t i) const {
+ assert(i < size(), "Array Out of Bounds");
+ return _cstr[i];
+ }
+
+ ///
+ /// \brief Dereference Operator
+ /// \returns A const qualified pointer to the underlying allocation
+ constexpr const char* operator*() const { return _cstr; }
+
+ ///
+ /// \brief Implicit Dereference Cast
+ constexpr operator const char*() const { return _cstr; }
+
+
+// Examination =========================================================================================================
+
+ ///
+ /// \returns The length of the string to the first null-terminator
+ constexpr size_t length() const
+ { return find('\0'); }
+
+ ///
+ /// \brief String Comparison
+ /// \param ostr the string to compare against
+ /// \returns Zero if both strings are equal, otherwise a negative value if lhs appears before rhs according to the
+ /// current locale, otherwise a positive value.
+ constexpr int compare(const cstring& str) const
+ { return ::strcoll(_cstr, str); }
+
+ constexpr bool operator==(const cstring& str) const
+ { return compare(str) == 0; }
+
+ ///
+ /// \brief Finds the index of the first occurrence of `x` in the string
+ /// \param x the character to find
+ /// \returns The index of `x` if it occurs in the string, otherwise returns `size()`
+ constexpr size_t find(char x) const
+ {
+ const char* loc = ::strchr(_cstr, x);
+ return loc ? loc - _cstr : size();
+ }
+
+ ///
+ /// \brief Finds the index of the first occurrence of `str` in the string.
+ /// \param str the string to find
+ /// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
+ constexpr size_t find(const cstring& str) const
+ {
+ const char* loc = ::strstr(_cstr, str);
+ return loc ? loc - _cstr : size();
+ }
+
+ ///
+ /// \brief Finds the index of the last occurrence of `x` in the string.
+ /// \param x the string to find
+ /// \returns The index of `x` if it occurs in the string, otherwise returns `size()`
+ constexpr size_t rfind(char x) const
+ {
+ const char* loc = ::strrchr(_cstr, x);
+ return loc ? loc - _cstr : size();
+ }
+
+ // TODO: constexpr size_t rfind(const string& str) const;
+
+private:
+ union {
+ char* _str;
+ const char* _cstr;
+ };
+ size_t _len;
+ bool _const;
+};
+
+}
+
+#endif // FENNEC_FPROC_STRINGS_CSTRING_H
diff --git a/include/fennec/fproc/strings/detail/__ctype.h b/include/fennec/fproc/strings/detail/__ctype.h
index dadcbc8..624bd91 100644
--- a/include/fennec/fproc/strings/detail/__ctype.h
+++ b/include/fennec/fproc/strings/detail/__ctype.h
@@ -22,8 +22,6 @@
#if _MSC_VER
#pragma warning(push)
#pragma warning(disable:4117)
-
-#define __PTRDIFF_TYPE__ ptrdiff_t
#endif
#pragma push_macro("__cplusplus")
diff --git a/include/fennec/fproc/strings/detail/__locale.h b/include/fennec/fproc/strings/detail/__locale.h
new file mode 100644
index 0000000..3d1d973
--- /dev/null
+++ b/include/fennec/fproc/strings/detail/__locale.h
@@ -0,0 +1,36 @@
+// =====================================================================================================================
+// 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 .
+// =====================================================================================================================
+
+#ifndef FENNEC_FPROC_STRINGS_DETAIL_CTYPE_H
+#define FENNEC_FPROC_STRINGS_DETAIL_CTYPE_H
+
+#if _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4117)
+#endif
+
+#pragma push_macro("__cplusplus")
+#undef __cplusplus
+#include
+#pragma pop_macro("__cplusplus")
+
+#if _MSC_VER
+#pragma warning(pop)
+#endif
+
+#endif // FENNEC_FPROC_STRINGS_DETAIL_CTYPE_H
diff --git a/include/fennec/fproc/strings/locale.h b/include/fennec/fproc/strings/locale.h
new file mode 100644
index 0000000..2a0b43b
--- /dev/null
+++ b/include/fennec/fproc/strings/locale.h
@@ -0,0 +1,44 @@
+// =====================================================================================================================
+// 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 .
+// =====================================================================================================================
+
+#ifndef FENNEC_FPROC_STRINGS_LOCALE_H
+#define FENNEC_FPROC_STRINGS_LOCALE_H
+
+#include
+
+namespace fennec
+{
+
+enum locale : int
+{
+ lc_all = LC_ALL
+, lc_collate = LC_COLLATE
+, lc_ctype = LC_CTYPE
+, lc_monetary = LC_MONETARY
+, lc_numeric = LC_NUMERIC
+, lc_time = LC_TIME
+};
+
+using ::lconv;
+
+using ::setlocale;
+using ::localeconv;
+
+}
+
+#endif // FENNEC_FPROC_STRINGS_LOCALE_H
diff --git a/include/fennec/fproc/strings/string.h b/include/fennec/fproc/strings/string.h
index a85923a..e2e8147 100644
--- a/include/fennec/fproc/strings/string.h
+++ b/include/fennec/fproc/strings/string.h
@@ -19,6 +19,7 @@
#ifndef FENNEC_FPROC_STRINGS_STRING_H
#define FENNEC_FPROC_STRINGS_STRING_H
+#include
#include
#include
@@ -28,35 +29,19 @@
namespace fennec
{
-// TODO: Document
-
-using ::isalnum;
-using ::isalpha;
-using ::islower;
-using ::isupper;
-using ::isdigit;
-using ::isxdigit;
-using ::iscntrl;
-using ::isgraph;
-using ::isspace;
-using ::isblank;
-using ::isprint;
-using ::ispunct;
-
-using ::tolower;
-using ::toupper;
-
///
/// \brief Struct for wrapping c-style strings
///
-/// \details fennec will use this class over `const char*` for memory safety.
-/// behaviour guarantees that the underlying string is null-terminated
+/// \details behaviour guarantees that the underlying string is null-terminated
template>
struct string
{
public:
using alloc_t = allocation;
+
+// Constructors ========================================================================================================
+
///
/// \brief Default Constructor, initializes empty string
constexpr string()
@@ -89,22 +74,9 @@ public:
///
/// \details adds additional character for null termination. Ignores whether str is null-terminated.
/// This constructor makes the assumption that `len` is the intended number of characters.
- constexpr string(const char* str, size_t len)
- : _str(str, len + 1)
- { _str[len] = '\0'; }
-
- ///
- /// \brief Array Copy Constructor
- /// \tparam N the number of characters
- /// \param str the array to copy
- ///
- /// \details if str is not null-terminated, adds additional character for null-termination.
- template
- constexpr string(const char str[N])
- {
- if (str[N - 1] == '\0') string(str, N - 1);
- else string(str, N);
- }
+ constexpr string(const cstring& str)
+ : _str(str, str.size() + 1)
+ { _str[str.size()] = '\0'; }
///
/// \brief String Copy Constructor
@@ -155,7 +127,7 @@ public:
///
/// \brief Implicit Dereference Cast
- constexpr operator const char*() const { return _str; }
+ constexpr operator const char*() const { return _str; }
// Examination =========================================================================================================
@@ -193,6 +165,16 @@ public:
return loc ? loc - _str : size();
}
+ ///
+ /// \brief Finds the index of the first occurrence of `str` in the string.
+ /// \param str the string to find
+ /// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
+ constexpr size_t find(const cstring& str) const
+ {
+ const char* loc = ::strstr(_str, str);
+ return loc ? loc - _str : size();
+ }
+
///
/// \brief Finds the index of the last occurrence of `x` in the string.
/// \param x the string to find
@@ -271,6 +253,14 @@ public:
return res;
}
+ constexpr string operator+(const cstring& str)
+ {
+ string res(size() + str.size()); // Make a new string with the size of this + str
+ fennec::memcpy(res, _str, size()); // Copy the contents of this
+ fennec::memcpy(&res[size()], str, str.size()); // Append the contents of str
+ return res;
+ }
+
constexpr string& operator+=(char c)
{
size_t x = size();
@@ -287,6 +277,14 @@ public:
return *this;
}
+ constexpr string& operator+=(const cstring& str)
+ {
+ size_t x = size();
+ resize(x + str.size());
+ fennec::memcpy(&_str[x], str, str.size());
+ return *this;
+ }
+
private:
alloc_t _str;
};
diff --git a/include/fennec/lang/detail/__type_traits.h b/include/fennec/lang/detail/__type_traits.h
index 0cef2fb..1d731f8 100644
--- a/include/fennec/lang/detail/__type_traits.h
+++ b/include/fennec/lang/detail/__type_traits.h
@@ -35,6 +35,9 @@ template<> struct __is_void : true_type {};
template struct __is_bool : false_type {};
template<> struct __is_bool : true_type {};
+template struct __is_null_pointer : false_type {};
+template<> struct __is_null_pointer : true_type {};
+
// Provides definitions for all builtin int types
template struct __is_integral : false_type {};
template<> struct __is_integral : true_type {};
diff --git a/include/fennec/lang/intrinsics.h b/include/fennec/lang/intrinsics.h
index ce2d25d..9039f6e 100644
--- a/include/fennec/lang/intrinsics.h
+++ b/include/fennec/lang/intrinsics.h
@@ -126,6 +126,22 @@
# define FENNEC_HAS_BUILTIN_IS_ABSTRACT 0
#endif
+// Inconsistent without intrinsics
+#if __has_builtin(__is_array)
+# define FENNEC_HAS_BUILTIN_IS_ARRAY 1
+# define FENNEC_BUILTIN_IS_ARRAY(arg) __is_array(arg)
+#else
+# define FENNEC_HAS_BUILTIN_IS_ARRAY
+#endif
+
+// Inconsistent without intrinsics
+#if __has_builtin(__is_class)
+# define FENNEC_HAS_BUILTIN_IS_CLASS 1
+# define FENNEC_BUILTIN_IS_CLASS(arg) __is_class(arg)
+#else
+# define FENNEC_HAS_BUILTIN_IS_CLASS
+#endif
+
// Difficult and Inconsistent without intrinsics
#if __has_builtin(__is_constructible)
# define FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE 1
@@ -159,6 +175,22 @@
#endif
#endif
+// Inconsistent without intrinsics.
+#if __has_builtin(__is_enum)
+# define FENNEC_HAS_BUILTIN_IS_ENUM 1
+# define FENNEC_BUILTIN_IS_ENUM(arg) __is_enum(arg)
+#else
+# define FENNEC_HAS_BUILTIN_IS_ENUM 0
+#endif
+
+// Inconsistent without intrinsics
+#if __has_builtin(__is_final)
+# define FENNEC_HAS_BUILTIN_IS_FINAL 1
+# define FENNEC_BUILTIN_IS_FINAL(arg) __is_final(arg)
+#else
+# define FENNEC_HAS_BUILTIN_IS_FINAL 0
+#endif
+
// Inconsistent without intrinsics
#if __has_builtin(__is_polymorphic)
# define FENNEC_HAS_BUILTIN_IS_POLYMORPHIC 1
diff --git a/include/fennec/lang/type_traits.h b/include/fennec/lang/type_traits.h
index 351b000..a0190d1 100644
--- a/include/fennec/lang/type_traits.h
+++ b/include/fennec/lang/type_traits.h
@@ -148,6 +148,74 @@ template constexpr bool_t is_bool_v
+// fennec::is_null_pointer =============================================================================================
+
+///
+/// \brief check if \p T is of type nullptr_t
+///
+/// \details Stores a boolean value in `is_null_pointer::value`, representing whether the provided type is of base type nullptr_t.
+/// \tparam T type to check
+template struct is_null_pointer
+ : detail::__is_null_pointer>{};
+
+///
+/// \brief shorthand for ```is_null_pointer::value```
+/// \tparam T type to check
+template constexpr bool_t is_null_pointer_v
+ = is_null_pointer::value;
+
+
+
+// fennec::is_array ====================================================================================================
+
+#if FENNEC_HAS_BUILTIN_IS_ARRAY
+
+///
+/// \brief check if \p T is of an array type
+/// \tparam T type to check
+template struct is_array
+ : bool_constant {};
+
+#else
+
+///
+/// \brief check if \p T is of an array type
+/// \tparam T type to check
+template struct is_array
+ : false_type {};
+
+// overload for a sized array type
+template struct is_array
+ : true_type {};
+
+// overload for a generic array type
+template struct is_array
+ : true_type {};
+
+#endif
+
+///
+/// \brief shorthand for ```is_array::value```
+/// \tparam T type to check
+template constexpr bool_t is_array_v
+ = is_array::value;
+
+// fennec::is_class ====================================================================================================
+
+///
+/// \brief check if \p T is a class
+/// \tparam T type to check
+template struct is_class
+ : bool_constant {};
+
+///
+/// \brief check if \p T is a class
+/// \tparam T type to check
+template constexpr size_t is_class_v
+ = is_class::value;
+
+
+
// Integral Types ======================================================================================================
///
diff --git a/source/lang/assert.cpp b/source/lang/assert.cpp
index 12ed477..bfd33b2 100644
--- a/source/lang/assert.cpp
+++ b/source/lang/assert.cpp
@@ -27,6 +27,7 @@ void __assert_impl(const char* expression, const char* file, int line, const cha
__assert_callback(expression, file, line, function, description);
#ifndef NDEBUG
+
::abort();
#endif
}
\ No newline at end of file
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 75ea123..c367baf 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -19,6 +19,9 @@ add_executable(fennec-test main.cpp
tests/math/test_exponential.h
tests/math/test_relational.h
tests/math/test_trigonometric.h
+ tests/fproc/test_strings.h
+ tests/fproc/strings/test_cstring.h
+ tests/test_fproc.h
)
target_link_libraries(fennec-test PRIVATE
diff --git a/test/main.cpp b/test/main.cpp
index 52cc0e8..16f4308 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -23,6 +23,7 @@
#include "tests/test_memory.h"
#include "test.h"
+#include "tests/test_fproc.h"
int main(int, char **)
@@ -41,5 +42,10 @@ int main(int, char **)
fennec::test::fennec_test_math();
fennec_test_spacer(3);
+ fennec_test_header("format processing library");
+ fennec_test_spacer(2);
+ fennec::test::fennec_test_fproc();
+ fennec_test_spacer(3);
+
return 0;
}
diff --git a/test/test.h b/test/test.h
index 8b8f750..d8fb8e6 100644
--- a/test/test.h
+++ b/test/test.h
@@ -57,7 +57,7 @@ inline std::ostream& operator<<(std::ostream& os, const matrix
-inline void __fennec_test_run(const std::string& expression, const ResultT result, const ResultT expected)
+inline void __fennec_test_run(const std::string& expression, const ResultT& result, const ResultT& expected)
{
// Print out the expression as a string and the resulting value
std::cout << std::boolalpha;
diff --git a/test/tests/fproc/strings/test_cstring.h b/test/tests/fproc/strings/test_cstring.h
new file mode 100644
index 0000000..1e784e9
--- /dev/null
+++ b/test/tests/fproc/strings/test_cstring.h
@@ -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 .
+// =====================================================================================================================
+
+#ifndef FENNEC_TEST_FPROC_STRINGS_CSTRING_H
+#define FENNEC_TEST_FPROC_STRINGS_CSTRING_H
+
+#include
+
+namespace fennec
+{
+
+namespace test
+{
+
+static char test_string[] = "Hello World!";
+static const char test_string_const[] = "Hello World!";
+
+inline void fennec_test_fproc_strings_cstring()
+{
+ cstring str = test_string;
+ const cstring cstr = test_string_const;
+
+ fennec_test_run(str, cstr);
+ fennec_test_run(cstr, str);
+
+ fennec_test_spacer(1);
+
+ fennec_test_run(str.length(), size_t(12));
+ fennec_test_run(str.compare(cstr), 0);
+ fennec_test_run(str.find('W'), size_t(6));
+ fennec_test_run(str.find("World"), size_t(6));
+ fennec_test_run(str.rfind('o'), size_t(7));
+
+ fennec_test_spacer(2);
+
+}
+
+}
+
+}
+
+#endif // FENNEC_TEST_FPROC_STRINGS_CSTRING_H
diff --git a/test/tests/fproc/test_strings.h b/test/tests/fproc/test_strings.h
new file mode 100644
index 0000000..925871b
--- /dev/null
+++ b/test/tests/fproc/test_strings.h
@@ -0,0 +1,44 @@
+// =====================================================================================================================
+// 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 .
+// =====================================================================================================================
+
+#ifndef FENNEC_TEST_FPROC_STRINGS_H
+#define FENNEC_TEST_FPROC_STRINGS_H
+
+#include "../../test.h"
+#include "./strings/test_cstring.h"
+
+namespace fennec
+{
+
+namespace test
+{
+
+inline void fennec_test_fproc_strings()
+{
+ fennec_test_subheader("cstring");
+ fennec_test_spacer(2);
+ fennec_test_fproc_strings_cstring();
+ fennec_test_spacer(3);
+
+}
+
+}
+
+}
+
+#endif // FENNEC_TEST_FPROC_STRINGS_H
diff --git a/test/tests/test_fproc.h b/test/tests/test_fproc.h
new file mode 100644
index 0000000..566e491
--- /dev/null
+++ b/test/tests/test_fproc.h
@@ -0,0 +1,44 @@
+// =====================================================================================================================
+// 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 .
+// =====================================================================================================================
+
+#ifndef FENNEC_TEST_FPROC_H
+#define FENNEC_TEST_FPROC_H
+
+#include "../test.h"
+#include "./fproc/test_strings.h"
+
+namespace fennec
+{
+
+namespace test
+{
+
+inline void fennec_test_fproc()
+{
+ fennec_test_header("strings");
+ fennec_test_spacer(2);
+ fennec_test_fproc_strings();
+ fennec_test_spacer(3);
+
+}
+
+}
+
+}
+
+#endif // FENNEC_TEST_FPROC_H