📄 xpackfile.cpp
字号:
#include <stdio.h>
#include <string.h>
#include <allegro.h>
#include "queue.h"
//-------------------------------------------------------------------------------------------
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))
//-------------------------------------------------------------------------------------------
#define MEMFILE_ID 0x544D454DL
#define MEMFILE_READ 1
#define MEMFILE_WRITE 2
typedef struct { int ID,filetype; Queue oq; void* input; long input_size;long file_pos; void** output; long* output_size; } mem_packfile;
//--------------------------------------------------------------------------------------
extern "C" {
PACKFILE* mem_fopen_read_buffer(void* p_input,long p_input_size);
PACKFILE* mem_fopen_write_buffer(void** p_output,long* p_output_size);
int mem_fclose(void* userdata);
int mem_fgetc(void* userdata);
int mem_ungetc(int c,void* userdata);
long mem_fread(void* p, long n, void* userdata);
int mem_putc(int c, void* userdata);
long mem_fwrite(AL_CONST void *p, long n, void *userdata);
int mem_fseek(void* userdata,int offset);
int mem_feof(void* userdata);
int mem_ferror(void* userdata);
const struct PACKFILE_VTABLE memp_vtable=
{
&mem_fclose,
&mem_fgetc,
&mem_ungetc,
&mem_fread,
&mem_putc,
&mem_fwrite,
&mem_fseek,
&mem_feof,
&mem_ferror
};
//--------------------------------------------------------------------------------------
PACKFILE* mem_fopen_read_buffer(void* p_input,long p_input_size)
{
PACKFILE* result=NULL;
if ( p_input==NULL || p_input_size<=0 ) return NULL;
mem_packfile* mp= new mem_packfile;
if (!mp) return NULL;
mp->ID= MEMFILE_ID;
mp->filetype= MEMFILE_READ;
mp->input= p_input;
mp->input_size= p_input_size;
mp->file_pos= 0;
mp->output= NULL;
mp->output_size= NULL;
result = pack_fopen_vtable( &memp_vtable, (void*) mp );
if (!result) delete mp;
return result;
}
//--------------------------------------------------------------------------------------
// output and output_size are filled when memfile is closed by calling mem_fclose
PACKFILE* mem_fopen_write_buffer(void** p_output,long* p_output_size)
{
PACKFILE* result=NULL;
if (p_output==NULL || p_output_size==NULL) return NULL;
mem_packfile* mp= new mem_packfile;
if (!mp) return NULL;
mp->ID= MEMFILE_ID;
mp->filetype= MEMFILE_WRITE;
mp->input= NULL;
mp->input_size= 0;
mp->file_pos= 0;
mp->output= p_output;
mp->output_size= p_output_size;
result = pack_fopen_vtable( &memp_vtable, (void*) mp );
if (!result) delete mp;
return result;
}
//--------------------------------------------------------------------------------------
int mem_fclose(void* userdata)
{
mem_packfile* mp= (mem_packfile*) userdata;
if (mp->ID!=MEMFILE_ID) return EOF;
if (mp->filetype==MEMFILE_READ)
{
delete mp;
return 0;
}
else
if (mp->filetype==MEMFILE_WRITE)
{
int total_bytes= mp->oq.GetLength();
int bytes_written= 0;
void* buffer= NULL;
if (total_bytes>0)
{
buffer= malloc(total_bytes);
if (buffer)
{
bytes_written = mp->oq.Read(buffer,total_bytes);
(*mp->output)= buffer; //user is responsible to release the buffer
(*mp->output_size)= bytes_written;
}
}
if (!buffer)
{
(*mp->output)= NULL;
(*mp->output_size)= 0;
}
delete mp;
return 0;
}
return EOF;
}
//--------------------------------------------------------------------------------------
int mem_fgetc(void* userdata)
{
mem_packfile* mp= (mem_packfile*) userdata;
if (mp->ID!=MEMFILE_ID || mp->filetype!=MEMFILE_READ) return EOF;
unsigned char* buffer= (unsigned char*) mp->input;
int result;
if ( mp->file_pos < mp->input_size && mp->file_pos>=0 )
{
result= buffer[mp->file_pos];
mp->file_pos++;
}
else
result=EOF;
return result;
}
//--------------------------------------------------------------------------------------
int mem_ungetc(int c,void* userdata)
{
mem_packfile* mp= (mem_packfile*) userdata;
if (mp->ID!=MEMFILE_ID || mp->filetype!=MEMFILE_READ) return EOF;
if (mp->file_pos>0) mp->file_pos--;
return c;
}
//--------------------------------------------------------------------------------------
long mem_fread(void* p, long n, void* userdata)
{
mem_packfile* mp= (mem_packfile*) userdata;
if (mp->ID!=MEMFILE_ID || mp->filetype!=MEMFILE_READ) return EOF;
unsigned char* buffer= (unsigned char*) mp->input;
int bytes_to_read= max(0,min(n, (mp->input_size - mp->file_pos) ) );
if ( bytes_to_read>0)
{
memcpy(p,(buffer+mp->file_pos),bytes_to_read);
mp->file_pos+=bytes_to_read;
}
return bytes_to_read;
}
//--------------------------------------------------------------------------------------
int mem_putc(int c, void* userdata)
{
mem_packfile* mp= (mem_packfile*) userdata;
if (mp->ID!=MEMFILE_ID || mp->filetype!=MEMFILE_WRITE) return EOF;
mp->oq.Write(&c,1);
return c;
}
//--------------------------------------------------------------------------------------
long mem_fwrite(AL_CONST void *p, long n, void *userdata)
{
mem_packfile* mp= (mem_packfile*) userdata;
if (mp->ID!=MEMFILE_ID || mp->filetype!=MEMFILE_WRITE) return EOF;
int written=mp->oq.Write((void*) p,n);
return written;
}
//--------------------------------------------------------------------------------------
int mem_fseek(void* userdata,int relative_offset)
{
mem_packfile* mp= (mem_packfile*) userdata;
if (mp->ID!=MEMFILE_ID || mp->filetype!=MEMFILE_READ) return EOF;
if (relative_offset<0) return EOF;
if ( (mp->file_pos + relative_offset)> mp->input_size ) return EOF;
mp->file_pos += relative_offset;
return 0;
}
//--------------------------------------------------------------------------------------
int mem_feof(void* userdata)
{
mem_packfile* mp= (mem_packfile*) userdata;
if (mp->ID!=MEMFILE_ID || mp->filetype!=MEMFILE_READ) return EOF;
if (mp->file_pos < mp->input_size)
return 0;
else
return 1;
}
//--------------------------------------------------------------------------------------
int mem_ferror(void* userdata)
{
//not yet implemented
return 0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -