25 #ifndef JAU_DYN_ARRAY_HPP_
26 #define JAU_DYN_ARRAY_HPP_
35 #include <condition_variable>
36 #include <initializer_list>
51 #define DARRAY_PRINTF(...) { fprintf(stderr, __VA_ARGS__); fflush(stderr); }
53 #define DARRAY_PRINTF(...)
96 template <
typename Value_type,
typename Alloc_type = jau::callocator<Value_type>,
typename Size_type = jau::n
size_t,
97 bool use_memmove = std::is_trivially_copyable_v<Value_type>,
98 bool use_realloc = std::is_base_of_v<jau::callocator<Value_type>, Alloc_type>,
130 constexpr
static const size_type DIFF_MAX = std::numeric_limits<difference_type>::max();
131 constexpr
static const size_type MIN_SIZE_AT_GROW = 10;
137 float growth_factor_;
153 if( size_ > DIFF_MAX ) {
164 explicit_bzero((
void*)m, size_*
sizeof(
value_type));
171 template<
class _Alloc_type>
175 if( new_capacity_ > DIFF_MAX ) {
180 explicit_bzero((
void*)end_, (storage_end_-end_)*
sizeof(
value_type));
190 explicit_bzero((
void*)(m+(end_-begin_)), (new_capacity_-(end_-begin_))*
sizeof(
value_type));
194 template<
class _Alloc_type>
202 constexpr
void freeStore() {
203 if(
nullptr != begin_ ) {
205 explicit_bzero((
void*)begin_, (storage_end_-begin_)*
sizeof(
value_type));
207 alloc_inst.
deallocate(begin_, storage_end_-begin_);
212 begin_ = new_storage_;
213 end_ = new_storage_+size_;
214 storage_end_ = new_storage_+capacity_;
219 storage_end_ = begin_+capacity_;
222 constexpr
void dtor_one(
iterator pos) {
226 explicit_bzero((
void*)pos,
sizeof(
value_type));
232 DARRAY_PRINTF(
"dtor [%zd .. %zd], count %zd\n", (first-begin_), (last-begin_)-1, (last-first));
233 for(; first < last; ++first, ++count ) {
237 explicit_bzero((
void*)(last-count), count*
sizeof(
value_type));
243 DARRAY_PRINTF(
"ctor_copy_range [%zd .. %zd] -> ??, dist %zd\n", (first-begin_), (last-begin_)-1, (last-first));
244 for(; first < last; ++dest, ++first) {
249 DARRAY_PRINTF(
"clone_range [%zd .. %zd], count %zd\n", (first-begin_), (last-begin_)-1, (last-first));
251 ctor_copy_range(dest, first, last);
255 DARRAY_PRINTF(
"clone_range [%zd .. %zd], count %zd -> %d\n", (first-begin_), (last-begin_)-1, (last-first), (
int)dest_capacity);
256 pointer dest = allocStore(dest_capacity);
257 ctor_copy_range(dest, first, last);
261 DARRAY_PRINTF(
"ctor_copy_range_check [%zd .. %zd] -> ??, dist %zd\n", (first-begin_), (last-begin_)-1, (last-first));
265 for(; first < last; ++dest, ++first) {
270 DARRAY_PRINTF(
"clone_range_check [%zd .. %zd], count %zd -> %d\n", (first-begin_), (last-begin_)-1, (last-first), (
int)dest_capacity);
271 if( dest_capacity <
size_type(last-first) ) {
275 pointer dest = allocStore(dest_capacity);
276 ctor_copy_range_check(dest, first, last);
279 template<
class InputIt >
280 constexpr
static void ctor_copy_range_foreign(
pointer dest, InputIt first, InputIt last) {
285 for(; first != last; ++dest, ++first) {
289 template<
class InputIt >
290 constexpr
pointer clone_range_foreign(
const size_type dest_capacity, InputIt first, InputIt last) {
291 if( dest_capacity <
size_type(last-first) ) {
295 pointer dest = allocStore(dest_capacity);
296 ctor_copy_range_foreign(dest, first, last);
300 constexpr
void grow_storage_move(
const size_type new_capacity) {
302 pointer new_storage = allocStore(new_capacity);
306 for(; first < end_; ++dest, ++first) {
312 set_iterator(new_storage,
size(), new_capacity);
313 }
else if( use_realloc ) {
314 pointer new_storage = reallocStore<allocator_type>(new_capacity);
315 set_iterator(new_storage,
size(), new_capacity);
317 pointer new_storage = allocStore(new_capacity);
318 memcpy(
reinterpret_cast<void*
>(new_storage),
319 reinterpret_cast<void*
>(begin_), (uint8_t*)end_-(uint8_t*)begin_);
322 set_iterator(new_storage,
size(), new_capacity);
325 constexpr
void grow_storage_move() {
335 memmove(
reinterpret_cast<void*
>(dest),
336 reinterpret_cast<const void*
>(first),
sizeof(
value_type)*count);
340 DARRAY_PRINTF(
"move_elements.mmm.left [%zd .. %zd] -> %zd, dist %zd\n", (first-begin_), ((first + count)-begin_)-1, (dest-begin_), (first-dest));
341 explicit_bzero((
void*)(dest+count), (first-dest)*
sizeof(
value_type));
344 DARRAY_PRINTF(
"move_elements.mmm.right [%zd .. %zd] -> %zd, dist %zd\n", (first-begin_), ((first + count)-begin_)-1, (dest-begin_), (dest-first));
345 explicit_bzero((
void*)first, (dest-first)*
sizeof(
value_type));
352 DARRAY_PRINTF(
"move_elements.def.left [%zd .. %zd] -> %zd, dist %zd\n", (first-begin_), (last-begin_)-1, (dest-begin_), (first-dest));
353 for(; first < last; ++dest, ++first ) {
360 DARRAY_PRINTF(
"move_elements.def.right [%zd .. %zd] -> %zd, dist %zd\n", (first-begin_), (last-begin_)-1, (dest-begin_), (dest-first));
362 for(--last; first <= last; --dest, --last ) {
379 : alloc_inst(), begin_(
nullptr ), end_(
nullptr ), storage_end_(
nullptr ),
391 : alloc_inst( alloc ), begin_( allocStore(
capacity) ), end_( begin_ ), storage_end_( begin_ +
capacity ),
404 : alloc_inst( x.alloc_inst ), begin_( clone_range(x.begin_, x.end_) ), end_( begin_ + x.
size() ),
405 storage_end_( begin_ + x.
size() ), growth_factor_( x.growth_factor_ ) {
418 : alloc_inst( alloc ), begin_( clone_range(x.begin_, x.end_) ), end_( begin_ + x.
size() ),
436 : alloc_inst( alloc ), begin_( clone_range( _capacity, x.begin_, x.end_) ), end_( begin_ + x.
size() ),
437 storage_end_( begin_ + _capacity ), growth_factor_(
growth_factor ) {
451 dtor_range(begin_, end_);
452 growth_factor_ = x.growth_factor_;
453 if( x_size_ > capacity_ ) {
455 begin_ = clone_range(x_size_, x.begin_, x.end_);
456 set_iterator(x_size_, x_size_);
458 ctor_copy_range(begin_, x.begin_, x.end_);
459 set_iterator(x_size_, capacity_);
470 : alloc_inst( std::move(x.alloc_inst) ), begin_( std::move(x.begin_) ), end_( std::move(x.end_) ),
471 storage_end_( std::move(x.storage_end_) ), growth_factor_( std::move(x.growth_factor_) )
476 explicit_bzero((
void*)&x,
sizeof(x));
480 : alloc_inst( std::move(alloc) ), begin_( std::move(x.begin_) ), end_( std::move(x.end_) ),
481 storage_end_( std::move(x.storage_end_) ), growth_factor_( std::move(
growth_factor) )
487 explicit_bzero((
void*)&x,
sizeof(x));
491 x.storage_end_ =
nullptr;
492 x.growth_factor_ = 0.0;
501 DARRAY_PRINTF(
"assignment move.0: x %s\n", x.get_info().c_str());
504 alloc_inst = std::move(x.alloc_inst);
505 begin_ = std::move(x.begin_);
506 end_ = std::move(x.end_);
507 storage_end_ = std::move(x.storage_end_);
508 growth_factor_ = std::move( x.growth_factor_ );
511 explicit_bzero((
void*)&x,
sizeof(x));
514 DARRAY_PRINTF(
"assignment move.X: x %s\n", x.get_info().c_str());
535 : alloc_inst( alloc ), begin_( clone_range_check(_capacity, first, last) ), end_(begin_ +
size_type(last - first) ),
536 storage_end_( begin_ + _capacity ), growth_factor_(
growth_factor ) {
554 template<
class InputIt >
557 : alloc_inst( alloc ), begin_( clone_range_foreign(_capacity, first, last) ), end_(begin_ +
size_type(last - first) ),
558 storage_end_( begin_ + _capacity ), growth_factor_(
growth_factor ) {
571 template<
class InputIt >
573 : alloc_inst( alloc ), begin_( clone_range_foreign(
size_type(last - first), first, last) ), end_(begin_ +
size_type(last - first) ),
585 : alloc_inst( alloc ), begin_( clone_range_foreign(initlist.
size(), initlist.
begin(), initlist.
end()) ),
619 constexpr
iterator storage_end() noexcept {
return storage_end_; }
621 constexpr
const_iterator storage_end() const noexcept {
return storage_end_; }
623 constexpr
const_iterator cstorage_end() const noexcept {
return storage_end_; }
637 return growth_factor_;
650 return std::max<size_type>( std::max<size_type>( MIN_SIZE_AT_GROW, a_capacity+1 ),
651 static_cast<size_type>(a_capacity * growth_factor_ + 0.5f) );
657 constexpr
bool empty() const noexcept {
return begin_ == end_; }
720 if( 0 <= i && i <
size() ) {
730 if( 0 <= i && i <
size() ) {
747 if( new_capacity > capacity_ ) {
748 grow_storage_move(new_capacity);
758 template<
class InputIt >
759 constexpr
void assign( InputIt first, InputIt last ) {
763 dtor_range(begin_, end_);
764 if( x_size_ > capacity_ ) {
766 begin_ = clone_range_foreign(x_size_, first, last);
767 set_iterator(x_size_, x_size_);
769 ctor_copy_range_foreign(begin_, first, last);
770 set_iterator(x_size_, capacity_);
782 dtor_range(begin_, end_);
783 if( x_size_ > capacity_ ) {
785 begin_ = clone_range_check(x_size_, first, last);
786 set_iterator(x_size_, x_size_);
788 ctor_copy_range_check(begin_, first, last);
789 set_iterator(x_size_, capacity_);
797 dtor_range(begin_, end_);
801 storage_end_ =
nullptr;
814 std::swap(growth_factor_, x.growth_factor_);
823 if( begin_ != end_ ) {
833 if( begin_ <= pos && pos < end_ ) {
836 if( 0 < right_count ) {
837 move_elements(
const_cast<value_type*
>(pos), pos+1, right_count);
841 return begin_ <= const_cast<iterator>(pos) &&
const_cast<iterator>(pos) <= end_ ?
const_cast<iterator>(pos) : end_;
849 const size_type count = dtor_range(first, last);
852 if( 0 < right_count ) {
853 move_elements(first, last, right_count);
857 return begin_ <= const_cast<iterator>(first) &&
const_cast<iterator>(first) <= end_ ?
const_cast<iterator>(first) : end_;
873 if( begin_ <= pos && pos <= end_ ) {
875 if( end_ == storage_end_ ) {
878 iterator pos_new = begin_ + pos_idx;
880 if( 0 < right_count ) {
881 move_elements(pos_new+1, pos_new, right_count);
886 return begin_ <= pos_new && pos_new <= end_ ? pos_new : end_;
905 if( begin_ <= pos && pos <= end_ ) {
907 if( end_ == storage_end_ ) {
910 iterator pos_new = begin_ + pos_idx;
912 if( 0 < right_count ) {
913 move_elements(pos_new+1, pos_new, right_count);
918 return begin_ <= pos_new && pos_new <= end_ ? pos_new : end_;
936 template<
typename... Args>
938 if( begin_ <= pos && pos <= end_ ) {
940 if( end_ == storage_end_ ) {
943 iterator pos_new = begin_ + pos_idx;
945 if( 0 < right_count ) {
946 move_elements(pos_new+1, pos_new, right_count);
948 new (pos_new)
value_type( std::forward<Args>(args)... );
951 return begin_ <= pos_new && pos_new <= end_ ? pos_new : end_;
965 template<
class InputIt >
967 if( begin_ <= pos && pos <= end_ ) {
970 if( end_ + new_elem_count >= storage_end_ ) {
971 grow_storage_move(
size() + new_elem_count);
973 iterator pos_new = begin_ + pos_idx;
975 if( 0 < right_count ) {
976 move_elements(pos_new + new_elem_count, pos_new, right_count);
978 ctor_copy_range_foreign(pos_new, first, last);
979 end_ += new_elem_count;
981 return begin_ <= pos_new && pos_new <= end_ ? pos_new : end_;
992 if( end_ == storage_end_ ) {
1004 if( end_ == storage_end_ ) {
1005 grow_storage_move();
1021 template<
typename... Args>
1023 if( end_ == storage_end_ ) {
1024 grow_storage_move();
1026 new (end_)
value_type( std::forward<Args>(args)... );
1038 template<
class InputIt >
1042 if( end_ + count >= storage_end_ ) {
1043 grow_storage_move(
size() + count);
1045 ctor_copy_range_foreign(end_, first, last);
1079 for(
auto it = begin_; it != end_; ) {
1080 if( comparator( *it, x ) ) {
1113 for(
auto it = end_-1; begin_ <= it; --it) {
1114 if( comparator( *it, x ) ) {
1117 if( !all_matching ) {
1129 if( 1 < ++i ) { res.append(
", "); }
1156 template<
typename Value_type,
typename Alloc_type>
1165 template<
typename Value_type,
typename Alloc_type>
1167 if( &rhs == &lhs ) {
1172 template<
typename Value_type,
typename Alloc_type>
1177 template<
typename Value_type,
typename Alloc_type>
1181 template<
typename Value_type,
typename Alloc_type>
1183 {
return lhs < rhs; }
1185 template<
typename Value_type,
typename Alloc_type>
1187 {
return !(lhs < rhs); }
1189 template<
typename Value_type,
typename Alloc_type>
1191 {
return !(rhs < lhs); }
1193 template<
typename Value_type,
typename Alloc_type>
1205 template<
class,
class =
void >