/***********************************************************************

                      CSDB Library, Free Evaluation Version 2.2.0 
                                           Release: June 9th 1997 

       Header file of the DLAY class.

                                           Copyright(c) 1994-1997 
                                                          ComBits 
                                                  The Netherlands 
***********************************************************************/

#ifndef __CSDLAY_H
#define __CSDLAY_H

#include "cspage.h"
#include "csdli.h"
#include "cscopton.h"

#ifdef feof
  #undef feof
#endif



struct olpo_ds
{
   U32	pos;
   U32	page;
   S16	offset;
}; // OLay-POs



class DLAY: public DLAYI
{

 protected:

     typedef struct
     {
	U32  p_page;
	U32  n_page;
	S16  used;	// number of bytes in use on this page
     } olhe;		// OLay HEad

       typedef struct olpo_ds olpo;

protected:

     olpo current;
     U32  last_page;
     U32  last_pos;
     U32  first_page;
     U16  per_page;

  protected:


     void init_vars(void);
     void init_defaults(void) {}

     void prev_page_a(olpo &olp);
     void next_page_a(olpo &olp);
     inline
     void next_page_a(olhe *hp,olpo &olp);
     inline
     void start_page(olpo &olp);

//////////////////////// Page manipulation ///////////////////////////////

     olpo insert_page(olpo &olp);
     void unchain_page(olpo &pos);
     void append_page(void);
     inline
     U32  new_page(void);
     inline
     void free_page(U32 p);

//////////////////////// Skip  //////////////////////////////////////////

     void skip_plus(olpo &olp,U32  delta);
     void skip_min(olpo &olp ,U32  delta);
     inline
     void skip_t(olpo &pos   ,S32 delta);
     inline
     void skip_plus_t(olpo &pos,U32 delta);
     inline
     void skip_min_t(olpo &pos ,U32 delta);

/////////////////////////// DB Header ///////////////////////////////////
     virtual int read_header(void);
     virtual int write_header(void);



//////////////////////// Disk access ////////////////////////////////////

     olhe *HP(U32 page)  { return (olhe *)load_page_h(page); }
     olhe *HPd(U32 page) { return (olhe *)load_page_hd(page); }


/////////////////////////  Modifying page header //////////////////////////////////
     inline
     void modify_head(U32 page,U32 p_page,U32 n_page);
     inline
     void modify_head(U32 page,U32 p_page,U32 n_page,U16 used);
     inline
     void modify_p_page(U32 page,U32 p_page);
     inline
     void modify_n_page(U32 page,U32 n_page);


/////////////////////////  Prev/Next page number //////////////////////////////////
     inline
     U32  prev_page_num(olpo& olp);
     inline
     U32  prev_page_num(U32 page);
     inline
     U32  next_page_num(olpo& olp);
     inline
     U32  next_page_num(U32  page);
     inline
     U32  next_page_num(olhe *hp);


/////////////////////////  Pointers ///////////////////////////////////////////////

     inline
     csCHAR *pos_po(olpo &olp);
     inline
     csCHAR *pos_pod(olpo &olp);
     inline
     csCHAR *pos_pod_last(void);

/////////////////////////  Amount of data on a page ///////////////////////////////

     U16  is_used(olpo &olp)  { return is_used(olp.page); }
     U16  is_used(U32  page)  { return HP(page)->used; }

     inline
     void modify_used(olpo &pos,U16 use);
     inline
     void modify_used(U32 page,U16 use);
     inline
     void modify_used_delta(olpo &pos,S16 delta);
     inline
     void modify_used_delta(U32 page,S16 delta);

// Can become negative!
     inline
     S16  left_used(olpo &olp);
     inline
     S16  left_used(olhe *hp,U16 offset);

     inline
     U16  space_free(olpo &olp);
     inline
     U16  space_free(U32 page);

/////////////////////////  Locating //////////////////////////////////////////////

     void go_to(olpo &pos,U32 new_pos);
     olpo go_to(U32  pos);
     inline
     void last(olpo &pos);

/////////////////////////  Auxiliary //////////////////////////////////////////////

     U16  mini_off(void)   { return sizeof(olhe); }
     U16  max_free(void)   { return per_page; }
     void ola_copy(olpo &p2,olpo &p1,U16 len);

     virtual void set_id(void);
     virtual int check_id(U32 id);



/////////////////////////  Support for public functions ////////////////////////////

     void del_mod_use(olpo &pos,U16 new_used);
     int  replace(olpo &pos,U32 old_len,void *p_new,U32 new_len);
     inline
     U16  stil_fit(olpo &pos);
     inline
     U16  stil_fit(U16 used );


/////////////////////////  Table functions ////////////////////////////////////////

     int  table_look(U32 pos,olpo& op);
     int  table_insert(olpo& op);
     inline
     void table_insert(U32 pa,U32 po);
     void table_delete_update(olpo& op,U32 len);
     void table_insert_update(olpo& op,U32 len);
     inline
     void table_unchain_update(olpo &pos);


////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////// PUBLIC FUNCTIONS ////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////


  public:

     DLAY(void);
     virtual
    ~DLAY(void);


//////////////////////// Definition //////////////////////////////////////////
     int  define(csCHAR *name)		     { return define(name,page_size()); }
     int  define(csCHAR *name,U16 page_length);

//////////////////////// Open & Close ////////////////////////////////////////
     int  open(csCHAR *name,S16 kb_buf=30);
     void save(void)			     { BUFFER::save(); }
     int  close();

//////////////////////// Read & Write ////////////////////////////////////////
     U32  read(U32  pos,void *p,U32 len)
	  { olpo op=go_to(pos); return read(op,p,len); }
     U32  read(olpo &pos, void *p,U32 len);

     int  write(U32  pos,void *p,U32 len)
	  { olpo op=go_to(pos); return write(op,p,len); }
     int  write(olpo &pos,void *p,U32 len); //Pos will change!

//////////////////////// Append  /////////////////////////////////////////////
     int  append(void *p,U32 len);
     int  append(olpo &pos,void *p,U32 len);

//////////////////////// Replace /////////////////////////////////////////////
     int  replace(U32 pos,U32 old_len,void *p_new,U32 new_len)
	  { olpo op=go_to(pos); return replace(op,old_len,p_new,new_len); }

//////////////////////// Delete //////////////////////////////////////////////
     S32  delet(U32  pos,S32 len)
	  { olpo op=go_to(pos); return delet(op,len); }
     S32  delet(olpo &pos,S32 len);

//////////////////////// Insert //////////////////////////////////////////////
     int  insert(U32 pos,void *p,U32 len)
	  { olpo op=go_to(pos); return insert(op,p,len); }
     int  insert(olpo &pos,void *p,U32 len);

//////////////////////// Import & Export //////////////////////////////////////
     int  import_bin(csCHAR *name)  { return import(name,TRUE);  }
     int  import_asc(csCHAR *name)  { return import(name,FALSE); }
     int  import(csCHAR *name,int bin_mode=TRUE);

     int  export_bin(csCHAR *name)  { return export(name,TRUE);  }
     int  export_asc(csCHAR *name)  { return export(name,FALSE); }
     int  export(csCHAR *name,int bin_mode=TRUE);

//////////////////////// Number of bytes in File ///////////////////////////////
     U32  filesize(void)      { return bottom()-1; }


////////////////////////// Reports /////////////////////////////////////////////
     int  report(csCHAR *name,int sub=1);
     void report(FILE *fp,int sub=1);


////////////////////////// Working at the edge /////////////////////////////////


     int insapp(U32  pos,void *p,U32 len)
     {
	if (pos==bottom()) return append(p,len);
	else		   return insert(pos,p,len);
     }

     int insapp(olpo &pos,void *p,U32 len)
     {
	if (pos.pos==bottom()) return append(pos,p,len);
	else		       return insert(pos,p,len);
     }

     int wriapp(olpo &pos,void *p,U32 len);


////////////////////////// Sequential IO ///////////////////////////////////////

    int   fseek(long offset,int origin=SEEK_SET);
    long  ftell(void)  { return current.pos-1; }
    int   feof(void)   { return (current.pos==bottom()); }
    int   fgetc(void);
    int   fputc(int csCHARacter);
    int   fread( void *buf,int size,int count);
    int   fwrite(void *buf,int size,int count);
  csCHAR *fgets(csCHAR *str,int num);
    int   fputs(csCHAR *str) { return !fwrite(str,strlen(str),1); }

    long  fdelete(long amount);
    int   finsert(void *buf,long amount);


//////////////////////// Data in Header Page /////////////////////////////////
  /* Inherited
     int  data_2_header(void * ptr,U16 length);
     int  header_2_data(void * ptr,U16 length);
     U16  max_data_in_header(void);
  */


////////////////////////// Miscellaneous ///////////////////////////////////////
/* Inherited
     int  background(void)
*/
     int  pack(void);
     int  empty(void);
     U32  bottom(void)		 { return last_pos; }
     void info(void);
     void fflush(void)		 { BUFFER::save(); }

     virtual int class_ID(void)  { return CS_CLID_DLAY; }

};



#include "cscoptof.h"

#endif
