//*****************************************************************************
//
// filebuf.h
//
// buffered file io
//
//*****************************************************************************
#include <stdio.h>
#include <time.h>
#include "mud.h"
//*****************************************************************************
// local structures and defines
//*****************************************************************************
#define FBMODE_READ 0
#define FBMODE_WRITE 1
struct buffered_file {
FILE *fl;
BUFFER *buf;
int pos;
int mode;
};
//
// buffer up input from our file
void fb_buffer(FILEBUF *fb) {
if(feof(fb->fl))
return;
char in[MAX_BUFFER+1];
int amnt;
do {
amnt = fread(in, sizeof(char), MAX_BUFFER, fb->fl);
in[amnt] = '\0';
bufferCat(fb->buf, in);
} while(amnt == MAX_BUFFER);
}
FILEBUF *fbopen(const char *fname, const char *mode) {
// make sure we can access the file...
FILE *fl = fopen(fname, mode);
if(fl == NULL)
return NULL;
// clock our performance
// struct timeval start_time;
// gettimeofday(&start_time, NULL);
FILEBUF *fb = malloc(sizeof(FILEBUF));
fb->fl = fl;
fb->buf = newBuffer(1024);
fb->pos = 0;
if(*mode == 'r') {
fb->mode = FBMODE_READ;
fb_buffer(fb);
}
else
fb->mode = FBMODE_WRITE;
// finish clocking performance
// struct timeval end_time;
// gettimeofday(&end_time, NULL);
// int usecs = (int)(end_time.tv_usec - start_time.tv_usec);
// int secs = (int)(end_time.tv_sec - start_time.tv_sec);
// log_string("buffer open time %d %s", (int)(secs*1000000 + usecs), fname);
return fb;
}
//
// close, flush, and delete the buffered file reader
void fbclose(FILEBUF *fb) {
fbflush(fb);
fclose(fb->fl);
deleteBuffer(fb->buf);
free(fb);
}
//
// flush the buffered file reader
void fbflush(FILEBUF *fb) {
if(fb->mode == FBMODE_WRITE && bufferLength(fb->buf) > fb->pos) {
const char *to_flush = bufferString(fb->buf);
fprintf(fb->fl, "%s", to_flush+fb->pos);
fb->pos = bufferLength(fb->buf);
}
}
//
// return the next char in the buffered file
char fbgetc(FILEBUF *fb) {
if(fb->pos >= bufferLength(fb->buf))
return EOF;
else
return bufferString(fb->buf)[fb->pos++];
}
//
// print the formatting to the file
int fbprintf(FILEBUF *fb, const char *fmt, ...) {
va_list va;
va_start(va, fmt);
int res = vbprintf(fb->buf, fmt, va);
va_end(va);
return res;
}
//
// append the text to the buffer
void fbwrite(FILEBUF *fb, const char *str) {
bufferCat(fb->buf, str);
}
//
// go to the position, from the specified offset. Uses SEEK_CUR, SEEK_SET,
// and SEEK_END from stdio.h
void fbseek(FILEBUF *fb, int offset, int origin) {
if(origin == SEEK_SET)
fb->pos = 0;
else if(origin == SEEK_END)
fb->pos = bufferLength(fb->buf) - 1;
else if(origin != SEEK_CUR)
return;
fb->pos += offset;
}