//////////////////////////////////////////////////////////////////////////////// /** \file \brief \ru Одномерный массив указателей. \en One-dimensional array of pointers. \~ */ //////////////////////////////////////////////////////////////////////////////// #ifndef __TEMPL_RP_ARRAY_H #define __TEMPL_RP_ARRAY_H #include #include #include #include #include #include FORVARD_DECL_TEMPLATE_TYPENAME( class RPArray ); FORVARD_DECL_TEMPLATE_TYPENAME( bool set_Rarray_size( RPArray &, size_t newSize ) ); FORVARD_DECL_TEMPLATE_TYPENAME( size_t find_in_array ( const RPArray & arr, const Type * el ) ); FORVARD_DECL_TEMPLATE_TYPENAME( reader & CALL_DECLARATION operator >> ( reader & in, RPArray & ref ) ); FORVARD_DECL_TEMPLATE_TYPENAME( writer & CALL_DECLARATION operator << ( writer & out, const RPArray & ref ) ); FORVARD_DECL_TEMPLATE_TYPENAME( reader & CALL_DECLARATION operator >> ( reader & in, RPArray *& ptr ) ); FORVARD_DECL_TEMPLATE_TYPENAME( writer & CALL_DECLARATION operator << ( writer & out, const RPArray * ptr ) ); //------------------------------------------------------------------------------ /** \brief \ru Одномерный массив указателей на объекты. \en One-dimensional array of pointers to objects. \~ \details \ru Шаблонный массив, работающий с указателями на объекты. \n \en A template array working with pointers to objects. \n \~ \ingroup Base_Tools_Containers */ // --- template class RPArray { public: /// \ru Имя указателя на объект. \en A name of the pointer to the object. typedef Type * TPtr; typedef Type * value_type; typedef Type * const & const_reference; typedef Type * & reference; protected: size_t count; ///< \ru Количество элементов в массиве. \en The number of elements in array. size_t upper; ///< \ru Под какое количество элементов выделена память. \en The number of elements the memory is allocated for. uint16 delta; ///< \ru Приращение по количеству элементов при выделении дополнительной памяти. \en Increment by the number of elements while the allocation of additional memory. private: TPtr * parr; ///< \ru Указатель на первый элемент массива. \en A pointer to the first array element. public : /// \ru Конструктор. \en Constructor. RPArray(); /// \ru Конструктор. \en Constructor. RPArray ( size_t i_upper, uint16 i_delta = 1 );//, bool shouldNullSet = false ); /// \ru Деструктор. \en Destructor. virtual ~RPArray(); public: /// \ru Получить приращение по количеству элементов при выделении дополнительной памяти. \en Get the increment by the number of elements while the allocation of additional memory. uint16 Delta() const { return delta; } /// \ru Количество элементов, для которых выделена память? \en The number of elements the memory is allocated for. size_t Upper() const { return upper; } /// \ru Установить приращение по количеству элементов при выделении дополнительной памяти (1 - автоприращение). \en Set the increment by the number of elements while the allocation of additional memory (1 - autoincrement). void Delta( uint16 newDelta ) { delta = newDelta; } /// \ru Установить максимальное из приращений. \en Set the maximum increment. void SetMaxDelta( uint16 newDelta ) { if ( delta < newDelta ) delta = newDelta; } /// \ru Функции, выделяющие потенциально большие участки памяти, возвращают результат операции (успех/ошибка). /// \en Functions that allocate potentially large memory, return an operation result (success/error). bool SetSize ( size_t newSize ); ///< \ru Установить новый размер массива. \en Set the new size of an array. bool Reserve ( size_t n, bool addAdditionalSpace = true ); ///< \ru Зарезервировать место под столько элементов. \en Reserve space for a given number of elements. bool Add ( Type * ); ///< \ru Добавить элемент в конец массива. \en Add an element to the end of the array. bool AddAt ( Type * e, size_t index ) { return Insert( index, e ); } ///< \ru Вставить элемент в указанную позицию. \en Insert an element to the given position. bool AddAfter( Type * e, size_t index ); ///< \ru Добавить элемент после указанного. \en Add an element after the specified one. bool Insert ( size_t index, Type * ); ///< \ru Вставить элемент перед указанным. \en Insert an element before the specified one. bool AddArray ( const RPArray & ); ///< \ru Добавить массив. \en Add array. bool AddCArray ( const Type **, size_t count ); ///< \ru Добавить C-массив. \en Add C-array. bool InsertArray( const RPArray &, size_t index ); ///< \ru Добавить массив в позицию. \en Add an array to the position. void DetachAll(); ///< \ru Удалить все элементы обнулить количество элементов. \en Delete all elements and set the number of elements to null. void Adjust(); ///< \ru Удалить лишнюю память. \en Free the unnecessary memory. Type * DetachInd( size_t delIndex ); ///< \ru Отсоединить элемент от массива. \en Detach an element from the array. bool DetachObj( const Type * delObject ); ///< \ru Отсоединить элемент от массива. \en Detach an element from the array. virtual Type * RemoveInd( size_t delIndex, DelType /*del*/ = defDelete ) { return DetachInd( delIndex); } ///< \ru Удалить элемент из массива по индексу. \en Delete an element from array by the index. void Swap( RPArray & arr ); ///< \ru Обменять местами данные массивов. \en Swap data of arrays. size_t FindIt ( const Type * ) const; ///< \ru Найти элемент по указателю. \en Find an element by a pointer. bool IsExist( const Type * ) const; ///< \ru Есть ли элемент в массиве. \en Whether an element belongs the array. size_t Count() const { return count; } ///< \ru Получить количество элементов массива. \en Get the number of array elements. ptrdiff_t MaxIndex() const { return ((ptrdiff_t)count - 1); } ///< \ru Получить индекс последнего объект в массиве. \en Get the index of the last element in the array. typedef int (*CompFunc)( const Type **, const Type ** ); ///< \ru Шаблон функции сортировки. \en A template of sorting function. void Sort ( CompFunc comp ); ///< \ru Сортировать массив. \en Sort the array. /// \ru Оператор доступа по индексу. \en Access by index operator. Type *& operator []( size_t loc ) const; /// \ru Получить адрес последнего элемента в массиве. \en Get the address of the last element in the array. Type * GetLast() const { return ((count > 0) ? parr[count-1] : (Type*)nullptr); } public: // \ru унификация с вектором STL \en unification with STL vector bool empty() const { return count == 0; } size_t size() const { return count; } ///< \ru Дать количество элементов массива. \en Get the number of elements in array. bool reserve( size_t n ) { return Reserve( n, false ); } ///< \ru Зарезервировать место под столько элементов. \en Reserve space for a given number of elements. size_t capacity() const { return Upper(); } ///< \ru Под какое количество элементов выделена память? \en What is the number of elements the memory is allocated for? void push_back( const Type * e ) { Add( const_cast(e) ); } ///< \ru Добавить элемент в конец массива. \en Add an element to the end of the array. void emplace_back( const Type * e ) { Add( const_cast(e) ); } ///< \ru Добавить элемент в конец массива. \en Add an element to the end of the array. template void insert( Iterator pos, const Type * e ); ///< \ru Вставить элемент перед указанным. \en Insert an element before the specified one. // \ru прописывать поведение у всех классов-наследников! \en define the behavior for all classes-inheritors! template void erase( Iterator pos ); ///< \ru Удалить элемент из массива по индексу. \en Delete an element from array by the index. template void erase( Iterator first, Iterator last ); ///< \ru Удалить элементы из массива начиная с индекса first до last-1 включительно. \en Delete elements from the array from first to last-1 inclusively. virtual void clear() { DetachAll(); } ///< \ru Обнулить количество элементов. \en Set the number of elements to null. void shrink_to_fit() { Adjust(); } ///< \ru Удалить лишнюю память. \en Free the unnecessary memory (Reduce capacity). const TPtr * begin() const { return parr; } ///< \ru Получить указатель на первый элемент массива. \en Get the pointer to the first array element. TPtr * begin() { return parr; } ///< \ru Получить указатель на первый элемент массива. \en Get the pointer to the first array element. const TPtr * end() const { return parr + count; } ///< \ru Получить указатель на участок памяти после массива. \en Get the pointer to the piece of memory after the array. TPtr * end() { return parr + count; } ///< \ru Получить указатель на участок памяти после массива. \en Get the pointer to the piece of memory after the array. const TPtr * cbegin() const { return parr; } ///< \ru Получить указатель на первый элемент массива. \en Get the pointer to the first array element. const TPtr * cend() const { return parr + count; } ///< \ru Получить указатель на участок памяти после массива. \en Get the pointer to the piece of memory after the array. const value_type front() const; value_type & front(); const value_type back() const; value_type & back(); const_reference at( size_t idx ) const; reference at( size_t idx ); protected: const Type ** GetAddr() const { return (const Type **)parr; } ///< \ru Получить указатель на первый элемент массива. \en Get the pointer to the first array element. const TPtr * _Begin() const { return parr; } ///< \ru Получить указатель на первый элемент массива. \en Get the pointer to the first array element. TPtr * _Begin() { return parr; } ///< \ru Получить указатель на первый элемент массива. \en Get the pointer to the first array element. const TPtr * _End() const { return parr + count; } ///< \ru Получить указатель на участок памяти после массива. \en Get the pointer to the piece of memory after the array. bool CatchMemory(); ///< \ru Захватить память. \en Catch memory. bool AddMemory( size_t n ); ///< \ru Обеспечить место в памяти под n элементов, независимо от AutoDelta \en Provide memory for n elements, independently from AutoDelta size_t AutoDelta() const { return ::KsAutoDelta( count, delta ); } ///< \ru Вычислить автоприращение. \en Calculate autoincrement. private: RPArray( const RPArray & ); // \ru запрещено !!! \en forbidden !!! RPArray & operator =( const RPArray & ); // \ru запрещено !!! \en forbidden !!! TEMPLATE_FRIEND bool set_Rarray_size TEMPLATE_SUFFIX ( RPArray &, size_t newSize ); TEMPLATE_FRIEND size_t find_in_array TEMPLATE_SUFFIX ( const RPArray & arr, const Type * el ); #if defined(_MSC_VER) && !defined(_MSVC_PERMISSIVE_OFF) TEMPLATE_FRIEND size_t find_in_array TEMPLATE_SUFFIX ( const RPArray & arr, const Type * el ); #endif // _MSC_VER TEMPLATE_FRIEND reader & CALL_DECLARATION operator >> TEMPLATE_SUFFIX ( reader & in, RPArray & ref ); TEMPLATE_FRIEND writer & CALL_DECLARATION operator << TEMPLATE_SUFFIX ( writer & out, const RPArray & ref ); TEMPLATE_FRIEND reader & CALL_DECLARATION operator >> TEMPLATE_SUFFIX ( reader & in, RPArray *& ptr ); TEMPLATE_FRIEND writer & CALL_DECLARATION operator << TEMPLATE_SUFFIX ( writer & out, const RPArray * ptr ); #ifdef __DEBUG_MEMORY_ALLOCATE_FREE_ public: void * operator new ( size_t ); void operator delete ( void *, size_t ); #endif // __DEBUG_MEMORY_ALLOCATE_FREE_ public: RPArray( RPArray && ); ///< \ru Конструктор перемещения массива. \en Constructor of an array moving. RPArray & operator = ( RPArray && ); ///< \ru Оператор перемещения массива. \en Operator of an array moving. }; #ifdef __DEBUG_MEMORY_ALLOCATE_FREE_ //------------------------------------------------------------------------------ // \ru Перегрузка оператора new. \en Overloading of the "new" operator. // --- template inline void * RPArray::operator new( size_t size ) { return ::Allocate( size, typeid(RPArray).name() ); } //------------------------------------------------------------------------------ // \ru Перегрузка оператора delete. \en Overloading of the "delete" operator. // --- template inline void RPArray::operator delete( void * ptr, size_t size ) { ::Free( ptr, size, typeid(RPArray).name() ); } #endif // __DEBUG_MEMORY_ALLOCATE_FREE_ //------------------------------------------------------------------------------ // \ru конструктор массива \en constructor of an array // --- template inline RPArray::RPArray() : count( 0 ) , upper( 0 ) , delta( 1 ) , parr ( 0 ) {} //------------------------------------------------------------------------------ // \ru конструктор массива \en constructor of an array // --- template inline RPArray::RPArray( size_t i_upper, uint16 i_delta )//, bool shouldNullSet ) : count( 0 ) , upper( 0 ) , delta( i_delta ) , parr ( 0 ) //i_upper ? new TPtr[i_upper] : 0 ) { if ( !set_Rarray_size(*this, i_upper) && !ExceptionMode::IsEnabled() ) throw std::bad_alloc(); // \ru Бросить исключение при любом режиме. \en Throw exception in case of any mode. //if ( shouldNullSet && upper > 0 ) { // count = upper; // memset( parr, 0, count * SIZE_OF_POINTER ); //} } //------------------------------------------------------------------------------ // \ru Конструктор перемещения массива. \en Constructor of an array moving. // --- template inline RPArray::RPArray( RPArray && _Right ) : count(_Right.count) , upper(_Right.upper) , delta(_Right.delta) , parr (_Right.parr) { _Right.count = 0; _Right.upper = 0; _Right.delta = 1; _Right.parr = nullptr; } //------------------------------------------------------------------------------ // \ru Оператор перемещения массива. \en Operator of an array moving. // --- template RPArray & RPArray::operator = ( RPArray && _Right ) { if ( this != &_Right ) { set_Rarray_size( *this, 0 ); _Right.Swap( *this ); } return (*this); } //------------------------------------------------------------------------------ // \ru деструктор массива \en destructor of array // --- template inline RPArray::~RPArray() { set_Rarray_size( *this, 0 ); //delete [] parr; } //------------------------------------------------------------------------------ // \ru Оператор доступа по индексу. \en Access by index operator. // --- template inline Type *& RPArray::operator []( size_t loc ) const { return parr[loc]; } //------------------------------------------------------------------------------ // \ru Доступ к первому элементу. \en Access to the first element. // --- template inline const typename RPArray::value_type RPArray::front() const { PRECONDITION( !empty() ); return *parr; } //------------------------------------------------------------------------------- // \ru Доступ к первому элементу. \en Access to the first element. // --- template inline typename RPArray::value_type & RPArray::front() { PRECONDITION( !empty() ); return *parr; } //------------------------------------------------------------------------------- // \ru Доступ к последнему элементу. \en Access to the last element. // --- template inline const typename RPArray::value_type RPArray::back() const { PRECONDITION( !empty() ); return *( parr + count - 1 ); } //------------------------------------------------------------------------------- // \ru Доступ к последнему элементу. \en Access to the last element. // --- template inline typename RPArray::value_type & RPArray::back() { PRECONDITION( !empty() ); return *( parr + count - 1 ); } //------------------------------------------------------------------------------- // \ru Доступ по индексу. \en Access by index operator. // --- template inline typename RPArray::const_reference RPArray::at( size_t idx ) const { PRECONDITION( idx < count ); return parr[idx]; } //------------------------------------------------------------------------------- // \ru Доступ по индексу. \en Access by index operator. // --- template inline typename RPArray::reference RPArray::at( size_t idx ) { PRECONDITION( idx < count ); return parr[idx]; } //------------------------------------------------------------------------------- // \ru обнулить количество элементов \en set the number of elements to null // --- template inline void RPArray::DetachAll() { count = 0; } //------------------------------------------------------------------------------ // \ru Указать новый размер массива. \en Set the new size of an array. // --- template inline bool RPArray::SetSize( size_t newSize ) { return set_Rarray_size( *this, newSize ); } //------------------------------------------------------------------------------ // \ru Зарезервировать место под n элементов. \en Reserve memory for n elements. // --- template inline bool RPArray::Reserve( size_t n, bool addAdditionalSpace ) { if ( addAdditionalSpace ) n += count; // \ru Захватить память, если требуется памяти больше, чем есть сейчас. \en if there is required more memory that exists at the moment catch it. if ( upper < n ) { return set_Rarray_size( *this, n ); } else { // C3D_ASSERT( upper <= n ); // Use SetSize!!! } return true; } //------------------------------------------------------------------------------ // \ru Обеспечить место под n элементов, независимо от AutoDelta \en Provide memory for n elements, independently from AutoDelta // --- template inline bool RPArray::AddMemory( size_t n ) { if ( upper - count < n ) { return set_Rarray_size( *this, count + n ); } return true; } //------------------------------------------------------------------------------ // \ru освободить лишнюю память \en free unnecessary memory // --- template inline void RPArray::Adjust() { if ( count < upper ) set_Rarray_size( *this, count ); } //------------------------------------------------------------------------------ // \ru добавить 1 элемент в конец массива \en add 1 element to the end of array // --- template inline bool RPArray::Add( Type * ent ) { if ( CatchMemory() ) { parr[count++] = ent; return true; } return false; } //------------------------------------------------------------------------------ // \ru добавить 1 элемент после заданного \en add 1 element after the given one // --- template inline bool RPArray::AddAfter( Type * ent, size_t index ) { if ( !count ) return Add( ent ); else { if ( CatchMemory() ) { // \ru добавить памяти, если все использовано \en add memory if whole allocated memory is used if ( index > count - 1 ) index = count - 1; // \ru передвинем вправо все элементы массива с index+1 до последнего \en move to the right all elements of the array from index+1 to the last memmove( parr + index + 2, parr + index + 1, (count - index - 1) * SIZE_OF_POINTER ); parr[index + 1] = ent; // \ru записываем новый элемент \en writing new element count++; return true; } } return false; } //------------------------------------------------------------------------------ // \ru добавить массив \en add array // \ru эти функции раньше обнуляли признак владения у второго массива, \en These functions set to null the attribute of second element ownership earlier, // \ru Теперь об этом нужно заботиться самостоятельно ! \en Now you should take care of it ! // --- template inline bool RPArray::AddArray( const RPArray & from ) { return AddCArray( from.GetAddr(), from.count ); } //------------------------------------------------------------------------------ // \ru добавить C-массив \en add C-array // --- template inline bool RPArray::AddCArray( const Type ** from, size_t fromCount ) { if ( fromCount ) { if ( AddMemory( fromCount ) ) { // \ru обеспечить память на такое кол-во элементов \en allocate memory for the given number of elements memcpy( parr + count, from, fromCount * SIZE_OF_POINTER ); count += fromCount; return true; } } return false; } //------------------------------------------------------------------------------ // \ru добавить массив в позицию index \en Add an array to the position index // \ru (если index>count, то в конец) \en (if 'index' > 'count' then add to the end) // \ru эти функции раньше обнуляли признак владения у второго массива, \en These functions set to null the attribute of second element ownership earlier, // \ru теперь об этом нужно заботиться самостоятельно ! \en Now you should take care of it ! // --- template inline bool RPArray::InsertArray( const RPArray & from, size_t index ) { if ( from.count ) { if ( index > count ) index = count; if ( AddMemory( from.count ) ) { if ( count > index ) // \ru переместить хвост подальше \en move a tale farther memmove( parr + index + from.count, parr + index, (count - index) * SIZE_OF_POINTER ); memcpy( parr + index, from.parr, from.count * SIZE_OF_POINTER ); count += from.count; return true; } } return false; } //------------------------------------------------------------------------------ // \ru вставить 1 элемент перед указанным \en insert 1 element before the specified one // --- template inline bool RPArray::Insert( size_t index, Type * ent ) { if ( CatchMemory() ) { // \ru добавить памяти, если все использовано \en add memory if whole allocated memory is used if ( index >= count ) index = count; else { // \ru передвинем вправо все элементы массива с последнего до указанного \en move to the right all elements of the array from the last to the specified one memmove( parr + index + 1, parr + index, (count - index) * SIZE_OF_POINTER ); } parr[index] = ent; // \ru записываем новый элемент \en writing new element count++; return true; } return false; } //------------------------------------------------------------------------------ // \ru вернуть индекс элемента в массиве \en return an index of the element in the array // --- template inline size_t RPArray::FindIt( const Type * el ) const { // \ru MA Linux return find_in_array( *this, el ); // ошибка при сопоставлении шаблонов для RPArray \en MA Linux return find_in_array( *this, el ); // an error in matching of templates for RPArray if ( parr ) { TPtr * iterLast = parr+count; TPtr * iter = std::find( parr, iterLast, el ); if ( iter != iterLast ) { return std::distance( parr, iter ); } } return SYS_MAX_T; } //------------------------------------------------------------------------------ // \ru Есть ли в массиве такой указатель \en Whether such pointer exists in the array // --- template inline bool RPArray::IsExist( const Type * el ) const { return (FindIt( el ) != SYS_MAX_T); } //------------------------------------------------------------------------------ // \ru отсоединить элемент от массива (по индексу) \en detach an element from the array (by the index) // --- template inline Type * RPArray::DetachInd( size_t delIndex ) { Type * r = 0; if ( parr ) { PRECONDITION( delIndex < count ); if ( delIndex < count ) { r = parr[delIndex]; memmove( parr + delIndex, parr + delIndex + 1, ( count-- - delIndex - 1 ) * SIZE_OF_POINTER ); } } return r; } //------------------------------------------------------------------------------ // \ru Вставить элемент перед указанным. \en Insert an element before the specified one. // --- template template void RPArray::insert( Iterator pos, const Type * e ) { if ( !begin() ) { reserve( 1 ); pos = begin(); } if ( begin() ) { const ptrdiff_t k = std::distance( (Iterator)begin(), pos ); if ( k >= 0 && k <= (ptrdiff_t)count ) Insert( k, const_cast(e) ); } } //------------------------------------------------------------------------------ // \ru Удалить элемент из массива по индексу. \en Delete an element from array by the index. // --- template template void RPArray::erase( Iterator pos ) { if ( begin() ) { const ptrdiff_t k = std::distance( (Iterator)begin(), pos ); if ( k >= 0 && k < (ptrdiff_t)count ) RemoveInd( k ); } } //------------------------------------------------------------------------------ // \ru Удалить элементы из массива начиная с индекса first до last-1 включительно. \en Delete elements from the array from first to last-1 inclusively. // --- template template void RPArray::erase( Iterator first, Iterator last ) { if ( begin() ) { const ptrdiff_t k1 = std::distance( (Iterator)begin(), first ); const ptrdiff_t k2 = std::distance( (Iterator)begin(), last ); if ( k1 >= 0 && k1 < k2 && k2 <= (ptrdiff_t)count ) { for ( ptrdiff_t k = k2-1; k >= k1; k-- ) { RemoveInd( k ); } } } } //------------------------------------------------------------------------------ // \ru отсоединить элемент от массива (по указателю) \en detach an element from the array (by the pointer) // --- template inline bool RPArray::DetachObj( const Type * delObject ) { size_t i = FindIt( delObject ); if ( i != SYS_MAX_T ) { DetachInd( i ); return true; } return false; } //------------------------------------------------------------------------------- // \ru обменять местами данные массивов \en swap data of arrays // --- template void RPArray::Swap( RPArray & arr ) { std::swap( count, arr.count ); std::swap( upper, arr.upper ); std::swap( delta, arr.delta ); std::swap( parr, arr.parr ); } //------------------------------------------------------------------------------ // \ru захват большего куска памяти ( если нужно ) \en allocate the large piece of memory (if it is necessary) // --- template inline bool RPArray::CatchMemory() { if ( upper == count ) return set_Rarray_size( *this, upper + AutoDelta() ); return true; } //------------------------------------------------------------------------------ // \ru сортировать массив \en sort the array // --- !!!!!!!!!! template inline void RPArray::Sort( CompFunc fcmp ) { ::KsQSort( (void *)parr, count, SIZE_OF_POINTER, (KsQSortCompFunc)fcmp ); } //------------------------------------------------------------------------------ // \ru Установить присланный размер массива. Если он меньше имеющегося count, то \en Set the given size of an array. If it is less than existed 'count' then // \ru лишние элементы массива будут удалены \en extra elements of the array will be deleted // --- template bool set_Rarray_size( RPArray & arr, size_t newSize ) { if ( newSize != arr.upper ) { // \ru половина адресного пространства для 64- и 32-разрядного приложения \en a half of address space for 64- and 32-bit application if ( ::TestNewSize( SIZE_OF_POINTER, newSize ) ) { try { #ifdef __REALLOC_ARRAYS_STATISTIC_ void * oldParr = arr.parr; size_t oldSize = arr.upper; #endif // __REALLOC_ARRAYS_STATISTIC_ #ifdef USE_REALLOC_IN_ARRAYS arr.parr = (typename RPArray::TPtr *)REALLOC_ARRAY_SIZE( arr.parr, newSize * SIZE_OF_POINTER, false/*clear*/ ); #else typename RPArray::TPtr *p_tmp = newSize ? new typename RPArray::TPtr[newSize] : 0; if ( arr.parr && p_tmp ) memcpy( p_tmp, arr.parr, (arr.upper < newSize ? arr.upper : newSize) * SIZE_OF_POINTER ); if ( arr.parr ) delete[] arr.parr; arr.parr = p_tmp; #endif // USE_REALLOC_IN_ARRAYS arr.upper = newSize; arr.count = newSize < arr.count ? newSize : arr.count; #ifdef __REALLOC_ARRAYS_STATISTIC_ REALLOC_ARRAY_STATISTICS( oldParr, oldSize * SIZE_OF_POINTER, arr.parr, newSize * SIZE_OF_POINTER, 1/*RParray*/ ); #endif // __REALLOC_ARRAYS_STATISTIC_ } catch ( const std::bad_alloc & ) { C3D_CONTROLED_THROW; return false; } catch ( ... ) { if ( newSize == 0 )// \ru Не смогли корректно удалить arr.parr. \en Failed to delete arr.parr correctly. arr.parr = nullptr; C3D_CONTROLED_THROW; return false; } } else { PRECONDITION( false ); // \ru не бывает столько памяти \en incorrect size of memory C3D_CONTROLED_THROW_EX( std::bad_alloc() ); return false; } } return true; } //------------------------------------------------------------------------------- // \ru найти объект в массиве \en find an object in the array // --- template size_t find_in_array( const RPArray & arr, const Type * el ) { typename RPArray::TPtr * parr = arr.parr; for ( size_t i = 0, c = arr.count; i < c; i++, parr++ ) if ( *parr == el ) return i; return SYS_MAX_T; } #if defined(_MSC_VER) && !defined(_MSVC_PERMISSIVE_OFF) // LF-Linux: ambiguous template specialization //------------------------------------------------------------------------------- // \ru найти объект в массиве \en find an object in the array // --- template size_t find_in_array( const RPArray & arr, const Type * el ) { typename RPArray::TPtr * parr = arr.parr; for ( size_t i = 0, c = arr.count; i < c; i++, parr++ ) if ( *parr == el ) return i; return SYS_MAX_T; } #endif // _MSC_VER //------------------------------------------------------------------------------ // \ru Вычислить приращение для массива в зависимости от количества предполагаемых \en Calculate an increment for the array according to the number of assumed // \ru объектов в этом массив (делаю так, чтобы захватов памяти было не более 100) - \en objects in this array (so the number of memory captures will not exceed 100) - // \ru иначе при количестве объектов 75000 операции с захватом памяти занимают \en otherwise if the number of objects is 75000 then operations with memory captures take // \ru бесконечное время \en infinite time // --- inline uint16 CalcArrayDelta( size_t objsCount ) { size_t delta = objsCount / 100; delta = delta > 65000 ? 50000 : delta > 0 ? delta : 1; return (uint16)delta; } #endif // __TEMPL_RP_ARRAY_H