campo-sirio/include/array.cpp
guy 3e793a4cab applicat.cpp Gestione semplificata dei bar_item
array.cpp      Corretti TPointer_array
assoc.cpp      Aggiuntta add()
cfiles.c       Corretto salvataggio pathpref.ini
controls.cpp   Aggiunto attributo di read_only
default.url    Aggiunto menu di edit ed help
mask.cpp       Gestione menu edit
maskfld.cpp    Gestione menu edit
msksheet.cpp   Gestione menu edit
progind.cpp    Aggiunto nuova scavatura 3D
sheet.cpp
viswin.cpp     Aggiornati ID del menu edit
window.cpp     Corretta gestione voci di menu standard
xvtility.cpp   Aggiunto metodo per skippare gli errori di XVT


git-svn-id: svn://10.65.10.50/trunk@5791 c028cbd2-c16b-5b4b-a496-9718f37d4682
1997-12-24 14:26:25 +00:00

859 lines
20 KiB
C++
Executable File

#include <limits.h>
#include <ctype.h>
#include <stdlib.h>
#include <strings.h>
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.
// <nl>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;
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 <mf TArray::pack> 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.
// <nl>Nel caso il parametro pack sia TRUE permette di rendere contigui
// tutti gli elementi diversi da NULL tramite la chiamata alla funzione
// <mf TArray::pack>.
{
const int old = _items;
if (index < 0)
{
for (int i = size()-1; 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.
// <nl>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));
}
// @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.
// <nl>Se e' stato passato un indice minore della dimensione dell'array,
// viene aumentata automaticamente la dimensione dell'array stesso tramite
// la chiamata alla funzione <mf TArray::resize>.
// <nl><nl>ATTENZIONE: Nel caso si passi l'oggetto per indirizzo deve
// essere definita la funzione <mf TObject::dup>.
//
// @xref <mf TArray::insert>
{
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 (_data[index] != NULL)
{
#ifdef DBG
if (object == _data[index])
{
error_box("Iu ar traing tu overrait en arrei obgiect: %d", index);
return index;
}
#endif
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.
// <nl><nl>ATTENZIONE: Nel caso si passi l'oggetto per indirizzo deve
// essere definita la funzione <mf TObject::dup>.
//
// @xref <mf TArray::add>
{
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
// <mf TArray::pack> (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 <gt>0 | se <p this> <gt> <p s>
// @flag 0 | se <p this> == <p s>
// @flag <lt>0 | se <p this> <lt> <p s>
// @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 <mf TArray::sort> 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 <t COMPARE_FUNCTION>
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 <c Tsortable>
{
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 <mf TArray::pack> 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.
// <nl>Nel caso il parametro pack sia TRUE permette di rendere contigui
// tutti gli elementi diversi da NULL tramite la chiamata alla funzione
// <mf TArray::pack>.
{
if (data())
{
if (index < 0)
memset(data(), 0, size() * sizeof(TObject*));
else
remove(index);
}
return TArray::destroy(index, pack);
}
TPointer_array& TPointer_array::operator= (const TArray& a)
{
destroy();
if (size() < a.size())
resize(a.size());
for (int i = a.size()-1; i >= 0; i--)
add(a[i], i);
return *this;
}
int TPointer_array::add(TObject* object, int index)
{
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)
{
CHECK(_size >= ba._size, "TBit_array |=: right operand too big");
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 <mf TBit_array::last_one> <mf TBit_array::first_one>
{
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 <mf TBit_array::first_one> <mf TBit_array::ones>
{
for (word i = _size; i--;)
{
const byte b = _bit[i];
if (b)
{
for (byte j = 8; j--;)
if ((1<<j) & b) return (long(i)<<3) + j;
}
}
return -1;
}
// Certified 90%
// @doc EXTERNAL
// @mfunc Ritorna la posizione del primo 1 nell'array
//
// @rdesc Ritorna i seguenti valori:
//
// @flag >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 <mf TBit_array::last_one> <mf TBit_array::ones>
{
for (word i = 0; i < _size; i++)
{
const byte b = _bit[i];
if (b)
{
for (byte j = 0; j < 8; j++)
if ((1<<j) & b) return (long(i)<<3)+j;
}
}
return -1;
}
// @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 TBit_array::ok() const
// @comm Controlla se la dimensione dell'array e' maggiore di 0 e se esistono
// degli elementi diversi da NULL
{
return _bit != NULL && _size > 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;
}