diff --git a/doxy/Doxyfile b/doxy/Doxyfile index df913ab..26d134c 100644 --- a/doxy/Doxyfile +++ b/doxy/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = fennec # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.0.2 +PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/gdb/fennec/__init__.py b/gdb/fennec/__init__.py index 93a75de..24b31b9 100644 --- a/gdb/fennec/__init__.py +++ b/gdb/fennec/__init__.py @@ -24,6 +24,7 @@ import gdb from . import containers from . import strings from . import memory +from . import utility def register_printers(obj): gdb.printing.register_pretty_printer(obj, containers.printer) diff --git a/gdb/fennec/containers.py b/gdb/fennec/containers.py index c007edb..2fad66c 100644 --- a/gdb/fennec/containers.py +++ b/gdb/fennec/containers.py @@ -19,6 +19,7 @@ import gdb import re from collections import deque +from . import utility # OPTIONAL ============================================================================================================= class OptionalPrinter: @@ -34,7 +35,7 @@ class OptionalPrinter: else: return "{ empty }" -# OPTIONAL ============================================================================================================= +# PAIR ================================================================================================================= class PairPrinter: """Print a fennec::optional""" @@ -48,8 +49,28 @@ class PairPrinter: return ("first", self.val['first']), ("second", self.val['second']) +# TUPLE ================================================================================================================ + +class TuplePrinter: + """Print a fennec::tuple""" + + def __init__(self, val): + self.fields = val.type.fields()[0].type.fields() + self.elems = val + self.count = len(self.fields) + + def to_string(self): + return " { size = " + str(len(self.fields)) + " }" + + def children(self): + return (('[{}]'.format(i), self.elems.cast(self.fields[i].type)['value']) for i in range(self.count)) + + + # ARRAY ================================================================================================================ class ArrayPrinter: + """Print a fennec::array""" + def __init__(self, val): self.val = val @@ -66,6 +87,8 @@ class ArrayPrinter: # DYNARRAY ============================================================================================================= class DynArrayPrinter: + """Print a fennec::dynarray""" + def __init__(self, val): self.val = val @@ -201,6 +224,7 @@ class RDTreePrinter: # SET ================================================================================================================== class SetPrinter: + """Print a fennec::set""" class Iterator: def __init__(self, table, capacity): @@ -244,6 +268,7 @@ class SetPrinter: # MAP ================================================================================================================== class MapPrinter: + """Print a fennec::map""" class Iterator: def __init__(self, table, capacity): @@ -272,12 +297,12 @@ class MapPrinter: if not self.move: self.move = True - return ('key' + str(i), key) + return 'key' + str(i), key else: self.move = False self.index = self.index + 1 self.node = self.node + 1 - return ('value' + str(i), val) + return 'value' + str(i), val def __init__(self, val): self.table = val['_set']['_alloc']['_data'] @@ -303,6 +328,7 @@ def register_printers(): pp = gdb.printing.RegexpCollectionPrettyPrinter("fennec::containers") pp.add_printer('optional', '^fennec::optional<.*>$', OptionalPrinter) pp.add_printer('pair', '^fennec::pair<.*>$', PairPrinter) + pp.add_printer('tuple', '^fennec::tuple<.*>$', TuplePrinter) pp.add_printer('array', '^fennec::array<.*>$', ArrayPrinter) pp.add_printer('dynarray', '^fennec::dynarray<.*>$', DynArrayPrinter) pp.add_printer('list', '^fennec::list<.*>$', ListPrinter) diff --git a/gdb/fennec/utility.py b/gdb/fennec/utility.py new file mode 100644 index 0000000..1adce0b --- /dev/null +++ b/gdb/fennec/utility.py @@ -0,0 +1,20 @@ +# ====================================================================================================================== +# 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 . +# ====================================================================================================================== + +def printMembers(obj): + print(str(dir(obj))) \ No newline at end of file diff --git a/include/fennec/containers/detail/_tuple.h b/include/fennec/containers/detail/_tuple.h index de3cd0a..70a4207 100644 --- a/include/fennec/containers/detail/_tuple.h +++ b/include/fennec/containers/detail/_tuple.h @@ -24,34 +24,28 @@ namespace fennec::detail { -// leaves -template -struct _tuple_leaf { - T value; - template - _tuple_leaf(ArgsT&&...args) : value(args...) { - } +template +struct _tuple_leaf +{ + template + _tuple_leaf(ArgT&& arg) : value(fennec::forward(arg)) {} - constexpr operator T&() { - return value; - } + ~_tuple_leaf() = default; - constexpr operator const T&() const { - return value; - } + T value; }; -// proxy -template +template struct _tuple; -template -struct _tuple, TypesT...> : _tuple_leaf... { +template +struct _tuple, TypesT...> : _tuple_leaf... +{ + template + _tuple(ArgsT&&... args) : _tuple_leaf(fennec::forward(args))... {} - template - _tuple(ArgsT&&...args) : _tuple_leaf(args)... { - } + ~_tuple() = default; }; } diff --git a/include/fennec/containers/tuple.h b/include/fennec/containers/tuple.h index 8fbe501..8f43394 100644 --- a/include/fennec/containers/tuple.h +++ b/include/fennec/containers/tuple.h @@ -36,32 +36,44 @@ template struct tuple; template constexpr typename tuple::template elem_t& get(tuple& x) { using elem_t = typename tuple::template elem_t; - auto& it = static_cast>(x); - return it; + auto& it = *static_cast*>(&x); + return it.value; } template -constexpr const typename tuple::template elem_t& get(tuple& x) { +constexpr const typename tuple::template elem_t& get(const tuple& x) { using elem_t = typename tuple::template elem_t; - auto& it = static_cast>(x); - return it; + const auto& it = *static_cast*>(&x); + return it.value; } -template -struct tuple : detail::_tuple, TypesT...> { - -public: - using base_t = detail::_tuple, TypesT...>; +template +struct tuple : public detail::_tuple, TypesT...> +{ + using base_t = detail::_tuple, TypesT...>; template - using elem_t = nth_element; + using elem_t = typename nth_element::type; template - constexpr tuple(ArgsT&&...args) : base_t(args...) { + tuple(ArgsT&&...args) + : base_t(fennec::forward(args)...) { + } + + tuple(const tuple& cpy) + : base_t(cpy) { + } + + tuple(tuple&& cpy) + : base_t(cpy) { } }; +// This is needed for +template +tuple(TypesT...) -> tuple; + } #endif // FENNEC_CONTAINERS_TUPLE_H diff --git a/include/fennec/lang/detail/_type_sequences.h b/include/fennec/lang/detail/_type_sequences.h index eba03cf..614cc03 100644 --- a/include/fennec/lang/detail/_type_sequences.h +++ b/include/fennec/lang/detail/_type_sequences.h @@ -32,8 +32,8 @@ namespace fennec::detail template struct _nth_element : conditional< - n == i, type_identity, - _nth_element + n == i, HeadT, + typename _nth_element::type > {}; } diff --git a/include/fennec/langproc/strings/string.h b/include/fennec/langproc/strings/string.h index 73eb71c..3bf4bfa 100644 --- a/include/fennec/langproc/strings/string.h +++ b/include/fennec/langproc/strings/string.h @@ -86,10 +86,10 @@ public: /// /// \details adds additional character for null termination. Ignores whether str is null-terminated. /// This constructor makes the assumption that `n` is the intended number of characters. - constexpr _string(const char* str, size_t n) - : _str(n + 1) { + constexpr _string(char* str, size_t n) + : _str(str[n - 1] == '\0' ? n : n + 1) { fennec::memcpy(_str.data(), str, n); - _str[n] = '\0'; + if (str[n - 1] != '\0') _str[n] = '\0'; } /// @@ -97,7 +97,30 @@ public: /// \param str the buffer to wrap /// \tparam n the number of characters in the buffer plus the null terminator template - constexpr _string(char(&str)[n]) + explicit constexpr _string(char(&str)[n]) + : _str(str, n) { + assert(_str[n - 1] == '\0', "Invalid NTBS."); + } + + /// + /// \brief Buffer Copy Constructor + /// \param str the buffer to copy + /// \param n 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 `n` is the intended number of characters. + constexpr _string(const char* str, size_t n) + : _str(str[n - 1] == '\0' ? n : n + 1) { + fennec::memcpy(_str.data(), str, n); + if (str[n - 1] != '\0') _str[n] = '\0'; + } + + /// + /// \brief Buffer Constructor, wraps the provided C-Style string + /// \param str the buffer to wrap + /// \tparam n the number of characters in the buffer plus the null terminator + template + explicit constexpr _string(const char(&str)[n]) : _str(str, n) { assert(_str[n - 1] == '\0', "Invalid NTBS."); } @@ -385,7 +408,7 @@ public: /// \returns constexpr _string operator+(char c) const { // Copy contents with one additional byte. - _string res(_str.data(), _str.size()); + _string res(_str.data(), _str.size() + 1); res[size()] = c; // Set the last character to c return res; } diff --git a/planning/CONTAINERS.md b/planning/CONTAINERS.md index b78f532..d4d2a1a 100644 --- a/planning/CONTAINERS.md +++ b/planning/CONTAINERS.md @@ -29,7 +29,7 @@ Library and Template Library. | Symbol | Implemented | Passed | |:-------------------------------------|:-----------:|:------:| | pair | ✔ | ✔ | -| tuple | ⭕ | ❌ | +| tuple | ⭕ | ⭕ | | optional | ✔ | ✔ | | variant | ❌ | ❌ | | any | ❌ | ❌ | diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index aff97e5..c935096 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -34,6 +34,7 @@ add_executable(fennec-test main.cpp tests/containers/test_map.h tests/containers/test_rdtree.h tests/containers/test_list.h + tests/containers/test_tuple.h ) target_compile_definitions(fennec-test PUBLIC FENNEC_TEST_CWD="${CMAKE_SOURCE_DIR}/bin/${FENNEC_BUILD_NAME}" diff --git a/test/tests/containers/test_tuple.h b/test/tests/containers/test_tuple.h new file mode 100644 index 0000000..996c1c4 --- /dev/null +++ b/test/tests/containers/test_tuple.h @@ -0,0 +1,43 @@ +// ===================================================================================================================== +// fennec, a free and open source game engine +// Copyright © 2025 Medusa Slockbower +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// ===================================================================================================================== + +#ifndef FENNEC_TEST_CONTAINERS_TUPLE_H +#define FENNEC_TEST_CONTAINERS_TUPLE_H +#include +#include + +namespace fennec +{ + +namespace test +{ + +inline void fennec_test_containers_tuple() { + string str{ "Hello World!" }; + tuple test { 0, 0.5f, str }; + + fennec_test_run(get<0>(test), 0); + fennec_test_run(get<1>(test), 0.5f); + fennec_test_run(get<2>(test), str); +} + +} + +} + +#endif // FENNEC_TEST_CONTAINERS_TUPLE_H \ No newline at end of file diff --git a/test/tests/test_containers.h b/test/tests/test_containers.h index 0aaad91..2ea99cb 100644 --- a/test/tests/test_containers.h +++ b/test/tests/test_containers.h @@ -26,6 +26,7 @@ #include "containers/test_optional.h" #include "containers/test_rdtree.h" #include "containers/test_set.h" +#include "containers/test_tuple.h" namespace fennec::test { @@ -37,6 +38,11 @@ namespace fennec::test fennec_test_containers_optional(); fennec_test_spacer(3); + fennec_test_subheader("tuple tests"); + fennec_test_spacer(2); + fennec_test_containers_tuple(); + fennec_test_spacer(3); + fennec_test_subheader("array tests"); fennec_test_spacer(2); fennec_test_containers_array();