- Stacktrace generation with failed asserts
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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
1
external/cpptrace
vendored
Submodule
Submodule external/cpptrace added at 9133b90a99
@@ -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]; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
38
include/fennec/fproc/strings/detail/__ctype.h
Normal file
38
include/fennec/fproc/strings/detail/__ctype.h
Normal 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
|
||||||
297
include/fennec/fproc/strings/string.h
Normal file
297
include/fennec/fproc/strings/string.h
Normal 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
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -26,9 +26,9 @@
|
|||||||
|
|
||||||
#pragma push_macro("__cplusplus")
|
#pragma push_macro("__cplusplus")
|
||||||
#undef __cplusplus
|
#undef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
}
|
}
|
||||||
#pragma pop_macro("__cplusplus")
|
#pragma pop_macro("__cplusplus")
|
||||||
|
|
||||||
#if _MSC_VER
|
#if _MSC_VER
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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]; }
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|||||||
@@ -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] ...); }
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
@@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user