⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stream.c

📁 压缩算法的C语言源程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
	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 + -