blob: 90f32d934b75b68243a57c7394b715f675870e98 [file] [log] [blame]
// ==========================================================
// Input/Output functions
//
// Design and implementation by
// - Floris van den Berg (flvdberg@wxs.nl)
//
// This file is part of FreeImage 3
//
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
// THIS DISCLAIMER.
//
// Use at your own risk!
// ==========================================================
#include "FreeImage.h"
#include "Utilities.h"
#include "FreeImageIO.h"
// ----------------------------------------------------------
unsigned DLL_CALLCONV
_ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
return (unsigned)fread(buffer, size, count, (FILE *)handle);
}
unsigned DLL_CALLCONV
_WriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
return (unsigned)fwrite(buffer, size, count, (FILE *)handle);
}
int DLL_CALLCONV
_SeekProc(fi_handle handle, long offset, int origin) {
return fseek((FILE *)handle, offset, origin);
}
long DLL_CALLCONV
_TellProc(fi_handle handle) {
return ftell((FILE *)handle);
}
// ----------------------------------------------------------
void
SetDefaultIO(FreeImageIO *io) {
io->read_proc = _ReadProc;
io->seek_proc = _SeekProc;
io->tell_proc = _TellProc;
io->write_proc = _WriteProc;
}
// =====================================================================
// Memory IO functions
// =====================================================================
unsigned DLL_CALLCONV
_MemoryReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
unsigned x;
FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data);
for(x = 0; x < count; x++) {
//if there isnt size bytes left to read, set pos to eof and return a short count
if( (mem_header->filelen - mem_header->curpos) < (long)size ) {
mem_header->curpos = mem_header->filelen;
break;
}
//copy size bytes count times
memcpy( buffer, (char *)mem_header->data + mem_header->curpos, size );
mem_header->curpos += size;
buffer = (char *)buffer + size;
}
return x;
}
unsigned DLL_CALLCONV
_MemoryWriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
void *newdata;
long newdatalen;
FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data);
//double the data block size if we need to
while( (mem_header->curpos + (long)(size*count)) >= mem_header->datalen ) {
//if we are at or above 1G, we cant double without going negative
if( mem_header->datalen & 0x40000000 ) {
//max 2G
if( mem_header->datalen == 0x7FFFFFFF ) {
return 0;
}
newdatalen = 0x7FFFFFFF;
} else if( mem_header->datalen == 0 ) {
//default to 4K if nothing yet
newdatalen = 4096;
} else {
//double size
newdatalen = mem_header->datalen << 1;
}
newdata = realloc( mem_header->data, newdatalen );
if( !newdata ) {
return 0;
}
mem_header->data = newdata;
mem_header->datalen = newdatalen;
}
memcpy( (char *)mem_header->data + mem_header->curpos, buffer, size*count );
mem_header->curpos += size*count;
if( mem_header->curpos > mem_header->filelen ) {
mem_header->filelen = mem_header->curpos;
}
return count;
}
int DLL_CALLCONV
_MemorySeekProc(fi_handle handle, long offset, int origin) {
FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data);
switch(origin) { //0 to filelen-1 are 'inside' the file
default:
case SEEK_SET: //can fseek() to 0-7FFFFFFF always
if( offset >= 0 ) {
mem_header->curpos = offset;
return 0;
}
break;
case SEEK_CUR:
if( mem_header->curpos + offset >= 0 ) {
mem_header->curpos += offset;
return 0;
}
break;
case SEEK_END:
if( mem_header->filelen + offset >= 0 ) {
mem_header->curpos = mem_header->filelen + offset;
return 0;
}
break;
}
return -1;
}
long DLL_CALLCONV
_MemoryTellProc(fi_handle handle) {
FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data);
return mem_header->curpos;
}
// ----------------------------------------------------------
void
SetMemoryIO(FreeImageIO *io) {
io->read_proc = _MemoryReadProc;
io->seek_proc = _MemorySeekProc;
io->tell_proc = _MemoryTellProc;
io->write_proc = _MemoryWriteProc;
}