25#ifndef JAU_DYN_ARRAY_HPP_
26#define JAU_DYN_ARRAY_HPP_
33#include <initializer_list>
49 #define JAU_DARRAY_PRINTF0(...) { fprintf(stderr, __VA_ARGS__); fflush(stderr); }
51 #define JAU_DARRAY_PRINTF0(...)
56 #define JAU_DARRAY_PRINTF(...) { fprintf(stderr, __VA_ARGS__); fflush(stderr); }
58 #define JAU_DARRAY_PRINTF(...)
148 template <
typename Value_type,
typename Size_type = jau::n
size_t,
typename Alloc_type = jau::callocator<Value_type>,
149 bool use_memmove = std::is_trivially_copyable_v<Value_type> || is_container_memmove_compliant_v<Value_type>,
150 bool use_secmem = is_enforcing_secmem_v<Value_type>
160 constexpr static const bool uses_realloc = use_memmove && std::is_base_of_v<jau::callocator<Value_type>, Alloc_type>;
185 typedef std::remove_const_t<Value_type> value_type_mutable;
187 typedef value_type_mutable* pointer_mutable;
189 static constexpr void* voidptr_cast(
const_pointer p) {
return reinterpret_cast<void*
>(
const_cast<pointer_mutable
>( p ) ); }
191 constexpr static const size_type DIFF_MAX = std::numeric_limits<difference_type>::max();
192 constexpr static const size_type MIN_SIZE_AT_GROW = 10;
195 float m_growth_factor;
213 constexpr float growthFactor() const noexcept {
return m_growth_factor; }
235 constexpr bool pinned()
const {
return m_growth_factor < 1.0f; }
237 constexpr bool shared()
const {
return m_growth_factor < 0.0f; }
253 if( size_ > DIFF_MAX ) {
259 std::to_string(
sizeof(
value_type))+
" bytes/element = "+
263 value_type * m = m_alloc_inst.allocate(size_);
264 if(
nullptr == m && size_ > 0 ) {
266 throw jau::OutOfMemoryError(
"alloc "+std::to_string(size_)+
" elements * "+
267 std::to_string(
sizeof(
value_type))+
" bytes/element = "+
276 template<
class _Alloc_type>
278 std::enable_if_t< std::is_base_of_v<jau::callocator<value_type>, _Alloc_type>,
bool > =
true )
281 throw jau::IllegalStateError(
"realloc "+std::to_string(new_capacity_)+
" elements * "+
282 std::to_string(
sizeof(
value_type))+
" bytes/element = "+
286 if( new_capacity_ > DIFF_MAX ) {
287 throw jau::IllegalArgumentError(
"realloc "+std::to_string(new_capacity_)+
" > difference_type max "+
290 value_type * m = m_alloc_inst.reallocate(m_begin, m_storage_end-m_begin, new_capacity_);
291 if(
nullptr == m && new_capacity_ > 0 ) {
292 free(
const_cast<pointer_mutable
>(m_begin));
293 throw jau::OutOfMemoryError(
"realloc "+std::to_string(new_capacity_)+
" elements * "+
294 std::to_string(
sizeof(
value_type))+
" bytes/element = "+
299 template<
class _Alloc_type>
301 std::enable_if_t< !std::is_base_of_v<jau::callocator<value_type>, _Alloc_type>,
bool > =
true )
304 throw jau::UnsupportedOperationException(
"realloc not supported on non allocator_type not based upon jau::callocator",
E_FILE_LINE);
307 constexpr void freeStoreCheck() {
311 if( m_begin && !
shared() ) {
312 m_alloc_inst.deallocate(m_begin, m_storage_end-m_begin);
315 constexpr void freeStore() noexcept {
316 if( m_begin && !
shared() ) {
317 m_alloc_inst.deallocate(m_begin, m_storage_end-m_begin);
321 constexpr void clear_iterator() noexcept {
324 m_storage_end =
nullptr;
325 m_position =
nullptr;
330 const difference_type pos = std::min<difference_type>(size_, m_position - m_begin);
331 m_begin = new_storage_;
332 m_end = new_storage_+size_;
333 m_storage_end = new_storage_+capacity_;
334 m_position = m_begin + pos;
339 m_end = m_begin+size_;
340 m_storage_end = m_begin+capacity_;
342 if( m_position > m_limit) { m_position = m_limit; }
345 constexpr void dtor_one(
iterator pos) {
355 JAU_DARRAY_PRINTF0(
"dtor [%zd .. %zd], count %zd\n", (first-m_begin), (last-m_begin)-1, (last-first)-1);
356 for(; first < last; ++first, ++count ) {
366 JAU_DARRAY_PRINTF0(
"ctor_copy_range [%zd .. %zd] -> ??, dist %zd\n", (first-m_begin), (last-m_begin)-1, (last-first)-1);
384 for(; first < last; ++dest, ++first) {
385 new (
const_cast<pointer_mutable
>(dest))
value_type( *first );
390 JAU_DARRAY_PRINTF0(
"clone_range [0 .. %zd], count %zd\n", (last-first)-1, (last-first)-1);
392 ctor_copy_range(dest, first, last);
396 JAU_DARRAY_PRINTF0(
"clone_range [0 .. %zd], count %zd -> %d\n", (last-m_begin)-1, (last-first)-1, (
int)dest_capacity);
397 pointer dest = allocStore(dest_capacity);
398 ctor_copy_range(dest, first, last);
402 JAU_DARRAY_PRINTF0(
"ctor_copy_range_check [%zd .. %zd] -> ??, dist %zd\n", (first-m_begin), (last-m_begin)-1, (last-first)-1);
406 for(; first < last; ++dest, ++first) {
407 new (
const_cast<pointer_mutable
>(dest))
value_type( *first );
411 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);
412 if( dest_capacity <
size_type(last-first) ) {
413 throw jau::IllegalArgumentError(
"capacity "+std::to_string(dest_capacity)+
" < source range "+
416 pointer dest = allocStore(dest_capacity);
417 ctor_copy_range_check(dest, first, last);
422 if( m_begin > dest || dest + count > m_end ) {
427 for(
size_type i=0; i < count; ++i, ++dest) {
428 new (
const_cast<pointer_mutable
>(dest))
value_type( val );
432 template<
class InputIt >
433 constexpr static void ctor_copy_range_foreign(
pointer dest, InputIt first, InputIt last) {
435 throw jau::IllegalArgumentError(
"first "+
jau::to_string( first )+
" > last "+
438 for(; first != last; ++dest, ++first) {
439 new (
const_cast<pointer_mutable
>(dest))
value_type( *first );
442 template<
class InputIt >
443 constexpr pointer clone_range_foreign(
const size_type dest_capacity, InputIt first, InputIt last) {
444 if( dest_capacity <
size_type(last-first) ) {
445 throw jau::IllegalArgumentError(
"capacity "+std::to_string(dest_capacity)+
" < source range "+
448 pointer dest = allocStore(dest_capacity);
449 ctor_copy_range_foreign(dest, first, last);
453 constexpr void realloc_storage_move(
const size_type new_capacity) {
455 pointer new_storage = allocStore(new_capacity);
459 for(; first < m_end; ++dest, ++first) {
460 new (
const_cast<pointer_mutable
>(dest))
value_type( std::move( *first ) );
465 set_iterator(new_storage,
size(), new_capacity);
467 pointer new_storage = reallocStore<allocator_type>(new_capacity);
468 set_iterator(new_storage,
size(), new_capacity);
470 pointer new_storage = allocStore(new_capacity);
471 ::memcpy(voidptr_cast(new_storage),
472 m_begin, (uint8_t*)m_end-(uint8_t*)m_begin);
474 set_iterator(new_storage,
size(), new_capacity);
477 constexpr void grow_storage_move(
size_type add=1) {
488 ::memmove(voidptr_cast(dest),
493 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));
497 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));
508 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));
509 for(; first < last; ++dest, ++first ) {
510 new (
const_cast<pointer_mutable
>(dest))
value_type( std::move( *first ) );
516 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));
518 for(--last; first <= last; --dest, --last ) {
519 new (
const_cast<pointer_mutable
>(dest))
value_type( std::move( *last ) );
530 : m_alloc_inst( parent.m_alloc_inst ), m_growth_factor( -1 ),
531 m_begin(
begin ), m_end( m_begin +
size ), m_storage_end( m_begin +
size ),
534 if( m_begin > parent.
end() || m_end > parent.
end() || m_position > m_end || m_limit > m_end ) {
535 throw jau::IllegalArgumentError(
"Slice: Parent "+parent.getInfo()+
", this "+getInfo(), E_FILE_LINE);
537 parent.m_growth_factor = 0;
550 m_begin(
nullptr ), m_end(
nullptr ), m_storage_end(
nullptr ),
551 m_position(m_begin), m_limit(m_end)
563 : m_alloc_inst( alloc ), m_growth_factor( growth_factor ),
564 m_begin( allocStore(
capacity) ), m_end( m_begin ), m_storage_end( m_begin +
capacity ),
565 m_position(m_begin), m_limit(m_end)
579 : m_alloc_inst( alloc ), m_growth_factor( growth_factor ),
580 m_begin( allocStore(
size) ), m_end( m_begin +
size ), m_storage_end( m_begin +
size ),
581 m_position(m_begin), m_limit(m_end)
598 : m_alloc_inst( x.m_alloc_inst ), m_growth_factor( x.m_growth_factor ),
599 m_begin( clone_range(x.m_begin, x.m_end) ), m_end( m_begin + x.
size() ), m_storage_end( m_begin + x.
size() ),
600 m_position(m_begin), m_limit(m_end)
617 : m_alloc_inst( alloc ), m_growth_factor( growth_factor ),
618 m_begin( clone_range(x.m_begin, x.m_end) ), m_end( m_begin + x.
size() ), m_storage_end( m_begin + x.
size() ),
619 m_position(m_begin), m_limit(m_end)
637 : m_alloc_inst( alloc ), m_growth_factor( growth_factor ),
638 m_begin( clone_range( _capacity, x.m_begin, x.m_end) ), m_end( m_begin + x.
size() ), m_storage_end( m_begin + _capacity ),
639 m_position(m_begin), m_limit(m_end)
654 dtor_range(m_begin, m_end);
655 m_growth_factor = x.m_growth_factor;
656 if( x_size_ > capacity_ ) {
657 const difference_type pos = std::min<difference_type>(x_size_, m_position - m_begin);
659 m_begin = clone_range(x_size_, x.m_begin, x.m_end);
660 m_position = m_begin + pos;
661 set_iterator_end(x_size_, x_size_);
663 ctor_copy_range(m_begin, x.m_begin, x.m_end);
664 set_iterator_end(x_size_, capacity_);
675 : m_alloc_inst( std::move(x.m_alloc_inst) ), m_growth_factor( std::move(x.m_growth_factor) ),
676 m_begin( std::move(x.m_begin) ), m_end( std::move(x.m_end) ), m_storage_end( std::move(x.m_storage_end) ),
677 m_position( std::move(x.m_position) ), m_limit( std::move(x.m_limit) )
686 : m_alloc_inst( std::move(alloc) ), m_growth_factor( growth_factor ),
687 m_begin( std::move(x.m_begin) ), m_end( std::move(x.m_end) ), m_storage_end( std::move(x.m_storage_end) ),
688 m_position( std::move(x.m_position) ), m_limit( std::move(x.m_limit) )
704 m_alloc_inst = std::move(x.m_alloc_inst);
705 m_growth_factor = std::move( x.m_growth_factor );
706 m_begin = std::move(x.m_begin);
707 m_end = std::move(x.m_end);
708 m_storage_end = std::move(x.m_storage_end);
709 m_position = std::move(x.m_position);
710 m_limit = std::move(x.m_limit);
737 : m_alloc_inst( alloc ), m_growth_factor( growth_factor ),
738 m_begin( clone_range_check(_capacity, first, last) ), m_end(m_begin +
size_type(last - first) ), m_storage_end( m_begin + _capacity ),
739 m_position(m_begin), m_limit(m_end)
758 template<
class InputIt >
761 : m_alloc_inst( alloc ), m_growth_factor( growth_factor ),
762 m_begin( clone_range_foreign(_capacity, first, last) ), m_end(m_begin +
size_type(last - first) ), m_storage_end( m_begin + _capacity ),
763 m_position(m_begin), m_limit(m_end)
777 template<
class InputIt >
780 m_begin( clone_range_foreign(
size_type(last - first), first, last) ), m_end(m_begin +
size_type(last - first) ),
781 m_storage_end( m_begin +
size_type(last - first) ),
782 m_position(m_begin), m_limit(m_end)
801 m_begin( clone_range_foreign(initlist.
size(), initlist.
begin(), initlist.
end()) ),
802 m_end(m_begin + initlist.
size() ), m_storage_end( m_begin + initlist.
size() ),
803 m_position(m_begin), m_limit(m_end)
833 constexpr iterator storage_end() noexcept {
return m_storage_end; }
834 constexpr const_iterator storage_end() const noexcept {
return m_storage_end; }
835 constexpr const_iterator cstorage_end() const noexcept {
return m_storage_end; }
869 if (m_position > p) { m_position = p; }
875 m_limit = m_position;
876 m_position = m_begin;
882 m_position = m_begin;
897 m_position = m_begin;
908 if( m_position < m_limit ) {
909 return *(m_position++);
926 if( *grow && m_position == m_limit ) {
927 if( m_limit == m_storage_end ) {
936 if( m_position < m_limit ) {
955 template<
typename... Targs,
960 const size_type count1 =
sizeof...(args);
961 if( *grow && m_position + count1 > m_limit ) {
963 if( m_limit + count2 > m_storage_end ) {
966 }
else if( m_limit + count2 > m_end ) {
972 if( m_position + count1 - 1 < m_limit ) {
973 ( (*m_position++ =
static_cast<Value_type>(args)), ... );
993 return darray(*
this, m_position, m_position, m_position+new_size, new_size);
1005 if(m_position + idx + length > m_limit) {
1008 return darray(*
this, m_position+idx, m_position+idx, m_position+idx+length, length);
1020 m_growth_factor = 0;
1021 return darray(*
this, m_begin, m_position, m_limit,
size());
1027 constexpr bool hasRemaining() const noexcept {
return m_position < m_limit; }
1034 return m_alloc_inst;
1051 return std::max<size_type>( std::max<size_type>( MIN_SIZE_AT_GROW, a_capacity+add ),
1058 constexpr bool empty() const noexcept {
return m_begin == m_end; }
1107 return *(m_begin+i);
1114 return *(m_begin+i);
1121 if( 0 <= i && i <
size() ) {
1122 return *(m_begin+i);
1131 if( 0 <= i && i <
size() ) {
1132 return *(m_begin+i);
1148 realloc_storage_move(new_capacity);
1158 if( new_size > sz ) {
1160 realloc_storage_move(new_size);
1162 const size_type new_elem_count = new_size - sz;
1163 m_end += new_elem_count;
1164 m_limit += new_elem_count;
1165 ctor_copy_value(m_begin + sz, new_elem_count, val);
1166 }
else if( new_size < sz ) {
1167 const size_type del_elem_count = dtor_range(m_begin + new_size, m_end);
1168 assert(sz - new_size == del_elem_count);
1169 m_end -= del_elem_count;
1187 realloc_storage_move(size_);
1198 template<
class InputIt >
1199 constexpr void assign( InputIt first, InputIt last ) {
1203 dtor_range(m_begin, m_end);
1204 if( x_size_ > capacity_ ) {
1205 const difference_type pos = std::min<difference_type>(x_size_, m_position - m_begin);
1207 m_begin = clone_range_foreign(x_size_, first, last);
1208 m_position = m_begin + pos;
1209 set_iterator_end(x_size_, x_size_);
1211 ctor_copy_range_foreign(m_begin, first, last);
1212 set_iterator_end(x_size_, capacity_);
1224 dtor_range(m_begin, m_end);
1225 if( x_size_ > capacity_ ) {
1226 const difference_type pos = std::min<difference_type>(x_size_, m_position - m_begin);
1228 m_begin = clone_range_check(x_size_, first, last);
1229 m_position = m_begin + pos;
1230 set_iterator_end(x_size_, x_size_);
1232 ctor_copy_range_check(m_begin, first, last);
1233 set_iterator_end(x_size_, capacity_);
1248 dtor_range(m_begin, m_end);
1250 m_position = m_begin;
1274 m_storage_end =
nullptr;
1275 m_position =
nullptr;
1287 std::swap(m_alloc_inst, x.m_alloc_inst);
1288 std::swap(m_growth_factor, x.m_growth_factor);
1289 std::swap(m_begin, x.m_begin);
1290 std::swap(m_end, x.m_end);
1291 std::swap(m_storage_end, x.m_storage_end);
1292 std::swap(m_position, x.m_position);
1293 std::swap(m_limit, x.m_limit);
1304 if( m_begin != m_end ) {
1305 dtor_one( --m_end );
1307 if( m_position > m_limit ) { m_position = m_limit; }
1320 if( m_begin <= pos && pos < m_end ) {
1323 if( 0 < right_count ) {
1324 move_elements(pos, pos+1, right_count);
1327 if( m_position > m_begin && m_position > pos ) { --m_position; }
1329 return m_begin <= pos && pos <= m_end ? pos : m_end;
1341 const size_type count = dtor_range(first, clast);
1344 if( 0 < right_count ) {
1345 move_elements(first, clast, right_count);
1349 if( m_position > m_begin && m_position > first )
1350 { m_position -= std::min(count,
size_type(m_position - first)); }
1352 return m_begin <= first && first <= m_end ? first : m_end;
1363 return erase(m_begin + pos_idx);
1374 return erase(m_begin + first_idx, m_begin + last_idx);
1389 if( m_begin <= pos && pos <= m_end ) {
1390 if( m_end == m_storage_end ) {
1391 const size_type pos_idx = pos - m_begin;
1392 grow_storage_move();
1393 pos = m_begin + pos_idx;
1396 if( 0 < right_count ) {
1397 move_elements(
const_cast<iterator>(pos+1), pos, right_count);
1399 new (
const_cast<pointer_mutable
>(pos))
value_type( x );
1402 return m_begin <= pos && pos <= m_end ? const_cast<iterator>(pos) : m_end;
1415 return insert(m_begin + pos_idx, x);
1430 if( m_begin <= pos && pos <= m_end ) {
1431 const size_type pos_idx = pos - m_begin;
1432 if( m_end == m_storage_end ) {
1433 grow_storage_move();
1435 iterator pos_new = m_begin + pos_idx;
1437 if( 0 < right_count ) {
1438 move_elements(pos_new+1, pos_new, right_count);
1440 new (
const_cast<pointer_mutable
>(pos_new))
value_type( std::move( x ) );
1443 return m_begin <= pos_new && pos_new <= m_end ? pos_new : m_end;
1460 template<
typename... Args>
1462 if( m_begin <= pos && pos <= m_end ) {
1463 const size_type pos_idx = pos - m_begin;
1464 if( m_end == m_storage_end ) {
1465 grow_storage_move();
1467 iterator pos_new = m_begin + pos_idx;
1469 if( 0 < right_count ) {
1470 move_elements(pos_new+1, pos_new, right_count);
1472 new (
const_cast<pointer_mutable
>(pos_new))
value_type( std::forward<Args>(args)... );
1475 return m_begin <= pos_new && pos_new <= m_end ? pos_new : m_end;
1492 template<
class InputIt >
1494 if( m_begin <= pos && pos <= m_end ) {
1496 const size_type pos_idx = pos - m_begin;
1497 if( m_end + new_elem_count > m_storage_end ) {
1498 grow_storage_move(new_elem_count);
1500 iterator pos_new = m_begin + pos_idx;
1502 if( 0 < right_count ) {
1503 move_elements(pos_new + new_elem_count, pos_new, right_count);
1505 ctor_copy_range_foreign(pos_new, first, last);
1506 m_end += new_elem_count;
1509 return m_begin <= pos_new && pos_new <= m_end ? pos_new : m_end;
1523 if( m_end == m_storage_end ) {
1524 grow_storage_move();
1526 new (
const_cast<pointer_mutable
>(m_end))
value_type( x );
1539 if( m_end == m_storage_end ) {
1540 grow_storage_move();
1542 new (
const_cast<pointer_mutable
>(m_end))
value_type( std::move(x) );
1566 insert(m_begin, std::move(x));
1578 template<
typename... Args>
1580 if( m_end == m_storage_end ) {
1581 grow_storage_move();
1583 new (
const_cast<pointer_mutable
>(m_end))
value_type( std::forward<Args>(args)... );
1599 template<
class InputIt >
1603 if( m_end + count > m_storage_end ) {
1604 grow_storage_move(count);
1606 ctor_copy_range_foreign(m_end, first, last);
1620 template <
typename... Args>
1623 const size_type count =
sizeof...(Args);
1627 if( m_end + count > m_storage_end ) {
1628 grow_storage_move(count);
1631 (
new (
const_cast<pointer_mutable
>(m_end++))
value_type( args ), ... );
1647 template <
typename... Args>
1650 const size_type count =
sizeof...(Args);
1654 if( m_end + count > m_storage_end ) {
1655 grow_storage_move(count);
1658 (
new (
const_cast<pointer_mutable
>(m_end++))
value_type( std::move(args) ), ... );
1696 for(
auto it = m_begin; it != m_end; ) {
1697 if( comparator( *it, x ) ) {
1731 for(
auto it = m_end-1; m_begin <= it; --it) {
1732 if( comparator( *it, x ) ) {
1735 if( !all_matching ) {
1757 template<
class UnaryPredicate>
1760 for(
auto it = m_end-1; m_begin <= it; --it) {
1764 if( !all_matching ) {
1776 if( 1 < ++i ) { res.append(
", "); }
1788 ", size "+std::to_string(size_)+
" / "+std::to_string(cap_)+
1791 res.append(
"pinned");
1793 res.append(
", shared");
1796 res.append(
"], growth "+std::to_string(m_growth_factor)+
1797 ", type[integral "+std::to_string(std::is_integral_v<Value_type>)+
1798 ", trivialCpy "+std::to_string(std::is_trivially_copyable_v<Value_type>)+
1803 ", [pos "+std::to_string(m_position-m_begin)+
1804 ", lim "+std::to_string(m_limit-m_begin)+
1806 ", send "+std::to_string(m_storage_end-m_begin)+
" "+
jau::to_hexstring(m_storage_end)+
1833 template <
typename First,
typename... Next,
1835 std::enable_if_t< std::conjunction_v<std::is_same<First, Next>... >,
bool> =
true>
1855 template <
typename First,
typename... Next>
1859 d.
push_back( std::forward<First>(arg1) );
1866 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1875 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1877 if( &rhs == &lhs ) {
1882 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1887 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1891 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1893 {
return lhs < rhs; }
1895 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1897 {
return !(lhs < rhs); }
1899 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1901 {
return !(rhs < lhs); }
1903 template<
typename Value_type,
typename Size_type,
typename Alloc_type>
1915 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
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 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 size_type max_size() const noexcept
Returns std::numeric_limits<difference_type>::max() as the maximum array size.
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::string to_string(const endian_t v) noexcept
Return std::string representation of the given endian.
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.
std::ostream & operator<<(std::ostream &out, const cow_darray< Value_type, Size_type, Alloc_type > &c)
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 to_hexstring(value_type const &v, const bool skipLeading0x=false) noexcept
Produce a lower-case hexadecimal string representation with leading 0x in MSB of the given pointer.
__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...