Files correlati : ve1.exe Ricompilazione Demo : [ ] Commento : 0001643: Gestione campi trasparenti nei report Per quei campi dove non risulta settato il valore dello sfondo (trasparente, pieno, ecc..) metteremo di default pieno. Questo dovrebbe simulare il comportamento del programma prima della modifica. git-svn-id: svn://10.65.10.50/trunk@20498 c028cbd2-c16b-5b4b-a496-9718f37d4682
906 lines
21 KiB
C++
Executable File
906 lines
21 KiB
C++
Executable File
#include <ctype.h>
|
|
#include <limits.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];
|
|
memset(newdata, 0, arraysize*sizeof(TObject*));
|
|
if (_data != NULL)
|
|
{
|
|
memcpy(newdata, _data, _size*sizeof(TObject*));
|
|
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 = 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;
|
|
}
|
|
|
|
void TArray::copy(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;
|
|
}
|
|
|
|
TArray::TArray(int arraysize)
|
|
: _data(NULL), _size(0), _items(0), _next(0)
|
|
{
|
|
if (arraysize)
|
|
resize(arraysize);
|
|
}
|
|
|
|
TArray::TArray()
|
|
: _data(NULL), _size(0), _items(0), _next(0)
|
|
{
|
|
}
|
|
|
|
TArray::TArray(const TArray& a)
|
|
: _data(NULL), _size(0), _items(0), _next(0)
|
|
{
|
|
copy(a);
|
|
}
|
|
|
|
TArray& TArray::operator= (const TArray& a)
|
|
{
|
|
copy(a);
|
|
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));
|
|
}
|
|
|
|
#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.
|
|
// <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 (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.
|
|
// <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);
|
|
}
|
|
|
|
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*));
|
|
_items = a._items;
|
|
_next = a._next;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
int TPointer_array::find_long(long value) const
|
|
{
|
|
int i = 0;
|
|
for (i = last(); i >= 0 && get_long(i) != value; i = pred(i));
|
|
return i;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TBit_array
|
|
///////////////////////////////////////////////////////////
|
|
|
|
TBit_array::TBit_array(long size)
|
|
: _size(0), _bit(NULL)
|
|
{
|
|
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) : _size(0), _bit(NULL)
|
|
{ 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)
|
|
{
|
|
CHECKD(n >= 0, "Can't set a negative bit ", 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::neg(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;
|
|
}
|
|
|
|
bool TBit_array::some_one() const
|
|
{
|
|
for (word i = 0; i < _size; i++)
|
|
if (_bit[i]) return true;
|
|
return false;
|
|
}
|
|
|
|
|
|
// @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, ' ');
|
|
s.trim(); s.strip_double_spaces();
|
|
FOR_EACH_TOKEN(s, n) if (isdigit(*n))
|
|
set(atol(n));
|
|
}
|
|
|
|
void TBit_array::reset(const char* numbers)
|
|
{
|
|
TToken_string s(numbers, ' ');
|
|
s.trim(); s.strip_double_spaces();
|
|
FOR_EACH_TOKEN(s, n) if (isdigit(*n))
|
|
reset(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;
|
|
}
|
|
|
|
|