campo-sirio/include/assoc.cpp
andrea 4bb131e5cf Corretta documentazione in linea
git-svn-id: svn://10.65.10.50/trunk@3257 c028cbd2-c16b-5b4b-a496-9718f37d4682
1996-07-27 09:19:01 +00:00

363 lines
8.9 KiB
C++
Executable File

#include <assoc.h>
// @doc EXTERNAL
// @mfunc Cerca l'oggetto con chiave <p k>
//
// @rdesc Ritorna l'oggetto corrispondente alla chiave passate come parametro.
// <nl>Il parametro <p isnew> assume il valore TRUE se si tratta di un
// nuovo oggetto.
THash_object* TAssoc_array::_lookup(
const char* k, // @parm Chiave da cercare
bool& isnew, // @parm Viene asseganto TRUE se si tratta di una nuova chiave
bool insert) // @parm Permette di inserire la chiave
// @comm Ricerca all'interno della tabella hash l'oggetto con la chiave <p k>,
// nel caso non venga trovato <p isnew> ritorna TRUE (si tratta di un
// oggetto nuovo) e viene inserito nella tabella se il parametro <p insert>
// e' settato a TRUE.
{
const TFixed_string key(k);
const word hv = key.hash() % HASH_SIZE;
TArray& arr = _data[hv];
THash_object* o = NULL;
isnew = FALSE;
for (int i = 0; i < arr.items(); i++)
{
THash_object* ob = (THash_object*)&arr[i];
if (ob->_key == key)
{ o = ob; break; }
if (ob->_key > key)
break;
}
if (o == NULL && insert)
{
o = new THash_object(key);
arr.insert(o,i);
isnew = TRUE;
_cnt++;
}
return o;
}
void TAssoc_array::destroy()
{
for (int i = 0; i < HASH_SIZE; i++)
_data[i].destroy();
_cnt = _row = _col = 0;
}
TObject* TAssoc_array::first_item( )
{
_rowitem = 0;
_colitem = 0;
return succ_item( );
}
TObject* TAssoc_array::last_item( )
{
_rowitem = HASH_SIZE - 1;
while( _rowitem >= 0 && _data[ _rowitem ].items() == 0 )
_rowitem --;
if( _rowitem < 0 )
return NULL;
const TArray* arr = &_data[_rowitem];
_colitem = arr->items( ) - 1;
return pred_item( );
}
TObject* TAssoc_array::succ_item( )
{
const TArray* arr = &_data[_rowitem];
for(;_rowitem < HASH_SIZE;)
{
if ((int)_colitem < arr->items())
break;
arr = &_data[++_rowitem];
_colitem = 0;
}
if (_rowitem == HASH_SIZE)
return NULL;
THash_object* o = (THash_object*)arr->objptr(_colitem++);
return (o == NULL || o->_obj == NULL) ? NULL : o->_obj;
}
TObject* TAssoc_array::pred_item( )
{
const TArray* arr = &_data[_rowitem];
for(;_rowitem >= 0;)
{
if ((int)_colitem >= 0 )
break;
_rowitem --;
while( _rowitem >= 0 && _data[ _rowitem ].items( ) == 0 )
_rowitem --;
if (_rowitem < 0 )
return NULL;
arr = &_data[ _rowitem ];
_colitem = arr->items( ) - 1;
}
if (_rowitem < 0 )
return NULL;
THash_object* o = (THash_object*)arr->objptr(_colitem--);
return (o == NULL || o->_obj == NULL) ? NULL : o->_obj;
}
// @doc EXTERNAL
// @mfunc Aggiunge un oggetto all'array.
// @rdesc Ritorna TRUE se esisteva gia' un elemento con la stessa chiave
bool TAssoc_array::add(
const char* key, // @parm Chiave d'ordinamento
TObject* obj, // @parm Ogetto da inserire (default=NULL)
bool force) // @parm Permette di forzare l'inserimento se esiste gia'
// un oggetto con la stessa chiave
// @parm const TObject | &obj | Indirizzo dell'oggetto da aggiungere
//
// @syntax add(const char* key, TObject* obj, bool force)
// @syntax add(const char* key, const TObject& obj, bool force)
//
// @comm Se l'oggetto da aggiungere esite gia' la chiave guarda il parametro <p force>:
// <nl>se <p force> = TRUE lo sostituisce e ritorna TRUE,
// <nl>se <p force> = FALSE non sostituisce e ritorna TRUE,
// <nl>altrimenti ritorna FALSE.
// <nl><nl>Nel caso l'oggetto da aggiungere venga passato per indirizzo
// la funzione aggiunge una copia dell'oggetto e quindi deve essere
// definita <mf TObject::dup>
{
bool isnew = FALSE;
THash_object* o = _lookup(key,isnew,TRUE);
if (!isnew)
{
if (force)
{
if (o->_obj != NULL)
delete o->_obj;
o->_obj = obj;
}
return TRUE;
}
o->_obj = obj;
return FALSE;
}
bool TAssoc_array::add(const char* key, const TObject& obj, bool force)
{
return add(key,obj.dup(),force);
}
// @doc EXTERNAL
// @mfunc Elimina un oggetto.
// @rdesc Ritorna il risultato dell'operazione
//
// @flag TRUE | Eliminazione avvenuta
// @flag FALSE | L'oggetto non e' stato trovato
bool TAssoc_array::remove(
const char* k) // @parm Chiave dell'oggetto da eliminare
// @comm Cerca nella tabella hash l'oggetto con chiave <p k> e lo elimina.
{
const TFixed_string key(k);
const word hv = key.hash() % HASH_SIZE;
TArray& arr = _data[hv];
THash_object* o = NULL;
for (int i = 0; i < arr.items(); i++)
{
THash_object* ob = (THash_object*)&arr[i];
if (ob->_key == key)
{ o = ob; break; }
if (ob->_key > key)
break;
}
if (o != NULL)
{ arr.destroy(i,TRUE); _cnt--; return TRUE; }
return FALSE;
}
// @doc EXTERNAL
// @mfunc Trova l'oggetto indicizzato
//
// @rdesc Ritorna l'oggetto cercato. Se l'oggetto non viene trovato
// ritorna un errore
TObject& TAssoc_array::find(
const char* key) // @parm Chiave dell'oggetto da trovare
// @comm Cerca l'oggetto indicizzato con chiave <p key>. Viene controllato se
// non c'e' (normalmente si usa operator[key])
{
/* Guy ruined this
bool isnew = FALSE;
THash_object* o = _lookup(key, isnew);
if (o == NULL) error_box("INTERNAL (HASH): Unref key");
if (o->_obj == NULL) return error;
else return *(o->_obj);
*/
TObject* o = objptr(key);
CHECKS(o, "Can't find hash object with key ", key);
return *o;
}
// @doc EXTERNAL
// @mfunc Ritorna l'oggetto con chiave <p key>
// @rdesc Se l'oggetto esiste ne ritorna il puntatore, altrimenti ritorna NULL
TObject* TAssoc_array::objptr(
const char* key) // @parm Chiave dell'oggetto da ritornare
{
bool isnew = FALSE;
THash_object* o = _lookup(key,isnew);
if (o != NULL)
return o->_obj;
return NULL;
}
// @doc EXTERNAL
// @mfunc Controlla l'esistenza di una chiave
//
// @rdesc Ritorna il risultato della ricerca
//
// @flag TRUE | Se la chiave esiste
// @flag FALSE | Se la chiave non esiste
bool TAssoc_array::is_key(
const char* key) // @parm Chiave da cercarne l'esistenza
{
bool isnew = FALSE;
const THash_object* o = _lookup(key, isnew);
if (o == NULL) return FALSE;
return TRUE;
}
// @doc EXTERNAL
// @mfunc Ritorna solo l'oggetto
//
// @rdesc Ritorna il puntatore all'oggetto (se diverso da NULL), altrimenti
// ritorna error object
TObject* TAssoc_array::get()
// @xref <mf TAssoc_array::get_hashobj>
{
const TArray* arr = &_data[_row];
for(;_row < HASH_SIZE;)
{
if ((int)_col < arr->items())
break;
arr = &_data[++_row];
_col = 0;
}
if (_row == HASH_SIZE)
{ _row = 0; return NULL; }
THash_object* o = (THash_object*)arr->objptr(_col++);
return (o == NULL || o->_obj == NULL) ? &error : o->_obj;
}
// @doc EXTERNAL
// @mfunc Ritorna l'oggetto e la relativa chiave
//
// @rdesc Se l'oggetto esiste ne ritorna il puntatore, altrimenti ritorna NULL
THash_object* TAssoc_array::get_hashobj()
// @comm Se l'oggetto viene trovato viene richiamata la funzione
// <mf TAssoc_array::objptr>
//
// @xref <mf TAssoc_array::get>
{
const TArray* arr = &_data[_row];
for(;_row < HASH_SIZE;)
{
if ((int)_col < arr->items())
break;
arr = &_data[++_row];
_col = 0;
}
if (_row == HASH_SIZE)
{ _row = 0; return NULL; }
return (THash_object*)arr->objptr(_col++);
}
// mette chiavi e opzionalmente valori (come stringa) nel
// TString_array passato
int TAssoc_array::get_keys(TString_array& kl, bool add_values)
{
kl.destroy(); restart();
THash_object* o = NULL;
TString tmp(80);
while (o = get_hashobj())
{
TToken_string* tt = new TToken_string(o->key());
if (add_values)
{
tmp = "";
tmp << o->obj();
tt->add(tmp);
}
kl.add(tt);
}
restart();
return kl.items();
}
HIDDEN TAssoc_array * _new_assoc_array = NULL;
// @doc INTERNAL
// @func HIDDEN void | copia_elemento | Funzione per duplicare il contenuto di un assoc_array
HIDDEN void copia_elemento(const TObject & o)
{
const THash_object & h = (const THash_object & ) o;
_new_assoc_array->add(h.key(), h.obj(), TRUE);
}
// @doc INTERNAL
// @mfunc Copia tutto l'array e ne duplica gli elementi
//
TAssoc_array & TAssoc_array::copy(
const TAssoc_array & a) // @parm Array associativo sorgente
{
/* Guy mai vista 'na roba piu' orenda: non distrugge nemmeno i contenuti attuali!
CHECK(_new_assoc_array == NULL, "Trying to duplicate an assoc array while another copy is in progress");
_new_assoc_array = this;
((TAssoc_array &)a).for_each(copia_elemento);
_new_assoc_array = NULL;
*/
destroy();
TAssoc_array& from = (TAssoc_array&)a;
from.restart();
for (THash_object* obj = from.get_hashobj(); obj; obj = from.get_hashobj())
add(obj->key(), obj->obj(), TRUE);
return * this;
}