#ifndef STREAM_BUFFER_H
#define STREAM_BUFFER_H
#include <stdio.h>
#include <stdlib.h>
#include "gaudio.h"
typedef struct _streamBuffer streamBuffer;
//typedef size_t(*streamRead)(void* ctx,void* ptr,size_t size,size_t nmemb);
//typedef int(*streamSeek)(void* ctx,glong offset,int flag);
//typedef int(*streamClose)(void* ctx);
streamBuffer* stream_open_file(const gchar* file);
streamBuffer* stream_open_mem(gvoid* mem,gulong size);
streamBuffer* stream_open_callbacks(gread read,gseek seek,gtell tell,gclose close,gvoid* context);
glong stream_read(streamBuffer* stream,gvoid* ptr,gint size,glong nmemb);
glong stream_seek(streamBuffer* stream,glong offset,gint flag);
glong stream_close(streamBuffer* stream);
#endif
//! by ccsdu2004
#include <stdio.h>
#include <string.h>
#include "streamBuffer.h"
#include "gmemory.h"
struct _streamBuffer
{
gread read;
gseek seek;
gclose close;
gtell tell;
void* ctx;
};
typedef struct _stdIOContext
{
FILE *fp;
}stdIOContext;
glong stdio_stream_read(gvoid* ptr,gint size,glong nmemb,gvoid* ctx)
{
return fread(ptr,size,nmemb,((stdIOContext*)ctx)->fp);
}
glong stdio_stream_seek(gvoid* ctx,glong offset,gint flag)
{
return fseek(((stdIOContext*)ctx)->fp,offset,flag);
}
glong APIENTRY stdio_stream_tell(gvoid* ctx)
{
return ftell(((stdIOContext*)ctx)->fp);
}
glong stdio_stream_close(gvoid* ptr)
{
stdIOContext* ctx = (stdIOContext*)ptr;
gint ret = 0;
ret = fclose(ctx->fp);
gFreeBuffer(ctx);
return ret;
}
typedef struct memContext
{
guchar* base;
guchar* current;
guchar* end;
}memContext;
glong mem_stream_read(gvoid* ptr,gint size,glong nmemb,gvoid* ctx)
{
streamBuffer* stream = (streamBuffer*)ctx;
memContext *c;
glong count;
c = (memContext*)stream;
count = nmemb;
if(c->current + count * size > c->end)
count = (c->end - c->current) / size;
memcpy(ptr, c->current, count * size);
c->current += count * size;
return count;
}
glong mem_stream_seek(gvoid* ctx,glong offset,gint flag)
{
streamBuffer* stream = (streamBuffer*)ctx;
memContext* c;
c = (memContext*)stream;
if(c == NULL)
return -1;
if(flag == SEEK_SET)
{
if(offset < 0 || offset > c->end - c->base)
return -1;
c->current = c->base + offset;
return 0;
}
else if(flag == SEEK_CUR)
{
if(offset > 0)
{
if(offset > c->end - c->current)
return -1;
c->current += offset;
return 0;
}
else if(offset < 0)
{
if(-offset > c->current - c->base)
return -1;
c->current += offset;
return 0;
}
}
else if(flag == SEEK_END)
{
if(offset > 0 || offset > c->end - c->base)
return -1;
c->current = c->end - offset;
return 0;
}
return -1;
}
glong mem_stream_close(gvoid *ptr)
{
memContext* ctx = (memContext*)ptr;
gFreeBuffer(ctx->base);
gFreeBuffer(ctx);
return 0;
}
streamBuffer* stream_open_fp(FILE* fp)
{
stdIOContext* ctx;
streamBuffer* stream;
stream = gcreate_buffer<streamBuffer>(1);
if(stream == NULL)
return NULL;
ctx = gcreate_buffer<stdIOContext>(1);
if(ctx == NULL)
{
gFreeBuffer(stream);
return NULL;
}
ctx->fp = fp;
stream->ctx = ctx;
stream->read = stdio_stream_read;
stream->seek = stdio_stream_seek;
stream->close = stdio_stream_close;
return stream;
}
streamBuffer* stream_open_file(const gchar *file)
{
FILE *fp;
fp = fopen((char*)file,"rb");
if(fp == NULL)
return NULL;
return stream_open_fp(fp);
}
streamBuffer* stream_open_mem(gvoid* mem,gulong size)
{
memContext* ctx;
streamBuffer* stream;
stream = gcreate_buffer<streamBuffer>(1);
if(stream == NULL)
return NULL;
ctx = gcreate_buffer<memContext>(1);
if(ctx == NULL)
{
gFreeBuffer(stream);
return NULL;
}
ctx->base = (guchar*)mem;
ctx->current = (guchar*)mem;
ctx->end = ((guchar*) mem) + size;
stream->ctx = ctx;
stream->read = mem_stream_read;
stream->seek = mem_stream_seek;
stream->close = mem_stream_close;
return stream;
}
streamBuffer* stream_open_callbacks(gread read,gseek seek,gtell tell,gclose close,gvoid* context)
{
streamBuffer* stream = gcreate_buffer<streamBuffer>(1);
if(stream == NULL)
return NULL;
stream->ctx = context;
stream->read = read;
stream->seek = seek;
stream->tell = tell;
stream->close = close;
return stream;
}
glong stream_read(streamBuffer* stream,gvoid* ptr,gint size,glong nmemb)
{
return stream->read(ptr,size,nmemb,stream->ctx);
}
glong stream_seek(streamBuffer* stream,glong offset,gint flag)
{
return stream->seek(stream,offset,flag);
/*size_t c;
char tmp[1024];
while(offset > 0)
{
c = offset;
if(c > 1024)
c = 1024;
offset -= c;
if(c != stream_read(stream,tmp,1,c))
{
}
}
return 1;*/
}
glong stream_close(streamBuffer* stream)
{
gint ret = stream->close(stream->ctx);
gFreeBuffer(stream);
return ret;
}