#ifndef _FILEIO_H
#define _FILEIO_H 1
/*
 * File: fileio.h
 * Title: Compressed File I/O via <stdio.h> emulation
 * Author: Graham Toal
 * Created: Tue,21 May 1991.12:32:23
 * LastEdit: Tue,21 May 1991.12:32:23
 * Copyright Informat Computer Communications Ltd., 1991
 *
 * Description: Fake calls to the stdio procedures in order to read
 * directly from compressed files; the program merely
 * #include's this header file, then forgets about
 * compression.
 */

#include "extern.h"
#include "computil.h"
#include "lru.h"
#include "freel.h"

/* These struct definitions should really be private but they have to come
 before the external declarations. Just close your eyes and ignore them */

typedef struct _qfpos_t {
 FILEINDEX __lo; /* Since a real fpos_t is invisible, fake one */
} qfpos_t;

#define QFILE_LRU_SIZE 10

typedef struct _Q_FILE {
#define Q_MAGIC 0xf050163fL
 long q_magic;
 BLOCKINDEX blocknum; /* Current block in cache */
 long fid;
 /* These two were erroneously global. Now in struct */
 BLOCKINDEX cache_base /* cache[0] -> first block number */;
 BLOCKINDEX max_cache_entries; /* size of cache */


 /*char *inbuff;*/
 char *outbuff; /* compressed and uncompressed data respectively */
 FILEINDEX idx_pos; /* Offset into file where index is stored */
 FILEINDEX idx_entries; /* No. of entries in index */
 FILEINDEX file_length; /* Length of file once decompressed */
 FILEINDEX filepos; /* Notional pointer into virtual UNCOMPRESSED file */
 C_DATAINDEX blocksize; /* max size of inbuff & outbuff */
 C_DATAINDEX outsize; /* no. of valid bytes in outbuff */
 BINARYFILE f; /* Operating system's file underneath us */
 FILEINDEX *blockstart; /* Array holding Index pre-read from file */
 BOOL yellow_card; /* End-of-file to be returned on next read */
 BOOL cache_present; /* We have to be able to throw out caches for more Ram */
 struct _Q_FILE *next;
} QFILE;

typedef struct cache_block CBLOCK;

struct cache_block
{
 long fid; /* qfile id */
 BLOCKINDEX blockid; /* block id */
 char *buf; /* pointer to buffer */
 QFILE *qf;
};

typedef struct cb_lru_list CBLLIST;
struct cb_lru_list
{
 CBLLIST *next;
 long block_size;
 LRU cblru;
 long total_cache_space;
 long max_cache_space;
 FREEL *fl;
};

#define DEFAULT_CACHE_SPACE (128L*1024L)
#define INVALID_BUFFER -1L

/* Headers for c.fileio */
extern void FileIO_dump_profile(void);
extern int qfclose(QFILE *q);
extern QFILE *qfopen(const char *file, const char *fmode);
extern QFILE *qfreopen(const char *filename, const char *mode, QFILE *stream);
extern void qsetbuf(QFILE *stream, char *buf);
extern int qsetvbuf(QFILE *stream, char *buf, int mode, size_t size);
extern int qfscanf(QFILE *stream, const char *format, ...);
extern int qfgetc(QFILE *stream);
extern char *qfgets(char *s, int n, QFILE *stream);
extern int qgetc(QFILE *stream);
extern int qungetc(int c, QFILE *stream);
extern size_t qfread(void *ptr, size_t size, size_t nmemb, QFILE *stream);
extern int qfgetpos(QFILE *stream, qfpos_t *pos);
extern int qfseek(QFILE *q, long int where, int seektype);
extern int qfsetpos(QFILE *stream, const qfpos_t *pos);
extern long qftell(QFILE *q);
extern void qrewind(QFILE *stream);
extern void qclearerr(QFILE *stream);
extern int qfeof(QFILE *stream);
extern int qferror(QFILE *stream);
extern void qperror(const char *s);
extern void FreeSFCB(void);
extern CBLLIST *GetCBlist(long block_size);

/* End of headers for c.fileio */

#ifndef NO_FAKE_FILEIO /* allow us to suppress macro definitions in fileio.c itself */
#undef FILE
#define FILE QFILE
#define fclose(q) \
 qfclose(q)
#define fopen(file, fmode) \
 qfopen(file, fmode)
#define freopen(filename, mode, stream) \
 qfreopen(filename, mode, stream)
#define setbuf(stream, buf) \
 qsetbuf(stream, buf)
#define setvbuf(stream, buf, mode, size) \
 qsetvbuf(stream, buf, mode, size)
/* fscanf(stream, format, ...) */
#define fgetc(stream) \
 qfgetc(stream)
#define fgets(s, n, stream) \
 qfgets(s, n, stream)
#ifdef getc
#undef getc
#endif
#ifdef ungetc
#undef ungetc
#endif
#define getc(stream) \
 qgetc(stream)
#define ungetc(c, stream) \
 qungetc(c, stream)
#define fread(ptr, size, nmemb, stream) \
 qfread(ptr, size, nmemb, stream)
#define fgetpos(stream, pos) \
 qfgetpos(stream, pos)
#define fseek(q, where, seektype) \
 qfseek(q, where, seektype)
#define fsetpos(stream, pos) \
 qfsetpos(stream, pos)
#define ftell(q) \
 qftell(q)
#ifdef rewind
#undef rewind
#endif
#define rewind(stream) \
 qrewind(stream)
#ifdef clearerr
#undef clearerr
#endif
#define clearerr(stream) \
 qclearerr(stream)
#ifdef feof
#undef feof
#endif
#define feof(stream) \
 qfeof(stream)
#ifdef ferror
#undef ferror
#endif
#define ferror(stream) \
 qferror(stream)
#define perror(s) \
 qperror(s)
#endif /* Only if not asked to suppress macros */
#endif /* Double-entry test for FileIO.h */
