FS2_Open
Open source remastering of the Freespace 2 engine
cfilearchive.cpp
Go to the documentation of this file.
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 
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 
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 //
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 //
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 //
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 
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 
GLuint64EXT * result
Definition: Glext.h:10775
int cf_is_valid(CFILE *cfile)
Definition: cfile.cpp:935
#define MAX_CFILE_BLOCKS
Definition: cfilearchive.h:47
int raw_position
Definition: cfilearchive.h:38
int cfread_lua_number(double *buf, CFILE *cfile)
void _cdecl void void _cdecl void _cdecl Warning(char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
Assert(pm!=NULL)
Definition: cfile.h:28
#define CF_SEEK_SET
Definition: cfile.h:24
#define CF_SEEK_CUR
Definition: cfile.h:25
size_t max_read_len
Definition: cfilearchive.h:41
GLsizeiptr size
Definition: Glext.h:5496
#define Int3()
Definition: pstypes.h:292
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: Glext.h:7308
void * data
Definition: cfilearchive.h:29
int cftell(CFILE *cfile)
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
GLintptr offset
Definition: Glext.h:5497
int cfread(void *buf, int elsize, int nelem, CFILE *cfile)
#define CF_SEEK_END
Definition: cfile.h:26
Cfile_block Cfile_block_list[MAX_CFILE_BLOCKS]
Definition: cfile.cpp:99
int cfeof(CFILE *cfile)
int id
Definition: cfile.h:29
Definition: cfile.h:354
#define LOCATION
Definition: pstypes.h:245
hull_check pos
Definition: lua.cpp:5050
void cf_init_lowlevel_read_code(CFILE *cfile, int lib_offset, int size, int pos)
int cfseek(CFILE *cfile, int offset, int where)