#include #include #include void TContainer::for_each( OPERATION_FUNCTION op ) { TObject* curr = first_item(); while(curr) { op(*curr); curr = succ_item(); } } void TContainer::for_each_that( OPERATION_FUNCTION op, CONDITION_FUNCTION match ) { TObject* curr = first_that( match ); while( curr ) { op( *curr ); curr = succ_that( ); } } TObject* TContainer::first_that( CONDITION_FUNCTION match ) { _last_condition = match; if( _last_condition ) { TObject* curr = first_item( ); while( curr && !_last_condition( *curr ) ) curr = succ_item( ); return curr; } else return first_item( ); } TObject* TContainer::last_that( CONDITION_FUNCTION match ) { _last_condition = match; if( _last_condition ) { TObject* curr = last_item( ); while( curr && !_last_condition( *curr ) ) curr = pred_item( ); return curr; } else return last_item( ); } TObject* TContainer::succ_that( ) { if( _last_condition ) { TObject* curr = succ_item( ); while( curr && !_last_condition( *curr ) ) curr = succ_item( ); return curr; } else return succ_item( ); } TObject* TContainer::pred_that( ) { if( _last_condition ) { TObject* curr = pred_item( ); while( curr && !_last_condition( *curr ) ) curr = pred_item( ); return curr; } else return pred_item( ); } long TContainer::count( CONDITION_FUNCTION match ) { long c = 0; TObject* curr = first_item( ); while( curr ) if( match( *curr ) ) c++; return c; } TObject* TArray::first_item( ) { _scanindex = first( ); return ( _scanindex == size( ) )?NULL:_data[ _scanindex ]; }; TObject* TArray::last_item( ) { _scanindex = last( ); return ( _scanindex == -1 )?NULL:_data[ _scanindex ]; }; TObject* TArray::succ_item( ) { _scanindex = succ( _scanindex ); return ( _scanindex == size( ))?NULL:_data[ _scanindex ]; }; TObject* TArray::pred_item( ) { _scanindex = pred( _scanindex ); return ( _scanindex == -1)?NULL:_data[ _scanindex ]; }; // @doc EXTERNAL // @mfunc Modifica la dimensione dell'array. void TArray::resize( int arraysize) // @parm Indica la nuova dimensione che deve assumere l'array. // @comm Alloca la memoria necessaria per contentere i dati della nuova // dimensione inizializzando a NULL tutti i nuovi elementi aggiunti // all'array lasciando inalterati, sia in posizione che in // contenuto gli elementi gia' presenti. // Nel caso si cerchi di diminuire la dimensione viene dato un // messaggio di errore. { CHECK(arraysize > _size, "Can't reduce array size."); TObject** newdata = new TObject* [arraysize]; /* int i = 0; if (_data != NULL) for (i = 0; i < size(); i++) newdata[i] = _data[i]; while (i < arraysize) newdata[i++] = NULL; */ memset(newdata, 0, arraysize*sizeof(TObject*)); if (_data != NULL) memcpy(newdata, _data, _size*sizeof(TObject*)); if (_data != NULL) delete _data; _size = arraysize; _data = newdata; } // @doc EXTERNAL // @mfunc Rimuove uno o tutti (default) gli elementi // @rdesc Ritorna uno dei seguenti parametri: // // @flag TRUE | Se l'operazione e' riuscita con successo // @flag FALSE | Se il numero di elementi e' rimasto invariato bool TArray::destroy( int index, // @parm Numero dell'elemento da eliminare (default -1) bool pack) // @parm Se true richiama la funzione per compattare gli elementi dell'array (default FALSE) // @comm Permette la rimozione di uno (index > 0 ) o di tutti (default) gli // elementi dell'array assegnandone il valore NULL. // Nel caso il parametro pack sia TRUE permette di rendere contigui // tutti gli elementi diversi da NULL tramite la chiamata alla funzione // . { const int old = _items; if (index < 0) { for (int i = last(); i >= 0; i--) if (_data[i] != NULL) { delete _data[i]; _data[i] = NULL; } _items = _next = 0; } else { TObject* o = remove(index, pack); if (o) delete o; } return _items < old; } TArray::TArray(int arraysize) : _size(0), _items(0), _next(0), _data(NULL) { if (arraysize) resize(arraysize); } TArray::TArray() : _size(0), _items(0), _next(0), _data(NULL) { } TArray::TArray(const TArray& a) : _size(0), _items(0), _next(0), _data(NULL) { (*this) = a; } TArray& TArray::operator= (const TArray& a) { destroy(); if (size() < a.size()) resize(a.size()); for (int i = a.size()-1; i >= 0; i--) { const TObject* o = a.objptr(i); if (o != NULL) { _data[i] = o->dup(); #ifdef DBG const long vir_tab1 = *((long*)o); const long vir_tab2 = *((long*)_data[i]); if (vir_tab1 != vir_tab2) NFCHECK("Duplicazione di elementi di array pericolosa"); #endif } } _items = ( int )a.items(); _next = ( int )a._next; return *this; } TArray::~TArray() { if (ok()) { destroy(); delete _data; } } const char* TArray::class_name() const { return "Array"; } word TArray::class_id() const { return CLASS_ARRAY; } // @doc EXTERNAL // @mfunc Stampa un array void TArray::print_on( ostream& out) const // @parm indica l'output sul quale reindirizzare la stampa (funzione standard del C++) // @comm Permette di stampare sull'output passato come parametro il contenuto // dell'array, preceduto dal numero dell'elemetno a cui si riferisce. // Nel caso vi siano degli elementi vuoti (valore = NULL) viene // stampato il valore (null). { for (int i = 0; i < size(); i++) { out.width(4); out << i << ' '; out.width(); if (_data[i] != NULL) out << *_data[i]; else out << "(null)"; out << endl; } } // @doc EXTERNAL // @mfunc Controlla se si tratta di un oggetto valido // // @rdesc Ritorna uno dei seguenti parametri: // @flag TRUE | Se l'array contiene degli elementi // @flag FALSE | Se l'array e' vuoto bool TArray::ok() const // @comm Controlla se la dimensione dell'array e' uguale a 0 e se esistono // degli elementi diversi da NULL { return(size() != 0 && (_data != NULL)); } #ifdef DBG TObject& TArray::operator[] (int index) const { TObject* o = objptr(index); if (o == NULL) { NFCHECK("Can't access NULL array item %d of %d", index, _size); const int f = last(); if (f >= 0) { o = objptr(f)->dup(); ((TArray*)this)->add(o, index); } CHECK(o, "Unrecoverable array access error"); } return *o; } #endif // @doc EXTERNAL // @mfunc Aggiunge un oggetto ad un array. // // @rdesc La funzione ritorna la posizione nella quale e' stato aggiunto // l'oggetto. int TArray::add( TObject *object, // @parm Oggetto da aggiungere nell'array int index) // @parm Posizione in cui aggiungere l'oggetto // @parm TObject | &object | Oggetto da aggiungere nell'array. L'oggetto viene duplicato // @syntax add(TObject* object,int index); // @syntax add(TObject& object,int index); // // @comm Nel caso venga passata una posizione minore di 0 l'elemento viene aggiunto // in coda all'array, diversamente viene l'elemento presente viene // sostitito con l'oggetto passato nei prametri. // Se e' stato passato un indice minore della dimensione dell'array, // viene aumentata automaticamente la dimensione dell'array stesso tramite // la chiamata alla funzione . // ATTENZIONE: Nel caso si passi l'oggetto per indirizzo deve // essere definita la funzione . // // @xref { if (index < 0) for (index = _next; index < size() && _data[index]; index++); if (index >= size()) { long newsize = 3L * index / 2 + 1; if (newsize > INT_MAX) newsize = INT_MAX; resize((int)newsize); } if (object != _data[index]) // Evita ricopiatura su se stesso { if (_data[index] != NULL) { delete _data[index]; _items--; } _data[index] = object; if (object != NULL) { _items++; _next = index+1; } else { if (index < _next) _next = index; } } return index; } // @doc EXTERNAL // @mfunc Inserisce un elemento dell'array nella posizione index // // @rdesc La funzione ritorna la posizione nella quale e' stato inserito l'oggetto. int TArray::insert( TObject *object, // @parm Oggetto da inserire nell'array int index, // @parm Posizione in cui inserire l'oggetto (puo' essere -1) bool force) // @parm Forza l'inserimento anche se la posizione e' vuota // @parm TObject | &object | Oggetto da inserire nell'array. L'oggetto viene duplicato // @syntax insert(TObject* object, int index); // @syntax insert(TObject& object, int index); // // @comm Nel caso l'elemento della posizione passata sia diverso da NULL vengono // spostati di una posizione tutti gli elementi presenti nell'array. // La dimensione dell'array viene automaticamente aumentata nel caso // la stessa non sia sufficiente a contenere il nuovo oggetto. // ATTENZIONE: Nel caso si passi l'oggetto per indirizzo deve // essere definita la funzione . // // @xref { const int s = size(); if ((index >= 0 && index < s) && (force || objptr(index))) { if (_data[s - 1]) // Se l'ultimo non e' vuoto ... add(NULL, s); // ... aggiungi un elemento in fondo for (int i = size()-1; i > index; i--) // size va aggiornato perche potrebbe essere cambiato _data[i] = _data[i - 1]; _data[index] = NULL; } return add(object, index); } int TArray::add(const TObject& object, int index) { TObject* objptr = object.dup(); return add(objptr, index); } int TArray::insert(const TObject& object, int index, bool force) { TObject* objptr = object.dup(); return insert(objptr, index, force); } // @doc EXTERNAL // @mfunc Elimina l'elemento nella posizione index dell'array // // @rdesc Ritorna l'elemento dell'array eliminato senza farne la delete TObject* TArray::remove( int index, // @parm Indica la posizione dell'elemento da eliminare bool dopack) // @parm Indica se si vuole richiamare la funzione // (default FALSE) per spostare gli elementi successivi dell'array { CHECKD(index >= 0, "Can't remove array item ", index); TObject* o = objptr(index); if (o) { _data[index] = NULL; _items--; if (index < _next) _next = index; } if (dopack && index < size()) { const int last = size()-1; for (int i = index ; i < last; i++) _data[i] = _data[i+1]; _data[last] = NULL; } return o; } TObject* TArray::remove_item(bool pack ) { return remove(_scanindex,pack); } void TArray::swap(int i1, int i2) { TObject* o1 = remove(i1, FALSE); TObject* o2 = remove(i2, FALSE); if (o1) add(o1, i2); if (o2) add(o2, i1); } // @doc EXTERNAL // @mfunc Cerca il prossimo oggetto dell'array // // @rdesc Ritorna l'indice del prossimo elemento trovato o size() se non esiste int TArray::succ(int i) const { CHECKD(i >= -1, "Bad array index ", i); for (i++; i < size(); i++) if (_data[i]) break; return i; } // @doc EXTERNAL // @mfunc Cerca il precedente oggetto dell'array // // @rdesc Ritorna l'indice dell'elemento precedente o -1 se non esiste int TArray::pred(int i) const { CHECKD(i <= size(), "Bad array index ", i); for (i--; i >= 0; i--) if (_data[i]) break; return i; } // @doc EXTERNAL // @mfunc Cerca il primo oggetto dell'array // // @rdesc Ritorna l'indice del primo elemento trovato o size() se l'array e' vuoto int TArray::first() const { return succ(-1); } // @doc EXTERNAL // @mfunc Cerca l'ultimo oggetto dell'array // // @rdesc Ritorna l'indice dell'ultimo elemento trovato o -1 se l'array e' vuoto int TArray::last() const { return pred(size()); } // @doc EXTERNAL // @mfunc Rende contigui tutti gli elementi non nulli void TArray::pack() // @comm Riordina gli elementi dell'array facendo che tra di loro non ve ne // siano con valore uguale a NULL. { int next = 0; for (int i = 0; i < size(); i++) { if (_data[i] != NULL) { if (next < i) { _data[next] = _data[i]; _data[i] = NULL; } next++; } } _next = next; } // @doc INTERNAL // @func Funzione per permettere il confonto tra 2 oggetti. // // @rdesc Ritorna i seguenti valori // // @flag 0 | se

// @flag 0 | se

==

// @flag 0 | se

// @flag UNDEFINED | se l'ordine non e' definito static int sortable_compare( const TObject** o1, // @parm Primo oggetto da confrontare const TObject** o2) // @parm Secondo oggetto da confrontare // @comm E' utilizzata dalla funzione come default per // stabilire il criteri di ordinamento degli oggetti passati. { if (o1 == o2) return 0; // qsort a volte confronta un oggetto con se stesso: per cui ne approfitto! const TSortable* s1 = (const TSortable*)*o1; const TSortable* s2 = (const TSortable*)*o2; return s1->compare(*s2); } // @doc EXTERNAL // @mfunc Ordina i TObject secondo il criterio definito in void TArray::sort( COMPARE_FUNCTION compare) // @parm Funzione indicante il criterio di ordinamento (default TSortable) // @comm Nel caso non venga passata nessuna funzione che permetta di conforntare // i due oggetti viene utilizzato il criterio { typedef int (*qsortfunc)(const void*, const void*); if (compare == NULL) compare = sortable_compare; pack(); qsort(_data, items(), sizeof(TObject*), (qsortfunc)compare); } /////////////////////////////////////////////////////////// // TPointer_array /////////////////////////////////////////////////////////// // @doc EXTERNAL // @mfunc Rimuove uno o tutti (default) gli elementi // @rdesc Ritorna uno dei seguenti parametri: // // @flag TRUE | Se l'operazione e' riuscita con successo // @flag FALSE | Se il numero di elementi e' rimasto invariato bool TPointer_array::destroy( int index, // @parm Numero dell'elemento da eliminare (default -1) bool pack) // @parm Se true richiama la funzione per compattare gli elementi dell'array (default FALSE) // @comm Permette la rimozione di uno (index > 0 ) o di tutti (default) gli // elementi dell'array assegnandone il valore NULL. // Nel caso il parametro pack sia TRUE permette di rendere contigui // tutti gli elementi diversi da NULL tramite la chiamata alla funzione // . { if (data()) { if (index < 0) memset(data(), 0, size() * sizeof(TObject*)); else remove(index); } return TArray::destroy(index, pack); } void TPointer_array::copy(const TArray& a) { destroy(); if (size() < a.size()) resize(a.size()); // for (int i = a.size()-1; i >= 0; i--) // add(a.objptr(i), i); memcpy(data(), a.data(), a.size() * sizeof(TObject*)); } int TPointer_array::add(TObject* object, int index) { if (index >= 0) remove(index); return TArray::add(object, index); } int TPointer_array::add(const TObject& object, int index) { return add(&(TObject&)object, index); } int TPointer_array::insert(const TObject& object, int index, bool force) { return TArray::insert(&(TObject&)object, index, force); } /////////////////////////////////////////////////////////// // TBit_array /////////////////////////////////////////////////////////// TBit_array::TBit_array(long size) : _bit(NULL), _size(0) { if (size) resize(index(size)); } // @doc EXTERNAL // @mfunc Copia l'array passato come parametro void TBit_array::copy( const TBit_array& ba) // @parm Array da copiare // @comm Copia il contenuto dell'array passato come parametro. { if (_bit) { delete _bit; _bit = NULL; _size = 0; } resize(ba._size-1); memcpy(_bit, ba._bit, _size); } TBit_array::TBit_array(const TBit_array& ba) : _bit(NULL), _size(0) { copy(ba); } TBit_array& TBit_array::operator=(const TBit_array& ba) { copy(ba); return *this; } TBit_array::~TBit_array() { if (_bit) delete _bit; } // Certified 100% void TBit_array::set() { if (_bit) memset(_bit, 0xFF, _size); } // Certified 100% void TBit_array::reset() { if (_bit) memset(_bit, 0x0, _size); } // Certified 99% // @doc EXTERNAL // // @mfunc Modifica la dimensione dell'array. void TBit_array::resize( word size) // @parm Indica la nuova dimensione che deve assumere l'array. // @comm Alloca la memoria necessaria per contentere i dati della nuova // dimensione inizializzando a NULL tutti i nuovi elementi aggiunti // all'array lasciando inalterati, sia in posizione che in // contenuto gli elementi gia' presenti. { word oldsize = _size; byte* oldbit = _bit; _size = size+1; _bit = new byte[_size]; reset(); if (oldsize) { memcpy(_bit, oldbit, oldsize); delete oldbit; } } bool TBit_array::operator[] (long n) const { const word i = index(n); if (i >= _size) return FALSE; return (_bit[i] & mask(n)) != 0; } // Certified 99% TBit_array& TBit_array::operator|= (const TBit_array& ba) { if (_size < ba._size) resize(ba._size); for (word i = 0; i < _size; i++) _bit[i] |= ba._bit[i]; return *this; } // Certified 99% void TBit_array::set(long n) { const word i = index(n); if (i >= _size) resize(i); _bit[i] |= mask(n); } // Certified 99% void TBit_array::reset(long n) { const word i = index(n); if (i < _size) _bit[i] &= ~mask(n); } // Certified 99% void TBit_array::not(long n) { const word i = index(n); if (i >= _size) resize(i); _bit[i] ^= mask(n); } // Certified 90% // @doc EXTERNAL // @mfunc Ritorna il numero di 1 presenti nell'array // // @rdesc Numero di 1 trovati. long TBit_array::ones() const // @comm Passa tutto l'array di bit e conta quanti degli elementi presenti sono // settati ad 1. // // @xref { long one = 0; for (word i = 0; i < _size; i++) { const byte b = _bit[i]; if (b) { for (byte m = 1; m; m <<= 1) if (b & m) one++; } } return one; } // Certified 90% // @doc EXTERNAL // @mfunc Ritorna la posizione dell'ultimo 1 nell'array // // @rdesc Ritorna i seguenti valori: // @flag >0 | Posizione nella quale si trova l'ultimo 1 // @flag -1 | Se non sono presenti bit settati ad 1 long TBit_array::last_one() const // @comm Cerca all'interno dell'array di bit la posizione dell'ultimo bit // settato ad 1 // // @xref { for (word i = _size; i--;) { const byte b = _bit[i]; if (b) { for (byte j = 8; j--;) if ((1<0 | Posizione nella quale si trova il primo 1 // @flag -1 | Se non sono presenti bit settati ad 1 long TBit_array::first_one() const // @comm Cerca all'interno dell'array di bit la posizione del primo bit // settato ad 1 // // @xref { for (word i = 0; i < _size; i++) { const byte b = _bit[i]; if (b) { for (byte j = 0; j < 8; j++) if ((1< 0; } void TBit_array::set(const char* numbers) { TToken_string s(numbers, ' '); for (const char* n = s.get(0); n; n = s.get()) if (isdigit(*n)) set(atol(n)); } // @doc EXTERNAL // // @mfunc Stampa un array void TBit_array::print_on( ostream& out) const // @parm Indica l'output sul quale reindirizzare la stampa (funzione standard del C++) // @comm Stampa tutti gli indici degli elementi diversi da 0 { const long last = _size<<3; for (long i = 1; i < last; i++) if (operator[](i)) out << ' ' << i; }