/**********************************************************************
 *
 * File.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.
 *
 *********************************************************************/

//////////////////////////////////////////////////////////////////////////
// File.h -- File Base class
// 
//////////////////////////////////////////////////////////////////////////
 

 
#ifndef __FILE_BASE__
#define __FILE_BASE__

#include "FileSystem.h"
# define __CPP_EXCEPTIONS__ 1

// CRC-32 checksum used to detect bit errors
typedef mg_u_long Checksum;


// Constants for file operations and stream position 
const int MaxNameLength             = 512;        // Max length of names buffers
const FileSystem::FAU_t StartOfFile = (FileSystem::FAU_t)0; // First byte in the file
const FileSystem::FAU_t CURRADDR    = (FileSystem::FAU_t)-1;// Indicates current location
const isis::uint32_t CheckWord      = 0xfefefefe;           // Default synchronization word
const isis::int32_t  FSListCorrupt  = (FileSystem::FAU_t)-1;// Free space list is corrupt


//------------------
// File  error codes
//------------------
enum FileError { 
  FILE_NO_ERROR = 0,   // No errors reported
  FILE_CHECKSUM_ERROR, // Checksum Error
  FILE_CLOSE_ERROR,    // Error closing file
  FILE_CORRUPT,        // File corrupted
  FILE_CREATION_ERROR, // Error creating file
  FILE_EXISTS,         // File already exists
  FILE_NOT_OPEN_ERROR, // Trying to use a closed file
  FILE_NOT_READY,      // File not ready (failed or closed file)
  FILE_NOT_WRITEABLE,  // Could not write to file 
  FILE_OPEN_ERROR,     // Error opening file
  FILE_POSITION_ERROR, // Cannot obtain the current file position
  FILE_READ_ERROR,     // Error reading file  
  FILE_SEEK_ERROR,     // Error seeking in file
  FILE_WRITE_ERROR,    // Error writing to file

  FMGR_NO_DATABASE_OPEN,    // No database open
  FMGR_NO_FILE_EXISTS,      // No such file exists
  FMGR_NO_OBJECTS_EXIST,    // No objects exist
  FMGR_NULL_PTR,            // Accessing a null pointer 
  FMGR_OBJECT_EXISTS,       // Object already exists
  FMGR_OPEN_FILE_REFERENCE, // Another object is referencing this file
  FMGR_OVERFLOW,            // Math overflow
  FMGR_PARSE_ERROR,         // Parse error
  FMGR_PATH_ERROR,          // Invalid path
  FMGR_READ_ONLY_FILE,      // Trying to write to read-only file
  FMGR_STACK_EMPTY,         // Stack empty
  FMGR_STACK_FULL,          // Stack full
  FMGR_SYNC_ERROR,          // Synchronization Error
  FMGR_UNDERFLOW,           // Math under-flow
  FMGR_WRONG_FILE_TYPE,     // Wrong file type

  // Persistent lock error codes
  FMGR_INVALID_LOCK_TYPE,        // Invalid lock type specified
  FMGR_FILELOCK_ACCESS_ERROR,    // The file lock cannot be accessed
  FMGR_FILELOCK_ERROR,           // Error locking the file
  FMGR_RECORDLOCK_ACCESS_ERROR,  // The record lock cannot be accessed
  FMGR_RECORDLOCK_ERROR          // Error locking a record};


};




class DLL_CODE_API CFileBase 
{
protected:
    // File I/O operation codes
  enum IO_Op { 
     IO_READ,         // A read was performed
     IO_WRITE,        // A write operation was performed
     IO_REWIND,       // A rewind operation was performed
     IO_NO_OPERATION, // No operation was performed
     IO_SEEK          // A seek operation was preformed 
  };

  _TCHAR            file_name[MaxNameLength];  // Open file name
  FileSystem::FPTR* fp;                        // Stream file handle
  IO_Op             last_operation;            // Last I/O operation preformed
  FileError         file_error;                // Last reported file error

  // File status members
  int is_ok;             // Used to signal a fatal error condition
  int is_open;           // True if the file is open
  int ready_for_reading; // True if the file is ready for reading
  int ready_for_writing; // True if the file is ready for writing


public:
   CFileBase();
   virtual ~CFileBase();

public: // File functions
   virtual FileError Create(const TCHAR *fname);
   virtual FileError Open(const TCHAR *fname, FileSystem::AccessMode mode = FileSystem::FILE_READWRITE); 
   virtual FileError Close();
   
   FileError         Seek(FileSystem::FAU_t offset, FileSystem::SeekMode mode = FileSystem::FILE_SEEK_BEG);
 
   FileError         Fetch(void* buf, isis::uint32_t nBytes, FileSystem::FAU_t file_addres = CURRADDR);
   FileError         Store(const void* buf, isis::uint32_t nBytes, FileSystem::FAU_t file_address = CURRADDR,
			                int flush_flag = 1, int bit_test = 1);

   FileSystem::FAU_t     SeekTo(FileSystem::FAU_t file_address);
   FileSystem::StreamPos FilePosition();

   FileError Flush();

   _TCHAR *FileName() { return file_name; }

public: // 32-bit CRC checksum routines 
  isis::uint32_t CalcChecksum(isis::uint32_t bytes, FileSystem::FAU_t file_address, int mem_alloc = 1);

public:  // File Status functions
  int IsOK()                  { return ((is_ok == 1) && (is_open == 1)); }
  int IsOK()            const { return ((is_ok == 1) && (is_open == 1)); }
  int IsOpen()                { return ((is_ok == 1) && (is_open == 1)); }
  int IsOpen()          const { return ((is_ok == 1) && (is_open == 1)); }
  int ReadyForReading()       { return ready_for_reading == 1; }
  int ReadyForReading() const { return ready_for_reading == 1; }
  int ReadyForWriting()       { return ready_for_writing == 1; }
  int ReadyForWriting() const { return ready_for_writing == 1; }

public:  // Exception handling functions
  FileError   GetFileError()              { return file_error; }
  FileError   GetFileError() const        { return file_error; }
  void        SetFileError(FileError err) { file_error = err; }
  void        ResetFileError()            { file_error = FILE_NO_ERROR; }
  const TCHAR *FileExceptionMessage();

public: // General purpose file utilities
  static int Exists(const TCHAR *fname);
  static FileSystem::FAU_t FileSize(const TCHAR *fname);
  static int CanOpenForWriting(const TCHAR *fname);
  static int CanOpenReadOnly(const TCHAR *fname);
  
};


#ifdef __CPP_EXCEPTIONS__
// Class declarations for exceptions representing program errors. 
// This implementation is provided for use C++'s built-in exception
// handling routines.

class CFileBaseException 
{
	int error_;
public:
	CFileBaseException(int error) { error_ = error; }
};  

#endif // __CPP_EXCEPTIONS__
 
#endif   // __FILE_BASE__
