#ifndef _BINFILE_H_
#define _BINFILE_H_




/*
 *
 *          Copyright (C) 1995, M. A. Sridhar
 *  
 *
 *     This software is Copyright M. A. Sridhar, 1995. You are free
 *     to copy, modify or distribute this software  as you see fit,
 *     and to use  it  for  any  purpose, provided   this copyright
 *     notice and the following   disclaimer are included  with all
 *     copies.
 *
 *                        DISCLAIMER
 *
 *     The author makes no warranties, either expressed or implied,
 *     with respect  to  this  software, its  quality, performance,
 *     merchantability, or fitness for any particular purpose. This
 *     software is distributed  AS IS.  The  user of this  software
 *     assumes all risks  as to its quality  and performance. In no
 *     event shall the author be liable for any direct, indirect or
 *     consequential damages, even if the  author has been  advised
 *     as to the possibility of such damages.
 *
 */


// This is an abstract interface to a binary file, essentially a wrapper around
// the platform's file system calls. BinaryFile specializes Stream in that
// it represents a binary data stream on a disk file. It overrides the six
// core methods inherited from Stream.
//
// The BinaryFile methods support dependent notification. They treat the
// {\tt Write} method as the only one that modifies the file; this
// method consults pre-change dependents and notifies post-change
// dependents. (See {\tt base/object.h} for info about dependents.)
//
// Most of the methods return error indications in some form. The exact
// nature of the error can be obtained using the {\tt ErrorString} method.
//
// The strategy for deciding when to open and close the file is determined
// by BinaryFile's implementation, and
// could potentially be changed by classes derived from it (e.g., by a caching
// binary file class). So the user of this class cannot assume, for example,
// that the file is always open. In the current implementation, the
// constructor opens the file  and the destructor closes it, but this might
// change in a future YACL version.



#if defined(__GNUC__)
#pragma interface
#endif

#include "io/iodefs.h"  // Include this first!!!

#include "base/string.h"
#include "base/bytstrng.h"
#include "base/stream.h"


//[ Global
enum CL_FileOpenFlags {
    CLFile_Read = 1, CLFile_Write = 2, CLFile_Create = 4
};
// This enumeration lists the flags that can be bitwise-{\sc or}'ed for
// the parameter to the BinaryFile constructor.
//] Global

class YACL_IO CL_BinaryFile: public CL_Stream {
 
public:
 
    CL_BinaryFile (const char* pathName,
                   ushort flags = CLFile_Read | CLFile_Write); 
    // Constructor: instantiate a BinaryFile object with path name {\tt
    // pathName}. If {\tt flags} includes the {\tt CLFile_Create} bit,
    // create the file, overwriting any existing one; if it doesn't, and
    // the file does not exist, issue a runtime error. If {\tt flags}
    // does not include the {\tt CLFile_Write} bit, open the file in
    // read-only mode; in this case, all calls to {\tt Write} will fail.

    ~CL_BinaryFile();
    // Destructor: close the file.

    // ----------------- Error state methods ---------------------

    inline bool Valid() const;
    // Tell whether the state of the file is ok. This method returns FALSE if,
    // for example, the BinaryFile was created with an invalid path name.

    CL_String ErrorString () const;
    // Return the (platform-specific) error message string associated
    // with the most recent error.
    // This overrides the inherited virtual method.
    

    // ----------------- Read operations -------------------------

    virtual long Read (uchar* buffer, long n) const; 
    // Read $n$ bytes from current position into {\tt buffer}. The latter is
    // assumed to be large enough for $n$ bytes. This method returns either
    // the number of bytes read, 0 on eof, or $-1$ on error. This overrides
    // the inherited pure virtual method.
 
    // ----------------- Write operations ------------------------

    virtual bool Write (uchar* buffer, long n);
    // Write $n$ bytes from {\tt buffer} at the current position. Return
    // TRUE on success, FALSE if either  the file was
    // opened in read-only mode or the operation failed for some reason.
    // This overrides the inherited pure virtual method.

   
    
    // ----------------- Seek operations -------------------------
    
    virtual bool SeekTo (CL_Offset pos) const;
    // Change the current position to {\tt pos}. Returns TRUE on success,
    // FALSE if the {\tt lseek} call failed.
    // This overrides the inherited pure virtual method.
 
    virtual bool SeekToEnd () const;
    // Position to the end of the file. Returns TRUE on success, FALSE on
    // failure. This overrides the inherited virtual method.

    virtual bool SeekRelative (long n) const;
    // Change the position by {\tt n} bytes, which can be positive or
    // negative. Return TRUE on success, FALSE if the {\tt lseek} call failed. 
    // This overrides the inherited virtual method.
    
    virtual bool ChangeSize (CL_Offset size);
    // Change the size of file to {\tt size} bytes. The parameter can be
    // smaller or larger than the current size.
    // This overrides the inherited virtual method.

    // ---------------------- Querying ----------------------

    virtual bool Eof () const;
    // Return TRUE if the current file position is at end-of-file.
    // This overrides the inherited virtual method.
    
    virtual long Offset () const;
    // Return the current position.
    // This overrides the inherited virtual method.
    
    CL_String FileName() const;
    // Return the pathname of the file (the name it was initialized with).
    
    virtual long Size () const;
    // Return the current size of the file in bytes.
    // This overrides the inherited virtual method.
 
    // ------------------ Static functions ------------------------------

    static bool Exists (const char* pathName,
                        ulong accessPerms = CLFile_Read | CLFile_Write);
    // Return TRUE if the file with given name exists, FALSE if not. The
    // second parameter specifies the desired access permissions.
 
    static bool Create (const char* pathName);     
    // Create the file with the given path name. Truncate any existing file
    // with the same name. Return TRUE on success, FALSE on failure.

    // ------------------ Basic functions ------------------------------

    CL_String AsString () const;
    // The implementation returns the name of the file.
    
    const char* ClassName() const {return "CL_BinaryFile";};

    CL_ClassId ClassId() const { return _CL_BinaryFile_CLASSID;};

    // ------------------- End public protocol ------------------------ 
 
protected:
 
    //  Instance variables:

    CL_String    _pathName;     // Path name
    int          _fd;           // The file descriptor
    CL_String    _errorString;
    ushort       _flags;
    
    // Protected methods:
    
    virtual bool _Open ();
    // Open the file. 

    virtual void _Close ();
    // Close the file.

    void         _MakeErrorString (const char*) const;
    // Interrogate the platform for the most recent error, and set up its
    // description as {\tt _errorString}.

};
 
 


inline bool CL_BinaryFile::Valid() const
{
    return _errorString.Size() == 0;
}





inline CL_String CL_BinaryFile::FileName () const
{
    return _pathName;
}


#endif
