Patch level : 12.0 nopatch

Files correlati     :
Commento :

Spostato in libreria l'oggetto ttracciatoInvio per l'invio dell'intra.
This commit is contained in:
Alessandro Bonazzi 2021-03-07 23:03:09 +01:00
parent b206b434b4
commit 58d9f57378
2 changed files with 628 additions and 0 deletions

View File

@ -1064,3 +1064,506 @@ TTextfile::~TTextfile ()
if (_istemp) remove ((const char *) _filename);
remove ((const char *) _indname);
}
///////////////////////////////////////////////////////////
// TTracciatoInvio
///////////////////////////////////////////////////////////
void TTracciatoInvio::add_field(const char* name, InvioFieldType type, int pos, int len, int dec, int fldno)
{
switch (type)
{
case AN:
break;
case CB:
CHECKD(len == 1, "Booleano di lunghezza sospetta ", len);
// type = NU;
break;
case CF:
CHECKD(len == 16, "Codice fiscale di lunghezza sospetta ", len);
type = AN;
break;
case CN:
CHECKD(len == 11, "Codice fiscale numerico di lunghezza sospetta ", len);
type = NU;
break;
case DA:
CHECKD(len == 6, "Mese+Anno di lunghezza sospetta ", len);
type = NU;
break;
case DT:
CHECKD(len == 8, "Data di lunghezza sospetta ", len);
type = NU;
break;
case NU:
break;
case PN:
case PR:
CHECKD(len == 2, "provincia di lunghezza sospetta ", len);
type = AN;
break;
case QU:
CHECK(len > dec + 1, "numero di decimali incoerente");
default:
CHECK(false, "tipo campo sospetto");
break;
}
TFieldInvio* info = new TFieldInvio;
info->_desc = name;
info->_type = type;
info->_pos = pos;
info->_len = len;
info->_dec = dec;
if (fldno <= 0)
fldno = _fields.add(info) + 1;
else
_fields.add(info, fldno - 1);
}
const TFieldInvio& TTracciatoInvio::field(int pos) const
{
TFieldInvio* info = (TFieldInvio*)_fields.objptr(pos - 1);
#ifdef DBG
if (info == NULL)
fatal_box("Non esiste il campo %d sul tipo record %c", pos, _tipo);
#endif
return *info;
}
void TTracciatoInvio::auto_fill(TString& buffer) const
{
buffer.fill(' ', TOTAL_SIZE);
char* ptr = buffer.get_buffer();
for (int f = _fields.last(); f >= 0; f = _fields.pred(f))
{
const TFieldInvio& info = (const TFieldInvio&)_fields[f];
if (info._type == NU || info._type == CB || info._type == DA || info._type == DT || info._type == CN)
memset(ptr + info._pos - 1, '0', info._len);
}
buffer[0] = _tipo;
buffer.overwrite("A\r\n", TOTAL_SIZE - 3);
}
TTracciatoInvio::TTracciatoInvio(char tipo) : _tipo(tipo)
{
if (strchr("ABCEFHJZ[", tipo) == NULL)
NFCHECK("Tipo record non valido: %c", tipo);
add_field("Tipo record", AN, 1, 1); // 1
}
TTracciatoInvio::~TTracciatoInvio()
{
}
TTracciatiInvio _trcInvio;
const TTracciatoInvio& TTracciatiInvio::add_tracciato(TTracciatoInvio * tracciato)
{
int pos = tracciato->tipo() - 'A';
const TTracciatoInvio* trc = (TTracciatoInvio*)_trc.objptr(pos);
if (trc == nullptr)
_trc.add(tracciato, pos);
return *tracciato;
}
class TTracciatoInvioFileDati : public TTracciatoInvio
{
public:
TTracciatoInvioFileDati(const TRectype& rec);
virtual ~TTracciatoInvioFileDati() {}
};
TTracciatoInvioFileDati::TTracciatoInvioFileDati(const TRectype& rec)
{
for (int i = 0; i < rec.items(); i++)
{
const TString16 fieldname(rec.rec_des().Fd[i].Name);
TFieldtypes t = rec.type(fieldname);
int pos = 0;
switch (t)
{
case _nullfld:
break;
case _alfafld: // @emem Campo di tipo alfanumerico
add_field(fieldname, AN, pos++, rec.length(fieldname));
break;
case _intfld: // @emem Campo di tipo intero
case _longfld: // @emem Campo di tipo intero lungo
add_field(fieldname, NU, pos++, rec.length(fieldname));
break;
case _realfld: // @emem Campo di tipo reale (vedi <c real>)
add_field(fieldname, NU/*QU*/, pos++, rec.length(fieldname));
break;
case _datefld: // @emem Campo di tipo data (vedi <c TDate>)
add_field(fieldname, DT, pos++, rec.length(fieldname));
break;
case _wordfld: // @emem Campo di tipo intero senza segno
add_field(fieldname, NU, pos++, rec.length(fieldname));
break;
case _charfld: // @emem Campo di tipo carattere
add_field(fieldname, AN, pos++, 1);
break;
case _boolfld: // @emem Campo di tipo booleano
add_field(fieldname, CB, pos++, rec.length(fieldname));
break;
case _intzerofld: // @emem Campo di tipo intero zero filled
case _longzerofld: // @emem Campo di tipo intero lungo zero filled
add_field(fieldname, NU, pos++, rec.length(fieldname));
break;
case _memofld:
add_field(fieldname, AN, pos++, rec.length(fieldname));
break;
}
}
}
TTracciatiInvio & tracciati() {return _trcInvio;}
const TTracciatoInvio& TTracciatiInvio::tracciato(char tipo)
{
CHECK((tipo >= 'A' && tipo <= 'Z') || tipo == '[', "Tipo record non valido");
const int pos = tipo - 'A';
const TTracciatoInvio* trc = (TTracciatoInvio*)_trc.objptr(pos);
if (trc == NULL)
trc = &tracciati().add_tracciato(new TTracciatoInvio(tipo));
return *trc;
}
void TTracciatiInvio::destroy()
{
_trc.destroy();
}
TTracciatiInvio::TTracciatiInvio()
{
}
TTracciatiInvio::~TTracciatiInvio()
{
destroy(); // Non viene mai chiamato!
}
///////////////////////////////////////////////////////////
// TRecordInvio
///////////////////////////////////////////////////////////
const TTracciatoInvio& TRecordInvio::tracciato() const
{
return _trcInvio.tracciato(tipo_record());
}
void TRecordInvio::print_on(ostream& outs) const
{
outs.write(_buffer, TOTAL_SIZE);
}
void TRecordInvio::read_from(istream& ins)
{
_buffer.fill(' ', TOTAL_SIZE);
ins.read(_buffer.get_buffer(), TOTAL_SIZE);
}
const TFieldInvio& TRecordInvio::get_field(int pos) const
{
return tracciato().field(pos);
}
void TRecordInvio::set(const TFieldInvio& fld, const char* val)
{
TString256 str(val); // Ci sono campi di 100 caratteri!
if (fld._type == AN)
str.upper();
if (fld._type == QU)
{
str.replace(".", ",");
int dotpos = str.find(".");
if (dotpos < 0)
str << ".";
dotpos = str.find(".");
int dec = fld._dec - (str.len() - dotpos - 1);
while (dec > 0) str << '0';
}
int lenstr = str.len();
if (lenstr > fld._len)
{
#ifdef DBG
NFCHECK("Campo troppo lungo: '%s' (max. %d)", val, fld._len);
#endif
if (fld._type == QU)
{
str.ltrim(lenstr - fld._len);
lenstr = fld._len;
}
else
str.cut(lenstr = fld._len);
}
if (lenstr != fld._len)
{
str.trim();
if (fld._type == NU)
str.right_just(fld._len, '0');
else
str.left_just(fld._len);
}
_buffer.overwrite(str, fld._pos - 1);
}
void TRecordInvio::set(int pos, const char* val)
{
const TFieldInvio& fld = tracciato().field(pos);
set(fld, val);
}
void TRecordInvio::set(int pos, int val)
{
const TFieldInvio& fld = tracciato().field(pos);
CHECKD(fld._type == NU, "Invalid numeric field ", pos);
TString16 str; str.format("%d", val);
set(fld, str);
}
void TRecordInvio::set(int pos, long val)
{
const TFieldInvio& fld = tracciato().field(pos);
CHECKD(fld._type == NU, "Invalid numeric field ", pos);
TString16 str; str.format("%ld", val);
set(fld, str);
}
void TRecordInvio::set(int pos, const real& val)
{
const TFieldInvio& fld = tracciato().field(pos);
CHECKD(fld._type == NU, "Invalid numeric field ", pos);
const char* str = val.string(fld._len, 0);
set(fld, str);
}
void TRecordInvio::set(int pos, const TDate& val)
{
const TFieldInvio& fld = tracciato().field(pos);
CHECKD(fld._type == NU && (fld._len == 6 || fld._len == 8),
"Invalid date field ", pos);
const char* str;
if (fld._len == 8)
str = val.string(full, '\0', full, full, gma_date);
else
str = val.string(brief, '\0', full, full, gma_date);
set(fld, str);
}
void TRecordInvio::set(int pos, char val)
{
const TFieldInvio& fld = get_field(pos);
CHECKD(fld._type == AN && fld._len == 1, "Invalid char field ", pos);
const char str[2] = { val, '\0' };
set(fld, str);
}
void TRecordInvio::set(int pos, bool val)
{
const TFieldInvio& fld = get_field(pos);
CHECKD((fld._type == CB || fld._type == NU) && fld._len == 1, "Invalid boolean field ", pos);
set(fld, val ? "1" : "0");
}
const char* TRecordInvio::get(int pos, TString& str) const
{
const TFieldInvio& fld = get_field(pos);
str = _buffer.mid(fld._pos - 1, fld._len);
return str.trim();
}
int TRecordInvio::get_int(int pos) const
{
TString16 str; get(pos, str);
return atoi(str);
}
char TRecordInvio::get_char(int pos) const
{
const TFieldInvio& fld = get_field(pos);
CHECKD(fld._type == AN, "Invalid char field ", pos);
return _buffer[fld._pos - 1];
}
// Calcola i blocchi necessari per contenere la stringa val
int TRecordInvio::calculate_blocks(const char* val) const
{
// Il primo blocco contiene 16 caratteri, gli altri solo 15 perche' c'e' anche il +
int blocks = 1;
if (val && *val)
{
const int len = strlen(val);
if (len > FIELD_SIZE)
blocks += (len - FIELD_SIZE - 1) / (FIELD_SIZE - 1) + 1;
}
return blocks;
}
void TRecordInvio::tipo_record(char tipo)
{
_buffer[0] = tipo; tracciato().auto_fill(_buffer);
}
// Azzera tutti i campi non posizionali dei record di tipo E
void TRecordInvio::azzera_campi_non_posizionali()
{
CHECK(ha_campi_non_posizionali(), "Impossibile azzerare un record senza campi non posizionali");
char* buf = _buffer.get_buffer() + HEADER_SIZE;
memset(buf, ' ', USEABLE_SIZE);
}
// Aggiunge un campo non posizionale ai record di tipo E,F,G,H,J
bool TRecordInvio::np_put(const char* code, const char* val)
{
CHECK(ha_campi_non_posizionali(), "Impossibile aggiungere campi non posizionali");
CHECKS(code && strlen(code) == CODE_SIZE, "Invalid field code ", code);
//CHECKS(val && *val, "Can't add empty field ", code);
if (!(val && *val))
return false;
// Cerca il primo posto libero
int pos;
for (pos = HEADER_SIZE; pos < HEADER_SIZE + USEABLE_SIZE; pos += BLOCK_SIZE)
{
if (_buffer[pos] == ' ')
break;
}
const int free_blocks = (USEABLE_SIZE - pos) / BLOCK_SIZE;
const int needed_blocks = calculate_blocks(val);
const bool ok = free_blocks >= needed_blocks;
if (ok) // Se ci sono abbastanza blocchi liberi
{
TString80 str(val); str.upper();
const int lenstr = str.len();
for (int i = 0; i < lenstr; )
{
_buffer.overwrite(code, pos);
pos += CODE_SIZE;
int maxlen = FIELD_SIZE;
if (i > 0)
{
_buffer.overwrite("+", pos);
pos++;
maxlen--;
}
const TString& substr = str.mid(i, maxlen);
_buffer.overwrite(substr, pos);
pos += maxlen;
i += maxlen;
}
}
return ok;
}
bool TRecordInvio::np_put(const char* code, long val)
{
TString16 str; str.format("%16ld", val);
return np_put(code, str);
}
bool TRecordInvio::np_put(const char* code, const real& val)
{
bool done = !val.is_zero();
if (done)
{
const TString& str = val.stringa(16, 2);
done = np_put(code, str);
}
return done;
}
bool TRecordInvio::np_put(const char* code, char val)
{
bool done = val > ' ';
if (done)
{
const char str[2] = { val, '\0' };
done = np_put(code, str);
}
return done;
}
bool TRecordInvio::np_put(const char* code, const TDate& date)
{
bool done = date.ok();
if (done)
{
TString16 str;
str.format("%8s%02d%02d%04d", "", date.day(), date.month(), date.year());
done = np_put(code, str);
}
return done;
}
bool TRecordInvio::np_put(const char* code, bool cb)
{
bool done = false;
if (cb)
{
TString16 str; str.format("%16d", 1);
done = np_put(code, str);
}
return done;
}
bool TRecordInvio::np_get(int pos, TString& key, TString& val) const
{
CHECK(ha_campi_non_posizionali(), "Impossibile leggere campi non posizionali");
const int n = HEADER_SIZE + pos * BLOCK_SIZE;
bool ok = false;
if (n < HEADER_SIZE + USEABLE_SIZE)
{
ok = _buffer[n] > ' ';
if (ok)
{
key = _buffer.mid(n, CODE_SIZE);
val = _buffer.mid(n + CODE_SIZE, FIELD_SIZE);
#ifdef DBG
if (key == "AU001036")
int cazzone = atoi(val);
#endif
}
}
return ok;
}
bool TRecordInvio::np_get_real(int pos, TString& key, real& val) const
{
TString16 str;
const bool ok = np_get(pos, key, str);
if (ok && str.full())
{
str.replace(',', '.');
val = real(str);
}
else
val = ZERO;
return ok;
}
bool TRecordInvio::valid() const
{
const char tipo = tipo_record();
const bool ok = (tipo > ' ') && (strchr("ABEHJZ", tipo) != NULL);
return ok;
}
TRecordInvio::TRecordInvio(const TRectype& rec) : _buffer(TOTAL_SIZE, ' ')
{
tracciati().add_tracciato(new TTracciatoInvioFileDati(rec));
}

View File

@ -9,6 +9,10 @@
#include <strings.h>
#endif
#ifndef __ISAM_H
#include <isam.h>
#endif
#ifndef __RELATION_H
class TRelation;
#endif
@ -206,5 +210,126 @@ public:
virtual ~TTextfile();
};
enum { CODE_SIZE = 8, FIELD_SIZE = 16, BLOCK_SIZE = 24, HEADER_SIZE = 89, USEABLE_SIZE = 1800, TOTAL_SIZE = 1900 };
///////////////////////////////////////////////////////////
// TRecordInvio
///////////////////////////////////////////////////////////
enum InvioFieldType { AN, CF, CN, PI, DA, DT, NU, PN, PR, CB, VP, VN, QU };
struct TFieldInvio : public TObject
{
TString _desc;
int _pos; // Base 1
int _len;
int _dec;
InvioFieldType _type; // AN,NU,...
};
class TTracciatoInvio : public TObject
{
char _tipo;
TArray _fields;
protected:
void add_field(const char* name, InvioFieldType tipo, int pos, int len, int dec = 0, int filedno = 0);
void add_filler(int pos, int len, InvioFieldType tipo = AN) { add_field("Filler", tipo, pos, len); }
TTracciatoInvio() {}
void set_tipo(char t) { _tipo = t; }
public:
bool exists(int pos) const { return _fields.objptr(pos - 1) != NULL; }
const TFieldInvio& field(int pos) const;
void auto_fill(TString& buffer) const;
int campi_posizionali() const { return _fields.last() + 1; }
char tipo() const { return _tipo; }
TTracciatoInvio(char tipo);
virtual ~TTracciatoInvio();
};
///////////////////////////////////////////////////////////
// TTracciatiInvio
///////////////////////////////////////////////////////////
class TTracciatiInvio : public TObject
{
TArray _trc;
public:
const TTracciatoInvio& tracciato(char tipo);
const TTracciatoInvio& add_tracciato(TTracciatoInvio * tracciato);
void destroy();
TTracciatiInvio();
virtual ~TTracciatiInvio();
};
TTracciatiInvio & tracciati();
class TRecordInvio : public TObject
{
TString _buffer;
protected: // TObject
virtual TObject* dup() const { return new TRecordInvio(*this); }
virtual void print_on(ostream& outs) const;
virtual void read_from(istream& ins);
protected: // TObject
//virtual const TTracciatoInvio& add_tracciato(char tipo);
virtual const TTracciatoInvio& tracciato() const;
const TFieldInvio& get_field(int pos) const;
void set(const TFieldInvio& fld, const char* val);
int calculate_blocks(const char* val) const;
public:
void set(int pos, const char* val);
void set(int pos, int val);
void set(int pos, long val);
void set(int pos, const real& val);
void set(int pos, const TDate& val);
void set(int pos, char val);
void set(int pos, bool val);
bool np_put(const char* code, const char* val);
bool np_put(const char* code, const real& val);
bool np_put(const char* code, long val);
bool np_put(const char* code, char val);
bool np_put(const char* code, const TDate& date);
bool np_put(const char* code, bool cb);
const char* get(int pos, TString& str) const;
int get_int(int pos) const;
char get_char(int pos) const;
bool np_get(int pos, TString& key, TString& val) const;
bool np_get_real(int pos, TString& key, real& val) const;
const TRecordInvio& operator=(const TRecordInvio& rec)
{
_buffer = rec._buffer; return *this;
}
char tipo_record() const { return _buffer[0]; }
void tipo_record(char tipo);
int campi_posizionali() const { return tracciato().campi_posizionali(); }
void azzera_campi_non_posizionali();
virtual bool ha_campi_non_posizionali() const { return strchr("CDEFGHJ", tipo_record()) != NULL; }
bool ha_campi_non_posizionali_compilati() const { return _buffer[90] > ' ' && ha_campi_non_posizionali(); }
virtual bool valid() const;
TRecordInvio() : _buffer(TOTAL_SIZE, ' ') {}
TRecordInvio(char tipo) : _buffer(TOTAL_SIZE, ' ') { tipo_record(tipo); }
TRecordInvio(const TRecordInvio& rec) : _buffer(rec._buffer) { }
TRecordInvio(const TRectype& rec);
};
#endif