- Stacktrace generation with failed asserts

This commit is contained in:
2025-07-05 14:22:59 -04:00
parent 0afaae72ac
commit a33bf5206f
22 changed files with 529 additions and 191 deletions

3
.gitmodules vendored
View File

@@ -1,3 +1,6 @@
[submodule "external/sdl"] [submodule "external/sdl"]
path = external/sdl path = external/sdl
url = https://github.com/libsdl-org/SDL.git url = https://github.com/libsdl-org/SDL.git
[submodule "external/cpptrace"]
path = external/cpptrace
url = https://github.com/jeremy-rifkin/cpptrace.git

View File

@@ -7,6 +7,9 @@ project(fennec)
set(SDL_STATIC 1) set(SDL_STATIC 1)
add_subdirectory(external/sdl) add_subdirectory(external/sdl)
# CppTrace is a dependency of the project, added as a git submodule
add_subdirectory(external/cpptrace)
set(CMAKE_CXX_STANDARD 26) set(CMAKE_CXX_STANDARD 26)
set(CMAKE_C_STANDARD 26) set(CMAKE_C_STANDARD 26)
@@ -15,6 +18,8 @@ find_package(Doxygen)
# any necessary include directories # any necessary include directories
include_directories(include) include_directories(include)
include_directories(external/cpptrace/include)
include_directories(external/sdl/include)
# Metaprogramming is a dependency for generating various type info before compilation of the engine. # Metaprogramming is a dependency for generating various type info before compilation of the engine.
add_subdirectory(metaprogramming) add_subdirectory(metaprogramming)
@@ -58,7 +63,9 @@ add_library(fennec STATIC
include/fennec/lang/integer.h include/fennec/lang/integer.h
include/fennec/lang/detail/__bits.h include/fennec/lang/detail/__bits.h
include/fennec/lang/detail/__int.h
include/fennec/lang/detail/__numeric_transforms.h include/fennec/lang/detail/__numeric_transforms.h
include/fennec/lang/detail/__stdlib.h
include/fennec/lang/detail/__type_traits.h include/fennec/lang/detail/__type_traits.h
include/fennec/lang/detail/__type_sequences.h include/fennec/lang/detail/__type_sequences.h
@@ -75,6 +82,9 @@ add_library(fennec STATIC
include/fennec/memory/detail/__ptr_traits.h include/fennec/memory/detail/__ptr_traits.h
# DEBUG ================================================================================================================
source/debug/assert_impl.cpp
# MATH ================================================================================================================= # MATH =================================================================================================================
include/fennec/math/math.h include/fennec/math/math.h
@@ -98,22 +108,26 @@ add_library(fennec STATIC
include/fennec/math/relational.h include/fennec/math/relational.h
include/fennec/math/detail/__fwd.h include/fennec/math/detail/__fwd.h
include/fennec/math/detail/__math.h
include/fennec/math/detail/__matrix.h
include/fennec/math/detail/__types.h include/fennec/math/detail/__types.h
include/fennec/math/detail/__vector_traits.h include/fennec/math/detail/__vector_traits.h
source/debug/assert_impl.cpp
include/fennec/math/detail/__math.h
include/fennec/lang/detail/__int.h
include/fennec/lang/detail/__stdlib.h
include/fennec/math/detail/__matrix.h
include/fennec/math/ext/constants.h include/fennec/math/ext/constants.h
# FPROC ================================================================================================================
# Strings
include/fennec/fproc/strings/string.h
include/fennec/fproc/strings/detail/__ctype.h
) )
# add metaprogramming templates as a dependency and also force documentation to be generated when fennec is compiled # add metaprogramming templates as a dependency and also force documentation to be generated when fennec is compiled
if(DOXYGEN_FOUND) if(DOXYGEN_FOUND)
add_dependencies(fennec fennecdocs metaprogramming SDL3-static) add_dependencies(fennec fennecdocs metaprogramming SDL3-static cpptrace::cpptrace)
else() else()
add_dependencies(fennec metaprogramming SDL3-static) add_dependencies(fennec metaprogramming SDL3-static cpptrace::cpptrace)
endif() endif()
# Compiler Warning Flags # Compiler Warning Flags
@@ -123,12 +137,14 @@ else()
add_compile_options("-Wall" "-Wextra" "-pedantic" "-Werror") # All gcc/etc. Warnings throw as errors add_compile_options("-Wall" "-Wextra" "-pedantic" "-Werror") # All gcc/etc. Warnings throw as errors
endif() endif()
#target_compile_options(fennec PUBLIC "-mavx" "-mavx2" "-mavx512f") # SIMD Instructions, currently unused target_compile_options(fennec PUBLIC "-mavx" "-mavx2" "-mavx512f") # SIMD Instructions, automatic vectorization will occur
target_link_options(fennec PRIVATE "-nostdlib") # Do not compile base fennec library with c++ stdlib target_link_options(fennec PRIVATE "-nostdlib -nodefaultlibs -fno-exceptions") # 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. # 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 # This implementation is designed to be as readable as possible, and expose information that would otherwise be obfuscated
target_link_libraries(fennec PRIVATE SDL3-static cpptrace::cpptrace)
# add the test suite as a sub-project # add the test suite as a sub-project
add_subdirectory(test) add_subdirectory(test)

View File

@@ -121,8 +121,13 @@ Here are essential data-structures not specified in the C++ stdlib:
## Format Processing (`fproc`) ## Format Processing (`fproc`)
This library contains information for any data that is formatted. This includes basic string formats, file formats,
and eventually programming languages
fennec should be able to use Doxygen and LaTeX externally. Consider including binaries with releases. fennec should be able to use Doxygen and LaTeX externally. Consider including binaries with releases.
### Notes
* String Analysis (`fproc/strings`) * String Analysis (`fproc/strings`)
* Search * Search
* Manipulation * Manipulation
@@ -160,7 +165,7 @@ fennec should be able to use Doxygen and LaTeX externally. Consider including bi
- FBX - FBX
- Wavefront OBJ - Wavefront OBJ
**MAYBE** **TODO LATER**
* Compilation (`fproc/code`) * Compilation (`fproc/code`)
* Lexical Analysis * Lexical Analysis
* Syntax Analysis * Syntax Analysis

View File

@@ -31,6 +31,8 @@
may be used through the provided editor application, or as a standalone library to may be used through the provided editor application, or as a standalone library to
link against your application. link against your application.
<br> <br>
<a id="coding-standards"></a> <a id="coding-standards"></a>

View File

@@ -68,7 +68,7 @@ PROJECT_LOGO =
# entered, it will be relative to the location where doxygen was started. If # entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used. # left blank the current directory will be used.
OUTPUT_DIRECTORY = C:/Users/msloc/Documents/Work/Personal/fennec/docs OUTPUT_DIRECTORY = /home/medusa/Documents/Work/Personal/fennec/docs
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096 # If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096
# sub-directories (in 2 levels) under the output directory of each output format # sub-directories (in 2 levels) under the output directory of each output format
@@ -815,7 +815,7 @@ FILE_VERSION_FILTER =
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
# tag is left empty. # tag is left empty.
LAYOUT_FILE = C:/Users/msloc/Documents/Work/Personal/fennec/doxy/DoxyLayout.xml LAYOUT_FILE = /home/medusa/Documents/Work/Personal/fennec/doxy/DoxyLayout.xml
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing # The CITE_BIB_FILES tag can be used to specify one or more bib files containing
# the reference definitions. This must be a list of .bib files. The .bib # the reference definitions. This must be a list of .bib files. The .bib
@@ -943,9 +943,9 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched. # Note: If this tag is empty the current directory is searched.
INPUT = "C:/Users/msloc/Documents/Work/Personal/fennec/include/" \ INPUT = "/home/medusa/Documents/Work/Personal/fennec/include/" \
"C:/Users/msloc/Documents/Work/Personal/fennec/source/" \ "/home/medusa/Documents/Work/Personal/fennec/source/" \
"C:/Users/msloc/Documents/Work/Personal/fennec/README.md" "/home/medusa/Documents/Work/Personal/fennec/README.md"
# This tag can be used to specify the character encoding of the source files # This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@@ -1079,7 +1079,7 @@ EXCLUDE_SYMBOLS =
# that contain example code fragments that are included (see the \include # that contain example code fragments that are included (see the \include
# command). # command).
EXAMPLE_PATH = "C:/Users/msloc/Documents/Work/Personal/fennec" EXAMPLE_PATH = "/home/medusa/Documents/Work/Personal/fennec"
# If the value of the EXAMPLE_PATH tag contains directories, you can use the # If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
@@ -1160,7 +1160,7 @@ FILTER_SOURCE_PATTERNS =
# (index.html). This can be useful if you have a project on for instance GitHub # (index.html). This can be useful if you have a project on for instance GitHub
# and want to reuse the introduction page also for the doxygen output. # and want to reuse the introduction page also for the doxygen output.
USE_MDFILE_AS_MAINPAGE = "C:/Users/msloc/Documents/Work/Personal/fennec/README.md" USE_MDFILE_AS_MAINPAGE = "/home/medusa/Documents/Work/Personal/fennec/README.md"
# The Fortran standard specifies that for fixed formatted Fortran code all # The Fortran standard specifies that for fixed formatted Fortran code all
# characters from position 72 are to be considered as comment. A common # characters from position 72 are to be considered as comment. A common
@@ -1359,7 +1359,7 @@ HTML_FILE_EXTENSION = .html
# of the possible markers and block names see the documentation. # of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
HTML_HEADER = C:/Users/msloc/Documents/Work/Personal/fennec/doxy/header.html HTML_HEADER = /home/medusa/Documents/Work/Personal/fennec/doxy/header.html
# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
# generated HTML page. If the tag is left blank doxygen will generate a standard # generated HTML page. If the tag is left blank doxygen will generate a standard
@@ -1369,7 +1369,7 @@ HTML_HEADER = C:/Users/msloc/Documents/Work/Personal/fennec/doxy/head
# that doxygen normally uses. # that doxygen normally uses.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FOOTER = C:/Users/msloc/Documents/Work/Personal/fennec/doxy/footer.html HTML_FOOTER = /home/medusa/Documents/Work/Personal/fennec/doxy/footer.html
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
# sheet that is used by each HTML page. It can be used to fine-tune the look of # sheet that is used by each HTML page. It can be used to fine-tune the look of
@@ -1381,7 +1381,7 @@ HTML_FOOTER = C:/Users/msloc/Documents/Work/Personal/fennec/doxy/foot
# obsolete. # obsolete.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
HTML_STYLESHEET = C:/Users/msloc/Documents/Work/Personal/fennec/doxy/style.css HTML_STYLESHEET = /home/medusa/Documents/Work/Personal/fennec/doxy/style.css
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# cascading style sheets that are included after the standard style sheets # cascading style sheets that are included after the standard style sheets
@@ -1399,10 +1399,10 @@ HTML_STYLESHEET = C:/Users/msloc/Documents/Work/Personal/fennec/doxy/styl
# documentation. # documentation.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_STYLESHEET = C:/Users/msloc/Documents/Work/Personal/fennec/doxy/doxygen-awesome.css \ HTML_EXTRA_STYLESHEET = /home/medusa/Documents/Work/Personal/fennec/doxy/doxygen-awesome.css \
C:/Users/msloc/Documents/Work/Personal/fennec/doxy/doxygen-awesome-sidebar-only.css \ /home/medusa/Documents/Work/Personal/fennec/doxy/doxygen-awesome-sidebar-only.css \
C:/Users/msloc/Documents/Work/Personal/fennec/doxy/doxygen-awesome-sidebar-only-darkmode-toggle.css \ /home/medusa/Documents/Work/Personal/fennec/doxy/doxygen-awesome-sidebar-only-darkmode-toggle.css \
C:/Users/msloc/Documents/Work/Personal/fennec/doxy/custom.css /home/medusa/Documents/Work/Personal/fennec/doxy/custom.css
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note # other source files which should be copied to the HTML output directory. Note
@@ -1412,7 +1412,7 @@ HTML_EXTRA_STYLESHEET = C:/Users/msloc/Documents/Work/Personal/fennec/doxy/doxy
# files will be copied as-is; there are no commands or markers available. # files will be copied as-is; there are no commands or markers available.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_FILES = "C:/Users/msloc/Documents/Work/Personal/fennec/doxy/doxygen-awesome-darkmode-toggle.js" HTML_EXTRA_FILES = "/home/medusa/Documents/Work/Personal/fennec/doxy/doxygen-awesome-darkmode-toggle.js"
# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output # The HTML_COLORSTYLE tag can be used to specify if the generated HTML output
# should be rendered with a dark or light theme. # should be rendered with a dark or light theme.

1
external/cpptrace vendored Submodule

Submodule external/cpptrace added at 9133b90a99

View File

@@ -57,7 +57,7 @@ struct array
/// ///
/// \copydetails array::at(size_t) const /// \copydetails array::at(size_t) const
constexpr ValueT& at(size_t i) { static_assert(i < ElemV); assert(i < ElemV); return elements[i]; } constexpr ValueT& at(size_t i) { static_assert(i < ElemV); assert(i < ElemV, "Array Out of Bounds"); return elements[i]; }
/// ///
/// \brief access specified element, **with bounds checking** /// \brief access specified element, **with bounds checking**
@@ -70,7 +70,7 @@ struct array
/// ///
/// \par Space-Complexity /// \par Space-Complexity
/// Constant /// Constant
constexpr const ValueT& at(size_t i) const { static_assert(i < ElemV); assert(i < ElemV); return elements[i]; } constexpr const ValueT& at(size_t i) const { static_assert(i < ElemV); assert(i < ElemV, "Array Out of Bounds"); return elements[i]; }

View File

@@ -0,0 +1,38 @@
// =====================================================================================================================
// 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_STRINGS_DETAIL_CTYPE_H
#define FENNEC_FPROC_STRINGS_DETAIL_CTYPE_H
#if _MSC_VER
#pragma warning(push)
#pragma warning(disable:4117)
#define __PTRDIFF_TYPE__ ptrdiff_t
#endif
#pragma push_macro("__cplusplus")
#undef __cplusplus
#include <ctype.h>
#pragma pop_macro("__cplusplus")
#if _MSC_VER
#pragma warning(pop)
#endif
#endif // FENNEC_FPROC_STRINGS_DETAIL_CTYPE_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_FPROC_STRINGS_STRING_H
#define FENNEC_FPROC_STRINGS_STRING_H
#include <fennec/fproc/strings/detail/__ctype.h>
#include <fennec/lang/assert.h>
#include <fennec/memory/allocator.h>
#include <fennec/memory/memory.h>
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
template<typename AllocT = allocator<char>>
struct string
{
public:
using alloc_t = allocation<char, AllocT>;
///
/// \brief Default Constructor, initializes empty string
constexpr string()
: _str()
{ }
///
/// \brief Sized Constructor, initializes a null-terminated string of size `n` with null characters
/// \param n the number of characters
///
/// \details adds additional character for null termination.
constexpr string(size_t n)
: string('\0', n)
{ }
///
/// \brief Sized Constructor, initializes a null-terminated string of size `n` filled with the character `c`
/// \param c the character to fill with
/// \param n the number of characters
///
/// \details adds additional character for null termination.
constexpr string(char c, size_t n)
: _str(n + 1)
{ fennec::memset(_str, c, n); _str[n] = '\0'; }
///
/// \brief Buffer Copy Constructor
/// \param str the buffer to copy
/// \param len number of characters in the buffer
///
/// \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<size_t N>
constexpr string(const char str[N])
{
if (str[N - 1] == '\0') string(str, N - 1);
else string(str, N);
}
///
/// \brief String Copy Constructor
/// \param str the string to copy
constexpr string(const string& str)
: string(str, str.size() - 1)
{ }
constexpr string(string&& str) noexcept
: _str(fennec::move(str._str))
{ }
///
/// \brief String Destructor, cleans up the underlying allocation
constexpr ~string() = default; // allocation cleans up itself
// Properties ==========================================================================================================
///
/// \returns The size of the string excluding null terminator
constexpr size_t size() const { return _str.capacity() - 1; }
// Access ==============================================================================================================
///
/// \brief Array Access Operator
/// \param i the index to access
/// \returns a reference to the character
constexpr char& operator[](int i) {
assert(i >= 0 && i < size(), "Array Out of Bounds");
return _str[i];
}
///
/// \brief Const-Array Access Operator
/// \param i the index to access
/// \returns a copy of the character
constexpr char operator[](int i) const {
assert(i >= 0 && i < size(), "Array Out of Bounds");
return _str[i];
}
///
/// \brief Dereference Operator
/// \returns A const qualified pointer to the underlying allocation
constexpr const char* operator*() const { return _str; }
///
/// \brief Implicit Dereference Cast
constexpr operator const char*() const { return _str; }
// 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 string& ostr) const
{ return ::strcoll(_str, ostr); }
///
/// \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(_str, x);
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 string& 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
/// \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(_str, x);
return loc ? loc - _str : size();
}
// TODO: constexpr size_t rfind(const string& str) const;
// Manipulation ========================================================================================================
///
/// \brief Resize the string, filling additional bytes with `'\0'`
/// \param n the new size of the string
constexpr void resize(size_t n)
{
size_t i = size();
_str.reallocate(n + 1);
if (n > i) fennec::memset(*_str + i, '\0', n - i);
}
///
/// \brief Copy Assignment Operator
/// \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());
fennec::memcpy(_str, str, str.size());
_str[str.size()] = '\0';
return *this;
}
///
/// \brief Move Assignment Operator
/// \param str the string to move
/// \returns a reference to `this`
constexpr string& operator=(string&& str) noexcept
{
_str = fennec::move(str._str);
return *this;
}
///
/// \brief Retrieve a substring of a string
/// \param i the start index
/// \param n the number of characters
/// \return
constexpr string substring(size_t i, size_t n = size())
{
assert(i < size(), "Array Out of Bounds");
n = min(n, size() - i);
return string(&_str[i], n);
}
///
/// \brief Returns a string with `c` appended to it
/// \param c
/// \returns
constexpr string operator+(char c)
{
// Copy contents with one additional byte.
string res(_str, _str.size());
res[size()] = c; // Set the last character to c
return res;
}
constexpr string operator+(const string& 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();
resize(x + 1);
_str[x] = c;
return *this;
}
constexpr string& operator+=(const string& str)
{
size_t x = size();
string::resize(x + str.size());
fennec::memcpy(&_str[x], str, str.size());
return *this;
}
private:
alloc_t _str;
};
}
#endif // FENNEC_FPROC_STRINGS_STRING_H

View File

@@ -25,8 +25,9 @@
using assert_handler = void (*)(const char *, const char *, int , const char *); 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); extern void __assert_impl(const char* expression, const char* file, int line, const char* function, const char* desc);
#define assert(expression) if(not(expression)) { __assert_impl(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__); } #define assert(expression, description) \
if(not(expression)) { __assert_impl(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__, description); }
#endif // FENNEC_LANG_ASSERT_H #endif // FENNEC_LANG_ASSERT_H

View File

@@ -153,17 +153,6 @@
/// \copybrief fennec::int64_t /// \copybrief fennec::int64_t
/// ///
/// ///
///// <tr><td width="50%" style="vertical-align: top"> <br>
///// <tt>\ref fennec::float32_t "float32_t"</tt>
///// <td width="50%" style="vertical-align: top">
///// \copybrief fennec::float32_t
/////
///// <tr><td width="50%" style="vertical-align: top"> <br>
///// <tt>\ref fennec::float64_t "float64_t"</tt>
///// <td width="50%" style="vertical-align: top">
///// \copybrief fennec::float64_t
///
///
/// <tr><th colspan=2 style="text-align: center;">Special Types /// <tr><th colspan=2 style="text-align: center;">Special Types
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// <tt>\ref fennec::nullptr_t "nullptr_t"</tt> /// <tt>\ref fennec::nullptr_t "nullptr_t"</tt>

View File

@@ -324,7 +324,7 @@ struct matrix
/// ///
/// \copydetails matrix::operator[](size_t) const /// \copydetails matrix::operator[](size_t) const
constexpr column_t& operator[](size_t i) constexpr column_t& operator[](size_t i)
{ assert(i < columns); return data[i]; } { assert(i < columns, "Array Out of Bounds"); return data[i]; }
/// ///
/// \brief returns the column at index \f$i\f$ /// \brief returns the column at index \f$i\f$
@@ -333,20 +333,20 @@ struct matrix
/// \param i the index /// \param i the index
/// \returns the column at index \f$i\f$ /// \returns the column at index \f$i\f$
constexpr const column_t& operator[](size_t i) const constexpr const column_t& operator[](size_t i) const
{ assert(i < columns); return data[i]; } { assert(i < columns, "Array Out of Bounds"); return data[i]; }
/// ///
/// \copydetails matrix::operator()(size_t, size_t) const /// \copydetails matrix::operator()(size_t, size_t) const
constexpr scalar_t& operator()(size_t i, size_t j) constexpr scalar_t& operator[](size_t i, size_t j)
{ assert(i < columns && j < rows); return data[i][j]; } { assert(i < columns && j < rows, "Array Out of Bounds"); return data[i][j]; }
/// ///
/// \brief returns the cell in row \p j column \p i /// \brief returns the cell in row \p j column \p i
/// \param i the column /// \param i the column
/// \param j the row /// \param j the row
/// \returns the cell at the specified index. /// \returns the cell at the specified index.
constexpr scalar_t operator()(size_t i, size_t j) const constexpr scalar_t operator[](size_t i, size_t j) const
{ assert(i < columns && j < rows); return data[i][j]; } { assert(i < columns && j < rows, "Array Out of Bounds"); return data[i][j]; }
/// @} /// @}

View File

@@ -710,7 +710,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \brief unary boolean not operator /// \brief unary boolean not operator
/// ///
/// \details /// \details
/// \param v the vector /// \param x the vector
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=!x_i\f$ /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=!x_i\f$
constexpr friend vector_t operator!(const vector_t& x) constexpr friend vector_t operator!(const vector_t& x)
{ return vector_t(!x[IndicesV] ...); } { return vector_t(!x[IndicesV] ...); }

View File

@@ -22,6 +22,7 @@
#include <fennec/memory/ptr_traits.h> #include <fennec/memory/ptr_traits.h>
#include <fennec/lang/conditional_types.h> #include <fennec/lang/conditional_types.h>
#include <fennec/lang/numeric_transforms.h>
#include <fennec/lang/types.h> #include <fennec/lang/types.h>
#include <fennec/lang/type_traits.h> #include <fennec/lang/type_traits.h>
#include <fennec/math/common.h> #include <fennec/math/common.h>
@@ -64,7 +65,7 @@ private:
struct __diff<AllocT, PtrT, void_t<typename AllocT::diff_t>> { using type = typename AllocT::diff_t; }; struct __diff<AllocT, PtrT, void_t<typename AllocT::diff_t>> { using type = typename AllocT::diff_t; };
template<typename AllocT, typename DiffT, typename = void> template<typename AllocT, typename DiffT, typename = void>
struct __size : std::make_unsigned<DiffT> {}; struct __size : make_unsigned<DiffT> {};
template<typename AllocT, typename DiffT> template<typename AllocT, typename DiffT>
struct __size<AllocT, DiffT, void_t<typename AllocT::size_t>> { using type = typename AllocT::size_t; }; struct __size<AllocT, DiffT, void_t<typename AllocT::size_t>> { using type = typename AllocT::size_t; };
@@ -188,7 +189,17 @@ public:
/// \brief Sized Constructor, initializes the allocation with a block of size `n * sizeof(T)` bytes /// \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 /// \param n The number of elements of type `T` to allocate for
constexpr allocation(size_t n) noexcept constexpr allocation(size_t n) noexcept
: _data(_alloc.al), _capacity(n) {} : _data(nullptr), _capacity(0)
{ allocate(n); }
///
/// \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)
: allocation(n)
{ fennec::memcpy(_data, data, n); }
/// ///
/// \brief Allocator Constructor /// \brief Allocator Constructor
@@ -205,7 +216,20 @@ public:
/// ///
/// \details This constructor should be used when the type `AllocT` needs internal data. /// \details This constructor should be used when the type `AllocT` needs internal data.
constexpr allocation(size_t n, const alloc_t& alloc) noexcept constexpr allocation(size_t n, const alloc_t& alloc) noexcept
: _alloc(alloc), _data(nullptr), _capacity(0) {} : _alloc(alloc), _data(nullptr), _capacity(0)
{ allocate(n); }
///
/// \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, const alloc_t& alloc)
: allocation(n, alloc)
{ fennec::memcpy(_data, data, n); }
/// ///
/// \brief Copy Constructor, creates an allocation of equal size and performs a byte-wise copy /// \brief Copy Constructor, creates an allocation of equal size and performs a byte-wise copy
@@ -227,6 +251,35 @@ public:
/// \brief Default Destructor, releases the memory block if still present /// \brief Default Destructor, releases the memory block if still present
constexpr ~allocation() noexcept { if (_data) _alloc.deallocate(_data); } constexpr ~allocation() noexcept { if (_data) _alloc.deallocate(_data); }
///
/// \brief Copy Assignment Operator
/// \param alloc the allocation to copy
/// \returns a reference to `this`
constexpr allocation& operator=(const allocation& alloc)
{
allocation::allocate(alloc.capacity());
fennec::memcpy(_data, alloc, size());
return *this;
}
///
/// \brief Move Assignment Operator
/// \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;
return *this;
}
/// ///
/// \brief Allocate a block of memory for the allocation. /// \brief Allocate a block of memory for the allocation.
/// If there is already an allocated block of memory, the previous allocation is released. /// If there is already an allocated block of memory, the previous allocation is released.
@@ -236,7 +289,7 @@ public:
if (_data) if (_data)
_alloc.deallocate(_data); _alloc.deallocate(_data);
_data = alloc_t::allocate(_capacity = n); _data = _alloc.allocate(_capacity = n);
} }
/// ///
@@ -245,6 +298,7 @@ public:
{ {
if (_data) if (_data)
_alloc.deallocate(_data); _alloc.deallocate(_data);
_data = nullptr; _data = nullptr;
_capacity = 0; _capacity = 0;
} }
@@ -258,7 +312,7 @@ public:
return _alloc.allocate(_capacity = n); return _alloc.allocate(_capacity = n);
value_t* old = _data; value_t* old = _data;
_data = alloc_t::allocate(n); _data = _alloc.allocate(n);
fennec::memcpy(_data, old, min(_capacity, n) * sizeof(T)); fennec::memcpy(_data, old, min(_capacity, n) * sizeof(T));
_alloc.deallocate(old); _alloc.deallocate(old);
_capacity = n; _capacity = n;

View File

@@ -21,46 +21,32 @@
#include <fennec/lang/types.h> #include <fennec/lang/types.h>
namespace fennec
{
namespace detail
{
constexpr size_t __memcpy_8(void* dst, const void* src) // deprecated, switched to ISO C implementation
{ *static_cast<uint8_t*>(dst) = *static_cast<const uint8_t*>(src); return 1; } // see https://git.mslockbo.org/mslockbo/fennec/src/commit/0eeb7ae3cff9d78e98dc5d9fc09bcb98b10986b9 for previous
// implementation
// helper for copying 2 bytes at once #if _MSC_VER
constexpr size_t __memcpy_16(void* dst, const void* src) #pragma warning(push)
{ *static_cast<uint16_t*>(dst) = *static_cast<const uint16_t*>(src); return 2; } #pragma warning(disable:4117)
#endif
// helper for copying 4 bytes at once #if __GNUC__
constexpr size_t __memcpy_32(void* dst, const void* src) #define __OPTIMIZE__
{ *static_cast<uint32_t*>(dst) = *static_cast<const uint32_t*>(src); return 4; } #endif
// helper for copying 8 bytes at once #pragma push_macro("__cplusplus")
constexpr size_t __memcpy_64(void* dst, const void* src) #undef __cplusplus
{ *static_cast<uint64_t*>(dst) = *static_cast<const uint64_t*>(src); return 8; } #include <string.h>
#pragma pop_macro("__cplusplus")
constexpr size_t __memcpy(void* dst, const void* src, size_t n) #if __GNUC__
{ #undef __OPTIMIZE__
switch (n) #endif
{
case 0:
return 0;
case 1:
return __memcpy_8(dst, src);
case 2: case 3:
return __memcpy_16(dst, src);
case 4: case 5: case 6: case 7:
return __memcpy_32(dst, src);
default:
return __memcpy_64(dst, src);
}
}
} #if _MSC_VER
#pragma warning(pop)
} #endif
#endif // FENNEC_MEMORY_DETAIL_MEMORY_H #endif // FENNEC_MEMORY_DETAIL_MEMORY_H

View File

@@ -21,7 +21,7 @@
#define FENNEC_MEMORY_H #define FENNEC_MEMORY_H
#include <fennec/lang/type_traits.h> #include <fennec/lang/type_traits.h>
#include <fennec/memory/detail/__memory.h> #include <fennec/memory/detail/__string.h>
namespace fennec namespace fennec
{ {
@@ -34,27 +34,14 @@ namespace fennec
template<typename TypeT> template<typename TypeT>
constexpr TypeT* addressof(TypeT& obj) { return FENNEC_BUILTIN_ADDRESSOF(obj); } constexpr TypeT* addressof(TypeT& obj) { return FENNEC_BUILTIN_ADDRESSOF(obj); }
///
/// \copydetails fennec::memchr(const void*, int, size_t)
constexpr void* memchr(void* arr, int ch, size_t n)
{
uint8_t* a = static_cast<uint8_t*>(arr);
while (n-- && *a++ != ch) {}
return n ? a : nullptr;
}
/// ///
/// \brief Finds the first occurence of ```static_cast<uint8_t>(ch)``` in the first \f$n\f$ bytes /// \brief Finds the first occurence of ```static_cast<uint8_t>(ch)``` in the first \f$n\f$ bytes
/// \param arr Pointer to the object, interpreted as an array of bytes /// \param arr Pointer to the object, interpreted as an array of bytes
/// \param ch The byte to search for /// \param ch The byte to search for
/// \param n The number of bytes to search /// \param n The number of bytes to search
/// \returns A pointer to the location of \f$ch\f$, otherwise \f$nullptr\f$ if \f$ch\f$ is not found. /// \returns A pointer to the location of \f$ch\f$, otherwise \f$nullptr\f$ if \f$ch\f$ is not found.
constexpr const void* memchr(const void* arr, int ch, size_t n) using ::memchr;
{ using ::wmemchr;
const uint8_t* a = static_cast<const uint8_t*>(arr);
while (n-- && *a++ != ch) {}
return n ? a : nullptr;
}
/// ///
/// \brief Compares the bytes of \f$lhs\f$ with \f$rhs\f$. /// \brief Compares the bytes of \f$lhs\f$ with \f$rhs\f$.
@@ -63,13 +50,8 @@ constexpr const void* memchr(const void* arr, int ch, size_t n)
/// \param n The number of bytes to parse /// \param n The number of bytes to parse
/// \returns \f$0\f$ if the first \f$n\f$ bytes of \f$lhs\f$ and \f$rhs\f$ are equivalent. Otherwise, returns \f$1\f$ /// \returns \f$0\f$ if the first \f$n\f$ bytes of \f$lhs\f$ and \f$rhs\f$ are equivalent. Otherwise, returns \f$1\f$
/// for the first byte \f$b\f$ where \f$lhs[b] > \f$ rhs[b]\f$, and \f$-1\f$ for \f$ /// for the first byte \f$b\f$ where \f$lhs[b] > \f$ rhs[b]\f$, and \f$-1\f$ for \f$
constexpr int memcmp(const void* lhs, const void* rhs, size_t n) using ::memcmp;
{ using ::wmemcmp;
const uint8_t* lhs_ = static_cast<const uint8_t*>(lhs);
const uint8_t* rhs_ = static_cast<const uint8_t*>(rhs);
while (n-- && *lhs_++ == *rhs_++) {}
return n ? *lhs_ - *rhs_ : 0;
}
/// ///
/// \brief Safe version of memcmp /// \brief Safe version of memcmp
@@ -91,19 +73,8 @@ constexpr int memcmp_s(const void* lhs, size_t n0, const void* rhs, size_t n1)
/// \f$src\f$ will be repeated in \f$dst\f$ with a period of \f$k\f$. /// \f$src\f$ will be repeated in \f$dst\f$ with a period of \f$k\f$.
/// ///
/// A full mathematical proof of this function is possible in Set Theory. /// A full mathematical proof of this function is possible in Set Theory.
constexpr void* memcpy(void* dst, const void* src, size_t n) using ::memcpy;
{ using ::wmemcpy;
if (dst == src) return dst;
uint8_t* d = static_cast<uint8_t*>(dst);
const uint8_t* s = static_cast<const uint8_t*>(src);
while (n > 0) {
size_t step = detail::__memcpy(d, s, n);
d += step; s += step; n -= step;
}
return dst;
}
/// ///
/// \brief Safe version of memcpy /// \brief Safe version of memcpy
@@ -119,27 +90,8 @@ constexpr void* memcpy_s(void* dst, size_t n0, const void* src, size_t n1)
/// \param src The source object, interpreted as an array of bytes /// \param src The source object, interpreted as an array of bytes
/// \param n The number of bytes to copy /// \param n The number of bytes to copy
/// \returns \f$dst\f$ /// \returns \f$dst\f$
constexpr void* memmove(void* dst, const void* src, size_t n) using ::memmove;
{ using ::wmemmove;
if (dst == src) return dst;
uint8_t* d = static_cast<uint8_t*>(dst);
const uint8_t* s = static_cast<const uint8_t*>(src);
if (d < s) {
while (n > 0) {
size_t step = detail::__memcpy(d, s, n);
d += step; s += step; n -= step;
}
}
else {
d += n - 1; s += n - 1;
while (n > 0) {
size_t step = detail::__memcpy(d, s, n);
d -= step; s -= step; n -= step;
}
}
return dst;
}
/// ///
/// \brief Safe version of memmove /// \brief Safe version of memmove
@@ -155,18 +107,8 @@ constexpr void* memmove_s(void* dst, size_t n0, const void* src, size_t n1)
/// \param ch The value, interpreted as an \f$uint8_t\f$ /// \param ch The value, interpreted as an \f$uint8_t\f$
/// \param n The number of bytes to set /// \param n The number of bytes to set
/// \returns \f$dst\f$ /// \returns \f$dst\f$
constexpr void* memset(void* dst, int ch, size_t n) using ::memset;
{ using ::wmemset;
uint8_t* d = static_cast<uint8_t*>(dst);
uint8_t val[8] = { static_cast<uint8_t>(ch) };
while (n > 0) {
size_t step = detail::__memcpy(d, val, n);
d += step; n -= step;
}
return dst;
}
} }

View File

@@ -20,8 +20,6 @@
#ifndef FENNEC_MEMORY_NEW_H #ifndef FENNEC_MEMORY_NEW_H
#define FENNEC_MEMORY_NEW_H #define FENNEC_MEMORY_NEW_H
#include <new>
#include <fennec/lang/types.h> #include <fennec/lang/types.h>
#include <fennec/lang/utility.h> #include <fennec/lang/utility.h>

View File

@@ -16,7 +16,16 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
// ===================================================================================================================== // =====================================================================================================================
void __assert_callback(const char*, const char*, int, const char*) #include <cpptrace/cpptrace.hpp>
{
void __assert_callback(const char* expression, const char* file, int line, const char* function, const char* description)
{
// Skip
// __assert_callback
// __assert_impl
printf("Assert failed: \"%s\" \n"
"At %s:%d in %s \n"
"Description: %s \n",
expression, file, line, function, description);
cpptrace::generate_trace(2).print();
} }

View File

@@ -20,13 +20,13 @@
using assert_handler = void (*)(const char *, const char *, int , const char *); 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); extern 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) void __assert_impl(const char* expression, const char* file, int line, const char* function, const char* description)
{ {
__assert_callback(expression, file, line, function); __assert_callback(expression, file, line, function, description);
#ifndef NDEBUG #ifndef NDEBUG
abort(); ::abort();
#endif #endif
} }

View File

@@ -29,10 +29,10 @@
#else #else
// Allocation functions // 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) { 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); }
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 // Aligned allocation & deallocation functions
#ifdef _WIN32 #ifdef _WIN32
@@ -46,31 +46,31 @@ inline void* operator new[](fennec::size_t size, fennec::align_t align)
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); }
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 #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) noexcept { free(ptr); } inline void operator delete[](void* ptr) 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); }
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); }
inline void* operator new (fennec::size_t size, fennec::align_t align) { return aligned_alloc(static_cast<size_t>(align), size); } 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) { return aligned_alloc(static_cast<size_t>(align), size); } 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<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<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 #endif
// Aligned deallocation functions // 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); }
inline void operator delete[](void* ptr, fennec::align_t) noexcept { free(ptr); } inline void operator delete[](void* ptr, fennec::align_t) noexcept { ::free(ptr); }
// Sized deallocation functions // 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) 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); }
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 // Non-throwing deallocation functions
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, 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); }
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 #endif

View File

@@ -51,9 +51,6 @@ inline std::ostream& operator<<(std::ostream& os, const matrix<ScalarT, RowsV, C
{ {
os << "[ "; os << "[ ";
((os << m[ColIndicesV] << " "), ...); ((os << m[ColIndicesV] << " "), ...);
//[m]<size_t...i>(std::ostream& os, index_sequence<i...>) {
// ((os << fennec::row(m, i) << " "), ...);
//}(os, make_index_sequence<RowsV>{});
os << "]"; os << "]";
return os; return os;
} }
@@ -97,7 +94,7 @@ inline void __fennec_test_run(const std::string& expression, const ResultT resul
std::cout << std::endl; std::cout << std::endl;
// Assert to halt and get some debug info // Assert to halt and get some debug info
assert(passed); assert(passed, "Test Failed");
} }
} }