Skip to content

Commit

Permalink
✨ Add resize method using @misccos patches (they couldn't merge prope…
Browse files Browse the repository at this point in the history
…rly. D:)

— 🎨 Use ztd::idk's to_address and to_mutable_iter since they are better-designed customization points
— ✨Add resize tests from @misccos patches in #6
  • Loading branch information
ThePhD committed Jul 17, 2022
1 parent 92db248 commit a4544b3
Show file tree
Hide file tree
Showing 12 changed files with 487 additions and 164 deletions.
139 changes: 1 addition & 138 deletions include/itsy/detail/bit_detail.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <ztd/idk/type_traits.hpp>
#include <ztd/idk/unwrap.hpp>
#include <ztd/ranges/adl.hpp>
#include <ztd/idk/to_mutable_iter.hpp>

#include <cstddef>
#include <cstdint>
Expand Down Expand Up @@ -283,144 +284,6 @@ namespace ITSY_BITSY_SOURCE_NAMESPACE
template<typename _Container>
inline constexpr bool __is_bit_container_v = __is_bit_container<_Container>::value;

template<typename __Iter>
using __invoke_iter_as_mutable_test = decltype(__iter_as_mutable(::std::declval<__Iter>()));

template<typename __Iter>
using __is_iter_as_mutable_invokable = ::ztd::is_detected<__invoke_iter_as_mutable_test, __Iter>;

template<typename __Iter>
inline constexpr bool __is_iter_as_mutable_invokable_v = __is_iter_as_mutable_invokable<__Iter>::value;

template<typename _FromIt, typename _Container>
constexpr auto
__iter_as_mutable_from_begin(_FromIt& __from_it, _Container& __source) noexcept
{
using _ToIt = decltype(::ztd::ranges::ranges_adl::adl_begin(__source));

if constexpr (::std::is_same_v<::std::remove_cv_t<::std::remove_reference_t<_ToIt>>, _FromIt>)
{
(void)__source;
return _ToIt(__from_it);
}
else if constexpr (__is_iter_as_mutable_invokable_v<_FromIt&>)
{
(void)__source;
return __iter_as_mutable(__from_it);
}
else if constexpr (::ztd::is_detected_v<__has_pair_iterator_insert_test, _Container>)
{
// http://eel.is/c++draft/container.requirements#sequence.reqmts-8
// "The iterator returned from a.insert(p, i, j)
// points to the copy of the first element inserted into a,
// or p if i == j."
// in other words, this is our cheat code to avoid
// hitting the worst-case-scenario here
return __source.insert(__from_it, ::ztd::ranges::ranges_adl::adl_cend(__source), ::ztd::ranges::ranges_adl::adl_cend(__source));
}
else if constexpr (::std::is_invocable_r_v<bool, ::std::not_equal_to<>, _ToIt, _FromIt> &&
(::std::is_same_v<typename ::std::iterator_traits<_FromIt>::iterator_category,
::std::forward_iterator_tag> ||
::std::is_same_v<typename ::std::iterator_traits<_FromIt>::iterator_category,
::std::bidirectional_iterator_tag>))
{
// we can avoid 2N walk of iterators
// by just moving up by them if they're
// comparable to one another
auto __begin_it = ::ztd::ranges::ranges_adl::adl_begin(__source);
while (__begin_it != __from_it)
{
++__begin_it;
}
return __begin_it;
}
else
{
// either this is random access and O(1),
// or this is some other weird iterator and it's O(2N)
auto __begin_it = ::ztd::ranges::ranges_adl::adl_begin(__source);
auto __it_dist = ::std::distance(_FromIt(__begin_it), __from_it);
std::advance(__begin_it, __it_dist);
return __begin_it;
}
}

template<typename _FromIt, typename _Container>
constexpr auto
__iter_as_mutable_from_end(_FromIt& __from_it, _Container& __source) noexcept
{
using _ToIt = decltype(::ztd::ranges::ranges_adl::adl_end(__source));

if constexpr (::std::is_same_v<::std::remove_cv_t<::std::remove_reference_t<_ToIt>>, _FromIt>)
{
(void)__source;
return _ToIt(__from_it);
}
else if constexpr (__is_iter_as_mutable_invokable_v<_FromIt&>)
{
(void)__source;
return __iter_as_mutable(__from_it);
}
else if constexpr (::ztd::is_detected_v<__has_pair_iterator_insert_test, _Container>)
{
// http://eel.is/c++draft/container.requirements#sequence.reqmts-8
// "The iterator returned from a.insert(p, i, j)
// points to the copy of the first element inserted into a,
// or p if i == j."
// in other words, this is our cheat code to avoid
// hitting the worst-case-scenario here
return __source.insert(__from_it, ::ztd::ranges::ranges_adl::adl_cend(__source), ::ztd::ranges::ranges_adl::adl_cend(__source));
}
else if constexpr (::std::is_invocable_r_v<bool, ::std::not_equal_to<>, _ToIt, _FromIt> &&
(::std::is_same_v<typename ::std::iterator_traits<_FromIt>::iterator_category,
::std::bidirectional_iterator_tag>))
{
// we can avoid 2N walk of iterators
// by just moving up by them if they're
// comparable to one another
auto __begin_it = ::ztd::ranges::ranges_adl::adl_end(__source);
while (__begin_it != __from_it)
{
--__begin_it;
}
return __begin_it;
}
else if constexpr (::std::is_invocable_r_v<bool, ::std::not_equal_to<>, _ToIt, _FromIt> &&
(::std::is_same_v<typename ::std::iterator_traits<_FromIt>::iterator_category,
::std::forward_iterator_tag>))
{
// we can avoid 2N walk of iterators
// by just moving up by them if they're
// comparable to one another
auto __begin_it = ::ztd::ranges::ranges_adl::adl_begin(__source);
while (__begin_it != __from_it)
{
++__begin_it;
}
return __begin_it;
}
else
{
// either this is random access and O(1),
// or this is some other weird iterator and it's O(2N)
auto __end_it = ::ztd::ranges::ranges_adl::adl_end(__source);
auto __it_dist = ::std::distance(__from_it, _FromIt(__end_it));
std::advance(__end_it, __it_dist);
return __end_it;
}
}

template <typename _It>
decltype(auto) __adl_to_address (const _It& __it) noexcept {
#if ITSY_BITSY_IS_ON(ITSY_BITSY_STD_LIB_TO_ADDRESS_I_)
using ::std::to_address;
#endif
return to_address(__it);
}

template <typename _It>
using __adl_to_address_test = decltype(__adl_to_address(::std::declval<_It>()));

} // namespace ITSY_BITSY_SOURCE_NAMESPACE

#endif // ITSY_BITSY_DETAIL_BIT_DETAIL_HPP
5 changes: 3 additions & 2 deletions include/itsy/detail/bit_iterator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <ztd/idk/unwrap.hpp>
#include <ztd/ranges/iterator.hpp>
#include <ztd/ranges/range.hpp>
#include <ztd/idk/to_address.hpp>

#include <cstddef>
#include <cassert>
Expand Down Expand Up @@ -674,9 +675,9 @@ namespace ITSY_BITSY_SOURCE_NAMESPACE
}
else
{
if constexpr (::ztd::is_detected_v<__adl_to_address_test, iterator_type>)
if constexpr (::ztd::is_to_addressable_v<iterator_type>)
{
return __adl_to_address(this->_M_base_it) != nullptr;
return ::ztd::idk_adl::adl_to_address(this->_M_base_it) != nullptr;
}
else
{
Expand Down
64 changes: 50 additions & 14 deletions include/itsy/detail/bit_sequence.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include <itsy/detail/bit_view.hpp>
#include <itsy/detail/bit_detail.hpp>

#include <ztd/idk/to_mutable_iter.hpp>

#include <cstddef>
#include <type_traits>
#include <utility>
Expand Down Expand Up @@ -42,13 +44,13 @@ namespace ITSY_BITSY_SOURCE_NAMESPACE
using __range_ref = typename __base_t::__range_ref;

public:
using difference_type = typename __base_t::difference_type;
using size_type = typename __base_t::size_type;
using value_type = typename __base_t::value_type;
using reference = typename __base_t::reference;
using const_reference = typename __base_t::const_reference;
using difference_type = typename __base_t::difference_type;
using size_type = typename __base_t::size_type;
using value_type = typename __base_t::value_type;
using reference = typename __base_t::reference;
using const_reference = typename __base_t::const_reference;
using iterator_category = typename __base_t::iterator_category;
using iterator_concept = ::ztd::ranges::iterator_concept_t<__base_iterator>;
using iterator_concept = ::ztd::ranges::iterator_concept_t<__base_iterator>;
using pointer = typename __base_t::pointer;
using iterator = typename __base_t::iterator;
using sentinel = typename __base_t::sentinel;
Expand Down Expand Up @@ -234,8 +236,9 @@ namespace ITSY_BITSY_SOURCE_NAMESPACE
{
if (__desired_count < static_cast<size_type>(1))
{
__base_c_iterator __where_base = ::std::move(__where).base();
__base_iterator __nowhere =
this->_M_storage_unwrapped().insert(__where.base(), __where.base());
::ztd::to_mutable_iter_from_begin(__where_base, this->_M_storage_unwrapped());
return iterator(::std::move(__nowhere), __where.position());
}
iterator __current_pos = this->insert(::std::move(__where), __val);
Expand All @@ -246,7 +249,8 @@ namespace ITSY_BITSY_SOURCE_NAMESPACE
return __current_pos;
}

template<typename _Iterator, typename _Sentinel>
template<typename _Iterator, typename _Sentinel,
::std::enable_if_t<!::std::is_arithmetic_v<_Iterator>>* = nullptr>
iterator
insert(const_iterator __where, _Iterator __first, _Sentinel __last)
{
Expand All @@ -256,7 +260,7 @@ namespace ITSY_BITSY_SOURCE_NAMESPACE
{
__base_c_iterator __where_base = ::std::move(__where).base();
__base_iterator __nowhere =
__iter_as_mutable_from_begin(__where_base, this->_M_storage_unwrapped());
::ztd::to_mutable_iter_from_begin(__where_base, this->_M_storage_unwrapped());
return iterator(::std::move(__nowhere), __where.position());
}

Expand Down Expand Up @@ -360,6 +364,36 @@ namespace ITSY_BITSY_SOURCE_NAMESPACE
return __insertion_return;
}

// modifiers: resize
void
resize(size_type __desired_count)
{
const auto __size = this->size();
if (__desired_count < __size)
{
this->erase(::std::next(this->cbegin(), __desired_count), this->cend());
}
else
{
this->insert(this->cend(), static_cast<size_type>(__desired_count - __size),
static_cast<value_type>(false));
}
}

void
resize(size_type __desired_count, value_type __val)
{
const auto __size = this->size();
if (__desired_count < __size)
{
this->erase(::std::next(this->cbegin(), __desired_count), this->cend());
}
else
{
this->insert(this->cend(), static_cast<size_type>(__desired_count - __size), __val);
}
}

void
pop_back()
{
Expand Down Expand Up @@ -412,7 +446,8 @@ namespace ITSY_BITSY_SOURCE_NAMESPACE
{
if (__first == __last)
{
__base_iterator __nowhere = this->_M_storage_unwrapped().erase(__first.base(), __first.base());
__base_c_iterator __where_base = ::std::move(__first).base();
__base_iterator __nowhere = ::ztd::to_mutable_iter_from_begin(__where_base, this->_M_storage_unwrapped());
return iterator(::std::move(__nowhere), __first.position());
}
if (this->empty())
Expand Down Expand Up @@ -803,7 +838,8 @@ namespace ITSY_BITSY_SOURCE_NAMESPACE
if (__modulo_bit_counter == __binary_digits_v<__base_value_type>)
{
__base_iterator __storage_it =
__storage.insert(::ztd::ranges::ranges_adl::adl_cend(__storage), static_cast<__base_value_type>(0));
__storage.insert(::ztd::ranges::ranges_adl::adl_cend(__storage),
static_cast<__base_value_type>(0));
__it = iterator(::std::move(__storage_it), 0);
__modulo_bit_counter = 0;
}
Expand Down Expand Up @@ -945,7 +981,7 @@ namespace ITSY_BITSY_SOURCE_NAMESPACE
__insert_bit_count / __binary_digits_v<__base_value_type>;
difference_type __insert_bit_shift = __insert_bit_count % __binary_digits_v<__base_value_type>;
iterator __shift_insertion_target = this->_M_copy_words_if_necessary(
__insert_word_count, __where_dist, __where_base, __first);
__insert_word_count, __where_dist, __where_base, __first);
if (__insert_bit_shift > 0)
{
this->_M_basic_insert(__shift_insertion_target, __first, __last);
Expand Down Expand Up @@ -1013,7 +1049,7 @@ namespace ITSY_BITSY_SOURCE_NAMESPACE
__first += __insert_word_bit_count;
return __wheret_copy_it;
}
return iterator(__iter_as_mutable_from_begin(__where_base, this->_M_storage_unwrapped()), 0);
return iterator(::ztd::to_mutable_iter_from_begin(__where_base, this->_M_storage_unwrapped()), 0);
}

template<typename _Iterator, typename _Sentinel>
Expand Down Expand Up @@ -1095,7 +1131,7 @@ namespace ITSY_BITSY_SOURCE_NAMESPACE
}
else
{
return __iter_as_mutable_from_begin(__first_base_it, this->_M_storage_unwrapped());
return ::ztd::to_mutable_iter_from_begin(__first_base_it, this->_M_storage_unwrapped());
}
}

Expand Down
31 changes: 31 additions & 0 deletions include/itsy/detail/small_bit_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1055,6 +1055,37 @@ namespace ITSY_BITSY_SOURCE_NAMESPACE
return this->begin() + __preserve_old_position;
}

// modifiers: resize
// modifiers: resize
void
resize(size_type __desired_count)
{
const auto __size = this->size();
if (__desired_count < __size)
{
this->erase(::std::next(this->cbegin(), __desired_count), this->cend());
}
else
{
this->insert(this->cend(), static_cast<size_type>(__desired_count - __size),
static_cast<value_type>(false));
}
}

void
resize(size_type __desired_count, value_type __val)
{
const auto __size = this->size();
if (__desired_count < __size)
{
this->erase(::std::next(this->cbegin(), __desired_count), this->cend());
}
else
{
this->insert(this->cend(), static_cast<size_type>(__desired_count - __size), __val);
}
}

// modifiers: erase
void
pop_front() noexcept(::std::is_nothrow_move_constructible_v<__base_value_type>)
Expand Down
10 changes: 0 additions & 10 deletions include/itsy/version.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,16 +125,6 @@
#define ITSY_BITSY_STD_CHAR8_T_I_ ITSY_BITSY_DEFAULT_OFF
#endif

#if defined(__cpp_lib_to_address)
#if __cpp_lib_to_address != 0
#define ITSY_BITSY_STD_LIB_TO_ADDRESS_I_ ITSY_BITSY_ON
#else
#define ITSY_BITSY_STD_LIB_TO_ADDRESS_I_ ITSY_BITSY_OFF
#endif
#else
#define ITSY_BITSY_STD_LIB_TO_ADDRESS_I_ ITSY_BITSY_DEFAULT_OFF
#endif

#if defined(__cpp_lib_bitops)
#if __cpp_lib_bitops != 0
#define ITSY_BITSY_STD_LIB_BIT_I_ ITSY_BITSY_ON
Expand Down
Loading

0 comments on commit a4544b3

Please sign in to comment.