/**********************************************************************
 *
 * XRFFile.h
 * Copyright (C) 2003  UNESCO
 *
 * A component of the Greenstone digital library software
 * from the New Zealand Digital Library Project at the
 * University of Waikato, New Zealand.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *********************************************************************/

////////////////////////////////////////////////////////////
// XRFFILE.H : Cross Ref File object
//
////////////////////////////////////////////////////////////
 
#ifndef _XRFFILE_H_
#define _XRFFILE_H_
#ifndef _BLKFILE_H_
#include "blkfile.h"
#endif
#include <assert.h>
#include "IErrors.h"
 
const int MAXTIV     =     127; //  # of XRF entries per block
const int XRFBLKSIZE =     512; //
const int MAXMFB     = 1048576; 

 
 
/////////////////////////////////////////
// Cross reference file data structures
//
 
 
struct MSTA_ENTRY                 // Unpacked MST address
{             
   mg_s_long       xrfmfb_;             // Master file block
   short int  xrfmfp_;             // Offset
} ;
 
struct XRFA                       // To strore unpacked addresses
{                
   mg_s_long          xrfpos_;          // Block number on xrf_ file or -1 if empty
   short int     xrfeof_;          // 1 if last block of xrf_ file
   MSTA_ENTRY xrftiv_[MAXTIV];     // MAXTIV unpacked MST addresses

   XRFA() { Init(); }

   void Init()
   {
	   xrfeof_ = 0;              // Not eof
	   xrfpos_ = -1;             // empty   
	   for (int i=0; i<MAXTIV; i++)
	   {
		   xrftiv_[i].xrfmfb_  = -1;
	       xrftiv_[i].xrfmfp_  = 0;
	   }
   }


} ;
 
struct XRF                       // To store packed addresses
{                                // for reading and wrting
   mg_s_long xrfpos_;                  // block number on xrf_ file
   mg_s_long xrftiv_[MAXTIV];          // MAXTIV packed MST addresses 
} ;
 
///////////////////
// XrfFile class
//

 
class XrfFile : public BlkFile 
{
private:
   XRF*  xrf_;             // Buffer to store packed addresses
   XRFA* xrfa_;            // Buffer to store unpacked addresses
   mg_s_long  last_block_;      // Should always contain the last allocated block
   
   void ReadXrf(mg_s_long b);
   void WriteXrf(mg_s_long b);
   void UnPack();
   void Pack();
   void Grow(mg_s_long from_lastb, mg_s_long to_lastb);
public:
   XrfFile();
   IsisError OpenXrf(const _TCHAR *fname,
	                 FileSystem::AccessMode mode = FileSystem::FILE_READWRITE);
   IsisError CreateXrf(const _TCHAR *fname);
   IsisError CreateXrf(const _TCHAR *fname, mg_s_long nextMfn);
  ~XrfFile();
   int  GetMfp(mg_s_long mfn, mg_s_long& mfb, int& mfp);
   void PutMfp(mg_s_long mfn, mg_s_long mfb, int mfp, int status);
};
 
//////////////////////////////
 
inline XrfFile::XrfFile()  :
// Makes a XrfFile object that isn't connected to a file
   xrf_(new XRF),
   xrfa_(new XRFA)
{
   last_block_ = -1;   // Not yet initialize
   // Nothing more to do
}
 
//////////////////////////////
 
 
inline XrfFile::~XrfFile()
{
   if (xrf_)  delete xrf_;
   if (xrfa_) delete xrfa_;
}
 
//////////////////////////////
 
inline void XrfFile::ReadXrf(mg_s_long b)
// Reads block # b into xrf_ buffer
{
	assert(b>0);
    ReadBlk(xrf_, b);
    UnPack();
}
 
//////////////////////////////
 
inline void XrfFile::WriteXrf(mg_s_long b)
// Writes the content of xrf_ buffer as block number b
{
	assert(b>0);
    Pack();
    WriteBlk(xrf_, b);
}
#endif
