diff --git a/CMakeLists.txt b/CMakeLists.txt
index ddfa32f..d4c55e4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -70,16 +70,23 @@ add_library(fennec STATIC
# CONTAINERS ===========================================================================================================
+ include/fennec/containers/containers.h
+
include/fennec/containers/array.h
+ include/fennec/containers/deque.h
include/fennec/containers/dynarray.h
+ include/fennec/containers/graph.h
include/fennec/containers/list.h
include/fennec/containers/map.h
+ include/fennec/containers/object_pool.h
include/fennec/containers/optional.h
include/fennec/containers/pair.h
include/fennec/containers/rdtree.h
include/fennec/containers/set.h
+ include/fennec/containers/traversal.h
include/fennec/containers/tuple.h
+
include/fennec/containers/detail/_tuple.h
@@ -106,6 +113,9 @@ add_library(fennec STATIC
include/fennec/lang/utility.h
include/fennec/lang/integer.h
+ include/fennec/lang/assert.h source/lang/assert.cpp
+
+
include/fennec/lang/detail/_bits.h
include/fennec/lang/detail/_int.h
include/fennec/lang/detail/_numeric_transforms.h
@@ -115,8 +125,6 @@ add_library(fennec STATIC
include/fennec/lang/detail/_type_sequences.h
include/fennec/lang/detail/_typeuuid.h
- include/fennec/lang/assert.h source/lang/assert.cpp
-
# MEMORY ===============================================================================================================
include/fennec/memory/new.h source/memory/new.cpp
@@ -200,10 +208,6 @@ add_library(fennec STATIC
# EXTRA SOURCES ========================================================================================================
${FENNEC_EXTRA_SOURCES}
- include/fennec/containers/traversal.h
- include/fennec/containers/graph.h
- include/fennec/containers/deque.h
- include/fennec/containers/object_pool.h
)
add_dependencies(fennec metaprogramming)
@@ -232,6 +236,7 @@ file(COPY logo DESTINATION docs/logo)
if(DOXYGEN_FOUND)
add_dependencies(fennec fennecdocs)
set(DOXY_OUTPUT_DIR "${FENNEC_SOURCE_DIR}/docs")
+ set(DOXY_EXAMPLES_DIR "${FENNEC_SOURCE_DIR}/examples")
get_filename_component(DOXYGEN_PROJECT_NAME ${FENNEC_SOURCE_DIR} NAME) # Set Doxy Project name to the name of the root dir
set(DOXYGEN_CONFIG_IN "${FENNEC_SOURCE_DIR}/doxy/Doxyfile.in") # Input config file with preprocessor arguments
set(DOXYGEN_CONFIG_OUT "${FENNEC_SOURCE_DIR}/doxy/Doxyfile") # Generated config file from input
diff --git a/README.md b/README.md
index 1fd919a..ee2895c 100644
--- a/README.md
+++ b/README.md
@@ -8,21 +8,21 @@
-## Table of Contents
+
+
Table of Contents
-
* [Table of Contents](#table-of-contents)
* [Introduction](#introduction)
* [Coding Standards](#coding-standards)
* [Building from Source](#building-from-source)
* [Building from Terminal](#building-from-terminal)
* [Debian](#debian)
+ * [Fedora](#fedora-dnf) → `dnf`
* [Building on Windows](#building-on-windows)
* [Running the Test Suite](#running-the-test-suite)
* [Usage](#usage)
* [Licensing](#licensing)
* [Contribution](#contribution)
-
@@ -152,6 +152,7 @@ using specific toolchains for specific platforms that necessitate this. The prim
If you wish to build for Windows *and* Linux, your options are WSL or Dual Boot. I recommend Dual Boot over WSL.
+
#### Debian
On Debian-based distributions, you can install dependencies using the following command:
@@ -165,6 +166,7 @@ for Doxygen run:
sudo apt install doxygen graphviz
```
+
#### Fedora (`dnf`)
On Debian-based distributions, you can install dependencies using the following command:
@@ -238,23 +240,26 @@ information displayed is correct.
## Usage
+
### Licensing
The following content of this section is not legal advice, nor is it legally binding, and nor does it change the terms
of the license. Please seek legal council if you have any concerns.
- fennec is licensed under GPLv3. The primary reason for the choice of license is to dissuade corporations from modifying
-fennec and using it in a commercial manner. This of course does not bar them from using fennec commercially, however
-it will prevent them from being able to make the derivative work proprietary. You are free to use and redistribute
-fennec however you wish according to the terms of the license, which does not bar you from commercializing software
-based on fennec.
+TLDR; You may license your game under whichever license you please. Any C++ code that is by definition a derivative work
+must be licensed under GPLv3 and freely available, everything else; assets, scripts, design documents, etc. may be under
+the license of your choosing and remain proprietary.
+
+ fennec is licensed under GPLv3. The primary reason for the choice of license is to dissuade corporations from
+modifying fennec and using it in a commercial manner. This of course does not bar them from using fennec commercially,
+however it will prevent them from being able to make the derivative work proprietary. You are free to use and redistribute
+fennec however you wish according to the terms of the license, which does not bar you from commercializing software based
+on fennec.
If you wish to protect your game files, assets and generated content do not constitute a covered work and may be
copyrighted under a non-compliant license. Think of it in terms of using Blender to create a mesh for a game, then
licensing that mesh under another license.
-Any code that is linked against fennec or uses any part is by definition a covered work must be licensed under GPLv3.
-
Later down the line, I plan on implementing scripts in a manner that allows the script itself to remain proprietary.
The scripts will likely be trans-compiled to another language before being compiled to binary, but this is only an
intermediate step and will be erased when no longer needed.
diff --git a/build.sh b/build.sh
index a9652a8..b780158 100755
--- a/build.sh
+++ b/build.sh
@@ -38,7 +38,7 @@ Help()
Debug()
{
mkdir -p build/debug
- cd ./build/debug
+ cd ./build/debug || exit
cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -S ../.. -B .
cmake --build . --target fennec
cd ../..
@@ -47,7 +47,7 @@ Debug()
Release()
{
mkdir -p build/release
- cd ./build/release
+ cd ./build/release || exit
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -S ../.. -B .
cmake --build . --target fennec
cd ../..
@@ -56,7 +56,7 @@ Release()
RelWithDebInfo()
{
mkdir -p build/relwithdebinfo
- cd ./build/relwithdebinfo
+ cd ./build/relwithdebinfo || exit
cmake -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -S ../.. -B .
cmake --build . --target fennec
cd ../..
@@ -65,7 +65,7 @@ RelWithDebInfo()
MinSizeRel()
{
mkdir -p build/minsizerel
- cd ./build/minsizerel
+ cd ./build/minsizerel || exit
cmake -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel -S ../.. -B .
cmake --build . --target fennec
cd ../..
diff --git a/doxy/Doxyfile b/doxy/Doxyfile
index 26d134c..ba17054 100644
--- a/doxy/Doxyfile
+++ b/doxy/Doxyfile
@@ -129,7 +129,7 @@ BRIEF_MEMBER_DESC = YES
# brief descriptions will be completely suppressed.
# The default value is: YES.
-REPEAT_BRIEF = NO
+REPEAT_BRIEF = YES
# This tag implements a quasi-intelligent brief description abbreviator that is
# used to form the text in various listings. Each string in this list, if found
@@ -944,8 +944,7 @@ WARN_LOGFILE =
# Note: If this tag is empty the current directory is searched.
INPUT = "/home/medusa/Documents/Work/Personal/fennec/include" \
- "/home/medusa/Documents/Work/Personal/fennec/source" \
- "/home/medusa/Documents/Work/Personal/fennec/README.md"
+ "/home/medusa/Documents/Work/Personal/fennec/source"
# 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
@@ -1099,7 +1098,7 @@ EXAMPLE_RECURSIVE = NO
# that contain images that are to be included in the documentation (see the
# \image command).
-IMAGE_PATH =
+IMAGE_PATH = "/home/medusa/Documents/Work/Personal/fennec/doxy/static"
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
@@ -1981,7 +1980,7 @@ GENERATE_LATEX = NO
# The default directory is: latex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_OUTPUT = latex
+LATEX_OUTPUT = ./latex
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked.
@@ -2664,7 +2663,7 @@ TEMPLATE_RELATIONS = NO
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
-INCLUDE_GRAPH = YES
+INCLUDE_GRAPH = NO
# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
# set to YES then doxygen will generate a graph for each documented file showing
@@ -2676,7 +2675,7 @@ INCLUDE_GRAPH = YES
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
-INCLUDED_BY_GRAPH = YES
+INCLUDED_BY_GRAPH = NO
# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
# dependency graph for every global function or class method.
diff --git a/doxy/Doxyfile.in b/doxy/Doxyfile.in
index c460a84..7e8ae61 100644
--- a/doxy/Doxyfile.in
+++ b/doxy/Doxyfile.in
@@ -129,7 +129,7 @@ BRIEF_MEMBER_DESC = YES
# brief descriptions will be completely suppressed.
# The default value is: YES.
-REPEAT_BRIEF = NO
+REPEAT_BRIEF = YES
# This tag implements a quasi-intelligent brief description abbreviator that is
# used to form the text in various listings. Each string in this list, if found
@@ -944,8 +944,7 @@ WARN_LOGFILE =
# Note: If this tag is empty the current directory is searched.
INPUT = "@PROJECT_SOURCE_DIR@/include" \
- "@PROJECT_SOURCE_DIR@/source" \
- "@PROJECT_SOURCE_DIR@/README.md"
+ "@PROJECT_SOURCE_DIR@/source"
# 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
@@ -1099,7 +1098,7 @@ EXAMPLE_RECURSIVE = NO
# that contain images that are to be included in the documentation (see the
# \image command).
-IMAGE_PATH =
+IMAGE_PATH = "@PROJECT_SOURCE_DIR@/doxy/static"
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
@@ -1981,7 +1980,7 @@ GENERATE_LATEX = NO
# The default directory is: latex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
-LATEX_OUTPUT = latex
+LATEX_OUTPUT = ./latex
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked.
@@ -2664,7 +2663,7 @@ TEMPLATE_RELATIONS = NO
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
-INCLUDE_GRAPH = YES
+INCLUDE_GRAPH = NO
# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
# set to YES then doxygen will generate a graph for each documented file showing
@@ -2676,7 +2675,7 @@ INCLUDE_GRAPH = YES
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
-INCLUDED_BY_GRAPH = YES
+INCLUDED_BY_GRAPH = NO
# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
# dependency graph for every global function or class method.
diff --git a/doxy/retrieve-emojis.py b/doxy/retrieve-emojis.py
new file mode 100644
index 0000000..6438689
--- /dev/null
+++ b/doxy/retrieve-emojis.py
@@ -0,0 +1,71 @@
+# script to download the emoticons from GitHub and to produce a table for
+# inclusion in Doxygen. Works with python 2.7+ and python 3.x
+import json
+import os
+import argparse
+import re
+try:
+ import urllib.request as urlrequest
+except ImportError:
+ import urllib as urlrequest
+
+unicode_re = re.compile(r'.*?/unicode/(.*?).png\?.*')
+
+def get_emojis():
+ response = urlrequest.urlopen('https://api.github.com/emojis')
+ raw_data = response.read()
+ return json.loads(raw_data)
+
+def download_images(dir_name, silent):
+ if not os.path.exists(dir_name):
+ os.makedirs(dir_name)
+ json_data = get_emojis()
+ num_items = len(json_data)
+ cur_item=0
+ for image,url in sorted(json_data.items()):
+ image_name = image+'.png'
+ cur_item=cur_item+1
+ if url.find('/unicode/')==-1 or not os.path.isfile(dir_name+'/'+image_name):
+ success = True
+ with open(dir_name+'/'+image_name,'wb') as file:
+ if not silent:
+ print('%s/%s: fetching %s' % (cur_item,num_items,image_name))
+ try:
+ file.write(urlrequest.urlopen(url).read())
+ except:
+ print('Unable to fetch %s' % (image_name))
+ success = False
+ if not success:
+ os.remove(dir_name+'/'+image_name)
+ else:
+ if not silent:
+ print('%s/%s: skipping %s' % (cur_item,num_items,image_name))
+
+def produce_table():
+ json_data = get_emojis()
+ lines = []
+ for image,url in sorted(json_data.items()):
+ match = unicode_re.match(url)
+ if match:
+ unicodes = match.group(1).split('-')
+ unicodes_html = ''.join([""+x+";" for x in unicodes])
+ image_str = "\":"+image+":\","
+ unicode_str = "\""+unicodes_html+"\""
+ lines.append(' { %-42s %-38s }' % (image_str,unicode_str))
+ out_str = ',\n'.join(lines)
+ print("{")
+ print(out_str)
+ print("};")
+
+if __name__=="__main__":
+ parser = argparse.ArgumentParser()
+
+ parser.add_argument('-d','--dir',help='directory to place images in')
+ parser.add_argument('-t','--table',help='generate code fragment',action='store_true')
+ parser.add_argument('-s','--silent',help='silent mode',action='store_true')
+ args = parser.parse_args()
+
+ if args.table:
+ produce_table()
+ if args.dir:
+ download_images(args.dir, args.silent)
\ No newline at end of file
diff --git a/doxy/static/graphs/containers/rdtree.svg b/doxy/static/graphs/containers/rdtree.svg
new file mode 100644
index 0000000..5fb4644
--- /dev/null
+++ b/doxy/static/graphs/containers/rdtree.svg
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/external/cpptrace b/external/cpptrace
index 9133b90..69179bb 160000
--- a/external/cpptrace
+++ b/external/cpptrace
@@ -1 +1 @@
-Subproject commit 9133b90a9995e438476206bb116c849dfd0fe712
+Subproject commit 69179bbe8fb1019cc9d9264f3b266accb996be5b
diff --git a/include/fennec/containers/array.h b/include/fennec/containers/array.h
index 8be4948..6b3dad8 100644
--- a/include/fennec/containers/array.h
+++ b/include/fennec/containers/array.h
@@ -40,24 +40,62 @@ namespace fennec
///
///
-/// \brief wrapper for fixed size arrays
+/// \brief Data Structure that defines a compile-time allocated array
///
/// \details
-/// | Property | Value |
-/// |:--------:|:-----------------------:|
-/// | stable | \emoji heavy_check_mark |
-/// | access | \f$O(1)\f$ |
-/// | space | \f$O(N)\f$ |
+/// | Property | Value |
+/// |:----------:|:----------:|
+/// | stable | ✅ |
+/// | dynamic | ⛔ |
+/// | homogenous | ✅ |
+/// | distinct | ⛔ |
+/// | ordered | ⛔ |
+/// | space | \f$O(N)\f$ |
+/// | linear | ✅ |
+/// | access | \f$O(1)\f$ |
+/// | find | \f$O(N)\f$ |
+/// | insertion | ⛔ |
+/// | deletion | ⛔ |
///
/// \tparam ValueT value type
/// \tparam ElemV number of elements
template
struct array
{
+// Public Members ======================================================================================================
+
+ /// \name Public Members
+ /// @{
+
///
/// \brief backing c-style array handle
ValueT elements[ElemV];
+ /// @}
+
+
+
+// Properties ==========================================================================================================
+
+ /// \name Properties
+ /// @{
+
+ ///
+ /// \brief returns the number of elements in the array
+ /// \returns the number of elements in the array
+ [[nodiscard]] constexpr size_t size() const { return ElemV; }
+
+ ///
+ /// \brief returns **true** when the array is empty
+ /// \return \f$ElemV == 0\f$
+ [[nodiscard]] constexpr bool_t empty() const { return ElemV == 0; }
+
+ /// @}
+
+
+
+// Access ==============================================================================================================
+
/// \name Element Access
/// @{
@@ -84,32 +122,11 @@ struct array
return elements[i];
}
- constexpr ValueT* begin() { return elements; }
- constexpr ValueT* end() { return elements + ElemV; }
-
- constexpr const ValueT* begin() const { return elements; }
- constexpr const ValueT* end() const { return elements + ElemV; }
-
/// @}
- /// \name Capacity
- /// @{
-
- ///
- /// \brief returns the number of elements in the array
- /// \returns the number of elements in the array
- [[nodiscard]] constexpr size_t size() const { return ElemV; }
-
- ///
- /// \brief returns **true** when the array is empty
- /// \return \f$ElemV == 0\f$
- [[nodiscard]] constexpr bool_t empty() const { return ElemV == 0; }
-
- /// @}
-
-
+// Comparison ==========================================================================================================
/// \name Comparison Operators
/// @{
@@ -126,6 +143,32 @@ struct array
/// @}
+
+// Iteration ===========================================================================================================
+
+ /// \name Iteration
+ /// @{
+
+ ///
+ /// \returns A pointer to the first element of the array
+ constexpr ValueT* begin() { return elements; }
+
+ ///
+ /// \returns A pointer to one after the end of the array
+ constexpr ValueT* end() { return elements + ElemV; }
+
+
+
+ ///
+ /// \returns A const-qualified pointer to the first element of the array
+ constexpr const ValueT* begin() const { return elements; }
+
+ ///
+ /// \returns A const-qualified pointer to one after the end of the array
+ constexpr const ValueT* end() const { return elements + ElemV; }
+
+ /// @}
+
private:
template
static bool _compare(const array& lhs, const array& rhs, const_index_sequence) {
diff --git a/include/fennec/containers/containers.h b/include/fennec/containers/containers.h
new file mode 100644
index 0000000..6dcb13c
--- /dev/null
+++ b/include/fennec/containers/containers.h
@@ -0,0 +1,94 @@
+// =====================================================================================================================
+// 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 .
+// =====================================================================================================================
+
+///
+/// \file containers.h
+/// \brief fennec containers library main header
+///
+///
+/// \details
+/// \author Medusa Slockbower
+///
+/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
+///
+///
+
+#ifndef FENNEC_CONTAINERS_CONTAINERS_H
+#define FENNEC_CONTAINERS_CONTAINERS_H
+
+///
+/// \page fennec_containers Containers Library
+///
+/// \brief The fennec Containers Library.
+/// Includes various data structures, those specified in the C++ Standard Library, and custom data structures
+/// that fennec uses.
+///
+/// \code #include \endcode
+///
+/// \section fennec_containers_cppstdlib C++ Standard Template Library
+///
+/// | Symbol | Implemented | Passed |
+/// |:----------------------------------------------------------------------------|:-----------:|:------:|
+/// | \ref fennec::any "fennec::any" | ⛔ | ⛔ |
+/// | \ref fennec::array "fennec::array" | ✅ | ✅ |
+/// | \ref fennec::bitset "fennec::bitset" | ⛔ | ⛔ |
+/// | \ref fennec::deque "fennec::deque" | ⛔ | ⛔ |
+/// | \ref fennec::dynarray "fennec::dynarray" `std::vector` | 🚧 | 🚧 |
+/// | \ref fennec::list "fennec::list" | ✅ | ✅ |
+/// | \ref fennec::map "fennec::map" `std::unordered_map` | ✅ | ✅ |
+/// | \ref fennec::map_sequence "fennec::map_sequence" `std::map` | ⛔ | ⛔ |
+/// | \ref fennec::multiset "fennec::multiset" `std::unordered_multiset` | ⛔ | ⛔ |
+/// | \ref fennec::multisequence "fennec::multisequence" `std::multiset` | ⛔ | ⛔ |
+/// | \ref fennec::multimap "fennec::multimap" `std::unordered_multimap` | ⛔ | ⛔ |
+/// | \ref fennec::multimap_sequence "fennec::multimap_sequence" `std::multimap` | ⛔ | ⛔ |
+/// | \ref fennec::optional "fennec::optional" | ✅ | ✅ |
+/// | \ref fennec::pair "fennec::pair" | ✅ | ✅ |
+/// | \ref fennec::sequence "fennec::sequence" `std::set` | ⛔ | ⛔ |
+/// | \ref fennec::set "fennec::set" `std::unordered_set` | ✅ | ✅ |
+/// | \ref fennec::tuple "fennec::tuple" | 🚧 | 🚧 |
+/// | \ref fennec::variant "fennec::variant" | ⛔ | ⛔ |
+///
+///
+/// \section fennec_containers_fennec fennec
+///
+/// | Symbol | Implemented | Passed |
+/// |:-------------------------|:-----------:|:------:|
+/// | \ref fennec::graph | 🚧 | 🚧 |
+/// | \ref fennec::object_pool | 🚧 | 🚧 |
+/// | \ref fennec::rdtree | ✅ | ✅ |
+///
+///
+/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
+///
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#endif // FENNEC_CONTAINERS_CONTAINERS_H
\ No newline at end of file
diff --git a/include/fennec/containers/deque.h b/include/fennec/containers/deque.h
index 032a7e2..263105b 100644
--- a/include/fennec/containers/deque.h
+++ b/include/fennec/containers/deque.h
@@ -26,15 +26,40 @@
namespace fennec
{
+///
+///
+/// \brief Data structure defining a double-ended queue.
+///
+/// \details
+/// This behaves the similar to fennec::list, however it does not allow arbitrary access, insertion, or deletion.
+/// It is one of the few data structures in this library that is stable, i.e. pointers to elements do not change.
+///
+/// | Property | Value |
+/// |:----------:|:----------:|
+/// | stable | ✅ |
+/// | dynamic | ✅ |
+/// | homogenous | ✅ |
+/// | distinct | ⛔ |
+/// | ordered | ⛔ |
+/// | space | \f$O(N)\f$ |
+/// | linear | ⛔ |
+/// | access | \f$O(1)\f$ |
+/// | find | \f$O(N)\f$ |
+/// | insertion | \f$O(1)\f$ |
+/// | deletion | \f$O(1)\f$ |
+///
+/// \tparam TypeT value type
template>
struct deque {
// Definitions =========================================================================================================
public:
- using elem_t = TypeT;
+ using value_t = TypeT;
+ class iterator;
+private:
struct node {
- elem_t value;
+ value_t value;
node *prev, *next;
template
@@ -46,11 +71,18 @@ public:
~node() = default;
};
+public:
using alloc_t = allocator_traits::template rebind;
+ using elem_t = node*;
// Constructors ========================================================================================================
+ /// \name Constructors & Destructor
+ /// @{
+
+ ///
+ /// \brief Default Constructor, initializes an empty deque
deque()
: _alloc()
, _first(nullptr)
@@ -58,6 +90,24 @@ public:
, _size(0) {
}
+ ///
+ /// \brief Copy Constructor
+ /// \param deque the deque to copy
+ deque(const deque& deque)
+ : _alloc(deque._alloc)
+ , _first(nullptr)
+ , _last(nullptr)
+ , _size(0) {
+ const elem_t node = deque._first;
+ while (node) {
+ this->push_back(node->value);
+ node = node->next;
+ }
+ }
+
+ ///
+ /// \brief Deque Move Constructor
+ /// \param deque the deque to move
deque(deque&& deque) noexcept
: _alloc(deque._alloc)
, _first(deque._first)
@@ -67,69 +117,128 @@ public:
deque._last = nullptr;
}
+ ///
+ /// \brief Destructor, calls deque::clear
~deque() {
clear();
}
+ /// @}
+
// Properties ==========================================================================================================
- bool empty() const {
+ /// \name Properties
+ /// @{
+
+ ///
+ /// \returns `true` when the deque is empty, `false` otherwise
+ constexpr bool empty() const {
return _size == 0;
}
- size_t size() const {
+ ///
+ /// \returns the number of elements in size()
+ constexpr size_t size() const {
return _size;
}
+ /// @}
+
// Access ==============================================================================================================
- elem_t& front() {
+ /// \name Access
+ /// @{
+
+ ///
+ /// \returns a reference to the first element in the deque
+ value_t& front() {
assert(not empty(), "Attempted to access an empty deque.");
return _first->value;
}
- elem_t& back() {
+ ///
+ /// \returns a const-qualified reference to the first element in the deque
+ const value_t& front() const {
+ assert(not empty(), "Attempted to access an empty deque.");
+ return _first->value;
+ }
+
+ ///
+ /// \returns a reference to the last element in the deque
+ value_t& back() {
assert(not empty(), "Attempted to access an empty deque.");
return _last->value;
}
+ ///
+ /// \returns a const-qualified reference to the last element in the deque
+ const value_t& back() const {
+ assert(not empty(), "Attempted to access an empty deque.");
+ return _last->value;
+ }
-// Insertion ===========================================================================================================
+ /// @}
- void push_front(elem_t&& elem) {
+
+// Modifiers ===========================================================================================================
+
+ /// \name Modifiers
+ /// @{
+
+ ///
+ /// \brief Push Front Move, moves a value to the front of the deque
+ /// \param elem the value to move
+ void push_front(value_t&& elem) {
this->_push_front(elem);
}
- void push_front(const elem_t& elem) {
+ ///
+ /// \brief Push Front Copy, copies a value to the front of the deque
+ /// \param elem the value to copy
+ void push_front(const value_t& elem) {
this->_push_front(elem);
}
+ ///
+ /// \brief Emplace Front, constructs a new value at the front of the deque
+ /// \tparam ArgsT Argument types
+ /// \param args Arguments used to construct the value
template
void emplace_front(ArgsT&&...args) {
this->_push_front(fennec::forward(args)...);
}
- void push_back(elem_t&& elem) {
+
+ ///
+ /// \brief Push Back Move, moves a value to the back of the deque
+ /// \param elem the value to move
+ void push_back(value_t&& elem) {
this->_push_back(elem);
}
- void push_back(const elem_t& elem) {
+ ///
+ /// \brief Push Back Copy, copies a value to the back of the deque
+ /// \param elem the value to copy
+ void push_back(const value_t& elem) {
this->_push_back(elem);
}
+ ///
+ /// \brief Emplace Back, constructs a new value at the back of the deque
+ /// \tparam ArgsT Argument types
+ /// \param args Arguments used to construct the value
template
void emplace_back(ArgsT&&...args) {
this->_push_back(fennec::forward(args)...);
}
-
-// Deletion ============================================================================================================
-
+ ///
+ /// \brief Clears the contents of the deque
void clear() {
- node* it = _first;
+ elem_t it = _first;
while (it) {
- node* next = it->next;
+ elem_t next = it->next;
fennec::destruct(it);
_alloc.deallocate(it);
it = next;
@@ -139,11 +248,13 @@ public:
_size = 0;
}
+ ///
+ /// \brief Erase the First Element
void pop_front() {
if (_first == nullptr) {
return;
}
- node* next = _first->next;
+ elem_t next = _first->next;
fennec::destruct(_first);
_alloc.deallocate(_first);
_first = next;
@@ -151,11 +262,13 @@ public:
--_size;
}
+ ///
+ /// \brief Erase the Last Element
void pop_back() {
if (_last == nullptr) {
return;
}
- node* prev = _last->prev;
+ elem_t prev = _last->prev;
fennec::destruct(_last);
_alloc.deallocate(_last);
_last = prev;
@@ -163,6 +276,15 @@ public:
--_size;
}
+ /// @}
+
+
+// Iteration ===========================================================================================================
+
+ /*
+ * TODO: Decide whether you should be able to iterate over a deque
+ */
+
private:
alloc_t _alloc;
node *_first, *_last;
@@ -170,7 +292,7 @@ private:
template
void _push_front(ArgsT&&...args) {
- node* next = _first;
+ elem_t next = _first;
_first = _alloc.allocate(1);
fennec::construct(_first, nullptr, next, fennec::forward(args)...);
if (next) {
@@ -183,7 +305,7 @@ private:
template
void _push_back(ArgsT&&...args) {
- node* prev = _last;
+ elem_t prev = _last;
_last = _alloc.allocate(1);
fennec::construct(_last, prev, nullptr, fennec::forward(args)...);
if (prev) {
diff --git a/include/fennec/containers/dynarray.h b/include/fennec/containers/dynarray.h
index 652e609..65dee72 100644
--- a/include/fennec/containers/dynarray.h
+++ b/include/fennec/containers/dynarray.h
@@ -40,15 +40,21 @@ namespace fennec
///
///
-/// \brief wrapper for dynamically sized arrays
+/// \brief Wrapper for dynamically sized arrays
/// \details
-/// | Property | Value |
-/// |-----------|:----------:|
-/// | stable | \emoji x |
-/// | access | \f$O(1)\f$ |
-/// | insertion | \f$O(N)\f$ |
-/// | deletion | \f$O(N)\f$ |
-/// | space | \f$O(N)\f$ |
+/// | Property | Value |
+/// |:----------:|:----------:|
+/// | stable | ⛔ |
+/// | dynamic | ✅ |
+/// | homogenous | ✅ |
+/// | distinct | ⛔ |
+/// | ordered | ⛔ |
+/// | space | \f$O(N)\f$ |
+/// | linear | ✅ |
+/// | access | \f$O(1)\f$ |
+/// | find | \f$O(N)\f$ |
+/// | insertion | \f$O(N)\f$ |
+/// | deletion | \f$O(N)\f$ |
///
/// \tparam TypeT value type
template>
@@ -63,13 +69,20 @@ public:
// Constructors ========================================================================================================
+ /// \name Constructors & Destructor
+ /// @{
+
///
/// \brief Default Constructor, initializes an empty allocation.
- constexpr dynarray() : _alloc(8), _size(0) {}
+ constexpr dynarray()
+ : _alloc(8)
+ , _size(0) {
+ }
///
/// \brief Alloc Constructor, initialize empty allocation with allocator instance.
- /// \param alloc An allocator object to copy, for instances where the allocator needs to be initialized with some data.
+ /// \param alloc An allocator object to copy, for instances where the allocator needs to be initialized with some
+ /// data.
constexpr dynarray(const alloc_t& alloc)
: _alloc(8, alloc)
, _size(0) {
@@ -77,14 +90,16 @@ public:
///
/// \brief Alloc Move Constructor, initialize empty allocation with allocator instance.
- /// \param alloc An allocator object to copy, for instances where the allocator needs to be initialized with some data.
+ /// \param alloc An allocator object to copy, for instances where the allocator needs to be initialized with some
+ /// data.
constexpr dynarray(alloc_t&& alloc) noexcept
: _alloc(8, alloc)
, _size(0) {
}
///
- /// \brief Sized Allocation, create an allocation of size `n` elements, initialized with the default constructor.
+ /// \brief Sized Allocation, create an allocation of size `n` elements,
+ /// initialized with the default constructor.
constexpr dynarray(size_t n)
: _alloc(n)
, _size(n)
@@ -96,7 +111,8 @@ public:
}
///
- /// \brief Sized Allocation Alloc Constructor, initializes a dynarray with allocator `alloc` and `n` elements using the default constructor.
+ /// \brief Sized Allocation Alloc Constructor, initializes a dynarray with allocator `alloc` and `n` elements
+ /// using the default constructor.
/// \param n The number of elements
/// \param alloc The allocator object to copy
constexpr dynarray(size_t n, const alloc_t& alloc)
@@ -109,7 +125,8 @@ public:
}
///
- /// \brief Sized Allocation Alloc Move Constructor, initializes a dynarray with allocator `alloc` and `n` elements using the default constructor.
+ /// \brief Sized Allocation Alloc Move Constructor, initializes a dynarray with allocator `alloc` and `n` elements
+ /// using the default constructor.
/// \param n The number of elements
/// \param alloc The allocator object to copy
constexpr dynarray(size_t n, alloc_t&& alloc)
@@ -122,8 +139,9 @@ public:
}
///
- /// \brief Sized Allocation Copy Constructor, Create an allocation of size `n` elements, with each element constructed using the copy constructor
- /// \brief n the number of elements
+ /// \brief Sized Allocation Copy Constructor, Create an allocation of size `n` elements, with each element
+ /// constructed using the copy constructor
+ /// \param n the number of elements
constexpr dynarray(size_t n, const TypeT& val)
: _alloc(n)
, _size(n) {
@@ -143,13 +161,33 @@ public:
/// \param n The number of objects to create
/// \param args The arguments to create each object with
template
- constexpr dynarray(size_t n, ArgsT&&...args) {
- element_t* addr = _alloc.data();
- for(; n > 0; --n, ++addr) {
- fennec::construct(addr, fennec::forward(args)...);
+ constexpr dynarray(size_t n, ArgsT&&...args)
+ : _alloc(n)
+ , _size(n) {
+ for(; n > 0; --n) {
+ fennec::construct(&_alloc[n], fennec::forward(args)...);
}
}
+ ///
+ /// \brief Copy Constructor, uses the copy constructor to copy each element
+ /// \param arr the dynarray to copy
+ constexpr dynarray(const dynarray& arr)
+ : _alloc(arr._size)
+ , _size(arr._size) {
+ for (size_t i = 0; i < _size; ++i) {
+ fennec::construct(&_alloc[i], arr[i]);
+ }
+ }
+
+ ///
+ /// \brief Move Constructor, takes ownership of the allocation
+ /// \param arr the dynarray to move
+ constexpr dynarray(dynarray&& arr)
+ : _alloc(fennec::move(arr._alloc))
+ , _size(arr._size) {
+ }
+
///
/// \brief Default Destructor, destructs all elements and frees the underlying allocation
constexpr ~dynarray() {
@@ -160,9 +198,14 @@ public:
}
}
+ /// @}
+
// Properties ==========================================================================================================
+ /// \name Properties
+ /// @{
+
///
/// \returns The size of the dynarray in elements
constexpr size_t size() const {
@@ -181,9 +224,14 @@ public:
return _size == 0;
}
+ /// @}
+
// Element Access ======================================================================================================
+ /// \name Access
+ /// @{
+
///
/// \brief Array Access Operator
/// \param i The index to access
@@ -226,28 +274,13 @@ public:
return this->operator[](size() - 1);
}
- ///
- /// \brief "Iterator" Begin Function
- /// \returns A pointer to the first element in the dynarray
- constexpr TypeT* begin() { return _alloc.data(); }
-
- ///
- /// \brief "Iterator" End Function
- /// \return A pointer to the address after the last element in the dynarray
- constexpr TypeT* end() { return begin() + _size; }
-
- ///
- /// \brief Const "Iterator" Begin Function
- /// \returns A const qualified pointer to the first element in the dynarray
- constexpr const TypeT* begin() const { return _alloc; }
-
- ///
- /// \brief Const "Iterator" End Function
- /// \return A const qualified pointer to the address after the last element in the dynarray
- constexpr const TypeT* end() const { return begin() + _size; }
+ /// @}
-// Insertion & Deletion ================================================================================================
+// Modifiers ===========================================================================================================
+
+ /// \name Modifiers
+ /// @{
///
/// \brief Move Insertion
@@ -364,6 +397,36 @@ public:
}
}
+ /// @}
+
+
+// Iteration ===========================================================================================================
+
+ /// \name Iteration
+ /// @{
+
+ ///
+ /// \brief "Iterator" Begin Function
+ /// \returns A pointer to the first element in the dynarray
+ constexpr TypeT* begin() { return _alloc.data(); }
+
+ ///
+ /// \brief "Iterator" End Function
+ /// \return A pointer to the address after the last element in the dynarray
+ constexpr TypeT* end() { return begin() + _size; }
+
+ ///
+ /// \brief Const "Iterator" Begin Function
+ /// \returns A const qualified pointer to the first element in the dynarray
+ constexpr const TypeT* begin() const { return _alloc; }
+
+ ///
+ /// \brief Const "Iterator" End Function
+ /// \return A const qualified pointer to the address after the last element in the dynarray
+ constexpr const TypeT* end() const { return begin() + _size; }
+
+ /// @}
+
private:
constexpr void _grow() {
_alloc.creallocate(_alloc.capacity() * 2);
diff --git a/include/fennec/containers/graph.h b/include/fennec/containers/graph.h
index 73fdd82..f883482 100644
--- a/include/fennec/containers/graph.h
+++ b/include/fennec/containers/graph.h
@@ -39,26 +39,54 @@
namespace fennec
{
-template
+///
+/// \brief Graph Data Structure, describes sets of arbitrarily connected nodes
+/// \tparam NodeT The type associated with each node
+/// \tparam WeightT The type associated with each connection
+template
struct graph {
public:
- using weight_t = ConnectionT;
+// Definitions =========================================================================================================
+
+ /// \name Definitions
+ /// @{
+ using weight_t = WeightT;
using node_t = NodeT;
using conn_map_t = dynarray