#ifndef __RECARRAY_H #define __RECARRAY_H #ifndef __ASSOC_H #include #endif #ifndef __ISAM_H #include #endif /////////////////////////////////////////////////////////// // TRecord_Array /////////////////////////////////////////////////////////// // @doc EXTERNAL // @class TRecord_array | Classe per la gestione di un array di record // // @base public | TArray class TRecord_array : public TObject // @author:(INTERNAL) Guido // @access:(INTERNAL) Private Member { // @cmember:(INTERNAL) Numero logico del file principale int _file; // @cmember:(INTERNAL) Array di records TArray _data; // @cmember:(INTERNAL) Offset iniziale del record array int _offset; // @cmember:(INTERNAL) Nome del campo col numero di riga TString16 _num; // @access Protected Member protected: // @cmember Ritorna il numero riga del record

int rec2row(const TRectype& r) const; // @cmember Ritorna il nome del campo con numero di riga const TString& num_field() const { return _num; } // @cmember Elimina il record di posizione

(ritorna il risultato dell'operazione) int remove_from(int i) const; // @cmember Confronta i campi della chiave 1 scartando l'ultimo bool good(const TRectype& rec) const; // @cmember Duplica un record array virtual TObject* dup() const { return new TRecord_array(*this);} // @access Public Member public: // @cmember Ritorna il record che fa da chiave per tutti gli altri const TRectype& key() const; // @cmember Ritorna il numero di righe presenti int rows() const { return _data.items()-1; } // @cmember Ritorna la riga successiva non vuota a partire da

int succ_row(int r) const { return _data.succ(r - _offset) + _offset; } // @cmember Ritorna la riga precedente non vuota a partire da

int pred_row(int r) const { return _data.pred(r - _offset) + _offset; }; // @cmember Ritorna l'ultma riga non vuota int last_row() const { return _data.last() + _offset; } // @cmember Ritorna la prima riga non vuota int first_row() const { return succ_row(0); } // @cmember Ritorna il record

-esimo const TRectype& row(int r) const { CHECKD(r > _offset, "Bad record number ", r); return (const TRectype&)operator[](r - _offset); } // @cmember Controlla se esiste la riga

(TRUE se esiste) bool exist(int r) const; // @cmember Ritorna la riga

-esima; se tale riga non esiste e se

assume il valore TRUE la riga viene creata TRectype& row(int r, bool create); // @cmember Ritorna la riga

-esima se tale riga esiste const TRectype& operator [](int r) const { return (const TRectype &) ((TRecord_array *) this)->row(r, FALSE);} // @cmember Ritorna la riga

-esima se tale riga esiste TRectype& operator [](int r) { return row(r, FALSE);} // @cmember Inserisce una riga alla posizione indicata nel record, sposta gli altri elementi se la posizione era gia' occupata virtual int insert_row(TRectype* r); // @cmember Inserisce una riga alla posizione indicata nel record, sposta gli altri elementi se la posizione era gia' occupata int insert_row(const TRectype& r) { return insert_row((TRectype*)r.dup()); } // @cmember Aggiunge/sostituisce una riga alla posizione indicata nel record virtual int add_row(TRectype* r); // @cmember Aggiunge/sostituisce una riga alla posizione indicata nel record int add_row(const TRectype& r) { return add_row((TRectype*)r.dup()); } // @cmember Compatta le righe piene virtual void pack() ; // @cmember Cancella una riga identificata da

virtual bool destroy_row(int n, bool pack = FALSE); // @cmember Cancella una riga identificata da

virtual bool destroy_row(const TRectype& r, bool pack = FALSE) { return destroy_row(rec2row(r), pack); } // @cmember Cancella tutte le righe void destroy_rows(); // @cmember Copia un record array TRecord_array& copy(const TRecord_array& a); // @cmember Operatore di assegnamento di un record array TRecord_array& operator= (const TRecord_array& a) { return copy(a); } // @cmember Ritorna il numero logico del file principale int logic_num() const { return _file; } // @cmember Cambia l'intera chiave (solo se vuoto) void set_key(TRectype* r); // @cmember Rinumera il campo chiave in seguito a reinsert bool renum_key(const char* field, const TString& num); // @cmember Rinumera il campo chiave in seguito a reinsert bool renum_key(const char* field, long num); // @cmember Ordina il Record Array secondo il criterio definito in void sort(COMPARE_FUNCTION sort_func); // @cmember Legge tutto l'array dal file virtual int read(const TRectype& r); // @cmember Legge tutto l'array dal file virtual int read(TRectype* r); // @cmember Aggiorna il file (se

== TRUE allora viene aggiornato il record se esisteva) virtual int write(bool re = FALSE) const; // @cmember Aggiorna il record sul file virtual int rewrite() const { return write(TRUE); } // @cmember Cancella tutti i record dal file virtual int remove() const; // @cmember Costruttore TRecord_array(const TRectype& r, const char* numfield, int first = 1); // @cmember Costruttore TRecord_array(int logicnum, const char* numfield, int first = 1); // @cmember Costruttore TRecord_array(const TRecord_array& a); // @cmember Distruttore virtual ~TRecord_array(); }; /////////////////////////////////////////////////////////// // TFile_cache /////////////////////////////////////////////////////////// class TFile_cache : public TObject { static unsigned long _hits, _misses; TToken_string _code; TString16 _filecode; TLocalisamfile* _file; int _key; long _last_firm; int _error; long _last_read, _limit; bool _test_changes; unsigned long _last_change_test; protected: TAssoc_array _cache; protected: void init_file(TLocalisamfile* f=NULL); void test_firm(); void kill_file(); const TObject& query(const char* chiave); virtual TObject* rec2obj(const TRectype& rec) const pure; TLocalisamfile & file(); public: virtual bool discard(const char* victim); int io_result(); const int key_number() const { return _key; } bool already_loaded(const char* code) const; bool already_loaded(long code) const; long items() const { return _cache.items(); } long fill(); void destroy(); virtual void flush(); void set_items_limit(long l) { _limit = l; } void test_file_changes(bool t = TRUE) { _test_changes = t; } void notify_change(); static void stats(unsigned long& hits, unsigned long& misses); TFile_cache(TLocalisamfile *f,int key = 1); TFile_cache(int num, int key = 1); TFile_cache(const char* table, int key = 1); virtual ~TFile_cache(); }; class TDecoder : public TFile_cache { TString16 _outf; protected: virtual TObject* rec2obj(const TRectype& rec) const; public: const TString& decode(const char* code); const TString& decode(long code); TDecoder(int num, const char* field, int key = 1); TDecoder(const char* table, const char* field = "S0", int key = 1); virtual ~TDecoder() { } }; class TRecord_cache : public TFile_cache { protected: virtual TObject* rec2obj(const TRectype& rec) const; // @cmember Elimina la chiave dalla cache public: // @cmember ritorna il record con una determinata chiave virtual const TRectype& get(const char* chiave); // @cmember ritorna il campo (chiama get(chiave)) const TString& get(const char* chiave, const char* campo); // @cmember ritorna il record con una determinata chiave numerica const TRectype& get(long chiave); const TString& get(long chiave, const char* campo) ; TRecord_cache(int num, int key = 1); TRecord_cache(TLocalisamfile *f, int key = 1); TRecord_cache(const char* table, int key = 1); virtual ~TRecord_cache() { } }; class TDB_cache : public TArray { public: TRecord_cache& rec_cache(int file); bool discard(int file, const char* key); bool discard(const char *table, const char* key); bool discard(const TRectype& rec); void flush(int file) { rec_cache(file).flush(); } const TRectype& get(int file, const char* key) { return rec_cache(file).get(key); } const TRectype& get(int file, long key) { return rec_cache(file).get(key); } const TRectype& get(const char* table, const char* key); const TString& get(int file, const char* key, const char * campo) { return get(file, key).get(campo); } const TString& get(int file, long key, const char * campo) { return get(file, key).get(campo); } const TString& get(const char* table, const char* key, const char * campo) { return get(table, key).get(campo); } void test_file_changes(int file, bool t = TRUE) { rec_cache(file).test_file_changes(t); } }; TDB_cache& cache(); TRecord_cache& rec_cache(int file); #endif