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);
386 for(; first < last; ++dest, ++first) {
387 new (
const_cast<pointer_mutable
>(dest))
value_type( *first );
392 JAU_DARRAY_PRINTF0(
"clone_range [0 .. %zd], count %zd\n", (last-first)-1, (last-first)-1);
394 ctor_copy_range(dest, first, last);
398 JAU_DARRAY_PRINTF0(
"clone_range [0 .. %zd], count %zd -> %d\n", (last-m_begin)-1, (last-first)-1, (
int)dest_capacity);
399 pointer dest = allocStore(dest_capacity);
400 ctor_copy_range(dest, first, last);
404 JAU_DARRAY_PRINTF0(
"ctor_copy_range_check [%zd .. %zd] -> ??, dist %zd\n", (first-m_begin), (last-m_begin)-1, (last-first)-1);
408 for(; first < last; ++dest, ++first) {
409 new (
const_cast<pointer_mutable
>(dest))
value_type( *first );
413 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);
414 if( dest_capacity <
size_type(last-first) ) {
415 throw jau::IllegalArgumentError(
"capacity "+std::to_string(dest_capacity)+
" < source range "+
418 pointer dest = allocStore(dest_capacity);
419 ctor_copy_range_check(dest, first, last);
424 if( m_begin > dest || dest + count > m_end ) {
429 for(
size_type i=0; i < count; ++i, ++dest) {
430 new (
const_cast<pointer_mutable
>(dest))
value_type( val );
434 template<
class InputIt >
435 constexpr static void ctor_copy_range_foreign(
pointer dest, InputIt first, InputIt last) {
437 throw jau::IllegalArgumentError(
"first "+
jau::to_string( first )+
" > last "+
440 for(; first != last; ++dest, ++first) {
441 new (
const_cast<pointer_mutable
>(dest))
value_type( *first );
444 template<
class InputIt >
445 constexpr pointer clone_range_foreign(
const size_t dest_capacity, InputIt first, InputIt last) {
446 if( dest_capacity > std::numeric_limits<size_type>::max() ) {
447 throw jau::IllegalArgumentError(
"capacity "+std::to_string(dest_capacity)+
" > size_type max "+
448 std::to_string(std::numeric_limits<size_type>::max()),
E_FILE_LINE);
450 if( dest_capacity <
size_type(last-first) ) {
451 throw jau::IllegalArgumentError(
"capacity "+std::to_string(dest_capacity)+
" < source range "+
455 ctor_copy_range_foreign(dest, first, last);
459 constexpr void realloc_storage_move(
const size_type new_capacity) {
461 pointer new_storage = allocStore(new_capacity);
465 for(; first < m_end; ++dest, ++first) {
466 new (
const_cast<pointer_mutable
>(dest))
value_type( std::move( *first ) );
471 set_iterator(new_storage,
size(), new_capacity);
473 pointer new_storage = reallocStore<allocator_type>(new_capacity);
474 set_iterator(new_storage,
size(), new_capacity);
476 pointer new_storage = allocStore(new_capacity);
477 ::memcpy(voidptr_cast(new_storage),
478 m_begin, (uint8_t*)m_end-(uint8_t*)m_begin);
480 set_iterator(new_storage,
size(), new_capacity);
483 constexpr void grow_storage_move(
size_type add=1) {
494 ::memmove(voidptr_cast(dest),
499 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));
503 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));
514 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));
515 for(; first < last; ++dest, ++first ) {
516 new (
const_cast<pointer_mutable
>(dest))
value_type( std::move( *first ) );
522 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));
524 for(--last; first <= last; --dest, --last ) {
525 new (
const_cast<pointer_mutable
>(dest))
value_type( std::move( *last ) );
536 : m_alloc_inst( parent.m_alloc_inst ), m_growth_factor( -1 ),
537 m_begin(
begin ), m_end( m_begin +
size ), m_storage_end( m_begin +
size ),
540 if( m_begin > parent.
end() || m_end > parent.
end() || m_position > m_end || m_limit > m_end ) {
541 throw jau::IllegalArgumentError(
"Slice: Parent "+parent.getInfo()+
", this "+getInfo(), E_FILE_LINE);
543 parent.m_growth_factor = 0;
556 m_begin(
nullptr ), m_end(
nullptr ), m_storage_end(
nullptr ),
557 m_position(m_begin), m_limit(m_end)
569 : m_alloc_inst( alloc ), m_growth_factor( growth_factor ),
570 m_begin( allocStore(
capacity) ), m_end( m_begin ), m_storage_end( m_begin +
capacity ),
571 m_position(m_begin), m_limit(m_end)
585 : m_alloc_inst( alloc ), m_growth_factor( growth_factor ),
586 m_begin( allocStore(
size) ), m_end( m_begin +
size ), m_storage_end( m_begin +
size ),
587 m_position(m_begin), m_limit(m_end)
604 : m_alloc_inst( x.m_alloc_inst ), m_growth_factor( x.m_growth_factor ),
605 m_begin( clone_range(x.m_begin, x.m_end) ), m_end( m_begin + x.
size() ), m_storage_end( m_begin + x.
size() ),
606 m_position(m_begin), m_limit(m_end)
623 : m_alloc_inst( alloc ), m_growth_factor( growth_factor ),
624 m_begin( clone_range(x.m_begin, x.m_end) ), m_end( m_begin + x.
size() ), m_storage_end( m_begin + x.
size() ),
625 m_position(m_begin), m_limit(m_end)
643 : m_alloc_inst( alloc ), m_growth_factor( growth_factor ),
644 m_begin( clone_range( _capacity, x.m_begin, x.m_end) ), m_end( m_begin + x.
size() ), m_storage_end( m_begin + _capacity ),
645 m_position(m_begin), m_limit(m_end)
660 dtor_range(m_begin, m_end);
661 m_growth_factor = x.m_growth_factor;
662 if( x_size_ > capacity_ ) {
663 const difference_type pos = std::min<difference_type>(x_size_, m_position - m_begin);
665 m_begin = clone_range(x_size_, x.m_begin, x.m_end);
666 m_position = m_begin + pos;
667 set_iterator_end(x_size_, x_size_);
669 ctor_copy_range(m_begin, x.m_begin, x.m_end);
670 set_iterator_end(x_size_, capacity_);
681 : m_alloc_inst( std::move(x.m_alloc_inst) ), m_growth_factor( x.m_growth_factor ),
682 m_begin( std::move(x.m_begin) ), m_end( std::move(x.m_end) ), m_storage_end( std::move(x.m_storage_end) ),
683 m_position( std::move(x.m_position) ), m_limit( std::move(x.m_limit) )
692 : m_alloc_inst( std::move(alloc) ), m_growth_factor( growth_factor ),
693 m_begin( std::move(x.m_begin) ), m_end( std::move(x.m_end) ), m_storage_end( std::move(x.m_storage_end) ),
694 m_position( std::move(x.m_position) ), m_limit( std::move(x.m_limit) )
710 m_alloc_inst = std::move(x.m_alloc_inst);
711 m_growth_factor = x.m_growth_factor;
712 m_begin = std::move(x.m_begin);
713 m_end = std::move(x.m_end);
714 m_storage_end = std::move(x.m_storage_end);
715 m_position = std::move(x.m_position);
716 m_limit = std::move(x.m_limit);
743 : m_alloc_inst( alloc ), m_growth_factor( growth_factor ),
744 m_begin( clone_range_check(_capacity, first, last) ), m_end(m_begin +
size_type(last - first) ), m_storage_end( m_begin + _capacity ),
745 m_position(m_begin), m_limit(m_end)
764 template<
class InputIt >
767 : m_alloc_inst( alloc ), m_growth_factor( growth_factor ),
768 m_begin( clone_range_foreign(_capacity, first, last) ), m_end(m_begin +
size_type(last - first) ), m_storage_end( m_begin + _capacity ),
769 m_position(m_begin), m_limit(m_end)
783 template<
class InputIt >
786 m_begin( clone_range_foreign(
size_type(last - first), first, last) ), m_end(m_begin +
size_type(last - first) ),
787 m_storage_end( m_begin +
size_type(last - first) ),
788 m_position(m_begin), m_limit(m_end)
807 m_begin( clone_range_foreign(initlist.
size(), initlist.
begin(), initlist.
end()) ),
808 m_end(m_begin + initlist.
size() ), m_storage_end( m_begin + initlist.
size() ),
809 m_position(m_begin), m_limit(m_end)
839 constexpr iterator storage_end() noexcept {
return m_storage_end; }
840 constexpr const_iterator storage_end() const noexcept {
return m_storage_end; }
841 constexpr const_iterator cstorage_end() const noexcept {
return m_storage_end; }
875 if (m_position > p) { m_position = p; }
881 m_limit = m_position;
882 m_position = m_begin;
888 m_position = m_begin;
903 m_position = m_begin;
914 if( m_position < m_limit ) {
915 return *(m_position++);
932 if( *grow && m_position == m_limit ) {
933 if( m_limit == m_storage_end ) {
942 if( m_position < m_limit ) {
962 if( initlist.size() > std::numeric_limits<size_type>::max() ) {
964 std::to_string(std::numeric_limits<size_type>::max()),
E_FILE_LINE);
967 if( *grow && m_position + count1 > m_limit ) {
969 if( m_limit + count2 > m_storage_end ) {
974 }
else if( m_limit + count2 > m_end ) {
982 if( m_position + count1 - 1 < m_limit ) {
983 ctor_copy_range_foreign(m_position, initlist.begin(), initlist.end());
1002 template<
typename... Targs,
1007 const size_type count1 =
sizeof...(args);
1008 if( *grow && m_position + count1 > m_limit ) {
1010 if( m_limit + count2 > m_storage_end ) {
1013 }
else if( m_limit + count2 > m_end ) {
1019 if( m_position + count1 - 1 < m_limit ) {
1020 ( (*m_position++ =
static_cast<Value_type>(args)), ... );
1040 return darray(*
this, m_position, m_position, m_position+new_size, new_size);
1052 if(m_position + idx + length > m_limit) {
1055 return darray(*
this, m_position+idx, m_position+idx, m_position+idx+length, length);
1067 m_growth_factor = 0;
1068 return darray(*
this, m_begin, m_position, m_limit,
size());
1074 constexpr bool hasRemaining() const noexcept {
return m_position < m_limit; }
1081 return m_alloc_inst;
1098 return std::max<size_type>( std::max<size_type>( MIN_SIZE_AT_GROW, a_capacity+add ),
1105 constexpr bool empty() const noexcept {
return m_begin == m_end; }
1154 return *(m_begin+i);
1161 return *(m_begin+i);
1168 if( 0 <= i && i <
size() ) {
1169 return *(m_begin+i);
1178 if( 0 <= i && i <
size() ) {
1179 return *(m_begin+i);
1195 realloc_storage_move(new_capacity);
1205 if( new_size > sz ) {
1207 realloc_storage_move(new_size);
1209 const size_type new_elem_count = new_size - sz;
1210 m_end += new_elem_count;
1211 m_limit += new_elem_count;
1212 ctor_copy_value(m_begin + sz, new_elem_count, val);
1213 }
else if( new_size < sz ) {
1214 const size_type del_elem_count = dtor_range(m_begin + new_size, m_end);
1215 assert(sz - new_size == del_elem_count);
1216 m_end -= del_elem_count;
1234 realloc_storage_move(size_);
1245 template<
class InputIt >
1246 constexpr void assign( InputIt first, InputIt last ) {
1250 dtor_range(m_begin, m_end);
1251 if( x_size_ > capacity_ ) {
1252 const difference_type pos = std::min<difference_type>(x_size_, m_position - m_begin);
1254 m_begin = clone_range_foreign(x_size_, first, last);
1255 m_position = m_begin + pos;
1256 set_iterator_end(x_size_, x_size_);
1258 ctor_copy_range_foreign(m_begin, first, last);
1259 set_iterator_end(x_size_, capacity_);
1271 dtor_range(m_begin, m_end);
1272 if( x_size_ > capacity_ ) {
1273 const difference_type pos = std::min<difference_type>(x_size_, m_position - m_begin);
1275 m_begin = clone_range_check(x_size_, first, last);
1276 m_position = m_begin + pos;
1277 set_iterator_end(x_size_, x_size_);
1279 ctor_copy_range_check(m_begin, first, last);
1280 set_iterator_end(x_size_, capacity_);
1295 dtor_range(m_begin, m_end);
1297 m_position = m_begin;
1321 m_storage_end =
nullptr;
1322 m_position =
nullptr;
1334 std::swap(m_alloc_inst, x.m_alloc_inst);
1335 std::swap(m_growth_factor, x.m_growth_factor);
1336 std::swap(m_begin, x.m_begin);
1337 std::swap(m_end, x.m_end);
1338 std::swap(m_storage_end, x.m_storage_end);
1339 std::swap(m_position, x.m_position);
1340 std::swap(m_limit, x.m_limit);
1351 if( m_begin != m_end ) {
1352 dtor_one( --m_end );
1354 if( m_position > m_limit ) { m_position = m_limit; }
1367 if( m_begin <= pos && pos < m_end ) {
1370 if( 0 < right_count ) {
1371 move_elements(pos, pos+1, right_count);
1374 if( m_position > m_begin && m_position > pos ) { --m_position; }
1376 return m_begin <= pos && pos <= m_end ? pos : m_end;
1388 const size_type count = dtor_range(first, clast);
1391 if( 0 < right_count ) {
1392 move_elements(first, clast, right_count);
1396 if( m_position > m_begin && m_position > first )
1397 { m_position -= std::min(count,
size_type(m_position - first)); }
1399 return m_begin <= first && first <= m_end ? first : m_end;
1410 return erase(m_begin + pos_idx);
1421 return erase(m_begin + first_idx, m_begin + last_idx);
1436 if( m_begin <= pos && pos <= m_end ) {
1437 if( m_end == m_storage_end ) {
1438 const size_type pos_idx = pos - m_begin;
1439 grow_storage_move();
1440 pos = m_begin + pos_idx;
1443 if( 0 < right_count ) {
1444 move_elements(
const_cast<iterator>(pos+1), pos, right_count);
1446 new (
const_cast<pointer_mutable
>(pos))
value_type( x );
1449 return m_begin <= pos && pos <= m_end ? const_cast<iterator>(pos) : m_end;
1462 return insert(m_begin + pos_idx, x);
1477 if( m_begin <= pos && pos <= m_end ) {
1478 const size_type pos_idx = pos - m_begin;
1479 if( m_end == m_storage_end ) {
1480 grow_storage_move();
1482 iterator pos_new = m_begin + pos_idx;
1484 if( 0 < right_count ) {
1485 move_elements(pos_new+1, pos_new, right_count);
1487 new (
const_cast<pointer_mutable
>(pos_new))
value_type( std::move( x ) );
1490 return m_begin <= pos_new && pos_new <= m_end ? pos_new : m_end;
1507 template<
typename... Args>
1509 if( m_begin <= pos && pos <= m_end ) {
1510 const size_type pos_idx = pos - m_begin;
1511 if( m_end == m_storage_end ) {
1512 grow_storage_move();
1514 iterator pos_new = m_begin + pos_idx;
1516 if( 0 < right_count ) {
1517 move_elements(pos_new+1, pos_new, right_count);
1519 new (
const_cast<pointer_mutable
>(pos_new))
value_type( std::forward<Args>(args)... );
1522 return m_begin <= pos_new && pos_new <= m_end ? pos_new : m_end;
1539 template<
class InputIt >
1541 if( m_begin <= pos && pos <= m_end ) {
1543 const size_type pos_idx = pos - m_begin;
1544 if( m_end + new_elem_count > m_storage_end ) {
1545 grow_storage_move(new_elem_count);
1547 iterator pos_new = m_begin + pos_idx;
1549 if( 0 < right_count ) {
1550 move_elements(pos_new + new_elem_count, pos_new, right_count);
1552 ctor_copy_range_foreign(pos_new, first, last);
1553 m_end += new_elem_count;
1556 return m_begin <= pos_new && pos_new <= m_end ? pos_new : m_end;
1570 if( m_end == m_storage_end ) {
1571 grow_storage_move();
1573 new (
const_cast<pointer_mutable
>(m_end))
value_type( x );
1575 m_position = m_limit;
1586 if( m_end == m_storage_end ) {
1587 grow_storage_move();
1589 new (
const_cast<pointer_mutable
>(m_end))
value_type( std::move(x) );
1591 m_position = m_limit;
1603 if( initlist.size() > std::numeric_limits<size_type>::max() ) {
1605 std::to_string(std::numeric_limits<size_type>::max()),
E_FILE_LINE);
1608 if( m_end + count1 > m_storage_end ) {
1611 const size_type count2 = epos + count1 - spos;
1614 ctor_copy_range_foreign(m_end, initlist.begin(), initlist.end());
1617 m_position = m_limit;
1639 insert(m_begin, std::move(x));
1651 template<
typename... Args>
1653 if( m_end == m_storage_end ) {
1654 grow_storage_move();
1656 new (
const_cast<pointer_mutable
>(m_end))
value_type( std::forward<Args>(args)... );
1672 template<
class InputIt >
1676 if( m_end + count > m_storage_end ) {
1677 grow_storage_move(count);
1679 ctor_copy_range_foreign(m_end, first, last);
1693 template <
typename... Args>
1696 const size_type count =
sizeof...(Args);
1700 if( m_end + count > m_storage_end ) {
1701 grow_storage_move(count);
1704 (
new (
const_cast<pointer_mutable
>(m_end++))
value_type( args ), ... );
1720 template <
typename... Args>
1723 const size_type count =
sizeof...(Args);
1727 if( m_end + count > m_storage_end ) {
1728 grow_storage_move(count);
1731 (
new (
const_cast<pointer_mutable
>(m_end++))
value_type( std::move(args) ), ... );
1769 for(
auto it = m_begin; it != m_end; ) {
1770 if( comparator( *it, x ) ) {
1804 for(
auto it = m_end-1; m_begin <= it; --it) {
1805 if( comparator( *it, x ) ) {
1808 if( !all_matching ) {
1830 template<
class UnaryPredicate>
1833 for(
auto it = m_end-1; m_begin <= it; --it) {
1837 if( !all_matching ) {
1849 if( 1 < ++i ) { res.append(
", "); }
1861 ", size "+std::to_string(size_)+
" / "+std::to_string(cap_)+
1864 res.append(
"pinned");
1866 res.append(
", shared");
1869 res.append(
"], growth "+std::to_string(m_growth_factor)+
1870 ", type[integral "+std::to_string(std::is_integral_v<Value_type>)+
1871 ", trivialCpy "+std::to_string(std::is_trivially_copyable_v<Value_type>)+
1876 ", [pos "+std::to_string(m_position-m_begin)+
1877 ", lim "+std::to_string(m_limit-m_begin)+
1879 ", send "+std::to_string(m_storage_end-m_begin)+
" "+
jau::toHexString(m_storage_end)+
1906 template <
typename First,
typename... Next,
1908 std::enable_if_t< std::conjunction_v<std::is_same<First, Next>... >,
bool> =
true>
1928 template <
typename First,
typename... Next>
1932 d.
push_back( std::forward<First>(arg1) );
1939 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1948 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1950 if( &rhs == &lhs ) {
1955 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1960 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1964 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1966 {
return lhs < rhs; }
1968 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1970 {
return !(lhs < rhs); }
1972 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1974 {
return !(rhs < lhs); }
1976 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1988 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
std::string toString() const
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.
std::string getInfo() const
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.
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.
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::string_view to_string(const endian_t v) noexcept
Return std::string representation of the given endian.
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
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...