1 /*
2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
3 *
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on the
6 * source.
7 *
8 */
9
10
11
12 #define _CFILE_INTERNAL
13
14 #include <stdlib.h>
15 #include <string.h>
16 #include <stdio.h>
17
18 #ifdef _WIN32
19 #include <io.h>
20 #include <direct.h>
21 #include <windows.h>
22 #include <winbase.h> /* needed for memory mapping of file functions */
23 #endif
24
25 #include "cfile/cfile.h"
26 #include "cfile/cfilearchive.h"
27 #include "luaconf.h"
28
29 #include <sstream>
30
31
32 #define CHECK_POSITION
33
34 // Called once to setup the low-level reading code.
35
cf_init_lowlevel_read_code(CFILE * cfile,int lib_offset,int size,int pos)36 void cf_init_lowlevel_read_code( CFILE * cfile, int lib_offset, int size, int pos )
37 {
38 Assert(cfile != NULL);
39
40 Cfile_block *cb;
41 Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
42 cb = &Cfile_block_list[cfile->id];
43
44 cb->lib_offset = lib_offset;
45 cb->raw_position = pos;
46 cb->size = size;
47
48 if ( cb->fp ) {
49 if ( cb->lib_offset ) {
50 fseek( cb->fp, cb->lib_offset, SEEK_SET );
51 }
52
53 #if defined(CHECK_POSITION) && !defined(NDEBUG)
54 int raw_position;
55 raw_position = ftell(cb->fp) - cb->lib_offset;
56 Assert(raw_position == cb->raw_position);
57 #endif
58 }
59 }
60
61
62
63 // cfeof() Tests for end-of-file on a stream
64 //
65 // returns a nonzero value after the first read operation that attempts to read
66 // past the end of the file. It returns 0 if the current position is not end of file.
67 // There is no error return.
68
cfeof(CFILE * cfile)69 int cfeof(CFILE *cfile)
70 {
71 Assert(cfile != NULL);
72
73 Cfile_block *cb;
74 Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
75 cb = &Cfile_block_list[cfile->id];
76
77 int result;
78
79 result = 0;
80
81 // cfeof() not supported for memory-mapped files
82 Assert( !cb->data );
83
84 Assert(cb->fp != NULL);
85
86 #if defined(CHECK_POSITION) && !defined(NDEBUG)
87 int raw_position;
88 raw_position = ftell(cb->fp) - cb->lib_offset;
89 Assert(raw_position == cb->raw_position);
90 #endif
91
92 if (cb->raw_position >= cb->size ) {
93 result = 1;
94 } else {
95 result = 0;
96 }
97
98 return result;
99 }
100
101 // cftell() returns offset into file
102 //
103 // returns: success ==> offset into the file
104 // error ==> -1
105 //
cftell(CFILE * cfile)106 int cftell( CFILE * cfile )
107 {
108 Assert(cfile != NULL);
109 Cfile_block *cb;
110 Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
111 cb = &Cfile_block_list[cfile->id];
112
113 // Doesn't work for memory mapped files
114 Assert( !cb->data );
115
116 Assert(cb->fp != NULL);
117
118 #if defined(CHECK_POSITION) && !defined(NDEBUG)
119 int raw_position;
120 raw_position = ftell(cb->fp) - cb->lib_offset;
121 Assert(raw_position == cb->raw_position);
122 #endif
123
124 return cb->raw_position;
125 }
126
127
128 // cfseek() moves the file pointer
129 //
130 // returns: success ==> 0
131 // error ==> non-zero
132 //
cfseek(CFILE * cfile,int offset,int where)133 int cfseek( CFILE *cfile, int offset, int where )
134 {
135
136 Assert(cfile != NULL);
137 Cfile_block *cb;
138 Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
139 cb = &Cfile_block_list[cfile->id];
140
141
142 // TODO: seek to offset in memory mapped file
143 Assert( !cb->data );
144 Assert( cb->fp != NULL );
145
146 int goal_position;
147
148 switch( where ) {
149 case CF_SEEK_SET:
150 goal_position = offset+cb->lib_offset;
151 break;
152 case CF_SEEK_CUR:
153 {
154 goal_position = cb->raw_position+offset+cb->lib_offset;
155 }
156 break;
157 case CF_SEEK_END:
158 goal_position = cb->size+offset+cb->lib_offset;
159 break;
160 default:
161 Int3();
162 return 1;
163 }
164
165 int result = fseek(cb->fp, goal_position, SEEK_SET );
166 cb->raw_position = goal_position - cb->lib_offset;
167
168 #if defined(CHECK_POSITION) && !defined(NDEBUG)
169 int tmp_offset;
170 tmp_offset = (int)ftell(cb->fp) - cb->lib_offset;
171 Assert(tmp_offset==cb->raw_position);
172 #endif
173
174 return result;
175 }
176
177
178 // cfread() reads from a file
179 //
180 // returns: returns the number of full elements read
181 //
182 //
cfread(void * buf,int elsize,int nelem,CFILE * cfile)183 int cfread(void *buf, int elsize, int nelem, CFILE *cfile)
184 {
185 if(!cf_is_valid(cfile))
186 return 0;
187
188 int size = elsize*nelem;
189
190 if(buf == NULL || size <= 0)
191 return 0;
192
193 Cfile_block *cb = &Cfile_block_list[cfile->id];
194
195 // cfread() not supported for memory-mapped files
196 if(cb->data != NULL)
197 {
198 Warning(LOCATION, "Writing is not supported for mem-mapped files");
199 return 0;
200 }
201
202 if ( (cb->raw_position+size) > cb->size ) {
203 size = cb->size - cb->raw_position;
204 if ( size < 1 ) {
205 return 0;
206 }
207 //mprintf(( "CFILE: EOF encountered in file\n" ));
208 }
209
210 if (cb->max_read_len) {
211 if ( (size_t)(cb->raw_position+size) > cb->max_read_len ) {
212 std::ostringstream s_buf;
213 s_buf << "Attempted to read " << size << "-byte(s) beyond length limit";
214
215 throw cfile::max_read_length(s_buf.str());
216 }
217 }
218
219 int bytes_read = fread( buf, 1, size, cb->fp );
220 if ( bytes_read > 0 ) {
221 cb->raw_position += bytes_read;
222 }
223
224 #if defined(CHECK_POSITION) && !defined(NDEBUG)
225 int tmp_offset;
226 tmp_offset = ftell(cb->fp) - cb->lib_offset;
227 Assert(tmp_offset==cb->raw_position);
228 #endif
229
230 return bytes_read / elsize;
231
232 }
233
cfread_lua_number(double * buf,CFILE * cfile)234 int cfread_lua_number(double *buf, CFILE *cfile)
235 {
236 if(!cf_is_valid(cfile))
237 return 0;
238
239 if(buf == NULL)
240 return 0;
241
242 Cfile_block *cb = &Cfile_block_list[cfile->id];
243
244 // cfread() not supported for memory-mapped files
245 if(cb->data != NULL)
246 {
247 Warning(LOCATION, "Writing is not supported for mem-mapped files");
248 return 0;
249 }
250
251 long orig_pos = ftell(cb->fp);
252 int items_read = fscanf(cb->fp, LUA_NUMBER_SCAN, buf);
253 cb->raw_position += ftell(cb->fp)-orig_pos;
254
255 #if defined(CHECK_POSITION) && !defined(NDEBUG)
256 int tmp_offset;
257 tmp_offset = ftell(cb->fp) - cb->lib_offset;
258 Assert(tmp_offset==cb->raw_position);
259 #endif
260
261 return items_read;
262
263 }
264
265