// -*- c++ -*-

/*
 * Jakelib2 - General purpose C++ library
 * Copyright (C) 2001 Florian Wolff  (florian@donuz.de)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * $Id: RandomAccessFile.h,v 1.4 2003/09/12 16:13:51 florian Exp $
 */

#ifndef INCLUDE_JAKELIB2_IO_RANDOMACCESSFILE_H
# define INCLUDE_JAKELIB2_IO_RANDOMACCESSFILE_H

namespace jakelib {
  namespace io {
    class File;

    /**
     * @brief This class allows reading and writing of files at random locations.
     * Most Java I/O classes are either pure sequential input or output.
     *
     * This class fulfills the need to be able to read the bytes of a file in an
     * arbitrary order.  In addition, this class implements the
     * <code>DataInput</code> and <code>DataOutput</code> interfaces to allow
     * the reading and writing of Java primitives.
     *
     * @class RandomAccessFile
     * @version $Id: RandomAccessFile.h,v 1.4 2003/09/12 16:13:51 florian Exp $
     * @author Florian 'Overflo' Wolff (florian@donuz.de)
     */
    class RandomAccessFile : public jakelib::lang::Object
      {
      public:

        /**
         * @brief This method initializes a new instance of \c RandomAccessFile
         * to read from the specified file name with the specified access mode.
         * The access mode is either \c "r" for read only access or \c "rw" for read
         * write access.
         *
         * @param name The name of the file to read and/or write
         * @param mode \c "r" for read only or \c "rw" for read-write access to the file
         */
        RandomAccessFile(jakelib::lang::String* name, jakelib::lang::String* mode);

        /**
         * @brief This method initializes a new instance of \c RandomAccessFile
         * to read from the specified file with the specified access mode.
         * The access mode is either \c "r" for read only access or \c "rw" for read
         * write access.
         *
         * @param file The file to read and/or write
         * @param mode \c "r" for read only or \c "rw" for read-write access to the file
         */
        RandomAccessFile(File* file, jakelib::lang::String* mode);

        ~RandomAccessFile();

        /**
         * @brief This method closes the file and frees up all file related system
         * resources.  Since most operating systems put a limit on how many files
         * may be opened at any given time, it is a good idea to close all files
         * when no longer needed to avoid hitting this limit
         */
        virtual void close();

        /**
         * @brief This method reads a single byte of data from the file and returns it
         * as an integer.
         *
         * @return The byte read as an int, or \c -1 if the end of the file was reached.
         * @exception IOException If an error occurs
         */
	virtual int read();

        /**
         * @brief This methods reads up to \c len bytes from the file into the
         * specified array starting at position \c offset into the array.
         *
         * @param buf The array to read the bytes into
         * @param offset The index into the array to start storing bytes
         * @param len The requested number of bytes to read
         * @return The actual number of bytes read, or \c -1 if end of file
         * @exception IOException If an error occurs
         */
	virtual int read(jbyte* buf, int offset, int len);

        /**
         * @brief This method reads raw bytes into the passed array \c buf.
         * The number of bytes read will be
         * exactly \c len. Note that this method blocks until the data is 
         * available and
         * throws an exception if there is not enough data left in 
         * the stream to read \c len bytes.
         *
         * @param buf The array to read the bytes into
         * @param offset The index into the array to start storing bytes
         * @param len The requested number of bytes to read
         * @exception IOException If an error occurs
         * @exception EOFException If end of file is reached before filling the buffer
         */
	virtual void readFully(jbyte* buf, int offset, int len);

        /**
         * @brief This method reads a \c jboolean value from an input stream. It does
         * so by reading a single byte of data. If that byte is zero, then the
         * value returned is \c false. If the byte is non-zero, then
         * the value returned is \c true.
         *
         * @return The \c jboolean value read
         * @exception EOFException If end of file is reached before reading the boolean
         * @exception IOException If any other error occurs
         */
        virtual jboolean readBoolean();

        /**
         * @brief This method reads a \c jbyte value from an input stream. The value
         * is in the range of \c -128 to \c 127.
         *
         * @return The \c jbyte value read
         * @exception EOFException If end of file is reached before reading the byte
         * @exception IOException If any other error occurs
         */
        virtual jbyte readByte();

        /**
         * @brief This method reads a \c char value from an input stream.  
         * It operates by reading two bytes from the stream and converting them to 
         * a single 16-bit \c jchar  The two bytes are stored most
         * significant byte first (i.e., "big endian") regardless of the native
         * host byte ordering. 
         *
         * As an example, if <code>byte1</code> and code{byte2</code> represent the first
         * and second byte read from the stream respectively, they will be
         * transformed to a <code>char</code> in the following manner:
         *
         * <code>(char)(((byte1 & 0xFF) << 8) | (byte2 & 0xFF)</code>
         *
         * @return The \c jchar value read 
         * @exception EOFException If end of file is reached before reading the char
         * @exception IOException If any other error occurs
         */
        virtual jchar readChar();

        /**
         * @brief This method reads a \c jint value from an input stream
         * It operates by reading four bytes from the stream and converting them to 
         * a single \c jint.  The bytes are stored most
         * significant byte first (i.e., "big endian") regardless of the native
         * host byte ordering. 
         *
         * As an example, if <code>byte1</code> through <code>byte4</code> represent the first
         * four bytes read from the stream, they will be
         * transformed to an <code>int</code> in the following manner:
         * <p>
         * <code>(int)(((byte1 & 0xFF) << 24) + ((byte2 & 0xFF) << 16) + 
         * ((byte3 & 0xFF) << 8) + (byte4 & 0xFF)))</code>
         *
         * @return The \c jint value read
         *
         * @exception EOFException If end of file is reached before reading the int
         * @exception IOException If any other error occurs
         */
        virtual jint readInt();

        /**
         * @brief This method reads a \c jlong value from an input stream
         * It operates by reading eight bytes from the stream and converting them to 
         * a single \c jlong.  The bytes are stored most
         * significant byte first (i.e., "big endian") regardless of the native
         * host byte ordering. 
         *
         * As an example, if <code>byte1</code> through <code>byte8</code> represent the first
         * eight bytes read from the stream, they will be
         * transformed to an <code>long</code> in the following manner:
         *
         * <code>(long)((((long)byte1 & 0xFF) << 56) + (((long)byte2 & 0xFF) << 48) + 
         * (((long)byte3 & 0xFF) << 40) + (((long)byte4 & 0xFF) << 32) + 
         * (((long)byte5 & 0xFF) << 24) + (((long)byte6 & 0xFF) << 16) + 
         * (((long)byte7 & 0xFF) << 8) + ((long)byte9 & 0xFF)))</code>
         *
         * @return The \c jlong value read
         * @exception EOFException If end of file is reached before reading the long
         * @exception IOException If any other error occurs
         */
        virtual jlong readLong();

        /**
         * @brief This method sets the current file position to the specified offset 
         * from the beginning of the file. Note that some operating systems will
         * allow the file pointer to be set past the current end of the file.
         *
         * @param pos The offset from the beginning of the file at which to set the file pointer
         * @exception IOException If an error occurs
         */
        virtual void seek(int pos);

        /**
         * @brief This method attempts to skip and discard the specified number of bytes 
         * in the input stream. It may actually skip fewer bytes than requested. 
         * The actual number of bytes skipped is returned. This method will not
         * skip any bytes if passed a negative number of bytes to skip.
         *
         * @param n The requested number of bytes to skip.
         * @return The number of bytes actually skipped.
         * @exception IOException If an error occurs.
         */
        virtual int skipBytes(int n);

      protected:

	FILE* handle;

      private:

        void init(jakelib::lang::String* name, jakelib::lang::String* mode);

	JAKELIB_DECLARE_CLASS(RandomAccessFile);
      };

  }
}
#endif

