#include #include #define __ISAM_CPP #ifndef FOXPRO #include #include #include #include #endif #include #include #include #include #include #include #include #if XVT_OS==XVT_OS_SCOUNIX #include #include #include #else #include #include #endif #define NOT_LINKED(i,f) CHECKS(i != NULL, "Record senza tracciato: impossibile eseguire ", f) #define NOT_OPEN(f) CHECKS(_isamfile != NULL, "File chiuso: ", f) 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; void set_autoload_new_files(bool on) { __autoload = on; } /////////////////////////////////////////////////////////// // TExtrectype /////////////////////////////////////////////////////////// class TExtrectype : public TRectype { 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 ]; _i = new isdef; _i->r = r.rec(); zero(); } TExtrectype::~TExtrectype() { delete _rec; delete _i; } /////////////////////////////////////////////////////////// // TBaseisamfile /////////////////////////////////////////////////////////// TBaseisamfile::TBaseisamfile(int logicnum, bool linkrecinst) { TTrec r; _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; } r.get(logicnum); /* _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 filehnd()->i.Base[filehnd()->i.PN].PEOD; } const char* TBaseisamfile::name() const { sprintf(__tmp_string, "%d", num()); return __tmp_string; } const char* TBaseisamfile::filename() const { if (_isamfile == NULL) { TDir d; d.get(num()); return strcpy(__tmp_string, d.name()); } return _isamfile->d->SysName; } const char* TBaseisamfile::description() const { if (_isamfile == NULL) { TDir d; d.get(num()); return strcpy(__tmp_string, d.des()); } return _isamfile->d->Des; } void TBaseisamfile::setkey(int nkey) { CHECKD(nkey > 0 && nkey - 1 <= _isamfile->r->NKeys, "Chiave non valida n.ro ", nkey); NOT_OPEN(name()); _isamfile->i.PN = nkey - 1; } int TBaseisamfile::getkey() const { NOT_OPEN(name()); return _isamfile->i.PN + 1; } int TBaseisamfile::first(word lockop) { NOT_OPEN(name()); curr().setdirty(); cisread(_isamfile, curr().string(), _isfirst + lockop, &_lasterr); _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::last(word lockop) { NOT_OPEN(name()); curr().setdirty(); cisread(_isamfile, curr().string(), _islast + lockop, &_lasterr); _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::next(word lockop) { NOT_OPEN(name()); curr().setdirty(); cisread(_isamfile, curr().string(), _isnext + lockop, &_lasterr); _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::next(TDate& atdate) { TRectype wr(curr()); TRecfield fll(curr(), RFLD_SYS_LAST), fd(wr, RFLD_SYS_DATE); TRecnotype wrn; NOT_OPEN(name()); if (!_historicfile) error_box("%s not historic file", filename()); if (_lasthf == -1L) return _iseof; curr().setdirty(); _hf.read(curr().string(), _lasthf); wrn = fll.ptr(); if (wrn < 0L) { readat(-wrn); atdate = eotime; _lasthf = -1L; } else { _hf.read(curr().string(), wrn); _lasthf = wrn; wrn = fll.ptr(); if (wrn < 0) readat(wr, -wrn); else _hf.read(wr.string(), wrn); atdate = (const TDate&)fd - 1L; } return NOERR; } int TBaseisamfile::prev(word lockop) { NOT_OPEN(name()); curr().setdirty(); cisread(_isamfile, curr().string(), _isprev + lockop, &_lasterr); _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::prev(TDate& atdate) { TRecfield flf(curr(), RFLD_SYS_LAST), fd(curr(), RFLD_SYS_DATE); TRecnotype wrn; NOT_OPEN(name()); if (!_historicfile) error_box("%s not historic file", filename()); if (_lasthf == -1L) return _isbof; curr().setdirty(); _hf.read(curr().string(), _lasthf); wrn = flf.ptr(); atdate = (const TDate&) fd - 1L; if (wrn < 0L) _lasthf = -1L; else { _hf.read(curr().string(), wrn); _lasthf = wrn; } return NOERR; } int TBaseisamfile::reread(word lockop, TDate& atdate) { NOT_OPEN(name()); curr().setdirty(); if ((!_historicfile) || (atdate == botime)) return cisread(_isamfile, curr().string(), _iscurr + lockop, &_lasterr); else { if (cisread(_isamfile, curr().string(), _iscurr + lockop, &_lasterr) == NOERR) _lasterr = gethr(curr(), atdate); } _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::reread(TRectype& rec, word lockop, TDate& atdate) { NOT_OPEN(name()); rec.setdirty(); if ((!_historicfile) || (atdate == botime)) cisread(_isamfile, rec.string(), _iscurr + lockop, &_lasterr); else { if (cisread(_isamfile, rec.string(), _iscurr + lockop, &_lasterr) == NOERR) _lasterr = gethr(rec, atdate); } _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::skip(TRecnotype nrec, word lockop) { NOT_OPEN(name()); if (!nrec) return NOERR; curr().setdirty(); if (nrec >0) cisread(_isamfile, curr().string(), _isnextn + lockop + (UINT16) nrec, &_lasterr); else cisread(_isamfile, curr().string(), _isprevn + lockop - (UINT16) nrec, &_lasterr); _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::read(word op, word lockop, TDate& atdate) { CHECKD(op >= _iscurr && op <= _isgteq, "Invalid read operation : ", op); NOT_OPEN(name()); curr().setdirty(); if ((!_historicfile) || (atdate == botime)) cisread(_isamfile, curr().string(), op + lockop, &_lasterr); else { if (cisread(_isamfile, curr().string(), op + lockop, &_lasterr) == NOERR) _lasterr = gethr(curr(), atdate); } _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(name()); rec.setdirty(); if ((!_historicfile) || (atdate == botime)) cisread(_isamfile, rec.string(), op + lockop, &_lasterr); else { if (cisread(_isamfile, rec.string(), op + lockop, &_lasterr) == NOERR) _lasterr = gethr(rec, atdate); } _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::readat(TRecnotype nrec, word lockop) { NOT_OPEN(name()); curr().setdirty(); cisreadrec(_isamfile, nrec, curr().string(), lockop, &_lasterr); _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::readat(TRectype& rec, TRecnotype nrec, word lockop) { NOT_OPEN(name()); rec.setdirty(); cisreadrec(_isamfile, nrec, rec.string(), lockop, &_lasterr); _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::write(TDate& atdate) { NOT_OPEN(name()); if ((!_historicfile) || (atdate == botime)) ciswrite(_isamfile, curr().string(), &_lasterr); else _lasterr = addhr(curr(), atdate); _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::write(const TRectype& rec, TDate& atdate) { NOT_OPEN(_isamfile->d->SysName); if ((!_historicfile) || (atdate == botime)) ciswrite(_isamfile, rec.string(), &_lasterr); else _lasterr = addhr(rec, atdate); _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::rewrite(TDate& atdate) { NOT_OPEN(name()); if ((!_historicfile) || (atdate == botime)) cisrewrite(_isamfile, curr().string(), &_lasterr); else _lasterr = rewhr(curr(), atdate); _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::rewrite(const TRectype& rec, TDate& atdate) { NOT_OPEN(name()); if ((!_historicfile) || (atdate == botime)) cisrewrite(_isamfile, rec.string(), &_lasterr); else _lasterr = rewhr(rec, atdate); _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::rewriteat(TRecnotype nrec) { NOT_OPEN(name()); return cisrewrec(_isamfile, nrec, curr().string(), &_lasterr); } int TBaseisamfile::rewriteat(const TRectype& rec, TRecnotype nrec) { NOT_OPEN(name()); return cisrewrec(_isamfile, nrec, curr().string(), &_lasterr); } int TBaseisamfile::remove(TDate& atdate) { NOT_OPEN(name()); if ((!_historicfile) || (atdate == botime)) cisdelete(_isamfile, curr().string(), &_lasterr); else _lasterr = delhr(curr(), atdate); _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::remove(const TRectype& rec, TDate& atdate) { NOT_OPEN(name()); if ((!_historicfile) || (atdate == botime)) cisdelete(_isamfile, rec.string(), &_lasterr); else _lasterr = delhr(rec, atdate); _recno = _isamfile->RecNo; return _lasterr; } int TBaseisamfile::lock() { NOT_OPEN(name()); return cislock(_isamfile, &_lasterr); } int TBaseisamfile::unlock() { NOT_OPEN(name()); return cisunlock(_isamfile, &_lasterr); } void TBaseisamfile::indexon() { IndexOn(); } bool TBaseisamfile::empty() { return _isamfile->i.Base[_isamfile->i.PN].PEOD == 0; } void TBaseisamfile::indexoff() { IndexOff(); } int TBaseisamfile::_open(unsigned int mode) { int err; if (filehnd() != NULL) fatal_box("Il file %d e' gia' aperto", _logicnum); if ((cisopen(&_isamfile, _logicnum, NOALLOC, mode, &err) == NOERR) && (_historicfile)) { TFilename s(filename()); s.ext("hst"); _hf.len() = filehnd()->d->LenR; _hf.base() = 1; _hf.open(s); if (_hf.status() == 2) { _hf.create(s); _hf.open(s); } if (_hf.error()) return err = _hf.status(); _lasthf = -1L; _hfhd = _hf; _hfhd.len() = sizeof(TRecnotype); _hfhd.base() = 0; } if (err == NOERR) { isdef * fh = filehnd(); const TRecnotype nitems = fh->i.Base[0].PEOX; if (fh->d->EOX != nitems) recover(); } _recno = -1L; _current->_i = filehnd(); setstatus(err); return err; } int TBaseisamfile::_close() { int err = NOERR; if (filehnd() != NULL) { cisclose(ptrfilehnd(), NULL, &err); clearfilehnd(); } _current->_i = NULL; 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) { cisclose(&_isamfile, NULL, &err); _isamfile = 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]; _current->_i = filehnd(); } 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) { int err; NOT_OPEN(name()); setstatus(err); return cisupdflags(filehnd(), &err, updateeod); } /////////////////////////////////////////////////////////// // TIsamtempfile /////////////////////////////////////////////////////////// TIsamtempfile::TIsamtempfile(int logicnum, const char* radix, bool create) : TLocalisamfile(logicnum, 2) { TRecnotype eod = 0; TRecnotype eox = 100; TFilename n; n.tempdir(); n << '/' << radix; n.ext("dta"); if (!create) { TDir dir; dir.get(logicnum); const word& len = dir.len(); FILE* f = fopen(n, "r"); CHECKS(f, "Can't open temporary file ", (const char*)n); fseek(f, 0, SEEK_END); eod = eox = ftell(f) / len; fclose(f); } _autodel = create > TRUE; n.ext(""); 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; if (filehnd() != NULL) fatal_box("File %s already open", filename()); if ((cisopentemp(ptrfilehnd(), _logicnum, (char*)radix, NOALLOC, create, eod, eox, &err) == NOERR) && (_historicfile)) { TFilename s(filename()); s.ext("hst"); _hf.len() = filehnd()->d->LenR; _hf.base() = 1; _hf.open(s); if (_hf.status() == 2) { _hf.create(s); _hf.open(s); } if (_hf.error()) return err = _hf.status(); _lasthf = -1L; _hfhd = _hf; _hfhd.len() = sizeof(TRecnotype); _hfhd.base() = 0; } _current->_i = filehnd(); _recno = -1L; setstatus(err); return err; } int TIsamtempfile::close() { int err = NOERR; if (filehnd() != NULL) { cisclosetemp(ptrfilehnd(), NULL, _autodel, &err); clearfilehnd(); } _current->_i = NULL; setstatus(err); return err; } /////////////////////////////////////////////////////////// // TSystemsamfile /////////////////////////////////////////////////////////// int TSystemisamfile::build(TRecnotype eox) { int err; if(filehnd() != NULL) fatal_box("Can't recreate open file %s", filename()); TDir d; d.get(num()); TFilename f(d.name()); f = f.path(); if (!fexist(f)) #if XVT_OS==XVT_OS_SCOUNIX mkdir(f, 0777); #else mkdir(f); #endif cisbuild(filehnd(), num(), eox, &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; if (filehnd() != NULL) fatal_box("Can't extend open file %s", filename()); cisextend(filehnd(), num(), eox, &err); setstatus(err); clearfilehnd(); return err; } long TSystemisamfile::size(TRecnotype eox) { int err; const long size = cisextension(num(), eox, &err); if (err != NOERR) setstatus(err); return size; } #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 <= stdlevel; 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("Non posso 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 <= stdlevel; 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) { if (filehnd() != NULL) fatal_box("Can't update description for open file %s", filename()); TDir dir; dir.get(num(), _lock, _nordir, _sysdirop); const char p = *dir.name(); const bool is_com = prefhndl->is_com(); const bool toconvert = is_com ? dir.is_com() : dir.is_firm(); int err = NOERR; TTrec oldrec; oldrec.get(num()); const long lev = prefhndl->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; TFilename tmpfname; tmpfname.temp(NULL); FILE* f = fopen(tmpfname, "w"); err = ferror(f); if (f == NULL) { clearerr(f); setstatus(err); return err; } open(_excllock); 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; for (int j = 0; j < nflds; j++) fld.add(TString(curr().fieldname(j)), j); for (i = 1; i <= nitems && !p.iscancelled(); i++) { if ((i % 50) == 0) p.setstatus(i + 1); readat(i); if (curr().valid()) { 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); fwrite(nrec.string(), lenr, 1, f); } } p.setstatus(nitems); close(); fclose(f); fcopy(tmpfname, fname); ::remove(tmpfname); dir.eod() = ni; } // aggiornare il log file dir.set_len(lenr); dir.put(num(), _nordir, _sysdirop); newrec.put(num()); if (toconvert && dir.eox() > 0L) packindex(); exec_convapp(lev, FALSE); return err; } int TSystemisamfile::packfile(bool vis) { int err; if (filehnd() != NULL) fatal_box("Can't pack open file %s", filename()); setstatus(creorgfile(num(), vis, &err)); return err; } int TSystemisamfile::packindex(bool vis) { int err; if (filehnd() != NULL) fatal_box("Can't pack open file %s", filename()); setstatus(creorgindex(num(), vis, &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 = ferror(fl); 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 > stdlevel) 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, stdlevel / 100, stdlevel % 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", prefhndl->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() { isdef * fh = filehnd(); const TRecnotype nitems = fh->i.Base[0].PEOX; CHECKD(getkey() == 1, "La chiave corrente non e' 1 ma ", getkey()); TFilename fn = filename(); fn = fn.name(); #ifndef FOXPRO if (yesno_box("La dimensione dell'archivio %s e' errata. Cerco di recuperarlo?", (const char *)fn)) { TDir d; TString mess(80); mess.format("Ricostruzione archivio %s : I Fase", (const char*) fn); TProgind p(nitems ? nitems : 1, mess, TRUE, TRUE, 70); const TDirtype dir = (fh->ft == 0) ? _nordir : _comdir; d.get(num(), _lock, dir, _sysdirop); d.eod() = fh->d->EOD = nitems; d.eox() = fh->d->EOX = nitems; d.put(num(), dir, _sysdirop); for (TRecnotype r = 1; r <= nitems; r++) { p.addstatus(1); CRead(&fh->f, curr().string(), r, _nolock); curr().discard(); CWrite(&fh->f, curr().string(), r, _nolock); } p.close_modal(); mess.format("Ricostruzione archivio %s : II Fase", (const char*) fn); TProgind pi(items() ? items() : 1, mess, TRUE, TRUE, 70); for (first(); good(); next()) { pi.addstatus(1); curr().recall(); rewrite(); } message_box("L'archivio %s deve essere compattato", (const char *) fn); } else #endif fatal_box("L'archivio %s e' incosistente e deve essere corretto prima di utilizzarlo", (const char *)fn); } //////////////////////////////////////////////////////////// // TRectype //////////////////////////////////////////////////////////// TRectype::TRectype(int logicnum) : _cod(NULL) { TDir wdir; _logicnum = logicnum; wdir.get(_logicnum, _nolock, _nordir, _sysdirop); if (wdir.name()[0] == '%') wdir.get(_logicnum, _nolock, _comdir, _sysdirop); _length = wdir.len(); _rec = new char [ _length ]; _i = openf[_logicnum - 1]; *_tab = '\0'; setempty(TRUE); } TRectype::TRectype(const TBaseisamfile* i) : _cod(NULL) { _logicnum = i->num(); if (i->filehnd() != NULL) _length = i->filehnd()->d->LenR; else { TDir wdir; wdir.get(_logicnum, _nolock, _nordir, _sysdirop); if (wdir.name()[0] == '%') wdir.get(_logicnum, _nolock, _comdir, _sysdirop); _length = wdir.len(); } *_tab = '\0'; _rec = new char [ _length ]; _i = i->filehnd(); 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); _i = r._i; strcpy(_tab, r._tab); if (r._cod != NULL) _cod = new TRecfield(*this, "COD"); setempty(r.empty()); } TRectype::~TRectype() { if (_cod != NULL) delete _cod; 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; } 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) /////////////////////////////////////////////////////////// int TRectype::items() const { return _i->r->NFields; } const char* TRectype::start(int nf) const { return string() + _i->r->Fd[nf].RecOff; } int TRectype::compare(const TSortable& s) const { const TRectype& br = (const TRectype&) s; int res = 0; if (br.empty()) return UNDEFINED; for (int i = 0; i < items() ; i++) { const char* b = br.start(i); const char* a = start(i); const byte typ = _i->r->Fd[i].TypeF; /* if (typ == _boolfld) res = *a - *b; else { */ const int sz = _i->r->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 { NOT_LINKED(_i, "type"); return (TFieldtypes) CFieldType((char*) fieldname, _i->r); } int TRectype::length(const char* fieldname) const { NOT_LINKED(_i, "length"); return CFieldSize((char*) fieldname, _i->r); } int TRectype::ndec(const char* fieldname) const { NOT_LINKED(_i, "dec"); return CFieldDec((char*) fieldname, _i->r); } bool TRectype::exist(const char* fieldname) const { NOT_LINKED(_i, "exist"); return findfld(_i->r, (char*)fieldname) != -1; } const char* TRectype::fieldname(int i) const { NOT_LINKED(_i, "fieldname"); return i >= 0 && i < _i->r->NFields ? _i->r->Fd[i].Name : NULL; } #ifndef FOXPRO int TRectype::get_int(const char* fieldname) const { NOT_LINKED(_i, "get_int"); if (CGetFieldBuff((char*) fieldname, _i->r, _rec, __tmp_string) == -1) UNKNOWN_FIELD(num(), fieldname); return atoi(__tmp_string); } long TRectype::get_long(const char* fieldname) const { NOT_LINKED(_i, "get_long"); if (CGetFieldBuff((char*) fieldname, _i->r, _rec, __tmp_string) == -1) UNKNOWN_FIELD(num(), fieldname); return atol(__tmp_string); } word TRectype::get_word(const char* fieldname) const { NOT_LINKED(_i, "get_word"); if (CGetFieldBuff((char*) fieldname, _i->r, _rec, __tmp_string) == -1) UNKNOWN_FIELD(num(), fieldname); return (word)atoi(__tmp_string); } real TRectype::get_real(const char* fieldname) const { NOT_LINKED(_i, "get_real"); if (CGetFieldBuff((char*) fieldname, _i->r, _rec, __tmp_string) == -1) UNKNOWN_FIELD(num(), fieldname); real r(__tmp_string); return r; } char TRectype::get_char(const char* fieldname) const { NOT_LINKED(_i, "get_char"); if (CGetFieldBuff((char*) fieldname, _i->r, _rec, __tmp_string) == -1) UNKNOWN_FIELD(num(), fieldname); return *__tmp_string; } bool TRectype::get_bool(const char* fieldname) const { NOT_LINKED(_i, "get_bool"); if (CGetFieldBuff((char*) fieldname, _i->r, _rec, __tmp_string) == -1) UNKNOWN_FIELD(num(), fieldname); return *__tmp_string == 'X'; } #endif // FOXPRO TDate TRectype::get_date(const char* fieldname) const { NOT_LINKED(_i, "get_date"); const TRecfield f((TRectype&)*this, fieldname); return (TDate) f; } const TString& TRectype::get(const char* fieldname) const { static TFixed_string s(__tmp_string, 256); NOT_LINKED(_i, "get"); if (CFieldType((char*) fieldname, _i->r) == _datefld) { const TRecfield f((TRectype&)*this, fieldname); s = (const char*) f; } else if (CGetFieldBuff((char*) fieldname, _i->r, _rec, __tmp_string) == -1) UNKNOWN_FIELD(num(), fieldname); return s; } #ifndef FOXPRO void TRectype::put(const char* fieldname, int val) { NOT_LINKED(_i, "put"); if (CPutField((char*) fieldname, _i->r, &val, _rec) == -1) UNKNOWN_FIELD(num(), fieldname); setempty(FALSE); } void TRectype::put(const char* fieldname, long val) { NOT_LINKED(_i, "put"); if (CPutField((char*) fieldname, _i->r, &val, _rec) == -1) UNKNOWN_FIELD(num(), fieldname); setempty(FALSE); } void TRectype::put(const char* fieldname, word val) { NOT_LINKED(_i, "put"); if (CPutField((char*) fieldname, _i->r, &val, _rec) == -1) UNKNOWN_FIELD(num(), fieldname); setempty(FALSE); } void TRectype::put(const char* fieldname, const real& val) { NOT_LINKED(_i, "put"); if (CPutField((char*) fieldname, _i->r, val.ptr(), _rec) == -1) UNKNOWN_FIELD(num(), fieldname); setempty(FALSE); } void TRectype::put(const char* fieldname, const TDate& val) { NOT_LINKED(_i, "put"); TRecfield f(*this, fieldname); f = val.string(4); setempty(FALSE); } void TRectype::put(const char* fieldname, char val) { NOT_LINKED(_i, "put"); char w[2] = {val, '\0'}; if (CPutFieldBuff((char*) fieldname, _i->r, w, _rec) == -1) UNKNOWN_FIELD(num(), fieldname); setempty(FALSE); } void TRectype::put(const char* fieldname, bool val) { NOT_LINKED(_i, "put"); char* s = val ? "X" : " "; if (CPutFieldBuff((char*) fieldname, _i->r, s, _rec) == -1) UNKNOWN_FIELD(num(), fieldname); setempty(FALSE); } #endif // FOXPRO void TRectype::put(const char* fieldname, const char* val) { NOT_LINKED(_i, "put"); if (val == NULL || *val == '\0') // Da provare { TRecfield f(*this, fieldname); if (*f.pos() == '\0') return; } if (CFieldType((char*) fieldname, _i->r) == _datefld) { TRecfield f(*this, fieldname); f = val; } else if (CPutFieldBuff((char*) fieldname, _i->r, (char*) val, _rec) == -1) UNKNOWN_FIELD(num(), fieldname); setempty(FALSE); } void TRectype::zero(const char* fieldname) { NOT_LINKED(_i, "zero"); if (_cod != NULL && strcmp(fieldname , "COD") == 0) *_cod = _tab; else if (CZeroField((char*) fieldname, _i->r, _rec) == -1) UNKNOWN_FIELD(num(), fieldname); } void TRectype::zero() { zero('\0'); } void TRectype::zero(char c) { NOT_LINKED(_i, "zero"); 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"); _i = rec._i; // Copy filehndl 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 99% TRectype& TRectype::operator =(const char* rec) { memcpy(_rec, rec, _length); setempty(FALSE); return *this; } const char* TRectype::key(int numkey) const { NOT_LINKED(_i, "key"); CBuildKey(_i->r, numkey, _rec, __tmp_string); return __tmp_string; } TRec_array::TRec_array(int dimension, TBaseisamfile& i) : TArray(dimension) { TRectype r(&i); for (int j = 0 ; j < size(); j++) add(r, j); } /////////////////////////////////////////////////////////// // TRecfield (campo/sottocampo di un record) /////////////////////////////////////////////////////////// void TRecfield::set(int from, int to) { int nf; const isdef* bf = _rec->filehnd(); if ((nf = findfld(bf->r, _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() + bf->r->Fd[nf].RecOff + from; _dec = bf->r->Fd[nf].Dec; _type = bf->r->Fd[nf].TypeF; if (to >= 0) { CHECK(from <= to && to <= bf->r->Fd[nf].Len, "Invalid Range"); _len = to - from + 1; } else _len = bf->r->Fd[nf].Len - from; } } TRecfield::TRecfield(TRectype& rec, const char* name, int from, int to) { strcpy(_name, name); NOT_LINKED(rec.filehnd(), "TRecfield"); _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)) { while ((*recin == ' ') && (l)) { recin++; l--; } if ((t != _realfld) && (t != _charfld) && (t != _intzerofld) && (t != _longzerofld)) { 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 (t == _datefld && *s) { TDate dt(atol(s)); strcpy(s, dt.string(4)); } } 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) { TDate dt(s2); sprintf(s2,"%06ld", (long) dt); } } else if (t == _realfld) setdec(s2, d); len = strlen(s2); if (len > l) return ; if ((t == _intfld) || (t == _longfld) || (t == _wordfld) || (t == _realfld)) { if (len == 0) { strcpy(s2, "0"); len = 1; } i = 0; while (i < l - len - 1) recout[i++] = ' '; 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(__tmp_string, "%0*d", _len, i); else sprintf(__tmp_string, "%d", i); __putfieldbuff( _len, _dec, _type, __tmp_string, _p); _rec->setempty(FALSE); return i; } long TRecfield::operator =(long l) { if (_type == _longzerofld) sprintf(__tmp_string, "%0*ld", _len, l); else sprintf(__tmp_string, "%ld", l); __putfieldbuff( _len, _dec, _type, __tmp_string, _p); _rec->setempty(FALSE); return l; } #ifndef FOXPRO const real& TRecfield::operator =(const real& r) { strcpy(__tmp_string, r.string()); __putfieldbuff( _len, _dec, _type, __tmp_string, _p); _rec->setempty(FALSE); return r; } #endif // FOXPRO const TDate& TRecfield::operator =(const TDate& d) { strcpy(__tmp_string, (const char*) d); __putfieldbuff( _len, _dec, _type, __tmp_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, __tmp_string); return atoi(__tmp_string); } TRecfield::operator long() const { __getfieldbuff( _len, _type, _p, __tmp_string); return atol(__tmp_string); } #ifndef FOXPRO TRecfield::operator const real() const { __getfieldbuff( _len, _type, _p, __tmp_string); real r(__tmp_string); return r; } #endif // FOXPRO TRecfield::operator TDate() const { static TDate d; __getfieldbuff( _len, _type, _p, __tmp_string); d = __tmp_string; return d; } TRecfield::operator const char*() const { __getfieldbuff( _len, _type, _p, __tmp_string); return __tmp_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; } void TTransaction::begin() { StTrans(); } void TTransaction::end(bool success) { if (success) EndTrans(); else AbTrans(); }