1 /*
2 * HLLib
3 * Copyright (C) 2006-2010 Ryan Gregg
4
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later
9 * version.
10 */
11
12 #include "HLLib.h"
13 #include "FileStream.h"
14
15 using namespace HLLib;
16 using namespace HLLib::Streams;
17
18 #ifdef _WIN32
CFileStream(const hlChar * lpFileName)19 CFileStream::CFileStream(const hlChar *lpFileName) : hFile(0), uiMode(HL_MODE_INVALID)
20 #else
21 CFileStream::CFileStream(const hlChar *lpFileName) : iFile(-1), uiMode(HL_MODE_INVALID)
22 #endif
23 {
24 this->lpFileName = new hlChar[strlen(lpFileName) + 1];
25 strcpy(this->lpFileName, lpFileName);
26 }
27
~CFileStream()28 CFileStream::~CFileStream()
29 {
30 this->Close();
31
32 delete []this->lpFileName;
33 }
34
GetType() const35 HLStreamType CFileStream::GetType() const
36 {
37 return HL_STREAM_FILE;
38 }
39
GetFileName() const40 const hlChar *CFileStream::GetFileName() const
41 {
42 return this->lpFileName;
43 }
44
GetOpened() const45 hlBool CFileStream::GetOpened() const
46 {
47 #ifdef _WIN32
48 return this->hFile != 0;
49 #else
50 return this->iFile >= 0;
51 #endif
52 }
53
GetMode() const54 hlUInt CFileStream::GetMode() const
55 {
56 return this->uiMode;
57 }
58
Open(hlUInt uiMode)59 hlBool CFileStream::Open(hlUInt uiMode)
60 {
61 this->Close();
62
63 #ifdef _WIN32
64 DWORD dwDesiredAccess = ((uiMode & HL_MODE_READ) ? GENERIC_READ : 0) | ((uiMode & HL_MODE_WRITE) ? GENERIC_WRITE : 0);
65 DWORD dwShareMode = (uiMode & HL_MODE_VOLATILE) ? FILE_SHARE_READ | FILE_SHARE_WRITE : ((uiMode & HL_MODE_READ) && !(uiMode & HL_MODE_WRITE) ? FILE_SHARE_READ : 0);
66 DWORD dwCreationDisposition = (uiMode & HL_MODE_WRITE) && (uiMode & HL_MODE_CREATE) ? (bOverwriteFiles ? CREATE_ALWAYS : CREATE_NEW) : ((uiMode & HL_MODE_READ) || (uiMode & HL_MODE_WRITE) ? OPEN_EXISTING : 0);
67
68 if(dwDesiredAccess == 0 || dwCreationDisposition == 0)
69 {
70 LastError.SetErrorMessageFormated("Invalid open mode (%#.8x).", uiMode);
71
72 return hlFalse;
73 }
74
75 this->hFile = CreateFile(this->lpFileName, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL);
76
77 if(this->hFile == INVALID_HANDLE_VALUE)
78 {
79 LastError.SetSystemErrorMessage("Error opening file.");
80
81 this->hFile = 0;
82 return hlFalse;
83 }
84 #else
85 hlInt iMode;
86
87 if((uiMode & HL_MODE_READ) && (uiMode & HL_MODE_WRITE))
88 {
89 iMode = O_RDWR;
90 }
91 else if(uiMode & HL_MODE_READ)
92 {
93 iMode = O_RDONLY;
94 }
95 else if(uiMode & HL_MODE_WRITE)
96 {
97 iMode = O_WRONLY;
98 }
99
100 if((uiMode & HL_MODE_WRITE) && (uiMode & HL_MODE_CREATE))
101 {
102 iMode |= bOverwriteFiles ? O_CREAT | O_TRUNC : O_CREAT | O_EXCL;
103 }
104
105 if((uiMode & (HL_MODE_READ | HL_MODE_WRITE)) == 0)
106 {
107 LastError.SetErrorMessageFormated("Invalid open mode (%#.8x).", uiMode);
108
109 return hlFalse;
110 }
111
112 this->iFile = open(this->lpFileName, iMode | O_BINARY | O_RANDOM, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
113
114 if(this->iFile < 0)
115 {
116 LastError.SetSystemErrorMessage("Error opening file.");
117
118 this->iFile = -1;
119 return hlFalse;
120 }
121 #endif
122
123 this->uiMode = uiMode;
124
125 return hlTrue;
126 }
127
Close()128 hlVoid CFileStream::Close()
129 {
130 if(this->GetOpened())
131 {
132 #ifdef _WIN32
133 CloseHandle(this->hFile);
134 this->hFile = 0;
135 #else
136 close(this->iFile);
137 this->iFile = -1;
138 #endif
139
140 this->uiMode = HL_MODE_INVALID;
141 }
142 }
143
GetStreamSize() const144 hlULongLong CFileStream::GetStreamSize() const
145 {
146 if(!this->GetOpened())
147 {
148 return 0;
149 }
150
151 #ifdef _WIN32
152 LARGE_INTEGER liFileSize;
153 return GetFileSizeEx(this->hFile, &liFileSize) ? static_cast<hlULongLong>(liFileSize.QuadPart) : 0;
154 #else
155 struct stat Stat;
156
157 return fstat(this->iFile, &Stat) < 0 ? 0 : Stat.st_size;
158 #endif
159 }
160
GetStreamPointer() const161 hlULongLong CFileStream::GetStreamPointer() const
162 {
163 if(!this->GetOpened())
164 {
165 return 0;
166 }
167
168 #ifdef _WIN32
169 LARGE_INTEGER liOffset;
170 liOffset.QuadPart = 0;
171
172 LARGE_INTEGER liPointer;
173 return SetFilePointerEx(this->hFile, liOffset, &liPointer, FILE_CURRENT) ? static_cast<hlULongLong>(liPointer.QuadPart) : 0;
174 #else
175 return (hlUInt)lseek(this->iFile, 0, SEEK_CUR);
176 #endif
177 }
178
Seek(hlLongLong iOffset,HLSeekMode eSeekMode)179 hlULongLong CFileStream::Seek(hlLongLong iOffset, HLSeekMode eSeekMode)
180 {
181 if(!this->GetOpened())
182 {
183 return 0;
184 }
185
186 #ifdef _WIN32
187 DWORD dwMode = FILE_BEGIN;
188 switch(eSeekMode)
189 {
190 /*case HL_SEEK_BEGINNING:
191 dwMode = FILE_BEGIN;
192 break;*/
193 case HL_SEEK_CURRENT:
194 dwMode = FILE_CURRENT;
195 break;
196 case HL_SEEK_END:
197 dwMode = FILE_END;
198 break;
199 }
200
201 LARGE_INTEGER liOffset;
202 liOffset.QuadPart = iOffset;
203
204 LARGE_INTEGER liPointer;
205 return SetFilePointerEx(this->hFile, liOffset, &liPointer, dwMode) ? static_cast<hlULongLong>(liPointer.QuadPart) : 0;
206 #else
207 hlInt iMode = SEEK_SET;
208 switch(eSeekMode)
209 {
210 /*case HL_SEEK_BEGINNING:
211 iMode = SEEK_SET;
212 break;*/
213 case HL_SEEK_CURRENT:
214 iMode = SEEK_CUR;
215 break;
216 case HL_SEEK_END:
217 iMode = SEEK_END;
218 break;
219 }
220
221 return (hlUInt)lseek(this->iFile, iOffset, iMode);
222 #endif
223 }
224
Read(hlChar & cChar)225 hlBool CFileStream::Read(hlChar &cChar)
226 {
227 if(!this->GetOpened())
228 {
229 return hlFalse;
230 }
231
232 if((this->uiMode & HL_MODE_READ) == 0)
233 {
234 LastError.SetErrorMessage("Stream not in read mode.");
235 return hlFalse;
236 }
237
238 #ifdef _WIN32
239 hlULong ulBytesRead = 0;
240
241 if(!ReadFile(this->hFile, &cChar, 1, &ulBytesRead, NULL))
242 {
243 LastError.SetSystemErrorMessage("ReadFile() failed.");
244 }
245
246 return ulBytesRead == 1;
247 #else
248 hlInt iBytesRead = read(this->iFile, &cChar, 1);
249
250 if(iBytesRead < 0)
251 {
252 LastError.SetSystemErrorMessage("read() failed.");
253 }
254
255 return iBytesRead == 1;
256 #endif
257 }
258
Read(hlVoid * lpData,hlUInt uiBytes)259 hlUInt CFileStream::Read(hlVoid *lpData, hlUInt uiBytes)
260 {
261 if(!this->GetOpened())
262 {
263 return 0;
264 }
265
266 if((this->uiMode & HL_MODE_READ) == 0)
267 {
268 LastError.SetErrorMessage("Stream not in read mode.");
269 return 0;
270 }
271
272 #ifdef _WIN32
273 hlULong ulBytesRead = 0;
274
275 if(!ReadFile(this->hFile, lpData, uiBytes, &ulBytesRead, NULL))
276 {
277 LastError.SetSystemErrorMessage("ReadFile() failed.");
278 }
279
280 return (hlUInt)ulBytesRead;
281 #else
282 hlInt iBytesRead = read(this->iFile, lpData, uiBytes);
283
284 if(iBytesRead < 0)
285 {
286 LastError.SetSystemErrorMessage("read() failed.");
287 }
288
289 return (hlUInt)iBytesRead;
290 #endif
291 }
292
Write(hlChar cChar)293 hlBool CFileStream::Write(hlChar cChar)
294 {
295 if(!this->GetOpened())
296 {
297 return hlFalse;
298 }
299
300 if((this->uiMode & HL_MODE_WRITE) == 0)
301 {
302 LastError.SetErrorMessage("Stream not in write mode.");
303 return hlFalse;
304 }
305
306 #ifdef _WIN32
307 hlULong ulBytesWritten = 0;
308
309 if(!WriteFile(this->hFile, &cChar, 1, &ulBytesWritten, NULL))
310 {
311 LastError.SetSystemErrorMessage("WriteFile() failed.");
312 }
313
314 return ulBytesWritten == 1;
315 #else
316 hlInt iBytesWritten = write(this->iFile, &cChar, 1);
317
318 if(iBytesWritten < 0)
319 {
320 LastError.SetSystemErrorMessage("write() failed.");
321 }
322
323 return iBytesWritten == 1;
324 #endif
325 }
326
Write(const hlVoid * lpData,hlUInt uiBytes)327 hlUInt CFileStream::Write(const hlVoid *lpData, hlUInt uiBytes)
328 {
329 if(!this->GetOpened())
330 {
331 return 0;
332 }
333
334 if((this->uiMode & HL_MODE_WRITE) == 0)
335 {
336 LastError.SetErrorMessage("Stream not in write mode.");
337 return 0;
338 }
339
340 #ifdef _WIN32
341 hlULong ulBytesWritten = 0;
342
343 if(!WriteFile(this->hFile, lpData, uiBytes, &ulBytesWritten, NULL))
344 {
345 LastError.SetSystemErrorMessage("WriteFile() failed.");
346 }
347
348 return (hlUInt)ulBytesWritten;
349 #else
350 hlInt iBytesWritten = write(this->iFile, lpData, uiBytes);
351
352 if(iBytesWritten < 0)
353 {
354 LastError.SetSystemErrorMessage("write() failed.");
355 }
356
357 return (hlUInt)iBytesWritten;
358 #endif
359 }
360