git-svn-id: svn://10.65.10.50/branches/R_10_00@23005 c028cbd2-c16b-5b4b-a496-9718f37d4682
1076 lines
31 KiB
C++
Executable File
1076 lines
31 KiB
C++
Executable File
#include <stdlib.h>
|
|
|
|
#include <filetext.h>
|
|
#include <tabutil.h>
|
|
|
|
|
|
// Ritorna TRUE se la stringa e' piena di zero
|
|
static bool zero_only(const TString& v)
|
|
{
|
|
int i;
|
|
for (i = v.len()-1; i>=0 && v[i]=='0'; i--);
|
|
return i<0;
|
|
}
|
|
|
|
//////////////////////////////////////// TTracciato_Campo ////////////////////////////////////////
|
|
TTracciato_campo::TTracciato_campo(int position, int length, int decimal, const char align, const char filler)
|
|
: _datatype('S'), _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_datatype(tc._datatype);
|
|
set_type(tc._type);
|
|
set_field(tc._field);
|
|
set_ftype(tc._ftype);
|
|
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);
|
|
}
|
|
|
|
// determina la lunghezza del campo da scrivere su file isam
|
|
const int TFile_text::flength(const TTracciato_campo &tc , const TRectype & record ) const
|
|
{
|
|
if (tc.ftype().empty())
|
|
return tc.field().len(record); // il default è la lunghezza del campo isam
|
|
else
|
|
return ((TTracciato_campo &)_tipi[tc.ftype()]).length(); // altrimenti è quella definita nel FTYPE
|
|
}
|
|
const int TFile_text::fdecimal(const TTracciato_campo &tc ) const
|
|
{
|
|
if (tc.ftype().empty())
|
|
return tc.decimal();
|
|
else
|
|
return ((TTracciato_campo &)_tipi[tc.ftype()]).decimal();
|
|
}
|
|
const char TFile_text::falign(const TTracciato_campo &tc ) const
|
|
{
|
|
if (tc.ftype().empty())
|
|
return tc.align();
|
|
else
|
|
return ((TTracciato_campo &)_tipi[tc.ftype()]).align();
|
|
}
|
|
const char TFile_text::ffiller(const TTracciato_campo &tc ) const
|
|
{
|
|
if (tc.ftype().empty())
|
|
return tc.filler();
|
|
else
|
|
return ((TTracciato_campo &)_tipi[tc.ftype()]).filler();
|
|
}
|
|
const TString& TFile_text::fpicture(const TTracciato_campo &tc ) const
|
|
{
|
|
if (tc.ftype().empty())
|
|
return tc.picture();
|
|
else
|
|
return ((TTracciato_campo &)_tipi[tc.ftype()]).picture();
|
|
}
|
|
|
|
//////////////////////////////////////// TTracciato_record ////////////////////////////////////////
|
|
|
|
void TTracciato_record::set_relation(TRelation* rel)
|
|
{
|
|
if (_rel) delete _rel;
|
|
_rel = rel;
|
|
}
|
|
|
|
TObject* TTracciato_record::dup() const
|
|
{
|
|
TTracciato_record* t = new TTracciato_record(*this);
|
|
return t;
|
|
}
|
|
|
|
TTracciato_record::TTracciato_record(const TTracciato_record& tr) : _rel(NULL)
|
|
{
|
|
set_relation(tr.relation());
|
|
set_type(tr.type());
|
|
_tracciati_campo = tr._tracciati_campo;
|
|
}
|
|
|
|
TTracciato_record::~TTracciato_record()
|
|
{
|
|
if (_rel) delete _rel;
|
|
}
|
|
|
|
void TTracciato_record::add(const TTracciato_campo& tc, int pos)
|
|
{
|
|
_tracciati_campo.add(tc,pos);
|
|
}
|
|
|
|
void TTracciato_record::add(TTracciato_campo* tc, int pos)
|
|
{
|
|
_tracciati_campo.add(tc,pos);
|
|
}
|
|
|
|
int TTracciato_record::get_pos(const char* name) const
|
|
{
|
|
int i;
|
|
|
|
for (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();
|
|
add(t, n);
|
|
}
|
|
return (TTracciato_campo&)_tracciati_campo[n];
|
|
}
|
|
//////////////////////////////////////// TRecord_text ////////////////////////////////////////
|
|
const TString& TRecord_text::row(int pos) const
|
|
{
|
|
const TString* str = (const TString*)_array.objptr(pos);
|
|
if (str != NULL)
|
|
return *str;
|
|
return EMPTY_STRING;
|
|
}
|
|
|
|
TString& TRecord_text::row(int pos)
|
|
{
|
|
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) const
|
|
{
|
|
return (TTracciato_record*)_tracciati_record.objptr(type);
|
|
}
|
|
|
|
TTracciato_record* TFile_text::t_rec(int mainfile, const char * tabname) const
|
|
{
|
|
if (tabname)
|
|
mainfile=(tabname[0] != '%') ? LF_TAB: LF_TABCOM;
|
|
TTracciato_record *trrd;
|
|
TAssoc_array &tr = (((TFile_text *)this)->_tracciati_record);
|
|
tr.restart();
|
|
while ((trrd=(TTracciato_record *)tr.get()))
|
|
{
|
|
if (trrd->relation() && trrd->relation()->lfile().num()==mainfile)
|
|
if (tabname)
|
|
{
|
|
TTable & tab=(TTable & )trrd->relation()->lfile();
|
|
if (tabname == tab.name() )
|
|
break;
|
|
} else
|
|
break;
|
|
}
|
|
return trrd;
|
|
}
|
|
|
|
|
|
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
|
|
TString tmpstring = config.get("FIELDSEP",section); // solo se a lung. variabile
|
|
|
|
if (tmpstring[0] == '\\')
|
|
{
|
|
if (tmpstring = "\t")
|
|
_fieldsep = '\t';
|
|
}
|
|
else
|
|
_fieldsep = tmpstring[0]; // 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";
|
|
if (_recordsep[0] == '\\')
|
|
{
|
|
if (_recordsep == "\\r")
|
|
_recordsep = "\r"; else
|
|
if (_recordsep == "\\n")
|
|
_recordsep = "\n"; else
|
|
if (_recordsep == "\\n\\r")
|
|
_recordsep = "\n\r";
|
|
}
|
|
_skiplines = config.get_int("SKIPLINES",section); // righe iniziali da ignorare
|
|
|
|
_typefield = config.get_int("TYPEFIELD",section); // Numero del campo tipo (puo' essere -1)
|
|
_fixedlen = _fieldsep <= ' '; // && _recordsep.blank();
|
|
_typepos = config.get_int("TYPEPOS", section, -1, -1);
|
|
_typelen = config.get_int("TYPELEN", section, -1, 0);
|
|
if (_typelen > 16)
|
|
NFCHECK("Tipo record di lunghezza spropositata: %d", _typelen);
|
|
}
|
|
|
|
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));
|
|
const char datatype=config.get_char("DATA", section);
|
|
if (datatype>' ')
|
|
tipo.set_datatype(datatype);
|
|
else
|
|
tipo.set_datatype('S');
|
|
TString s = config.get("FILLER", section);
|
|
if (s.len() > 1)
|
|
tipo.set_filler(s[1]);
|
|
else
|
|
tipo.set_filler(s[0]);
|
|
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 sectkey = section;
|
|
sectkey.ltrim(6);//elimino la parola 'RECORD' o 'HEADER' o 'FOOTER' e gli spazi vuoti
|
|
sectkey.trim();//per avere solo il nome del tipo del record
|
|
TTracciato_record *tr=new TTracciato_record(sectkey);//istanzio un tracciato_record del tipo corrente
|
|
//setto tutti i dati relatvi ai tipi predefini nei tracciati campo per i diversi campi del record
|
|
TRelation *tmprel=NULL; // relazione associata al tracciato record
|
|
config.set_paragraph(section);
|
|
TString lavoro;
|
|
TString_array variables;
|
|
const int numvar = config.list_variables(variables, TRUE);//scarico tutte le variabili della sezione
|
|
variables.sort(FALSE);
|
|
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);
|
|
}
|
|
if (lavoro == "USE") // setta la relazione
|
|
{
|
|
CHECKS(tmprel == NULL,"Relazione già definita per il tracciato: %s", (const char *) sectkey);
|
|
if (atoi((const char *)obj)!=0)
|
|
tmprel= new TRelation(atoi((const char *)obj));
|
|
else
|
|
tmprel= new TRelation((const char *)obj);
|
|
}
|
|
if (lavoro == "JOI") // setta i join
|
|
{
|
|
CHECKS(tmprel, "Can't join to NULL relation %s", (const char*)j);
|
|
|
|
TToken_string join_expr((const char *)obj,' '); // Join expression
|
|
int token=0;
|
|
TString16 j(join_expr.get(token++)); // file or table
|
|
int to=0; // 'to' default: _relation->lfile()->num();
|
|
if (strcmp(join_expr.get(token++),"TO")==0) // TO keyword
|
|
{
|
|
const char* t = join_expr.get(token++);
|
|
to = name2log(t);
|
|
} else
|
|
token --;
|
|
int nkey = 1;
|
|
if (strcmp(join_expr.get(token++),"KEY")==0)
|
|
nkey = join_expr.get_int(token++);
|
|
else
|
|
token--;
|
|
int alias = 0;
|
|
if (strcmp(join_expr.get(token++),"ALIAS")==0)
|
|
alias = join_expr.get_int(token++);
|
|
else
|
|
token--;
|
|
TToken_string exp(80);
|
|
if (strcmp(join_expr.get(token++),"INTO")==0)
|
|
{
|
|
const char* r = join_expr.get(token++);
|
|
while (r && strchr(r, '=') != NULL)
|
|
{
|
|
exp.add(r);
|
|
r = join_expr.get(token++);
|
|
}
|
|
}
|
|
|
|
#ifdef DBG
|
|
if (exp.empty()) yesnofatal_box("JOIN senza espressioni INTO");
|
|
#endif
|
|
|
|
if (j[0] >= '0' && j[0] <= '9')
|
|
{
|
|
tmprel->add(atoi(j), exp, nkey, to, alias); // join file
|
|
tmprel->write_enable(atoi(j),key.left(6)!="JOINRO");
|
|
} else
|
|
{
|
|
#ifdef DBG
|
|
if (j.len() > 4)
|
|
yesnofatal_box("'%s' non e' una tabella valida: %d", (const char*)j);
|
|
else
|
|
#endif
|
|
{
|
|
tmprel->add(j, exp, nkey, to, alias); // join table
|
|
tmprel->write_enable(j,key.left(6)!="JOINRO");
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
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 == "FTY") // field type
|
|
{
|
|
CHECKS(_tipi.objptr(obj)!=NULL,"Riferimento a campo inesistente:%s", (const char *) obj);
|
|
tc.set_ftype(obj);
|
|
continue;
|
|
}
|
|
if (lavoro == "POS")
|
|
{
|
|
const int pos = atoi(obj);
|
|
if (pos >= 0)
|
|
{
|
|
tc.set_position(pos);
|
|
if (_typepos < 0 && n == _typefield)
|
|
_typepos = pos;
|
|
}
|
|
continue;
|
|
}
|
|
if (lavoro == "LEN")
|
|
{
|
|
const int len = atoi(obj);
|
|
if (tc.length() <= 0 && len > 0)
|
|
{
|
|
tc.set_length(len);
|
|
if (_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)
|
|
{
|
|
if (obj.len() > 1)
|
|
tc.set_filler(obj[1]);
|
|
else
|
|
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;
|
|
}
|
|
if (_fixedlen && _typelen < 0 && n == _typefield)
|
|
_typelen = tc.length();
|
|
|
|
}
|
|
tr->set_relation(tmprel);
|
|
//aggiungo il tracciato record all'assoc_array dei tracciati record
|
|
_tracciati_record.add(sectkey, tr);
|
|
}
|
|
|
|
TFile_text::TFile_text(const char* file_name, const char* config_name)
|
|
: _name(file_name), _skiplines(0), _kill_zeroes(FALSE), _force_record_separator(FALSE)
|
|
{
|
|
_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 == "FTY") // field type
|
|
{
|
|
set_type_parm(config, section);
|
|
continue;
|
|
}
|
|
if ((sec == "REC")||(sec == "HEA")||(sec == "FOO"))
|
|
{
|
|
set_rec_parm(config, section);
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
TFile_text::~TFile_text()
|
|
{
|
|
if (_read_file)
|
|
delete _read_file;
|
|
if (_write_file)
|
|
delete _write_file;
|
|
_tipi.destroy();
|
|
_tracciati_record.destroy();
|
|
|
|
}
|
|
|
|
//Legge da file il record text
|
|
int TFile_text::read(TRecord_text& rec)
|
|
{
|
|
if (_read_file == NULL)
|
|
open('r');
|
|
|
|
TToken_string buffer;
|
|
|
|
if (_recordsize > 0)
|
|
{
|
|
if (buffer.size() < _recordsize)
|
|
buffer.spaces(_recordsize);
|
|
|
|
_read_file->read(buffer.get_buffer(), _recordsize);
|
|
if (!ok_r()) return 1; //non ritorna errore se fine file ed il record e' completo!
|
|
}
|
|
else
|
|
{
|
|
if (_recordsep == "\r\n" || _recordsep == "\n\r")
|
|
{
|
|
const int maxsize = 1024*16;
|
|
char* buf = buffer.get_buffer(maxsize);
|
|
_read_file->get(buf, maxsize, _recordsep[0]);
|
|
if (buffer.empty())
|
|
return EOF;
|
|
char c = _read_file->get();
|
|
c = _read_file->get();
|
|
}
|
|
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!
|
|
}
|
|
for (int j = _recordsep.len()-1; j > 0; j--)
|
|
c = _read_file->get();
|
|
}
|
|
}
|
|
|
|
if (_fieldsep != '\0')
|
|
{
|
|
buffer.separator(_fieldsep);
|
|
|
|
const char* tipo = _typefield >= 0 ? buffer.get(_typefield) : "";
|
|
TTracciato_record& tr = *t_rec(tipo);
|
|
rec.set_type(tipo);//istanzio il tipo del record text
|
|
|
|
TArray& a_tc = tr.tracciati_campo();
|
|
const int items = a_tc.items();
|
|
buffer.restart();
|
|
TString lavoro;
|
|
for (int i = 0; i < items; i++)
|
|
{
|
|
buffer.get(i, lavoro);
|
|
rec.add(lavoro, i);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TString16 tipo;
|
|
if (_typepos >= 0 && _typelen > 0)
|
|
{
|
|
tipo = buffer.mid(_typepos, _typelen);
|
|
tipo.trim();
|
|
}
|
|
rec.set_type(tipo);//istanzio il tipo del record text
|
|
TTracciato_record* tr = t_rec(tipo);
|
|
if (tr != NULL)
|
|
{
|
|
//ora che ho il tracciato record devo scandire i tracciati campo e caricare il record text
|
|
const TArray& a_tc = tr->tracciati_campo();
|
|
const int items = a_tc.items();
|
|
for (int i = 0; i < items; i++)
|
|
{
|
|
TTracciato_campo& tc = tr->get(i);
|
|
const int pos = tc.position();
|
|
const int len = tc.length();
|
|
const TString& lavoro = buffer.mid(pos, len);
|
|
rec.add(lavoro, i);
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//Scrive su file il record_text (valido anche per header e footer)
|
|
int TFile_text::write(TRecord_text& rec)
|
|
{
|
|
TString campo;
|
|
TToken_string buffer;
|
|
|
|
const TString& type = rec.type();
|
|
TTracciato_record& tr = *t_rec(type);
|
|
|
|
const int items = rec.items();
|
|
if (_typepos>=0)
|
|
rec.add(type,_typepos);
|
|
|
|
const TArray& tac = tr.tracciati_campo();
|
|
|
|
if (_fixedlen) // campi a lunghezza fissa
|
|
{
|
|
FOR_EACH_ARRAY_ITEM(tac, i, obj)
|
|
{
|
|
const TTracciato_campo& tc = tr.get(i);
|
|
campo = rec.get(i);
|
|
format_textfield(tc, campo);
|
|
buffer.overwrite(campo, tc.position());
|
|
}
|
|
CHECK(_write_file, "Impossibile scrivere su un file chiuso.");
|
|
if (_recordsize<=0)
|
|
{
|
|
// Record a lunghezza var
|
|
*_write_file << buffer;
|
|
*_write_file << _recordsep;
|
|
}
|
|
else
|
|
{
|
|
// Record a lunghezza fissa
|
|
buffer.rpad(_recordsize);
|
|
buffer.cut(_recordsize);
|
|
*_write_file << buffer;
|
|
if (_force_record_separator)
|
|
*_write_file << _recordsep;
|
|
}
|
|
if (!ok_w()) return 1;
|
|
}
|
|
else
|
|
{
|
|
buffer.separator(_fieldsep);
|
|
FOR_EACH_ARRAY_ITEM(tac, i, obj)
|
|
{
|
|
const TTracciato_campo& tc = tr.get(i);
|
|
campo = rec.get(i);
|
|
format_textfield(tc, campo);
|
|
buffer.add(campo);
|
|
}
|
|
CHECK(_write_file, "Impossibile scrivere su un file chiuso.");
|
|
*_write_file << buffer;
|
|
*_write_file << _recordsep;
|
|
if (!ok_w()) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Carica tutti i dati del tracciato record (anche header o footer)
|
|
// nel record_text
|
|
bool TFile_text::autoload(TRecord_text& rec, int mainfile)
|
|
{
|
|
TTracciato_record* tr = t_rec(mainfile);
|
|
if (tr)
|
|
{
|
|
// esiste il tracciato e posso fare l'autoload
|
|
TCursor cur(tr->relation());
|
|
rec.set_type(tr->type());
|
|
return _autoload(rec,cur,*tr);
|
|
}
|
|
//CHECK (FALSE,"Il tracciato record non esiste");
|
|
return FALSE;
|
|
}
|
|
|
|
// Carica tutti i dati del tracciato record (anche header o footer)
|
|
// nel record_text
|
|
bool TFile_text::autoload(TRecord_text& rec, const char * tabname)
|
|
{
|
|
TTracciato_record* tr = t_rec(tabname);
|
|
if (tr)
|
|
{
|
|
// esiste il tracciato e posso fare l'autoload
|
|
TCursor cur(tr->relation());
|
|
rec.set_type(tr->type());
|
|
return _autoload(rec,cur,*tr);
|
|
}
|
|
//CHECK (FALSE,"Il tracciato record non esiste");
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//Carica tutti i dati nel tracciato record (valido anche per header e footer) nel record_text
|
|
bool TFile_text::autoload(TRecord_text& rec, TCursor& cur , const TString* tipo)
|
|
{
|
|
const TString& type = rec.type();
|
|
if (tipo == NULL) tipo = &type;
|
|
TTracciato_record* tr = t_rec(*tipo);
|
|
CHECKS(tr!=NULL,"Tracciato record file di testo non trovato ",(const char *)*tipo);
|
|
return _autoload(rec,cur,*tr);
|
|
}
|
|
|
|
bool TFile_text::autoload(TCursor& cur, const TString* tipo)
|
|
{
|
|
CHECK(_current,"Record corrente non settato");
|
|
return autoload(*_current, cur, tipo);
|
|
}
|
|
|
|
//Carica tutti i dati nel tracciato record (valido anche per header e footer) nel record_text
|
|
bool TFile_text::_autoload(TRecord_text& rec, TCursor& cur , TTracciato_record& tr )
|
|
{
|
|
TString campo;
|
|
TRelation& rel = *cur.relation();
|
|
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().not_empty())
|
|
campo = field.read(rel);
|
|
|
|
const TString& message = tc.message();
|
|
if (message.full())
|
|
{
|
|
TToken_string msg (message, ',');
|
|
if (!msg.blank())
|
|
validate(cur, rec, msg, campo);
|
|
}
|
|
|
|
rec.add(campo, i);
|
|
campo.cut(0);
|
|
}
|
|
return can_write(rec,rel);
|
|
}
|
|
|
|
int TFile_text::autosave(const TRecord_text& rec, int mainfile )
|
|
{
|
|
const TString& type = rec.type();//prendo il tracciato record del tipo del record_text
|
|
TTracciato_record* tr = t_rec(type);
|
|
if (tr)
|
|
{
|
|
TRelation* rel = tr->relation();
|
|
if (rel && (mainfile==0 || rel->lfile().num()==mainfile))
|
|
return _autosave(*rel,rec, *tr);
|
|
}
|
|
return NOERR; // l'assenza del tracciato non significa un errore
|
|
}
|
|
|
|
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);
|
|
return _autosave(rel,rec, tr);
|
|
}
|
|
|
|
int TFile_text::autosave(int mainfile)
|
|
{
|
|
CHECK(_current,"Record corrente non settato");
|
|
return autosave(*_current,mainfile);
|
|
}
|
|
|
|
//Carico la relazione con i dati del record text
|
|
int TFile_text::_autosave(TRelation& rel, const TRecord_text& rec, TTracciato_record& tr )
|
|
{
|
|
TArray& a_tc = tr.tracciati_campo();
|
|
int items = a_tc.items();
|
|
TString valore;
|
|
for (int i = 0; i < items; i++)
|
|
{
|
|
const TTracciato_campo& tc = tr.get(i);
|
|
if (tc.field().name().not_empty())
|
|
{
|
|
const TFieldref& field = tc.field();
|
|
valore = rec.row(i);
|
|
// formatta il campo del file di testo secondo le specifiche del campo su file isam
|
|
preformat_field(field,valore,rel,tr.type());
|
|
const TRectype& rel_rec = rel.curr(field.file());
|
|
TFieldtypes tipo_campo = rel_rec.type(field.name());
|
|
switch(tipo_campo)
|
|
{
|
|
case _datefld:
|
|
{
|
|
if (real::is_null(valore))
|
|
valore.cut(0);
|
|
TDate data(valore);
|
|
format_date(data, fpicture(tc), valore);//formatta la data secondo le specifiche del tracciato
|
|
}
|
|
break;
|
|
case _realfld:
|
|
case _intfld:
|
|
case _longfld:
|
|
{
|
|
real numero(valore);
|
|
valore = numero.string(fpicture(tc));//formatta il numero secondo le specifiche del tracciato
|
|
|
|
int length = flength(tc,rel_rec);
|
|
if (falign(tc) == 'L')
|
|
valore.left_just(length, ffiller(tc));
|
|
else
|
|
valore.right_just(length, ffiller(tc));
|
|
int j = valore.replace('.', _decsep); //!?!?! consento decsep diversi per isam e text ?
|
|
CHECK(j >= 0 && j <= 1 , "Impossibile scrivere più separatori decimali.");
|
|
}
|
|
break;
|
|
default:
|
|
if (_kill_zeroes && zero_only(valore))
|
|
valore = "";
|
|
valore = format_field(tc, rel.lfile().num(), valore);//formatta il campo secondo le specifiche del record
|
|
break;
|
|
}
|
|
|
|
if (rel.exist(field.file()))
|
|
field.write(valore, rel);//faccio una write sulla relazione del fieldref
|
|
}
|
|
}
|
|
if (pre_writerel(rel,rec))
|
|
{
|
|
int err= rel.write();
|
|
if (err == _isdupkey || err ==_isreinsert)
|
|
err = rel.rewrite();
|
|
return err;
|
|
}
|
|
|
|
return NOERR;
|
|
}
|
|
|
|
//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());
|
|
if (tr != NULL)
|
|
{
|
|
const int ncampo = tr->get_pos(name);
|
|
if (ncampo >= 0)
|
|
return rec.row(ncampo);
|
|
}
|
|
|
|
NFCHECK("Campo inesistente %s", name);
|
|
return EMPTY_STRING;
|
|
}
|
|
|
|
//Carica nel record_text il campo alla posizione <ncampo> con il valore <val> già formattato
|
|
void TFile_text::add_field(TRecord_text& rec, const int ncampo, const char* val)
|
|
{
|
|
TTracciato_record* tr = t_rec(rec.type());
|
|
CHECKS(tr, "Tracciato inesistente ", (const char*)rec.type());
|
|
tr->get(ncampo);
|
|
rec.add(val, ncampo);
|
|
}
|
|
|
|
//Carica nel record_text il campo <name> con il valore <val> già formattato
|
|
void TFile_text::add_field(TRecord_text& rec, const char* name, const char* val)
|
|
{
|
|
TTracciato_record* tr = t_rec(rec.type());
|
|
CHECKS(tr, "Tracciato inesistente ", (const char*)rec.type());
|
|
int ncampo = tr->get_pos(name);
|
|
CHECKS(ncampo >= 0, "Campo inesistente ", name);
|
|
rec.add(val, 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)
|
|
{
|
|
TString16 s;
|
|
s.format("%02d", data.day());
|
|
data_str << s;
|
|
}
|
|
if (cnt == 3)
|
|
{
|
|
TString16 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)
|
|
{
|
|
TString16 s;
|
|
s.format("%02d", data.month());
|
|
data_str << s;
|
|
}
|
|
if (cnt == 3)
|
|
{
|
|
TString16 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 alle definizioni del tracciato
|
|
// La stringa ritornata rappresenta il valore del campo nel filetext e i parametri di fomattazione
|
|
// sono quelli associati al campo nel filetext
|
|
TString& TFile_text::format_textfield(const TTracciato_campo& tc, TString& campo)
|
|
{
|
|
//int pos = tc.position();
|
|
int length = tc.length();
|
|
char fillch=tc.filler();
|
|
if (!tc.picture().blank())
|
|
{
|
|
switch (tc.datatype())
|
|
{
|
|
case 'N': // number
|
|
{
|
|
real tmp(campo);
|
|
campo=tmp.string(tc.picture());
|
|
}
|
|
break;
|
|
case 'D': //data
|
|
{
|
|
TDate d(campo);
|
|
TFormatted_date tmp(d, tc.picture());
|
|
campo=tmp.string();
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
TString tmp;
|
|
tmp.picture(tc.picture(), campo);
|
|
campo=tmp;
|
|
}
|
|
}
|
|
}
|
|
if (length > campo.len())
|
|
{
|
|
if (fillch == '\0' && _fixedlen)
|
|
fillch=' ';
|
|
if (tc.align() == 'R')
|
|
campo.right_just(length,fillch);
|
|
else
|
|
campo.left_just(length, fillch);
|
|
}
|
|
else
|
|
{
|
|
if (length > 0)
|
|
{
|
|
if (tc.align() == 'R')
|
|
campo=campo.right(length);
|
|
else
|
|
campo.cut(length);
|
|
}
|
|
}
|
|
return campo;
|
|
}
|
|
|
|
// Formatta la stringa passata in base al field del file isam
|
|
// La stringa ritornata rappresenta il valore del campo nel file isam e i parametri di fomattazione
|
|
// sono quelli associati al campo nel file isam (metodi fpicture, falign ecc.)
|
|
TString& TFile_text::format_field(const TTracciato_campo& tc, short lfile, TString& campo)
|
|
{
|
|
const TRectype record(tc.field().file() ? tc.field().file() : lfile);
|
|
|
|
int length = flength(tc,record);
|
|
const bool is_memo = record.type(tc.field().name()) == _memofld;
|
|
|
|
if (!fpicture(tc).blank())
|
|
{
|
|
TString tmp;
|
|
tmp.picture(fpicture(tc), campo);
|
|
campo=tmp;
|
|
}
|
|
if (length > campo.len() || is_memo) // Se il field di destinazione e' un memo... si scrive tutto!
|
|
{
|
|
if (falign(tc) == 'R')
|
|
campo.right_just(length, ffiller(tc));
|
|
else
|
|
campo.left_just(length, ffiller(tc));
|
|
}
|
|
else
|
|
{
|
|
if (length > 0)
|
|
{
|
|
if (falign(tc) == 'R')
|
|
campo=campo.right(length);
|
|
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);
|
|
return _read_file->rdstate() != ios::goodbit;
|
|
}
|
|
|
|
if (_skiplines > 0)
|
|
{
|
|
if (_recordsize > 0)
|
|
{
|
|
streamoff bytestoskip = streamoff(_recordsize) * _skiplines;
|
|
_read_file->seekg(bytestoskip, ios::beg);
|
|
} else
|
|
if (_recordsep.not_empty())
|
|
{
|
|
int s = _skiplines;
|
|
int c;
|
|
for (c = _read_file->get(); c != EOF; c = _read_file->get())
|
|
{
|
|
if (c == _recordsep[0])
|
|
{
|
|
for (int k = _recordsep.len()-1; k > 0; k--)
|
|
c = _read_file->get();
|
|
if (--s == 0)
|
|
break;
|
|
}
|
|
}
|
|
if (c == EOF)
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
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;
|
|
if (_read_file) _read_file->close();
|
|
if (_write_file) _write_file->close();
|
|
return 0;
|
|
}
|