campo-sirio/include/filetext.cpp
guy 52fd0bd544 anafis.h Tolto campo inesistente TIPOA
anagiu.h     Tolto campo inesistente TIPOA
form.cpp     Modificato costruttore delle subsection per non dare warning
msksheet.cpp Tolta riga vuota
utility.cpp  Tolto errore fatale nella funzione copyfile
filetext.* Aggiunta gestione file di testo della Paola


git-svn-id: svn://10.65.10.50/trunk@4974 c028cbd2-c16b-5b4b-a496-9718f37d4682
1997-07-30 12:36:24 +00:00

594 lines
19 KiB
C++
Executable File
Raw Blame History

#include <filetext.h>
#include <utility.h>
//////////////////////////////////////// TTracciato_Campo ////////////////////////////////////////
TTracciato_campo::TTracciato_campo(int position, int length, int decimal, const char align, const char filler)
:_position(position), _length(length), _decimal(decimal), _align(align), _filler(filler) {}
TObject* TTracciato_campo::dup() const
{
TTracciato_campo* t = new TTracciato_campo(*this);
return t;
}
const TTracciato_campo& TTracciato_campo::operator =(const TTracciato_campo& tc)
{
copy(tc);
return *this;
}
void TTracciato_campo::copy(const TTracciato_campo& tc)
{
set_name(tc._name);
set_type(tc._type);
set_field(tc._field);
set_position(tc._position);
set_length(tc._length);
set_decimal(tc._decimal);
set_align(tc._align);
set_filler(tc._filler);
set_picture(tc._picture);
set_message(tc._message);
}
//////////////////////////////////////// TTracciato_record ////////////////////////////////////////
TObject* TTracciato_record::dup() const
{
TTracciato_record* t = new TTracciato_record(*this);
return t;
}
TTracciato_record::TTracciato_record(const TTracciato_record& tr)
{
set_type(tr.type());
_tracciati_campo = tr._tracciati_campo;
}
void TTracciato_record::add(const TTracciato_campo& tc, int pos)
{
_tracciati_campo.add(tc,pos);
}
int TTracciato_record::get_pos(const char* name) const
{
for (int i = _tracciati_campo.last(); i >= 0; i = _tracciati_campo.pred(i))
{
const TTracciato_campo& tc = get(i);
if (tc.name() == name)
break;
}
return i;
}
TTracciato_campo& TTracciato_record::get(int n)
{
if (TTracciato_record::ptr(n) == NULL)//se non esiste lo creo
{
TTracciato_campo* t = new TTracciato_campo();
TTracciato_record::add(*t, n);
}
return (TTracciato_campo&)_tracciati_campo[n];
}
//////////////////////////////////////// TRecord_text ////////////////////////////////////////
const TString& TRecord_text::row(int pos) const
{
return _array.row(pos);
}
void TRecord_text::add(const TString& c, int pos)
{
_array.add(c, pos);
}
//////////////////////////////////////// TFile_text ////////////////////////////////////////
TTracciato_record& TFile_text::t_rec(const char* type)
{
return (TTracciato_record&)_tracciati_record[type];
}
void TFile_text::set_gen_parm(TConfig& config, const TString& section)
{
_decsep = config.get_char("DECSEP",section);
_recordsize = config.get_int("RECORDSIZE",section); // solo se a lung. fissa
_fieldsep = config.get_char("FIELDSEP",section); // solo se a lung. variabile
_recordsep = config.get("RECORDSEP",section); // solo se a lung. variabile
if (_recordsize <= 0 && (_recordsep.empty())) // separatore di record standard
_recordsep = "\r\n";
_typefield = config.get_int("TYPEFIELD",section); // Numero del campo tipo (puo' essere -1)
_fixedlen = _fieldsep <= ' ' && _recordsep.blank();
_typepos = -1;
_typelen = -1;
}
void TFile_text::set_type_parm(TConfig& config, TString& section)
{
TString lavoro = section;
lavoro.ltrim(4);//elimino la parola 'TYPE' e gli spazi vuoti
lavoro.trim();//per avere solo il nome del tipo predefinito
TTracciato_campo tipo;
tipo.set_type(lavoro);
tipo.set_length(config.get_int("LENGTH", section));
tipo.set_decimal(config.get_int("DECIMAL", section));
tipo.set_align(config.get_char("ALIGN", section));
TString s = config.get("FILLER", section);
tipo.set_filler(s[1]);
tipo.set_picture(config.get("PICTURE", section));
_tipi.add(lavoro, tipo);// aggiungo il tracciato campo all'assoc_array dei tipi predefiniti
}
void TFile_text::set_rec_parm(TConfig& config, const char* section)
{
TString comodo = section;
comodo.ltrim(6);//elimino la parola 'RECORD' o 'HEADER' o 'FOOTER' e gli spazi vuoti
comodo.trim();//per avere solo il nome del tipo del record
TTracciato_record tr(comodo);//istanzio un tracciato_record del tipo corrente
//setto tutti i dati relatvi ai tipi predefini nei tracciati campo per i diversi campi del record
config.set_paragraph(section);
TString lavoro;
TString_array variables;
const int numvar = config.list_variables(variables, TRUE);//scarico tutte le variabili della sezione
TBit_array indici(numvar);
indici.reset();
for (int j = 0; j < numvar; j++)//scandisco tutte le variabili della sezione
{
const TString key = variables.row(j).get(0);//estraggo nome
const TString& obj = variables.row(j).get(1);//estraggo valore
lavoro = key.left(3);
int pos = key.find('(');
int n = atoi(key.mid(pos+1, -1));//estraggo l'indice
if (!indici[n])
{
if (config.exist("TYPE", n))
{
TString tipo = config.get("TYPE", section, n);
if (!tipo.empty())
{
TTracciato_campo& tc = (TTracciato_campo&)_tipi[tipo];
tr.add(tc, n);
}
}
indici.set(n);
}
TTracciato_campo& tc = tr.get(n);//prendo il tracciato campo con indice <n>
if (lavoro == "NAM")
{
tc.set_name(obj);
continue;
}
if (lavoro == "FIE")
{
TFieldref field;
field = obj;
tc.set_field(field);
continue;
}
if (lavoro == "POS")
{
int pos = atoi(obj);
tc.set_position(pos);
if (_fixedlen && _typepos < 0 && n == _typefield)
_typepos = pos;
continue;
}
if (lavoro == "LEN")
{
int len = atoi(obj);
if (tc.length() <= 0 && len >= 0 && tc.length() != len)
tc.set_length(len);
if (_fixedlen && _typelen < 0 && n == _typefield)
_typelen = len;
continue;
}
if (lavoro == "DEC")
{
int dec = atoi(obj);
if (tc.decimal() <= 0 && dec >= 0 && tc.decimal() != dec)
tc.set_decimal(dec);
continue;
}
if (lavoro == "ALI")
{
bool condition = tc.align() != obj[0];
if (condition)
tc.set_align(obj[0]);
continue;
}
if (lavoro == "FIL")
{
if (!obj.blank())
{
bool condition = tc.filler() != obj[1];
if (condition)
tc.set_filler(obj[0]);
}
continue;
}
if (lavoro == "PIC")
{
if (tc.picture().blank() && (!obj.blank()))
tc.set_picture(obj);
continue;
}
if (lavoro == "MES")
{
tc.set_message(obj);
continue;
}
}
//aggiungo il tracciato record all'assoc_array dei tracciati record
_tracciati_record.add(comodo, tr);
}
TFile_text::TFile_text(const char* file_name, const char* config_name)
: _name(file_name)
{
_read_file = NULL;
_write_file = NULL;
TConfig config(config_name);
TString_array paragraphs;
config.list_paragraphs(paragraphs);//scarico la lista dei paragrafi
int items = paragraphs.items();//quanti paragrafi ho scaricato
TString section, sec;
for (int i = 0; i < items; i++)//scandisco tutti i paragrafi
{
section = paragraphs.row(i) ;//prendo il nome del paragrafo
sec = section.left(3);//prendo le prime tre lettere del nome
if (sec == "MAI") //inizializzo i parametri generali del file
{
set_gen_parm(config,section);
continue;
}
if (sec == "TYP")
{
set_type_parm(config, section);
continue;
}
if ((sec == "REC")||(sec == "HEA")||(sec == "FOO"))
{
set_rec_parm(config, section);
continue;
}
}
}
//Scrive su file il record_text (valido anche per header e footer)
int TFile_text::write(TRecord_text& rec)
{
TString buffer;
TString campo;
const TString& type = rec.type();
TTracciato_record& tr = t_rec(type);
TArray& a_tc = tr.tracciati_campo();
int items = rec.items();
if (_fixedlen)
{
for (int i = 0; i < items; i++)
{
campo = rec.row(i);
TTracciato_campo& tc = tr.get(i);
//buffer.insert(campo, tc.position());
buffer << campo;
campo.cut(0);
}
CHECK(_write_file, "Impossibile scrivere su un file chiuso.");
*_write_file << buffer;
if (!ok_w()) return 1;
buffer.cut(0);
}
else
{
TToken_string ts(buffer, _fieldsep);
for (int i = 0; i < items; i++)
{
campo = rec.row(i);
ts.add(campo, i);
campo.cut(0);
}
CHECK(_write_file, "Impossibile scrivere su un file chiuso.");
*_write_file << ts;
*_write_file << _recordsep;
if (!ok_w()) return 1;
ts.cut(0);
}
return 0;
}
//Carica tutti i dati nel tracciato record (valido anche per header e footer) nel record_text
void TFile_text::autoload(TRecord_text& rec, TCursor& cur , const TString* tipo)
{
TString campo;
TRelation& rel = *cur.relation();
const TString& type = rec.type();
if (tipo == NULL) tipo = &type;
TTracciato_record& tr = t_rec(*tipo);
TArray& a_tc = tr.tracciati_campo();
int items = a_tc.items();
for (int i = 0; i < items; i++)
{
TTracciato_campo& tc = tr.get(i);
const TFieldref& field = tc.field();
if (!field.name().empty())
campo = field.read(rel);
TString message = tc.message();
if (!message.empty())
{
TToken_string msg (message, ',');
if (!msg.blank())
validate(cur, rec, msg, campo);
}
const TRectype& rel_rec = rel.curr(field.file());
TFieldtypes tipo_campo = rel_rec.type(field.name());
/* Guy was here
if (tipo_campo != _datefld && tipo_campo != _realfld && tipo_campo != _intfld && tipo_campo != _longfld && message != "_IMPORTO,!TOT")
campo = format_field(tc, campo);//formatta il campo secondo le specifiche del tracciato
else
{
if (tipo_campo == _datefld)
{
TDate data(campo);
TString s;
format_date(data, tc.picture(), s);//formatta la data secondo le specifiche del tracciato
campo = s ;
}
if (tipo_campo == _realfld || tipo_campo == _intfld || tipo_campo == _longfld)
{
real numero(campo);
campo = numero.string(tc.picture());//formatta il numero secondo le specifiche del tracciato
int length = tc.length();
if (tc.align() == 'R')
campo.right_just(length, tc.filler());
else
campo.left_just(length, tc.filler());
int j = campo.replace('.', _decsep);
CHECK(j >= 0 && j <= 1 , "Impossibile scrivere pi<70> separatori decimali.");
}
}
*/
switch(tipo_campo)
{
case _datefld:
{
TDate data(campo);
format_date(data, tc.picture(), campo);//formatta la data secondo le specifiche del tracciato
}
break;
case _realfld:
case _intfld:
case _longfld:
{
real numero(campo);
campo = numero.string(tc.picture());//formatta il numero secondo le specifiche del tracciato
int length = tc.length();
if (tc.align() == 'R')
campo.right_just(length, tc.filler());
else
campo.left_just(length, tc.filler());
int j = campo.replace('.', _decsep);
CHECK(j >= 0 && j <= 1 , "Impossibile scrivere pi<70> separatori decimali.");
}
break;
default:
campo = format_field(tc, campo);//formatta il campo secondo le specifiche del tracciato
break;
}
rec.add(campo, i);
campo.cut(0);
}
}
//Legge da file il record text
int TFile_text::read(TRecord_text& rec)
{
CHECK(_read_file, "Impossibile leggere da un file chiuso.");
TString buffer(_recordsize), lavoro;
if (_fixedlen)
{
buffer.cut(0);
_read_file->read(buffer.get_buffer(),buffer.size());
if (!ok_r()) return 1; //non ritorna errore se fine file ed il record e' completo!
const TString tipo = buffer.mid(_typepos, _typelen);
rec.set_type(tipo);//istanzio il tipo del record text
TTracciato_record& tr = t_rec(tipo);
//ora che ho il tracciato record devo scandire i tracciati campo e caricare il record text
TArray& a_tc = tr.tracciati_campo();
int items = a_tc.items();
for (int i = 0; i < items; i++)
{
TTracciato_campo& tc = tr.get(i);
int pos = tc.position();
int len = tc.length();
lavoro = buffer.mid(pos, len);
rec.add(lavoro, i);
}
}
else
{
//legge carattere per carattere fino a quando non si trova il separatore di record
char c = _read_file->get();
if (c == EOF)
return EOF;
while (c != _recordsep[0])
{
buffer << c;
c = _read_file->get();
if (!ok_r())
return EOF; //non ritorna errore se fine file ed il record e' completo!
}
// prendo il resto del separatore
int l = _recordsep.len()-1;
for (int j = 0; j < l;c = _read_file-> get (), j++);
TToken_string ts(buffer, _fieldsep);
const char* tipo = _typefield >= 0 ? ts.get(_typefield) : "";
TTracciato_record& tr = t_rec(tipo);
rec.set_type(tipo);//istanzio il tipo del record text
TArray& a_tc = tr.tracciati_campo();
int items = a_tc.items();
ts.restart();
for (int i = 0; i < items; i++)
{
lavoro = ts.get();
rec.add(lavoro, i);
}
}
return 0;
}
//Carico la relazione con i dati del record text
int TFile_text::autosave(TRelation& rel, const TRecord_text& rec)
{
const TString& type = rec.type();//prendo il tracciato record del tipo del record_text
TTracciato_record& tr = t_rec(type);
TArray& a_tc = tr.tracciati_campo();
int items = a_tc.items();
for (int i = 0; i < items; i++)
{
const TTracciato_campo& tc = tr.get(i);
const TFieldref& field = tc.field();
if (field.name().not_empty())
{
const TString& valore = rec.row(i);
field.write(valore, rel);//faccio una write sulla relazione del fieldref
}
}
int err = rel.write();
if (err == _isdupkey || err ==_isreinsert)
err = rel.rewrite();
return err;
}
//Scarica dal record_text il campo alla posizione <ncampo>
const TString& TFile_text::get_field(const TRecord_text& rec, int ncampo)
{
/* Guy was here
const TString& type = rec.type();//prendo il tracciato record del tipo del record_text
TTracciato_record tr(type);
TTracciato_campo& tc = tr.get(ncampo);
*/
return rec.row(ncampo);
}
//Scarica dal record_text il campo <name>
const TString& TFile_text::get_field(const TRecord_text& rec, const char* name)
{
TTracciato_record& tr = t_rec(rec.type());
int ncampo = tr.get_pos(name);
CHECKS(ncampo >= 0, "Campo inesistente ", name);
return rec.row(ncampo);
}
//Carica nel record_text il campo alla posizione <ncampo> con il valore <val> gi<67> formattato
void TFile_text::add_field(TRecord_text& rec, const int ncampo, const char* val)
{
TTracciato_record& tr = t_rec(rec.type());
TTracciato_campo& tc = tr.get(ncampo);
TString valore = val;
valore = format_field(tc, valore);
rec.add(valore, ncampo);
}
//Formatta la data in base al tracciato
void TFile_text::format_date(const TDate& data, const TString& form, TString& data_str)
{
int i = 1, cnt = 0;
char x = form[0];
do
{
char k = x;
if (k != 'a' && k != 'm'&& k != 'g')
data_str << k;
else
cnt++;
x = form[i];
i++;
if (k != x)
switch (k)
{
case 'g': CHECKD(cnt >= 1 && cnt <= 4, "Formato per giorno non valido ", cnt);
if (cnt == 1) data_str << data.day();
if (cnt == 2) data_str << format("%02d", data.day());
if (cnt == 3) {TString s = itow(data.wday());s.cut(3);data_str << s;}
if (cnt == 4) data_str << itow(data.wday());
cnt = 0;
break;
case 'm': CHECKD(cnt >= 1 && cnt <= 4, "Formato per mese non valido ", cnt);
if (cnt == 1) data_str << data.month();
if (cnt == 2) data_str << format("%02d", data.month());
if (cnt == 3) {TString s = itom(data.month());s.cut(3);data_str << s;}
if (cnt == 4) data_str << itom(data.month());
cnt = 0;
break;
case 'a': CHECKD(cnt >= 2 && cnt <= 4, "Formato per anno non valido ", cnt);
if (cnt == 2) {TString s;s << data.year();s.ltrim(2);data_str << s;}
if (cnt == 3) {TString s;s << data.year();s.ltrim(1);data_str << s;}
if (cnt == 4) data_str << data.year();
cnt = 0;
break;
}
}
while (i <= form.len());
}
//Formatta la stringa in base al tracciato
TString& TFile_text::format_field(TTracciato_campo& tc, TString& campo)
{
int pos = tc.position();
int length = tc.length();
if (!tc.picture().blank())
campo.picture(tc.picture(), campo);
if (length > campo.len())
{
if (tc.align() == 'R')
campo.right_just(length, tc.filler());
else
campo.left_just(length, tc.filler());
}
else
campo.cut(length);
return campo;
}
int TFile_text::open(char mode)
{
if (mode == 'r')//apertura in lettura
{
if (_read_file)
delete _read_file;
_read_file = new ifstream(_name, ios::binary);
if (!ok_r())
error_box("Impossibile aprire il file %s in lettura", (const char *)_name);
}
if (mode == 'w')//apertura in scrittura
{
if (_write_file)
delete _write_file;
_write_file = new ofstream(_name, ios::binary|ios::app);
}
return 0;
}
int TFile_text::open(const char* name, char mode)
{
set_name(name);
return open(mode);
}
int TFile_text::close()
{
_name = "";
_current = NULL;
_tipi.destroy();
_tracciati_record.destroy();
if (_read_file) _read_file->close();
if (_write_file) _write_file->close();
return 0;
}