#if !defined(__alfffile_h) // Sentry, use file only if it's not already included.
#define __alfffile_h
/*  Project Biblio-Tec

	 SUBSYSTEM:    TEC30r.dll Library (TecLib)
	 FILE:         alfffile.h
	 AUTHOR:       Alcindo Ferreira Filho

	 OVERVIEW:
	 ALFFFile (Generic Unbuffered File) Class definition.

    COPYRIGHT:    © 2002-2005
                  Alcindo Ferreira Filho
                  <alcindo@inttec.com.br>

    LICENSE:      Biblio-Tec license (BiblTec.txt)
*/

#ifndef __STDLIB_H
#include <stdlib.h>
#endif

#ifndef __STDIO_H
#include <stdio.h>
#endif

#ifndef __FCNTL_H
#include <fcntl.h>
#endif

#ifndef __STAT_H
#include <sys/stat.h>
#endif

#ifndef __SHARE_H
#include <share.h>
#endif

#ifndef __IO_H
#include <io.h>
#endif

#ifndef __DOS_H
#include <dos.h>
#endif

#if !defined( __SYSTYPES_H )
#include <systypes.h>
#endif

#include <windows.h>

#include "alffobj.h"

// This class is available only under WIN32 Targets
#ifdef _WIN32
struct ALFFFileStatus
{
	 SYSTEMTIME createTime;
	 SYSTEMTIME modifyTime;
	 SYSTEMTIME accessTime;
	 long  fileSize;
	 DWORD attributes;
    HANDLE fileHandle;
	 char fullName[_MAX_PATH];
};


class _TECLIBCLASS ALFFFile : public ALFFObject
{
public:

	 ALFFFile();
	 ALFFFile( HANDLE handle );
    ALFFFile( const ALFFFile& file);
	 ALFFFile( const char* name,
				  DWORD access=GENERIC_READ,
				  DWORD permission=FILE_SHARE_READ,
				  DWORD flagCreate=OPEN_EXISTING,
				  DWORD flagAttr=FILE_ATTRIBUTE_NORMAL );
	~ALFFFile();
    char far* GetClassName() {return "ALFFFile";}
	 int Open( const char* name,
				  DWORD access, DWORD permission,
				  DWORD flagCreate, DWORD flagAttr );
	 int Close();

	 HANDLE GetHandle() const;

	 long Position() const;
	 DWORD Length() const;
	 void Length( long newLen );
	 long Seek( long offset, DWORD origin = FILE_BEGIN );
	 long SeekToBegin();
	 long SeekToEnd();
	 int  GetStatus( ALFFFileStatus& status ) const;
	 int  IsOpen() const;
	 DWORD Read( void* buffer, unsigned long numBytes );
	 DWORD Write( const void* buffer, unsigned long numBytes );
	 void Flush();

	 void LockRange( long position, uint32 count );
	 void UnlockRange(long Position, uint32 count );

	 static int GetStatus( const char* name, ALFFFileStatus& status, bool closeHandle=true );
	 static int SetStatus( const char* name, const ALFFFileStatus& status );
	 static void Remove( const char* name );
	 static void Rename( const char* oldName, const char* newName );

private:

	 HANDLE Handle;         // Low-level C file handle
	 char*  FileName;
	 int ShouldClose;       // Should C++ object close file on dtor

};

//---------------------------------------------------------------------------
// Inlines
//---------------------------------------------------------------------------

inline ALFFFile::ALFFFile() : Handle( INVALID_HANDLE_VALUE ), ShouldClose(0)
{
 FileName = NULL;
}

inline ALFFFile::ALFFFile( HANDLE h ) : Handle(h), ShouldClose(0)
{
 FileName = NULL;
}

inline ALFFFile::ALFFFile( const ALFFFile& file) : ShouldClose(1)
{
  HANDLE thisProcessHnd = ::GetCurrentProcess();
  DuplicateHandle( thisProcessHnd, file.Handle, thisProcessHnd, &Handle,
                   0, true, DUPLICATE_SAME_ACCESS);
}

inline ALFFFile::ALFFFile( const char* name, DWORD access,
									DWORD permission, DWORD flagCreate,
									DWORD flagAttr) :
								  Handle(INVALID_HANDLE_VALUE),
								  ShouldClose(1),
                          ALFFObject()
{
 FileName = NULL;
 Open( name, access, permission, flagCreate, flagAttr );
}

inline ALFFFile::~ALFFFile()
{
	 if( IsOpen() && ShouldClose )
		  ::CloseHandle(Handle);
	 if (FileName)
	  delete [] FileName;
}
inline HANDLE ALFFFile::GetHandle() const
{
	 return Handle;
}

inline long ALFFFile::Position() const
{
	 return ::SetFilePointer(Handle,0,NULL,FILE_CURRENT);
}

inline int ALFFFile::IsOpen() const
{
	 return Handle != INVALID_HANDLE_VALUE;
}

inline void ALFFFile::Length( long newLen )
{
  newLen = ::GetFileSize( Handle, NULL );
}

inline long ALFFFile::Seek( long offset, DWORD origin )
{
	 return ::SetFilePointer( Handle, offset, NULL, origin);
}

inline long ALFFFile::SeekToBegin()
{
	 return ::SetFilePointer( Handle, 0, NULL, FILE_BEGIN);
}

inline long ALFFFile::SeekToEnd()
{
	 return ::SetFilePointer( Handle, 0, NULL, FILE_END);
}

inline DWORD ALFFFile::Read( void *buffer, unsigned long numBytes )
{
	 DWORD numberOfBytesRead;
	 if (::ReadFile(Handle, buffer, numBytes, &numberOfBytesRead, NULL))
		 return numberOfBytesRead;
	 else return ::GetLastError();
}

inline DWORD ALFFFile::Write( const void *buffer, unsigned long numBytes)
{
	 DWORD numberOfBytesWritten;
	 if ( ::WriteFile(Handle, buffer, numBytes, &numberOfBytesWritten, NULL))
	  return numberOfBytesWritten;
	 else return ::GetLastError();
}

inline void ALFFFile::Flush()
{
	 ::FlushFileBuffers(Handle);
}

inline void ALFFFile::LockRange( long position, uint32 count )
{
	 ::LockFile( Handle, position, 0, count, 0 );
}

inline void ALFFFile::UnlockRange( long position, uint32 count )
{
	 ::UnlockFile( Handle, position, 0, count, 0 );
}

inline void ALFFFile::Remove( const char *name )
{
	 ::DeleteFile(name);
}

inline void ALFFFile::Rename( const char *oldName, const char *newName )
{
	 ::rename( oldName, newName );
}

#else   // _WIN16

#include <classlib\file.h>

// WIN16 ALFFFile is an OWL TFile Class

struct ALFFFileStatus : public TFileStatus
{
	 //SYSTEMTIME createTime;
	 //SYSTEMTIME modifyTime;
	 //SYSTEMTIME accessTime;
	 //long  fileSize;
	 //DWORD attributes;
    int fileHandle;
	 //char fullName[_MAX_PATH];
};


class _TECLIBCLASS ALFFFile : public TFile,  public ALFFObject
{
public:
	 ALFFFile();
	 ALFFFile( int handle );
    ALFFFile( const ALFFFile& file);
	 ALFFFile( const char* name,
				  DWORD access=TFile::ReadWrite,
				  DWORD permission=TFile::PermRdWr,
              DWORD flagCreate=TFile::Append,
 				  DWORD flagAttr=TFile::Normal);
	~ALFFFile();
    char far* GetClassName() {return "ALFFFile";}
	 int Open( const char* name,
				  DWORD access, DWORD permission,
				  DWORD flagCreate, DWORD flagAttr );
	 int Close();


	 int  GetHandle() const;

	 long Position() const;
	 DWORD Length() const;
    long Length();
	 void Length( long newLen );
	 long Seek( long offset, DWORD origin = TFile::beg );
	 long SeekToBegin();
	 long SeekToEnd();
	 int  GetStatus( ALFFFileStatus& status ) const;
	 int  IsOpen() const;
	 DWORD Read( void* buffer, unsigned long numBytes );
	 DWORD Write( const void* buffer, unsigned long numBytes );
	 void Flush();

	 void LockRange( long position, uint32 count );
	 void UnlockRange(long Position, uint32 count );

	 static int GetStatus( const char* name, ALFFFileStatus& status, bool closeHandle=true );
	 static int SetStatus( const char* name, const ALFFFileStatus& status );
	 static void Remove( const char* name );
	 static void Rename( const char* oldName, const char* newName );

private:

	 int    Handle;         // Low-level C file handle
	 char*  FileName;
	 int ShouldClose;       // Should C++ object close file on dtor

};

//---------------------------------------------------------------------------
// Inlines
//---------------------------------------------------------------------------

inline ALFFFile::ALFFFile() : TFile(), ALFFObject(), Handle(-1), ShouldClose(0)
{
 FileName = NULL;
}

inline ALFFFile::ALFFFile( int handle ) : TFile(handle), ALFFObject(),
                                          Handle(-1), ShouldClose(0)
{
 FileName = NULL;
}

inline ALFFFile::ALFFFile( const ALFFFile& file)
                         : TFile(file), ALFFObject(), ShouldClose(1)
{
  FileName = NULL;
  Handle = file.GetHandle();
}

inline ALFFFile::ALFFFile( const char* name, DWORD access,
									DWORD permission, DWORD flagCreate,
									DWORD flagAttr) :
								  TFile(name, access, permission),
                          ALFFObject(),
								  ShouldClose(1)

{
  FileName = NULL;
  Open( name, access, permission, NULL, NULL);
  Handle = GetHandle();
}

inline ALFFFile::~ALFFFile()
{
 if( IsOpen() && ShouldClose )
   Close();
 if (FileName)
   delete [] FileName;
}
inline int ALFFFile::GetHandle() const
{
  return Handle;
}

inline long ALFFFile::Position() const
{
  return TFile::Position();
}

inline int ALFFFile::IsOpen() const
{
	 return TFile::IsOpen();
}

inline long ALFFFile::Length()
{
  return TFile::Length();
}

inline void ALFFFile::Length( long newLen )
{
  TFile::Length(newLen);
}

inline long ALFFFile::Seek( long offset, DWORD origin )
{
	 return TFile::Seek(offset, origin);
}

inline long ALFFFile::SeekToBegin()
{
	 return TFile::SeekToBegin();
}

inline long ALFFFile::SeekToEnd()
{
	 return TFile::SeekToEnd();
}

inline DWORD ALFFFile::Read( void *buffer, unsigned long numBytes )
{
	 return TFile::Read(buffer, numBytes);
}

inline DWORD ALFFFile::Write( const void *buffer, unsigned long numBytes)
{
    return TFile::Write(buffer, numBytes);
}

inline void ALFFFile::Flush()
{
	 TFile::Flush();
}

inline void ALFFFile::LockRange( long position, uint32 count )
{
	TFile::LockRange (position, count);
}

inline void ALFFFile::UnlockRange( long position, uint32 count )
{
	 TFile::UnlockRange(position, count);
}

inline void ALFFFile::Remove( const char *name )
{
	 TFile::Remove(name);
}

inline void ALFFFile::Rename( const char *oldName, const char *newName )
{
	 TFile::Rename( oldName, newName );
}

#endif  // _WIN16

//{{ALFFFile}}
#endif

