25#ifndef JAU_DYN_ARRAY_HPP_
26#define JAU_DYN_ARRAY_HPP_
33#include <initializer_list>
50 #define JAU_DARRAY_PRINTF0(...) { fprintf(stderr, __VA_ARGS__); fflush(stderr); }
52 #define JAU_DARRAY_PRINTF0(...)
57 #define JAU_DARRAY_PRINTF(...) { fprintf(stderr, __VA_ARGS__); fflush(stderr); }
59 #define JAU_DARRAY_PRINTF(...)
149 template <
typename Value_type,
typename Size_type = jau::n
size_t,
typename Alloc_type = jau::callocator<Value_type>,
150 bool use_memmove = std::is_trivially_copyable_v<Value_type> || is_container_memmove_compliant_v<Value_type>,
151 bool use_secmem = is_enforcing_secmem_v<Value_type>
161 constexpr static const bool uses_realloc = use_memmove && std::is_base_of_v<jau::callocator<Value_type>, Alloc_type>;
186 typedef std::remove_const_t<Value_type> value_type_mutable;
188 typedef value_type_mutable* pointer_mutable;
190 static constexpr void* voidptr_cast(
const_pointer p) {
return reinterpret_cast<void*
>(
const_cast<pointer_mutable
>( p ) ); }
192 constexpr static size_type DIFF_MAX = std::numeric_limits<difference_type>::max();
193 constexpr static size_type MIN_SIZE_AT_GROW = 10;
196 float m_growth_factor;
214 constexpr float growthFactor() const noexcept {
return m_growth_factor; }
236 constexpr bool pinned()
const {
return m_growth_factor < 1.0f; }
238 constexpr bool shared()
const {
return m_growth_factor < 0.0f; }
254 if( size_ > DIFF_MAX ) {
260 std::to_string(
sizeof(
value_type))+
" bytes/element = "+
264 value_type * m = m_alloc_inst.allocate(size_);
265 if(
nullptr == m && size_ > 0 ) {
267 throw jau::OutOfMemoryError(
"alloc "+std::to_string(size_)+
" elements * "+
268 std::to_string(
sizeof(
value_type))+
" bytes/element = "+
277 template<
class _Alloc_type>
279 std::enable_if_t< std::is_base_of_v<jau::callocator<value_type>, _Alloc_type>,
bool > =
true )
282 throw jau::IllegalStateError(
"realloc "+std::to_string(new_capacity_)+
" elements * "+
283 std::to_string(
sizeof(
value_type))+
" bytes/element = "+
287 if( new_capacity_ > DIFF_MAX ) {
288 throw jau::IllegalArgumentError(
"realloc "+std::to_string(new_capacity_)+
" > difference_type max "+
291 value_type * m = m_alloc_inst.reallocate(m_begin, m_storage_end-m_begin, new_capacity_);
292 if(
nullptr == m && new_capacity_ > 0 ) {
293 free(
const_cast<pointer_mutable
>(m_begin));
294 throw jau::OutOfMemoryError(
"realloc "+std::to_string(new_capacity_)+
" elements * "+
295 std::to_string(
sizeof(
value_type))+
" bytes/element = "+
300 template<
class _Alloc_type>
302 std::enable_if_t< !std::is_base_of_v<jau::callocator<value_type>, _Alloc_type>,
bool > =
true )
305 throw jau::UnsupportedOperationException(
"realloc not supported on non allocator_type not based upon jau::callocator",
E_FILE_LINE);
308 constexpr void freeStoreCheck() {
312 if( m_begin && !
shared() ) {
313 m_alloc_inst.deallocate(m_begin, m_storage_end-m_begin);
316 constexpr void freeStore() noexcept {
317 if( m_begin && !
shared() ) {
318 m_alloc_inst.deallocate(m_begin, m_storage_end-m_begin);
322 constexpr void clear_iterator() noexcept {
325 m_storage_end =
nullptr;
326 m_position =
nullptr;
331 const difference_type pos = std::min<difference_type>(size_, m_position - m_begin);
332 m_begin = new_storage_;
333 m_end = new_storage_+size_;
334 m_storage_end = new_storage_+capacity_;
335 m_position = m_begin + pos;
340 m_end = m_begin+size_;
341 m_storage_end = m_begin+capacity_;
343 if( m_position > m_limit) { m_position = m_limit; }
346 constexpr void dtor_one(
iterator pos) {
356 JAU_DARRAY_PRINTF0(
"dtor [%zd .. %zd], count %zd\n", (first-m_begin), (last-m_begin)-1, (last-first)-1);
357 for(; first < last; ++first, ++count ) {
367 JAU_DARRAY_PRINTF0(
"ctor_copy_range [%zd .. %zd] -> ??, dist %zd\n", (first-m_begin), (last-m_begin)-1, (last-first)-1);
385 for(; first < last; ++dest, ++first) {
386 new (
const_cast<pointer_mutable
>(dest))
value_type( *first );
391 JAU_DARRAY_PRINTF0(
"clone_range [0 .. %zd], count %zd\n", (last-first)-1, (last-first)-1);
393 ctor_copy_range(dest, first, last);
397 JAU_DARRAY_PRINTF0(
"clone_range [0 .. %zd], count %zd -> %d\n", (last-m_begin)-1, (last-first)-1, (
int)dest_capacity);
398 pointer dest = allocStore(dest_capacity);
399 ctor_copy_range(dest, first, last);
403 JAU_DARRAY_PRINTF0(
"ctor_copy_range_check [%zd .. %zd] -> ??, dist %zd\n", (first-m_begin), (last-m_begin)-1, (last-first)-1);
407 for(; first < last; ++dest, ++first) {
408 new (
const_cast<pointer_mutable
>(dest))
value_type( *first );
412 JAU_DARRAY_PRINTF0(
"clone_range_check [%zd .. %zd], count %zd -> %d\n", (first-m_begin), (last-m_begin)-1, (last-first)-1, (
int)dest_capacity);
413 if( dest_capacity <
size_type(last-first) ) {
414 throw jau::IllegalArgumentError(
"capacity "+std::to_string(dest_capacity)+
" < source range "+
417 pointer dest = allocStore(dest_capacity);
418 ctor_copy_range_check(dest, first, last);
423 if( m_begin > dest || dest + count > m_end ) {
428 for(
size_type i=0; i < count; ++i, ++dest) {
429 new (
const_cast<pointer_mutable
>(dest))
value_type( val );
433 template<
class InputIt >
434 constexpr static void ctor_copy_range_foreign(
pointer dest, InputIt first, InputIt last) {
436 throw jau::IllegalArgumentError(
"first "+
jau::to_string( first )+
" > last "+
439 for(; first != last; ++dest, ++first) {
440 new (
const_cast<pointer_mutable
>(dest))
value_type( *first );
443 template<
class InputIt >
444 constexpr pointer clone_range_foreign(
const size_t dest_capacity, InputIt first, InputIt last) {
445 if( dest_capacity > std::numeric_limits<size_type>::max() ) {
446 throw jau::IllegalArgumentError(
"capacity "+std::to_string(dest_capacity)+
" > size_type max "+
447 std::to_string(std::numeric_limits<size_type>::max()),
E_FILE_LINE);
449 if( dest_capacity <
size_type(last-first) ) {
450 throw jau::IllegalArgumentError(
"capacity "+std::to_string(dest_capacity)+
" < source range "+
454 ctor_copy_range_foreign(dest, first, last);
458 constexpr void realloc_storage_move(
const size_type new_capacity) {
460 pointer new_storage = allocStore(new_capacity);
464 for(; first < m_end; ++dest, ++first) {
465 new (
const_cast<pointer_mutable
>(dest))
value_type( std::move( *first ) );
470 set_iterator(new_storage,
size(), new_capacity);
472 pointer new_storage = reallocStore<allocator_type>(new_capacity);
473 set_iterator(new_storage,
size(), new_capacity);
475 pointer new_storage = allocStore(new_capacity);
476 ::memcpy(voidptr_cast(new_storage),
477 m_begin, (uint8_t*)m_end-(uint8_t*)m_begin);
479 set_iterator(new_storage,
size(), new_capacity);
482 constexpr void grow_storage_move(
size_type add=1) {
493 ::memmove(voidptr_cast(dest),
498 JAU_DARRAY_PRINTF0(
"move_elements.mmm.left [%zd .. %zd] -> %zd, dist %zd\n", (first-m_begin), ((first + count)-m_begin)-1, (dest-m_begin), (first-dest));
502 JAU_DARRAY_PRINTF0(
"move_elements.mmm.right [%zd .. %zd] -> %zd, dist %zd, size %zu\n", (first-m_begin), ((first + count)-m_begin)-1, (dest-m_begin), (dest-first), (dest-first)*
sizeof(
value_type));
513 JAU_DARRAY_PRINTF0(
"move_elements.def.left [%zd .. %zd] -> %zd, dist %zd\n", (first-m_begin), (last-m_begin)-1, (dest-m_begin), (first-dest));
514 for(; first < last; ++dest, ++first ) {
515 new (
const_cast<pointer_mutable
>(dest))
value_type( std::move( *first ) );
521 JAU_DARRAY_PRINTF0(
"move_elements.def.right [%zd .. %zd] -> %zd, dist %zd\n", (first-m_begin), (last-m_begin)-1, (dest-m_begin), (dest-first));
523 for(--last; first <= last; --dest, --last ) {
524 new (
const_cast<pointer_mutable
>(dest))
value_type( std::move( *last ) );
535 : m_alloc_inst( parent.m_alloc_inst ), m_growth_factor( -1 ),
536 m_begin(
begin ), m_end( m_begin +
size ), m_storage_end( m_begin +
size ),
539 if( m_begin > parent.
end() || m_end > parent.
end() || m_position > m_end || m_limit > m_end ) {
540 throw jau::IllegalArgumentError(
"Slice: Parent "+parent.getInfo()+
", this "+getInfo(), E_FILE_LINE);
542 parent.m_growth_factor = 0;
555 m_begin(
nullptr ), m_end(
nullptr ), m_storage_end(
nullptr ),
556 m_position(m_begin), m_limit(m_end)
568 : m_alloc_inst( alloc ), m_growth_factor( growth_factor ),
569 m_begin( allocStore(
capacity) ), m_end( m_begin ), m_storage_end( m_begin +
capacity ),
570 m_position(m_begin), m_limit(m_end)
584 : m_alloc_inst( alloc ), m_growth_factor( growth_factor ),
585 m_begin( allocStore(
size) ), m_end( m_begin +
size ), m_storage_end( m_begin +
size ),
586 m_position(m_begin), m_limit(m_end)
603 : m_alloc_inst( x.m_alloc_inst ), m_growth_factor( x.m_growth_factor ),
604 m_begin( clone_range(x.m_begin, x.m_end) ), m_end( m_begin + x.
size() ), m_storage_end( m_begin + x.
size() ),
605 m_position(m_begin), m_limit(m_end)
622 : m_alloc_inst( alloc ), m_growth_factor( growth_factor ),
623 m_begin( clone_range(x.m_begin, x.m_end) ), m_end( m_begin + x.
size() ), m_storage_end( m_begin + x.
size() ),
624 m_position(m_begin), m_limit(m_end)
642 : m_alloc_inst( alloc ), m_growth_factor( growth_factor ),
643 m_begin( clone_range( _capacity, x.m_begin, x.m_end) ), m_end( m_begin + x.
size() ), m_storage_end( m_begin + _capacity ),
644 m_position(m_begin), m_limit(m_end)
659 dtor_range(m_begin, m_end);
660 m_growth_factor = x.m_growth_factor;
661 if( x_size_ > capacity_ ) {
662 const difference_type pos = std::min<difference_type>(x_size_, m_position - m_begin);
664 m_begin = clone_range(x_size_, x.m_begin, x.m_end);
665 m_position = m_begin + pos;
666 set_iterator_end(x_size_, x_size_);
668 ctor_copy_range(m_begin, x.m_begin, x.m_end);
669 set_iterator_end(x_size_, capacity_);
680 : m_alloc_inst( std::move(x.m_alloc_inst) ), m_growth_factor( x.m_growth_factor ),
681 m_begin( std::move(x.m_begin) ), m_end( std::move(x.m_end) ), m_storage_end( std::move(x.m_storage_end) ),
682 m_position( std::move(x.m_position) ), m_limit( std::move(x.m_limit) )
691 : m_alloc_inst( std::move(alloc) ), m_growth_factor( growth_factor ),
692 m_begin( std::move(x.m_begin) ), m_end( std::move(x.m_end) ), m_storage_end( std::move(x.m_storage_end) ),
693 m_position( std::move(x.m_position) ), m_limit( std::move(x.m_limit) )
709 m_alloc_inst = std::move(x.m_alloc_inst);
710 m_growth_factor = x.m_growth_factor;
711 m_begin = std::move(x.m_begin);
712 m_end = std::move(x.m_end);
713 m_storage_end = std::move(x.m_storage_end);
714 m_position = std::move(x.m_position);
715 m_limit = std::move(x.m_limit);
742 : m_alloc_inst( alloc ), m_growth_factor( growth_factor ),
743 m_begin( clone_range_check(_capacity, first, last) ), m_end(m_begin +
size_type(last - first) ), m_storage_end( m_begin + _capacity ),
744 m_position(m_begin), m_limit(m_end)
763 template<
class InputIt >
766 : m_alloc_inst( alloc ), m_growth_factor( growth_factor ),
767 m_begin( clone_range_foreign(_capacity, first, last) ), m_end(m_begin +
size_type(last - first) ), m_storage_end( m_begin + _capacity ),
768 m_position(m_begin), m_limit(m_end)
782 template<
class InputIt >
785 m_begin( clone_range_foreign(
size_type(last - first), first, last) ), m_end(m_begin +
size_type(last - first) ),
786 m_storage_end( m_begin +
size_type(last - first) ),
787 m_position(m_begin), m_limit(m_end)
806 m_begin( clone_range_foreign(initlist.
size(), initlist.
begin(), initlist.
end()) ),
807 m_end(m_begin + initlist.
size() ), m_storage_end( m_begin + initlist.
size() ),
808 m_position(m_begin), m_limit(m_end)
838 constexpr iterator storage_end() noexcept {
return m_storage_end; }
839 constexpr const_iterator storage_end() const noexcept {
return m_storage_end; }
840 constexpr const_iterator cstorage_end() const noexcept {
return m_storage_end; }
874 if (m_position > p) { m_position = p; }
880 m_limit = m_position;
881 m_position = m_begin;
887 m_position = m_begin;
902 m_position = m_begin;
913 if( m_position < m_limit ) {
914 return *(m_position++);
931 if( *grow && m_position == m_limit ) {
932 if( m_limit == m_storage_end ) {
941 if( m_position < m_limit ) {
961 if( initlist.size() > std::numeric_limits<size_type>::max() ) {
963 std::to_string(std::numeric_limits<size_type>::max()),
E_FILE_LINE);
966 if( *grow && m_position + count1 > m_limit ) {
968 if( m_limit + count2 > m_storage_end ) {
973 }
else if( m_limit + count2 > m_end ) {
981 if( m_position + count1 - 1 < m_limit ) {
982 ctor_copy_range_foreign(m_position, initlist.begin(), initlist.end());
1001 template<
typename... Targs,
1006 const size_type count1 =
sizeof...(args);
1007 if( *grow && m_position + count1 > m_limit ) {
1009 if( m_limit + count2 > m_storage_end ) {
1012 }
else if( m_limit + count2 > m_end ) {
1018 if( m_position + count1 - 1 < m_limit ) {
1019 ( (*m_position++ =
static_cast<Value_type>(args)), ... );
1039 return darray(*
this, m_position, m_position, m_position+new_size, new_size);
1051 if(m_position + idx + length > m_limit) {
1054 return darray(*
this, m_position+idx, m_position+idx, m_position+idx+length, length);
1066 m_growth_factor = 0;
1067 return darray(*
this, m_begin, m_position, m_limit,
size());
1073 constexpr bool hasRemaining() const noexcept {
return m_position < m_limit; }
1080 return m_alloc_inst;
1097 return std::max<size_type>( std::max<size_type>( MIN_SIZE_AT_GROW, a_capacity+add ),
1104 constexpr bool empty() const noexcept {
return m_begin == m_end; }
1153 return *(m_begin+i);
1160 return *(m_begin+i);
1167 if( 0 <= i && i <
size() ) {
1168 return *(m_begin+i);
1177 if( 0 <= i && i <
size() ) {
1178 return *(m_begin+i);
1194 realloc_storage_move(new_capacity);
1204 if( new_size > sz ) {
1206 realloc_storage_move(new_size);
1208 const size_type new_elem_count = new_size - sz;
1209 m_end += new_elem_count;
1210 m_limit += new_elem_count;
1211 ctor_copy_value(m_begin + sz, new_elem_count, val);
1212 }
else if( new_size < sz ) {
1213 const size_type del_elem_count = dtor_range(m_begin + new_size, m_end);
1214 assert(sz - new_size == del_elem_count);
1215 m_end -= del_elem_count;
1233 realloc_storage_move(size_);
1244 template<
class InputIt >
1245 constexpr void assign( InputIt first, InputIt last ) {
1249 dtor_range(m_begin, m_end);
1250 if( x_size_ > capacity_ ) {
1251 const difference_type pos = std::min<difference_type>(x_size_, m_position - m_begin);
1253 m_begin = clone_range_foreign(x_size_, first, last);
1254 m_position = m_begin + pos;
1255 set_iterator_end(x_size_, x_size_);
1257 ctor_copy_range_foreign(m_begin, first, last);
1258 set_iterator_end(x_size_, capacity_);
1270 dtor_range(m_begin, m_end);
1271 if( x_size_ > capacity_ ) {
1272 const difference_type pos = std::min<difference_type>(x_size_, m_position - m_begin);
1274 m_begin = clone_range_check(x_size_, first, last);
1275 m_position = m_begin + pos;
1276 set_iterator_end(x_size_, x_size_);
1278 ctor_copy_range_check(m_begin, first, last);
1279 set_iterator_end(x_size_, capacity_);
1294 dtor_range(m_begin, m_end);
1296 m_position = m_begin;
1320 m_storage_end =
nullptr;
1321 m_position =
nullptr;
1333 std::swap(m_alloc_inst, x.m_alloc_inst);
1334 std::swap(m_growth_factor, x.m_growth_factor);
1335 std::swap(m_begin, x.m_begin);
1336 std::swap(m_end, x.m_end);
1337 std::swap(m_storage_end, x.m_storage_end);
1338 std::swap(m_position, x.m_position);
1339 std::swap(m_limit, x.m_limit);
1350 if( m_begin != m_end ) {
1351 dtor_one( --m_end );
1353 if( m_position > m_limit ) { m_position = m_limit; }
1366 if( m_begin <= pos && pos < m_end ) {
1369 if( 0 < right_count ) {
1370 move_elements(pos, pos+1, right_count);
1373 if( m_position > m_begin && m_position > pos ) { --m_position; }
1375 return m_begin <= pos && pos <= m_end ? pos : m_end;
1387 const size_type count = dtor_range(first, clast);
1390 if( 0 < right_count ) {
1391 move_elements(first, clast, right_count);
1395 if( m_position > m_begin && m_position > first )
1396 { m_position -= std::min(count,
size_type(m_position - first)); }
1398 return m_begin <= first && first <= m_end ? first : m_end;
1409 return erase(m_begin + pos_idx);
1420 return erase(m_begin + first_idx, m_begin + last_idx);
1435 if( m_begin <= pos && pos <= m_end ) {
1436 if( m_end == m_storage_end ) {
1437 const size_type pos_idx = pos - m_begin;
1438 grow_storage_move();
1439 pos = m_begin + pos_idx;
1442 if( 0 < right_count ) {
1443 move_elements(
const_cast<iterator>(pos+1), pos, right_count);
1445 new (
const_cast<pointer_mutable
>(pos))
value_type( x );
1448 return m_begin <= pos && pos <= m_end ? const_cast<iterator>(pos) : m_end;
1461 return insert(m_begin + pos_idx, x);
1476 if( m_begin <= pos && pos <= m_end ) {
1477 const size_type pos_idx = pos - m_begin;
1478 if( m_end == m_storage_end ) {
1479 grow_storage_move();
1481 iterator pos_new = m_begin + pos_idx;
1483 if( 0 < right_count ) {
1484 move_elements(pos_new+1, pos_new, right_count);
1486 new (
const_cast<pointer_mutable
>(pos_new))
value_type( std::move( x ) );
1489 return m_begin <= pos_new && pos_new <= m_end ? pos_new : m_end;
1506 template<
typename... Args>
1508 if( m_begin <= pos && pos <= m_end ) {
1509 const size_type pos_idx = pos - m_begin;
1510 if( m_end == m_storage_end ) {
1511 grow_storage_move();
1513 iterator pos_new = m_begin + pos_idx;
1515 if( 0 < right_count ) {
1516 move_elements(pos_new+1, pos_new, right_count);
1518 new (
const_cast<pointer_mutable
>(pos_new))
value_type( std::forward<Args>(args)... );
1521 return m_begin <= pos_new && pos_new <= m_end ? pos_new : m_end;
1538 template<
class InputIt >
1540 if( m_begin <= pos && pos <= m_end ) {
1542 const size_type pos_idx = pos - m_begin;
1543 if( m_end + new_elem_count > m_storage_end ) {
1544 grow_storage_move(new_elem_count);
1546 iterator pos_new = m_begin + pos_idx;
1548 if( 0 < right_count ) {
1549 move_elements(pos_new + new_elem_count, pos_new, right_count);
1551 ctor_copy_range_foreign(pos_new, first, last);
1552 m_end += new_elem_count;
1555 return m_begin <= pos_new && pos_new <= m_end ? pos_new : m_end;
1569 if( m_end == m_storage_end ) {
1570 grow_storage_move();
1572 new (
const_cast<pointer_mutable
>(m_end))
value_type( x );
1574 m_position = m_limit;
1585 if( m_end == m_storage_end ) {
1586 grow_storage_move();
1588 new (
const_cast<pointer_mutable
>(m_end))
value_type( std::move(x) );
1590 m_position = m_limit;
1602 if( initlist.size() > std::numeric_limits<size_type>::max() ) {
1604 std::to_string(std::numeric_limits<size_type>::max()),
E_FILE_LINE);
1607 if( m_end + count1 > m_storage_end ) {
1610 const size_type count2 = epos + count1 - spos;
1613 ctor_copy_range_foreign(m_end, initlist.begin(), initlist.end());
1616 m_position = m_limit;
1638 insert(m_begin, std::move(x));
1650 template<
typename... Args>
1652 if( m_end == m_storage_end ) {
1653 grow_storage_move();
1655 new (
const_cast<pointer_mutable
>(m_end))
value_type( std::forward<Args>(args)... );
1671 template<
class InputIt >
1675 if( m_end + count > m_storage_end ) {
1676 grow_storage_move(count);
1678 ctor_copy_range_foreign(m_end, first, last);
1692 template <
typename... Args>
1695 const size_type count =
sizeof...(Args);
1699 if( m_end + count > m_storage_end ) {
1700 grow_storage_move(count);
1703 (
new (
const_cast<pointer_mutable
>(m_end++))
value_type( args ), ... );
1719 template <
typename... Args>
1722 const size_type count =
sizeof...(Args);
1726 if( m_end + count > m_storage_end ) {
1727 grow_storage_move(count);
1730 (
new (
const_cast<pointer_mutable
>(m_end++))
value_type( std::move(args) ), ... );
1768 for(
auto it = m_begin; it != m_end; ) {
1769 if( comparator( *it, x ) ) {
1803 for(
auto it = m_end-1; m_begin <= it; --it) {
1804 if( comparator( *it, x ) ) {
1807 if( !all_matching ) {
1829 template<
class UnaryPredicate>
1832 for(
auto it = m_end-1; m_begin <= it; --it) {
1836 if( !all_matching ) {
1848 if( 1 < ++i ) { res.append(
", "); }
1860 ", size "+std::to_string(size_)+
" / "+std::to_string(cap_)+
1863 res.append(
"pinned");
1865 res.append(
", shared");
1868 res.append(
"], growth "+std::to_string(m_growth_factor)+
1869 ", type[integral "+std::to_string(std::is_integral_v<Value_type>)+
1870 ", trivialCpy "+std::to_string(std::is_trivially_copyable_v<Value_type>)+
1875 ", [pos "+std::to_string(m_position-m_begin)+
1876 ", lim "+std::to_string(m_limit-m_begin)+
1878 ", send "+std::to_string(m_storage_end-m_begin)+
" "+
jau::toHexString(m_storage_end)+
1905 template <
typename First,
typename... Next,
1907 std::enable_if_t< std::conjunction_v<std::is_same<First, Next>... >,
bool> =
true>
1927 template <
typename First,
typename... Next>
1931 d.
push_back( std::forward<First>(arg1) );
1938 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1947 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1949 if( &rhs == &lhs ) {
1954 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1959 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1963 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1965 {
return lhs < rhs; }
1967 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1969 {
return !(lhs < rhs); }
1971 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1973 {
return !(rhs < lhs); }
1975 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1987 template<
class,
class =
void >
Implementation of a dynamic linear array storage, aka vector, including relative positional access.
constexpr self_t & rewind() noexcept
Sets position to zero.
constexpr void push_front(value_type &&x)
Like std::vector::push_front(), move.
darray< value_type, size_type, allocator_type, use_memmove, use_secmem > self_t
static constexpr size_type max_size() noexcept
Returns std::numeric_limits<difference_type>::max() as the maximum array size.
constexpr_cxx20 self_t & put(const_reference v, Bool grow=Bool::False)
Relative put() for single value, increasing position().
const jau::type_info & valueSignature() const noexcept
Returns type signature of implementing class's stored value type.
const allocator_type & get_allocator_ref() const noexcept
constexpr iterator insert(const_iterator pos, InputIt first, InputIt last)
Like std::vector::insert(), inserting the value_type range [first, last).
constexpr void push_back(InputIt first, InputIt last)
Like std::vector::push_back(), but appends the value_type range [first, last).
const jau::type_info & classSignature() const noexcept
Returns type signature of implementing class.
const value_type * const_iterator
constexpr size_type erase_if(const bool all_matching, UnaryPredicate p)
Erase either the first matching element or all matching elements.
constexpr void swap(darray &x) noexcept
Like std::vector::swap().
constexpr void assign(InputIt first, InputIt last)
Like std::vector::assign()
constexpr darray & operator=(const darray &x)
Like std::vector::operator=(&), assignment.
bool(* equal_comparator)(const value_type &a, const value_type &b)
std::make_signed_t< size_type > difference_type
constexpr_cxx20 const_reference at(size_type i) const
Like std::vector::at(size_type), immutable reference.
constexpr void assign(const_iterator first, const_iterator last)
Like std::vector::assign(), but non-template overload using const_iterator.
constexpr_cxx20 const_reference operator[](size_type i) const noexcept
Like std::vector::operator[](size_type), immutable reference.
constexpr iterator erase(const_iterator cpos)
Like std::vector::erase(), removes the elements at pos.
static constexpr const bool uses_secmem
constexpr reference front()
Like std::vector::front(), mutable access.
constexpr darray(std::initializer_list< value_type > initlist, const allocator_type &alloc=allocator_type())
Create a new instance from an initializer list.
constexpr_cxx20 self_t & put(std::initializer_list< value_type > initlist, Bool grow=Bool::False)
Relative put() for an initializer list of same type, increasing position().
constexpr const_iterator begin() const noexcept
constexpr_cxx20 const_reference get()
Relative get() for single value reference, increasing position() by one.
constexpr iterator end() noexcept
constexpr_cxx20 reference at(size_type i)
Like std::vector::at(size_type), mutable reference.
constexpr size_type capacity() const noexcept
constexpr const_iterator cend() const noexcept
constexpr size_type size() const noexcept
Like std::vector::size().
constexpr void push_back(value_type &&x)
Like std::vector::push_back(), move.
const value_type * const_pointer
constexpr const_iterator end() const noexcept
constexpr void push_back(const value_type &x)
Like std::vector::push_back(), copy.
constexpr darray(darray &&x) noexcept
constexpr self_t & resize(size_type new_size)
Like std::vector::resize(size_type)
constexpr reference emplace_back(Args &&... args)
Like std::vector::emplace_back(), construct a new element in place at the end().
constexpr self_t & clear() noexcept
Like std::vector::clear(), calls destructor on all elements and leaving capacity unchanged.
constexpr darray(const darray &x)
Creates a new instance, copying all elements from the given darray.
constexpr size_type position() const noexcept
constexpr iterator erase(const_iterator cfirst, const_iterator clast)
Like std::vector::erase(), removes the elements in the range [first, last).
allocator_type allocator_type
constexpr iterator erase(const size_type first_idx, const size_type last_idx)
Similar to std::vector::erase() using indices, removes the elements in the range [first_idx,...
constexpr size_type erase_matching(const value_type &x, const bool all_matching, equal_comparator comparator)
Erase either the first matching element or all matching elements using erase().
constexpr darray(InputIt first, InputIt last, const allocator_type &alloc=allocator_type())
Creates a new instance, copying all elements from the given template input-iterator value_type range ...
constexpr bool pinned() const
Returns true if growthFactor() < 1, otherwise false.
constexpr bool shared() const
Returns true if growthFactor() < 0, otherwise false.
constexpr iterator insert(const size_type pos_idx, const value_type &x)
Similar to std::vector::insert() using an index, copy.
std::string toString() const noexcept
constexpr bool empty() const noexcept
Like std::vector::empty().
constexpr const_pointer data() const noexcept
Like std::vector::data(), const immutable pointer.
constexpr darray & operator=(darray &&x) noexcept
Like std::vector::operator=(&&), move.
constexpr const_iterator cbegin() const noexcept
constexpr bool capacity_reached() const noexcept
Returns true if capacity has been reached and the next push_back() will grow the storage and invalida...
self_t & setLimit(size_type v)
Sets new limit and adjusts position if new limit is below.
constexpr pointer data() noexcept
Like std::vector::data(), mutable pointer.
constexpr const_pointer limit_ptr() const noexcept
Pointer to immutable read/write limit, one element beyond maximum element with limit <= size/end.
constexpr darray() noexcept
Default constructor, giving zero capacity and zero memory footprint.
constexpr darray(size_type capacity, const float growth_factor=DEFAULT_GROWTH_FACTOR, const allocator_type &alloc=allocator_type())
Creating an empty instance with initial capacity and other (default) properties.
constexpr darray(darray &parent, pointer begin, pointer position, pointer limit, size_type size)
Slicing ctor.
constexpr_cxx20 reference operator[](size_type i) noexcept
Like std::vector::operator[](size_type), mutable reference.
constexpr darray(std::nullptr_t, size_type size, value_type value=value_type(), const float growth_factor=DEFAULT_GROWTH_FACTOR, const allocator_type &alloc=allocator_type())
Creating a sized instance with initial size elements with default value.
constexpr size_type limit() const noexcept
self_t & setPosition(size_type v)
Sets position.
constexpr darray(darray &&x, const float growth_factor, const allocator_type &alloc) noexcept
constexpr iterator insert(const_iterator pos, const value_type &x)
Like std::vector::insert(), copy.
constexpr iterator begin() noexcept
constexpr void push_back_list(const Args &... args)
Like push_back(), but for more multiple const r-value to copy.
constexpr_cxx20 self_t & putN(Bool grow, const Targs &...args)
Relative put() for multiple value of an assignable type fitting into value_type, increasing position(...
constexpr void push_back_list(Args &&... args)
Like push_back(), but for more multiple r-value references to move.
constexpr pointer position_ptr() noexcept
Pointer to mutable next relative read/write element index, with 0 <= position <= limit.
constexpr self_t & clearPosition() noexcept
Clears the relative position and limit w/o destructing elements nor mutating storage.
static constexpr const bool uses_realloc
allocator_type get_allocator() const noexcept
constexpr iterator erase(const size_type pos_idx)
Similar to std::vector::erase() using an index, removes the elements at pos_idx.
constexpr bool push_back_unique(const value_type &x, equal_comparator comparator)
Like std::vector::push_back(), but only if the newly added element does not yet exist.
constexpr bool hasRemaining() const noexcept
Returns whether position < limit, i.e.
self_t slice()
Returns a sliced duplicate starting from this buffers' current position.
constexpr self_t & reserve(size_type new_capacity)
Like std::vector::reserve(), increases this instance's capacity to new_capacity.
constexpr iterator insert(const_iterator pos, value_type &&x)
Like std::vector::insert(), move.
constexpr const_reference front() const
Like std::vector::front(), immutable access.
static constexpr const bool uses_memmove
constexpr self_t & shrink_to_fit()
Like std::vector::shrink_to_fit(), but ensured constexpr.
self_t slice(size_type idx, size_type length)
Returns a sliced duplicate starting from the given idx.
constexpr iterator emplace(const_iterator pos, Args &&... args)
Like std::vector::emplace(), construct a new element in place.
const value_type & const_reference
constexpr darray(const size_type _capacity, const_iterator first, const_iterator last, const float growth_factor=DEFAULT_GROWTH_FACTOR, const allocator_type &alloc=allocator_type())
Creates a new instance with custom initial storage capacity, copying all elements from the given cons...
constexpr self_t & resize(size_type new_size, const value_type &val)
Like std::vector::resize(size_type, const value_type&)
constexpr const_pointer position_ptr() const noexcept
Pointer to immutable next relative read/write element index, with 0 <= position <= limit.
constexpr_cxx20 void push_back(std::initializer_list< value_type > initlist)
Like std::push_back(), but for an initializer list to copy.
constexpr void setGrowthFactor(float v) noexcept
Sets the growth factor when size() == capacity() is reached for growing operations,...
constexpr float growthFactor() const noexcept
Returns growth factor, see setGrowthFactor() for semantics.
constexpr self_t & clear(bool releaseMem) noexcept
Like std::vector::clear(), calls destructor on all elements.
static constexpr const float DEFAULT_GROWTH_FACTOR
constexpr reference back()
Like std::vector::back(), mutable access.
constexpr darray(const size_type _capacity, InputIt first, InputIt last, const float growth_factor=DEFAULT_GROWTH_FACTOR, const allocator_type &alloc=allocator_type())
Creates a new instance with custom initial storage capacity, copying all elements from the given temp...
constexpr void pop_back() noexcept
Like std::vector::pop_back().
constexpr const_reference back() const
Like std::vector::back(), immutable access.
constexpr size_type get_grown_capacity(size_type add=1) const noexcept
Return the current capacity() multiplied by the growth factor, minimum is max(capacity()+add,...
constexpr size_type remaining() const noexcept
Returns limit - position.
constexpr void push_front(const value_type &x)
Like std::vector::push_front(), copy.
self_t duplicate()
Returns a duplicate with same position and limit.
constexpr darray(const darray &x, const size_type _capacity, const float growth_factor, const allocator_type &alloc)
Creates a new instance with custom initial storage capacity, copying all elements from the given darr...
constexpr self_t & flip() noexcept
Sets limit to position and position to zero.
constexpr darray(const darray &x, const float growth_factor, const allocator_type &alloc)
Creates a new instance, copying all elements from the given darray.
std::string getInfo() const noexcept
Generic type information using either Runtime type information (RTTI) or Compile time type informatio...
#define JAU_DARRAY_PRINTF(...)
#define JAU_DARRAY_PRINTF0(...)
constexpr UnaryFunction for_each_const(T &data, UnaryFunction f, std::enable_if_t< is_cow_type< T >::value, bool >=true) noexcept
std::ostream & operator<<(std::ostream &out, const bitfield_t< StorageType, BitSize > &v)
std::tuple_element_t< 0, std::tuple< Ts... > > first_type
#define constexpr_cxx20
constexpr qualifier replacement for C++20 constexpr.
constexpr bool value(const Bool rhs) noexcept
#define PRAGMA_DISABLE_WARNING_PUSH
constexpr bool is_all_same_v
#define PRAGMA_DISABLE_WARNING_STRINGOP_OVERFLOW
const jau::type_info & static_ctti() noexcept
Returns a static global reference of make_ctti<T>(true) w/ identity instance.
constexpr std::string_view name(const Bool v) noexcept
#define PRAGMA_DISABLE_WARNING_POP
#define PRAGMA_DISABLE_WARNING_NULL_DEREFERENCE
Bool
Boolean type without implicit conversion, safe for function parameter.
bool operator>=(const cow_darray< Value_type, Size_type, Alloc_type > &rhs, const cow_darray< Value_type, Size_type, Alloc_type > &lhs)
constexpr darray< First > make_darray(First &&arg1, Next &&... argsN)
Construct a darray<T> instance, initialized by move semantics from the variadic (template pack) argum...
bool operator>(const cow_darray< Value_type, Size_type, Alloc_type > &rhs, const cow_darray< Value_type, Size_type, Alloc_type > &lhs)
bool operator<(const cow_darray< Value_type, Size_type, Alloc_type > &rhs, const cow_darray< Value_type, Size_type, Alloc_type > &lhs)
void swap(cow_darray< Value_type, Size_type, Alloc_type > &rhs, cow_darray< Value_type, Size_type, Alloc_type > &lhs) noexcept
bool operator<=(const cow_darray< Value_type, Size_type, Alloc_type > &rhs, const cow_darray< Value_type, Size_type, Alloc_type > &lhs)
@ free
Denotes a func::free_target_t.
void zero_bytes_sec(void *s, size_t n) noexcept __attrdecl_no_optimize__
Wrapper to ::explicit_bzero(), ::bzero() or ::memset(), whichever is available in that order.
std::string toHexString(const void *data, const nsize_t length, const lb_endian_t byteOrder=lb_endian_t::big, const LoUpCase capitalization=LoUpCase::lower, const PrefixOpt prefix=PrefixOpt::prefix) noexcept
Produce a hexadecimal string representation of the given lsb-first byte values.
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
bool operator==(const callocator< T1 > &lhs, const callocator< T2 > &rhs) noexcept
std::string to_string(const bit_order_t v) noexcept
Return std::string representation of the given bit_order_t.
bool operator!=(const callocator< T1 > &lhs, const callocator< T2 > &rhs) noexcept
template< class T > is_darray_type<T>::value compile-time Type Trait, determining whether the given t...