/*
This product contains certain software code or other information
("AT&T Software") proprietary to AT&T Corp. ("AT&T").  The AT&T
Software is provided to you "AS IS".  YOU ASSUME TOTAL RESPONSIBILITY
AND RISK FOR USE OF THE AT&T SOFTWARE.  AT&T DOES NOT MAKE, AND
EXPRESSLY DISCLAIMS, ANY EXPRESS OR IMPLIED WARRANTIES OF ANY KIND
WHATSOEVER, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, WARRANTIES OF
TITLE OR NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS, ANY
WARRANTIES ARISING BY USAGE OF TRADE, COURSE OF DEALING OR COURSE OF
PERFORMANCE, OR ANY WARRANTY THAT THE AT&T SOFTWARE IS "ERROR FREE" OR
WILL MEET YOUR REQUIREMENTS.

Unless you accept a license to use the AT&T Software, you shall not
reverse compile, disassemble or otherwise reverse engineer this
product to ascertain the source code for any AT&T Software.

(c) AT&T Corp. All rights reserved.  AT&T is a registered trademark of AT&T Corp.

***********************************************************************

History:

      24/11/99  - initial release by Hartmut Liefke, liefke@seas.upenn.edu
                                     Dan Suciu,      suciu@research.att.com
*/

//**************************************************************************
//**************************************************************************

// This module contains the input file class
// Based on class 'CFile', the new class 'Input' implements the
// buffer management

#pragma once

#include <stdio.h>
#include <string.h>

#include "XMillData.h"
#include "File.hpp"
#include "Types.hpp"

// The standard size of the file buffer
#define FILEBUF_SIZE 65536L

class CFile;

class Input
{
   char  databuf[FILEBUF_SIZE];  // The data buffer
   unsigned long curlineno;      // The current line number
   CFile *thefile;

	int increaseBytesRead (int len = 1);
	inline int FillBufLen (int mylen);

public:
   char  *curptr;                // The current buffer position
   char  *endptr;                // Points to the end of the valid data
                                 // (curptr-endptr) determines the number
                                 // of remaining bytes

	Session *session;
	int   *bytesreadptr;				// pointer to increase when a char is read

	Input(Session *s);
   ~Input();

	void reInit();

	void setBytesReadPtr(int *bytesread);

	/* 4 methods added because the CFile relation has changed from
	is-a to has-a */
   unsigned GetFilePos();
   unsigned ReadBlock(char *dest,unsigned bytecount);
	void CloseFile();
	void SetCFile(CFile *cfile);

   // The function fills the buffer as much as possible
	void FillBuf();

   char OpenFile(char *filename);
      // Opens the file and fills the buffer

   char ReadData(char *dest,int len);
      // Reads 'len' characters into the buffer 'dest'
      // If the data is already in memory, we simply copy
      // Otherwise, we iteratively read more from the file
      // The functions returns 0 if 'len' bytes are read
      // It returns 1, if the end of the file has been reached

   char GetChar(char *ptr);
      // Reads one single character and stores it in *ptr

   char ReadFullUInt32(unsigned long *data);
      // Reads a full integer (32 bit)

   char ReadUInt32(unsigned long *data);
      // Reads a compressed integer
      // If the MSB (most significant bit) of the first byte is 0, then
      // we have a vlaue <128
      // If the MSB is zero, then we look at the second MSB - if it is 0, then
      // we have a value <16384, otherwise, a value <2^30

	char PeekData(char *ptr,int len);
      // The functions looks ahead 'len' bytes and stores them in 'ptr'

   char PeekChar(char *ptr);
      // Peeks one character ahead and stores it in *ptr
      // Returns -1 if there was an error
      // Returns -2 if there is no character left
      // Returns 0 if everything is okay

   void SkipData(int len);
      // Skips 'len' characters
      // If the data is already in memory, we simply skip
      // Otherwise, we iteratively read more from the file
      // The functions returns 0 if 'len' bytes are skipped
      // Otherwise, it returns -1, if the was some I/O error
      // If we reached EOF, we return -2

   void FastSkipData(int len);
      // Does a fast skip - the data is already expected to be in the buffer

   char SkipChar();
      // Skips one single character

   char IsEndOfFile(unsigned len=0);
      // Checks whether we reached the end of the file

   int GetCurBlockPtr(char **ptr);
      // Returns the length of rest of data in the buffer and
      // stores the data pointer in *ptr

   void RefillAndGetCurBlockPtr(char **ptr,int *len);
      // Refills and
      // returns the length of rest of data in the buffer and
      // stores the data pointer in *ptr

   void UndoReadChar(int len = 1);
      // Unreads the last characters that were read
};

class MemFile: public CFile
{
	char *buffer;
	int buflen;
	unsigned bytesleft;
public:
	MemFile(char *b,int buflen=0);

   virtual char OpenFile(char *b,int blen=0);
	virtual unsigned ReadBlock(char *dest,unsigned bytecount);
      // Reads a data block into the memory at 'dest'. The maximum size is 'bytecount'
      // The function returns the number of bytes read or -1, if something fails
      // If the result is smaller than bytecount, the end of the file has been reached
      // and flag eof is set to 1.

	virtual void CloseFile();
};

class MemInput: public Input
{
	MemFile *memfile;

public:
	MemInput(Session *s);
	MemInput(Session *s, char *membuf, int buflen);
	~MemInput();

	void setData(char *membuf, int buflen);
};
