From cc129eb4e27afdff3b7668c7cd94d4d3e8c2998e Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sat, 23 Aug 2025 12:35:08 +0100 Subject: [PATCH 1/3] Update catch2 --- subprojects/Catch2.wrap | 3 ++- test/unit/meson.build | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/subprojects/Catch2.wrap b/subprojects/Catch2.wrap index 3053b28..973fd54 100644 --- a/subprojects/Catch2.wrap +++ b/subprojects/Catch2.wrap @@ -3,4 +3,5 @@ revision = b5373dadca40b7edc8570cf9470b9b1cb1934d40 url = https://github.com/catchorg/Catch2.git [provide] -Catch2 = catch2_with_main_dep +catch2-with-main = catch2_with_main_dep +Catch2 = catch2_dep diff --git a/test/unit/meson.build b/test/unit/meson.build index 5ec1bd0..7777af0 100644 --- a/test/unit/meson.build +++ b/test/unit/meson.build @@ -1,4 +1,4 @@ -catch2_dep = dependency('Catch2', version: '>=3.5.2') +catch2_dep = dependency('catch2-with-main', version: '>=3.5.2') unit_test_prog = executable(meson.project_name(), 'int_conv_test.cpp', From a2d6944249cdb05734b28fb6147337e385eb58e4 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sat, 23 Aug 2025 12:36:29 +0100 Subject: [PATCH 2/3] New PackedPointer class --- include/duckhandy/bitfield_pack.hpp | 2 +- include/duckhandy/packed_pointer.hpp | 194 +++++++++++++++++++++++++++ 2 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 include/duckhandy/packed_pointer.hpp diff --git a/include/duckhandy/bitfield_pack.hpp b/include/duckhandy/bitfield_pack.hpp index 1311571..a140fbe 100644 --- a/include/duckhandy/bitfield_pack.hpp +++ b/include/duckhandy/bitfield_pack.hpp @@ -1,4 +1,4 @@ -/* Copyright 2016-2024 Michele Santullo +/* Copyright 2016-2025 Michele Santullo * This file is part of "duckhandy". * * "duckhandy" is free software: you can redistribute it and/or modify diff --git a/include/duckhandy/packed_pointer.hpp b/include/duckhandy/packed_pointer.hpp new file mode 100644 index 0000000..84aa8de --- /dev/null +++ b/include/duckhandy/packed_pointer.hpp @@ -0,0 +1,194 @@ +/* Copyright 2016-2025 Michele Santullo + * This file is part of "duckhandy". + * + * "duckhandy" 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. + * + * "duckhandy" 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 "duckhandy". If not, see . + */ + +#ifndef id83CE9FAB90684250B98EA584C548E13F +#define id83CE9FAB90684250B98EA584C548E13F + +#include "bitfield_pack.hpp" +#include +#include +#include + +namespace dhandy { +namespace implem { + +//This monster expression is just the one-liner version of this +//implementation of log2: +//unsigned int v; // 32-bit value to find the log2 of +//register unsigned int r; // result of log2(v) will go here +//register unsigned int shift; +// +//r = (v > 0xFFFF) << 4; v >>= r; +//shift = (v > 0xFF ) << 3; v >>= shift; r |= shift; +//shift = (v > 0xF ) << 2; v >>= shift; r |= shift; +//shift = (v > 0x3 ) << 1; v >>= shift; r |= shift; +// r |= (v >> 1); +//see https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog for +//an explanation of that. +//This is a shorter version of it but it only works if the input is a power +//of 2: +//(((((NUM&0xAAAAAAAA)!=0)|((NUM&0xFFFF0000)!=0)<<4)|((NUM&0xFF00FF00)!=0)<< +//3)|((NUM&0xF0F0F0F0)!=0)<<2)|((NUM&0xCCCCCCCC)!=0)<<1 +//Source for that is also available at the page linked above. +template const constexpr std::size_t + pointer_unused_bit_count = + ((((((NUM > 0xFFFF) << 4) | (((NUM >> ((NUM > 0xFFFF) << 4)) > 0xFF) << + 3)) | ((((NUM >> ((NUM > 0xFFFF) << 4)) >> (((NUM >> ((NUM > 0xFFFF) << + 4)) > 0xFF) << 3)) > 0xF) << 2)) | (((((NUM >> ((NUM > 0xFFFF) << 4)) >> + (((NUM >> ((NUM > 0xFFFF) << 4)) > 0xFF) << 3)) >> ((((NUM >> ((NUM > + 0xFFFF) << 4)) >> (((NUM >> ((NUM > 0xFFFF) << 4)) > 0xFF) << 3)) > 0xF) + << 2)) > 0x3) << 1)) | (((((NUM >> ((NUM > 0xFFFF) << 4)) >> (((NUM >> ( + (NUM > 0xFFFF) << 4)) > 0xFF) << 3)) >> ((((NUM >> ((NUM > 0xFFFF) << 4) + ) >> (((NUM >> ((NUM > 0xFFFF) << 4)) > 0xFF) << 3)) > 0xF) << 2)) >> (( + (((NUM >> ((NUM > 0xFFFF) << 4)) >> (((NUM >> ((NUM > 0xFFFF) << 4)) > + 0xFF) << 3)) >> ((((NUM >> ((NUM > 0xFFFF) << 4)) >> (((NUM >> ((NUM > + 0xFFFF) << 4)) > 0xFF) << 3)) > 0xF) << 2)) > 0x3) << 1)) >> 1)) +; + +template +BitfieldPack< + std::uintptr_t, + sizeof(std::uintptr_t) * CHAR_BIT - sizeof...(S), (S+1)/(S+1)... +> +guess_bitfield_type (std::index_sequence); + +template +using BaseBitfieldPackForPackedPointer = decltype( + implem::guess_bitfield_type( + std::make_index_sequence>() + ) +); +} //namespace implem + +template +class PackedPointer : private implem::BaseBitfieldPackForPackedPointer { + static_assert(sizeof(T*) == sizeof(std::uintptr_t), "Mismatching int/pointer size"); + typedef implem::BaseBitfieldPackForPackedPointer parent_type; +public: + static const constexpr std::size_t FlagsCount = parent_type::TotalEntries - 1; + + PackedPointer(); + PackedPointer (T* ptr); + ~PackedPointer() = default; + + operator T*() const; + operator bool() const; + template bool flag () const; + template void set_flag (bool v); + + PackedPointer& operator= (T* ptr); + T* operator->(); + const T* operator->() const; + T& operator*(); + const T& operator*() const; + bool operator== (const PackedPointer& other) const; + bool operator== (T* other) const; + bool operator!= (const PackedPointer& other) const; + bool operator!= (T* other) const; + +private: + //static const constexpr uintptr_t PtrMask = static_cast(-1) << FlagsCount; +}; + +template const constexpr std::size_t PackedPointer::FlagsCount; +//template const constexpr std::uintptr_t PackedPointer::PtrMask; + +template +PackedPointer::PackedPointer() : + PackedPointer(nullptr) +{ +} + +template +PackedPointer::PackedPointer (T* ptr) : + parent_type(0) +{ + (*this) = ptr; +} + +template +PackedPointer::operator T*() const { + return reinterpret_cast(this->get(0) << FlagsCount); +} + +template +PackedPointer::operator bool() const { + return static_cast(*this) != nullptr; +} + +template +template +bool PackedPointer::flag() const { + static_assert(Idx < FlagsCount, "Index out of range"); + return static_cast(this->get(Idx + 1)); +} + +template +template +void PackedPointer::set_flag (bool v) { + static_assert(Idx < FlagsCount, "Index out of range"); + this->set(Idx + 1, (v ? 1 : 0)); +} + +template +PackedPointer& PackedPointer::operator= (T* ptr) { + this->set(0, reinterpret_cast(ptr) >> FlagsCount); + return *this; +} + +template +T* PackedPointer::operator->() { + return static_cast(*this); +} + +template +const T* PackedPointer::operator->() const { + return static_cast(*this); +} + +template +T& PackedPointer::operator*() { + return *static_cast(*this); +} + +template +const T& PackedPointer::operator*() const { + return *static_cast(*this); +} + +template +bool PackedPointer::operator== (const PackedPointer& other) const { + return this == &other or static_cast(*this) == static_cast(other); +} + +template +bool PackedPointer::operator== (T* other) const { + return static_cast(*this) == other; +} + +template +bool PackedPointer::operator!= (const PackedPointer& other) const { + return not this->operator==(other); +} + +template +bool PackedPointer::operator!= (T* other) const { + return not this->operator==(other); +} +} //namepace dhandy + +#endif From 96c6ac1df3070beb833d3807f521af4b2bc15c4e Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sat, 23 Aug 2025 12:39:15 +0100 Subject: [PATCH 3/3] No idea what this is This stuff's been laying around for months and years, just committing and crossing fingers - pro coding here! --- .../implem/reversed_sized_array_bt.hpp | 27 +++++++++++- include/duckhandy/variadic_repeat_bt.hpp | 41 +++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 include/duckhandy/variadic_repeat_bt.hpp diff --git a/include/duckhandy/implem/reversed_sized_array_bt.hpp b/include/duckhandy/implem/reversed_sized_array_bt.hpp index 41b4ce8..257c80d 100644 --- a/include/duckhandy/implem/reversed_sized_array_bt.hpp +++ b/include/duckhandy/implem/reversed_sized_array_bt.hpp @@ -18,6 +18,7 @@ #ifndef idFC25566D624140559C54B39FFFE52F04 #define idFC25566D624140559C54B39FFFE52F04 +#include "../variadic_repeat_bt.hpp" #include #include #if !defined(INT_CONV_WITHOUT_HELPERS) @@ -37,13 +38,16 @@ namespace dhandy { using iterator = T*; constexpr ReversedSizedArray() = default; + constexpr ReversedSizedArray (const ReversedSizedArray&) = default; + constexpr ReversedSizedArray (ReversedSizedArray&&) = default; + template constexpr explicit ReversedSizedArray (Items&&... items); ~ReversedSizedArray() = default; constexpr std::size_t size() const { return S - (m_curr + 1); } constexpr bool empty() const { return m_curr + 1 == S; } constexpr const T operator[] (std::size_t idx) const { if (idx >= size()) throw std::out_of_range("Out of bound array access"); return m_data[idx + m_curr + 1]; } constexpr T& operator[] (std::size_t idx) { if (idx >= size()) throw std::out_of_range("Out of bound array access"); return m_data[idx + m_curr + 1]; } - constexpr void push_front (const T& itm) { if (size() == S) throw std::length_error("ReversedSizedArray is full"); m_data[m_curr--] = itm; } + constexpr void push_front (const T& itm) { /*if (size() == S) throw std::length_error("ReversedSizedArray is full");*/ m_data[m_curr--] = itm; } constexpr const T* data() const { return m_data + m_curr + 1; } constexpr const T* base_ptr() const { return m_data; } constexpr iterator begin() { return m_data + m_curr + 1; } @@ -67,6 +71,9 @@ namespace dhandy { #endif private: + template + constexpr explicit ReversedSizedArray (bt::variadic_repeat, Items&&... items); + T m_data[S]; std::size_t m_curr {S - 1}; }; @@ -78,6 +85,24 @@ namespace dhandy { } } //namespace implem + template + template + inline constexpr ReversedSizedArray::ReversedSizedArray (Items&&... items) : + ReversedSizedArray( + bt::make_variadic_repeat{}, + std::forward(items)... + ) + { } + + template + template + constexpr ReversedSizedArray::ReversedSizedArray (bt::variadic_repeat, Items&&... items) : + m_data{ItemsFill..., std::forward(items)...}, + m_curr(S - 1 - sizeof...(Items)) + { + static_assert(sizeof...(ItemsFill) + sizeof...(Items) == S, "Wrong number of input elements"); + } + #if !defined(INT_CONV_WITHOUT_HELPERS) template inline diff --git a/include/duckhandy/variadic_repeat_bt.hpp b/include/duckhandy/variadic_repeat_bt.hpp new file mode 100644 index 0000000..8c5262d --- /dev/null +++ b/include/duckhandy/variadic_repeat_bt.hpp @@ -0,0 +1,41 @@ +/* Copyright 2016-2024 Michele Santullo + * This file is part of "duckhandy". + * + * "duckhandy" 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. + * + * "duckhandy" 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 "duckhandy". If not, see . + */ + +#include + +namespace dhandy::bt { +template +struct variadic_repeat { +}; + +namespace detail { + template + struct VariadicRepeatBuilder; + + template + struct VariadicRepeatBuilder<0, T, V0, V...> { + typedef variadic_repeat type; + }; + + template + struct VariadicRepeatBuilder : public VariadicRepeatBuilder { + }; +} //namespace detail + +template +using make_variadic_repeat = typename detail::VariadicRepeatBuilder::type; +} //namespace dhandy::bt