// ========================================================== // 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" // ===================================================================== // 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; }