/**********************************************************************
This file is part of Crack dot Com's free source code release of
Golgotha.
for
information about compiling & licensing issues visit this URL
If that doesn't help, contact Jonathan Clark at golgotha_source@usa.net (Subject should have "GOLG" in it) ***********************************************************************/ #include "file/buf_file.hh" #include "memory/malloc.hh" #include "error/error.hh" #includew32 i4_buffered_file_class::read(void *buffer, w32 size) { w32 total_read=0; while (size) { if (offset>=buf_start && offset read(buf,buf_size); if (buf_end==buf_start) return total_read; } else // need to seek from file to a new spot { from->seek(offset); buf_start=buf_end=offset; } } return total_read; } w32 i4_buffered_file_class::write(const void *buffer, w32 size) { w32 total_write=0; while (size) { write_file=i4_T; if (offset>=buf_start && offset<=buf_end) { w32 copy_size; if (offset+size buf_end) { buf_end=offset; if (buf_end-buf_start==buf_size) { from->write(buf, buf_end-buf_start); buf_start=buf_end; } } } else if (buf_end!=buf_start) // flush the buffer { from->write(buf, buf_end-buf_start); buf_start=buf_end; } else { from->seek(offset); buf_start=buf_end=offset; } } return total_write; } w32 i4_buffered_file_class::seek (w32 offset) { i4_buffered_file_class::offset=offset; return offset; } w32 i4_buffered_file_class::size () { return from->size(); } w32 i4_buffered_file_class::tell () { return offset; } i4_buffered_file_class::~i4_buffered_file_class() { if (write_file && buf_start!=buf_end) from->write(buf, buf_end-buf_start); delete from; i4_free(buf); } i4_buffered_file_class::i4_buffered_file_class(i4_file_class *from, w32 buffer_size, w32 current_offset) : from(from), buf_size(buffer_size), offset(current_offset) { write_file=i4_F; buf=i4_malloc(buf_size,"file buffer"); buf_start=buf_end=0; } struct callback_context { i4_bool in_use; w32 prev_read; void *prev_context; i4_file_class::async_callback prev_callback; i4_buffered_file_class *bfile; } ; // Maximum number async reads going on at the same time enum { MAX_ASYNC_READS = 4 }; static callback_context contexts[MAX_ASYNC_READS]; static w32 t_callbacks_used=0; void i4_async_buf_read_callback(w32 count, void *context) { callback_context *c=(callback_context *)context; c->bfile->offset+=count; i4_file_class::async_callback call=c->prev_callback; count += c->prev_read; void *ctext=c->prev_context; c->in_use=i4_F; t_callbacks_used--; call(count, ctext); } i4_bool i4_buffered_file_class::async_read (void *buffer, w32 size, async_callback call, void *context) { if (!(offset>=buf_start && offset seek(offset); buf_start=buf_end=0; } if (t_callbacks_used>=MAX_ASYNC_READS) return i4_file_class::async_read(buffer, size, call, context); else { w32 avail_size; if (offset>=buf_start && offset in_use=i4_T; } if (c==0) i4_error("didn't find a free context"); t_callbacks_used++; if (avail_size) c->prev_read=read(buffer,avail_size); else c->prev_read=0; c->prev_context=context; c->prev_callback=call; c->bfile=this; return from->async_read((w8 *)buffer + avail_size, size-avail_size, i4_async_buf_read_callback, c); } else { call(read(buffer,avail_size), context); return i4_T; } } } //{{{ Emacs Locals // Local Variables: // folded-file: t // End: //}}}