#ifndef __ASSOC_H
#define __ASSOC_H

#ifndef __STRINGS_H
#include <strings.h>
#endif

// @doc INTERNAL

// @class THash_object | Classe per la definizione degli elementi di una tabella hash.
//
// @base public | TObject
class THash_object : public TObject

// @author:(INTERNAL) Guido

{
  // @cfriend TAssoc_array
  friend class TAssoc_array;  
  
  // @access:(INTERNAL) Private Member

  // @cmember:(INTERNAL) Chiave d'ordinamento
  TString  _key;
  // @cmember:(INTERNAL) Oggetto della tabella da ordinare
  TObject* _obj;

  // @access Public Member
public:
  
  // @cmember Ritorna la chiave di ordinamento
  const TString& key() const
  { return _key; }
  // @cmember Ritorna l'oggetto
  TObject& obj() const
  { return *_obj; }

  // @cmember Costruttore (inizializza la chiave ed opzionalmente l'oggetto)
  THash_object(const char* k, TObject* o = NULL) : _key(k), _obj(o)
  {}
  // @cmember Distruttore
  ~THash_object()
  { if (_obj != NULL) delete _obj; }
}; 


// @doc EXTERNAL

// @class TAssoc_array | Tabella hash di oggetti generici
//
// @base public |TObject
class TAssoc_array : public TContainer

// @author:(INTERNAL) Guido

//@access:(INTERNAL) Private Member
{
  // @ccost:(INTERNAL) HASH_SIZE | 113 | Dimensione della tabella hash
  enum { HASH_SIZE = 113 };
  // @cmember:(INTERNAL) Numero di oggetti contenuti nella tabella
  word _cnt;
  // @cmember:(INTERNAL) Numero di righe della tabella hash
  word _row;
  // @cmember:(INTERNAL) Numero di colonne della tabella hash
  word _col;
  // @cmember:(INTERNAL) Numero di righe della tabella hash per i metodi _item
  int _rowitem;
  // @cmember:(INTERNAL) Numero di colonne della tabella hash per i metodi _item
  int _colitem;
  // @cmember:(INTERNAL) Array contenente i dati veri e propri
  TArray _data[HASH_SIZE];
  
  // @access Protected member
protected:

  // @cmember Cerca l'oggetto con chiave k
  THash_object* _lookup(const char* k, bool& isnew, bool insert = FALSE);  
  // @cmember Copia tutto l'array associativo e ne duplica gli elementi
  TAssoc_array & copy(const TAssoc_array & a);

  // @access Public Member
public:

  // @cmember Ritorna il numero di elementi presenti
  int items() const
  { return _cnt; }
  
  // @cmember Ritorna un puntatore al primo oggetto
  virtual TObject* first_item( );
  // @cmember Ritorna un puntatore all'ultimo oggetto
  virtual TObject* last_item( );
  // @cmember Ritorna un puntatore all'oggetto successivo al quello corrente
  virtual TObject* succ_item( );
  // @cmember Ritorna unpuntatore all'oggetto oggetto che precede quello corrente
  virtual TObject* pred_item( );
  // @cmember Ritorna il numero di elementi presenti come long  
  long objects( )
  { return _cnt; }
  
  // @cmember Cancella tutti gli elementi
  virtual void destroy();

  // @cmember Aggiunge un oggetto. Se era gia' presente guarda il parametro force
  bool add(const char* key, TObject* obj = NULL, bool force = FALSE);

  // @cmember Aggiunge una copia dell'oggetto
  bool add(const char* key, const TObject& obj, bool force = FALSE);

  // @cmember Elimina un oggetto
  bool remove(const char* key);

  // @cmember Trova l'oggetto indicizzato
  TObject& find(const char* key);

  // @cmember Ritorna l'oggetto con chiave key
  TObject* objptr(const char* key) const ;

  // @cmember Controlla l'esistenza di una chiave
  bool is_key(const char* key) const ;

  // @cmember Ritorna l'indice del oggetto con chiave key (piu' intuitivo di <mf TAssoc_array::find>)
  TObject& operator[] (const char* key)
  { return find(key); }
  
  // iterazione come TToken_string
  // si puo' adoperare get() e get_hashobj() intercambiabilmente ma
  // non sono indipendenti (entrambe avanzano gli stessi contatori)

  // @cmember Ritorna solo l'oggetto
  TObject* get();
  // @cmember Ritorna l'oggetto e la relativa chiave
  THash_object* get_hashobj();
  // @cmember Azzera il numero di riga e colonna corrente della tabella hash
  void restart()
  { _row = 0; _col = 0; }
                                                        
  // @cmember Mette chiavi e opzionalmente valori (come stringa) nel <c TString_array> passato  
  int get_keys(TString_array& kl, bool add_values = FALSE);
  // @cmember Operatore di assegnamento tra array associativi
  TAssoc_array & operator= (const TAssoc_array & a)
  { return copy(a); }
  
  // @cmember Costruttore
  TAssoc_array()  : _cnt(0), _row(0), _col(0)
  {}
  // @cmember Costruttore. Copia tutto l'array associativo e ne duplica gli elementi
  TAssoc_array(const TAssoc_array & a) : _cnt(0), _row(0), _col(0)
  { copy(a); }
  // @cmember Distruttore
  virtual ~TAssoc_array() 
  { destroy(); }  
};

#endif
