Coverage Report

Created: 2023-12-08 06:53

/src/freeimage-svn/FreeImage/trunk/Source/FreeImage/FreeImageIO.cpp
Line
Count
Source (jump to first uncovered line)
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 
31
0
_ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
32
0
  return (unsigned)fread(buffer, size, count, (FILE *)handle);
33
0
}
34
35
unsigned DLL_CALLCONV 
36
0
_WriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
37
0
  return (unsigned)fwrite(buffer, size, count, (FILE *)handle);
38
0
}
39
40
int DLL_CALLCONV
41
0
_SeekProc(fi_handle handle, long offset, int origin) {
42
0
  return fseek((FILE *)handle, offset, origin);
43
0
}
44
45
long DLL_CALLCONV
46
0
_TellProc(fi_handle handle) {
47
0
  return ftell((FILE *)handle);
48
0
}
49
50
// ----------------------------------------------------------
51
52
void
53
0
SetDefaultIO(FreeImageIO *io) {
54
0
  io->read_proc  = _ReadProc;
55
0
  io->seek_proc  = _SeekProc;
56
0
  io->tell_proc  = _TellProc;
57
0
  io->write_proc = _WriteProc;
58
0
}
59
60
// =====================================================================
61
// Memory IO functions
62
// =====================================================================
63
64
/**
65
The _MemoryReadProc function reads up to count items of size bytes from the input stream and stores them in buffer.
66
_MemoryReadProc returns the number of full items actually read, 
67
which may be less than count if an error occurs or if the end of the file is encountered before reaching count.
68
If size or count is 0, _MemoryReadProc returns 0 and the buffer contents are unchanged
69
70
@param buffer
71
@param size
72
@param count
73
@param handle
74
@return
75
*/
76
unsigned DLL_CALLCONV
77
400M
_MemoryReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
78
400M
  if (!handle || !buffer || (size == 0) || (count == 0)) {
79
26.4k
    return 0;
80
26.4k
  }
81
82
400M
  FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data);
83
84
400M
  const int required_bytes = (int)(size) * count;
85
400M
  const int remaining_bytes = mem_header->file_length - mem_header->current_position;
86
87
400M
  if ((required_bytes > 0) && (remaining_bytes > 0)) {
88
373M
    if (required_bytes <= remaining_bytes) {
89
      // copy size bytes count times
90
372M
      memcpy(buffer, (char*)mem_header->data + mem_header->current_position, (size_t)required_bytes);
91
372M
      mem_header->current_position += required_bytes;
92
372M
      return count;
93
372M
    }
94
683k
    else {
95
      // if there isn't required_bytes bytes left to read, set pos to eof and return a short count
96
683k
      memcpy(buffer, (char*)mem_header->data + mem_header->current_position, (size_t)remaining_bytes);
97
683k
      mem_header->current_position = mem_header->file_length;
98
683k
      return (unsigned)(remaining_bytes / size);
99
683k
    }
100
373M
  }
101
  
102
  // if size or count is 0, _MemoryReadProc returns 0 and the buffer contents are unchanged.
103
26.9M
  return 0;
104
400M
}
105
106
unsigned DLL_CALLCONV 
107
0
_MemoryWriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
108
0
  if (!handle || !buffer) {
109
0
    return 0;
110
0
  }
111
112
0
  FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data);
113
114
0
  const long required_bytes = (long)(size * count);
115
116
  // double the data block size if we need to
117
0
  while( (mem_header->current_position + required_bytes) >= mem_header->data_length ) {
118
0
    long newdatalen = 0;
119
120
    // if we are at or above 1G, we cant double without going negative
121
0
    if( mem_header->data_length & 0x40000000 ) {
122
      // max 2G
123
0
      if( mem_header->data_length == 0x7FFFFFFF ) {
124
0
        return 0;
125
0
      }
126
0
      newdatalen = 0x7FFFFFFF;
127
0
    } else if( mem_header->data_length == 0 ) {
128
      // default to 4K if nothing yet
129
0
      newdatalen = 4096;
130
0
    } else {
131
      // double size
132
0
      newdatalen = mem_header->data_length << 1;
133
0
    }
134
0
    void *newdata = realloc(mem_header->data, newdatalen);
135
0
    if(!newdata) {
136
0
      return 0;
137
0
    }
138
0
    mem_header->data = newdata;
139
0
    mem_header->data_length = newdatalen;
140
0
  }
141
142
0
  memcpy((char *)mem_header->data + mem_header->current_position, buffer, required_bytes);
143
0
  mem_header->current_position += required_bytes;
144
145
0
  if( mem_header->current_position > mem_header->file_length ) {
146
0
    mem_header->file_length = mem_header->current_position;
147
0
  }
148
149
0
  return count;
150
0
}
151
152
/**
153
The _MemorySeekProc function moves the file pointer (if any) associated with stream to a new location that is offset bytes from origin. 
154
The next operation on the stream takes place at the new location. On a stream open for update, the next operation can be either a read or a write.
155
The argument origin must be one of the following constants, defined in STDIO.H:
156
  SEEK_CUR  Current position of file pointer.
157
  SEEK_END  End of file.
158
  SEEK_SET  Beginning of file.
159
You can use _MemorySeekProc to reposition the pointer anywhere in a file. 
160
The pointer can also be positioned beyond the end of the file. 
161
162
@param handle
163
@param offset
164
@param origin
165
@return If successful, returns 0. Otherwise, returns -1.
166
*/
167
int DLL_CALLCONV 
168
183M
_MemorySeekProc(fi_handle handle, long offset, int origin) {
169
183M
  if (!handle) {
170
0
    return -1;
171
0
  }
172
173
183M
  FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data);
174
175
  // you can use _MemorySeekProc to reposition the pointer anywhere in a file
176
  // the pointer can also be positioned beyond the end of the file
177
178
183M
  switch (origin) { //0 to filelen-1 are 'inside' the file
179
0
    default:
180
180M
    case SEEK_SET: //can fseek() to 0-7FFFFFFF always
181
180M
      if ((offset >= 0) && (offset <= std::numeric_limits<int>::max())) {
182
        // the 64-bit long offset may overflow when casted to int
183
156M
        mem_header->current_position = offset;
184
156M
        return 0;
185
156M
      }
186
24.0M
      break;
187
188
24.0M
    case SEEK_CUR:
189
2.73M
      if (((mem_header->current_position + offset) >= 0) && ((mem_header->current_position + offset) <= std::numeric_limits<int>::max())) {
190
        // the 64-bit result may overflow when casted to int
191
2.70M
        mem_header->current_position += offset;
192
2.70M
        return 0;
193
2.70M
      }
194
26.9k
      break;
195
196
96.5k
    case SEEK_END:
197
96.5k
      if (((mem_header->file_length + offset) >= 0) && ((mem_header->file_length + offset) <= std::numeric_limits<int>::max())) {
198
        // the 64-bit result may overflow when casted to int
199
96.5k
        mem_header->current_position = mem_header->file_length + offset;
200
96.5k
        return 0;
201
96.5k
      }
202
0
      break;
203
183M
  }
204
205
24.1M
  return -1;
206
183M
}
207
208
long DLL_CALLCONV 
209
269M
_MemoryTellProc(fi_handle handle) {
210
269M
  if (!handle) {
211
0
    return -1;
212
0
  }
213
269M
  FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data);
214
269M
  return mem_header->current_position;
215
269M
}
216
217
// ----------------------------------------------------------
218
219
void
220
30.0k
SetMemoryIO(FreeImageIO *io) {
221
30.0k
  io->read_proc  = _MemoryReadProc;
222
30.0k
  io->seek_proc  = _MemorySeekProc;
223
30.0k
  io->tell_proc  = _MemoryTellProc;
224
30.0k
  io->write_proc = _MemoryWriteProc;
225
30.0k
}