//////////////////////////////////////////////////////////////////////////////// /** \file \brief \ru Little SArray - укороченный SArray. \en Little SArray - shortened SArray. \~ */ //////////////////////////////////////////////////////////////////////////////// #ifndef __TEMPL_LIS_ARRAY_H #define __TEMPL_LIS_ARRAY_H #include #include FORVARD_DECL_TEMPLATE_TYPENAME( class LiSArray ); FORVARD_DECL_TEMPLATE_TYPENAME( void set_array_size( LiSArray &, size_t newSize ) ); FORVARD_DECL_TEMPLATE_TYPENAME( reader & CALL_DECLARATION operator >> ( reader& in, LiSArray & ref ) ); FORVARD_DECL_TEMPLATE_TYPENAME( writer & CALL_DECLARATION operator << ( writer& out, const LiSArray & ref ) ); FORVARD_DECL_TEMPLATE_TYPENAME( reader & CALL_DECLARATION operator >> ( reader& in, LiSArray *& ptr ) ); FORVARD_DECL_TEMPLATE_TYPENAME( writer & CALL_DECLARATION operator << ( writer& out, const LiSArray * ptr ) ); //------------------------------------------------------------------------------ // \ru Little SArray - укороченный SArray \en Little SArray - shortened SArray // \ru одномерный массив объектов не содержащих указателей !!!!!!! \en one-dimensional array of objects without pointers !!! // \ru В массиве нельзя хранить объекты содержащие указатели или \en An array should not contain objects with pointers or // \ru классы с указателями, а также абстрактные классы с наследниками \en classes with pointers and abstract classes with inheritors // --- template class LiSArray { protected : uint8 count; // \ru размерность массива \en a size of the array Type * parr; // \ru Этот массив прирастает всегда по 2. \en This array always increase by 2. enum { li_delta = 2, }; public : LiSArray(); LiSArray( const LiSArray & ); virtual ~LiSArray() { set_array_size( *this, 0 ); } public: void Flush(); // \ru обнулить количество элементов \en set the number of elements to null. Type * Add( const Type & ); // \ru добавить элемент в конец массива \en add element to the end of array Type * InsertInd( size_t index, const Type & ); // \ru вставить элемент перед указанным \en insert element before the specified one void RemoveInd( size_t delIndex ); // \ru удалить элемент из массива \en delete an element from array size_t Count() const { return count; } // \ru дать количество элементов массива \en get the number of elements LiSArray & operator = ( const LiSArray & ); LiSArray & operator += ( const LiSArray & ); const Type & operator []( size_t loc ) const { C3D_ASSERT(loc < count); return parr[loc]; } // \ru ИР C3D_ASSERT нужен для оценки выхода за пределы массива. Я один раз вышел полдня потом искал!!! \en ИР C3D_ASSERT is necessary to detect out of bounds. - Type & operator []( size_t loc ) { C3D_ASSERT(loc < count); return parr[loc]; } // \ru ИР C3D_ASSERT нужен для оценки выхода за пределы массива. Я один раз вышел полдня потом искал!!! \en ИР C3D_ASSERT is necessary to detect out of bounds. - const Type * GetAddr() const { return parr; } // \ru выдать адрес начала массива \en get address of the beginning of an array protected : void CatchMemory(); // \ru захватить память \en catch memory TEMPLATE_FRIEND void set_array_size TEMPLATE_SUFFIX ( LiSArray &, size_t newSize ); TEMPLATE_FRIEND reader & CALL_DECLARATION operator >> TEMPLATE_SUFFIX ( reader & in, LiSArray & ref ); TEMPLATE_FRIEND writer & CALL_DECLARATION operator << TEMPLATE_SUFFIX ( writer & out, const LiSArray & ref ); TEMPLATE_FRIEND reader & CALL_DECLARATION operator >> TEMPLATE_SUFFIX ( reader & in, LiSArray *& ptr ); TEMPLATE_FRIEND writer & CALL_DECLARATION operator << TEMPLATE_SUFFIX ( writer & out, const LiSArray * ptr ); #ifdef __DEBUG_MEMORY_ALLOCATE_FREE_ public: void * operator new ( size_t ); void operator delete ( void *, size_t ); #endif // __DEBUG_MEMORY_ALLOCATE_FREE_ }; #ifdef __DEBUG_MEMORY_ALLOCATE_FREE_ //------------------------------------------------------------------------------ // \ru Перегрузка оператора new. \en Overloading of the "new" operator. // --- template inline void * LiSArray::operator new( size_t size ) { return ::Allocate( size, typeid(LiSArray).name() ); } //------------------------------------------------------------------------------ // \ru Перегрузка оператора delete. \en Overloading of the "delete" operator. // --- template inline void LiSArray::operator delete( void * ptr, size_t size ) { ::Free( ptr, size, typeid(LiSArray).name() ); } #endif // __DEBUG_MEMORY_ALLOCATE_FREE_ //------------------------------------------------------------------------------ // \ru Конструктор массива \en Constructor of an array // --- template inline LiSArray::LiSArray() : count ( 0 ) , parr ( 0 ) {} //------------------------------------------------------------------------------ // \ru Конструктор копирования массива \en Copy-constructor of an array // --- template inline LiSArray::LiSArray( const LiSArray & o ) : count ( 0 ) , parr ( 0 ) { *this = o; } //------------------------------------------------------------------------------ // \ru сбросить массив \en reset an array // --- template inline void LiSArray::Flush() { set_array_size( *this, 0 ); count = 0; } //------------------------------------------------------------------------------ // \ru добавить элемент в конец массива \en add element to the end of array // --- template inline Type* LiSArray::Add( const Type & ent ) { CatchMemory(); C3D_ASSERT( count < 253 ); return (Type*)memcpy( parr+count++, &ent, sizeof(Type) ); // SKIP_SA } //------------------------------------------------------------------------------ // \ru вставить элемент перед указанным \en insert element before the specified one // --- template inline Type * LiSArray::InsertInd( size_t index, const Type & ent ) { C3D_ASSERT( index <= count ); CatchMemory(); // \ru добавить памяти, если все использовано \en add memory if whole allocated memory is used if ( index >= count ) index = count; else { memmove( parr+index+1, parr+index, (count-index) * sizeof(Type) ); // SKIP_SA } count++; C3D_ASSERT( count < 254 ); // \ru передвинем вправо все элементы массива с последнего до указанного \en move to the right all elements of the array from the last to the specified one return (Type*)memcpy( parr+index, &ent, sizeof(Type) ); // \ru записываем новый элемент \en writing new element // SKIP_SA } //------------------------------------------------------------------------------ // \ru удалить элемент из массива \en delete an element from array // --- template inline void LiSArray::RemoveInd( size_t delIndex ) { C3D_ASSERT( delIndex < count ); C3D_ASSERT( delIndex < 254 ); C3D_ASSERT( count < 254 ); if ( delIndex < count ) { memcpy( parr+delIndex, parr+delIndex+1, (count - delIndex-1)*sizeof(Type) ); count--; C3D_ASSERT( count < 254 ); } } //------------------------------------------------------------------------------ // \ru присвоение массива массиву \en assignment of an array to array // --- template inline LiSArray & LiSArray::operator = ( const LiSArray & o ) { set_array_size( *this, o.count ); // \ru обеспечить память на такое кол-во элементов \en allocate memory for the given number of elements count = o.count; C3D_ASSERT( count < 254 ); if ( count > 0 && parr != nullptr ) memcpy( parr, o.parr, count * sizeof(Type) ); // SKIP_SA return *this; } //------------------------------------------------------------------------------ // \ru добавление массива к массиву \en add the array to the array // --- template inline LiSArray & LiSArray::operator += ( const LiSArray & o ) { if ( o.count ) { set_array_size( *this, count + o.count ); // \ru обеспечить память на такое кол-во элементов \en allocate memory for the given number of elements if ( parr != nullptr ) memcpy( parr+count, o.parr, o.count * sizeof(Type) ); count = (uint8)(count + o.count); C3D_ASSERT( count < 254 ); } return *this; } //------------------------------------------------------------------------------ // \ru захват большего куска памяти ( если нужно ) \en allocate the large piece of memory (if it is necessary) // --- template inline void LiSArray::CatchMemory() { C3D_ASSERT( count < 254 ); set_array_size( *this, count + 1 ); // \ru здесь count не увеличивается! \en 'count' is not increased! } //------------------------------------------------------------------------------ // \ru Если захвачен не такой размер памяти, то захватить новый \en If the size of caught memory is not appropriated then allocate memory again // \ru если clear = true, то присвоить arr.count=0 и старое содержимое не копировать \en if clear = true then set arr.count=0 and do not copy the old content // --- template void set_array_size( LiSArray & arr, size_t newSize ) { C3D_ASSERT( newSize <= 0xff ); // \ru поскольку здесь uint8 count \en since uint8 count C3D_ASSERT( arr.Count() < 254 ); uint8 newUpper = (uint8)(newSize + newSize % (size_t)LiSArray::li_delta); uint8 oldUpper = (uint8)(arr.Count() + arr.Count() % (size_t)LiSArray::li_delta); if ( newUpper != oldUpper ) { #ifdef __REALLOC_ARRAYS_STATISTIC_ void *oldParr = arr.parr; #endif // __REALLOC_ARRAYS_STATISTIC_ #ifdef USE_REALLOC_IN_ARRAYS arr.parr = (Type*) ::realloc( arr.parr, newUpper * sizeof(Type) ); #else Type *p_tmp = newUpper ? (Type*)new TCHAR[ newUpper * sizeof(Type) ] : 0; if ( arr.parr && p_tmp ) memcpy( p_tmp, arr.parr, std_min(oldUpper, (uint8)newUpper)* sizeof(Type) ); if ( arr.parr ) delete [] (TCHAR *) arr.parr; arr.parr = p_tmp; #endif // USE_REALLOC_IN_ARRAYS // \ru !!! здесь count не изменяется!!! \en !!! 'count' is not changed!! #ifdef __REALLOC_ARRAYS_STATISTIC_ REALLOC_ARRAY_STATISTICS( oldParr, oldUpper * sizeof(Type), arr.parr, newUpper * sizeof(Type), 3/*LiSArray*/ ); #endif // __REALLOC_ARRAYS_STATISTIC_ } } #endif // __TEMPL_LIS_ARRAY_H