#include // @ccost:(INTERNAL) HASH_SIZE | 883 | Dimensione della tabella hash const int HASH_SIZE = 883; THash_object::~THash_object() { if (_obj != NULL) delete _obj; } 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

// // @rdesc Ritorna l'oggetto corrispondente alla chiave passate come parametro. // Il parametro

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

, // nel caso non venga trovato

ritorna TRUE (si tratta di un // oggetto nuovo) e viene inserito nella tabella se il parametro

// 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 Oggetto 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

: // se

= TRUE lo sostituisce e ritorna TRUE, // se

= FALSE non sostituisce e ritorna TRUE, // altrimenti ritorna FALSE. // Nel caso l'oggetto da aggiungere venga passato per indirizzo // la funzione aggiunge una copia dell'oggetto e quindi deve essere // definita { 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

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

. 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

// @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 { 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 // // // @xref { 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; }