// definizione dei record_text per trasferimento da/a file di testo #include #include #include #include // nomi delle variabili in .ini per HEADER #define HEADER "HEADER" #define NOMEFILE "NOMEFILE" #define LUNGHEZZA "LUNGHEZZA" #define RECORDSEP "RECORDSEP" #define FIELDSEP "FIELDSEP" class TFile_text; class TRecord_text : public TToken_string { // lunghezza del record (se a lunghezza fissa) int _length; // separatore di record (se necessario) TString16 _recordsep; // il separatore di campi esiste già (_separator) public: // restituisce la lunghezza del record int length() { return _length; } // restituisce il separatore di record (se esiste) const char* recordsep() { return _recordsep; } // ritorna il campo alla posizione // aggiungere la possibilità di estrarlo const char* get(int pos) const; // ritorna il campo che va dal carattere al carattere const char* get(int da, int a) const; // scrive il campo nel record alla posizione void put(const char* c, int pos = -1); // scrive il campo nel record partendo dal carattere fino al carattere // se il campo è più lungo viene troncato void put(const char* c, int da, int a); // costruttore TRecord_text(const char* recordsep = "\n", char fieldsep = '|') : _length(-1), _recordsep(recordsep) { TToken_string::TToken_string("",fieldsep); } // costruttore TRecord_text(int length, const char* recordsep = "\n") : _length(length) { TToken_string::TToken_string(length); spaces(); } // distruttore ~TRecord_text() {}; }; const char* TRecord_text::get(int pos) const { return ((TToken_string*)this)->get(pos); } const char* TRecord_text::get(int da, int a) const { CHECK(_length > 0, "Get non consentita su record non a lunghezza fissa"); return sub(da, a); } void TRecord_text::put(const char* c, int pos) { add(c, pos); } void TRecord_text::put(const char* c, int da, int a) { CHECK(_length > 0, "Put non consentita su record non a lunghezza fissa"); TString s = c; int len = da-a+1; if ( s.len() > len) s = s.cut(len); // sistemare se è più corta (la fill non va bene) TToken_string::overwrite(s, da); } // definizione dei field_text per trasferimento da/a file di testo class TField_text : public TObject { // nome del campo TString16 _name; // posizione assoluta nel record (se con separatore) int _pos; // posizione iniziale nel record (se a lunghezza fissa) int _from; // posizione finale /se a lunghezza fissa) int _to; protected: public: // costruttore TField_text() : _name(0), _pos(-1), _from(-1), _to(-1) {} // costruttore TField_text(const char* name, int pos = -1, int from = -1, int to = -1) : _name(name), _pos(pos), _from(from), _to(to) {} // ritorna il nome del campo const char* name() const { return _name; } // setta il nome del campo void set_name(const char* name) { _name = name; } // ritorna la posizione iniziale del campo int from() const { return _from; } // setta la posizione iniziale del campo void set_from(int from) { _from = from; } // ritorna la posizione finale del campo int to() const { return _to; } // setta la posizione finale del campo void set_to(int to) { _to = to; } // ritorna la posizione del campo int pos() const { return _pos; } // setta la posizione del campo void set_pos(int pos) { _pos = pos; } // cerca nel record il campo e ne ritorna il contenuto const char* read(const TRecord_text& rec) const; // cerca nel record il campo e vi scrive void write(const char* val, TRecord_text& rec); virtual ~TField_text() {}; }; const char* TField_text::read(const TRecord_text& rec) const { int pos = TField_text::pos(); if (pos = -1) { int from = TField_text::from(); int to = TField_text::to(); if (from != -1 && to != -1) return rec.get(from, to); else return ""; } else return rec.get(pos); } void TField_text::write(const char* val, TRecord_text& rec) { int pos = TField_text::pos(); if (pos != -1) { int from = TField_text::from(); int to = TField_text::to(); if (from != -1 && to != -1) rec.put(val, from, to); } else rec.put(val, pos); } // definizione dei file_text per trasferimento da/a file di testo class TFile_text: public fstream { TFilename _name; TRecord_text _current; TString _buffer; TArray _arr_exprs; TArray _arr_fields; public: // apre il file, se create = TRUE e il file non esiste lo crea int open(TFilename name, bool create = FALSE); // chiude il file int close(); // crea il file int create(TFilename name) { return open(name, TRUE); }; // cancella il file int remove(); // ritorna il record corrente TRecord_text& curr() { return _current; } // setta _current a rec void set_curr(TRecord_text& rec); // restituisce il nome del file const char* name() { return _name; } // setta il nome del file void set_name(TFilename name) { _name = name;} // si posiziona sul primo record del file int first(); // si posiziona sul prossimo record del file int next(); // aggiunge il record rec in fondo int write(TRecord_text& rec); // aggiunge il record corrente in fondo int write(); // costruttore TFile_text(const char* file_name, const char* config_name) : _name(file_name), _buffer(1024*16) { setbuf((char*)(const char*)_buffer, _buffer.size()); TConfig config(config_name); const TString_array fields; const char* recordsep = config.get(RECORDSEP,HEADER); const char* fieldsep = config.get(FIELDSEP,HEADER); int lunghezza = config.get_int(LUNGHEZZA,HEADER); if (lunghezza = 0) _current(recordsep, fieldsep); else _current(lunghezza,recordsep); const int i = config.list_paragraphs(fields); //int posheader = fields.find(HEADER); fields.remove(fields.find(HEADER),TRUE); //for ( int k = 0; k < fields.items(); k++ ) }; // distruttore ~TFile_text() { }; }; void TFile_text::set_curr(TRecord_text& rec) { //CHECK(rec,"NULL record"); _current = rec; } int TFile_text::write(TRecord_text& rec) { //CHECK(rec = NULL, "NULL record"); const char* record = (char*)&rec; if (rec.length() > 0) fstream::write(record, rec.length()); else fstream::write(record, rec.len()); const TString16 separator = rec.recordsep(); if ( separator.ok()) { int lensep = separator.len(); fstream::write(separator, lensep); } return 0; } int TFile_text::write() { //CHECK(_current, "NULL current record"); const char* record = (char*)(&_current); if (_current.length() > 0) fstream::write(record, _current.length()); else fstream::write(record, _current.len()); const TString16 separator = _current.recordsep(); if ( separator.ok()) { int lensep = separator.len(); fstream::write(separator, lensep); } return 0; } int TFile_text::open(TFilename name, bool create) { set_name(name); if (create) open(name,ios::app|ios::binary|ios::out); else open(name,ios::app|ios::binary|ios::in|ios::nocreate); if (bad()) fatal_box("Impossibile aprire %s",name); return 0; } int TFile_text::next() { //CHECK(_current, "NULL current record"); if (_current.length() > 0) fstream::read((char*)(&_current), _current.length()); else { TString16 separator = curr().recordsep(); if (separator.ok()) { TString record; int countsep = 0; do { char c = get(); record << c; if (c = separator[countsep]) countsep++; else countsep = 0; } while (countsep < separator.len() && good() && !eof()); if (countsep = separator.len()) record.cut(record.len()-separator.len()); (TToken_string&)_current = record; } } return 0; } int TFile_text::close() { _name = ""; _current = NULL; _buffer = ""; fstream::close(); return 0; }