301 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			301 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
#include <multirec.h>
 | 
						|
 | 
						|
void TMultiple_rectype::set_body_key(TRectype & rowrec)
 | 
						|
{
 | 
						|
  const RecDes* recd = rowrec.rec_des();    // Descrizione del record della testata
 | 
						|
  const KeyDes& kd = recd->Ky[0];       // Elenco dei campi della chiave 1
 | 
						|
  
 | 
						|
    // Copia tutti i campi chiave, tranne l'ultimo, in tutti i records
 | 
						|
  for (int i = kd.NkFields-2; i >= 0; i--)
 | 
						|
  {                        
 | 
						|
    const int nf = kd.FieldSeq[i] % MaxFields;
 | 
						|
    const RecFieldDes& rf = recd->Fd[nf];  
 | 
						|
    const TString& val = get(rf.Name);
 | 
						|
    rowrec.renum_key(rf.Name, val);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TMultiple_rectype::load_rows_file(int logicnum)
 | 
						|
{
 | 
						|
  const int index = log2ind(logicnum);
 | 
						|
  TRectype * rec = new_body_record(logicnum);
 | 
						|
  set_body_key(*rec);
 | 
						|
  if (_files.objptr(index) == NULL)
 | 
						|
  {
 | 
						|
    // crea
 | 
						|
    TRecord_array * r = new TRecord_array(logicnum, (TString &) _numfields[index]);
 | 
						|
    _files.add( r, index);
 | 
						|
  }
 | 
						|
  ((TRecord_array &)_files[index]).read(rec);  // rilegge
 | 
						|
  _changed[index]=FALSE;
 | 
						|
}
 | 
						|
 | 
						|
int TMultiple_rectype::find(int logicnum, const char * fieldname, const char * s, int from, bool reverse) const
 | 
						|
{
 | 
						|
  const TRecord_array & recarray = body(logicnum);
 | 
						|
  const int last = recarray.last_row();
 | 
						|
  const int len = s ? strlen(s) : 0;
 | 
						|
 | 
						|
  if (reverse)
 | 
						|
  {
 | 
						|
    if (from > 0)
 | 
						|
    {
 | 
						|
      if (len == 0)
 | 
						|
        return from - 1;
 | 
						|
      for (int i = recarray.pred_row(from); i > 0; i = recarray.pred_row(i))
 | 
						|
        if (recarray[i].get(fieldname) == s)
 | 
						|
          return i;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    if (last > from)
 | 
						|
    {
 | 
						|
      if (len == 0)
 | 
						|
        return from + 1;
 | 
						|
      for (int i = recarray.succ_row(from); i <= last; i = recarray.succ_row(i))
 | 
						|
        if (recarray[i].get(fieldname) == s)
 | 
						|
          return i;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return -1;
 | 
						|
}
 | 
						|
 | 
						|
int TMultiple_rectype::write_rewrite(TBaseisamfile & f, bool re) const
 | 
						|
{
 | 
						|
  int err = NOERR;
 | 
						|
 | 
						|
  if (_nuovo && re)           // E' nuovo di zecca! quindi ...
 | 
						|
    re = FALSE;               // ... non fare la rewrite
 | 
						|
 | 
						|
  if (re)
 | 
						|
  {
 | 
						|
    for (int i = _nfiles - 1; err == NOERR && i >= 0 ; i--)
 | 
						|
    {
 | 
						|
      TRecord_array * r = (TRecord_array *) _files.objptr(i);
 | 
						|
      if (r && !_changed[i])
 | 
						|
        err = r->write(re);
 | 
						|
    }
 | 
						|
    // rewrite:
 | 
						|
    if (err == NOERR)
 | 
						|
    {
 | 
						|
      err = TRectype::rewrite(f);
 | 
						|
      if (err != NOERR)
 | 
						|
        err = TRectype::write(f);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    // write:
 | 
						|
    if (_nuovo)
 | 
						|
    {
 | 
						|
      do
 | 
						|
      {
 | 
						|
        err = TRectype::write(f);
 | 
						|
        if (err == _isreinsert && ((TMultiple_rectype *)this)->renum())
 | 
						|
           ((TMultiple_rectype *)this)->renum_key();
 | 
						|
      } while (err == _isreinsert);
 | 
						|
      ((TMultiple_rectype *)this)->_nuovo = (err != NOERR);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      err = TRectype::write(f);
 | 
						|
      if (err != NOERR)
 | 
						|
        err = TRectype::rewrite(f);
 | 
						|
    }
 | 
						|
    for (int i = _nfiles - 1; err == NOERR && i >= 0 ; i--)
 | 
						|
    {
 | 
						|
      TRecord_array * r = (TRecord_array *)_files.objptr(i);
 | 
						|
      if (r && !_changed[i])
 | 
						|
        err = r->write(re);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return err;
 | 
						|
}
 | 
						|
 | 
						|
void TMultiple_rectype::remove_body(int logicnum)
 | 
						|
{
 | 
						|
  const int index = log2ind(logicnum);
 | 
						|
 | 
						|
  if (_files.objptr(index) != NULL)
 | 
						|
    _files.remove(index);
 | 
						|
}
 | 
						|
 | 
						|
int TMultiple_rectype::log2ind(int logicnum) const
 | 
						|
{
 | 
						|
  if (logicnum == 0)
 | 
						|
    return 0;
 | 
						|
  for (int i = _nfiles - 1; i >= 0 ; i--)
 | 
						|
    if (_logicnums[i] == logicnum)
 | 
						|
      return i;
 | 
						|
  NFCHECK("Can't find file %d in multiple record", logicnum);
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
TRecord_array & TMultiple_rectype::body(int logicnum) const
 | 
						|
{
 | 
						|
  const int index = log2ind(logicnum);
 | 
						|
 | 
						|
  if (_files.objptr(index) == NULL || _changed[index])
 | 
						|
    ((TMultiple_rectype *) this)->load_rows_file(_logicnums[index]);
 | 
						|
  return (TRecord_array &) _files[index];
 | 
						|
}
 | 
						|
 | 
						|
void TMultiple_rectype::renum_key()
 | 
						|
{
 | 
						|
  for (int i = _nfiles - 1; i >= 0 ; i--) 
 | 
						|
  {
 | 
						|
    const int logicnum = _logicnums[i];
 | 
						|
    TRecord_array * b = (TRecord_array *) _files.objptr(i);
 | 
						|
    if (b)
 | 
						|
    {
 | 
						|
      TRectype * rec = new TRectype(b->key());
 | 
						|
 | 
						|
      set_body_key(*rec);
 | 
						|
      b->set_key(rec); // Aggiorna righe
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
TRectype & TMultiple_rectype::operator =(const TRectype & r)
 | 
						|
{
 | 
						|
  TRectype::operator=(r);
 | 
						|
  reset_fields(*this);
 | 
						|
  set_fields(*this);
 | 
						|
  return *this;
 | 
						|
}
 | 
						|
 | 
						|
TRectype & TMultiple_rectype::operator =(const char * r)
 | 
						|
{
 | 
						|
  TRectype::operator=(r);
 | 
						|
  reset_fields(*this);
 | 
						|
  set_fields(*this);
 | 
						|
  return *this;
 | 
						|
}
 | 
						|
 | 
						|
void TMultiple_rectype::zero(char c)
 | 
						|
{
 | 
						|
  reset_fields(*this);
 | 
						|
  TAuto_variable_rectype::zero(c);
 | 
						|
  for (int i = _nfiles - 1; i >= 0 ; i--)
 | 
						|
    if (_files.objptr(i) != NULL)
 | 
						|
      ((TRecord_array &)_files[i]).destroy_rows();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int TMultiple_rectype::read(TRectype & rec, word op, word lockop)
 | 
						|
{
 | 
						|
  TLocalisamfile f(num());
 | 
						|
  int err = NOERR;
 | 
						|
 | 
						|
  *this = rec;
 | 
						|
  _nuovo = FALSE;
 | 
						|
 | 
						|
  if (op == _isequal)
 | 
						|
  {
 | 
						|
    TRectype r(rec);
 | 
						|
  
 | 
						|
    err = TRectype::read(f, op, lockop);
 | 
						|
    if (err != NOERR)
 | 
						|
    {
 | 
						|
      *this = r;
 | 
						|
      _nuovo = TRUE;
 | 
						|
    }
 | 
						|
  }                
 | 
						|
  else
 | 
						|
    err = TRectype::read(f, op, lockop);
 | 
						|
  for (int i = _nfiles - 1; i >= 0 ; i--)
 | 
						|
  {
 | 
						|
    if (_nuovo)          
 | 
						|
    {   
 | 
						|
      TRecord_array * b = (TRecord_array *) _files.objptr(i);
 | 
						|
      if (b != NULL)
 | 
						|
      {
 | 
						|
        _changed[i] = FALSE;
 | 
						|
        b->destroy_rows();  
 | 
						|
        TRectype * r = new_body_record(_logicnums[i]);
 | 
						|
        set_body_key(*r);
 | 
						|
        b->set_key(r);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      if (_autoload[i])
 | 
						|
        load_rows_file(_logicnums[i]);
 | 
						|
      else
 | 
						|
        if (_files.objptr(i) != NULL)
 | 
						|
          _changed[i] = TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return err;
 | 
						|
}
 | 
						|
 | 
						|
int TMultiple_rectype::remove(TBaseisamfile & f) const
 | 
						|
{
 | 
						|
  int err = NOERR;
 | 
						|
 | 
						|
  for (int i = _nfiles - 1; err == NOERR && i >= 0 ; i--)
 | 
						|
  {
 | 
						|
    TRecord_array & r = body(_logicnums[i]);
 | 
						|
    err = r.remove();
 | 
						|
  }
 | 
						|
  if (err == NOERR)
 | 
						|
    err = TRectype::remove(f);
 | 
						|
  return err;
 | 
						|
}
 | 
						|
 | 
						|
// @doc INTERNAL
 | 
						|
TMultiple_rectype::TMultiple_rectype(int hfn)
 | 
						|
                  : TAuto_variable_rectype(hfn), _nuovo(TRUE), _nfiles(0)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
void TMultiple_rectype::enable_autoload(int logicnum,bool on)
 | 
						|
{
 | 
						|
  const int index = log2ind(logicnum);
 | 
						|
  _autoload[index] = on;
 | 
						|
}
 | 
						|
 | 
						|
bool TMultiple_rectype::autoload_enabled(int logicnum)
 | 
						|
{
 | 
						|
  return _autoload[log2ind(logicnum)];
 | 
						|
}
 | 
						|
 | 
						|
// @cmember Aggiunge il corpo lgicnum
 | 
						|
void TMultiple_rectype::add_file(int logicnum, const char * numfield)
 | 
						|
{
 | 
						|
	CHECK(_nfiles < maxfiles, "Too many files added");
 | 
						|
	_logicnums[_nfiles] = logicnum;
 | 
						|
	_autoload[_nfiles] = FALSE;
 | 
						|
	_numfields.add(numfield, _nfiles++);
 | 
						|
}
 | 
						|
 | 
						|
TMultiple_rectype::TMultiple_rectype(const TBaseisamfile* file)
 | 
						|
                  :TAuto_variable_rectype(file), _nuovo(TRUE), _nfiles(0)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
  // @ cmember costruttore dal record
 | 
						|
TMultiple_rectype::TMultiple_rectype(const TRectype & rec)
 | 
						|
                  :TAuto_variable_rectype(rec), _nuovo(TRUE), _nfiles(0)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
// @mfunc costruttore di copia
 | 
						|
TMultiple_rectype::TMultiple_rectype(const TMultiple_rectype& r)
 | 
						|
                  :TAuto_variable_rectype(r), _files(r._files)
 | 
						|
{
 | 
						|
  // copia..
 | 
						|
  _nuovo=r._nuovo;
 | 
						|
  _nfiles=r._nfiles;    // file delle righe
 | 
						|
  for (int i = _nfiles - 1; i >= 0; i--) 
 | 
						|
  {
 | 
						|
    _logicnums[i] = r._logicnums[i];
 | 
						|
    _changed[i] = r._changed[i];
 | 
						|
    _autoload[i] = r._autoload[i];
 | 
						|
  }
 | 
						|
  _numfields=r._numfields;
 | 
						|
}
 | 
						|
 |