campo-sirio/include/isam.cpp
guy 76719be75d isam.cpp Aggiunta funzione per costruire la stringa chiave da un record
isam.h       Aggiunti prototipo funzione precedente
maskfld.h    Aggiunta funzione per settare il modo di trim dei campi
relation.cpp Aggiunto codice di debug nella TRecord_array::remove_from


git-svn-id: svn://10.65.10.50/trunk@2125 c028cbd2-c16b-5b4b-a496-9718f37d4682
1995-11-10 13:37:28 +00:00

2892 lines
64 KiB
C++
Executable File

#include <stdio.h>
#include <stdlib.h>
#define __ISAM_CPP
#ifndef FOXPRO
#include <applicat.h>
#include <expr.h>
#include <execp.h>
#include <progind.h>
#endif
#include <config.h>
#include <extcdecl.h>
#include <mailbox.h>
#include <prefix.h>
#include <relation.h>
#include <scanner.h>
#include <utility.h>
#include <memo.h>
#include <codeb.h>
#if XVT_OS==XVT_OS_WIN
#include <process.h>
#else
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
#define NOT_OPEN() CHECKS(_isamfile != NULL, "File chiuso: ", (const char*)name())
//#define INTTLOCK 0x600
#define RECLOCKTYPES 0xFF00
#define READTYPES 0x00FF
isfdptr* openf;
Str80 cprefix;
HIDDEN int error_codes_g[] = {-1,_isnotopen,-1,-1,-1,_islocked,-1,-1,-1,-1,-1,-1,_isfilefull,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,_iskeynotfound,_ispatherr,-1,-1,_isdupkey};
HIDDEN int error_codes_ra[] = {NOERR,NOERR,_iskeynotfound,_iseof,_isbof,_isnrecerr} ;
// Codici da 0 a 9
HIDDEN int error_codes_rb[] = {-1,-1,_isreinsert,-1,-1,_islocked,-1,_isalropen,_iskeyerr } ;
// Codici da 10 a ...
extern "C" {
void CUpString(char*);
void crtrim(char*);
};
HIDDEN char _isam_string[257];
HIDDEN void UNKNOWN_FIELD(int num, const char* name)
{ yesnofatal_box("Il campo '%s' non appartiene al file %d", name, num); }
#define NOALLOC (char **) -1
HIDDEN bool __autoload = TRUE;
////////////////////////////////////////////////////////////////////////////////////////////////////
// Funzioni implementate per la gestione file dati tramite Codebase
////////////////////////////////////////////////////////////////////////////////////////////////////
// Inizio(@)
void get_idx_names(int logicnum, TToken_string& i_names) // Returns a Token_string with the index names. (Current prefix!)
{
long c = DB_getconf();
TDir d;
TTrec r;
d.get(logicnum);
r.get(logicnum);
TFilename f(d.name());
if ( c & 1) f.ext("cdx");
if ( c & 4) f.ext("mdx");
i_names.cut(0);
i_names.add(f);
f.ext("");
f.rtrim(1);
if (c & 2 || c & 8) // DBIII or CLIPPER format, returns f_name + .cgp, f_nameX + .n{d|t}x
for (int j=1; j<=r.keys();j++)
{
TString xx=f.name();
if (xx.len()<8)
f << ('0' + j);
else
f[8] = ('0' + j);
if (c & 2) // CLIPPER
f.ext("ndx");
else // DBIII
f.ext("ntx");
i_names.add(f);
}
i_names.restart();
}
int get_error(int err)
{
if (err > 0)
{
if (err >= 10)
{
if (err > 80 || error_codes_rb[err/10]==-1) return err;
else
return(error_codes_rb[err/10]);
}
else
return(error_codes_ra[err]);
}
else
if (err < 0)
{
int ierr = DB_get_error();
if (ierr < 0) ierr = -ierr;
if (ierr > 340 || error_codes_g[ierr/10]==-1)
return (-ierr);
return (error_codes_g[ierr/10]);
}
DB_zero_error();
return(NOERR);
}
HIDDEN void browse_null(char *start, int nc)
{
for (int i = nc - 1; i >= 0 ; i--) // Anche il primo byte(deletion flag) deve essere cambiato. nc comprende il primo byte
if (start[i] == '\0') start[i] = ' ';
}
HIDDEN void getisfd(isfdptr & isfd, int logicnum)
{
isfd = new isdef ;
isfd->r = new RecDes ;
isfd->d = new FileDes ;
CGetFile(logicnum, isfd->d, _nolock, _nordir);
const TFixed_string name(isfd->d->SysName);
if (name.not_empty() && name[0] != '$')
isfd->ft = _comdir;
else
isfd->ft = _nordir;
COpenFile(logicnum, isfd->d, _nolock, isfd->ft);
CGetRec(logicnum, isfd->r, isfd->ft);
isfd->ln = logicnum;
}
HIDDEN void relisfd(isfdptr & isfd)
{
if (isfd->ln > 0 && isfd->fhnd >= 0)
{
TDir d;
d.get(isfd->ln, _lock, (TDirtype) isfd->ft, _sysdirop);
d.eod() = isfd->d->EOD;
d.eox() = isfd->d->EOX;
d.put(isfd->ln, (TDirtype) isfd->ft, _sysdirop);
}
delete isfd->d;
delete isfd->r;
delete isfd;
#ifdef DBG
isfd = NULL; // Per provocare errori
#endif
}
HIDDEN int CBuildKey(RecDes *recd, int numkey, RecType recin, char *key, bool build_x_cb)
/* *recd; descrittore record */
/* numkey; numero chiave */
/* recin; buffer contenente il record */
/* *key; valore della chiave */
/* build_x_cb flag di costruzione per codebase */
{
key[0] = '\0';
if (numkey-- <= recd->NKeys)
{
int l = 0;
for (int i = 0; i < recd->Ky[numkey].NkFields; i++)
{
const KeyDes& kd = recd->Ky[numkey];
const bool upp = kd.FieldSeq[i] > MaxFields;
const int nf = upp ? kd.FieldSeq[i] - MaxFields : kd.FieldSeq[i];
const RecFieldDes& rf = recd->Fd[nf];
int off, len;
if (kd.FromCh[i] == 255)
{
off = rf.RecOff;
len = rf.Len;
}
else
{
off = rf.RecOff + kd.FromCh[i];
len = kd.ToCh[i] - kd.FromCh[i] + 1;
}
if ((l + len) > 80)
{
key[0] = '\0';
return(_iskeylenerr);
}
strncpy((key + l), (recin + off), len);
const TFieldtypes f = (TFieldtypes) rf.TypeF;
if (recin[off] == '\0')
{
memset(key + l, ' ', len);
if (build_x_cb && ((f == _intfld) || (f == _longfld) || (f == _wordfld) ||
(f == _intzerofld) || (f == _longzerofld)))
key[l + len - 1] = '0';
}
else
if ((f == _intfld) || (f == _longfld) || (f == _wordfld) || (f == _intzerofld) || (f == _longzerofld))
{
int w = l, j = l + len;
while (w < j && key[w] == ' ') w++;
while (w < j && key[w] == '0') key[w++] = ' ';
if (build_x_cb && (w == j)) key[w-1] = '0';
}
if (upp)
for (int i = l+len-1; i >= l; i--)
key[i] = toupper(key[i]);
l += len;
}
while (l > 0 && key[l-1] == ' ') l--;
key[l] = '\0';
return(NOERR);
}
return(_ispatherr);
}
HIDDEN int cisstart(isfdptr isfd, int keynum, TRectype & record, unsigned int mode)
{
// It seems quite unuseful... Quando cambio la chiave con setkey, la d4tagselect
// seleziona gia' l'indice, rendendo inutile il senso della cisstart
return NOERR;
}
HIDDEN int cisread(isfdptr isfd, TRectype & record, int mode)
{
int rmode = (mode & READTYPES), lmode = (mode & RECLOCKTYPES);
// Non usare mai _isnextn o _isprevn, usare il metodo skip!
CHECK (rmode !=_isnextn && rmode !=_isprevn, "_isnextn and _isprevn not supported in cisread");
char key[128];
int err = NOERR ;
do
{
if (rmode>=_isequal && rmode<=_isgteq)
{
err=CBuildKey(isfd->r, isfd->knum, record.string(),key,TRUE);
if (err == NOERR)
{
err = DB_seek(isfd->fhnd,key);
if (rmode == _isgreat && err == NOERR)
err = DB_next(isfd->fhnd);
if (err != NOERR)
err = get_error(err);
}
if (rmode != _isequal && err == _iskeynotfound)
err = NOERR;
}
else
{
if (rmode==_isfirst)
err=DB_first(isfd->fhnd); else
if (rmode==_islast)
err=DB_last(isfd->fhnd); else
if (rmode==_isnext)
err=DB_next(isfd->fhnd); else
if (rmode==_isprev)
err=DB_prev(isfd->fhnd); else
if (rmode==_iscurr)
err=DB_go(isfd->fhnd,DB_recno(isfd->fhnd));
if (err != NOERR) err=get_error(err);
}
if (err == _iseof)
DB_last(isfd->fhnd);
if (err == NOERR && (lmode == _lock || lmode == _testandlock)) // _lock e _testandlock
{
err=DB_lock(isfd->fhnd);
if (err != NOERR) err=get_error(err);
if (err == _islocked && lmode == _testandlock) break;
}
if (err == _islocked)
{
memcpy(record.string(),DB_getrecord(isfd->fhnd),DB_reclen(isfd->fhnd));
CBuildKey(isfd->r, isfd->knum, record.string(), key, TRUE);
message_box("Codice %s in uso da parte\ndi un altro utente.", key);
}
} while (err ==_islocked);
if (err == NOERR && lmode == _unlock)
{
err=DB_unlock(isfd->fhnd);
if (err != NOERR) err=get_error(err);
}
memcpy(record.string(),DB_getrecord(isfd->fhnd),DB_reclen(isfd->fhnd));
isfd->RecNo = DB_recno(isfd->fhnd);
return err;
}
HIDDEN int delkeys(isfdptr fd, char* record,long recno)
{
int rt=NOERR,oldkey = fd->knum;
for (int i=1; i<=fd->r->NKeys;i++)
{
char key[128];
DB_tagselect(fd->fhnd,i);
rt=CBuildKey(fd->r,i,record,key,TRUE);
if (rt!=NOERR) break;
rt=DB_delkey(fd->fhnd,key,recno);
if (rt!=NOERR) break;
}
DB_tagselect(fd->fhnd,oldkey);
return(rt);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Funzioni implementate per la gestione file dati tramite Codebase
////////////////////////////////////////////////////////////////////////////////////////////////////
// Fine(@)
void set_autoload_new_files(bool on)
{
__autoload = on;
}
///////////////////////////////////////////////////////////
// TExtrectype
///////////////////////////////////////////////////////////
class TExtrectype : public TRectype
{
RecDes* _rd;
protected: // TRectype
virtual RecDes* rec_des() const { return _rd; }
public:
// FPUB
TExtrectype(const TTrec& r); // Costruisce il record a partire da r
virtual ~TExtrectype() {}
};
TExtrectype::TExtrectype(const TTrec& r) : TRectype(6)
{
delete _rec;
_length = r.len();
_rec = new char [ _length ];
_rd = r.rec();
zero();
}
///////////////////////////////////////////////////////////
// TBaseisamfile
///////////////////////////////////////////////////////////
TBaseisamfile::TBaseisamfile(int logicnum, bool linkrecinst)
{
_isamfile = NULL;
_logicnum = logicnum;
_lasterr = NOERR;
_delopenrec = FALSE;
if ((openrec[_logicnum - 1] == NULL) || (!linkrecinst))
{
_current = new TRectype(this);
if (openrec[_logicnum - 1] == NULL)
{
openrec[_logicnum - 1] = _current;
_delopenrec = TRUE;
}
_delrec = TRUE;
}
else
{
_current = openrec[_logicnum - 1];
_delrec = FALSE;
}
// _historicfile = ((r.field(RFLD_SYS_DATE) != FIELDERR) &&
// (r.field(RFLD_SYS_FIRST) != FIELDERR) &&
// (r.field(RFLD_SYS_LAST) != FIELDERR));
_historicfile = FALSE;
}
TBaseisamfile::~TBaseisamfile()
{
if (_delrec)
{
if (_delopenrec)
openrec[_logicnum - 1] = NULL;
delete _current;
}
if (_isamfile != NULL)
delete _isamfile;
}
int TBaseisamfile::gethr(TRectype& rec, TDate& atdate)
{
TRecfield fd0(rec, RFLD_SYS_DATE);
TDate d0((const TDate&) fd0);
if (d0 < atdate)
{
atdate = eotime;
return NOERR;
}
TRectype wr(rec);
TRecfield flf(wr, RFLD_SYS_FIRST),
fll(wr, RFLD_SYS_LAST),
fd1(wr, RFLD_SYS_DATE);
TDate d1;
TRecnotype wr0 = -1L, wr1 = -1L;
if ((wr0 == flf.ptr()) == -1L) return _iskeynotfound;
_hf.read(wr.string(), wr0);
if ((d1 = (const TDate&) fd1) > atdate)
{
rec = wr;
atdate = d0 - 1L;
return _iskeynotfound;
}
while ((d1 < atdate) && (wr0 > 0))
{
rec = wr;
wr1 = wr0;
if ((wr0 = fll.ptr()) > 0)
{
_hf.read(wr.string(), wr0);
d1 = (const TDate&) fd1;
}
}
if (wr0 <= 0)
atdate = d0 - 1L;
else
atdate = d1 - 1L;
return NOERR;
}
int TBaseisamfile::addhr(const TRectype& rec, TDate& atdate)
{
return NOERR;
}
int TBaseisamfile::rewhr(const TRectype& rec, TDate& atdate)
{
return NOERR;
}
int TBaseisamfile::delhr(const TRectype& rec, TDate& atdate)
{
return NOERR;
}
long TBaseisamfile::items() const
{
return(DB_reccount(filehnd()->fhnd));
}
const char* TBaseisamfile::name() const
{
sprintf(_isam_string, "%d", num());
return _isam_string;
}
const char* TBaseisamfile::filename() const
{
if (_isamfile == NULL)
{
TDir d;
d.get(num());
strcpy(_isam_string, d.filename());
}
else
{
strcpy(_isam_string, _isamfile->d->SysName);
strcat(_isam_string, ".dbf");
}
return _isam_string;
}
const char* TBaseisamfile::description() const
{
if (_isamfile == NULL)
{
TDir d;
d.get(num());
strcpy(_isam_string, d.des());
return _isam_string;
}
return _isamfile->d->Des;
}
TRecnotype TBaseisamfile::eod() const
{
NOT_OPEN();
return(DB_reccount(_isamfile->fhnd));
}
void TBaseisamfile::setkey(int nkey)
{
CHECKD(nkey > 0 && nkey-1 <= _isamfile->r->NKeys, "Chiave non valida ", nkey);
NOT_OPEN();
int rt = DB_tagselect(_isamfile->fhnd,nkey);
if (rt>=0) _isamfile->knum=nkey;
if (rt!=NOERR) rt=get_error(rt);
if (_lasterr == NOERR) setstatus(rt);
}
int TBaseisamfile::getkey() const
{
NOT_OPEN();
CHECK(DB_tagget(_isamfile->fhnd) == _isamfile->knum, "Chiave inconsistente");
return _isamfile->knum;
}
int TBaseisamfile::first(word lockop)
{
NOT_OPEN();
curr().setdirty();
_lasterr=cisread(_isamfile, curr(), _isfirst + lockop);
if (_lasterr != NOERR) _lasterr = get_error(_lasterr);
_recno = _isamfile->RecNo;
return _lasterr;
}
int TBaseisamfile::last(word lockop)
{
NOT_OPEN();
curr().setdirty();
_lasterr=cisread(_isamfile, curr(), _islast + lockop );
if (_lasterr != NOERR) _lasterr = get_error(_lasterr);
_recno = _isamfile->RecNo;
return _lasterr;
}
int TBaseisamfile::next(word lockop)
{
NOT_OPEN();
curr().setdirty();
if (_recno != DB_recno(_isamfile->fhnd))
{
_lasterr = cisread(_isamfile, curr(), _isgteq + lockop);
if (_lasterr != NOERR)
{
_lasterr = get_error(_lasterr);
if (_lasterr != _islocked && _lasterr != _iseof)
fatal_box("Errore nella next %d : non posso riposizionarmi", _lasterr);
}
}
else
{
_lasterr=cisread(_isamfile, curr(), _isnext + lockop);
if (_lasterr != NOERR) _lasterr = get_error(_lasterr);
}
_recno = _isamfile->RecNo;
return _lasterr;
}
int TBaseisamfile::next(TDate& atdate)
{
error_box("TBaseisamfile::next(TDate&) is no more available");
return NOERR;
}
int TBaseisamfile::prev(word lockop)
{
NOT_OPEN();
curr().setdirty();
if (_recno != DB_recno(_isamfile->fhnd))
{
_lasterr = DB_go(_isamfile->fhnd, _recno);
if (_lasterr != NOERR)
{
_lasterr = get_error(_lasterr);
if (_lasterr != _islocked)
fatal_box("Errore nella prev %d : non posso riposizionarmi", _lasterr);
}
}
_lasterr=cisread(_isamfile, curr(), _isprev + lockop);
if (_lasterr != NOERR) _lasterr = get_error(_lasterr);
_recno = _isamfile->RecNo;
return _lasterr;
}
int TBaseisamfile::prev(TDate& atdate)
{
error_box("TBaseisamfile::prev(TDate&) is no more available");
return NOERR;
}
int TBaseisamfile::reread(word lockop, TDate& atdate)
{
NOT_OPEN();
curr().setdirty();
_lasterr=cisread(_isamfile, curr(), _iscurr + lockop);
if (_lasterr != NOERR) _lasterr = get_error(_lasterr);
_recno = _isamfile->RecNo;
return _lasterr;
}
int TBaseisamfile::reread(TRectype& rec, word lockop, TDate& atdate)
{
NOT_OPEN();
rec.setdirty();
_lasterr=cisread(_isamfile, rec, _iscurr + lockop);
if (_lasterr != NOERR) _lasterr = get_error(_lasterr);
_recno = _isamfile->RecNo;
return _lasterr;
}
int TBaseisamfile::skip(TRecnotype nrec, word lockop)
{
char key[128];
NOT_OPEN();
if (!nrec) return NOERR;
curr().setdirty();
if (_recno != DB_recno(_isamfile->fhnd))
{
_lasterr = DB_go(_isamfile->fhnd, _recno);
if (_lasterr != NOERR)
{
_lasterr = get_error(_lasterr);
if (_lasterr != _islocked)
fatal_box("Errore nella skip %d : non posso riposizionarmi", _lasterr);
}
}
_lasterr=DB_skip(_isamfile->fhnd,nrec);
if (_lasterr != NOERR) _lasterr = get_error(_lasterr);
do {
if (_lasterr == _islocked)
{
CBuildKey(_isamfile->r, DB_tagget(_isamfile->fhnd), curr().string(), key,TRUE);
message_box("Codice %s in uso da parte\ndi un altro utente.", key);
}
_lasterr=cisread(_isamfile,curr(),_iscurr + lockop);
} while (_lasterr ==_islocked);
_recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd);
return _lasterr;
}
int TBaseisamfile::read(word op, word lockop, TDate& atdate)
{
CHECKD(op >= _iscurr && op <= _isgteq, "Invalid read operation : ", op);
NOT_OPEN();
curr().setdirty();
_lasterr=cisread(_isamfile, curr(), op + lockop);
if (_lasterr != NOERR) _lasterr=get_error(_lasterr);
_recno = _isamfile->RecNo;
return _lasterr;
}
int TBaseisamfile::read(TRectype& rec, word op, word lockop, TDate& atdate)
{
CHECKD(op >= _iscurr && op <= _isgteq, "Invalid read operation : ", op);
NOT_OPEN();
rec.setdirty();
_lasterr=cisread(_isamfile, rec, op + lockop);
if (_lasterr != NOERR) _lasterr = get_error(_lasterr);
_recno = _isamfile->RecNo;
return _lasterr;
}
int TBaseisamfile::readat(TRecnotype nrec, word lockop)
{
NOT_OPEN();
curr().setdirty();
_lasterr=DB_go(_isamfile->fhnd,nrec);
if (_lasterr != NOERR) _lasterr = get_error(_lasterr);
else
memcpy(curr().string(),DB_getrecord(_isamfile->fhnd),DB_reclen(_isamfile->fhnd));
_recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd);
return _lasterr;
}
int TBaseisamfile::readat(TRectype& rec, TRecnotype nrec, word lockop)
{
NOT_OPEN();
rec.setdirty();
_lasterr=DB_go(_isamfile->fhnd,nrec);
if (_lasterr != NOERR) _lasterr = get_error(_lasterr);
else
memcpy(rec.string(),DB_getrecord(_isamfile->fhnd),DB_reclen(_isamfile->fhnd));
_recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd);
return _lasterr;
}
int TBaseisamfile::write(TDate& atdate)
{
CHECK(!curr().empty(), "Can't write an empty record");
NOT_OPEN();
int oldkey=getkey();
browse_null(curr().string(),DB_reclen(_isamfile->fhnd));
setkey(1);
memcpy(DB_getrecord(_isamfile->fhnd),curr().string(),DB_reclen(_isamfile->fhnd));
_lasterr = DB_add(_isamfile->fhnd);
if (_lasterr != NOERR) _lasterr = get_error(_lasterr);
setkey(oldkey);
_recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd);
return _lasterr;
}
int TBaseisamfile::write(const TRectype& rec, TDate& atdate)
{
CHECK(!rec.empty(), "Can't write an empty record");
NOT_OPEN();
int oldkey=getkey();
browse_null(rec.string(),DB_reclen(_isamfile->fhnd));
setkey(1);
memcpy(DB_getrecord(_isamfile->fhnd),rec.string(),DB_reclen(_isamfile->fhnd));
_lasterr = DB_add(_isamfile->fhnd);
if (_lasterr != NOERR) _lasterr = get_error(_lasterr);
setkey(oldkey);
_recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd);
return _lasterr;
}
int TBaseisamfile::rewrite(TDate& atdate)
{
CHECK(!curr().empty(), "Can't rewrite an empty record");
NOT_OPEN();
TRectype save_rec(curr());
_lasterr = cisread(_isamfile, save_rec, _isequal + _nolock); // Si Posiziona per sicurezza...
if (_lasterr == NOERR)
{
browse_null(curr().string(),DB_reclen(_isamfile->fhnd));
memcpy(DB_getrecord(_isamfile->fhnd), curr().string(),DB_reclen(_isamfile->fhnd));
_lasterr = DB_rewrite(_isamfile->fhnd);
if (_lasterr != NOERR) _lasterr = get_error(_lasterr);
_recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd);
}
return _lasterr;
}
int TBaseisamfile::rewrite(const TRectype& rec, TDate& atdate)
{
CHECK(!rec.empty(), "Can't write an empty record");
NOT_OPEN();
TRectype save_rec(rec);
_lasterr = cisread(_isamfile, save_rec, _isequal + _nolock); // Si Posiziona per sicurezza...
if (_lasterr == NOERR)
{
browse_null(rec.string(),DB_reclen(_isamfile->fhnd));
memcpy(DB_getrecord(_isamfile->fhnd), rec.string(),DB_reclen(_isamfile->fhnd));
_lasterr = DB_rewrite(_isamfile->fhnd);
if (_lasterr != NOERR) _lasterr = get_error(_lasterr);
_recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd);
}
return _lasterr;
}
int TBaseisamfile::rewriteat(TRecnotype nrec)
{
NOT_OPEN();
if ((_lasterr=DB_go(_isamfile->fhnd,nrec))== NOERR)
{
browse_null(curr().string(),DB_reclen(_isamfile->fhnd));
memcpy(DB_getrecord(_isamfile->fhnd),curr().string(),DB_reclen(_isamfile->fhnd));
_lasterr=DB_rewrite(_isamfile->fhnd);
if (_lasterr != NOERR) _lasterr = get_error(_lasterr);
} else
_lasterr = get_error(_lasterr);
_recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd);
return _lasterr;
}
int TBaseisamfile::rewriteat(const TRectype& rec, TRecnotype nrec)
{
NOT_OPEN();
if ((_lasterr=DB_go(_isamfile->fhnd,nrec))== NOERR)
{
browse_null(rec.string(),DB_reclen(_isamfile->fhnd));
memcpy(DB_getrecord(_isamfile->fhnd),rec.string(),DB_reclen(_isamfile->fhnd));
_lasterr=DB_rewrite(_isamfile->fhnd);
if (_lasterr != NOERR) _lasterr = get_error(_lasterr);
} else
_lasterr = get_error(_lasterr);
_recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd);
return _lasterr;
}
int TBaseisamfile::remove(TDate& atdate)
{
CHECK(!curr().empty(), "Can't remove empty record");
NOT_OPEN();
// rimozione campi memo
#ifndef FOXPRO
TMemo_file* memo = NULL;
for (int i = 0; i < curr().items(); i++)
{
if (curr().type(curr().fieldname(i)) == _memofld)
{
long val = curr().get_long(curr().fieldname(i));
if (val > 0l)
{
if (memo == NULL)
memo = new TMemo_file(filename());
memo->remove_field(val);
}
}
}
if (memo != NULL) delete memo;
#endif
if ((_lasterr=cisread(_isamfile, curr(), _isequal + _nolock)) == NOERR)
{
_lasterr = DB_delete(_isamfile->fhnd); // Put only deletion flag on record, must remove keys too!
if (_lasterr != NOERR)
_lasterr = get_error(_lasterr);
else
{
_lasterr=delkeys(_isamfile,curr().string(), _isamfile->RecNo);
if (_lasterr != NOERR)
{
DB_recall(_isamfile->fhnd);
_lasterr = get_error(_lasterr);
}
}
}
_recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd);
return _lasterr;
}
int TBaseisamfile::remove(const TRectype& rec, TDate& atdate)
{
CHECK(!rec.empty(), "Can't remove an empty record");
NOT_OPEN();
memcpy(DB_getrecord(_isamfile->fhnd),rec.string(),DB_reclen(_isamfile->fhnd));
if ((_lasterr=cisread(_isamfile, (TRectype&) rec, _isequal + _nolock))==NOERR)
{
_lasterr = DB_delete(_isamfile->fhnd); // Put only deletion flag on record, must remove keys too!
if (_lasterr != NOERR)
_lasterr = get_error(_lasterr);
else
{
_lasterr=delkeys(_isamfile,rec.string(),_isamfile->RecNo);
if (_lasterr != NOERR)
{
DB_recall(_isamfile->fhnd);
_lasterr = get_error(_lasterr);
}
}
}
_recno = _isamfile->RecNo = DB_recno(_isamfile->fhnd);
return _lasterr;
}
int TBaseisamfile::lock()
{
NOT_OPEN();
_lasterr = DB_lockfile(_isamfile->fhnd);
if (_lasterr != NOERR) _lasterr = get_error(_lasterr);
return _lasterr;
}
int TBaseisamfile::unlock()
{
NOT_OPEN();
_lasterr = DB_unlock(_isamfile->fhnd);
if (_lasterr != NOERR) _lasterr = get_error(_lasterr);
return (_lasterr);
}
void TBaseisamfile::indexon()
{
}
bool TBaseisamfile::empty()
{
return (DB_reccount(_isamfile->fhnd) == 0);
}
void TBaseisamfile::indexoff()
{
}
int TBaseisamfile::_open(unsigned int mode)
{
CHECKS(filehnd() == NULL, "File already open ", (const char*)filename());
getisfd(_isamfile,num());
if ((filehnd()->fhnd = DB_open(filehnd()->d->SysName,mode==_excllock)) >= 0)
{
TRecnotype n=DB_reccount(filehnd()->fhnd);
TDir d;
d.get(num(),_nolock,_nordir,_sysdirop);
if (d.is_com()) d.get(num(),_nolock,_comdir,_sysdirop);
if ((filehnd()->d->EOD != n && n > 0) || (n > d.eox()))
{
filehnd()->d->EOD = d.eod() = n;
filehnd()->d->EOX = d.eox() = n;
if (d.is_com())
d.put(num(),_comdir,_sysdirop);
else
d.put(num(),_nordir,_sysdirop);
}
filehnd()->ln = num();
openf[num() - 1] = filehnd();
_recno = -1L;
CHECKD(filehnd()->r->NKeys > 0, "File senza indici: ", num());
setkey(1);
_lasterr = NOERR;
}
else
{
_lasterr = get_error(filehnd()->fhnd);
relisfd(_isamfile);
fatal_box("Il file %d non puo' essere aperto, errore %d",num(),_lasterr);
}
return (_lasterr);
}
int TBaseisamfile::_close()
{
int err = NOERR;
if (filehnd() != NULL)
{
if (num() > 0)
{
TDir d;
TRecnotype n=DB_reccount(filehnd()->fhnd);
d.get(num(),_nolock,_nordir,_sysdirop);
if (d.is_com()) d.get(num(),_nolock,_comdir,_sysdirop);
if ((filehnd()->d->EOD != n && n > 0) || (n > d.eox()))
{
filehnd()->d->EOD = d.eod() = n;
filehnd()->d->EOX = d.eox() = n;
if (d.is_com())
d.put(num(),_comdir,_sysdirop);
else
d.put(num(),_nordir,_sysdirop);
}
CHECK(openf[num() - 1] != NULL, "Open file array corrupted");
err=DB_close(filehnd()->fhnd);
if (err != NOERR) err = get_error(err);
if ((err == NOERR) && (num() > 0))
openf[num() - 1] = NULL ;
}
else
if (filehnd() == NULL)
{
err = _isnotopen;
error_box("File n. %d close : Error n. %d ", num(), err);
}
if (err == NOERR)
{
relisfd(_isamfile);
clearfilehnd();
}
}
setstatus(err);
return err;
}
///////////////////////////////////////////////////////////
// TLocalisamfile
///////////////////////////////////////////////////////////
// Attenzione linkrecinst puo' valere 0, 1, 2.
// Se vale 2 significa che si sta costruendo un file temporaneo
// per cui linkrecinst va' considerato FALSE
TLocalisamfile::TLocalisamfile(int logicnum, bool linkrecinst)
: TBaseisamfile(logicnum, linkrecinst == TRUE)
{
if (linkrecinst <= TRUE)
{
open();
if (_was_open)
_oldkey = getkey();
setkey(1);
}
else _was_open = FALSE;
}
TLocalisamfile::~TLocalisamfile()
{
if (_was_open)
setkey(_oldkey);
close();
}
int TLocalisamfile::close()
{
int err = NOERR;
if (!_was_open)
{
clearfilehnd();
}
else
{
if (_isamfile)
{
TRecnotype n = DB_reccount(filehnd()->fhnd);
TDir d;
d.get(num(),_nolock,_nordir,_sysdirop);
if (d.is_com()) d.get(num(),_nolock,_comdir,_sysdirop);
if ((filehnd()->d->EOD!=n && n > 0) || (n > d.eox()))
{
filehnd()->d->EOD = d.eod() = n;
filehnd()->d->EOX = d.eox() = n;
if (d.is_com())
d.put(num(),_comdir,_sysdirop);
else
d.put(num(),_nordir,_sysdirop);
}
err = DB_close(_isamfile->fhnd);
_isamfile->fhnd = -1;
if (err != NOERR) err = get_error(err);
relisfd(_isamfile);
_isamfile=NULL;
}
openf[num() -1] = NULL;
}
setstatus(err);
return err;
}
int TLocalisamfile::open(unsigned int mode)
{
int err = NOERR;
const int logicnum = num();
if (openf[logicnum - 1] != NULL)
{
_was_open = FALSE;
_isamfile = openf[logicnum - 1];
}
else
{
err = _open();
_was_open = TRUE;
}
setstatus(err);
return err;
}
int TLocalisamfile::operator +=(const TRecnotype npos)
{
skip(npos);
return status();
}
int TLocalisamfile::operator -=(const TRecnotype npos)
{
skip(-npos);
return status();
}
int TLocalisamfile::operator ++()
{
next();
return status();
}
int TLocalisamfile::operator --()
{
prev();
return status();
}
TIsamfile::TIsamfile(int logicnum, bool linkrecinst) : TBaseisamfile(logicnum, linkrecinst) {}
TIsamfile::~TIsamfile()
{
close();
}
int TIsamfile::flags(bool updateeod)
{
TDir d;
int err = NOERR;
if (filehnd()->ln <= 0) return NOERR ;
NOT_OPEN();
const TDirtype dirtype = (TDirtype) filehnd()->ft;
d.get(num(), _lock, dirtype);
if ((err = d.status(dirtype)) == NOERR)
{
d.flags() = filehnd()->d->Flags;
if (updateeod) d.eod() = filehnd()->d->EOD;
d.put(num(), dirtype);
}
setstatus(err);
return err;
}
///////////////////////////////////////////////////////////
// TIsamtempfile
///////////////////////////////////////////////////////////
TIsamtempfile::TIsamtempfile(int logicnum, const char* radix, bool create)
: TLocalisamfile(logicnum, 2)
{
TRecnotype eod = 0;
TRecnotype eox = 100;
TFilename n;
if (radix && *radix)
{
if (*radix == '%')
n = radix;
else
{
n.tempdir();
n << '/' << radix;
}
}
n.ext("dbf");
if (!create)
{
TDir dir; dir.get(logicnum);
const word& len = dir.len();
// Tolgo il % senno' che fa la fopen ?
if (n[0] == '%')
n = n.sub(1);
FILE* f = fopen(n, "r");
#if XVT_OS == XVT_OS_WIN
CHECKS(f, "Can't open temporary file ", (const char*)strerror(NULL));
#else
CHECKS(f, "Can't open temporary file ", (const char*)n);
#endif
fseek(f, 0, SEEK_END);
eod = eox = ftell(f) / len;
fclose(f);
}
_autodel = create > TRUE;
n.ext("");
// Ci rimetto il % se prima l'avevo tolto, senno' che fa la open ?
// if (*radix == '%')
if (n[0] != '%')
n.insert("%", 0);
open(n, create, eod, eox);
}
TIsamtempfile::~TIsamtempfile()
{
close();
}
int TIsamtempfile::open(const char* radix, bool create, TRecnotype eod, TRecnotype eox)
{
int err = NOERR;
TFilename tmpname;
CHECKS(filehnd() == NULL, "File already open", (const char*)filename());
if (radix[0] == '%')
tmpname << &radix[1] ;
else
tmpname.temp(radix);
getisfd (_isamfile, num());
strcpy(filehnd()->d->SysName, (const char*)tmpname);
filehnd()->d->EOX = eox;
if (create)
{
err=DB_build(filehnd()->d->SysName, filehnd()->r) ;
if (err == NOERR)
filehnd()->d->EOD = 0L;
else
{
err = get_error(err);
relisfd(_isamfile);
fatal_box("Create temporary file: Error n. %d", err);
}
}
else
filehnd()->d->EOD = eod;
filehnd()->fhnd = DB_open(filehnd()->d->SysName, 0);
if (filehnd()->fhnd < 0)
err = get_error(filehnd()->fhnd);
if (err != NOERR)
{
relisfd(_isamfile);
fatal_box("Open temporary file: Error n. %d ",err);
}
else
{
filehnd()->ln = -num();
filehnd()->knum = 1;
}
_recno = -1L;
setstatus(err);
return err;
}
int TIsamtempfile::close()
{
int err = NOERR;
if (filehnd() != NULL)
{
err=DB_close(filehnd()->fhnd);
if (err != NOERR) err = get_error(err);
if (_autodel && err==NOERR)
{
TFilename f(filehnd()->d->SysName);
long c = DB_getconf();
f.ext("dbf");
::remove((const char*)f);
if (c & 1) // FOXPRO format
f.ext("cdx");
if (c & 4) // DBIV format
f.ext("mdx");
if (c & 8 || c & 2) // CLIPPER and DBIII format
{
f.ext("cgp");
FILE *fp=fopen((const char*)f,"r");
char in[16];
while (fgets(in,16,fp)!=NULL)
{
TFilename a(in);
if (c & 8) // DBIII format
a.ext("ndx");
else
a.ext("ntx"); // CLIPPER format
::remove((const char *)a);
}
fclose(fp);
}
::remove((const char *)f);
}
relisfd(_isamfile);
clearfilehnd();
}
setstatus(err);
return err;
}
///////////////////////////////////////////////////////////
// TSystemsamfile
///////////////////////////////////////////////////////////
int TSystemisamfile::build(TRecnotype eox)
{
CHECKS(filehnd() == NULL, "Can't build open file", (const char*)filename());
int err=NOERR;
TDir d;
TTrec r;
d.get(num());
r.get(num());
CHECK(r.len() != 0, "Can't create a file with empty field info");
TFilename f(d.name());
f = f.path(); if (!is_not_slash(f.right(1)[0])) f.rtrim(1);
if (!fexist(f))
make_dir(f);
if (r.len() != 0)
{
err=DB_build(d.name(),r.rec());
if (err == NOERR)
{
isfdptr i;
getisfd(i,num());
i->d->EOX = eox;
i->fhnd = 0; // So relisfd() will record the EOX just set
relisfd(i);
}
else
err = get_error(err);
setstatus(err);
clearfilehnd();
#ifndef FOXPRO
if (err == NOERR && __autoload)
{
TFilename lf;
lf.format("%sstd/lf%04d.txt", __ptprf, num());
if (fexist(lf))
load(lf, '|', '\0', '\n', TRUE, TRUE);
}
#endif
}
return err;
}
int TSystemisamfile::extend(TRecnotype eox)
{
int err = NOERR;
isfdptr i;
CHECKS(filehnd() == NULL, "Can't extend open file ", (const char*)filename());
getisfd(i,num());
if (num() > 0)
{
if (eox < i->d->EOD)
err = _ispathfull;
else
{
i->d->EOX = eox;
i->fhnd = 0; // So relisfd() will write the EOX just set.
}
}
relisfd(i);
setstatus(err);
clearfilehnd();
return err;
}
long TSystemisamfile::size(TRecnotype eox)
{
return 51200L;
}
#ifndef FOXPRO
bool TSystemisamfile::exec_convapp(long flev, const bool before)
{
const char * const v = before ? "BCNV" : "ACNV";
if (flev == 0) flev = 199401;
else flev++;
for (long l = flev; l <= get_std_level(); l++)
{
TString16 paragraph(format("%06ld", l));
TConfig conv(CONFIG_FCONV, paragraph);
if (!conv.new_paragraph() && conv.exist(v, num()))
{
int err = 0;
TString80 s(conv.get(v, NULL, num())); s << " " << main_app().get_firm();
TExternal_app app(s);
if (app.can_run())
{
app.run();
err = app.error();
TMailbox mail;
TMessage* msg = mail.next(TRUE);
if (err == 0 && msg != NULL)
err = atoi(msg->body());
}
else err = 16;
if (err)
return error_box("Impossibile eseguire il programma di %sconversione\ndel livello %ld/%ld\nErrore n.ro %d", before ? "pre" : "post", l / 100, l % 100, err);
}
}
return TRUE;
}
bool TSystemisamfile::getlcf(long flev)
{
_flds.destroy();
_exps.destroy();
if (flev == 0) flev = 199401;
else flev++;
for (long l = flev; l <= get_std_level(); l++)
{
TString16 paragraph(format("%06ld", l));
TConfig conv(CONFIG_FCONV, paragraph);
if (!conv.new_paragraph() && conv.exist("F", num()))
{
TToken_string exprline(conv.get("F", NULL, num()));
if (exprline.empty()) return FALSE;
TToken_string w("", '=');
const char * wexprs = exprline.get();
while (wexprs != NULL)
{
w = wexprs;
TFixed_string fld(w.get());
_flds.add(new TFieldref(fld, 0));
_exps.add(new TExpression(w.get(), _strexpr));
wexprs = exprline.get();
}
}
}
return _flds.items() > 0;
}
void TSystemisamfile::makelc(TRectype& rec)
{
for (int i = 0 ; i < _flds.items(); i++)
{
TFieldref& f = (TFieldref&) _flds[i];
TExpression& e = (TExpression & )_exps[i];
for (int k = 0; k < e.numvar(); k++)
e.setvar(k, get(e.varname(k)));
f.write(e, rec);
}
}
int TSystemisamfile::update(TTrec& newrec, bool vis)
{
CHECKS(filehnd() == NULL, "Can't update open file", (const char*)filename());
CHECK(newrec.len() != 0, "Can't update to file with empty field info");
TDir dir;
dir.get(num(), _unlock, _nordir, _sysdirop);
const bool is_com = prefix().is_com();
const bool toconvert = is_com ? dir.is_com() : dir.is_firm();
int err = NOERR;
TTrec oldrec;
oldrec.get(num());
if (newrec.len() != 0)
{
const long lev = prefix().filelevel();
const bool lcf = getlcf(lev);
exec_convapp(lev, TRUE);
if (!lcf && newrec == oldrec)
{
exec_convapp(lev, FALSE);
return NOERR;
}
const TRecnotype nitems = dir.eod();
const unsigned int lenr = newrec.len();
if (!toconvert && dir.eox() > 0L)
{
dir.eod() = 0L;
dir.eox() = 0L;
}
if (toconvert && dir.eox() > 0L)
{
TRecnotype ni = 0L;
isfdptr i0;
TFilename tmpfname("tmpf");
open(_excllock);
getisfd(i0, num());
err=DB_build((const char*) tmpfname, newrec.rec());
if (err != NOERR)
{
err=get_error(err);
return (err);
}
i0->fhnd=DB_open((const char*)tmpfname,0);
if (i0->fhnd < 0 ) err=get_error(i0->fhnd);
TFilename fname(filename());
TString s(80);
s.format("Aggiornamento archivio %s", (const char*) fname);
TProgind p(nitems ? nitems : 1, s, TRUE, TRUE, 70);
int nflds = curr().items();
TArray fld(nflds);
TExtrectype nrec(newrec);
TRecnotype i = 0;
for (int j = 0; j < nflds; j++)
fld.add(TString(curr().fieldname(j)), j);
for (first(); good(); next())
{
if ((i++ % 50) == 0) p.setstatus(i + 1);
nrec.zero();
ni++;
for (j = 0; j < nflds; j++)
if (nrec.exist((const TString&) fld[j]))
nrec.put((const TString&) fld[j], get((const TString&) fld[j]));
if (lcf)
makelc((TRectype &)nrec);
browse_null(nrec.string(),DB_reclen(i0->fhnd));
memcpy(DB_getrecord(i0->fhnd),nrec.string(),DB_reclen(i0->fhnd));
err=DB_add(i0->fhnd);
if (err != NOERR) err=get_error(err);
setstatus(err);
}
err=DB_close(i0->fhnd);
close();
if (err!=NOERR) err=get_error(err);
relisfd(i0);
p.setstatus(nitems);
if (err == NOERR)
{
long c = DB_getconf();
fname.ext("dbf");
tmpfname.ext("dbf");
fcopy((const char*)tmpfname,(const char*)fname);
::remove((const char*)tmpfname);
if (c & 1) // FOXPRO format
tmpfname.ext("cdx");
if (c & 4) // DBIV format
tmpfname.ext("mdx");
if (c & 8 || c & 2)
{
tmpfname.ext("cgp");
char in[16];
FILE *fp=fopen((const char *) tmpfname,"r");
while (fgets(in,16,fp)!=NULL)
{
TFilename a(in);
a.rtrim(1); // Cut \n
if (c & 8) // DBIII format
a.ext("ndx");
else
a.ext("ntx"); // CLIPPER format
::remove((const char *)a);
}
fclose(fp);
}
::remove((const char*)tmpfname);
dir.eod() = ni;
}
}
dir.set_len(lenr);
dir.put(num(), _nordir, _sysdirop);
newrec.put(num());
if (toconvert && dir.eox() > 0L) packindex();
exec_convapp(lev, FALSE);
}
setstatus(err);
return err;
}
int TSystemisamfile::packfile(bool vis)
{
int err=NOERR;
TDir d;
d.get(num(),_nolock, _nordir,_sysdirop);
d.get(num(),_nolock, (d.is_com()) ? _comdir : _nordir);
CHECKS(filehnd() == NULL, "Can't pack open file", (const char*)filename());
err=DB_packfile(vis,d.name(),d.eod());
if (err != NOERR) err = get_error(err);
if (err != NOERR) error_box("Errore in compattamento dati.\nFile %d : %d", num(),err);
setstatus(err);
return err;
}
int TSystemisamfile::packindex(bool vis)
{
int err=NOERR;
TRecnotype peod;
TTrec r;
TDir d;
CHECKS(filehnd() == NULL, "Can't pack index of open file", (const char*)filename());
r.get(num());
d.get(num(),_nolock, _nordir,_sysdirop);
bool is_com = d.is_com();
d.get(num(),_nolock, is_com ? _comdir : _nordir);
err=DB_packindex(vis,d.name(),r.rec(),&peod);
if (err != NOERR) err = get_error(err);
if (err != NOERR) error_box("Errore in compattamento indici.\nFile %d : %d", num(),err);
else
if (peod >= 0 && peod != d.eod())
{
d.eod() = peod;
d.put(num(), is_com ? _comdir : _nordir);
}
setstatus(err);
return err;
}
int TSystemisamfile::pack(bool vis)
{
int err=NOERR;
if ((err=packfile(vis))==NOERR)
err=packindex(vis);
setstatus(err);
return err;
}
int TSystemisamfile::load(const char* from, char fs, char fd, char rs, bool vis, bool extended)
{
FILE* fl = fopen(from, "r");
int err=NOERR;
if (fl == NULL)
{
error_box("Non riesco ad aprire il file %s",from);
return 2;
}
TRecnotype r = 0, e = 0, nitems = 0, nread = 0;
TString16 firm, year, attprev("00000");
if (extended)
{
TDate d(TODAY);
TLocalisamfile ditte(LF_NDITTE);
firm.format("%05ld", main_app().get_firm());
year.format("%04d", d.year());
ditte.zero();
ditte.put("CODDITTA", firm);
if (ditte.read() == NOERR)
attprev = ditte.get("CODATTPREV");
}
if (fl == NULL)
{
clearerr(fl);
setstatus(err);
return err;
}
char w[80];
while ((fgets(w, 80, fl) != NULL))
{
if (strncmp(w, "[Data]", 6) == 0)
{
nitems = ftell(fl);
break;
}
}
fseek(fl, 0L, SEEK_END);
nitems = ftell(fl) - nitems;
fclose(fl);
TScanner f(from);
open();
TToken_string s(1024, fs);
bool fixedlen = (fs == '\0');
int nflds = curr().items();
TArray fld(nflds);
int len[MaxFields];
TString sfd(3);
TString s1(64);
bool lcf = FALSE;
if (f.paragraph("Header"))
{
f.equal();
const long level = atol(f.line());
if (level > get_std_level())
error_box("L'archivio %s e' stato generato con gli archivi di livello %ld%/%ld.\n Il livello attuale e' %ld/%ld.\n Convertire gli archivi e ripetere l' operazione.",
from, level/100, level%100, get_std_level()/100, get_std_level()%100);
lcf = getlcf(level);
nflds = 0;
TToken_string s2(f.line());
int p = s2.find('=');
if (p > 0)
{
s1 = s2.left(p);
s2.ltrim(p+1);
}
else s1.cut(0);
while (s1 == "Fields")
{
for (const char * fd = s2.get(); fd != NULL; fd = s2.get())
{
TToken_string wfd(fd, ',');
fld.add(new TString(wfd.get()));
len[nflds] = wfd.get_int();
nflds++;
}
s2 = f.line();
p = s2.find('=');
if (p > 0)
{
s1 = s2.left(p);
s2.ltrim(p+1);
}
else s1.cut(0);
}
}
else
{
for (int j = 0; j < nflds; j++)
{
fld.add(TString(curr().fieldname(j)), j);
const TString & wfld = (const TString & ) fld[j];
len[j] = (curr().type(wfld) == _datefld) ? 10 : curr().length(wfld);
}
}
if (!f.paragraph("Data"))
{
error_box("Formato dei dati non valido");
close();
err = 1;
setstatus(err);
return err;
}
if (fd) sfd << fd;
int last = NOERR;
s1.format("Imp. archivio %s\n%6ld records %6ld errori - %3d", filename(), r, e, last);
TProgind p(nitems, s1, TRUE, TRUE, 70);
s = f.line();
while (s.not_empty() && !p.iscancelled())
{
if (extended)
{
int p, i;
while ((p = s.find("%yr%")) >= 0)
for (i = 0; i < 4; i++) s[p + i] = year[i];
while ((p = s.find("%frm%")) >= 0)
for (i = 0; i < 5; i++) s[p + i] = firm[i];
while ((p = s.find("%att%")) >= 0)
for (i = 0; i < 5; i++) s[p + i] = attprev[i];
}
if ((r + e) % 50 == 0)
{
s1.format("Imp. archivio %s\n%6ld records %6ld errori - %3d", filename(), r, e, last);
p.set_text(s1);
}
p.setstatus(nread + 1);
nread += s.len() + 1;
zero();
if (fixedlen)
{
int pos = 0;
for (int j = 0; j < nflds; j++)
{
s1 = s.mid(pos,len[j]);
s1.rtrim();
put((const TString&) fld[j], s1);
pos += len[j];
}
}
else
{
s.restart();
for (int j = 0; j < nflds; j++)
{
char* s2 = (char*) s.get();
if (fd)
{
s2++;
s2[strlen(s2) - 1] = '\0';
}
put((const TString&) fld[j], s2);
}
}
if (write() == NOERR) r++;
else
{
e++;
last = status();
}
s = f.line();
}
s1.format("Imp. archivio %s\n%6ld records %6ld errori - %3d", filename(), r, e, last);
p.set_text(s1);
close();
setstatus(err);
return err;
}
int TSystemisamfile::dump(const char* to, int nkey, char fs, char fd, char rs, bool vis, bool withdeleted)
{
FILE* f = fopen(to, "w");
int err = ferror(f);
if (withdeleted) nkey = 0;
if (f == NULL)
{
clearerr(f);
setstatus(err);
return err;
}
open();
TString s(512);
bool fixedlen = (fs == '\0');
int nflds = curr().items();
TArray fld(nflds);
TBit_array rjust(nflds);
int len[MaxFields];
for (int j = 0; j < nflds; j++)
{
fld.add(TString(curr().fieldname(j)), j);
const TString & wfld = (const TString&) fld[j];
const TFieldtypes t = curr().type(wfld);
rjust.set(j, t == _intfld || t == _longfld || t == _realfld ||
t == _wordfld || t == _intzerofld || t == _longzerofld);
len[j] = (t == _datefld) ? 10 : curr().length(wfld);
}
TRecnotype i = 0;
const TRecnotype nitems = nkey ? items() : filehnd()->d->EOD;
s.format("Esportazione archivio %s", filename());
TProgind p(nitems, s, TRUE, TRUE, 70);
TString s1;
fprintf(f, "[Header]\nVersion=%ld", prefix().filelevel());
for (int k = 0; k < nflds; k++)
{
if ((k % 10) == 0) fprintf(f, "\nFields=");
else fprintf(f, "|");
fprintf(f, "%s,%d", (const char *) (const TString&) fld[k], len[k]);
}
fprintf(f, "\n\n[Data]\n");
if (nkey)
{
setkey(nkey);
for ( first(); status() == NOERR && !p.iscancelled(); next(), i++)
{
p.setstatus(i + 1);
s = "";
for (j = 0; j < nflds; j++)
{
if (fixedlen)
{
s1 = get((const TString&)fld[j]);
if (rjust[j]) s1.right_just(len[j]);
else s1.left_just(len[j]);
}
else
{
s1 = "";
if (j && fs) s1 << fs;
if (fd) s1 << fd;
s1 << get((const TString&)fld[j]);
if (fd) s1 << fd;
}
s << s1;
}
fprintf(f, "%s%c", (const char*) s, rs);
}
}
else
{
for (i = 0; i < nitems && !p.iscancelled(); i++)
{
zero();
p.setstatus(i + 1);
readat(i + 1);
s="";
if (withdeleted || curr().valid())
{
for (j = 0; j < nflds; j++)
{
if (fixedlen)
{
s1 = get((const TString&)fld[j]);
if (rjust[j]) s1.right_just(len[j]);
else s1.left_just(len[j]);
}
else
{
s1 = "";
if (j && fs) s1 << fs;
if (fd) s1 << fd;
s1 << get((const TString&)fld[j]);
if (fd) s1 << fd;
}
s << s1;
}
fprintf(f, "%s%c", (const char*) s, rs);
}
}
}
p.setstatus(nitems);
close();
fclose(f);
setstatus(err);
return err;
}
#endif // FOXPRO
void TBaseisamfile::recover()
{
}
////////////////////////////////////////////////////////////
// TRectype
////////////////////////////////////////////////////////////
TRectype::TRectype(int logicnum) : _cod(NULL)
{
_logicnum = logicnum;
if (openf[_logicnum - 1] != NULL)
_length = DB_reclen(openf[logicnum - 1]->fhnd);
else
{
TDir wdir;
wdir.get(_logicnum, _nolock, _nordir, _sysdirop);
if (wdir.is_com())
wdir.get(_logicnum, _nolock, _comdir, _sysdirop);
_length = wdir.len();
}
_rec = new char [ _length ];
*_tab = '\0';
if (_length)
zero();
else
setempty(TRUE);
}
TRectype::TRectype(const TBaseisamfile* i): _cod(NULL)
{
_logicnum = i->num();
if (i->filehnd() != NULL)
_length = DB_reclen(i->filehnd()->fhnd);
else
{
TDir wdir;
wdir.get(_logicnum, _nolock, _nordir, _sysdirop);
if (wdir.is_com())
wdir.get(_logicnum, _nolock, _comdir, _sysdirop);
_length = wdir.len();
}
*_tab = '\0';
_rec = new char [ _length ];
if (_length)
zero();
else
setempty(TRUE);
}
TRectype::TRectype(const TRectype& r)
: _cod(NULL)
{
_logicnum = r._logicnum;
_length = r.len();
_rec = new char [ _length ];
_rec[0] = r._rec[0];
memcpy(_rec + 1, r._rec + 1, _length - 1);
strcpy(_tab, r._tab);
if (r._cod != NULL)
_cod = new TRecfield(*this, "COD");
setempty(r.empty());
}
TRectype::~TRectype()
{
if (_cod != NULL) delete _cod;
if (_rec != NULL) delete _rec;
}
void TRectype::settab(const char *tab)
{
if (_cod != NULL)
{
delete _cod;
_cod = NULL;
}
strcpy(_tab, tab);
if (*_tab != '\0')
_cod = new TRecfield(*this, "COD");
zero();
}
TObject* TRectype::dup() const
{
TRectype* o = new TRectype(*this);
return o;
}
const char* TRectype::build_key(int num) const
{
CBuildKey(rec_des(), num, string(), __tmp_string, TRUE);
return __tmp_string;
}
int TRectype::compare_key(const TRectype& rec, int key) const
{
TString256 key1= build_key(key);
TString256 key2 = rec.build_key(key);
return key1.compare(key2);
}
HIDDEN bool fld_empty(const char* s, int len, bool number)
{
/*if (number)
{
for (; len; s++, len--)
if (strchr(" 0.", *s) == NULL) return FALSE;
}
else */
if (*s)
{
for (; len; s++, len--)
if (*s != ' ') return FALSE;
}
return TRUE;
}
HIDDEN int fld_cmp(const char* a, const char* b, int len, bool number)
{
for (int i = 0; i < len && *a == *b; b++, a++, i++);
if (i == len) return 0;
int res = *a - *b;
if (number)
{
b -= i;
i = 0;
}
return fld_empty(b, len - i, number) ? 0 : res;
}
///////////////////////////////////////////////////////////
// TRectype (record di un file)
///////////////////////////////////////////////////////////
RecDes* TRectype::rec_des() const
{
const isdef* i = openf[_logicnum-1];
CHECKD(i, "Can't use a record of closed file ", _logicnum);
RecDes* r = i->r;
CHECKD(r, "Missing record description of file", _logicnum);
return r;
}
int TRectype::items() const
{
return rec_des()->NFields;
}
const char* TRectype::start(int nf) const
{
return string() + rec_des()->Fd[nf].RecOff;
}
int TRectype::compare(const TSortable& s) const
{
const TRectype& br = (const TRectype&) s;
int res = 0;
if (br.empty()) return UNDEFINED;
const RecDes& rd = *rec_des();
for (int i = 0; i < items() ; i++)
{
const char* b = br.start(i);
const char* a = start(i);
const byte typ = rd.Fd[i].TypeF;
const int sz = rd.Fd[i].Len;
const bool number = (typ == _intfld) || (typ == _realfld) ||
(typ == _longfld) || (typ == _wordfld) ||
(typ == _intzerofld) || (typ == _longzerofld)
|| (typ == _datefld) ;
if (fld_empty(b, sz, number)) continue;
res = ::fld_cmp(a, b, sz, number);
if (res) return res;
}
return 0;
}
TFieldtypes TRectype::type(const char* fieldname) const
{
return (TFieldtypes) CFieldType((char*) fieldname, rec_des());
}
int TRectype::length(const char* fieldname) const
{
return CFieldSize((char*) fieldname, rec_des());
}
int TRectype::ndec(const char* fieldname) const
{
return CFieldDec((char*) fieldname, rec_des());
}
bool TRectype::exist(const char* fieldname) const
{
return findfld(rec_des(), (char*)fieldname) != -1;
}
const char* TRectype::fieldname(int i) const
{
RecDes* rd = rec_des();
return i >= 0 && i < rd->NFields ? rd->Fd[i].Name : NULL;
}
const char* TRectype::get_str(const char* fieldname) const
{
RecDes* rd = rec_des();
if (CFieldType((char*) fieldname, rd) == _datefld)
{
const TRecfield f((TRectype&)*this, fieldname);
strcpy(_isam_string, (const char*) f);
}
else
{
if (CGetFieldBuff((char*) fieldname, rd, _rec, _isam_string) == -1)
UNKNOWN_FIELD(num(), fieldname);
if (CFieldType((char*) fieldname,rd) == _boolfld)
{
if (toupper(*_isam_string) == 'T' || toupper(*_isam_string) == 'Y'
|| toupper(*_isam_string) == 'S' || toupper(*_isam_string) == 'X')
strcpy(_isam_string,"X");
else
strcpy(_isam_string," ");
}
}
return _isam_string;
}
#ifndef FOXPRO
const TString& TRectype::get(const char* fieldname) const
{
static TFixed_string tmp(_isam_string, sizeof(_isam_string));
get_str(fieldname);
return tmp;
}
int TRectype::get_int(const char* fieldname) const
{
if (CGetFieldBuff((char*) fieldname, rec_des(), _rec, _isam_string) == -1)
UNKNOWN_FIELD(num(), fieldname);
return atoi(_isam_string);
}
long TRectype::get_long(const char* fieldname) const
{
if (CGetFieldBuff((char*) fieldname, rec_des(), _rec, _isam_string) == -1)
UNKNOWN_FIELD(num(), fieldname);
return atol(_isam_string);
}
word TRectype::get_word(const char* fieldname) const
{
if (CGetFieldBuff((char*) fieldname, rec_des(), _rec, _isam_string) == -1)
UNKNOWN_FIELD(num(), fieldname);
return (word)atoi(_isam_string);
}
real TRectype::get_real(const char* fieldname) const
{
if (CGetFieldBuff((char*) fieldname, rec_des(), _rec, _isam_string) == -1)
UNKNOWN_FIELD(num(), fieldname);
real r(_isam_string);
return r;
}
char TRectype::get_char(const char* fieldname) const
{
if (CGetFieldBuff((char*) fieldname, rec_des(), _rec, _isam_string) == -1)
UNKNOWN_FIELD(num(), fieldname);
return *_isam_string;
}
bool TRectype::get_bool(const char* fieldname) const
{
if (CGetFieldBuff((char*) fieldname, rec_des(), _rec, _isam_string) == -1)
UNKNOWN_FIELD(num(), fieldname);
if (toupper(*_isam_string) == 'T' || toupper(*_isam_string) == 'Y'
|| toupper(*_isam_string) == 'S' || toupper(*_isam_string) == 'X')
return TRUE;
else
return FALSE;
}
bool TRectype::get_memo(const char* fieldname, TTextfile& txt) const
{
long val = get_long(fieldname);
bool ok = FALSE;
if (ok = (val != 0l))
{
TLocalisamfile f(_logicnum);
TMemo_file memo(f.filename());
ok |= memo.get_field(txt, val);
}
return ok;
}
#endif // FOXPRO
TDate TRectype::get_date(const char* fieldname) const
{
if (CGetFieldBuff((char*) fieldname, rec_des(), _rec, _isam_string) == -1)
UNKNOWN_FIELD(num(), fieldname);
TDate d(_isam_string);
return d;
}
#ifndef FOXPRO
void TRectype::put(const char* fieldname, int val)
{
if (CPutField((char*) fieldname, rec_des(), &val, _rec) == -1)
UNKNOWN_FIELD(num(), fieldname);
setempty(FALSE);
}
void TRectype::put(const char* fieldname, long val)
{
if (CPutField((char*) fieldname, rec_des(), &val, _rec) == -1)
UNKNOWN_FIELD(num(), fieldname);
setempty(FALSE);
}
void TRectype::put(const char* fieldname, TTextfile& txt)
{
long val = get_long(fieldname);
bool isnew = val == 0;
TLocalisamfile f(_logicnum);
TMemo_file memo(f.filename());
long id = memo.set_field(txt, isnew ? -1 : val);
if (isnew) val = id;
TString16 str; str << val;
if (CPutFieldBuff((char*) fieldname, rec_des(), (char*)(const char*)str, _rec) == -1)
UNKNOWN_FIELD(num(), fieldname);
setempty(FALSE);
}
void TRectype::put(const char* fieldname, word val)
{
if (CPutField((char*) fieldname, rec_des(), &val, _rec) == -1)
UNKNOWN_FIELD(num(), fieldname);
setempty(FALSE);
}
void TRectype::put(const char* fieldname, const real& val)
{
if (CPutFieldBuff((char*) fieldname, rec_des(), (char*)(const char*)val.string(), _rec) == -1)
UNKNOWN_FIELD(num(), fieldname);
setempty(FALSE);
}
void TRectype::put(const char* fieldname, const TDate& val)
{
TRecfield f(*this, fieldname);
f = val.string(full);
setempty(FALSE);
}
void TRectype::put(const char* fieldname, char val)
{
char w[2] = {val, '\0'};
if (CPutFieldBuff((char*) fieldname, rec_des(), w, _rec) == -1)
UNKNOWN_FIELD(num(), fieldname);
setempty(FALSE);
}
void TRectype::put(const char* fieldname, bool val)
{
char* s = val ? "T" : "F";
if (CPutFieldBuff((char*) fieldname, rec_des(), s, _rec) == -1)
UNKNOWN_FIELD(num(), fieldname);
setempty(FALSE);
}
#endif // FOXPRO
void TRectype::put(const char* fieldname, const char* val)
{
if (val == NULL || *val == '\0') // Da provare
{
TRecfield f(*this, fieldname);
if (*f.pos() == '\0') return;
}
if (CFieldType((char*) fieldname, rec_des()) == _datefld)
{
TRecfield f(*this, fieldname);
f = val;
}
else
{
TString wval;
wval=val;
if (CFieldType((char*) fieldname,rec_des()) == _boolfld)
{
if (toupper(*val) == 'T' || toupper(*val) == 'Y'
|| toupper(*val) == 'S' || toupper(*val) == 'X')
wval="T";
else
wval="F";
}
if (CPutFieldBuff((char*) fieldname, rec_des(), (char*) (const char*)wval, _rec) == -1)
UNKNOWN_FIELD(num(), fieldname);
}
setempty(FALSE);
}
void TRectype::zero(const char* fieldname)
{
if (_cod != NULL && strcmp(fieldname , "COD") == 0)
*_cod = _tab;
else
{
if (CFieldType((char*) fieldname, rec_des()) == _datefld)
{
TRecfield f(*this, fieldname);
f = "";
}
else
if (CZeroField((char*) fieldname, rec_des(), _rec) == -1)
UNKNOWN_FIELD(num(), fieldname);
}
}
void TRectype::zero()
{
zero('\0');
}
void TRectype::zero(char c)
{
recall();
memset(_rec + 1, c, len() - 1);
if (_cod != NULL)
*_cod = _tab;
setempty(TRUE);
}
// Certified 99%
TRectype& TRectype::operator =(const TRectype& rec)
{
CHECK(num() == rec.num(), "Can't assign records of different file");
memcpy(_rec, rec._rec, _length); // Copy contents
setempty(rec.empty()); // Copy emptiness status
return *this;
}
// Certified 100%
TRectype& TRectype::operator =(const TBaseisamfile& f)
{
return *this = f.curr();
}
// Certified 100%
int TRectype::read(TBaseisamfile& f, word op)
{ return f.read(*this, op); }
// Certified 100%
int TRectype::next(TBaseisamfile& f)
{
const int err = f.next();
*this = f.curr();
return err;
}
// Certified 100%
int TRectype::write(TBaseisamfile& f) const
{ return f.write(*this); }
// Certified 100%
int TRectype::rewrite(TBaseisamfile& f) const
{
return f.rewrite(*this);
}
// Certified 100%
int TRectype::remove(TBaseisamfile& f) const
{
return f.remove(*this);
}
void TRectype::renum_key(const char* field, const char* val)
{
put(field, val);
}
// Certified 99%
TRectype& TRectype::operator =(const char* rec)
{
memcpy(_rec, rec, _length);
setempty(FALSE);
return *this;
}
const char* TRectype::key(int numkey) const
{
CBuildKey(rec_des(), numkey, _rec, _isam_string,FALSE);
return _isam_string;
}
///////////////////////////////////////////////////////////
// TRecfield (campo/sottocampo di un record)
///////////////////////////////////////////////////////////
void TRecfield::set(int from, int to)
{
int nf;
RecDes* rd = _rec->rec_des();
if ((nf = findfld(rd, _name)) == -1)
{
_p = NULL;
_len = 0;
_dec = 0;
_type = _nullfld;
yesnofatal_box("File n. %d unknown field %s", _rec->num(), _name);
}
else
{
CHECK(from >= 0, "Invalid Start");
_p = _rec->string() + rd->Fd[nf].RecOff + from;
_dec = rd->Fd[nf].Dec;
_type = rd->Fd[nf].TypeF;
if (to >= 0)
{
CHECK(from <= to && to <= rd->Fd[nf].Len, "Invalid Range");
_len = to - from + 1;
}
else _len = rd->Fd[nf].Len - from;
}
}
TRecfield::TRecfield(TRectype& rec, const char* name, int from, int to)
{
strcpy(_name, name);
_rec = &rec;
set(from, to);
}
HIDDEN void __getfieldbuff(byte l, byte t, const char* recin, char *s)
{
if (recin == NULL)
{
*s = '\0';
return;
}
if (t != _alfafld && t != _datefld)
{
if (t == _intzerofld || t == _longzerofld)
{
byte i = 0;
for (char* c = (char*)recin; i < l; c++, i++)
if (*c == ' ') *c = '0';
else break;
if (i == l)
l = 0;
}
else
{
while ((*recin == ' ') && (l))
{
recin++;
l--;
}
if ((t != _realfld) && (t != _charfld))
{
while ((*recin == '0') && (l))
{
recin++;
l--;
}
}
}
}
if (l)
{
strncpy(s, recin, l);
for (int i = l-1; i >= 0 && s[i] == ' '; i--);
l = byte(i+1);
}
s[l] = '\0';
if (*s)
{
if (t == _datefld)
{
const TDate dt(atol(s));
strcpy(s, dt.string(full));
} else
if (t == _boolfld)
{
const char ok = toupper(*s);
if (ok == 'T' || ok == 'Y' || ok == 'S' || ok == 'X')
strcpy(s,"X");
else
strcpy(s," ");
}
}
}
HIDDEN void __putfieldbuff(byte l, byte d, byte t, const char* s, char* recout)
{
int len, i;
if (recout == NULL) return;
char s2[256];
strcpy(s2, s);
if (t == _datefld)
{
if (*s2)
{
const TDate dt(s2);
sprintf(s2,"%8s", dt.string(ANSI));
}
}
else
if (t == _boolfld)
{
const char ok = toupper(*s2);
if (ok == 'T' || ok == 'Y' || ok == 'S' || ok == 'X')
strcpy(s2, "T");
else
strcpy(s2, "F");
}
else
if (t == _realfld) setdec(s2, d);
len = strlen(s2);
if (len > l)
{
yesnofatal_box("Impossibile scrivere %d caratteri su di un campo di %d", (int)len, (int)l);
return;
}
if ((t == _intfld) ||
(t == _longfld) ||
(t == _wordfld) ||
(t == _realfld) ||
(t == _intzerofld) ||
(t == _longzerofld)
)
{
if (len == 0)
{
strcpy(s2, "0");
len = 1;
}
const char c = (t == _intzerofld || t == _longzerofld) ? '0' : ' ';
i = 0;
while (i < l - len - 1) recout[i++] = c;
strncpy(&recout[l - len - 1], s2, len) ;
}
else
{
strncpy(recout, s2, len) ;
while (len < l) recout[len++] = ' ';
}
}
int TRecfield::operator =(int i)
{
if (_type == _intzerofld)
sprintf(_isam_string, "%0*d", _len, i);
else
sprintf(_isam_string, "%d", i);
__putfieldbuff( _len, _dec, _type, _isam_string, _p);
_rec->setempty(FALSE);
return i;
}
long TRecfield::operator =(long l)
{
if (_type == _longzerofld)
sprintf(_isam_string, "%0*ld", _len, l);
else
sprintf(_isam_string, "%ld", l);
__putfieldbuff( _len, _dec, _type, _isam_string, _p);
_rec->setempty(FALSE);
return l;
}
#ifndef FOXPRO
const real& TRecfield::operator =(const real& r)
{
strcpy(_isam_string, r.string());
__putfieldbuff( _len, _dec, _type, _isam_string, _p);
_rec->setempty(FALSE);
return r;
}
#endif // FOXPRO
const TDate& TRecfield::operator =(const TDate& d)
{
strcpy(_isam_string, (const char*)d);
__putfieldbuff( _len, _dec, _type, _isam_string, _p);
_rec->setempty(FALSE);
return d;
}
const char* TRecfield::operator =(const char* s)
{
__putfieldbuff( _len, _dec, _type, s, _p);
_rec->setempty(FALSE);
return s;
}
void TRecfield::setptr(TRecnotype r)
{
if (_p == NULL) return;
bool n = r < 0;
unsigned char* wp = (unsigned char*) _p;
if (n) r = -r;
while(wp - (unsigned char*) _p <= 3)
{
*wp = r && 0x000000FF;
r >>= 8;
wp++;
}
if (n) *wp += 128;
}
TRecfield::operator int() const
{
__getfieldbuff( _len, _type, _p, _isam_string);
return atoi(_isam_string);
}
TRecfield::operator long() const
{
__getfieldbuff( _len, _type, _p, _isam_string);
return atol(_isam_string);
}
#ifndef FOXPRO
TRecfield::operator const real() const
{
__getfieldbuff( _len, _type, _p, _isam_string);
real r(_isam_string);
return r;
}
#endif // FOXPRO
TRecfield::operator TDate() const
{
__getfieldbuff(_len, _type, _p, _isam_string);
TDate d(_isam_string);
return d;
}
TRecfield::operator const char*() const
{
__getfieldbuff( _len, _type, _p, _isam_string);
return _isam_string;
}
TRecnotype TRecfield::ptr() const
{
if (_p == NULL) return(-1L);
unsigned char* wp = (unsigned char*) _p + 3;
TRecnotype r = *wp;
bool n = r > 127;
if (n) r -= 128;
while(wp-- > (unsigned char*) _p) r = r << 8 + *wp;
return n ? -r : r;
}
/*
///////////////////////////////////////////////////////////
// Never implemented story
///////////////////////////////////////////////////////////
void TTransaction::begin()
{
}
void TTransaction::end(bool success)
{
if (success) ;
else ;
}
*/