diff --git a/CMakeLists.txt b/CMakeLists.txt
index 44d2ea1..b2c7ddc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -31,6 +31,7 @@ set(FENNEC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
# include scripts
include("${FENNEC_SOURCE_DIR}/cmake/platform.cmake")
include("${FENNEC_SOURCE_DIR}/cmake/build.cmake")
+include("${FENNEC_SOURCE_DIR}/cmake/compiler.cmake")
# find dependencies
find_package(Doxygen)
@@ -170,6 +171,9 @@ add_library(fennec STATIC
${FENNEC_EXTRA_SOURCES}
+ include/fennec/lang/type_operators.h
+ include/fennec/containers/tuple.h
+ include/fennec/containers/detail/__tuple.h
)
add_dependencies(fennec metaprogramming)
diff --git a/cmake/compiler.cmake b/cmake/compiler.cmake
index df4c55a..1599f51 100644
--- a/cmake/compiler.cmake
+++ b/cmake/compiler.cmake
@@ -16,8 +16,6 @@
# along with this program. If not, see .
# ======================================================================================================================
-list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_COMPILER_GCC=0)
-
if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")
set(FENNEC_COMPILER "GCC")
include("${FENNEC_SOURCE_DIR}/cmake/gcc.cmake")
diff --git a/cmake/gcc.cmake b/cmake/gcc.cmake
index e916f64..6e5a838 100644
--- a/cmake/gcc.cmake
+++ b/cmake/gcc.cmake
@@ -20,4 +20,4 @@ add_compile_options("-mxsave" "-Wall" "-Wextra" "-pedantic" "-Werror")
set(FENNEC_PRIVATE_LINK_OPTIONS "-nostdlib" "-fno-exceptions" "-fno-rtti" "-fdiagnostics-all-candidates")
-list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_COMPILER=FENNEC_COMPILER_GCC)
\ No newline at end of file
+list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_COMPILER_GCC=1)
\ No newline at end of file
diff --git a/cmake/linux.cmake b/cmake/linux.cmake
index 8d5fad0..dadf5f0 100644
--- a/cmake/linux.cmake
+++ b/cmake/linux.cmake
@@ -18,6 +18,9 @@
macro(fennec_check_platform)
+ # unix
+ include("${FENNEC_SOURCE_DIR}/cmake/unix.cmake")
+
# compile definitions
list(APPEND FENNEC_COMPILE_DEFINITIONS
FENNEC_PLATFORM_NAME="Linux"
@@ -30,8 +33,8 @@ macro(fennec_check_platform)
)
# includes
- include("${FENNEC_SOURCE_DIR}/cmake/libwayland.cmake")
+ include("${FENNEC_SOURCE_DIR}/cmake/wayland.cmake")
# tests
- fennec_check_libwayland()
+ fennec_check_wayland()
endmacro()
\ No newline at end of file
diff --git a/cmake/libwayland.cmake b/cmake/wayland.cmake
similarity index 98%
rename from cmake/libwayland.cmake
rename to cmake/wayland.cmake
index ca69324..da49b40 100644
--- a/cmake/libwayland.cmake
+++ b/cmake/wayland.cmake
@@ -18,7 +18,7 @@
# https://gist.github.com/mariobadr/acc3c8adf4b4e722705be38c3deac59a
-macro(fennec_check_libwayland)
+macro(fennec_check_wayland)
set(WAYLAND_CLIENT_FOUND 0)
find_path(
diff --git a/doxy/Doxyfile b/doxy/Doxyfile
index 26d134c..df913ab 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 =
+PROJECT_NUMBER = 1.0.2
# 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/include/fennec/containers/detail/__tuple.h b/include/fennec/containers/detail/__tuple.h
new file mode 100644
index 0000000..c6fe199
--- /dev/null
+++ b/include/fennec/containers/detail/__tuple.h
@@ -0,0 +1,59 @@
+// =====================================================================================================================
+// 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_CONTAINERS_DETAIL_TUPLE_H
+#define FENNEC_CONTAINERS_DETAIL_TUPLE_H
+#include
+#include
+
+namespace fennec::detail
+{
+
+// leaves
+template
+struct __tuple_leaf {
+ T value;
+
+ template
+ __tuple_leaf(ArgsT&&...args) : value(args...) {
+ }
+
+ constexpr operator T&() {
+ return value;
+ }
+
+ constexpr operator const T&() const {
+ return value;
+ }
+};
+
+// proxy
+template
+struct __tuple;
+
+template
+struct __tuple, TypesT...> : __tuple_leaf... {
+
+ template
+ __tuple(ArgsT&&...args) : __tuple_leaf(args)... {
+ }
+};
+
+}
+
+#endif // FENNEC_CONTAINERS_DETAIL_TUPLE_H
diff --git a/include/fennec/containers/map.h b/include/fennec/containers/map.h
index 23ff305..34aca16 100644
--- a/include/fennec/containers/map.h
+++ b/include/fennec/containers/map.h
@@ -27,6 +27,24 @@ namespace fennec
// TODO: Document
+/* Ramblings
+ *
+ * Definitions:
+ * user = Programmer using this data structure
+ *
+ * The STL unordered-map is very contrived. Some of its functionality encourages younger programmers to use
+ * the exception model. Ideally, I would like this structure to never throw an error with typical use.
+ *
+ * The array access operator is, in my opinion, poorly implemented. I do not think that this operator should handle
+ * insertions and should handle access only. This is the only data structure in STL that has this behavior, no other
+ * data structure modifies contents by inherently calling operator[].
+ *
+ * Currently, I am considering implementing this as the following:
+ * Access will be handled only via operator[]. Return value will be an optional which forces user validation.
+ * Insertions will be handled only via an insert/emplace function.
+ * Deletions will be handled only via an erase function.
+*/
+
template, typename Alloc = allocator>>
struct map {
public:
@@ -36,13 +54,136 @@ public:
using alloc_t = typename allocator_traits::template rebind;
using hash_t = Hash;
- map() = default;
- ~map() = default;
+ // We only want to hash the key
+ struct key_hash : hash_t {
+ constexpr size_t operator()(const elem_t& p) const {
+ return hash_t::operator()(p.first);
+ }
+ };
+ // We only want to compare the keys
+ struct node_equals : equality {
+ constexpr bool operator()(const elem_t& a, const elem_t& b) const {
+ return equality::operator()(a.first, b.first);
+ }
+ };
+
+ constexpr map() = default;
+ constexpr ~map() = default;
+
+ constexpr value_t* operator[](const KeyT& key) {
+ union U { // Hacky way of avoiding constructing the value, TODO: Check for warnings on other compilers
+ pair root;
+ pair val;
+
+ ~U() {
+ root.~pair();
+ }
+ } trick = { .root = { key, 0 } };
+ auto it = _set.find(trick.val);
+ if (it == _set.end()) {
+ return nullptr;
+ }
+ return &_set.at(it)->second;
+ }
+
+ constexpr const value_t* operator[](const KeyT& key) const {
+ union U { // Hacky way of avoiding constructing the value, TODO: Check for warnings on other compilers
+ pair root;
+ pair val;
+
+ ~U() {
+ root.~pair();
+ }
+ } trick = { .root = { key, 0 } }; // Only initialize root
+ auto it = _set.find(trick.val);
+ if (it == _set.end()) {
+ return nullptr;
+ }
+ return &_set.at(it)->second;
+ }
+
+ template
+ constexpr value_t* operator[](ArgsT&&...args) {
+ union U { // Hacky way of avoiding constructing the value, TODO: Check for warnings on other compilers
+ pair root;
+ pair val;
+
+ ~U() {
+ root.~pair();
+ }
+ } trick = { .root = { key_t(fennec::forward(args)...), 0 } }; // Only initialize root
+ auto it = _set.find(trick.val);
+ if (it == _set.end()) {
+ return nullptr;
+ }
+ return &_set.at(it)->second;
+ }
+
+ template
+ constexpr const value_t* operator[](ArgsT&&...args) const {
+ union U { // Hacky way of avoiding constructing the value, TODO: Check for warnings on other compilers
+ pair root;
+ pair val;
+
+ ~U() {
+ root.~pair();
+ }
+ } trick = { .root = { key_t(fennec::forward(args)...), 0 } }; // Only initialize root
+ auto it = _set.find(trick.val);
+ if (it == _set.end()) {
+ return nullptr;
+ }
+ return &_set.at(it)->second;
+ }
+
+ constexpr void insert(elem_t&& pair) {
+ auto it = _set.find(pair);
+ if (it == _set.end()) {
+ _set.at(it)->second = fennec::move(pair.second);
+ return;
+ }
+ _set.insert(fennec::forward(pair));
+ }
+
+ template
+ constexpr void emplace(ArgsT&&...args) {
+ _set.insert(elem_t(args...));
+ }
+
+ constexpr void erase(KeyT&& key) {
+ union U { // Hacky way of avoiding constructing the value, TODO: Check for warnings on other compilers
+ pair root;
+ pair val;
+
+ ~U() {
+ root.~pair();
+ }
+ } trick = { .root = { fennec::forward(key), 0 } };
+ _set.erase(trick.val);
+ }
+
+ constexpr void erase(const KeyT& key) {
+ KeyT val = key;
+ erase(fennec::move(val));
+ }
+
+ template
+ constexpr void erase(ArgsT&&...args) {
+ union U { // Hacky way of avoiding constructing the value, TODO: Check for warnings on other compilers
+ pair root;
+ pair val;
+
+ ~U() {
+ root.~pair();
+ }
+ } trick = { .root = { KeyT(fennec::forward(args)...), 0 } };
+ _set.erase(trick.val);
+ }
private:
- set _set;
+ set _set;
};
}
diff --git a/include/fennec/containers/optional.h b/include/fennec/containers/optional.h
index a56cde2..0be5898 100644
--- a/include/fennec/containers/optional.h
+++ b/include/fennec/containers/optional.h
@@ -39,6 +39,10 @@ template
struct optional {
public:
// Constructors ========================================================================================================
+ using reference_t = T&;
+ using pointer_t = add_pointer_t>;
+ using const_reference_t = const T&;
+ using const_pointer_t = const add_pointer_t>;
///
/// \brief Default Constructor
@@ -203,11 +207,11 @@ public:
return _set;
}
- constexpr T* operator->() noexcept {
+ constexpr pointer_t operator->() noexcept {
return _set ? &_val : nullptr;
}
- constexpr const T* operator->() const noexcept {
+ constexpr const pointer_t operator->() const noexcept {
return _set ? &_val : nullptr;
}
diff --git a/include/fennec/containers/pair.h b/include/fennec/containers/pair.h
index 6a447a7..06fcc27 100644
--- a/include/fennec/containers/pair.h
+++ b/include/fennec/containers/pair.h
@@ -19,6 +19,7 @@
#ifndef FENNEC_CONTAINERS_PAIR_H
#define FENNEC_CONTAINERS_PAIR_H
+#include
#include
#include
@@ -42,6 +43,12 @@ struct pair {
, second(fennec::forward(y)) {
}
+ template
+ constexpr pair(Arg1T&& arg1, Arg2T&& arg2)
+ : first(fennec::forward(arg1))
+ , second(fennec::forward(arg2)) {
+ }
+
constexpr pair(const pair&) = default;
constexpr pair(pair&&) noexcept = default;
diff --git a/include/fennec/containers/set.h b/include/fennec/containers/set.h
index f1818c4..1a01d4e 100644
--- a/include/fennec/containers/set.h
+++ b/include/fennec/containers/set.h
@@ -22,6 +22,7 @@
// https://programming.guide/robin-hood-hashing.html
#include
+#include
#include
#include
#include
@@ -31,15 +32,17 @@ namespace fennec
// TODO: Document
-template, class Alloc = allocator>
+template, class Equals = equality, class Alloc = allocator>
struct set {
public:
using alloc_t = typename allocator_traits::template rebind;
using hash_t = Hash;
+ using equal_t = Equals;
using elem_t = T;
class iterator;
static constexpr size_t npos = -1;
+ static constexpr double default_load = 0.8;
private:
struct node {
@@ -54,60 +57,71 @@ public:
constexpr set()
: _alloc()
, _hash()
- , _size(0) {
+ , _size(0)
+ , _load(default_load) {
};
constexpr set(const hash_t& hash)
: _alloc()
, _hash(hash)
- , _size(0) {
+ , _size(0)
+ , _load(default_load) {
}
constexpr set(hash_t&& hash) noexcept
: _alloc()
, _hash(hash)
- , _size(0) {
+ , _size(0)
+ , _load(default_load) {
}
constexpr set(const alloc_t& alloc)
: _alloc(alloc)
, _hash()
- , _size(0) {
+ , _size(0)
+ , _load(default_load) {
}
constexpr set(alloc_t&& alloc) noexcept
: _alloc(alloc)
, _hash()
- , _size(0) {
+ , _size(0)
+ , _load(default_load) {
}
constexpr set(const hash_t& hash, const alloc_t& alloc)
: _alloc(alloc)
, _hash(hash)
- , _size(0) {
+ , _size(0)
+ , _load(default_load) {
}
constexpr set(const hash_t& hash, alloc_t&& alloc) noexcept
: _alloc(alloc)
, _hash(hash)
- , _size(0) {
+ , _size(0)
+ , _load(default_load) {
}
constexpr set(hash_t&& hash, alloc_t&& alloc) noexcept
: _alloc(alloc)
, _hash(hash)
- , _size(0) {
+ , _size(0)
+ , _load(default_load) {
}
constexpr set(hash_t&& hash, const alloc_t& alloc) noexcept
: _alloc(alloc)
, _hash(hash)
- , _size(0) {}
+ , _size(0)
+ , _load(default_load) {
+ }
constexpr set(const set& set)
: _alloc(set._alloc)
, _hash(set._hash)
- , _size(set._size) {
+ , _size(set._size)
+ , _load(default_load) {
}
constexpr set(set&& set) noexcept
@@ -127,7 +141,7 @@ public:
}
constexpr void insert(elem_t&& val) {
- if (_size >= capacity()) { // expand when full
+ if (_size == 0 or double(_size) / capacity() >= _load) { // expand when full
_expand();
}
@@ -135,7 +149,7 @@ public:
size_t i = _hash(value) % capacity(); // Initial search index
int psl = 0;
while (_alloc[i].value) { // Search for empty cell
- if (*_alloc[i].value == val) { // Check to see if this element is already inserted
+ if (_equal(*_alloc[i].value, val)) { // Check to see if this element is already inserted
return;
}
if (psl >= _alloc[i].psl) { // When psl is higher, swap
@@ -165,8 +179,8 @@ public:
int psl = 0;
// Loop while there is a value and its psl is greater than our probe
- while (_alloc[i].value && _alloc[i].psl > psl) {
- if (*_alloc[i].value == val) {
+ while (_alloc[i].value && _alloc[i].psl <= psl) {
+ if (_equal(*_alloc[i].value, val)) {
return iterator(this, i);
}
i = (i + 1) % capacity(); ++psl;
@@ -175,6 +189,20 @@ public:
return iterator(this, npos);
}
+ constexpr elem_t* at(const iterator& it) {
+ size_t i = it._i;
+ if (i >= capacity()) return nullptr;
+ if (not _alloc[i].value) return nullptr;
+ return &*_alloc[i].value;
+ }
+
+ constexpr const elem_t* at(const iterator& it) const {
+ size_t i = it._i;
+ if (i >= capacity()) return nullopt;
+ if (not _alloc[i].value) return nullopt;
+ return &*_alloc[i].value;
+ }
+
constexpr bool contains(const elem_t& val) const {
return this->find(val) != end();
}
@@ -251,6 +279,7 @@ public:
private:
const set* _set;
size_t _i;
+ friend set;
};
constexpr iterator begin() const {
@@ -271,10 +300,9 @@ public:
private:
constexpr void _expand() {
set cpy; // Create a new set
- cpy._alloc.allocate(
+ cpy._alloc.callocate(
fennec::next_prime2(_alloc.capacity())
);
- fennec::memset(cpy._alloc.data(), 0, cpy._alloc.size());
// rehash
for (size_t i = 0; i < capacity(); ++i) {
@@ -289,7 +317,9 @@ private:
allocation _alloc;
hash_t _hash;
+ equal_t _equal;
size_t _size;
+ double _load;
};
}
diff --git a/include/fennec/containers/tuple.h b/include/fennec/containers/tuple.h
new file mode 100644
index 0000000..45c6556
--- /dev/null
+++ b/include/fennec/containers/tuple.h
@@ -0,0 +1,64 @@
+// =====================================================================================================================
+// 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_CONTAINERS_TUPLE_H
+#define FENNEC_CONTAINERS_TUPLE_H
+
+#include
+#include
+
+namespace fennec
+{
+
+// TODO: Document
+
+template struct tuple;
+
+
+template
+typename tuple::template elem_t& get(tuple& x) {
+ using elem_t = typename tuple::template elem_t;
+ auto it = static_cast>(x);
+ return it;
+}
+
+template
+const typename tuple::template elem_t& get(tuple& x) {
+ using elem_t = typename tuple::template elem_t;
+ auto& it = static_cast>(x);
+ return it;
+}
+
+
+template
+struct tuple : detail::__tuple, TypesT...> {
+
+public:
+ using base_t = detail::__tuple, TypesT...>;
+
+ template
+ using elem_t = nth_element;
+
+ template
+ tuple(ArgsT&&...args) : base_t(args...) {
+ }
+};
+
+}
+
+#endif // FENNEC_CONTAINERS_TUPLE_H
diff --git a/include/fennec/fproc/strings/cstring.h b/include/fennec/fproc/strings/cstring.h
index bddb0f1..9392066 100644
--- a/include/fennec/fproc/strings/cstring.h
+++ b/include/fennec/fproc/strings/cstring.h
@@ -25,6 +25,7 @@
#include
#include
+#include
namespace fennec
{
@@ -303,6 +304,13 @@ private:
bool _const;
};
+template<>
+struct hash : hash {
+ constexpr size_t operator()(const cstring& str) {
+ return hash::operator()(byte_array(*str, str.size()));
+ }
+};
+
}
#endif // FENNEC_FPROC_STRINGS_CSTRING_H
diff --git a/include/fennec/fproc/strings/string.h b/include/fennec/fproc/strings/string.h
index 29daa1e..8ff8d89 100644
--- a/include/fennec/fproc/strings/string.h
+++ b/include/fennec/fproc/strings/string.h
@@ -154,7 +154,7 @@ public:
/// \param i the index to access
/// \returns a copy of the character
constexpr char operator[](int i) const {
- assertd(i >= 0 && i < size(), "Array Out of Bounds");
+ assertd(i >= 0 && (size_t)i < size(), "Array Out of Bounds");
return _str[i];
}
@@ -431,6 +431,13 @@ private:
alloc_t _str;
};
+template<>
+struct hash : hash {
+ constexpr size_t operator()(const string& str) const {
+ return hash::operator()(byte_array(*str, str.size()));
+ }
+};
+
}
diff --git a/include/fennec/lang/compare.h b/include/fennec/lang/compare.h
new file mode 100644
index 0000000..649d864
--- /dev/null
+++ b/include/fennec/lang/compare.h
@@ -0,0 +1,123 @@
+// =====================================================================================================================
+// 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_LANG_COMPARE_H
+#define FENNEC_LANG_COMPARE_H
+
+#include
+
+namespace fennec
+{
+
+// equality ============================================================================================================
+
+template struct equality;
+
+template requires has_equals_v
+struct equality {
+ constexpr bool operator()(const T0& x, const T1& y) const {
+ return x == y;
+ }
+};
+
+template requires(not has_equals_v
+ and has_less_v and has_less_v)
+struct equality {
+ constexpr bool operator()(const T0& x, const T1& y) const {
+ return not(x < y) and not(y < x);
+ }
+};
+
+template requires(not(has_equals_v)
+ and(not has_less_v or not has_less_v)
+ and(has_greater_v and has_greater_v))
+struct equality {
+ constexpr bool operator()(const T0& x, const T1& y) const {
+ return not(x > y) and not(y > x);
+ }
+};
+
+
+// inequality ==========================================================================================================
+
+template struct inequality;
+
+template requires has_nequals_v
+struct inequality {
+ constexpr bool operator()(const T0& x, const T1& y) const {
+ return x != y;
+ }
+};
+
+template requires has_less_v and has_less_v
+struct inequality {
+ constexpr bool operator()(const T0& x, const T1& y) const {
+ return (x < y) or (y < x);
+ }
+};
+
+template requires has_greater_v and has_greater_v
+struct inequality {
+ constexpr bool operator()(const T0& x, const T1& y) const {
+ return (x > y) or (y > x);
+ }
+};
+
+
+// less ================================================================================================================
+
+template requires has_less_v
+struct less {
+ constexpr bool operator()(const T0& x, const T1& y) const {
+ return x < y;
+ }
+};
+
+
+// less_equal ==========================================================================================================
+
+template requires has_less_equals_v
+struct less_equals {
+ constexpr bool operator()(const T0& x, const T1& y) const {
+ return x <= y;
+ }
+};
+
+
+// less ================================================================================================================
+
+template requires has_greater_v
+struct greater {
+ constexpr bool operator()(const T0& x, const T1& y) const {
+ return x < y;
+ }
+};
+
+
+// less_equal ==========================================================================================================
+
+template requires has_greater_equals_v
+struct greater_equals {
+ constexpr bool operator()(const T0& x, const T1& y) const {
+ return x <= y;
+ }
+};
+
+}
+
+#endif // FENNEC_LANG_COMPARE_H
diff --git a/include/fennec/lang/detail/__bits.h b/include/fennec/lang/detail/__bits.h
index 2ce0c5c..7540f7d 100644
--- a/include/fennec/lang/detail/__bits.h
+++ b/include/fennec/lang/detail/__bits.h
@@ -21,123 +21,118 @@
#include
-namespace fennec
+namespace fennec::detail
{
-namespace detail
-{
-
-// helper for bitwise and for 1 byte
-constexpr size_t __bit_and_8(void* dst, const void* src) {
- *static_cast(dst) = *static_cast(dst) & *static_cast(src); return 1;
-}
-
-// helper for bitwise and 2 bytes at once
-constexpr size_t __bit_and_16(void* dst, const void* src) {
- *static_cast(dst) = *static_cast(dst) & *static_cast(src); return 2;
-}
-
-// helper for bitwise and 4 bytes at once
-constexpr size_t __bit_and_32(void* dst, const void* src) {
- *static_cast(dst) = *static_cast(dst) & *static_cast(src); return 4;
-}
-
-// helper for bitwise and 8 bytes at once
-constexpr size_t __bit_and_64(void* dst, const void* src) {
- *static_cast(dst) = *static_cast(dst) & *static_cast(src); return 8;
-}
-
-// helper for selecting size
-constexpr size_t __bit_and(void* dst, const void* src, size_t n) {
- switch (n) {
- case 0:
- return 0;
- case 1:
- return __bit_and_8(dst, src);
- case 2: case 3:
- return __bit_and_16(dst, src);
- case 4: case 5: case 6: case 7:
- return __bit_and_32(dst, src);
- default:
- return __bit_and_64(dst, src);
+ // helper for bitwise and for 1 byte
+ constexpr size_t __bit_and_8(void* dst, const void* src) {
+ *static_cast(dst) = *static_cast(dst) & *static_cast(src); return 1;
}
-}
-
-// helper for bitwise or for 1 byte
-constexpr size_t __bit_or_8(void* dst, const void* src) {
- *static_cast(dst) = *static_cast(dst) | *static_cast(src); return 1;
-}
-
-// helper for bitwise or 2 bytes at once
-constexpr size_t __bit_or_16(void* dst, const void* src) {
- *static_cast(dst) = *static_cast(dst) | *static_cast(src); return 2;
-}
-
-// helper for bitwise or 4 bytes at once
-constexpr size_t __bit_or_32(void* dst, const void* src) {
- *static_cast(dst) = *static_cast(dst) | *static_cast(src); return 4;
-}
-
-// helper for bitwise or 8 bytes at once
-constexpr size_t __bit_or_64(void* dst, const void* src) {
- *static_cast(dst) = *static_cast(dst) | *static_cast(src); return 8;
-}
-
-// helper for selecting size
-constexpr size_t __bit_or(void* dst, const void* src, size_t n) {
- switch (n) {
- case 0:
- return 0;
- case 1:
- return __bit_or_8(dst, src);
- case 2: case 3:
- return __bit_or_16(dst, src);
- case 4: case 5: case 6: case 7:
- return __bit_or_32(dst, src);
- default:
- return __bit_or_64(dst, src);
+ // helper for bitwise and 2 bytes at once
+ constexpr size_t __bit_and_16(void* dst, const void* src) {
+ *static_cast(dst) = *static_cast(dst) & *static_cast(src); return 2;
}
-}
-
-// helper for bitwise and 1 byte
-constexpr size_t __bit_xor_8(void* dst, const void* src) {
- *static_cast(dst) = *static_cast(dst) ^ *static_cast(src); return 1;
-}
-
-// helper for bitwise xor 2 bytes at once
-constexpr size_t __bit_xor_16(void* dst, const void* src) {
- *static_cast(dst) = *static_cast(dst) ^ *static_cast(src); return 2;
-}
-
-// helper for bitwise xor 4 bytes at once
-constexpr size_t __bit_xor_32(void* dst, const void* src) {
- *static_cast(dst) = *static_cast(dst) ^ *static_cast(src); return 4;
-}
-
-// helper for bitwise xor 8 bytes at once
-constexpr size_t __bit_xor_64(void* dst, const void* src) {
- *static_cast(dst) = *static_cast(dst) ^ *static_cast(src); return 8;
-}
-
-// helper for selecting size
-constexpr size_t __bit_xor(void* dst, const void* src, size_t n) {
- switch (n) {
- case 0:
- return 0;
- case 1:
- return __bit_xor_8(dst, src);
- case 2: case 3:
- return __bit_xor_16(dst, src);
- case 4: case 5: case 6: case 7:
- return __bit_xor_32(dst, src);
- default:
- return __bit_xor_64(dst, src);
+ // helper for bitwise and 4 bytes at once
+ constexpr size_t __bit_and_32(void* dst, const void* src) {
+ *static_cast(dst) = *static_cast(dst) & *static_cast(src); return 4;
}
-}
-}
+ // helper for bitwise and 8 bytes at once
+ constexpr size_t __bit_and_64(void* dst, const void* src) {
+ *static_cast(dst) = *static_cast(dst) & *static_cast(src); return 8;
+ }
+
+ // helper for selecting size
+ constexpr size_t __bit_and(void* dst, const void* src, size_t n) {
+ switch (n) {
+ case 0:
+ return 0;
+ case 1:
+ return __bit_and_8(dst, src);
+ case 2: case 3:
+ return __bit_and_16(dst, src);
+ case 4: case 5: case 6: case 7:
+ return __bit_and_32(dst, src);
+ default:
+ return __bit_and_64(dst, src);
+ }
+ }
+
+
+ // helper for bitwise or for 1 byte
+ constexpr size_t __bit_or_8(void* dst, const void* src) {
+ *static_cast(dst) = *static_cast(dst) | *static_cast(src); return 1;
+ }
+
+ // helper for bitwise or 2 bytes at once
+ constexpr size_t __bit_or_16(void* dst, const void* src) {
+ *static_cast(dst) = *static_cast(dst) | *static_cast(src); return 2;
+ }
+
+ // helper for bitwise or 4 bytes at once
+ constexpr size_t __bit_or_32(void* dst, const void* src) {
+ *static_cast(dst) = *static_cast(dst) | *static_cast(src); return 4;
+ }
+
+ // helper for bitwise or 8 bytes at once
+ constexpr size_t __bit_or_64(void* dst, const void* src) {
+ *static_cast(dst) = *static_cast(dst) | *static_cast(src); return 8;
+ }
+
+ // helper for selecting size
+ constexpr size_t __bit_or(void* dst, const void* src, size_t n) {
+ switch (n) {
+ case 0:
+ return 0;
+ case 1:
+ return __bit_or_8(dst, src);
+ case 2: case 3:
+ return __bit_or_16(dst, src);
+ case 4: case 5: case 6: case 7:
+ return __bit_or_32(dst, src);
+ default:
+ return __bit_or_64(dst, src);
+ }
+ }
+
+
+ // helper for bitwise and 1 byte
+ constexpr size_t __bit_xor_8(void* dst, const void* src) {
+ *static_cast(dst) = *static_cast(dst) ^ *static_cast(src); return 1;
+ }
+
+ // helper for bitwise xor 2 bytes at once
+ constexpr size_t __bit_xor_16(void* dst, const void* src) {
+ *static_cast(dst) = *static_cast(dst) ^ *static_cast(src); return 2;
+ }
+
+ // helper for bitwise xor 4 bytes at once
+ constexpr size_t __bit_xor_32(void* dst, const void* src) {
+ *static_cast(dst) = *static_cast(dst) ^ *static_cast(src); return 4;
+ }
+
+ // helper for bitwise xor 8 bytes at once
+ constexpr size_t __bit_xor_64(void* dst, const void* src) {
+ *static_cast(dst) = *static_cast(dst) ^ *static_cast(src); return 8;
+ }
+
+ // helper for selecting size
+ constexpr size_t __bit_xor(void* dst, const void* src, size_t n) {
+ switch (n) {
+ case 0:
+ return 0;
+ case 1:
+ return __bit_xor_8(dst, src);
+ case 2: case 3:
+ return __bit_xor_16(dst, src);
+ case 4: case 5: case 6: case 7:
+ return __bit_xor_32(dst, src);
+ default:
+ return __bit_xor_64(dst, src);
+ }
+ }
}
diff --git a/include/fennec/lang/detail/__numeric_transforms.h b/include/fennec/lang/detail/__numeric_transforms.h
index 9cc134a..b98d433 100644
--- a/include/fennec/lang/detail/__numeric_transforms.h
+++ b/include/fennec/lang/detail/__numeric_transforms.h
@@ -22,42 +22,37 @@
#include
#include
-namespace fennec
+namespace fennec::detail
{
-namespace detail
-{
+ template struct __make_unsigned : type_identity {};
-template struct __make_unsigned : type_identity {};
-
-template<> struct __make_unsigned : type_identity {};
-template<> struct __make_unsigned : type_identity {};
-template<> struct __make_unsigned : type_identity {};
-template<> struct __make_unsigned : type_identity {};
-template<> struct __make_unsigned : type_identity {};
-template<> struct __make_unsigned : type_identity {};
-template<> struct __make_unsigned : type_identity {};
-template<> struct __make_unsigned : type_identity {};
-template<> struct __make_unsigned : type_identity {};
-template<> struct __make_unsigned : type_identity {};
-template<> struct __make_unsigned : type_identity {};
+ template<> struct __make_unsigned : type_identity {};
+ template<> struct __make_unsigned : type_identity {};
+ template<> struct __make_unsigned : type_identity {};
+ template<> struct __make_unsigned : type_identity {};
+ template<> struct __make_unsigned : type_identity {};
+ template<> struct __make_unsigned : type_identity {};
+ template<> struct __make_unsigned : type_identity {};
+ template<> struct __make_unsigned : type_identity {};
+ template<> struct __make_unsigned