Files
Extern/C3d/Include/templ_rp_array.h
T
SaraP 52f91a1dbb Extern :
- C3d aggiornamento librerie ( 118037).
2025-06-05 08:23:20 +02:00

751 lines
36 KiB
C++

////////////////////////////////////////////////////////////////////////////////
/**
\file
\brief \ru Одномерный массив указателей.
\en One-dimensional array of pointers. \~
*/
////////////////////////////////////////////////////////////////////////////////
#ifndef __TEMPL_RP_ARRAY_H
#define __TEMPL_RP_ARRAY_H
#include <system_cpp_standard.h>
#include <io_define.h>
#include <tool_quick_sort.h>
#include <templ_delete_define.h>
#include <string.h>
#include <tool_err_handling.h>
FORVARD_DECL_TEMPLATE_TYPENAME( class RPArray );
FORVARD_DECL_TEMPLATE_TYPENAME( bool set_Rarray_size( RPArray<Type> &, size_t newSize ) );
FORVARD_DECL_TEMPLATE_TYPENAME( size_t find_in_array ( const RPArray<Type> & arr, const Type * el ) );
FORVARD_DECL_TEMPLATE_TYPENAME( reader & CALL_DECLARATION operator >> ( reader & in, RPArray<Type> & ref ) );
FORVARD_DECL_TEMPLATE_TYPENAME( writer & CALL_DECLARATION operator << ( writer & out, const RPArray<Type> & ref ) );
FORVARD_DECL_TEMPLATE_TYPENAME( reader & CALL_DECLARATION operator >> ( reader & in, RPArray<Type> *& ptr ) );
FORVARD_DECL_TEMPLATE_TYPENAME( writer & CALL_DECLARATION operator << ( writer & out, const RPArray<Type> * 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 Type>
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<Type> & ); ///< \ru Добавить массив. \en Add array.
bool AddCArray ( const Type **, size_t count ); ///< \ru Добавить C-массив. \en Add C-array.
bool InsertArray( const RPArray<Type> &, 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 ( static_cast<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] : static_cast<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<Type *>(e) ); } ///< \ru Добавить элемент в конец массива. \en Add an element to the end of the array.
void emplace_back( const Type * e ) { Add( const_cast<Type *>(e) ); } ///< \ru Добавить элемент в конец массива. \en Add an element to the end of the array.
template <class Iterator>
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 <class Iterator>
void erase( Iterator pos ); ///< \ru Удалить элемент из массива по индексу. \en Delete an element from array by the index.
template <class Iterator>
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_cast<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<Type> & ); // \ru запрещено !!! \en forbidden !!!
RPArray<Type> & operator =( const RPArray<Type> & ); // \ru запрещено !!! \en forbidden !!!
TEMPLATE_FRIEND bool set_Rarray_size TEMPLATE_SUFFIX ( RPArray<Type> &, size_t newSize );
TEMPLATE_FRIEND size_t find_in_array TEMPLATE_SUFFIX ( const RPArray<Type> & arr, const Type * el );
#if defined(_MSC_VER) && !defined(_MSVC_PERMISSIVE_OFF)
TEMPLATE_FRIEND size_t find_in_array TEMPLATE_SUFFIX ( const RPArray<const Type> & arr, const Type * el );
#endif // _MSC_VER
TEMPLATE_FRIEND reader & CALL_DECLARATION operator >> TEMPLATE_SUFFIX ( reader & in, RPArray<Type> & ref );
TEMPLATE_FRIEND writer & CALL_DECLARATION operator << TEMPLATE_SUFFIX ( writer & out, const RPArray<Type> & ref );
TEMPLATE_FRIEND reader & CALL_DECLARATION operator >> TEMPLATE_SUFFIX ( reader & in, RPArray<Type> *& ptr );
TEMPLATE_FRIEND writer & CALL_DECLARATION operator << TEMPLATE_SUFFIX ( writer & out, const RPArray<Type> * 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<Type> && ); ///< \ru Конструктор перемещения массива. \en Constructor of an array moving.
RPArray<Type> & operator = ( RPArray<Type> && ); ///< \ru Оператор перемещения массива. \en Operator of an array moving.
};
#ifdef __DEBUG_MEMORY_ALLOCATE_FREE_
//------------------------------------------------------------------------------
// \ru Перегрузка оператора new. \en Overloading of the "new" operator.
// ---
template <class Type>
inline void * RPArray<Type>::operator new( size_t size ) {
return ::Allocate( size, typeid(RPArray<Type>).name() );
}
//------------------------------------------------------------------------------
// \ru Перегрузка оператора delete. \en Overloading of the "delete" operator.
// ---
template <class Type>
inline void RPArray<Type>::operator delete( void * ptr, size_t size ) {
::Free( ptr, size, typeid(RPArray<Type>).name() );
}
#endif // __DEBUG_MEMORY_ALLOCATE_FREE_
//------------------------------------------------------------------------------
// \ru конструктор массива \en constructor of an array
// ---
template <class Type>
inline RPArray<Type>::RPArray()
: count( 0 )
, upper( 0 )
, delta( 1 )
, parr ( 0 )
{}
//------------------------------------------------------------------------------
// \ru конструктор массива \en constructor of an array
// ---
template <class Type>
inline RPArray<Type>::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 <class Type>
inline RPArray<Type>::RPArray( RPArray<Type> && _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 <class Type>
RPArray<Type> & RPArray<Type>::operator = ( RPArray<Type> && _Right )
{
if ( this != &_Right )
{
set_Rarray_size( *this, 0 );
_Right.Swap( *this );
}
return (*this);
}
//------------------------------------------------------------------------------
// \ru деструктор массива \en destructor of array
// ---
template <class Type>
inline RPArray<Type>::~RPArray() {
set_Rarray_size( *this, 0 ); //delete [] parr;
}
//------------------------------------------------------------------------------
// \ru Оператор доступа по индексу. \en Access by index operator.
// ---
template <class Type>
inline Type *& RPArray<Type>::operator []( size_t loc ) const
{
return parr[loc];
}
//------------------------------------------------------------------------------
// \ru Доступ к первому элементу. \en Access to the first element.
// ---
template <class Type>
inline const typename RPArray<Type>::value_type RPArray<Type>::front() const {
PRECONDITION( !empty() );
return *parr;
}
//-------------------------------------------------------------------------------
// \ru Доступ к первому элементу. \en Access to the first element.
// ---
template <class Type>
inline typename RPArray<Type>::value_type & RPArray<Type>::front() {
PRECONDITION( !empty() );
return *parr;
}
//-------------------------------------------------------------------------------
// \ru Доступ к последнему элементу. \en Access to the last element.
// ---
template <class Type>
inline const typename RPArray<Type>::value_type RPArray<Type>::back() const
{
PRECONDITION( !empty() );
return *( parr + count - 1 );
}
//-------------------------------------------------------------------------------
// \ru Доступ к последнему элементу. \en Access to the last element.
// ---
template <class Type>
inline typename RPArray<Type>::value_type & RPArray<Type>::back()
{
PRECONDITION( !empty() );
return *( parr + count - 1 );
}
//-------------------------------------------------------------------------------
// \ru Доступ по индексу. \en Access by index operator.
// ---
template <class Type>
inline typename RPArray<Type>::const_reference RPArray<Type>::at( size_t idx ) const
{
PRECONDITION( idx < count );
return parr[idx];
}
//-------------------------------------------------------------------------------
// \ru Доступ по индексу. \en Access by index operator.
// ---
template <class Type>
inline typename RPArray<Type>::reference RPArray<Type>::at( size_t idx )
{
PRECONDITION( idx < count );
return parr[idx];
}
//-------------------------------------------------------------------------------
// \ru обнулить количество элементов \en set the number of elements to null
// ---
template <class Type>
inline void RPArray<Type>::DetachAll() {
count = 0;
}
//------------------------------------------------------------------------------
// \ru Указать новый размер массива. \en Set the new size of an array.
// ---
template <class Type>
inline bool RPArray<Type>::SetSize( size_t newSize ) {
return set_Rarray_size( *this, newSize );
}
//------------------------------------------------------------------------------
// \ru Зарезервировать место под n элементов. \en Reserve memory for n elements.
// ---
template <class Type>
inline bool RPArray<Type>::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 <class Type>
inline bool RPArray<Type>::AddMemory( size_t n ) {
if ( upper - count < n ) {
return set_Rarray_size( *this, count + n );
}
return true;
}
//------------------------------------------------------------------------------
// \ru освободить лишнюю память \en free unnecessary memory
// ---
template <class Type>
inline void RPArray<Type>::Adjust() {
if ( count < upper )
set_Rarray_size( *this, count );
}
//------------------------------------------------------------------------------
// \ru добавить 1 элемент в конец массива \en add 1 element to the end of array
// ---
template <class Type>
inline bool RPArray<Type>::Add( Type * ent ) {
if ( CatchMemory() ) {
parr[count++] = ent;
return true;
}
return false;
}
//------------------------------------------------------------------------------
// \ru добавить 1 элемент после заданного \en add 1 element after the given one
// ---
template <class Type>
inline bool RPArray<Type>::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 <class Type>
inline bool RPArray<Type>::AddArray( const RPArray<Type> & from ) {
return AddCArray( from.GetAddr(), from.count );
}
//------------------------------------------------------------------------------
// \ru добавить C-массив \en add C-array
// ---
template <class Type>
inline bool RPArray<Type>::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 <class Type>
inline bool RPArray<Type>::InsertArray( const RPArray<Type> & 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 <class Type>
inline bool RPArray<Type>::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 <class Type>
inline size_t RPArray<Type>::FindIt( const Type * el ) const
{
// \ru MA Linux return find_in_array( *this, el ); // ошибка при сопоставлении шаблонов для RPArray<const Type> \en MA Linux return find_in_array( *this, el ); // an error in matching of templates for RPArray<const Type>
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 <class Type>
inline bool RPArray<Type>::IsExist( const Type * el ) const {
return (FindIt( el ) != SYS_MAX_T);
}
//------------------------------------------------------------------------------
// \ru отсоединить элемент от массива (по индексу) \en detach an element from the array (by the index)
// ---
template <class Type>
inline Type * RPArray<Type>::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 <class Type>
template <class Iterator>
void RPArray<Type>::insert( Iterator pos, const Type * e )
{
if ( !begin() ) {
reserve( 1 );
pos = begin();
}
if ( begin() ) {
const ptrdiff_t k = std::distance( static_cast<Iterator>(begin()), pos );
if ( k >= 0 && k <= static_cast<ptrdiff_t>(count) )
Insert( k, const_cast<Type *>(e) );
}
}
//------------------------------------------------------------------------------
// \ru Удалить элемент из массива по индексу. \en Delete an element from array by the index.
// ---
template <class Type>
template <class Iterator>
void RPArray<Type>::erase( Iterator pos )
{
if ( begin() ) {
const ptrdiff_t k = std::distance( static_cast<Iterator>(begin()), pos );
if ( k >= 0 && k < static_cast<ptrdiff_t>(count) )
RemoveInd( k );
}
}
//------------------------------------------------------------------------------
// \ru Удалить элементы из массива начиная с индекса first до last-1 включительно. \en Delete elements from the array from first to last-1 inclusively.
// ---
template <class Type>
template <class Iterator>
void RPArray<Type>::erase( Iterator first, Iterator last )
{
if ( begin() ) {
const ptrdiff_t k1 = std::distance( static_cast<Iterator>(begin()), first );
const ptrdiff_t k2 = std::distance( static_cast<Iterator>(begin()), last );
if ( k1 >= 0 && k1 < k2 && k2 <= static_cast<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 <class Type>
inline bool RPArray<Type>::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 <class Type>
void RPArray<Type>::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 <class Type>
inline bool RPArray<Type>::CatchMemory() {
if ( upper == count )
return set_Rarray_size( *this, upper + AutoDelta() );
if ( parr != nullptr )
return true;
return false;
}
//------------------------------------------------------------------------------
// \ru сортировать массив \en sort the array
// --- !!!!!!!!!!
template <class Type>
inline void RPArray<Type>::Sort( CompFunc fcmp ) {
::KsQSort( static_cast<void *>(parr), count, SIZE_OF_POINTER, reinterpret_cast<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 <class Type>
bool set_Rarray_size( RPArray<Type> & 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<Type>::TPtr *)REALLOC_ARRAY_SIZE( arr.parr, newSize * SIZE_OF_POINTER, false/*clear*/ );
#else
typename RPArray<Type>::TPtr *p_tmp = newSize ? new typename RPArray<Type>::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 <class Type>
size_t find_in_array( const RPArray<Type> & arr, const Type * el ) {
typename RPArray<Type>::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 <class Type>
size_t find_in_array( const RPArray<const Type> & arr, const Type * el ) {
typename RPArray<const Type>::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 static_cast<uint16>(delta);
}
#endif // __TEMPL_RP_ARRAY_H