343 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			343 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| // definizione dei record_text per trasferimento da/a file di testo
 | |
| 
 | |
| #include <config.h>
 | |
| #include <fstream.h>
 | |
| #include <object.h>
 | |
| #include <strings.h>
 | |
| 
 | |
| //	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 <pos> 
 | |
| 	// aggiungere la possibilità di estrarlo <da> <a>
 | |
| 	const char* get(int pos) const;	
 | |
| 	                              
 | |
| 	// ritorna il campo che va dal carattere <da> al carattere <a>
 | |
| 	const char* get(int da, int a) const; 
 | |
| 	
 | |
| 	// scrive il campo <c> nel record alla posizione <pos>
 | |
| 	
 | |
| 	void put(const char* c, int pos = -1);	
 | |
| 	
 | |
| 	// scrive il campo <c> nel record partendo dal carattere <da> fino al carattere <a>
 | |
| 	// se il campo <c> è 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 <val>
 | |
| 	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;
 | |
| }
 | |
| 
 |