campo-sirio/include/files.cpp

731 lines
16 KiB
C++
Raw Normal View History

#include <stdio.h>
#include <files.h>
#include <utility.h>
#include <config.h>
#ifndef FOXPRO
#include <expr.h>
#include <applicat.h>
#else
#include <strings.h>
#endif
#include <extcdecl.h>
#include <lffiles.h>
#define BLOCKLEN 512
#define INVFLD 255
HIDDEN char _files_tmp_string[256];
TFile::TFile (int lenrec, int base)
{
_file = new SecDef;
// if (_file == NULL) fatal_box ("Can't allocate record file ");
_file->IOR = NOERR;
_len = lenrec;
_base = base;
_file->LockMode = _manulock;
_file->lpos = -1;
_file->name[0] = '\0';
}
TFile::~TFile ()
{
delete _file;
}
// @doc EXTERNAL
// @mfunc Apre il file specificato
void TFile::open (
const char *name, // @parm Nome del file da aprire
TFilelock lockmode) // @parm Tipo di lock da attivare durante l'apertura del file
// (default _manulock)
{
COpen (_file, (char *) name, _len, _base, lockmode);
}
bool TFile::verify (const char *name)
{
CVerify (_file, (char *) name);
return _file->IOR == NOERR;
}
// @doc EXTERNAL
// @mfunc Crea il file specificato
void TFile::create (
const char *name, // @parm Nome del file da creare
TRecnotype nrecord) // @parm Numero di recird che deve avere il file al momento
// della creazione (default 0)
// @comm Il file creato avra' dimensioni sufficienti a contenere <p nrecord> record
{
CCreate (_file, (char *) name, _len, _base, (nrecord * _len) / BLOCKLEN + 1);
}
void TFile::chsize (const char *name, TRecnotype nrecord)
{
CChsize (_file, (char *) name, _len, _base, (nrecord * _len) / BLOCKLEN + 1);
}
void TFile::close ()
{
CClose (_file);
}
void TFile::unlink (const char *name)
{
CDelete (_file, (char *) name);
}
// @doc EXTERNAL
// @mfunc Legge un record dal file
void TFile::read (
char *record, // @parm Record letto
TRecnotype recnum, // @parm Numero del record da leggere
TReclock lock) // @parm Tipo di blocco da attivare durante la letture (default _nolock)
{
_file->LenRec = _len;
_file->BaseFil = _base;
CRead (_file, record, recnum, lock);
}
// @doc EXTERNAL
// @mfunc Scrive un record sul file
void TFile::write (
char *record, // @parm Record da scrivere
TRecnotype recnum, // @parm Numero del record da scrivere
TReclock lock) // @parm Tipo di blocco da attivare durante la letture (default _nolock)
{
_file->LenRec = _len;
_file->BaseFil = _base;
CWrite (_file, record, recnum, lock);
}
int TFile::status () const
{
return _file->IOR;
}
TDir::TDir () : _num(-1), _com(FALSE)
{
_dir = new FileDes;
if (_dir == NULL)
fatal_box ("Can't allocate dir");
zero ();
}
TDir::TDir(const TDir & d)
{
_dir = new FileDes;
*_dir = *d._dir;
_num = d._num;
_com = d._com;
}
TDir::~TDir ()
{
delete _dir;
}
const char *TDir::name () const
{
return _dir->SysName;
}
const char *TDir::filename () const
{
strcpy(_files_tmp_string, CAddPref(_dir->SysName));
for (int i=strlen(_files_tmp_string); i>0; i--)
{
const char c = _files_tmp_string[i-1];
if (c == '\\' || c == '/')
{
strcat(_files_tmp_string, ".dbf");
break;
}
else
if (c == '.')
break;
}
return _files_tmp_string;
}
void TDir::set_name (const char * name)
{
CHECK(name != NULL, "NULL Filename");
CHECK(strlen(name) < 42, "Name too long");
for (int i=strlen(name); i>0; i--)
{
char c = name[i-1];
if (c == '\\' || c == '/')
break;
else
if (c == '.')
c = '\0';
break;
}
strncpy(_dir->SysName, name, 42);
_dir->SysName[41] = '\0';
}
const char *TDir::des () const
{
return _dir->Des;
}
const char* TDir::tab_des(const char* tab)
{
const char* t = tab; if (t[0] == '$' || t[0] == '%') t++;
TString256 tmp;
tmp << DESCDIR << "/d" << t << ".des";
#ifndef FOXPRO
TConfig cnf(tmp, DESCTAB);
t = cnf.get("Description", NULL, -1, tab);
#endif
return strcpy(__tmp_string, t);
}
const char *TDir::expr () const
{
return _dir->FCalc;
}
TRecnotype & TDir::eod () const
{
return _dir->EOD;
}
TRecnotype & TDir::eox () const
{
return _dir->EOX;
}
long& TDir::flags () const
{
return _dir->Flags;
}
word & TDir::len () const
{
return (word &) _dir->LenR;
}
int TDir::status (TDirtype dirop) const
{
return fdir[dirop].IOR;
}
void TDir::set_len (const UINT16 len)
{
_dir->LenR = len;
}
void TDir::set_eox (const RecNoType eox)
{
_dir->EOX = eox;
}
void TDir::set (const char *name, const RecNoType eod, const RecNoType flag, const char *des, const char *calc)
{
strncpy (_dir->SysName, name, sizeof (_dir->SysName));
_dir->EOD = eod;
_dir->Flags = flag;
strncpy (_dir->Des, des, sizeof (_dir->Des));
strncpy (_dir->FCalc, calc, sizeof (_dir->FCalc));
}
// @doc EXTERNAL
// @mfunc Aggiorna l'oggetto TDir con i parametri del file
void TDir::get (
int nfile, // @parm Numero del file con cui aggiornare l'oggetto
TReclock lock, // @parm Tipo di blocco (default _nolock)
TDirtype dirtype, // @parm Direttorio nella quale e' contenuto il file (default _nordir)
TDirop op) // @parm Tipo di operazioni effettuabili sul file (default _nordirop)
{
int whichdir = (dirtype == _nordir ? NORDIR : COMDIR);
if (op == _nordirop)
COpenFile (nfile, _dir, int(lock), whichdir);
else
CGetFile (nfile, _dir, int(lock), whichdir);
_num = nfile;
_com = _dir->SysName[0] != '$';
}
// @doc EXTERNAL
// @mfunc Aggiorna il file indicato con i parametri passati
void TDir::put (
int nfile, // @parm Numero del file da aggiornare
TDirtype dirtype, // @parm Direttorio nella quale e' contenuto il file (default _nordir)
TDirop op) // @parm Tipo di operazioni effettuabili sul file (default _nordirop)
{
CHECKD(nfile > 0, "Bad file number ", nfile);
const int whichdir = (dirtype == _nordir ? NORDIR : COMDIR);
if (op == _nordirop)
CCloseFile (nfile, _dir, whichdir);
else
CPutFile (nfile, _dir, whichdir);
}
void TDir::zero ()
{
zerofdes (_dir);
}
void TDir::print_on (ostream & out) const
{
CHECK(_dir,"Can't print a NULL _dir");
out << _num << '\n';
out << (int)_com << '\n';
out << _dir->SysName << '|';
out << _dir->EOD << '|';
out << _dir->EOX << '|';
out << _dir->LenR << '|';
out << _dir->Flags << '|';
out << _dir->Des << '|';
out << _dir->FCalc << '|';
out << _dir->GenPrompt << '|' << '\n';
}
void TDir::read_from (istream & in)
{
CHECK(_dir,"Can't read into a NULL _dir");
in.getline (_files_tmp_string, sizeof (_files_tmp_string), '\n');
_num = atoi(_files_tmp_string);
in.getline (_files_tmp_string, sizeof (_files_tmp_string), '\n');
_com = atoi(_files_tmp_string) != 0;
in.getline (_files_tmp_string, sizeof (_files_tmp_string), '\n');
TToken_string line(_files_tmp_string,'|');
line.restart();
strcpy(_dir->SysName,line.get());
_dir->EOD = line.get_long();
_dir->EOX = line.get_long();
_dir->LenR = line.get_int();
_dir->Flags = line.get_long();
strcpy(_dir->Des,line.get());
strcpy(_dir->FCalc,line.get());
strcpy(_dir->GenPrompt,line.get());
}
// @doc EXTERNAL
// @mfunc Ritorna il numero di file presenti nella directory <p dirtype>
//
// @rdesc Ritorna il numero di file presenti
int TDir::items (
TDirtype dirtype) const // @parm Directory della quale contare i file
{
FileDes f;
int _whichdir = (dirtype == _nordir ? NORDIR : COMDIR);
CGetFile (1, &f, _nolock, _whichdir);
return (int) f.EOD;
}
TTrec::TTrec ()
: _des(NULL), _tab("")
{
_rec = new RecDes;
zero ();
_num = -1;
}
TTrec::TTrec(const TTrec & r)
: _des(NULL), _tab("")
{
_rec = new RecDes;
*_rec = *r._rec;
_num = r._num;
}
TTrec::~TTrec ()
{
delete _rec;
}
int TTrec::compare(const TSortable & a) const
{
const TTrec & r = (const TTrec &) a;
int res = 0;
if (_rec->NFields != r._rec->NFields || _rec->NKeys != r._rec->NKeys) // Confronta prima il numero dei campi o il numero delle chiavi
res = 1;
else
{
const int nkeys = _rec->NKeys;
for (int i=0; i<nkeys && res==0; i++) // scorre la lista delle chiavi (sono meno del numero di campi)
{
const KeyDes& k1 = _rec->Ky[i];
const KeyDes& k2 = r._rec->Ky[i];
if (k1.DupKeys != k2.DupKeys || k1.NkFields != k2.NkFields)
res = 1;
else
for (int j=0; j<k1.NkFields && res==0; j++)
if (k1.FieldSeq[j] != k2.FieldSeq[j] || k1.FromCh[j] != k2.FromCh[j]
|| (k1.FromCh[j] != INVFLD && k1.ToCh[j] != k2.ToCh[j]))
res = 1;
}
if (res == 0) // se sono ancora uguali confronta tutti i campi
{
const int nflds = _rec->NFields;
for (int n=0; n<nflds && res==0; n++)
{
const RecFieldDes& r1 = _rec->Fd[n];
const RecFieldDes& r2 = r._rec->Fd[n];
if (r1.TypeF != r2.TypeF || r1.Len != r2.Len || r1.Dec != r2.Dec)
res = 1;
else
if (strcmp(r1.Name,r2.Name) != 0)
res = 1;
}
}
}
return res;
}
void TTrec::rehash()
{
int pos, tmppos, nf, i;
for (i = 0; i < MaxFields; i++) _rec->SortFd[i] = INVFLD;
if (_rec->NFields)
{
for (i = 0; i < _rec->NFields; i++)
{
nf = i;
pos = hashfun(_rec->Fd[nf].Name);
while (TRUE)
{
if (_rec->SortFd[pos] == INVFLD)
{
_rec->SortFd[pos] = (byte) nf;
break;
}
else
{
if (strcmp(_rec->Fd[_rec->SortFd[pos]].Name, _rec->Fd[nf].Name) <= 0)
{
pos++;
if (pos >= MaxFields)
pos = 0;
}
else
{
tmppos = _rec->SortFd[pos];
_rec->SortFd[pos] = (byte) nf;
nf = tmppos;
}
}
}
}
_rec->Fd[0].RecOff = 1;
for (i = 1; i < _rec->NFields; i++)
_rec->Fd[i].RecOff = _rec->Fd[i - 1].RecOff + _rec->Fd[i - 1].Len;
}
}
TTrec & TTrec::operator = (const TTrec & b)
{
_num = b._num;
memcpy (_rec, b._rec, sizeof (*_rec));
return *this;
}
// @doc EXTERNAL
// @mfunc Assegna all'oggetto TTrec il tracciato record del file indicato
void TTrec::get (
int nfile, // @parm Numero del file da cui estrarre il tracciato record
TDirtype dirtype) // @parm Direttorio nella quale e' contenuto il file (default _nordir)
{
int _whichdir = (dirtype == _nordir ? NORDIR : COMDIR);
CGetRec (nfile, _rec, _whichdir);
_num = nfile;
}
// @doc EXTERNAL
// @mfunc Setta il file indicato con il tracciato record dell'oggetto
void TTrec::put (
int nfile, // @parm Numero del file di cui settare il tracciato record
TDirtype dirtype) // @parm Direttorio nella quale e' contenuto il file (default _nordir)
{
int _whichdir = (dirtype == _nordir ? NORDIR : COMDIR);
if (nfile <= 0)
fatal_box ("Bad file number %d", nfile);
CPutRec (nfile, _rec, _whichdir);
}
void TTrec::zero ()
{
_rec->NFields = 0;
for (int i = 0; i < MaxFields; i++)
{
strcpy(_rec->Fd[i].Name, "");
_rec->Fd[i].TypeF = _nullfld;
_rec->Fd[i].Len = 0;
_rec->Fd[i].Dec = 0;
_rec->Fd[i].RecOff = 0;
_rec->SortFd[i] = INVFLD;
}
_rec->NKeys = 0;
for (i = 1; i < MaxKeys; i++)
{
_rec->Ky[i].DupKeys = FALSE;
_rec->Ky[i].NkFields = 0;
for (int j = 0; j < MKFields; j++)
{
_rec->Ky[i].FieldSeq[j] = INVFLD;
_rec->Ky[i].FromCh[j] = INVFLD;
_rec->Ky[i].ToCh[j] = INVFLD;
}
}
}
int TTrec::status (TDirtype dirop) const
{
return rdir[dirop].IOR;
}
int TTrec ::field (const char *name) const
{
return findfld (_rec, (char *) name);
}
const char *TTrec ::fielddef (int fld) const
{
sprintf (_files_tmp_string, "%s|%d|%d|%d", _rec->Fd[fld].Name,
(int) _rec->Fd[fld].TypeF, (int) _rec->Fd[fld].Len,
(int) _rec->Fd[fld].Dec);
return _files_tmp_string;
}
const char *TTrec ::keydef (int key) const
{
TFixed_string s (_files_tmp_string, 128);
s = "";
for (int j = 0; j < _rec->Ky[key].NkFields; j++)
{
const bool upper = _rec->Ky[key].FieldSeq[j] > MaxFields;
const int nfld = _rec->Ky[key].FieldSeq[j] - (upper ? MaxFields : 0);
if (j)
s << "+";
if (upper)
s << "UPPER(";
s << _rec->Fd[nfld].Name;
if (_rec->Ky[key].FromCh[j] < INVFLD)
s << format ("[%d,%d]", _rec->Ky[key].FromCh[j] + 1,
_rec->Ky[key].ToCh[j] + 1);
if (upper)
s << ")";
}
s << (_rec->Ky[key].DupKeys ? "|X" : "| ");
return (const char *) s;
}
#ifndef FOXPRO
bool TDir::is_active () const
{
const int module = abs((int)flags());
return main_app().has_module(module, CHK_DONGLE);
}
void TTrec::update_fielddef (int nfld, const char *desc)
{
TToken_string s (desc);
strcpy (_rec->Fd[nfld].Name, s.get ());
_rec->Fd[nfld].TypeF = s.get_int ();
_rec->Fd[nfld].Len = s.get_int ();
_rec->Fd[nfld].Dec = s.get_int ();
}
void TTrec::update_keydef (int key, const char *desc)
{
TExpression expr ("", _strexpr);
TToken_string s (desc);
TString ke (s.get ());
if (expr.set ((const char *) ke, _strexpr))
{
const char * dup = s.get();
_rec->Ky[key].DupKeys = (dup && *dup != ' ');
TCodearray & c = expr.code ();
c.begin ();
int n = 0;
while (!c.end ())
{
TCode & inst = c.step ();
TCodesym sym = inst.getsym ();
if (sym == _variable)
{
const char *s = inst.string ();
for (int i = 0; i < _rec->NFields; i++)
if (strcmp (_rec->Fd[i].Name, s) == 0)
break;
_rec->Ky[key].FieldSeq[n] = i;
_rec->Ky[key].FromCh[n] = INVFLD;
_rec->Ky[key].ToCh[n] = INVFLD;
inst = c.step ();
sym = inst.getsym ();
if (sym == _upper)
_rec->Ky[key].FieldSeq[n] += MaxFields;
else if (sym == _number)
{
_rec->Ky[key].FromCh[n] = (int)inst.number().integer() - 1;
inst = c.step ();
_rec->Ky[key].ToCh[n] = _rec->Ky[key].FromCh[n] + (int)inst.number ().integer () - 1;
inst = c.step ();
}
else
c.backtrace ();
n++;
}
}
_rec->Ky[key].NkFields = n;
}
}
void TTrec::print_on (ostream & out) const
{
const int n = num();
out << n;
if (_des && n>=LF_TABGEN && n<=LF_TAB && _tab.not_empty()) // Solo se e' una tabella...
out << "|" << _tab;
out << '\n';
const int nfields = fields ();
TToken_string s (80);
out << nfields << '\n';
for (int i = 0; i < nfields; i++)
{
s = fielddef (i);
out << s ;
if (_des)
out << "|" << _des->get(_rec->Fd[i].Name);
out << '\n';
}
const int nkeys = keys ();
out << nkeys << '\n';
for (i = 0; i < nkeys; i++)
{
s = keydef (i);
out << s << '\n';
}
}
void TTrec::read_from (istream & in)
{
int ln;
const int n = num();
in.getline (_files_tmp_string, sizeof (_files_tmp_string), '\n');
if (_des && n>=LF_TABGEN && n<=LF_TAB)
{
TString t(_files_tmp_string);
if (t.find('|')>-1)
{
TString tabname(t.right(3));
strcpy(_files_tmp_string,t.left(t.len()-4)); // Toglie il nome della tabella
if (_tab != tabname && !yesno_box("Descrizione relativa alla tabella %s.\n Continuo ?",(const char*) tabname))
return;
}
}
ln = atoi (_files_tmp_string);
if (ln != n && !yesno_box ("Descrizione relativa al file n.ro %d.\n Continuo ?", ln))
return;
int nfields;
in.getline (_files_tmp_string, sizeof (_files_tmp_string), '\n');
nfields = atoi (_files_tmp_string);
set_fields (nfields);
TToken_string t;
for (int i = 0; i < nfields; i++)
{
in.getline (_files_tmp_string, sizeof (_files_tmp_string), '\n');
t = _files_tmp_string;
const int itms = t.items();
update_fielddef (i, _files_tmp_string);
if (_des && itms == 5) // La descrizione viene caricata solo se esiste
_des->set(_rec->Fd[i].Name, t.get(itms-1));
}
int nkeys;
in.getline (_files_tmp_string, sizeof (_files_tmp_string), '\n');
nkeys = atoi (_files_tmp_string);
set_keys (nkeys);
for (i = 0; i < nkeys; i++)
{
in.getline (_files_tmp_string, sizeof (_files_tmp_string), '\n');
update_keydef (i, _files_tmp_string);
}
rehash ();
_des = NULL;
_tab = "";
}
#endif // FOXPRO