NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
CrossPlatformFileIO.cpp
Go to the documentation of this file.
1// This file contains utilities for cross-platform file I/O.
2
3#include <ctype.h>
4#include <string.h>
5#include <stdlib.h>
6#include <stdio.h>
7#include <stddef.h>
8
9#ifdef WIN32
10 #include <Windows.h>
11#endif
12
13// The Windows headers create the WIN32 symbol if we are compiling for Windows.
14// Here, we create an analogous MACINTOSH symbol if we are compiling for Macintosh.
15#if (defined(GENERATINGPOWERPC) || defined(GENERATING68K))
16 #define MACINTOSH 1
17#endif
18
19#include "CrossPlatformFileIO.h"
20
21/* CPCreateFile(fullFilePath, overwrite, macCreator, macFileType)
22
23 Creates a file with the location and name specified by fullFilePath.
24
25 fullFilePath must be a native path.
26
27 If overwrite is true and a file by that name already exists, it first
28 deletes the conflicting file. If overwrite is false and a file by that
29 name exists, it returns an error.
30
31 macFileType is ignored on Windows. On Macintosh, it is used to set
32 the new file's type. For example, use 'TEXT' for a text file.
33
34 macCreator is ignored on Windows. On Macintosh, it is used to set
35 the new file's creator code. For example, use 'IGR0' (last character is zero)
36 for an file.
37
38 Returns 0 if OK or an error code.
39*/
40int
41CPCreateFile(const char* fullFilePath, int overwrite, long macCreator, long macFileType)
42{
43 int err;
44
45 if (overwrite) // Delete file if it exists and if overwrite is specified.
46 CPDeleteFile(fullFilePath); // Ignore error.
47
48 #ifdef MACINTOSH
49 if (err = create(fullFilePath, 0, macCreator, macFileType))
50 return err;
51 return 0;
52 #endif
53
54 #ifdef WIN32
55 {
56 HANDLE fileH;
57 long accessMode, shareMode;
58
59 err = 0;
60 accessMode = GENERIC_READ | GENERIC_WRITE;
61 shareMode = 0;
62 fileH = CreateFile((LPCSTR) fullFilePath, accessMode, shareMode, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); //LPCWSTR
63 if (fileH == INVALID_HANDLE_VALUE)
64 err = GetLastError();
65 else
66 CloseHandle(fileH);
67 return err;
68 }
69 #endif
70}
71
72/* CPDeleteFile(fullFilePath)
73
74 Deletes the file specified by fullFilePath.
75
76 fullFilePath must be a native path.
77
78 Returns 0 if OK or an error code.
79
80 Added for Igor Pro 3.13 but works with any version. However, some error
81 codes returned require Igor Pro 3.13 or later, so you will get bogus error
82 messages if you return these error codes to earlier versions of Igor.
83*/
84int
85CPDeleteFile(const char* fullFilePath)
86{
87 #ifdef MACINTOSH
88 int err;
89
90 if (err = fsdelete(fullFilePath, 0))
91 return err;
92 return 0;
93 #endif
94
95 #ifdef WIN32
96 {
97 int err;
98
99 err = 0;
100 if (DeleteFile((LPCSTR) fullFilePath) == 0) //LPCWSTR
101 err = GetLastError();
102 return err;
103 }
104 #endif
105}
106
107/* CPOpenFile(fullFilePath, readOrWrite, fileRefPtr)
108
109 If readOrWrite is zero, opens an existing file for reading and returns a file reference
110 via fileRefPtr.
111
112 If readOrWrite is non-zero, opens an existing file for writing or creates a new
113 file if none exists and returns a file reference via fileRefPtr.
114
115 fullFilePath must be a native path.
116
117 Returns 0 if OK or an error code.
118*/
119int
120CPOpenFile(const char* fullFilePath, int readOrWrite, CP_FILE_REF* fileRefPtr)
121{
122 *fileRefPtr = fopen(fullFilePath, readOrWrite ? "wb" : "rb");
123 if (*fileRefPtr == NULL)
124 return CP_FILE_OPEN_ERROR;
125 return 0;
126}
127
128/* CPCloseFile(fileRef)
129
130 Closes the referenced file.
131
132 Returns 0 if OK or an error code.
133
134 Added for Igor Pro 3.13 but works with any version. However, some error
135 codes returned require Igor Pro 3.13 or later, so you will get bogus error
136 messages if you return these error codes to earlier versions of Igor.
137*/
138int
140{
141 if (fclose(fileRef))
142 return CP_FILE_CLOSE_ERROR;
143 return 0;
144}
145
146/* CPReadFile(fileRef, count, buffer, numBytesReadPtr)
147
148 Reads count bytes from the referenced file into the buffer.
149
150 If numBytesReadPtr is not NULL, stores the number of bytes read in
151 *numBytesReadPtr.
152
153 Returns 0 if OK or an error code.
154
155 If bytes remain to be read in the file and you ask to read more bytes
156 than remain, the remaining bytes are returned and the function result is
157 zero. If no bytes remain to be read in the file and you ask to read bytes,
158 no bytes are returned and the function result is CP_FILE_EOF_ERROR.
159
160 CPReadFile is appropriate when you are reading data of variable size, in
161 which case you do not want to consider it an error if the end of file is reached
162 before reading all of the bytes that you requested. If you are reading a
163 record of fixed size, use use CPReadFile2 instead of CPReadFile.
164
165 Added for Igor Pro 3.13 but works with any version. However, some error
166 codes returned require Igor Pro 3.13 or later, so you will get bogus error
167 messages if you return these error codes to earlier versions of Igor.
168*/
169int
170CPReadFile(CP_FILE_REF fileRef, unsigned long count, void* buffer, unsigned long* numBytesReadPtr)
171{
172 unsigned long numBytesRead;
173
174 if (count == 0) {
175 if (numBytesReadPtr != NULL)
176 *numBytesReadPtr = 0;
177 return 0;
178 }
179
180 clearerr(fileRef);
181 numBytesRead = fread(buffer, 1, count, fileRef);
182 if (numBytesReadPtr != NULL)
183 *numBytesReadPtr = numBytesRead;
184 if (ferror(fileRef))
185 return CP_FILE_READ_ERROR;
186 if (numBytesRead==0 && CPAtEndOfFile(fileRef))
187 return CP_FILE_EOF_ERROR; // We were at the end of file when asked to read some bytes.
188 return 0;
189}
190
191/* CPReadFile2(fileRef, count, buffer, numBytesReadPtr)
192
193 Reads count bytes from the referenced file into the buffer.
194
195 If numBytesReadPtr is not NULL, stores the number of bytes read in
196 *numBytesReadPtr.
197
198 Returns 0 if OK or an error code.
199
200 If bytes remain to be read in the file and you ask to read more bytes
201 than remain, the remaining bytes are returned and the function result is
202 CP_FILE_EOF_ERROR.
203
204 CPReadFile2 is appropriate when you are reading a record of fixed size, in
205 which case you want to consider it an error if the end of file is reached
206 before reading all of the bytes in the record. If you are reading a record
207 of variable size then you should use CPReadFile instead of CPReadFile2.
208
209 Added for Igor Pro 3.13 but works with any version. However, some error
210 codes returned require Igor Pro 3.13 or later, so you will get bogus error
211 messages if you return these error codes to earlier versions of Igor.
212*/
213int
214CPReadFile2(CP_FILE_REF fileRef, unsigned long count, void* buffer, unsigned long* numBytesReadPtr)
215{
216 unsigned long numBytesRead;
217
218 if (count == 0) {
219 if (numBytesReadPtr != NULL)
220 *numBytesReadPtr = 0;
221 return 0;
222 }
223
224 clearerr(fileRef);
225 numBytesRead = fread(buffer, 1, count, fileRef);
226 if (numBytesReadPtr != NULL)
227 *numBytesReadPtr = numBytesRead;
228 if (ferror(fileRef))
229 return CP_FILE_READ_ERROR;
230 if (numBytesRead < count) { // We did not read all of the bytes requested.
231 if (CPAtEndOfFile(fileRef))
232 return CP_FILE_EOF_ERROR; // We hit the end of file.
233 return CP_FILE_READ_ERROR; // Some other occurred but ferror did not reflect it.
234 }
235 return 0;
236}
237
238/* CPWriteFile(fileRef, count, buffer, numBytesWrittenPtr)
239
240 Writes count bytes from the buffer to the referenced file.
241
242 If numBytesWrittenPtr is not NULL, stores the number of bytes written in
243 *numBytesWrittenPtr.
244
245 Returns 0 if OK or an error code.
246
247 Added for Igor Pro 3.13 but works with any version. However, some error
248 codes returned require Igor Pro 3.13 or later, so you will get bogus error
249 messages if you return these error codes to earlier versions of Igor.
250*/
251int
252CPWriteFile(CP_FILE_REF fileRef, unsigned long count, const void* buffer, unsigned long* numBytesWrittenPtr)
253{
254 unsigned long numBytesWritten;
255
256 if (count == 0) {
257 if (numBytesWrittenPtr != NULL)
258 *numBytesWrittenPtr = 0;
259 return 0;
260 }
261
262 numBytesWritten = fwrite(buffer, 1, count, fileRef);
263 if (numBytesWrittenPtr != NULL)
264 *numBytesWrittenPtr = numBytesWritten;
265 if (numBytesWritten != count)
266 return CP_FILE_WRITE_ERROR;
267 return 0;
268}
269
270/* CPGetFilePosition(fileRef, filePosPtr)
271
272 Returns via filePosPtr the current file position of the referenced file.
273
274 Returns 0 if OK or an error code.
275
276 Added for Igor Pro 3.13 but works with any version. However, some error
277 codes returned require Igor Pro 3.13 or later, so you will get bogus error
278 messages if you return these error codes to earlier versions of Igor.
279*/
280int
281CPGetFilePosition(CP_FILE_REF fileRef, unsigned long* filePosPtr)
282{
283 long pos;
284
285 pos = ftell(fileRef);
286 if (pos == -1L)
287 return CP_FILE_POS_ERROR;
288 *filePosPtr = pos;
289 return 0;
290}
291
292/* CPSetFilePosition(fileRef, filePos, mode)
293
294 Sets the current file position in the referenced file.
295
296 If mode is -1, then filePos is relative to the start of the file.
297 If mode is 0, then filePos is relative to the current file position.
298 If mode is 1, then filePos is relative to the end of the file.
299
300 Returns 0 if OK or an error code.
301
302 Added for Igor Pro 3.13 but works with any version. However, some error
303 codes returned require Igor Pro 3.13 or later, so you will get bogus error
304 messages if you return these error codes to earlier versions of Igor.
305*/
306int
307CPSetFilePosition(CP_FILE_REF fileRef, long filePos, int mode)
308{
309 int seekMode;
310
311 switch(mode) {
312 case -1:
313 seekMode = SEEK_SET;
314 break;
315 case 0:
316 seekMode = SEEK_CUR;
317 break;
318 case 1:
319 seekMode = SEEK_END;
320 break;
321 default:
322 return CP_FILE_POS_ERROR;
323 }
324
325 if (fseek(fileRef, filePos, seekMode) != 0)
326 return CP_FILE_POS_ERROR;
327 return 0;
328}
329
330/* CPAtEndOfFile(fileRef)
331
332 Returns 1 if the current file position is at the end of file, 0 if not.
333
334 Added for Igor Pro 3.13 but works with any version. However, some error
335 codes returned require Igor Pro 3.13 or later, so you will get bogus error
336 messages if you return these error codes to earlier versions of Igor.
337*/
338int
340{
341 if (feof(fileRef)) // Hit end of file?
342 return 1;
343 return 0;
344}
345
346/* CPNumberOfBytesInFile(fileRef, numBytesPtr)
347
348 Returns via numBytesPtr the total number of bytes in the referenced file.
349
350 Returns 0 if OK or an error code.
351
352 Added for Igor Pro 3.13 but works with any version. However, some error
353 codes returned require Igor Pro 3.13 or later, so you will get bogus error
354 messages if you return these error codes to earlier versions of Igor.
355*/
356int
357CPNumberOfBytesInFile(CP_FILE_REF fileRef, unsigned long* numBytesPtr)
358{
359 long originalPos;
360
361 originalPos = ftell(fileRef);
362 if (fseek(fileRef, 0, SEEK_END) != 0)
363 return CP_FILE_POS_ERROR;
364 *numBytesPtr = ftell(fileRef);
365 if (*numBytesPtr == -1L)
366 return CP_FILE_POS_ERROR;
367 if (fseek(fileRef, originalPos, SEEK_SET) != 0)
368 return CP_FILE_POS_ERROR;
369 return 0;
370}
371
372
int CPCloseFile(CP_FILE_REF fileRef)
int CPDeleteFile(const char *fullFilePath)
int CPWriteFile(CP_FILE_REF fileRef, unsigned long count, const void *buffer, unsigned long *numBytesWrittenPtr)
int CPSetFilePosition(CP_FILE_REF fileRef, long filePos, int mode)
int CPGetFilePosition(CP_FILE_REF fileRef, unsigned long *filePosPtr)
int CPNumberOfBytesInFile(CP_FILE_REF fileRef, unsigned long *numBytesPtr)
int CPReadFile2(CP_FILE_REF fileRef, unsigned long count, void *buffer, unsigned long *numBytesReadPtr)
int CPOpenFile(const char *fullFilePath, int readOrWrite, CP_FILE_REF *fileRefPtr)
int CPReadFile(CP_FILE_REF fileRef, unsigned long count, void *buffer, unsigned long *numBytesReadPtr)
int CPCreateFile(const char *fullFilePath, int overwrite, long macCreator, long macFileType)
int CPAtEndOfFile(CP_FILE_REF fileRef)
#define CP_FILE_CLOSE_ERROR
#define CP_FILE_OPEN_ERROR
#define CP_FILE_EOF_ERROR
#define CP_FILE_WRITE_ERROR
#define CP_FILE_POS_ERROR
#define CP_FILE_REF
#define CP_FILE_READ_ERROR