source: trunk/tools/common/kFile.cpp@ 3592

Last change on this file since 3592 was 3592, checked in by bird, 25 years ago

File I/O class - initial coding, not tested at all!

File size: 8.4 KB
Line 
1/* $Id: kFile.cpp,v 1.1 2000-05-23 18:23:05 bird Exp $
2 *
3 * kFile - Simple (for the time being) file class.
4 *
5 * Copyright (c) 2000 knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
6 *
7 * Project Odin Software License can be found in LICENSE.TXT
8 *
9 */
10
11/*******************************************************************************
12* Defined Constants And Macros *
13*******************************************************************************/
14#define INCL_DOSFILEMGR
15#define INCL_DOSERRORS
16
17
18/*******************************************************************************
19* Header Files *
20*******************************************************************************/
21#include <os2.h>
22#include <string.h>
23
24#include <kFile.h>
25
26
27/**
28 * Updates the internal filestatus struct.
29 * @returns Success indicator.
30 * On success filestatus is refreshed.
31 * @remark
32 */
33BOOL kFile::refreshFileStatus()
34{
35 if (!fStatusClean)
36 {
37 rc = (int)DosQueryFileInfo(hFile, FIL_QUERYEASIZE, &filestatus, sizeof(filestatus));
38 fStatusClean = (rc == NO_ERROR);
39 if (!fStatusClean && fThrowErrors)
40 throw (rc);
41 }
42 else
43 rc = NO_ERROR;
44
45 return fStatusClean;
46}
47
48
49
50/**
51 * Changes the real file position to match the virtual file position.
52 * @returns Success indicator.
53 */
54BOOL kFile::position()
55{
56 /*
57 * If virtual file offset is different from the real,
58 * issue a set file pointer call.
59 */
60 if (offVirtual != offReal)
61 {
62 ULONG off;
63 rc = (int)DosSetFilePtr(hFile, offVirtual, FILE_BEGIN, &off);
64 if (rc != NO_ERROR || off != offVirtual)
65 {
66 if (fThrowErrors)
67 throw (rc);
68 return FALSE;
69 }
70 offReal = offVirtual;
71 }
72
73 return TRUE;
74}
75
76
77
78/**
79 * Opens a file for binary reading or readwrite.
80 * @returns <object> with state updated.
81 * Throws OS/2 error on error.
82 * @param pszFilename Filename.
83 * @param fReadOnly TRUE: Open the file readonly. (default)
84 * FALSE: Open the file readwrite appending
85 * existing files.
86 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
87 */
88kFile::kFile(const char *pszFilename, BOOL fReadOnly/*=TRUE*/)
89: fReadOnly(fReadOnly),
90 fStatusClean(FALSE),
91 fThrowErrors(FALSE),
92 offVirtual(0),
93 offReal(0)
94{
95 ULONG fulOpenFlags;
96 ULONG fulOpenMode;
97 ULONG ulAction;
98
99 /*
100 * Determin open flags according to fReadOnly.
101 */
102 if (fReadOnly)
103 {
104 fulOpenFlags = OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
105 fulOpenMode = OPEN_SHARE_DENYWRITE | OPEN_ACCESS_READONLY;
106 }
107 else
108 {
109 fulOpenFlags = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
110 fulOpenMode = OPEN_SHARE_DENYWRITE | OPEN_ACCESS_READWRITE;
111 }
112
113 rc = (int)DosOpen((PCSZ)pszFilename, &hFile, &ulAction, 0, FILE_NORMAL,
114 fulOpenFlags, fulOpenMode, NULL);
115 if (rc != NO_ERROR)
116 throw (rc);
117
118 if (refreshFileStatus())
119 throw (rc);
120}
121
122
123
124/**
125 * Closes the file.
126 */
127kFile::~kFile()
128{
129 DosClose(hFile);
130}
131
132
133
134/**
135 * Reads <cbBuffer> bytes from the current file posistion into the buffer.
136 * @returns success indicator. (TRUE/FALSE)
137 * @param pvBuffer Output buffer.
138 * @param cbBuffer Amount of bytes to read.
139 */
140BOOL kFile::read(void *pvBuffer, long cbBuffer)
141{
142 if (position())
143 {
144 ULONG cbRead;
145 rc = (int)DosRead(hFile, pvBuffer, cbBuffer, &cbRead);
146 if (rc == NO_ERROR)
147 {
148 offVirtual = offReal += cbRead;
149 return TRUE;
150 }
151 }
152
153 if (fThrowErrors)
154 throw (rc);
155 return FALSE;
156}
157
158
159
160/**
161 * Reads <cbBuffer> bytes at file offset <off>.
162 * @returns success indicator. (TRUE/FALSE)
163 * @param pvBuffer Output buffer.
164 * @param cbBuffer Amount of bytes to read.
165 * @param off Absolute file offset.
166 */
167BOOL kFile::readAt(void *pvBuffer, long cbBuffer, long off)
168{
169 return set(off) && read(pvBuffer, cbBuffer);
170}
171
172
173
174/**
175 * Writes <cbBuffer> bytes to the file at the current file position.
176 * @returns success indicator. (TRUE/FALSE)
177 * @param pvBuffer Output buffer.
178 * @param cbBuffer Amount of bytes to write.
179 */
180BOOL kFile::write(void *pvBuffer, long cbBuffer)
181{
182 if (fReadOnly)
183 rc = ERROR_ACCESS_DENIED;
184 else
185 {
186 if (position())
187 {
188 ULONG cbWrote;
189
190 rc = (int)DosWrite(hFile, pvBuffer, cbBuffer, &cbWrote);
191 if (rc == NO_ERROR)
192 {
193 fStatusClean = FALSE;
194 offVirtual = offReal += cbWrote;
195 return TRUE;
196 }
197 }
198 }
199
200 if (fThrowErrors)
201 throw(rc);
202 return FALSE;
203}
204
205
206/**
207 * Write <cbBuffer> bytes at file offset <off> from <pvBuffer>.
208 * @returns success indicator. (TRUE/FALSE)
209 * @param pvBuffer Output buffer.
210 * @param cbBuffer Amount of bytes to write.
211 * @param off Absolute file offset.
212 */
213BOOL kFile::writeAt(void *pvBuffer, long cbBuffer, long off)
214{
215 return set(off) && write(pvBuffer, cbBuffer);
216}
217
218
219
220/**
221 * Seek relative to the current position.
222 * @returns Success indicator.
223 * @param off Relative reposition.
224 */
225BOOL kFile::move(long off)
226{
227 if ((off + offVirtual) & 0x80000000UL) /* above 2GB or negative */
228 rc = ERROR_NEGATIVE_SEEK;
229 else
230 {
231 if (off + offVirtual > filestatus.cbFile && fReadOnly) /* can't expand readonly file. */
232 rc = ERROR_HANDLE_EOF;
233 else
234 {
235 offVirtual += off;
236 return TRUE;
237 }
238 }
239
240 if (fThrowErrors)
241 throw(rc);
242 return FALSE;
243}
244
245
246/**
247 * Seek to an absolute position in the file (off).
248 * @returns Success indicator.
249 * @param off New file position.
250 */
251BOOL kFile::set(long off)
252{
253 if (off < 0)
254 rc = ERROR_NEGATIVE_SEEK;
255 else
256 {
257 if ((unsigned long)off > filestatus.cbFile && fReadOnly)
258 rc = ERROR_HANDLE_EOF;
259 else
260 {
261 offVirtual = off;
262 rc = NO_ERROR;
263 return TRUE;
264 }
265 }
266 if (fThrowErrors)
267 throw(rc);
268 return FALSE;
269}
270
271
272/**
273 * Seek to the end of the file.
274 * @returns Success indicator. TRUE / FALSE.
275 * @remark Will only throw error if refreshFileStatus failes.
276 */
277BOOL kFile::end()
278{
279 if (!refreshFileStatus())
280 return FALSE;
281 offVirtual = filestatus.cbFile; //?? or +1
282 rc = NO_ERROR;
283 return TRUE;
284}
285
286
287/**
288 * Seek to the start of the file.
289 * @returns TRUE.
290 * @remark Will never throw errors.
291 */
292BOOL kFile::start()
293{
294 offVirtual = 0;
295 rc = NO_ERROR;
296 return TRUE;
297}
298
299
300
301/**
302 * Get the size of the file.
303 * @returns Returns file size on success.
304 * -1 on error.
305 * @remark Will only throw error if refreshFileStatus failes.
306 */
307LONG kFile::getSize()
308{
309 if (!refreshFileStatus())
310 return -1;
311
312 return filestatus.cbFile;
313}
314
315
316
317/**
318 * Checks if we have reached the file end.
319 * @returns TRUE if end-of-file is reached.
320 * FALSE is not end-of-file.
321 * @remark Will only throw error if refreshFileStatus failes.
322 */
323BOOL kFile::isEOF()
324{
325 #if 0
326 throw(ERROR_NOT_SUPPORTED); //this method don't currently work! Need to use flag!
327 #else
328 if (!refreshFileStatus())
329 return (BOOL)-1;
330
331 return filestatus.cbFile >= offReal; //???
332 #endif
333}
334
335
336
337/**
338 * Set error behaviour to fail by throwing the OS/2 return code when an
339 * error occures.
340 * @returns TRUE;
341 * @remark Will never throw errors.
342 */
343BOOL kFile::setThrowOnErrors()
344{
345 fThrowErrors = TRUE;
346 rc = NO_ERROR;
347 return TRUE;
348}
349
350
351/**
352 * Set error behaviour to fail by return FALSE when an error has occures.
353 * @returns TRUE;
354 * @remark Will never throw errors.
355 */
356BOOL kFile::setFailOnErrors()
357{
358 fThrowErrors = FALSE;
359 rc = NO_ERROR;
360 return TRUE;
361}
362
363
364/**
365 * Gets the last error code.
366 * @returns OS/2 error code for the last operation.
367 * @remark Will never throw errors.
368 */
369int kFile::getLastError()
370{
371 return rc;
372}
373
Note: See TracBrowser for help on using the repository browser.