rev |
line source |
nuclear@0
|
1 /**************************************************************************
|
nuclear@0
|
2
|
nuclear@0
|
3 Filename : OVR_File.cpp
|
nuclear@0
|
4 Content : File wrapper class implementation (Win32)
|
nuclear@0
|
5
|
nuclear@0
|
6 Created : April 5, 1999
|
nuclear@0
|
7 Authors : Michael Antonov
|
nuclear@0
|
8
|
nuclear@0
|
9 Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
|
nuclear@0
|
10
|
nuclear@0
|
11 Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
|
nuclear@0
|
12 you may not use the Oculus VR Rift SDK except in compliance with the License,
|
nuclear@0
|
13 which is provided at the time of installation or download, or which
|
nuclear@0
|
14 otherwise accompanies this software in either electronic or hard copy form.
|
nuclear@0
|
15
|
nuclear@0
|
16 You may obtain a copy of the License at
|
nuclear@0
|
17
|
nuclear@0
|
18 http://www.oculusvr.com/licenses/LICENSE-3.2
|
nuclear@0
|
19
|
nuclear@0
|
20 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
|
nuclear@0
|
21 distributed under the License is distributed on an "AS IS" BASIS,
|
nuclear@0
|
22 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
nuclear@0
|
23 See the License for the specific language governing permissions and
|
nuclear@0
|
24 limitations under the License.
|
nuclear@0
|
25
|
nuclear@0
|
26 **************************************************************************/
|
nuclear@0
|
27
|
nuclear@0
|
28 #define GFILE_CXX
|
nuclear@0
|
29
|
nuclear@0
|
30 // Standard C library (Captain Obvious guarantees!)
|
nuclear@0
|
31 #include <stdio.h>
|
nuclear@0
|
32
|
nuclear@0
|
33 #include "OVR_File.h"
|
nuclear@0
|
34
|
nuclear@0
|
35 namespace OVR {
|
nuclear@0
|
36
|
nuclear@0
|
37 // Buffered file adds buffering to an existing file
|
nuclear@0
|
38 // FILEBUFFER_SIZE defines the size of internal buffer, while
|
nuclear@0
|
39 // FILEBUFFER_TOLERANCE controls the amount of data we'll effectively try to buffer
|
nuclear@0
|
40 #define FILEBUFFER_SIZE (8192-8)
|
nuclear@0
|
41 #define FILEBUFFER_TOLERANCE 4096
|
nuclear@0
|
42
|
nuclear@0
|
43 // ** Constructor/Destructor
|
nuclear@0
|
44
|
nuclear@0
|
45 // Hidden constructor
|
nuclear@0
|
46 // Not supposed to be used
|
nuclear@0
|
47 BufferedFile::BufferedFile() : DelegatedFile(0)
|
nuclear@0
|
48 {
|
nuclear@0
|
49 pBuffer = (uint8_t*)OVR_ALLOC(FILEBUFFER_SIZE);
|
nuclear@0
|
50 BufferMode = NoBuffer;
|
nuclear@0
|
51 FilePos = 0;
|
nuclear@0
|
52 Pos = 0;
|
nuclear@0
|
53 DataSize = 0;
|
nuclear@0
|
54 }
|
nuclear@0
|
55
|
nuclear@0
|
56 // Takes another file as source
|
nuclear@0
|
57 BufferedFile::BufferedFile(File *pfile) : DelegatedFile(pfile)
|
nuclear@0
|
58 {
|
nuclear@0
|
59 pBuffer = (uint8_t*)OVR_ALLOC(FILEBUFFER_SIZE);
|
nuclear@0
|
60 BufferMode = NoBuffer;
|
nuclear@0
|
61 FilePos = pfile->LTell();
|
nuclear@0
|
62 Pos = 0;
|
nuclear@0
|
63 DataSize = 0;
|
nuclear@0
|
64 }
|
nuclear@0
|
65
|
nuclear@0
|
66
|
nuclear@0
|
67 // Destructor
|
nuclear@0
|
68 BufferedFile::~BufferedFile()
|
nuclear@0
|
69 {
|
nuclear@0
|
70 // Flush in case there's data
|
nuclear@0
|
71 if (pFile)
|
nuclear@0
|
72 FlushBuffer();
|
nuclear@0
|
73 // Get rid of buffer
|
nuclear@0
|
74 if (pBuffer)
|
nuclear@0
|
75 OVR_FREE(pBuffer);
|
nuclear@0
|
76 }
|
nuclear@0
|
77
|
nuclear@0
|
78 /*
|
nuclear@0
|
79 bool BufferedFile::VCopy(const Object &source)
|
nuclear@0
|
80 {
|
nuclear@0
|
81 if (!DelegatedFile::VCopy(source))
|
nuclear@0
|
82 return 0;
|
nuclear@0
|
83
|
nuclear@0
|
84 // Data members
|
nuclear@0
|
85 BufferedFile *psource = (BufferedFile*)&source;
|
nuclear@0
|
86
|
nuclear@0
|
87 // Buffer & the mode it's in
|
nuclear@0
|
88 pBuffer = psource->pBuffer;
|
nuclear@0
|
89 BufferMode = psource->BufferMode;
|
nuclear@0
|
90 Pos = psource->Pos;
|
nuclear@0
|
91 DataSize = psource->DataSize;
|
nuclear@0
|
92 return 1;
|
nuclear@0
|
93 }
|
nuclear@0
|
94 */
|
nuclear@0
|
95
|
nuclear@0
|
96 // Initializes buffering to a certain mode
|
nuclear@0
|
97 bool BufferedFile::SetBufferMode(BufferModeType mode)
|
nuclear@0
|
98 {
|
nuclear@0
|
99 if (!pBuffer)
|
nuclear@0
|
100 return false;
|
nuclear@0
|
101 if (mode == BufferMode)
|
nuclear@0
|
102 return true;
|
nuclear@0
|
103
|
nuclear@0
|
104 FlushBuffer();
|
nuclear@0
|
105
|
nuclear@0
|
106 // Can't set write mode if we can't write
|
nuclear@0
|
107 if ((mode==WriteBuffer) && (!pFile || !pFile->IsWritable()) )
|
nuclear@0
|
108 return 0;
|
nuclear@0
|
109
|
nuclear@0
|
110 // And SetMode
|
nuclear@0
|
111 BufferMode = mode;
|
nuclear@0
|
112 Pos = 0;
|
nuclear@0
|
113 DataSize = 0;
|
nuclear@0
|
114 return 1;
|
nuclear@0
|
115 }
|
nuclear@0
|
116
|
nuclear@0
|
117 // Flushes buffer
|
nuclear@0
|
118 void BufferedFile::FlushBuffer()
|
nuclear@0
|
119 {
|
nuclear@0
|
120 switch(BufferMode)
|
nuclear@0
|
121 {
|
nuclear@0
|
122 case WriteBuffer:
|
nuclear@0
|
123 // Write data in buffer
|
nuclear@0
|
124 FilePos += pFile->Write(pBuffer,Pos);
|
nuclear@0
|
125 Pos = 0;
|
nuclear@0
|
126 break;
|
nuclear@0
|
127
|
nuclear@0
|
128 case ReadBuffer:
|
nuclear@0
|
129 // Seek back & reset buffer data
|
nuclear@0
|
130 if ((DataSize-Pos)>0)
|
nuclear@0
|
131 FilePos = pFile->LSeek(-(int)(DataSize-Pos), Seek_Cur);
|
nuclear@0
|
132 DataSize = 0;
|
nuclear@0
|
133 Pos = 0;
|
nuclear@0
|
134 break;
|
nuclear@0
|
135 default:
|
nuclear@0
|
136 // not handled!
|
nuclear@0
|
137 break;
|
nuclear@0
|
138 }
|
nuclear@0
|
139 }
|
nuclear@0
|
140
|
nuclear@0
|
141 // Reloads data for ReadBuffer
|
nuclear@0
|
142 void BufferedFile::LoadBuffer()
|
nuclear@0
|
143 {
|
nuclear@0
|
144 if (BufferMode == ReadBuffer)
|
nuclear@0
|
145 {
|
nuclear@0
|
146 // We should only reload once all of pre-loaded buffer is consumed.
|
nuclear@0
|
147 OVR_ASSERT(Pos == DataSize);
|
nuclear@0
|
148
|
nuclear@0
|
149 // WARNING: Right now LoadBuffer() assumes the buffer's empty
|
nuclear@0
|
150 int sz = pFile->Read(pBuffer,FILEBUFFER_SIZE);
|
nuclear@0
|
151 DataSize = sz<0 ? 0 : (unsigned)sz;
|
nuclear@0
|
152 Pos = 0;
|
nuclear@0
|
153 FilePos += DataSize;
|
nuclear@0
|
154 }
|
nuclear@0
|
155 }
|
nuclear@0
|
156
|
nuclear@0
|
157
|
nuclear@0
|
158 // ** Overridden functions
|
nuclear@0
|
159
|
nuclear@0
|
160 // We override all the functions that can possibly
|
nuclear@0
|
161 // require buffer mode switch, flush, or extra calculations
|
nuclear@0
|
162
|
nuclear@0
|
163 // Tell() requires buffer adjustment
|
nuclear@0
|
164 int BufferedFile::Tell()
|
nuclear@0
|
165 {
|
nuclear@0
|
166 if (BufferMode == ReadBuffer)
|
nuclear@0
|
167 return int (FilePos - DataSize + Pos);
|
nuclear@0
|
168
|
nuclear@0
|
169 int pos = pFile->Tell();
|
nuclear@0
|
170 // Adjust position based on buffer mode & data
|
nuclear@0
|
171 if (pos!=-1)
|
nuclear@0
|
172 {
|
nuclear@0
|
173 OVR_ASSERT(BufferMode != ReadBuffer);
|
nuclear@0
|
174 if (BufferMode == WriteBuffer)
|
nuclear@0
|
175 pos += Pos;
|
nuclear@0
|
176 }
|
nuclear@0
|
177 return pos;
|
nuclear@0
|
178 }
|
nuclear@0
|
179
|
nuclear@0
|
180 int64_t BufferedFile::LTell()
|
nuclear@0
|
181 {
|
nuclear@0
|
182 if (BufferMode == ReadBuffer)
|
nuclear@0
|
183 return FilePos - DataSize + Pos;
|
nuclear@0
|
184
|
nuclear@0
|
185 int64_t pos = pFile->LTell();
|
nuclear@0
|
186 if (pos!=-1)
|
nuclear@0
|
187 {
|
nuclear@0
|
188 OVR_ASSERT(BufferMode != ReadBuffer);
|
nuclear@0
|
189 if (BufferMode == WriteBuffer)
|
nuclear@0
|
190 pos += Pos;
|
nuclear@0
|
191 }
|
nuclear@0
|
192 return pos;
|
nuclear@0
|
193 }
|
nuclear@0
|
194
|
nuclear@0
|
195 int BufferedFile::GetLength()
|
nuclear@0
|
196 {
|
nuclear@0
|
197 int len = pFile->GetLength();
|
nuclear@0
|
198 // If writing through buffer, file length may actually be bigger
|
nuclear@0
|
199 if ((len!=-1) && (BufferMode==WriteBuffer))
|
nuclear@0
|
200 {
|
nuclear@0
|
201 int currPos = pFile->Tell() + Pos;
|
nuclear@0
|
202 if (currPos>len)
|
nuclear@0
|
203 len = currPos;
|
nuclear@0
|
204 }
|
nuclear@0
|
205 return len;
|
nuclear@0
|
206 }
|
nuclear@0
|
207 int64_t BufferedFile::LGetLength()
|
nuclear@0
|
208 {
|
nuclear@0
|
209 int64_t len = pFile->LGetLength();
|
nuclear@0
|
210 // If writing through buffer, file length may actually be bigger
|
nuclear@0
|
211 if ((len!=-1) && (BufferMode==WriteBuffer))
|
nuclear@0
|
212 {
|
nuclear@0
|
213 int64_t currPos = pFile->LTell() + Pos;
|
nuclear@0
|
214 if (currPos>len)
|
nuclear@0
|
215 len = currPos;
|
nuclear@0
|
216 }
|
nuclear@0
|
217 return len;
|
nuclear@0
|
218 }
|
nuclear@0
|
219
|
nuclear@0
|
220 /*
|
nuclear@0
|
221 bool BufferedFile::Stat(FileStats *pfs)
|
nuclear@0
|
222 {
|
nuclear@0
|
223 // Have to fix up length is stat
|
nuclear@0
|
224 if (pFile->Stat(pfs))
|
nuclear@0
|
225 {
|
nuclear@0
|
226 if (BufferMode==WriteBuffer)
|
nuclear@0
|
227 {
|
nuclear@0
|
228 int64_t currPos = pFile->LTell() + Pos;
|
nuclear@0
|
229 if (currPos > pfs->Size)
|
nuclear@0
|
230 {
|
nuclear@0
|
231 pfs->Size = currPos;
|
nuclear@0
|
232 // ??
|
nuclear@0
|
233 pfs->Blocks = (pfs->Size+511) >> 9;
|
nuclear@0
|
234 }
|
nuclear@0
|
235 }
|
nuclear@0
|
236 return 1;
|
nuclear@0
|
237 }
|
nuclear@0
|
238 return 0;
|
nuclear@0
|
239 }
|
nuclear@0
|
240 */
|
nuclear@0
|
241
|
nuclear@0
|
242 int BufferedFile::Write(const uint8_t *psourceBuffer, int numBytes)
|
nuclear@0
|
243 {
|
nuclear@0
|
244 if ( (BufferMode==WriteBuffer) || SetBufferMode(WriteBuffer))
|
nuclear@0
|
245 {
|
nuclear@0
|
246 // If not data space in buffer, flush
|
nuclear@0
|
247 if ((FILEBUFFER_SIZE-(int)Pos)<numBytes)
|
nuclear@0
|
248 {
|
nuclear@0
|
249 FlushBuffer();
|
nuclear@0
|
250 // If bigger then tolerance, just write directly
|
nuclear@0
|
251 if (numBytes>FILEBUFFER_TOLERANCE)
|
nuclear@0
|
252 {
|
nuclear@0
|
253 int sz = pFile->Write(psourceBuffer,numBytes);
|
nuclear@0
|
254 if (sz > 0)
|
nuclear@0
|
255 FilePos += sz;
|
nuclear@0
|
256 return sz;
|
nuclear@0
|
257 }
|
nuclear@0
|
258 }
|
nuclear@0
|
259
|
nuclear@0
|
260 // Enough space in buffer.. so copy to it
|
nuclear@0
|
261 memcpy(pBuffer+Pos, psourceBuffer, numBytes);
|
nuclear@0
|
262 Pos += numBytes;
|
nuclear@0
|
263 return numBytes;
|
nuclear@0
|
264 }
|
nuclear@0
|
265 int sz = pFile->Write(psourceBuffer,numBytes);
|
nuclear@0
|
266 if (sz > 0)
|
nuclear@0
|
267 FilePos += sz;
|
nuclear@0
|
268 return sz;
|
nuclear@0
|
269 }
|
nuclear@0
|
270
|
nuclear@0
|
271 int BufferedFile::Read(uint8_t *pdestBuffer, int numBytes)
|
nuclear@0
|
272 {
|
nuclear@0
|
273 if ( (BufferMode==ReadBuffer) || SetBufferMode(ReadBuffer))
|
nuclear@0
|
274 {
|
nuclear@0
|
275 // Data in buffer... copy it
|
nuclear@0
|
276 if ((int)(DataSize-Pos) >= numBytes)
|
nuclear@0
|
277 {
|
nuclear@0
|
278 memcpy(pdestBuffer, pBuffer+Pos, numBytes);
|
nuclear@0
|
279 Pos += numBytes;
|
nuclear@0
|
280 return numBytes;
|
nuclear@0
|
281 }
|
nuclear@0
|
282
|
nuclear@0
|
283 // Not enough data in buffer, copy buffer
|
nuclear@0
|
284 int readBytes = DataSize-Pos;
|
nuclear@0
|
285 memcpy(pdestBuffer, pBuffer+Pos, readBytes);
|
nuclear@0
|
286 numBytes -= readBytes;
|
nuclear@0
|
287 pdestBuffer += readBytes;
|
nuclear@0
|
288 Pos = DataSize;
|
nuclear@0
|
289
|
nuclear@0
|
290 // Don't reload buffer if more then tolerance
|
nuclear@0
|
291 // (No major advantage, and we don't want to write a loop)
|
nuclear@0
|
292 if (numBytes>FILEBUFFER_TOLERANCE)
|
nuclear@0
|
293 {
|
nuclear@0
|
294 numBytes = pFile->Read(pdestBuffer,numBytes);
|
nuclear@0
|
295 if (numBytes > 0)
|
nuclear@0
|
296 {
|
nuclear@0
|
297 FilePos += numBytes;
|
nuclear@0
|
298 Pos = DataSize = 0;
|
nuclear@0
|
299 }
|
nuclear@0
|
300 return readBytes + ((numBytes==-1) ? 0 : numBytes);
|
nuclear@0
|
301 }
|
nuclear@0
|
302
|
nuclear@0
|
303 // Reload the buffer
|
nuclear@0
|
304 // WARNING: Right now LoadBuffer() assumes the buffer's empty
|
nuclear@0
|
305 LoadBuffer();
|
nuclear@0
|
306 if ((int)(DataSize-Pos) < numBytes)
|
nuclear@0
|
307 numBytes = (int)DataSize-Pos;
|
nuclear@0
|
308
|
nuclear@0
|
309 memcpy(pdestBuffer, pBuffer+Pos, numBytes);
|
nuclear@0
|
310 Pos += numBytes;
|
nuclear@0
|
311 return numBytes + readBytes;
|
nuclear@0
|
312
|
nuclear@0
|
313 /*
|
nuclear@0
|
314 // Alternative Read implementation. The one above is probably better
|
nuclear@0
|
315 // due to FILEBUFFER_TOLERANCE.
|
nuclear@0
|
316 int total = 0;
|
nuclear@0
|
317
|
nuclear@0
|
318 do {
|
nuclear@0
|
319 int bufferBytes = (int)(DataSize-Pos);
|
nuclear@0
|
320 int copyBytes = (bufferBytes > numBytes) ? numBytes : bufferBytes;
|
nuclear@0
|
321
|
nuclear@0
|
322 memcpy(pdestBuffer, pBuffer+Pos, copyBytes);
|
nuclear@0
|
323 numBytes -= copyBytes;
|
nuclear@0
|
324 pdestBuffer += copyBytes;
|
nuclear@0
|
325 Pos += copyBytes;
|
nuclear@0
|
326 total += copyBytes;
|
nuclear@0
|
327
|
nuclear@0
|
328 if (numBytes == 0)
|
nuclear@0
|
329 break;
|
nuclear@0
|
330 LoadBuffer();
|
nuclear@0
|
331
|
nuclear@0
|
332 } while (DataSize > 0);
|
nuclear@0
|
333
|
nuclear@0
|
334 return total;
|
nuclear@0
|
335 */
|
nuclear@0
|
336 }
|
nuclear@0
|
337 int sz = pFile->Read(pdestBuffer,numBytes);
|
nuclear@0
|
338 if (sz > 0)
|
nuclear@0
|
339 FilePos += sz;
|
nuclear@0
|
340 return sz;
|
nuclear@0
|
341 }
|
nuclear@0
|
342
|
nuclear@0
|
343
|
nuclear@0
|
344 int BufferedFile::SkipBytes(int numBytes)
|
nuclear@0
|
345 {
|
nuclear@0
|
346 int skippedBytes = 0;
|
nuclear@0
|
347
|
nuclear@0
|
348 // Special case for skipping a little data in read buffer
|
nuclear@0
|
349 if (BufferMode==ReadBuffer)
|
nuclear@0
|
350 {
|
nuclear@0
|
351 skippedBytes = (((int)DataSize-(int)Pos) >= numBytes) ? numBytes : (DataSize-Pos);
|
nuclear@0
|
352 Pos += skippedBytes;
|
nuclear@0
|
353 numBytes -= skippedBytes;
|
nuclear@0
|
354 }
|
nuclear@0
|
355
|
nuclear@0
|
356 if (numBytes)
|
nuclear@0
|
357 {
|
nuclear@0
|
358 numBytes = pFile->SkipBytes(numBytes);
|
nuclear@0
|
359 // Make sure we return the actual number skipped, or error
|
nuclear@0
|
360 if (numBytes!=-1)
|
nuclear@0
|
361 {
|
nuclear@0
|
362 skippedBytes += numBytes;
|
nuclear@0
|
363 FilePos += numBytes;
|
nuclear@0
|
364 Pos = DataSize = 0;
|
nuclear@0
|
365 }
|
nuclear@0
|
366 else if (skippedBytes <= 0)
|
nuclear@0
|
367 skippedBytes = -1;
|
nuclear@0
|
368 }
|
nuclear@0
|
369 return skippedBytes;
|
nuclear@0
|
370 }
|
nuclear@0
|
371
|
nuclear@0
|
372 int BufferedFile::BytesAvailable()
|
nuclear@0
|
373 {
|
nuclear@0
|
374 int available = pFile->BytesAvailable();
|
nuclear@0
|
375 // Adjust available size based on buffers
|
nuclear@0
|
376 switch(BufferMode)
|
nuclear@0
|
377 {
|
nuclear@0
|
378 case ReadBuffer:
|
nuclear@0
|
379 available += DataSize-Pos;
|
nuclear@0
|
380 break;
|
nuclear@0
|
381 case WriteBuffer:
|
nuclear@0
|
382 available -= Pos;
|
nuclear@0
|
383 if (available<0)
|
nuclear@0
|
384 available= 0;
|
nuclear@0
|
385 break;
|
nuclear@0
|
386 default:
|
nuclear@0
|
387 break;
|
nuclear@0
|
388 }
|
nuclear@0
|
389 return available;
|
nuclear@0
|
390 }
|
nuclear@0
|
391
|
nuclear@0
|
392 bool BufferedFile::Flush()
|
nuclear@0
|
393 {
|
nuclear@0
|
394 FlushBuffer();
|
nuclear@0
|
395 return pFile->Flush();
|
nuclear@0
|
396 }
|
nuclear@0
|
397
|
nuclear@0
|
398 // Seeking could be optimized better..
|
nuclear@0
|
399 int BufferedFile::Seek(int offset, int origin)
|
nuclear@0
|
400 {
|
nuclear@0
|
401 if (BufferMode == ReadBuffer)
|
nuclear@0
|
402 {
|
nuclear@0
|
403 if (origin == Seek_Cur)
|
nuclear@0
|
404 {
|
nuclear@0
|
405 // Seek can fall either before or after Pos in the buffer,
|
nuclear@0
|
406 // but it must be within bounds.
|
nuclear@0
|
407 if (((unsigned(offset) + Pos)) <= DataSize)
|
nuclear@0
|
408 {
|
nuclear@0
|
409 Pos += offset;
|
nuclear@0
|
410 return int (FilePos - DataSize + Pos);
|
nuclear@0
|
411 }
|
nuclear@0
|
412
|
nuclear@0
|
413 // Lightweight buffer "Flush". We do this to avoid an extra seek
|
nuclear@0
|
414 // back operation which would take place if we called FlushBuffer directly.
|
nuclear@0
|
415 origin = Seek_Set;
|
nuclear@0
|
416 OVR_ASSERT(((FilePos - DataSize + Pos) + (uint64_t)offset) < ~(uint64_t)0);
|
nuclear@0
|
417 offset = (int)(FilePos - DataSize + Pos) + offset;
|
nuclear@0
|
418 Pos = DataSize = 0;
|
nuclear@0
|
419 }
|
nuclear@0
|
420 else if (origin == Seek_Set)
|
nuclear@0
|
421 {
|
nuclear@0
|
422 if (((unsigned)offset - (FilePos-DataSize)) <= DataSize)
|
nuclear@0
|
423 {
|
nuclear@0
|
424 OVR_ASSERT((FilePos-DataSize) < ~(uint64_t)0);
|
nuclear@0
|
425 Pos = (unsigned)offset - (unsigned)(FilePos-DataSize);
|
nuclear@0
|
426 return offset;
|
nuclear@0
|
427 }
|
nuclear@0
|
428 Pos = DataSize = 0;
|
nuclear@0
|
429 }
|
nuclear@0
|
430 else
|
nuclear@0
|
431 {
|
nuclear@0
|
432 FlushBuffer();
|
nuclear@0
|
433 }
|
nuclear@0
|
434 }
|
nuclear@0
|
435 else
|
nuclear@0
|
436 {
|
nuclear@0
|
437 FlushBuffer();
|
nuclear@0
|
438 }
|
nuclear@0
|
439
|
nuclear@0
|
440 /*
|
nuclear@0
|
441 // Old Seek Logic
|
nuclear@0
|
442 if (origin == Seek_Cur && offset + Pos < DataSize)
|
nuclear@0
|
443 {
|
nuclear@0
|
444 //OVR_ASSERT((FilePos - DataSize) >= (FilePos - DataSize + Pos + offset));
|
nuclear@0
|
445 Pos += offset;
|
nuclear@0
|
446 OVR_ASSERT(int (Pos) >= 0);
|
nuclear@0
|
447 return int (FilePos - DataSize + Pos);
|
nuclear@0
|
448 }
|
nuclear@0
|
449 else if (origin == Seek_Set && unsigned(offset) >= FilePos - DataSize && unsigned(offset) < FilePos)
|
nuclear@0
|
450 {
|
nuclear@0
|
451 Pos = unsigned(offset - FilePos + DataSize);
|
nuclear@0
|
452 OVR_ASSERT(int (Pos) >= 0);
|
nuclear@0
|
453 return int (FilePos - DataSize + Pos);
|
nuclear@0
|
454 }
|
nuclear@0
|
455
|
nuclear@0
|
456 FlushBuffer();
|
nuclear@0
|
457 */
|
nuclear@0
|
458
|
nuclear@0
|
459
|
nuclear@0
|
460 FilePos = pFile->Seek(offset,origin);
|
nuclear@0
|
461 return int (FilePos);
|
nuclear@0
|
462 }
|
nuclear@0
|
463
|
nuclear@0
|
464 int64_t BufferedFile::LSeek(int64_t offset, int origin)
|
nuclear@0
|
465 {
|
nuclear@0
|
466 if (BufferMode == ReadBuffer)
|
nuclear@0
|
467 {
|
nuclear@0
|
468 if (origin == Seek_Cur)
|
nuclear@0
|
469 {
|
nuclear@0
|
470 // Seek can fall either before or after Pos in the buffer,
|
nuclear@0
|
471 // but it must be within bounds.
|
nuclear@0
|
472 if (((unsigned(offset) + Pos)) <= DataSize)
|
nuclear@0
|
473 {
|
nuclear@0
|
474 Pos += (unsigned)offset;
|
nuclear@0
|
475 return int64_t(FilePos - DataSize + Pos);
|
nuclear@0
|
476 }
|
nuclear@0
|
477
|
nuclear@0
|
478 // Lightweight buffer "Flush". We do this to avoid an extra seek
|
nuclear@0
|
479 // back operation which would take place if we called FlushBuffer directly.
|
nuclear@0
|
480 origin = Seek_Set;
|
nuclear@0
|
481 offset = (int64_t)(FilePos - DataSize + Pos) + offset;
|
nuclear@0
|
482 Pos = DataSize = 0;
|
nuclear@0
|
483 }
|
nuclear@0
|
484 else if (origin == Seek_Set)
|
nuclear@0
|
485 {
|
nuclear@0
|
486 if (((uint64_t)offset - (FilePos-DataSize)) <= DataSize)
|
nuclear@0
|
487 {
|
nuclear@0
|
488 Pos = (unsigned)((uint64_t)offset - (FilePos-DataSize));
|
nuclear@0
|
489 return offset;
|
nuclear@0
|
490 }
|
nuclear@0
|
491 Pos = DataSize = 0;
|
nuclear@0
|
492 }
|
nuclear@0
|
493 else
|
nuclear@0
|
494 {
|
nuclear@0
|
495 FlushBuffer();
|
nuclear@0
|
496 }
|
nuclear@0
|
497 }
|
nuclear@0
|
498 else
|
nuclear@0
|
499 {
|
nuclear@0
|
500 FlushBuffer();
|
nuclear@0
|
501 }
|
nuclear@0
|
502
|
nuclear@0
|
503 /*
|
nuclear@0
|
504 OVR_ASSERT(BufferMode != NoBuffer);
|
nuclear@0
|
505
|
nuclear@0
|
506 if (origin == Seek_Cur && offset + Pos < DataSize)
|
nuclear@0
|
507 {
|
nuclear@0
|
508 Pos += int (offset);
|
nuclear@0
|
509 return FilePos - DataSize + Pos;
|
nuclear@0
|
510 }
|
nuclear@0
|
511 else if (origin == Seek_Set && offset >= int64_t(FilePos - DataSize) && offset < int64_t(FilePos))
|
nuclear@0
|
512 {
|
nuclear@0
|
513 Pos = unsigned(offset - FilePos + DataSize);
|
nuclear@0
|
514 return FilePos - DataSize + Pos;
|
nuclear@0
|
515 }
|
nuclear@0
|
516
|
nuclear@0
|
517 FlushBuffer();
|
nuclear@0
|
518 */
|
nuclear@0
|
519
|
nuclear@0
|
520 FilePos = pFile->LSeek(offset,origin);
|
nuclear@0
|
521 return FilePos;
|
nuclear@0
|
522 }
|
nuclear@0
|
523
|
nuclear@0
|
524 int BufferedFile::CopyFromStream(File *pstream, int byteSize)
|
nuclear@0
|
525 {
|
nuclear@0
|
526 // We can't rely on overridden Write()
|
nuclear@0
|
527 // because delegation doesn't override virtual pointers
|
nuclear@0
|
528 // So, just re-implement
|
nuclear@0
|
529 uint8_t* buff = new uint8_t[0x4000];
|
nuclear@0
|
530 int count = 0;
|
nuclear@0
|
531 int szRequest, szRead, szWritten;
|
nuclear@0
|
532
|
nuclear@0
|
533 while(byteSize)
|
nuclear@0
|
534 {
|
nuclear@0
|
535 szRequest = (byteSize > int(sizeof(buff))) ? int(sizeof(buff)) : byteSize;
|
nuclear@0
|
536
|
nuclear@0
|
537 szRead = pstream->Read(buff,szRequest);
|
nuclear@0
|
538 szWritten = 0;
|
nuclear@0
|
539 if (szRead > 0)
|
nuclear@0
|
540 szWritten = Write(buff,szRead);
|
nuclear@0
|
541
|
nuclear@0
|
542 count +=szWritten;
|
nuclear@0
|
543 byteSize-=szWritten;
|
nuclear@0
|
544 if (szWritten < szRequest)
|
nuclear@0
|
545 break;
|
nuclear@0
|
546 }
|
nuclear@0
|
547
|
nuclear@0
|
548 delete[] buff;
|
nuclear@0
|
549
|
nuclear@0
|
550 return count;
|
nuclear@0
|
551 }
|
nuclear@0
|
552
|
nuclear@0
|
553 // Closing files
|
nuclear@0
|
554 bool BufferedFile::Close()
|
nuclear@0
|
555 {
|
nuclear@0
|
556 switch(BufferMode)
|
nuclear@0
|
557 {
|
nuclear@0
|
558 case WriteBuffer:
|
nuclear@0
|
559 FlushBuffer();
|
nuclear@0
|
560 break;
|
nuclear@0
|
561 case ReadBuffer:
|
nuclear@0
|
562 // No need to seek back on close
|
nuclear@0
|
563 BufferMode = NoBuffer;
|
nuclear@0
|
564 break;
|
nuclear@0
|
565 default:
|
nuclear@0
|
566 break;
|
nuclear@0
|
567 }
|
nuclear@0
|
568 return pFile->Close();
|
nuclear@0
|
569 }
|
nuclear@0
|
570
|
nuclear@0
|
571
|
nuclear@0
|
572 // ***** Global path helpers
|
nuclear@0
|
573
|
nuclear@0
|
574 // Find trailing short filename in a path.
|
nuclear@0
|
575 const char* OVR_CDECL GetShortFilename(const char* purl)
|
nuclear@0
|
576 {
|
nuclear@0
|
577 size_t len = OVR_strlen(purl);
|
nuclear@0
|
578 for (size_t i=len; i>0; i--)
|
nuclear@0
|
579 if (purl[i]=='\\' || purl[i]=='/')
|
nuclear@0
|
580 return purl+i+1;
|
nuclear@0
|
581 return purl;
|
nuclear@0
|
582 }
|
nuclear@0
|
583
|
nuclear@0
|
584 } // OVR
|
nuclear@0
|
585
|