📄 stream.c
字号:
/*
stream.c
File I/O stream for gsLib
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io.h>
#include <fcntl.h>
#ifdef __DJGPP__
#include <unistd.h>
#endif
#include <compress.h>
#define STREAM_BUF_SIZE 256
#define F_READ 0x0000
#define F_WRITE 0x0001
#define F_RDWR 0x0002
#define F_FDHANDLE 0x0000
#define F_FPHANDLE 0x0004
#define F_MPHANDLE 0x0008
#define F_FREEMEM 0x0010
#define F_BINARY 0x0080
#define F_EOF 0x8000
#define MODETYPE 0x0003
#define FPTYPE 0x000C
/*
STREAM *CreateStream()
Creates a new stream and returns a pointer to it
*/
STREAM *CreateStream()
{
STREAM *sp;
sp = (STREAM *)malloc(sizeof(STREAM) + STREAM_BUF_SIZE);
if(!sp) {
gerror("Can not allocate memory for a new STREAM");
THROW (E_MEMORY) return NULL;
}
memset(sp,0,sizeof(STREAM) + STREAM_BUF_SIZE);
return sp;
}
/*
void stream_set_base(STREAM *stream,dword base):
Sets the base in a STREAM
*/
void stream_set_base(STREAM *stream,dword base)
{
stream->position = stream->position + stream->base - base;
stream->base = base;
}
/*
void stream_set_limit(STREAM *stream,dword limit):
Sets the limit in a STREAM
*/
void stream_set_limit(STREAM *stream,dword limit)
{
stream->limit = limit;
}
/*
STREAM *stream_open(const char *filename,const char *mode):
Opens a file and returns the STREAM associated with it.
*/
STREAM *stream_open(const char *filename,const char *mode)
{
STREAM *sp;
int oflags = 0;
if(!filename || !mode) {
gerror("Filename or mode not specifed in stream_open().");
THROW (E_INVALID) return NULL;
}
sp = CreateStream();
if(!sp) return NULL;
switch(*mode) {
case 'a': oflags = O_CREAT | O_WRONLY; break;
case 'r': oflags = O_RDONLY; break;
case 'w': oflags = O_TRUNC | O_CREAT | O_WRONLY; break;
}
switch(mode[1]) {
case 't': oflags |= O_TEXT; break;
case 'b': oflags |= O_BINARY; break;
}
sp->flag = *mode == 'r' ? F_READ : F_WRITE;
sp->flag |= mode[1] == 'b' ? F_BINARY : 0;
sp->handle.fd = open(filename, oflags, 0666);
if(sp->handle.fd < 0) {
free(sp);
gerror("File `%s' not found.",filename);
THROW (E_FILE) return NULL;
}
if((sp->flag & MODETYPE) == F_READ) {
sp->base = 0;
sp->limit = filelength(sp->handle.fd);
reload_streambuf(sp);
} else if((sp->flag & MODETYPE) == F_WRITE) {
if(*mode == 'a') lseek(sp->handle.fd,0,SEEK_END);
sp->base = 0;
sp->limit = 0xFFFFFFFF;
}
return sp;
}
/*
STREAM *stream_fopen(FILE *fp,const char *mode):
Associates a STREAM with a FILE struct
*/
STREAM *stream_fopen(FILE *fp,const char *mode)
{
STREAM *stream;
stream = CreateStream();
if(!stream) return NULL;
stream->handle.fp = fp;
stream->flag = F_FPHANDLE;
if(*mode == 'w') stream->flag |= F_WRITE;
stream->flag |= mode[1] == 'b' ? F_BINARY : 0;
stream->position = ftell(fp);
stream->bufpos = 0;
stream->bitbuffer = 0;
stream->bitsinbuf = 0;
stream->base = 0;
stream->limit = filelength(fileno(fp));
return stream;
}
/*
STREAM *stream_mopen(void *mp,const char *mode,dword limit):
Associates a STREAM with an array
*/
STREAM *stream_mopen(void *mp,const char *mode,dword limit)
{
STREAM *stream;
stream = CreateStream();
if(!stream) return NULL;
stream->handle.mp = (byte *)mp;
stream->flag = F_MPHANDLE;
if(*mode == 'w') stream->flag |= F_WRITE;
stream->flag |= mode[1] == 'b' ? F_BINARY : 0;
stream->position = 0;
stream->bufpos = 0;
stream->bitbuffer = 0;
stream->bitsinbuf = 0;
stream->base = 0;
stream->limit = limit;
return stream;
}
/*
STREAM *stream_alloc(dword size):
Creates a memory stream with `size' length, the memory is free on
stream_close()
*/
STREAM *stream_alloc(dword size)
{
STREAM *stream;
stream = CreateStream();
if(!stream) return NULL;
// allocate the size of memory
stream->handle.mp = (byte *)malloc(size);
if(!stream->handle.mp) {
gerror("Not enough memory for a memory stream.");
free(stream);
THROW (E_MEMORY) return NULL;
}
stream->flag = F_MPHANDLE | F_RDWR | F_BINARY | F_FREEMEM;
stream->position = 0;
stream->bufpos = 0;
stream->bitbuffer = 0;
stream->bitsinbuf = 0;
stream->base = 0;
stream->limit = size;
return stream;
}
/*
STREAM *stream_dup(STREAM *stream):
Returns NULL on error or a pointer to a STREAM
*/
STREAM *stream_dup(STREAM *stream)
{
STREAM *newstream;
int fd;
char mode[4];
newstream = CreateStream();
if(!newstream) return NULL;
memcpy(newstream,stream,sizeof(STREAM) + STREAM_BUF_SIZE);
switch(stream->flag & FPTYPE) {
case F_FDHANDLE:
newstream->handle.fd = dup(stream->handle.fd);
if(newstream->handle.fd < 0) {
free(newstream);
gerror("Could not duplicate STREAM.");
THROW (E_FILE) return NULL;
}
break;
case F_FPHANDLE:
fd = dup(fileno(stream->handle.fp));
if(fd < 0) {
free(newstream);
gerror("Could nout duplicate STREAM.");
THROW (E_FILE) return NULL;
}
mode[0] = stream->flag & F_WRITE ? 'w' : 'r';
mode[1] = stream->flag & F_BINARY ? 'b' : 't';
mode[2] = NULL;
newstream->handle.fp = fdopen(fd,mode);
if(!newstream->handle.fp) {
close(fd); free(newstream);
gerror("Could nout duplicate STREAM.");
THROW (E_FILE) return NULL;
}
break;
}
return newstream;
}
/*
void stream_close(STREAM *stream):
Closes an open stream
*/
void stream_close(STREAM *stream)
{
if(stream->flag & F_WRITE) flush_streambuf(stream);
if(stream->flag & F_FREEMEM) free(stream->handle.mp);
if(stream->handle.fd >= 0 && ((stream->flag & FPTYPE) == F_FDHANDLE)) close(stream->handle.fd);
free(stream);
}
/*
int stream_getc(STREAM *stream):
Returns a byte from the stream
*/
int stream_getc(STREAM *stream)
{
if(stream_eof(stream) || (stream->flag & MODETYPE) == F_WRITE) return -1;
if(stream->position >= stream->limit) {
stream->flag |= F_EOF;
return -1;
}
stream->position++;
switch(stream->flag & FPTYPE) {
case F_FDHANDLE:
if(stream->bufpos >= STREAM_BUF_SIZE) reload_streambuf(stream);
return stream->fdbuf[stream->bufpos++];
case F_FPHANDLE:
return fgetc(stream->handle.fp);
case F_MPHANDLE:
return stream->handle.mp[stream->position + stream->base - 1];
}
return -1;
}
/*
int stream_getw(STREAM *stream):
Returns a word from the stream
*/
int stream_getw(STREAM *stream)
{
register int ch;
ch = stream_getc(stream);
ch |= stream_getc(stream) << 8;
return ch;
}
/*
int stream_getd(STREAM *stream):
Returns a double word from the stream
*/
int stream_getd(STREAM *stream)
{
register dword ch;
ch = stream_getc(stream);
ch |= stream_getc(stream) << 8;
ch |= stream_getc(stream) << 16;
ch |= stream_getc(stream) << 24;
return ch;
}
/*
int stream_putc(int ch, STREAM *stream):
Writes a byte to the stream
*/
int stream_putc(int ch,STREAM *stream)
{
if(stream_eof(stream) || (stream->flag & MODETYPE) == F_READ) return -1;
if(stream->position >= stream->limit) {
stream->flag |= F_EOF;
return -1;
}
stream->position++;
switch(stream->flag & FPTYPE) {
case F_FDHANDLE:
if(stream->bufpos >= STREAM_BUF_SIZE) flush_streambuf(stream);
stream->fdbuf[stream->bufpos++] = (byte)ch;
return ch;
case F_FPHANDLE:
return fputc(ch & 0xFF,stream->handle.fp);
case F_MPHANDLE:
stream->handle.mp[stream->position + stream->base - 1] = (byte)ch;
return ch;
}
return -1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -