Skip to content

Commit

Permalink
✨ Add new int128 and int256 type detection and test cases
Browse files Browse the repository at this point in the history
— 🛠 Fix up a typo/copy-paste error in the __ZTDC_MEMREVERSE8_IMPL (thanks J.M.)
— ✨ Add new bit constant data arrays for larger integer types
— 🛠 Slightly improve code flow for encoding detection
  • Loading branch information
ThePhD committed Jul 12, 2022
1 parent 844cd41 commit 9fa88d1
Show file tree
Hide file tree
Showing 8 changed files with 268 additions and 76 deletions.
40 changes: 20 additions & 20 deletions include/ztd/idk/detail/bit.memreverse.impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,26 +52,26 @@
#include <climits>
#endif

#define __ZTDC_MEMREVERSE8_IMPL(_TYPE, _PTR_COUNT, _PTR) \
for (size_t index = 0, limit = ((_PTR_COUNT * (sizeof(_TYPE) * CHAR_BIT)) / 2); index < limit;) { \
const size_t ptr_index = index / CHAR_BIT; \
const size_t reverse_ptr_index = _PTR_COUNT - 1 - ptr_index; \
_TYPE* p = _PTR + ptr_index; \
_TYPE* reverse_p = _PTR + reverse_ptr_index; \
const _TYPE b_temp = *p; \
const _TYPE reverse_b_temp = *reverse_p; \
*p = 0; \
*reverse_p = 0; \
for (size_t bit_index = 0, bit_limit = ((sizeof(_TYPE) * CHAR_BIT)); bit_index < bit_limit; \
bit_index += 8) { \
const size_t reverse_bit_index = (sizeof(_TYPE) * CHAR_BIT) - 8 - bit_index; \
const _TYPE bit_mask = ((_TYPE)0xFF) << bit_index; \
const _TYPE reverse_bit_mask = ((_TYPE)0xFF) << reverse_bit_index; \
*p |= (((reverse_b_temp & reverse_bit_mask) >> reverse_bit_index) << bit_index); \
*reverse_p |= (((b_temp & bit_mask) >> bit_index) << reverse_bit_index); \
index += 8; \
} \
} \
#define __ZTDC_MEMREVERSE8_IMPL(_TYPE, _PTR_COUNT, _PTR) \
for (size_t __index = 0, __limit = ((_PTR_COUNT * (sizeof(_TYPE) * CHAR_BIT)) / 2); __index < __limit;) { \
const size_t __ptr_index = __index / (sizeof(_TYPE) * CHAR_BIT); \
const size_t __reverse_ptr_index = _PTR_COUNT - 1 - __ptr_index; \
_TYPE* __p = _PTR + __ptr_index; \
_TYPE* __reverse_p = _PTR + __reverse_ptr_index; \
const _TYPE __b_temp = *__p; \
const _TYPE __reverse_b_temp = *__reverse_p; \
*__p = 0; \
*__reverse_p = 0; \
for (size_t __bit_index = 0, __bit_limit = ((sizeof(_TYPE) * CHAR_BIT)); __bit_index < __bit_limit; \
__bit_index += 8) { \
const size_t __reverse_bit_index = (sizeof(_TYPE) * CHAR_BIT) - 8 - __bit_index; \
const _TYPE __bit_mask = ((_TYPE)0xFF) << __bit_index; \
const _TYPE __reverse_bit_mask = ((_TYPE)0xFF) << __reverse_bit_index; \
*__p |= (((__reverse_b_temp & __reverse_bit_mask) >> __reverse_bit_index) << __bit_index); \
*__reverse_p |= (((__b_temp & __bit_mask) >> __bit_index) << __reverse_bit_index); \
__index += 8; \
} \
} \
ztd_static_assert(true, "end-of-macro")

#endif // ZTD_IDK_DETAIL_BIT_MEMREVERSE_IMPL_H
24 changes: 24 additions & 0 deletions include/ztd/idk/unwrap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,30 @@ namespace ztd {
template <typename _Type>
using unwrap_t = decltype(::ztd::unwrap(::std::declval<_Type>()));

//////
/// @brief Retrives the unwrapped type if the object were put through a call to ztd::unwrap.
///
/// @remarks Typically used to get the type underlying a `std::reference_wrapper` or similar.
//////
template <typename _Type>
using unwrap_iterator_t = decltype(::ztd::unwrap_iterator(::std::declval<_Type>()));

//////
/// @brief Retrives the unwrapped type if the object were put through a call to ztd::unwrap.
///
/// @remarks Typically used to get the type underlying a `std::reference_wrapper` or similar.
//////
template <typename _Type>
using unwrap_remove_cvref_t = remove_cvref_t<unwrap_t<_Type>>;

//////
/// @brief Retrives the unwrapped type if the object were put through a call to ztd::unwrap.
///
/// @remarks Typically used to get the type underlying a `std::reference_wrapper` or similar.
//////
template <typename _Type>
using unwrap_remove_reference_t = ::std::remove_reference_t<unwrap_t<_Type>>;

ZTD_IDK_INLINE_ABI_NAMESPACE_CLOSE_I_
} // namespace ztd

Expand Down
15 changes: 7 additions & 8 deletions include/ztd/ranges/reconstruct.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,19 +264,18 @@ namespace ztd { namespace ranges {
inline constexpr bool is_nothrow_range_reconstructible_v
= is_nothrow_tag_invocable_v<__rng_detail::__reconstruct_fn, _It, _Sen>;

template <typename _Range, typename _It = ranges::range_iterator_t<remove_cvref_t<_Range>>,
typename _Sen = ranges::range_sentinel_t<remove_cvref_t<_Range>>>
using reconstruct_t
= decltype(ranges::reconstruct(::std::declval<::std::in_place_type_t<remove_cvref_t<_Range>>>(),
::std::declval<_It>(), ::std::declval<_Sen>()));
template <typename _Range, typename _It = ranges::range_iterator_t<unwrap_remove_reference_t<_Range>>,
typename _Sen = ranges::range_sentinel_t<unwrap_remove_reference_t<_Range>>>
using reconstruct_t = decltype(ranges::reconstruct(
::std::in_place_type<unwrap_remove_cvref_t<_Range>>, ::std::declval<_It>(), ::std::declval<_Sen>()));

template <typename _Range>
using range_reconstruct_t = decltype(ranges::reconstruct(
::std::declval<::std::in_place_type_t<remove_cvref_t<_Range>>>(), ::std::declval<_Range>()));
::std::in_place_type<unwrap_remove_cvref_t<_Range>>, ::std::declval<_Range>()));

template <typename _Tag, typename _Range = _Tag>
using tag_range_reconstruct_t = decltype(ranges::reconstruct(
::std::declval<::std::in_place_type_t<remove_cvref_t<_Tag>>>(), ::std::declval<_Range>()));
using tag_range_reconstruct_t
= decltype(ranges::reconstruct(::std::in_place_type<unwrap_remove_cvref_t<_Tag>>, ::std::declval<_Range>()));

ZTD_RANGES_INLINE_ABI_NAMESPACE_CLOSE_I_
}} // namespace ztd::ranges
Expand Down
130 changes: 91 additions & 39 deletions include/ztd/tests/bit_constant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,102 +36,146 @@
#include <ztd/version.hpp>

#include <ztd/idk/type_traits.hpp>
#include <ztd/idk/size.hpp>

#include <memory>
#include <cstddef>
#include <cstring>

namespace ztd { namespace tests {

namespace __tests_detail {
inline constexpr const unsigned char __distinct_bit_constant_source_bytes[] = {
#if ZTDC_NATIVE_ENDIAN == ZTDC_LITTLE_ENDIAN
0xFF, 0xDD, 0xBB, 0x99, 0x77, 0x55, 0x33, 0x11, 0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x10
#else
0x10, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x11, 0x33, 0x55, 0x77, 0x99, 0xBB, 0xDD, 0xFF
#endif
};
inline constexpr const unsigned char __distinct_bit_constant_source_bytes_reverse[] = {
#if ZTDC_NATIVE_ENDIAN == ZTDC_LITTLE_ENDIAN
0x10, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x11, 0x33, 0x55, 0x77, 0x99, 0xBB, 0xDD, 0xFF
#else
0xFF, 0xDD, 0xBB, 0x99, 0x77, 0x55, 0x33, 0x11, 0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x10
#endif
};
} // namespace __tests_detail

template <typename _Type>
_Type get_distinct_bit_constant_positive() noexcept {
constexpr std::size_t N = sizeof(_Type) * CHAR_BIT;
if constexpr (N == 8) {
constexpr std::size_t _Nbytes = sizeof(_Type) * CHAR_BIT;
if constexpr (_Nbytes == 8) {
return static_cast<_Type>(0x10);
}
else if constexpr (N == 16) {
else if constexpr (_Nbytes == 16) {
return static_cast<_Type>(0x1023);
}
else if constexpr (N == 24) {
else if constexpr (_Nbytes == 24) {
return static_cast<_Type>(0x102345);
}
else if constexpr (N == 32) {
else if constexpr (_Nbytes == 32) {
return static_cast<_Type>(0x10234567);
}
else if constexpr (N == 40) {
else if constexpr (_Nbytes == 40) {
return static_cast<_Type>(0x1023456789);
}
else if constexpr (N == 48) {
else if constexpr (_Nbytes == 48) {
return static_cast<_Type>(0x1023456789AB);
}
else if constexpr (N == 56) {
else if constexpr (_Nbytes == 56) {
return static_cast<_Type>(0x1023456789ABCD);
}
else if constexpr (N == 64) {
else if constexpr (_Nbytes == 64) {
return static_cast<_Type>(0x1023456789ABCDEF);
}
else {
static_assert(ztd::always_false_v<_Type>, "unusable bit size for the given type");
constexpr const auto& __source_bytes = __tests_detail::__distinct_bit_constant_source_bytes;
static_assert(ztd::always_true_v<_Type> && CHAR_BIT == 8,
"this branch can only be used on CHAR_BIT == 8 machines");
static_assert(
_Nbytes <= (sizeof(__source_bytes) * CHAR_BIT), "unusable (too large) bit size for the given type");

_Type __value;
::std::memcpy(::std::addressof(__value), __source_bytes, ztd_c_array_size(__source_bytes));
return __value;
}
}

template <typename _Type>
_Type get_distinct_bit_constant_negative() noexcept {
constexpr std::size_t N = sizeof(_Type) * CHAR_BIT;
constexpr std::size_t _Nbytes = sizeof(_Type) * CHAR_BIT;
if constexpr (::std::is_signed_v<_Type>) {
if constexpr (N == 8) {
if constexpr (_Nbytes == 8) {
return -static_cast<_Type>(0x10);
}
else if constexpr (N == 16) {
else if constexpr (_Nbytes == 16) {
return -static_cast<_Type>(0x1023);
}
else if constexpr (N == 24) {
else if constexpr (_Nbytes == 24) {
return -static_cast<_Type>(0x102345);
}
else if constexpr (N == 32) {
else if constexpr (_Nbytes == 32) {
return -static_cast<_Type>(0x10234567);
}
else if constexpr (N == 40) {
else if constexpr (_Nbytes == 40) {
return -static_cast<_Type>(0x1023456789);
}
else if constexpr (N == 48) {
else if constexpr (_Nbytes == 48) {
return -static_cast<_Type>(0x1023456789AB);
}
else if constexpr (N == 56) {
else if constexpr (_Nbytes == 56) {
return -static_cast<_Type>(0x1023456789ABCD);
}
else if constexpr (N == 64) {
else if constexpr (_Nbytes == 64) {
return -static_cast<_Type>(0x1023456789ABCDEF);
}
else {
static_assert(ztd::always_false_v<_Type>, "unusable bit size for the given type");
constexpr const auto& __source_bytes = __tests_detail::__distinct_bit_constant_source_bytes;
static_assert(ztd::always_true_v<_Type> && CHAR_BIT == 8,
"this branch can only be used on CHAR_BIT == 8 machines");
static_assert(_Nbytes <= (sizeof(__source_bytes) * CHAR_BIT),
"unusable (too large) bit size for the given type");

_Type __value;
::std::memcpy(::std::addressof(__value), __source_bytes, ztd_c_array_size(__source_bytes));
return -__value;
}
}
else {
if constexpr (N == 8) {
if constexpr (_Nbytes == 8) {
return static_cast<_Type>(0x10);
}
else if constexpr (N == 16) {
else if constexpr (_Nbytes == 16) {
return static_cast<_Type>(0x1023);
}
else if constexpr (N == 24) {
else if constexpr (_Nbytes == 24) {
return static_cast<_Type>(0x102345);
}
else if constexpr (N == 32) {
else if constexpr (_Nbytes == 32) {
return static_cast<_Type>(0x10234567);
}
else if constexpr (N == 40) {
else if constexpr (_Nbytes == 40) {
return static_cast<_Type>(0x1023456789);
}
else if constexpr (N == 48) {
else if constexpr (_Nbytes == 48) {
return static_cast<_Type>(0x1023456789AB);
}
else if constexpr (N == 56) {
else if constexpr (_Nbytes == 56) {
return static_cast<_Type>(0x1023456789ABCD);
}
else if constexpr (N == 64) {
else if constexpr (_Nbytes == 64) {
return static_cast<_Type>(0x1023456789ABCDEF);
}
else {
static_assert(ztd::always_false_v<_Type>, "unusable bit size for the given type");
constexpr const auto& __source_bytes = __tests_detail::__distinct_bit_constant_source_bytes;
static_assert(ztd::always_true_v<_Type> && CHAR_BIT == 8,
"this branch can only be used on CHAR_BIT == 8 machines");
static_assert(_Nbytes <= (sizeof(__source_bytes) * CHAR_BIT),
"unusable (too large) bit size for the given type");

_Type __value;
::std::memcpy(::std::addressof(__value), __source_bytes, ztd_c_array_size(__source_bytes));
return __value;
}
}
}
Expand All @@ -143,33 +187,41 @@ namespace ztd { namespace tests {

template <typename _Type>
_Type get_distinct_bit_constant_reverse() noexcept {
constexpr std::size_t N = sizeof(_Type) * CHAR_BIT;
if constexpr (N == 8) {
constexpr std::size_t _Nbytes = sizeof(_Type) * CHAR_BIT;
if constexpr (_Nbytes == 8) {
return static_cast<_Type>(0x10);
}
else if constexpr (N == 16) {
else if constexpr (_Nbytes == 16) {
return static_cast<_Type>(0x2310);
}
else if constexpr (N == 24) {
else if constexpr (_Nbytes == 24) {
return static_cast<_Type>(0x452310);
}
else if constexpr (N == 32) {
else if constexpr (_Nbytes == 32) {
return static_cast<_Type>(0x67452310);
}
else if constexpr (N == 40) {
else if constexpr (_Nbytes == 40) {
return static_cast<_Type>(0x8967452310);
}
else if constexpr (N == 48) {
else if constexpr (_Nbytes == 48) {
return static_cast<_Type>(0xAB8967452310);
}
else if constexpr (N == 56) {
else if constexpr (_Nbytes == 56) {
return static_cast<_Type>(0xCDAB8967452310);
}
else if constexpr (N == 64) {
else if constexpr (_Nbytes == 64) {
return static_cast<_Type>(0xEFCDAB8967452310);
}
else {
static_assert(ztd::always_false_v<_Type>, "unusable bit size for the given type");
constexpr const auto& __source_bytes = __tests_detail::__distinct_bit_constant_source_bytes_reverse;
static_assert(ztd::always_true_v<_Type> && CHAR_BIT == 8,
"this branch can only be used on CHAR_BIT == 8 machines");
static_assert(
_Nbytes <= (sizeof(__source_bytes) * CHAR_BIT), "unusable (too large) bit size for the given type");

_Type __value;
::std::memcpy(::std::addressof(__value), __source_bytes, ztd_c_array_size(__source_bytes));
return __value;
}
}

Expand Down
12 changes: 12 additions & 0 deletions include/ztd/tests/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,18 @@ namespace ztd::tests {
MoveConsOnlyType& operator=(MoveConsOnlyType&&) = delete;
};

using unsigned_integer_types_list
= type_list<unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long
#if ZTD_IS_ON(ZTD___UINT128_T)
,
__uint128_t
#endif
#if ZTD_IS_ON(ZTD___UINT256_T)
,
__uint256_t
#endif
>;

using character_types_list = type_list<char, signed char, unsigned char,
#if ZTD_IS_ON(ZTD_NATIVE_CHAR8_T)
char8_t,
Expand Down

0 comments on commit 9fa88d1

Please sign in to comment.