/******************************************************************************/ /* ARRAYS *********************************************************************/ /******************************************************************************/ #ifndef _H_EBCL_ARRAYS #define _H_EBCL_ARRAYS #include #include #include #include namespace ebcl { // TODO: // * add addAll({}) // * add ={} / cons({}) /*= DYNAMIC ARRAYS ===========================================================*/ template< class T > class T_Array final { public: static constexpr uint32_t DEFAULT_GROWTH( ) { return std::max< uint32_t >( 1 , 4096 / sizeof( T ) ); } template< ptrdiff_t Direction > class T_Iterator_ final : public std::iterator< std::random_access_iterator_tag , T > { private: T_Array< T >* array_; ptrdiff_t pos_; public: T_Iterator_( T_Array< T >& array , const ptrdiff_t pos ) noexcept; M_ITER_CONS_DEF( T_Iterator_ ); M_ITER_CONS_COPY( T_Iterator_ ); M_ITER_SWAP( T_Iterator_ , T_Array ); M_ITER_CMP_ALL( T_Iterator_ ); M_ITER_DEREF_RANDOM( T& , T* ); M_ITER_OPS_RANDOM( T_Iterator_ ); bool valid( ) const noexcept; T_Array< T >* target( ) const noexcept; ptrdiff_t pos( ) const noexcept; }; using T_Iterator = T_Iterator_< 1 >; using T_ReverseIterator = T_Iterator_< -1 >; template< ptrdiff_t Direction > class T_ConstIterator_ : public std::iterator< std::random_access_iterator_tag , T > { private: T_Array< T > const* array_; ptrdiff_t pos_; public: T_ConstIterator_( T_Array< T > const& array , const ptrdiff_t pos ) noexcept; T_ConstIterator_( typename T_Array< T >::T_Iterator const& iterator ) noexcept; T_ConstIterator_& operator =( typename T_Array< T >::T_Iterator const& iterator ) noexcept; M_ITER_CONS_DEF( T_ConstIterator_ ); M_ITER_CONS_COPY( T_ConstIterator_ ); M_ITER_SWAP( T_ConstIterator_ , T_Array ); M_ITER_CMP_ALL( T_ConstIterator_ ); M_ITER_DEREF_RANDOM( T const& , T const* ); M_ITER_OPS_RANDOM( T_ConstIterator_ ); bool valid( ) const noexcept; T_Array< T >* target( ) const noexcept; ptrdiff_t pos( ) const noexcept; }; using T_ConstIterator = T_ConstIterator_< 1 >; using T_ConstReverseIterator = T_ConstIterator_< -1 >; private: typedef T_Array< T > MyType_; T* data_; uint32_t capacity_; uint32_t size_; uint32_t growth_; public: M_TEMPLATE_POINTERS( MyType_ ); T_Array( ) noexcept; explicit T_Array( uint32_t growth ) noexcept; // --------------------------------------------------------------------- T_Array( MyType_ const& source ) noexcept; MyType_& operator= ( MyType_ const& other ) noexcept; T_Array( MyType_&& source ) noexcept; MyType_& operator= ( MyType_&& other ) noexcept; T_Array( std::initializer_list< T > list ) noexcept; MyType_& operator= ( std::initializer_list< T > list ) noexcept; template< typename TP > friend void swap( T_Array< TP >& lhs , T_Array< TP >& rhs ) noexcept; // --------------------------------------------------------------------- ~T_Array( ); MyType_& clear( ) noexcept; MyType_& free( ) noexcept; // --------------------------------------------------------------------- uint32_t capacity( ) const noexcept; uint32_t size( ) const noexcept; uint32_t growth( ) const noexcept; bool empty( ) const noexcept; MyType_& ensureCapacity( uint32_t capacity ) noexcept; template< typename Q = T , typename = std::enable_if_t< std::is_default_constructible< Q >::value > > MyType_& resize( const uint32_t size ); template< typename Q = T , typename = std::enable_if_t< std::is_copy_constructible< Q >::value > > MyType_& resize( const uint32_t size , T const& value ); // --------------------------------------------------------------------- T& operator[] ( uint32_t index ) noexcept; T const& operator[] ( uint32_t index ) const noexcept; T& last( ) noexcept; T const& last( ) const noexcept; int32_t indexOf( T const& item ) const noexcept; bool contains( T const& item ) const noexcept; // --------------------------------------------------------------------- uint32_t add( T const& item ) noexcept; uint32_t add( T&& item ) noexcept; template< typename... Args > T& addNew( Args&& ... args ); // --------------------------------------------------------------------- MyType_& addAll( MyType_ const& other ) noexcept; MyType_& addAll( MyType_&& other ) noexcept; MyType_& addAll( std::initializer_list< T > values ) noexcept; // --------------------------------------------------------------------- MyType_& operator<< ( T const& item ) noexcept; MyType_& operator<< ( T&& item ) noexcept; MyType_& operator<< ( MyType_ const& other ) noexcept; MyType_& operator<< ( MyType_&& other ) noexcept; // --------------------------------------------------------------------- void insert( uint32_t index , T const& item ) noexcept; void insert( uint32_t index , T&& item ) noexcept; template< typename... Args > T& insertNew( uint32_t index , Args&& ... args ); // --------------------------------------------------------------------- void remove( uint32_t index ) noexcept; void removeSwap( uint32_t index ) noexcept; void removeLast( ) noexcept; // --------------------------------------------------------------------- void sort( F_Comparator< T > cmp = T_Comparator< T >::compare ) noexcept; void sort( uint32_t first , uint32_t items , F_Comparator< T > cmp = T_Comparator< T >::compare ) noexcept; // --------------------------------------------------------------------- MyType_ copyRange( uint32_t first , uint32_t last = UINT32_MAX ) const noexcept; MyType_ moveRange( uint32_t first , uint32_t last = UINT32_MAX ) noexcept; // --------------------------------------------------------------------- // Iterators for C++ for loops T_ConstIterator begin( ) const noexcept; T_ConstIterator end( ) const noexcept; T_ConstReverseIterator rbegin( ) const noexcept; T_ConstReverseIterator rend( ) const noexcept; T_ConstIterator cbegin( ) const noexcept; T_ConstIterator cend( ) const noexcept; T_ConstReverseIterator crbegin( ) const noexcept; T_ConstReverseIterator crend( ) const noexcept; T_Iterator begin( ) noexcept; T_Iterator end( ) noexcept; T_ReverseIterator rbegin( ) noexcept; T_ReverseIterator rend( ) noexcept; }; // Instantiate some common types directly extern template class T_Array< uint32_t >; /*= STATICALLY ALLOCATED ARRAYS ==============================================*/ /* These arrays offer the same interface as dynamic arrays, but are in fact * implemented as in-place storage. */ template< typename Type , uint32_t Size > class T_StaticArray final { static_assert( Size > 0 , "Size must be greater than 0" ); public: using T_Self = T_StaticArray< Type , Size >; private: // Actual storage type using T_Storage_ = std::aligned_storage_t< sizeof( Type ) , alignof( Type ) >; T_Storage_ storage_[ Size ]; uint32_t size_; public: M_TEMPLATE_POINTERS( T_Self ); T_StaticArray( ) noexcept; // Copy T_StaticArray( T_Self const& source ) noexcept; T_Self& operator= ( T_Self const& other ) noexcept; // Move T_StaticArray( T_Self&& source ) noexcept; T_Self& operator= ( T_Self&& other ) noexcept; ~T_StaticArray( ) noexcept; T_Self& clear( ) noexcept; template< typename T , uint32_t S > friend void swap( T_StaticArray< T , S >& lhs , T_StaticArray< T , S >& rhs ) noexcept; // --------------------------------------------------------------------- constexpr uint32_t capacity( ) const noexcept; uint32_t size( ) const noexcept; bool empty( ) const noexcept; // --------------------------------------------------------------------- Type& operator[] ( uint32_t index ) noexcept; Type const& operator[] ( uint32_t index ) const noexcept; Type& last( ) noexcept; Type const& last( ) const noexcept; int32_t indexOf( Type const& item ) const noexcept; bool contains( Type const& item ) const noexcept; // --------------------------------------------------------------------- uint32_t add( Type&& item ) noexcept; uint32_t add( Type const& item ) noexcept; template< typename... Args > Type& addNew( Args&& ... args ); // --------------------------------------------------------------------- T_Self& addAll( T_Self const& other ) noexcept; T_Self& addAll( T_Self&& other ) noexcept; // --------------------------------------------------------------------- T_Self& operator<< ( Type const& item ) noexcept; T_Self& operator<< ( Type&& item ) noexcept; T_Self& operator<< ( T_Self const& other ) noexcept; T_Self& operator<< ( T_Self&& other ) noexcept; // --------------------------------------------------------------------- void insert( uint32_t index , Type&& item ) noexcept; void insert( uint32_t index , Type const& item ) noexcept; template< typename... Args > Type& insertNew( uint32_t index , Args&& ... args ); // --------------------------------------------------------------------- void remove( uint32_t index ) noexcept; void removeSwap( uint32_t index ) noexcept; void removeLast( ) noexcept; // --------------------------------------------------------------------- void sort( F_Comparator< Type > cmp = T_Comparator< Type >::compare ) noexcept; void sort( uint32_t first , uint32_t items , F_Comparator< Type > cmp = T_Comparator< Type >::compare ) noexcept; // --------------------------------------------------------------------- T_Self copyRange( uint32_t first , uint32_t last = UINT32_MAX ) const noexcept; T_Self moveRange( uint32_t first , uint32_t last = UINT32_MAX ) noexcept; }; /*= MULTI-ARRAYS ============================================================-*/ /* * Arrays that allow storing multiple values for one entry. Values must be * added in order. */ template< typename T > class T_MultiArray { public: using T_Data = T_Array< T >; private: typedef T_MultiArray< T > MyType_; T_Array< uint32_t > meta_; T_Data values_; public: M_TEMPLATE_POINTERS( T_MultiArray ); template< typename TP > friend void swap( T_MultiArray< TP >& lhs , T_MultiArray< TP >& rhs ); // Start the next entry void next( ); // Add a value to the current entry void add( T value ); // Add a value, calling its constructor template< typename Q = T , typename... Args , typename = std::enable_if_t< std::is_class< Q >::value > > Q& addNew( Args&& ... args ); // Copy an array's contents into the current entry void copyFrom( T_Data const& source ); // Returns the amount of entries uint32_t size( ) const noexcept; // Returns the index of the first value for an entry uint32_t firstOf( uint32_t item ) const noexcept; // Returns the amount of values for an entry uint32_t sizeOf( uint32_t item ) const noexcept; // Returns the amount of values across all entries uint32_t values( ) const noexcept; // Access a value in an entry T const& get( uint32_t item , uint32_t sub ) const; T& get( uint32_t item , uint32_t sub ); // Access a value using its index T const& operator[] ( uint32_t index ) const; T& operator[] ( uint32_t index ); // Is a value present in an entry? bool contains( uint32_t index , T const& value ) const; // Reset storage, don't free memory void clear( ); // Reset storage and free memory void free( ); // Copy values from an entry into the current entry void copyFrom( uint32_t index ); // Copy another multi-array's entry into the current entry void copyFrom( MyType_ const& other , uint32_t index ); // Copy values from another entry into the current entry if // they are not already present. Duplicate entries in the // source array are still copied, though. void copyUnique( uint32_t index ); // Copy another multi-array's entry into the current entry, // ignoring values that are already present. Duplicates in // the source array are still copied. void copyUnique( MyType_ const& other , uint32_t index ); // Sort an entry's values void sort( uint32_t index , F_Comparator< T > cmp = T_Comparator< T >::compare ); }; // Instantiate some common types directly extern template class T_MultiArray< uint32_t >; /*= AUTOMATIC ARRAYS =========================================================*/ /* Arrays that are stored in-place up to some limit, then transform into * dynamic arrays if necessary. */ template< typename T , uint32_t StaticSize , uint32_t DynamicGrowth = StaticSize * 4 > class T_AutoArray { public: using T_Self = T_AutoArray< T , StaticSize , DynamicGrowth >; private: using T_Static_ = T_StaticArray< T , StaticSize >; using T_Dynamic_ = T_Array< T >; T_Union< T_Static_ , T_Dynamic_ > array_; // --------------------------------------------------------------------- public: M_TEMPLATE_POINTERS( T_Self ); T_AutoArray( ) noexcept; T_AutoArray( T_Self const& source ) noexcept; T_Self& operator =( T_Self const& source ) noexcept; T_AutoArray( T_Self&& source ) noexcept; T_Self& operator =( T_Self&& source ) noexcept; // --------------------------------------------------------------------- template< typename TP , uint32_t S , uint32_t G > friend void swap( T_AutoArray< TP , S , G >& lhs , T_AutoArray< TP , S , G >& rhs ) noexcept; // --------------------------------------------------------------------- T_Self& clear( ) noexcept; T_Self& free( ) noexcept; // --------------------------------------------------------------------- uint32_t capacity( ) const noexcept; uint32_t size( ) const noexcept; constexpr uint32_t growth( ) const noexcept; bool isStatic( ) const noexcept; bool empty( ) const noexcept; T_Self& ensureCapacity( uint32_t capacity ) noexcept; // --------------------------------------------------------------------- T& operator[] ( uint32_t index ) noexcept; T const& operator[] ( uint32_t index ) const noexcept; T& last( ) noexcept; T const& last( ) const noexcept; int32_t indexOf( T const& item ) const noexcept; bool contains( T const& item ) const noexcept; // --------------------------------------------------------------------- uint32_t add( T const& item ) noexcept; uint32_t add( T&& item ) noexcept; template< typename... Args > T& addNew( Args&& ... args ); // --------------------------------------------------------------------- T_Self& addAll( T_Self const& other ) noexcept; T_Self& addAll( T_Self&& other ) noexcept; // --------------------------------------------------------------------- T_Self& operator<< ( T const& item ) noexcept; T_Self& operator<< ( T&& item ) noexcept; T_Self& operator<< ( T_Self const& other ) noexcept; T_Self& operator<< ( T_Self&& other ) noexcept; // --------------------------------------------------------------------- void insert( uint32_t index , T const& item ) noexcept; void insert( uint32_t index , T&& item ) noexcept; template< typename... Args > T& insertNew( uint32_t index , Args&& ... args ); // --------------------------------------------------------------------- void remove( uint32_t index ) noexcept; void removeSwap( uint32_t index ) noexcept; void removeLast( ) noexcept; // --------------------------------------------------------------------- void sort( F_Comparator< T > cmp = T_Comparator< T >::compare ) noexcept; void sort( uint32_t first , uint32_t items , F_Comparator< T > cmp = T_Comparator< T >::compare ) noexcept; // --------------------------------------------------------------------- T_Self copyRange( uint32_t first , uint32_t last = UINT32_MAX ) const noexcept; T_Self moveRange( uint32_t first , uint32_t last = UINT32_MAX ) noexcept; // --------------------------------------------------------------------- private: void convertToDynamic_( uint32_t capacity ) noexcept; T_Static_& static_( ) noexcept; T_Static_ const& static_( ) const noexcept; T_Dynamic_& dynamic_( ) noexcept; T_Dynamic_ const& dynamic_( ) const noexcept; }; } #endif // _H_EBCL_ARRAYS #include