Files correlati : Ricompilazione Demo : [ ] Commento : Aggiunte utili per gestione dizionario assoc.cpp Aggiunta possibilita' di selezionare un elemento causale di un assoc controls.cpp Corretta gestione scrollbar dei listbox diction.cpp Migliorata selezione caratteri da trimmare dalle traduzioni isam.cpp Corretto azzeramento dei memo (non azzerava il TString_array corrispondente) msksheet.cpp Resa personalizzabile la larghezza della colonna col numero di riga netsock.cpp Migliorata gestione "a capo" in protocollo soap progind.cpp Corretto posizionamento progind sovrapposte relapp.cpp Cambiato un messaggio di richiesta annullamento git-svn-id: svn://10.65.10.50/trunk@11651 c028cbd2-c16b-5b4b-a496-9718f37d4682
451 lines
11 KiB
C++
Executable File
451 lines
11 KiB
C++
Executable File
#include <stdlib.h>
|
||
#include <assoc.h>
|
||
|
||
// @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 <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;
|
||
}
|
||
|
||
THash_object* TAssoc_array::random_hash_object()
|
||
{
|
||
THash_object* o = NULL;
|
||
if (items() > 0)
|
||
{
|
||
int bucket = rand() % _bucket.size();
|
||
if (_bucket.objptr(bucket) == NULL)
|
||
bucket = _bucket.succ(bucket);
|
||
if (_bucket.objptr(bucket) == NULL)
|
||
bucket = _bucket.pred(bucket);
|
||
const TArray* arr = (const TArray*)_bucket.objptr(bucket);
|
||
if (arr != NULL)
|
||
{
|
||
const int item = rand() % arr->size();
|
||
o = (THash_object*)arr->objptr(item);
|
||
if (o != NULL)
|
||
{
|
||
_rowitem = bucket;
|
||
_colitem = item;
|
||
}
|
||
}
|
||
}
|
||
return o;
|
||
}
|
||
|
||
// @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 <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])
|
||
{
|
||
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 di cui cercare 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;
|
||
}
|
||
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TCache
|
||
// Un simpatico contenitore che pu<70> dimenticare i contenuti
|
||
// a patto che riusciate a fornire un metodo per ricrearli!
|
||
///////////////////////////////////////////////////////////
|
||
|
||
TObject* TCache::key2obj(const char* key)
|
||
{
|
||
NFCHECK("Pure key2obj function not implemented");
|
||
return new TString(key); // Place holder
|
||
}
|
||
|
||
void TCache::discarding(const THash_object* obj)
|
||
{
|
||
// Nothing to do normally
|
||
}
|
||
|
||
TObject* TCache::objptr(const TString& key)
|
||
{
|
||
const int hv = key.hash() % _data.size();
|
||
THash_object* ho = (THash_object*)_data.objptr(hv);
|
||
TObject* obj = NULL;
|
||
if (ho != NULL && ho->key() == key)
|
||
{
|
||
obj = &ho->obj();
|
||
}
|
||
else
|
||
{
|
||
obj = key2obj(key);
|
||
if (obj != NULL)
|
||
{
|
||
if (ho != NULL)
|
||
{
|
||
discarding(ho);
|
||
_data.destroy(hv);
|
||
}
|
||
ho = new THash_object(key, obj);
|
||
_data.add(ho, hv);
|
||
}
|
||
}
|
||
return obj;
|
||
}
|
||
|
||
TObject* TCache::objptr(size_t s)
|
||
{
|
||
TString16 key; key.format("%10lu", s);
|
||
return objptr(key);
|
||
}
|
||
|
||
void TCache::destroy()
|
||
{
|
||
for (int i = _data.last(); i >= 0; i--)
|
||
{
|
||
THash_object* ho = (THash_object*)_data.objptr(i);
|
||
if (ho != NULL)
|
||
{
|
||
discarding(ho);
|
||
_data.destroy(i);
|
||
}
|
||
}
|
||
}
|
||
|
||
TCache::TCache(size_t size) : _data(size > 0 ? size : HASH_SIZE)
|
||
{ }
|
||
|
||
TCache::~TCache()
|
||
{
|
||
destroy();
|
||
}
|