1 // ==========================================================
2 // Input/Output functions
3 //
4 // Design and implementation by
5 // - Floris van den Berg (flvdberg@wxs.nl)
6 //
7 // This file is part of FreeImage 3
8 //
9 // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
10 // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
11 // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
12 // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
13 // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
14 // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
15 // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
16 // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
17 // THIS DISCLAIMER.
18 //
19 // Use at your own risk!
20 // ==========================================================
21
22 #include "FreeImage.h"
23 #include "Utilities.h"
24 #include "FreeImageIO.h"
25
26 // =====================================================================
27 // File IO functions
28 // =====================================================================
29
30 unsigned DLL_CALLCONV
_ReadProc(void * buffer,unsigned size,unsigned count,fi_handle handle)31 _ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
32 return (unsigned)fread(buffer, size, count, (FILE *)handle);
33 }
34
35 unsigned DLL_CALLCONV
_WriteProc(void * buffer,unsigned size,unsigned count,fi_handle handle)36 _WriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
37 return (unsigned)fwrite(buffer, size, count, (FILE *)handle);
38 }
39
40 int DLL_CALLCONV
_SeekProc(fi_handle handle,long offset,int origin)41 _SeekProc(fi_handle handle, long offset, int origin) {
42 return fseek((FILE *)handle, offset, origin);
43 }
44
45 long DLL_CALLCONV
_TellProc(fi_handle handle)46 _TellProc(fi_handle handle) {
47 return ftell((FILE *)handle);
48 }
49
50 // ----------------------------------------------------------
51
52 void
SetDefaultIO(FreeImageIO * io)53 SetDefaultIO(FreeImageIO *io) {
54 io->read_proc = _ReadProc;
55 io->seek_proc = _SeekProc;
56 io->tell_proc = _TellProc;
57 io->write_proc = _WriteProc;
58 }
59
60 // =====================================================================
61 // Memory IO functions
62 // =====================================================================
63
64 unsigned DLL_CALLCONV
_MemoryReadProc(void * buffer,unsigned size,unsigned count,fi_handle handle)65 _MemoryReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
66 unsigned x;
67
68 FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data);
69
70 for(x = 0; x < count; x++) {
71 long remaining_bytes = mem_header->file_length - mem_header->current_position;
72 //if there isn't size bytes left to read, set pos to eof and return a short count
73 if( remaining_bytes < (long)size ) {
74 if(remaining_bytes > 0) {
75 memcpy( buffer, (char *)mem_header->data + mem_header->current_position, remaining_bytes );
76 }
77 mem_header->current_position = mem_header->file_length;
78 break;
79 }
80 //copy size bytes count times
81 memcpy( buffer, (char *)mem_header->data + mem_header->current_position, size );
82 mem_header->current_position += size;
83 buffer = (char *)buffer + size;
84 }
85 return x;
86 }
87
88 unsigned DLL_CALLCONV
_MemoryWriteProc(void * buffer,unsigned size,unsigned count,fi_handle handle)89 _MemoryWriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
90 void *newdata;
91 long newdatalen;
92
93 FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data);
94
95 //double the data block size if we need to
96 while( (mem_header->current_position + (long)(size * count)) >= mem_header->data_length ) {
97 //if we are at or above 1G, we cant double without going negative
98 if( mem_header->data_length & 0x40000000 ) {
99 //max 2G
100 if( mem_header->data_length == 0x7FFFFFFF ) {
101 return 0;
102 }
103 newdatalen = 0x7FFFFFFF;
104 } else if( mem_header->data_length == 0 ) {
105 //default to 4K if nothing yet
106 newdatalen = 4096;
107 } else {
108 //double size
109 newdatalen = mem_header->data_length << 1;
110 }
111 newdata = realloc( mem_header->data, newdatalen );
112 if( !newdata ) {
113 return 0;
114 }
115 mem_header->data = newdata;
116 mem_header->data_length = newdatalen;
117 }
118 memcpy( (char *)mem_header->data + mem_header->current_position, buffer, size * count );
119 mem_header->current_position += size * count;
120 if( mem_header->current_position > mem_header->file_length ) {
121 mem_header->file_length = mem_header->current_position;
122 }
123 return count;
124 }
125
126 int DLL_CALLCONV
_MemorySeekProc(fi_handle handle,long offset,int origin)127 _MemorySeekProc(fi_handle handle, long offset, int origin) {
128 FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data);
129
130 // you can use _MemorySeekProc to reposition the pointer anywhere in a file
131 // the pointer can also be positioned beyond the end of the file
132
133 switch(origin) { //0 to filelen-1 are 'inside' the file
134 default:
135 case SEEK_SET: //can fseek() to 0-7FFFFFFF always
136 if( offset >= 0 ) {
137 mem_header->current_position = offset;
138 return 0;
139 }
140 break;
141
142 case SEEK_CUR:
143 if( mem_header->current_position + offset >= 0 ) {
144 mem_header->current_position += offset;
145 return 0;
146 }
147 break;
148
149 case SEEK_END:
150 if( mem_header->file_length + offset >= 0 ) {
151 mem_header->current_position = mem_header->file_length + offset;
152 return 0;
153 }
154 break;
155 }
156
157 return -1;
158 }
159
160 long DLL_CALLCONV
_MemoryTellProc(fi_handle handle)161 _MemoryTellProc(fi_handle handle) {
162 FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data);
163
164 return mem_header->current_position;
165 }
166
167 // ----------------------------------------------------------
168
169 void
SetMemoryIO(FreeImageIO * io)170 SetMemoryIO(FreeImageIO *io) {
171 io->read_proc = _MemoryReadProc;
172 io->seek_proc = _MemorySeekProc;
173 io->tell_proc = _MemoryTellProc;
174 io->write_proc = _MemoryWriteProc;
175 }
176