diff options
Diffstat (limited to 'libs/freeimage/src/FreeImage/FreeImageIO.cpp')
-rw-r--r-- | libs/freeimage/src/FreeImage/FreeImageIO.cpp | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/libs/freeimage/src/FreeImage/FreeImageIO.cpp b/libs/freeimage/src/FreeImage/FreeImageIO.cpp new file mode 100644 index 0000000000..1cba25818e --- /dev/null +++ b/libs/freeimage/src/FreeImage/FreeImageIO.cpp @@ -0,0 +1,173 @@ +// ========================================================== +// 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 "../stdafx.h" + +// ===================================================================== +// File IO functions +// ===================================================================== + +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++) { + long remaining_bytes = mem_header->file_length - mem_header->current_position; + //if there isn't size bytes left to read, set pos to eof and return a short count + if( remaining_bytes < (long)size ) { + if(remaining_bytes > 0) { + memcpy( buffer, (char *)mem_header->data + mem_header->current_position, remaining_bytes ); + } + mem_header->current_position = mem_header->file_length; + break; + } + //copy size bytes count times + memcpy( buffer, (char *)mem_header->data + mem_header->current_position, size ); + mem_header->current_position += 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->current_position + (long)(size * count)) >= mem_header->data_length ) { + //if we are at or above 1G, we cant double without going negative + if( mem_header->data_length & 0x40000000 ) { + //max 2G + if( mem_header->data_length == 0x7FFFFFFF ) { + return 0; + } + newdatalen = 0x7FFFFFFF; + } else if( mem_header->data_length == 0 ) { + //default to 4K if nothing yet + newdatalen = 4096; + } else { + //double size + newdatalen = mem_header->data_length << 1; + } + newdata = realloc( mem_header->data, newdatalen ); + if( !newdata ) { + return 0; + } + mem_header->data = newdata; + mem_header->data_length = newdatalen; + } + memcpy( (char *)mem_header->data + mem_header->current_position, buffer, size * count ); + mem_header->current_position += size * count; + if( mem_header->current_position > mem_header->file_length ) { + mem_header->file_length = mem_header->current_position; + } + return count; +} + +int DLL_CALLCONV +_MemorySeekProc(fi_handle handle, long offset, int origin) { + FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data); + + // you can use _MemorySeekProc to reposition the pointer anywhere in a file + // the pointer can also be positioned beyond the end of the file + + 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->current_position = offset; + return 0; + } + break; + + case SEEK_CUR: + if( mem_header->current_position + offset >= 0 ) { + mem_header->current_position += offset; + return 0; + } + break; + + case SEEK_END: + if( mem_header->file_length + offset >= 0 ) { + mem_header->current_position = mem_header->file_length + offset; + return 0; + } + break; + } + + return -1; +} + +long DLL_CALLCONV +_MemoryTellProc(fi_handle handle) { + FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data); + + return mem_header->current_position; +} + +// ---------------------------------------------------------- + +void +SetMemoryIO(FreeImageIO *io) { + io->read_proc = _MemoryReadProc; + io->seek_proc = _MemorySeekProc; + io->tell_proc = _MemoryTellProc; + io->write_proc = _MemoryWriteProc; +} |