campo-sirio/include/assoc.cpp
guy 369bde9243 Eliminate dipendenze dal sistema operativo tramite os_dep.h
git-svn-id: svn://10.65.10.50/trunk@6251 c028cbd2-c16b-5b4b-a496-9718f37d4682
1998-02-24 10:37:28 +00:00

357 lines
9.0 KiB
C++
Executable File

#include <assoc.h>
// @ccost:(INTERNAL) HASH_SIZE | 10883 | Dimensione della tabella hash
const int HASH_SIZE = 10883;
TArray& TAssoc_array::bucket(int index)
{
TArray* arr = (TArray*)_bucket.objptr(index);
if (arr == NULL)
{
arr = new TArray;
_bucket.add(arr, index);
}
return *arr;
}
// @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 assegnato 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 = bucket(hv);
THash_object* o = NULL;
isnew = FALSE;
for (int i = 0; i < arr.items(); i++)
{
THash_object* ob = (THash_object*)arr.objptr(i);
if (ob->_key == key)
{ o = ob; break; }
if (ob->_key > key)
break;
}
if (o == NULL)
{
if (insert)
{
o = new THash_object(key);
arr.insert(o,i);
_cnt++;
}
isnew = TRUE;
}
return o;
}
void TAssoc_array::destroy()
{
_bucket.destroy();
_cnt = _row = _col = 0;
_rowitem = _colitem = 0;
}
TObject* TAssoc_array::first_item()
{
_rowitem = _colitem = 0;
return succ_item();
}
TObject* TAssoc_array::last_item()
{
_rowitem = _bucket.last();
if( _rowitem < 0 )
return NULL;
_colitem = bucket(_rowitem).items() - 1;
return pred_item( );
}
TObject* TAssoc_array::succ_item()
{
const TArray* arr = (const TArray*)_bucket.objptr(_rowitem);
while (_rowitem < HASH_SIZE)
{
if (arr && (int)_colitem < arr->items())
break;
_rowitem = _bucket.succ(_rowitem);
if (_rowitem < HASH_SIZE)
{
arr = (TArray*)_bucket.objptr(_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 = (const TArray*)_bucket.objptr(_rowitem);
while (_rowitem >= 0)
{
if (arr && (int)_colitem >= 0)
break;
_rowitem = _bucket.pred(_rowitem);
if (_rowitem >= 0)
{
arr = (TArray*)_bucket.objptr(_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)
{
// Non inserire l'Hash_object se non lo trovi (ci pensa la add sotto)
bool isnew = FALSE;
THash_object* o = _lookup(key,isnew,FALSE);
if (!isnew && !force)
return TRUE;
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 = bucket(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) const // @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) const // @parm Chiave dell'oggetto da ritornare
{
bool isnew = FALSE;
THash_object* o = ((TAssoc_array*)this)->_lookup(key,isnew);
return o ? o->_obj : 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) const // @parm Chiave da cercarne l'esistenza
{
bool isnew = FALSE;
THash_object* o = ((TAssoc_array *)this)->_lookup(key,isnew);
return o != NULL;
}
// @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 = (const TArray*)_bucket.objptr(_row);
while(_row < HASH_SIZE)
{
if (arr && (int)_col < arr->items())
break;
_row = _bucket.succ(_row);
arr = (const TArray*)_bucket.objptr(_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_object : 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 = (const TArray*)_bucket.objptr(_row);
while(_row < HASH_SIZE)
{
if (arr && (int)_col < arr->items())
break;
_row = _bucket.succ(_row);
arr = (const TArray*)_bucket.objptr(_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();
}
// @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
{
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;
}