Files
Extern/C3d/Include/templ_s_list.h
SaraP b38b0825ee Extern :
- C3d aggiornamento delle librerie ( 114902).
2021-09-28 17:11:24 +02:00

957 lines
37 KiB
C++

////////////////////////////////////////////////////////////////////////////////
/**
\file
\brief \ru Список.
\en List. \~
*/
////////////////////////////////////////////////////////////////////////////////
#ifndef __TEMPL_S_LIST_H
#define __TEMPL_S_LIST_H
#include <system_types.h>
#include <templ_delete_define.h>
#include <io_define.h>
#include <tool_err_handling.h>
//-----------------------------------------------------------------------------
/** \brief \ru Элемент списка.
\en The list element. \~
\details \ru Элемент списка. \n
\en The list element. \n \~
\ingroup Base_Tools_Containers
*/
// ---
template <class Type>
class ListItem {
public:
ListItem<Type> * next; ///< \ru Указатель на следующий элемент. \en A pointer to the next element.
Type * data; ///< \ru Указатель на поле данных. \en A pointer to field of data.
public:
ListItem() : next( 0 ), data( 0 ) {}
ListItem( Type *d ) : next( 0 ), data( d ) {}
ListItem( Type *d, ListItem<Type> &prev ); // \ru добавить себя после заданного элемента \en add self after the given element
private:
ListItem ( const ListItem& ); // \ru запрещено \en forbidden
void operator = ( const ListItem& ); // \ru запрещено \en forbidden
};
//------------------------------------------------------------------------------
// \ru вставляет себя после item \en inserts itself after 'item'
//---
template <class Type>
inline ListItem<Type>::ListItem( Type *d, ListItem<Type> &prev ) {
next = prev.next;
prev.next = this;
data = d;
}
//------------------------------------------------------------------------------
//
// ---
FORVARD_DECL_TEMPLATE_TYPENAME( class LIterator );
FORVARD_DECL_TEMPLATE_TYPENAME( class List );
FORVARD_DECL_TEMPLATE_TYPENAME( void add_to_list ( List<Type> &, List<Type> & ) );
FORVARD_DECL_TEMPLATE_TYPENAME( void add_to_list ( List<Type> &, Type* data, const Type* after ) );
FORVARD_DECL_TEMPLATE_TYPENAME( void insert_to_list ( List<Type> &, List<Type> & ) );
FORVARD_DECL_TEMPLATE_TYPENAME( void remove_from_list ( List<Type> &, DelType shdl ) );
FORVARD_DECL_TEMPLATE_TYPENAME( void remove_from_list_release ( List<Type> & ) );
FORVARD_DECL_TEMPLATE_TYPENAME( size_t remove_from_list ( List<Type> &, List<Type> &, DelType shdl ) );
FORVARD_DECL_TEMPLATE_TYPENAME( bool detach_from_list ( List<Type> &, const Type * ) );
FORVARD_DECL_TEMPLATE_TYPENAME( size_t recalc_list ( List<Type> & ) );
FORVARD_DECL_TEMPLATE_TYPENAME( bool is_exist_in_list ( const List<Type> &, const Type * ) );
FORVARD_DECL_TEMPLATE_TYPENAME( ListItem<Type> * find_prev_in_list ( const List<Type> &, ListItem<Type>* now ) );
class reader;
class writer;
FORVARD_DECL_TEMPLATE_TYPENAME( reader& CALL_DECLARATION operator >> ( reader& in, List<Type> & ref ) );
FORVARD_DECL_TEMPLATE_TYPENAME( writer& CALL_DECLARATION operator << ( writer& out, const List<Type> & ref ) );
FORVARD_DECL_TEMPLATE_TYPENAME( reader& CALL_DECLARATION operator >> ( reader& in, List<Type> *& ptr ) );
FORVARD_DECL_TEMPLATE_TYPENAME( writer& CALL_DECLARATION operator << ( writer& out, const List<Type> * ptr ) );
//-----------------------------------------------------------------------------
/** \brief \ru Cписок указателей на элементы.
\en List of pointers to elements. \~
\details \ru Cписок указателей на элементы. \n
\en List of pointers to elements. \n \~
\ingroup Base_Tools_Containers
*/
// ---
template <class Type>
class List {
protected:
bool owns; ///< \ru Признак владения элементами. \en Attribute of ownership of elements.
size_t count; ///< \ru Кол-во эл-тов в списке. \en The number of elements in the list.
ListItem<Type> * first; ///< \ru Указатель на первый элемент в списке. \en A pointer to the first list element.
ListItem<Type> * last; ///< \ru Указатель на последний элемент в списке. \en A pointer to the last list element.
ListItem<Type> * nowDelItem; // \ru Bременно, для отладки \en Temporarily, for debugging
Type * nowDelElem; // \ru Bременно, для отладки \en Temporarily, for debugging
public:
explicit List( bool ownsEl = true )
: owns( ownsEl )
, count( 0 )
, first( nullptr )
, last( nullptr )
, nowDelItem( nullptr )
, nowDelElem( nullptr )
{}
virtual ~List();
bool OwnsElem() const { return owns; }
void OwnsElem( bool ownsEl ) { owns = ownsEl; }
void Add( Type * ); // \ru добавить элемент в конец списка \en add an element to the end of the list
void Add( Type *, const Type *after ); // \ru добавить элемент после заданного элемента \en add an element after the given element
void Add( Type *, bool check ); // \ru добавить элемент в конец списка с проверкой на существование \en add an element in the end of the list with existence validation.
void Add ( ListItem<Type> & ); // \ru добавить элемент в конец списка \en add an element to the end of the list
void Add ( List<Type> &l ) { add_to_list(*this, l); } // \ru добавить список list в конец данного списка \en add a list to the end of the given list
void AddAndEat( List<Type> & ); // \ru съесть список list в конец данного списка \en destroy a list and add it to the end of the given list
void Insert ( Type * ); // \ru вставить элемент в начало списка \en insert an element to the beginning of the list
void Insert ( ListItem<Type> & ); // \ru вставить элемент в начало списка \en insert an element to the beginning of the list
void Insert ( List<Type> &l ) { insert_to_list(*this, l); } // \ru вставить список в начало данного списка \en insert a list to the beginning of the given list
void InsertAndEat( List<Type> & ); // \ru съесть список в начало данного списка \en destroy and add a list to the beginning of the given list
void Flush ( DelType shdl=defDelete ) { Remove( shdl ); } // \ru удалить все элементы списка \en delete all elements of the list
void Remove( DelType shdl=defDelete ) { remove_from_list(*this, shdl); } // \ru удалить все элементы списка \en delete all elements of the list
void FlushRelease() { RemoveRelease(); } // \ru удалить все элементы списка \en delete all elements of the list
void RemoveRelease() { remove_from_list_release(*this); } // \ru удалить все элементы списка \en delete all elements of the list
bool Remove( Type *, DelType=defDelete ); // \ru удалить один элемент списка \en delete one element of the list
size_t Remove( List<Type> &l, DelType shdl=defDelete ) { return remove_from_list(*this, l, shdl ); } // \ru удалить все элементы принадлежащие списку l \en delete all elements from the list l
bool Detach( const Type *d ) { return detach_from_list(*this, d); } // \ru отсоединить один элемент списка \en detach one element from the list
size_t Detach( List<Type> &l ) { return Remove(l, noDelete); } // \ru отсоединить от списка другой список элементов \en detach other list from the list
void Close(); // \ru замкнуть список \en close the list
void Split(); // \ru разомкнуть список \en split the list
size_t Count() const {
PRECONDITION( nowDelItem == nullptr && nowDelElem == nullptr );
return count; } // \ru дать количество элементов в списке \en get the number of elements in the list
size_t ReCalc() { return recalc_list(*this); }// \ru пересчитать количество элементов в списке \en count the number of elements in the list
bool IsEmpty () const {
PRECONDITION( nowDelItem == nullptr && nowDelElem == nullptr );
return first == 0; } // \ru проверить, пустой ли список \en check whether the list is empty
bool IsExist( const Type * d ) const { return is_exist_in_list(*this, d);} // \ru найти элемент по равенству указателей \en find an element by the equality of pointers
Type * GetFirstData() const {
PRECONDITION( nowDelItem == nullptr && nowDelElem == nullptr );
PRECONDITION( first ); return first->data; } // \ru получить данные первого элемента списка \en get the data of the first element of the list
Type * GetLastData() const {
PRECONDITION( nowDelItem == nullptr && nowDelElem == nullptr );
PRECONDITION( last ); return last->data; } // \ru получить данные последнего элемента списка \en get the data of the last element of the list
protected:
TEMPLATE_FRIEND class LIterator TEMPLATE_SUFFIX;
private:
ListItem<Type> * findPrev( ListItem<Type> *now ) { return find_prev_in_list(*this, now); } // \ru найти предыдущий \en find the previous
List ( const List<Type>& ); // \ru запрещено \en forbidden
void operator = ( const List<Type>& ); // \ru запрещено \en forbidden
TEMPLATE_FRIEND void add_to_list TEMPLATE_SUFFIX ( List<Type> &, List<Type> & );
TEMPLATE_FRIEND void add_to_list TEMPLATE_SUFFIX ( List<Type> &, Type* data, const Type* after );
TEMPLATE_FRIEND void insert_to_list TEMPLATE_SUFFIX ( List<Type> &, List<Type> & );
TEMPLATE_FRIEND void remove_from_list TEMPLATE_SUFFIX ( List<Type> &, DelType shdl );
TEMPLATE_FRIEND void remove_from_list_release TEMPLATE_SUFFIX ( List<Type> & );
TEMPLATE_FRIEND size_t remove_from_list TEMPLATE_SUFFIX ( List<Type> &, List<Type> &, DelType shdl );
TEMPLATE_FRIEND bool detach_from_list TEMPLATE_SUFFIX ( List<Type> &, const Type * );
TEMPLATE_FRIEND size_t recalc_list TEMPLATE_SUFFIX ( List<Type> & );
TEMPLATE_FRIEND bool is_exist_in_list TEMPLATE_SUFFIX ( const List<Type> &, const Type * );
TEMPLATE_FRIEND ListItem<Type> * find_prev_in_list TEMPLATE_SUFFIX ( const List<Type> &, ListItem<Type>* now );
TEMPLATE_FRIEND reader& CALL_DECLARATION operator >> TEMPLATE_SUFFIX ( reader& in, List<Type> & ref );
TEMPLATE_FRIEND writer& CALL_DECLARATION operator << TEMPLATE_SUFFIX ( writer& out, const List<Type> & ref );
TEMPLATE_FRIEND reader& CALL_DECLARATION operator >> TEMPLATE_SUFFIX ( reader& in, List<Type> *& ptr );
TEMPLATE_FRIEND writer& CALL_DECLARATION operator << TEMPLATE_SUFFIX ( writer& out, const List<Type> * 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 <class Type>
inline void * List<Type>::operator new( size_t size ) {
return ::Allocate( size, typeid(List<Type>).name() );
}
//------------------------------------------------------------------------------
// \ru Перегрузка оператора delete. \en Overloading of the "delete" operator.
// ---
template <class Type>
inline void List<Type>::operator delete( void * ptr, size_t size ) {
::Free( ptr, size, typeid(List<Type>).name() );
}
#endif // __DEBUG_MEMORY_ALLOCATE_FREE_
//-----------------------------------------------------------------------------
/** \brief \ru Итератор списка.
\en Iterator of list. \~
\details \ru Итератор списка. \n
\en Iterator of list. \n \~
\ingroup Base_Tools_Containers
*/
// ---
template <class Type>
class LIterator {
protected:
List<Type> * list;
ListItem<Type> * curr;
ListItem<Type> * prev;
public:
LIterator() : list( nullptr ), curr( nullptr ), prev( nullptr ) {}
LIterator( const List<Type> & l ) : list( nullptr ), curr( nullptr ), prev( nullptr ) { Set(l); }
LIterator( const LIterator<Type> &i ) : list( i.list ), curr( i.curr ), prev( i.prev ) {}
virtual ~LIterator() {}
void Set( const List<Type>& l ) { list = (List<Type>*)&l; Restart(); }
void Restart() { PRECONDITION(list); curr = list->first; prev = nullptr; }
Type * GetData() const { return curr ? curr->data : nullptr; }
Type * GetDataAndGo(); // \ru взять данные и продвинуть итератор \en take the data and move the iterator
List<Type> * GetList() const { return list; }
Type& operator* () const { PRECONDITION(curr && curr->data ); return *curr->data; }
Type* operator () () const { return curr ? curr->data : nullptr; }
operator ListItem<Type>* () const { return curr; }
operator ListItem<Type>& () const { PRECONDITION(curr); return *curr; }
Type* operator ++() { prev = curr; if (curr) {curr=curr->next; return curr ? curr->data : nullptr;} else return nullptr; }
Type* operator ++(int) { prev = curr; if (curr) {Type* ret=curr->data; curr=curr->next; return ret;} else return nullptr; }
Type* operator --() { PRECONDITION(list); curr=prev; prev=list->findPrev(prev); return curr ? curr->data : nullptr; }
Type* operator --(int) { PRECONDITION(list); if (curr) {Type* ret=curr->data; curr=prev; prev=list->findPrev(prev); return ret;} else return nullptr; }
Type* operator ->() { return curr ? curr->data : nullptr; }
bool operator == ( const LIterator<Type> &o ) const { return list==o.list && curr==o.curr; }
bool operator != ( const LIterator<Type> &o ) const { return ! operator == (o); }
LIterator<Type> & operator = ( const List<Type> &l ) { Set(l); return* this; }
LIterator<Type> & operator = ( const LIterator<Type> &o ) { list=o.list; curr = o.curr; prev = o.prev; return *this; }
void Add ( Type * ); // \ru добавить элемент после заданного элемента \en add an element after the given element
void AddAndEat( List<Type> & ); // \ru съесть list после текущего элемента \en destroy the list and add it after the current element
void Insert ( Type * ); // \ru вставить элемент перед заданным элементом \en insert an element before the given element
void InsertAndEat( List<Type> & ); // \ru съесть list перед заданным элементом \en destroy the list and add it before the given element
void Remove( DelType = defDelete ); // \ru удалить элемент списка и продвинуть вперед \en delete an element from the list and move forward
void Detach(); // \ru отсоединить элемент списка \en detach an element from the list
bool IsOK() const { return curr != nullptr; }
ListItem<Type> * Next() const { PRECONDITION(curr); return curr->next; }
void Go() { prev = curr; if ( curr ) curr = curr->next; }
void GoLast() { PRECONDITION(list); curr = list->last; prev = list->findPrev(curr); }
bool IsFirst() const { PRECONDITION(list); return curr == list->first; }
bool IsLast() const { PRECONDITION(list); return curr == list->last; }
};
////////////////////////////////////////////////////////////////////////////////
//
// \ru список указателей на элементы \en a list of pointers to the elements
//
////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------
//
//---
template <class Type>
inline List<Type>::~List() {
PRECONDITION( nowDelItem == nullptr && nowDelElem == nullptr );
Remove();
}
//------------------------------------------------------------------------------
// \ru добавить элемент в конец списка \en add an element to the end of the list
//---
template <class Type>
inline void List<Type>::Add( Type* data ) {
PRECONDITION( nowDelItem == nullptr && nowDelElem == nullptr );
if ( last )
last = new ListItem<Type>( data, *last );
else
first = last = new ListItem<Type>( data );
count++;
}
//------------------------------------------------------------------------------
// \ru добавить элемент после заданного элемента \en add an element after the given element
//---
template <class Type>
inline void List<Type>::Add( Type* data, const Type* after ) {
PRECONDITION( nowDelItem == nullptr && nowDelElem == nullptr );
add_to_list( *this, data, after );
}
//------------------------------------------------------------------------------
// \ru добавить элемент в конец списка с проверкой на существование \en add an element in the end of the list with existence validation
//---
template <class Type>
inline void List<Type>::Add( Type * data, bool /*check*/ )
{
PRECONDITION( nowDelItem == nullptr && nowDelElem == nullptr );
if ( !IsExist(data) )
Add( data );
}
//------------------------------------------------------------------------------
// \ru добавить элемент в конец списка \en add an element to the end of the list
//---
template <class Type>
inline void List<Type>::Add( ListItem<Type> & item )
{
PRECONDITION( nowDelItem == nullptr && nowDelElem == nullptr );
item.next = nullptr;
if ( last )
last->next = &item;
else
first = &item;
last = &item;
count++;
}
//------------------------------------------------------------------------------
// \ru добавить список list в конец данного списка \en add a list to the end of the given list
// \ru list после добавления становится пустым! \en a list becomes empty after the adding of it!
//---
template <class Type>
inline void List<Type>::AddAndEat( List<Type> & list )
{
PRECONDITION( nowDelItem == nullptr && nowDelElem == nullptr );
if ( list.first ) {
if ( last ) {
last->next = list.first;
last = list.last;
}
else {
first = list.first;
last = list.last;
}
count += list.count;
list.count = 0;
list.first = list.last = nullptr;
}
}
//------------------------------------------------------------------------------
// \ru вставить элемент в начало списка \en insert an element to the beginning of the list
//---
template <class Type>
inline void List<Type>::Insert( Type * data )
{
PRECONDITION( nowDelItem == nullptr && nowDelElem == nullptr );
Insert( *new ListItem<Type>(data) );
}
//------------------------------------------------------------------------------
// \ru вставить элемент в начало списка \en insert an element to the beginning of the list
//---
template <class Type>
inline void List<Type>::Insert( ListItem<Type> & item )
{
PRECONDITION( nowDelItem == nullptr && nowDelElem == nullptr );
ListItem<Type>* old = first;
first = &item;
first->next = old;
if ( !last )
last = first;
count++;
}
//------------------------------------------------------------------------------
// \ru съесть список list в начало данного списка \en destroy and add a list to the beginning of the given list
//---
template <class Type>
inline void List<Type>::InsertAndEat( List<Type> & list )
{
PRECONDITION( nowDelItem == nullptr && nowDelElem == nullptr );
if ( list.first ) {
if ( first ) {
PRECONDITION( list.last );
list.last->next = first;
first = list.first;
}
else {
first = list.first;
last = list.last;
}
count += list.count;
list.count = 0;
list.first = list.last = nullptr;
}
}
//------------------------------------------------------------------------------
// \ru удалить один элемент списка \en delete one element of the list
//---
template <class Type>
inline bool List<Type>::Remove( Type * del, DelType shdl )
{
PRECONDITION( nowDelItem == nullptr && nowDelElem == nullptr );
if ( Detach(del) ) {
if ( shdl==Delete || (shdl==defDelete && owns) ) {
nowDelElem = del;
delete del;
nowDelElem = nullptr;
}
return true;
}
return false;
}
//------------------------------------------------------------------------------
// \ru замкнуть список \en close the list
//---
template <class Type>
inline void List<Type>::Close()
{
PRECONDITION( nowDelItem == nullptr && nowDelElem == nullptr );
if ( last )
last->next = first;
}
//------------------------------------------------------------------------------
// \ru разомкнуть список \en split the list
//---
template <class Type>
inline void List<Type>::Split()
{
PRECONDITION( nowDelItem == nullptr && nowDelElem == nullptr );
if ( last )
last->next = nullptr;
}
////////////////////////////////////////////////////////////////////////////////
//
// \ru итератор списка \en Iterator of list
//
////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------
// \ru взять данные и продвинуть итератор \en take the data and move the iterator.
//---
template <class Type>
inline Type * LIterator<Type>::GetDataAndGo()
{
PRECONDITION( list && list->nowDelItem == nullptr && list->nowDelElem == nullptr );
if ( curr ) {
Type * ret = curr->data;
prev = curr;
curr = curr->next;
return ret;
}
return nullptr;
}
//------------------------------------------------------------------------------
// \ru добавить элемент после текущего элемента \en add an element after the current element
//---
template <class Type>
inline void LIterator<Type>::Add( Type * data )
{
PRECONDITION( list && list->nowDelItem == nullptr && list->nowDelElem == nullptr );
if ( list ) {
if ( curr ) {
ListItem<Type> * newItem = new ListItem<Type>( data, *curr ); // \ru поставит себя после curr \en inserts itself after 'curr'
if ( list->last == curr )
list->last = newItem;
list->count++;
}
else
list->Add( data );
}
}
//------------------------------------------------------------------------------
// \ru съесть list после текущего элемента \en destroy a list and add it after the current element
//---
template <class Type>
inline void LIterator<Type>::AddAndEat( List<Type> & l )
{
PRECONDITION( list && list->nowDelItem == nullptr && list->nowDelElem == nullptr );
if ( list && l.first ) {
if ( curr ) {
PRECONDITION( l.last );
l.last->next = curr->next;
curr->next = l.first;
if ( list->last == curr )
list->last = l.last;
list->count += l.count;
l.count = 0;
l.first = l.last = nullptr;
}
else
list->AddAndEat( l ); // \ru съесть список l в конец данного списка \en destroy a list l and add it to the end of the given list
}
}
//------------------------------------------------------------------------------
// \ru вставить элемент перед текущим \en insert an element before the specified one
//---
template <class Type>
inline void LIterator<Type>::Insert( Type * data )
{
PRECONDITION( list && list->nowDelItem == nullptr && list->nowDelElem == nullptr );
if ( list ) {
if ( prev ) {
ListItem<Type> * newItem = new ListItem<Type>( data, *prev ); // \ru ставит себя после prev \en inserts itself after 'prev'
if ( list->last == prev )
list->last = newItem;
prev = newItem;
list->count++;
}
else
list->Insert( data ); // \ru вставить элемент в начало списка \en insert an element to the beginning of the list
}
}
//------------------------------------------------------------------------------
// \ru съесть list перед моим текущим элементом \en destroy a list and add it before mine current element
//---
template <class Type>
inline void LIterator<Type>::InsertAndEat( List<Type> & l )
{
PRECONDITION( list && list->nowDelItem == nullptr && list->nowDelElem == nullptr );
if ( list && l.first ) {
if ( prev ) {
PRECONDITION( l.last );
prev->next = l.first;
l.last->next = curr;
prev = l.last;
list->count += l.count;
l.count = 0;
l.first = l.last = nullptr;
}
else
list->InsertAndEat( l ); // \ru съесть список l в конец данного списка \en destroy a list l and add it to the end of the given list
}
}
//------------------------------------------------------------------------------
// \ru удалить текущий элемент итератора \en delete the current element of the iterator
//---
template <class Type>
inline void LIterator<Type>::Remove( DelType shdl )
{
PRECONDITION( list && list->nowDelItem == nullptr && list->nowDelElem == nullptr );
if ( list && curr ) {
if ( shdl==Delete || (shdl==defDelete && list->owns) ) {
list->nowDelElem = curr->data;
delete curr->data;
list->nowDelElem = nullptr;
}
Detach();
}
}
//------------------------------------------------------------------------------
// \ru отсоединить элемент списка \en detach an element from the list
//---
template <class Type>
inline void LIterator<Type>::Detach()
{
PRECONDITION( list && list->nowDelItem == nullptr && list->nowDelElem == nullptr );
if ( list && curr ) {
ListItem<Type>* next = curr->next;
if ( prev )
prev->next = next;
else
list->first = next;
if ( !next )
list->last = prev;
list->nowDelItem = curr;
delete curr;
list->nowDelItem = nullptr;
curr = next;
prev = list->findPrev( curr );
list->count--;
}
}
//------------------------------------------------------------------------------
template <class Type>
void add_to_list( List<Type> & list, Type * data, const Type * after )
{
PRECONDITION( list.nowDelItem == nullptr && list.nowDelElem == nullptr );
if ( after ) {
ListItem<Type> *c = list.first;
while ( c ) {
if ( c->data == after ) {
ListItem<Type> *newItem = new ListItem<Type>( data, *c ); // \ru поставит себя после c \en inserts itself after 'c'
if ( list.last == c )
list.last = newItem;
list.count++;
return;
}
else
c = c->next;
}
}
list.Add( data );
}
//------------------------------------------------------------------------------
template <class Type>
void add_to_list( List<Type> & to, List<Type> & from )
{
PRECONDITION( to.nowDelItem == nullptr && to.nowDelElem == nullptr );
PRECONDITION( from.nowDelItem == nullptr && from.nowDelElem == nullptr );
ListItem<Type> *curr = from.first;
while ( curr ) {
to.Add( curr->data );
curr = curr->next;
}
if ( to.owns )
from.owns = false;
}
//------------------------------------------------------------------------------
template <class Type>
void insert_to_list( List<Type> & to, List<Type> & from )
{
PRECONDITION( to.nowDelItem == nullptr && to.nowDelElem == nullptr );
PRECONDITION( from.nowDelItem == nullptr && from.nowDelElem == nullptr );
ListItem<Type> *curr = from.first;
while ( curr ) {
to.Insert( curr->data );
curr = curr->next;
}
if ( to.owns )
from.owns = false;
}
//------------------------------------------------------------------------------
// \ru Очистить лист с возможным удаленим данных \en Clear the list with data deletion
// ---
template <class Type>
void remove_from_list( List<Type> & list, DelType shdl )
{
PRECONDITION( list.nowDelItem == nullptr && list.nowDelElem == nullptr );
bool del = shdl==Delete || (shdl==defDelete && list.owns);
ListItem<Type> *first = list.first;
list.first = nullptr;
list.last = nullptr;
list.count = 0;
while ( first ) {
ListItem<Type> *temp = first;
first = first->next;
if ( del ) {
list.nowDelElem = temp->data;
delete temp->data;
list.nowDelElem = nullptr;
}
list.nowDelItem = temp;
delete temp;
list.nowDelItem = nullptr;
}
}
//------------------------------------------------------------------------------
// \ru Очистить лист с возможным удаленим данных \en Clear the list with data deletion
// ---
template <class Type>
void remove_from_list_release( List<Type> & list )
{
PRECONDITION( list.nowDelItem == nullptr && list.nowDelElem == nullptr );
ListItem<Type> *first = list.first;
list.first = nullptr;
list.last = nullptr;
list.count = 0;
while ( first ) {
ListItem<Type> *temp = first;
first = first->next;
list.nowDelElem = temp->data;
if ( temp->data )
temp->data->Release();
list.nowDelElem = nullptr;
list.nowDelItem = temp;
delete temp;
list.nowDelItem = nullptr;
}
}
//------------------------------------------------------------------------------
// \ru Отцепить один список от другого с возможным удалением данных \en Detach one list from another with data deletion
// ---
template <class Type>
size_t remove_from_list( List<Type> & list, List<Type> & deList, DelType shdl )
{
PRECONDITION( &list != &deList );
PRECONDITION( list.nowDelItem == nullptr && list.nowDelElem == nullptr );
PRECONDITION( deList.nowDelItem == nullptr && deList.nowDelElem == nullptr );
if ( !list.first || !deList.first ) // \ru какой-то из списков пуст ! \en one of the lists is empty !
return 0;
bool willDel = shdl==Delete || (shdl==defDelete && list.owns);
list.last->next = list.first; // \ru закольцуем список \en close the list
ListItem<Type> *curr = list.first; // \ru начнем сначала \en start from the beginning
ListItem<Type> *prev = list.last;
ListItem<Type> *del = deList.first; // \ru текущий удаляемый \en the current deleted
ListItem<Type> *pdel = nullptr; // \ru предыдущий удаляемый \en the previous deleted
size_t deleted = 0; // \ru отцепленных 0 \en there are 0 detached
while( del && list.first ) { // \ru есть еще пока чего удалять и откуда \en there are elements to delete
ListItem<Type> *from = curr; // \ru начинаем с текущего \en start from the current one
bool found = false;
do {
if ( curr->data == del->data ) { // \ru поймался !! \en found !!
ListItem<Type> *condemned = curr; // \ru его будем удалять \en it will be deleted
found = true;
if ( list.first == list.last ) { // \ru если всего один элемент, то ничего не останется \en if there is only one element then nothing will be left
list.count = 0;
list.first = nullptr;
list.last = nullptr;
// \ru curr продвигать не нужно - все равно заканчиваем \en 'curr' should not be moved
}
else {
list.count--; // \ru скорректируем счетчик \en correct the counter
if ( list.first == curr ) // \ru если вдруг в начале списка - \en if it is in the beginning of the list
list.first = curr->next; // \ru начало сдвинуть \en then move the beginning
if ( list.last == curr ) // \ru если вдруг в конце списка - \en if it is in the end of the list
list.last = prev; // \ru конец сдвинуть \en then move the end
prev->next = curr->next; // \ru отцепим найденный \en detach the found one
curr = curr->next; // \ru продвинемся \en move
}
if ( willDel ) { // \ru если надо - удалим данные \en delete the data if it is necessary
list.nowDelElem = condemned->data;
delete condemned->data;
list.nowDelElem = nullptr;
}
list.nowDelItem = condemned;
delete condemned; // \ru удалим квартиру \en delete condemned
list.nowDelItem = nullptr;
deleted++; // \ru еще один удалили \en another one has been deleted
break;
}
else { // \ru если не нашли - продвинемся на следующий \en if nothing is found then move to the next
prev = curr;
curr = curr->next;
}
} while( curr != from ); // \ru есть где поискать \en there is something to find
ListItem<Type> *next = del->next;
if ( found && willDel ) { // \ru удаляем квартиру в list'е задающем список удаляемых \en delete a condemned from the list which sets the list of deleted elements
if ( pdel )
pdel->next = next;
else
deList.first = next;
if ( !next )
deList.last = pdel;
deList.nowDelItem = del;
delete del; // \ru помним, что данные мы уже удалили \en remember that the data has already been deleted
deList.nowDelItem = nullptr;
deList.count--;
}
else
pdel = del;
del = next;
}
if ( list.last )
list.last->next = nullptr; // \ru разорвать список \en split the list
return deleted;
}
//------------------------------------------------------------------------------
template <class Type>
bool detach_from_list( List<Type> & from, const Type * del )
{
PRECONDITION( from.nowDelItem == nullptr && from.nowDelElem == nullptr );
ListItem<Type>* curr = from.first;
ListItem<Type>* prev = nullptr;
while( curr ) {
if ( curr->data == del ) { // \ru нашли \en found
ListItem<Type> *next = curr->next;
if ( prev )
prev->next = next;
else
from.first = next;
if ( !next )
from.last = prev;
from.nowDelItem = curr;
delete curr;
from.nowDelItem = nullptr;
from.count--;
return true;
}
else {
prev = curr;
curr = curr->next;
}
}
return false;
}
//------------------------------------------------------------------------------
template <class Type>
size_t recalc_list( List<Type> & list )
{
PRECONDITION( list.nowDelItem == nullptr && list.nowDelElem == nullptr );
list.count = 0;
ListItem<Type> *curr = list.first;
while ( curr ) {
list.count++;
curr = curr->next;
}
return list.count;
}
//------------------------------------------------------------------------------
template <class Type>
bool is_exist_in_list( const List<Type> & list, const Type * what )
{
PRECONDITION( list.nowDelItem == nullptr && list.nowDelElem == nullptr );
bool exist = false;
ListItem<Type> * curr = list.first;
while ( curr && !exist ) {
exist = ( curr->data == what );
curr = curr->next;
}
return exist;
}
//------------------------------------------------------------------------------
template <class Type>
ListItem<Type> * find_prev_in_list( const List<Type> & list, ListItem<Type> * now )
{
PRECONDITION( list.nowDelItem == nullptr && list.nowDelElem == nullptr );
if ( now ) {
ListItem<Type> *tmp = list.first;
while( tmp && tmp->next != now )
tmp = tmp->next;
return tmp;
}
return nullptr;
}
#endif // __TEMPL_S_LIST_H