oculus1
diff libovr/Src/Kernel/OVR_File.cpp @ 1:e2f9e4603129
added LibOVR and started a simple vr wrapper.
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 14 Sep 2013 16:14:59 +0300 |
parents | |
children | b069a5c27388 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libovr/Src/Kernel/OVR_File.cpp Sat Sep 14 16:14:59 2013 +0300 1.3 @@ -0,0 +1,1 @@ 1.4 +/************************************************************************** 1.5 1.6 Filename : OVR_File.cpp 1.7 Content : File wrapper class implementation (Win32) 1.8 1.9 Created : April 5, 1999 1.10 Authors : Michael Antonov 1.11 1.12 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. 1.13 1.14 Use of this software is subject to the terms of the Oculus license 1.15 agreement provided at the time of installation or download, or which 1.16 otherwise accompanies this software in either electronic or hard copy form. 1.17 1.18 **************************************************************************/ 1.19 1.20 #define GFILE_CXX 1.21 1.22 // Standard C library (Captain Obvious guarantees!) 1.23 #include <stdio.h> 1.24 1.25 #include "OVR_File.h" 1.26 1.27 namespace OVR { 1.28 1.29 // Buffered file adds buffering to an existing file 1.30 // FILEBUFFER_SIZE defines the size of internal buffer, while 1.31 // FILEBUFFER_TOLERANCE controls the amount of data we'll effectively try to buffer 1.32 #define FILEBUFFER_SIZE (8192-8) 1.33 #define FILEBUFFER_TOLERANCE 4096 1.34 1.35 // ** Constructor/Destructor 1.36 1.37 // Hidden constructor 1.38 // Not supposed to be used 1.39 BufferedFile::BufferedFile() : DelegatedFile(0) 1.40 { 1.41 pBuffer = (UByte*)OVR_ALLOC(FILEBUFFER_SIZE); 1.42 BufferMode = NoBuffer; 1.43 FilePos = 0; 1.44 Pos = 0; 1.45 DataSize = 0; 1.46 } 1.47 1.48 // Takes another file as source 1.49 BufferedFile::BufferedFile(File *pfile) : DelegatedFile(pfile) 1.50 { 1.51 pBuffer = (UByte*)OVR_ALLOC(FILEBUFFER_SIZE); 1.52 BufferMode = NoBuffer; 1.53 FilePos = pfile->LTell(); 1.54 Pos = 0; 1.55 DataSize = 0; 1.56 } 1.57 1.58 1.59 // Destructor 1.60 BufferedFile::~BufferedFile() 1.61 { 1.62 // Flush in case there's data 1.63 if (pFile) 1.64 FlushBuffer(); 1.65 // Get rid of buffer 1.66 if (pBuffer) 1.67 OVR_FREE(pBuffer); 1.68 } 1.69 1.70 /* 1.71 bool BufferedFile::VCopy(const Object &source) 1.72 { 1.73 if (!DelegatedFile::VCopy(source)) 1.74 return 0; 1.75 1.76 // Data members 1.77 BufferedFile *psource = (BufferedFile*)&source; 1.78 1.79 // Buffer & the mode it's in 1.80 pBuffer = psource->pBuffer; 1.81 BufferMode = psource->BufferMode; 1.82 Pos = psource->Pos; 1.83 DataSize = psource->DataSize; 1.84 return 1; 1.85 } 1.86 */ 1.87 1.88 // Initializes buffering to a certain mode 1.89 bool BufferedFile::SetBufferMode(BufferModeType mode) 1.90 { 1.91 if (!pBuffer) 1.92 return false; 1.93 if (mode == BufferMode) 1.94 return true; 1.95 1.96 FlushBuffer(); 1.97 1.98 // Can't set write mode if we can't write 1.99 if ((mode==WriteBuffer) && (!pFile || !pFile->IsWritable()) ) 1.100 return 0; 1.101 1.102 // And SetMode 1.103 BufferMode = mode; 1.104 Pos = 0; 1.105 DataSize = 0; 1.106 return 1; 1.107 } 1.108 1.109 // Flushes buffer 1.110 void BufferedFile::FlushBuffer() 1.111 { 1.112 switch(BufferMode) 1.113 { 1.114 case WriteBuffer: 1.115 // Write data in buffer 1.116 FilePos += pFile->Write(pBuffer,Pos); 1.117 Pos = 0; 1.118 break; 1.119 1.120 case ReadBuffer: 1.121 // Seek back & reset buffer data 1.122 if ((DataSize-Pos)>0) 1.123 FilePos = pFile->LSeek(-(int)(DataSize-Pos), Seek_Cur); 1.124 DataSize = 0; 1.125 Pos = 0; 1.126 break; 1.127 default: 1.128 // not handled! 1.129 break; 1.130 } 1.131 } 1.132 1.133 // Reloads data for ReadBuffer 1.134 void BufferedFile::LoadBuffer() 1.135 { 1.136 if (BufferMode == ReadBuffer) 1.137 { 1.138 // We should only reload once all of pre-loaded buffer is consumed. 1.139 OVR_ASSERT(Pos == DataSize); 1.140 1.141 // WARNING: Right now LoadBuffer() assumes the buffer's empty 1.142 int sz = pFile->Read(pBuffer,FILEBUFFER_SIZE); 1.143 DataSize = sz<0 ? 0 : (unsigned)sz; 1.144 Pos = 0; 1.145 FilePos += DataSize; 1.146 } 1.147 } 1.148 1.149 1.150 // ** Overridden functions 1.151 1.152 // We override all the functions that can possibly 1.153 // require buffer mode switch, flush, or extra calculations 1.154 1.155 // Tell() requires buffer adjustment 1.156 int BufferedFile::Tell() 1.157 { 1.158 if (BufferMode == ReadBuffer) 1.159 return int (FilePos - DataSize + Pos); 1.160 1.161 int pos = pFile->Tell(); 1.162 // Adjust position based on buffer mode & data 1.163 if (pos!=-1) 1.164 { 1.165 OVR_ASSERT(BufferMode != ReadBuffer); 1.166 if (BufferMode == WriteBuffer) 1.167 pos += Pos; 1.168 } 1.169 return pos; 1.170 } 1.171 1.172 SInt64 BufferedFile::LTell() 1.173 { 1.174 if (BufferMode == ReadBuffer) 1.175 return FilePos - DataSize + Pos; 1.176 1.177 SInt64 pos = pFile->LTell(); 1.178 if (pos!=-1) 1.179 { 1.180 OVR_ASSERT(BufferMode != ReadBuffer); 1.181 if (BufferMode == WriteBuffer) 1.182 pos += Pos; 1.183 } 1.184 return pos; 1.185 } 1.186 1.187 int BufferedFile::GetLength() 1.188 { 1.189 int len = pFile->GetLength(); 1.190 // If writing through buffer, file length may actually be bigger 1.191 if ((len!=-1) && (BufferMode==WriteBuffer)) 1.192 { 1.193 int currPos = pFile->Tell() + Pos; 1.194 if (currPos>len) 1.195 len = currPos; 1.196 } 1.197 return len; 1.198 } 1.199 SInt64 BufferedFile::LGetLength() 1.200 { 1.201 SInt64 len = pFile->LGetLength(); 1.202 // If writing through buffer, file length may actually be bigger 1.203 if ((len!=-1) && (BufferMode==WriteBuffer)) 1.204 { 1.205 SInt64 currPos = pFile->LTell() + Pos; 1.206 if (currPos>len) 1.207 len = currPos; 1.208 } 1.209 return len; 1.210 } 1.211 1.212 /* 1.213 bool BufferedFile::Stat(FileStats *pfs) 1.214 { 1.215 // Have to fix up length is stat 1.216 if (pFile->Stat(pfs)) 1.217 { 1.218 if (BufferMode==WriteBuffer) 1.219 { 1.220 SInt64 currPos = pFile->LTell() + Pos; 1.221 if (currPos > pfs->Size) 1.222 { 1.223 pfs->Size = currPos; 1.224 // ?? 1.225 pfs->Blocks = (pfs->Size+511) >> 9; 1.226 } 1.227 } 1.228 return 1; 1.229 } 1.230 return 0; 1.231 } 1.232 */ 1.233 1.234 int BufferedFile::Write(const UByte *psourceBuffer, int numBytes) 1.235 { 1.236 if ( (BufferMode==WriteBuffer) || SetBufferMode(WriteBuffer)) 1.237 { 1.238 // If not data space in buffer, flush 1.239 if ((FILEBUFFER_SIZE-(int)Pos)<numBytes) 1.240 { 1.241 FlushBuffer(); 1.242 // If bigger then tolerance, just write directly 1.243 if (numBytes>FILEBUFFER_TOLERANCE) 1.244 { 1.245 int sz = pFile->Write(psourceBuffer,numBytes); 1.246 if (sz > 0) 1.247 FilePos += sz; 1.248 return sz; 1.249 } 1.250 } 1.251 1.252 // Enough space in buffer.. so copy to it 1.253 memcpy(pBuffer+Pos, psourceBuffer, numBytes); 1.254 Pos += numBytes; 1.255 return numBytes; 1.256 } 1.257 int sz = pFile->Write(psourceBuffer,numBytes); 1.258 if (sz > 0) 1.259 FilePos += sz; 1.260 return sz; 1.261 } 1.262 1.263 int BufferedFile::Read(UByte *pdestBuffer, int numBytes) 1.264 { 1.265 if ( (BufferMode==ReadBuffer) || SetBufferMode(ReadBuffer)) 1.266 { 1.267 // Data in buffer... copy it 1.268 if ((int)(DataSize-Pos) >= numBytes) 1.269 { 1.270 memcpy(pdestBuffer, pBuffer+Pos, numBytes); 1.271 Pos += numBytes; 1.272 return numBytes; 1.273 } 1.274 1.275 // Not enough data in buffer, copy buffer 1.276 int readBytes = DataSize-Pos; 1.277 memcpy(pdestBuffer, pBuffer+Pos, readBytes); 1.278 numBytes -= readBytes; 1.279 pdestBuffer += readBytes; 1.280 Pos = DataSize; 1.281 1.282 // Don't reload buffer if more then tolerance 1.283 // (No major advantage, and we don't want to write a loop) 1.284 if (numBytes>FILEBUFFER_TOLERANCE) 1.285 { 1.286 numBytes = pFile->Read(pdestBuffer,numBytes); 1.287 if (numBytes > 0) 1.288 { 1.289 FilePos += numBytes; 1.290 Pos = DataSize = 0; 1.291 } 1.292 return readBytes + ((numBytes==-1) ? 0 : numBytes); 1.293 } 1.294 1.295 // Reload the buffer 1.296 // WARNING: Right now LoadBuffer() assumes the buffer's empty 1.297 LoadBuffer(); 1.298 if ((int)(DataSize-Pos) < numBytes) 1.299 numBytes = (int)DataSize-Pos; 1.300 1.301 memcpy(pdestBuffer, pBuffer+Pos, numBytes); 1.302 Pos += numBytes; 1.303 return numBytes + readBytes; 1.304 1.305 /* 1.306 // Alternative Read implementation. The one above is probably better 1.307 // due to FILEBUFFER_TOLERANCE. 1.308 int total = 0; 1.309 1.310 do { 1.311 int bufferBytes = (int)(DataSize-Pos); 1.312 int copyBytes = (bufferBytes > numBytes) ? numBytes : bufferBytes; 1.313 1.314 memcpy(pdestBuffer, pBuffer+Pos, copyBytes); 1.315 numBytes -= copyBytes; 1.316 pdestBuffer += copyBytes; 1.317 Pos += copyBytes; 1.318 total += copyBytes; 1.319 1.320 if (numBytes == 0) 1.321 break; 1.322 LoadBuffer(); 1.323 1.324 } while (DataSize > 0); 1.325 1.326 return total; 1.327 */ 1.328 } 1.329 int sz = pFile->Read(pdestBuffer,numBytes); 1.330 if (sz > 0) 1.331 FilePos += sz; 1.332 return sz; 1.333 } 1.334 1.335 1.336 int BufferedFile::SkipBytes(int numBytes) 1.337 { 1.338 int skippedBytes = 0; 1.339 1.340 // Special case for skipping a little data in read buffer 1.341 if (BufferMode==ReadBuffer) 1.342 { 1.343 skippedBytes = (((int)DataSize-(int)Pos) >= numBytes) ? numBytes : (DataSize-Pos); 1.344 Pos += skippedBytes; 1.345 numBytes -= skippedBytes; 1.346 } 1.347 1.348 if (numBytes) 1.349 { 1.350 numBytes = pFile->SkipBytes(numBytes); 1.351 // Make sure we return the actual number skipped, or error 1.352 if (numBytes!=-1) 1.353 { 1.354 skippedBytes += numBytes; 1.355 FilePos += numBytes; 1.356 Pos = DataSize = 0; 1.357 } 1.358 else if (skippedBytes <= 0) 1.359 skippedBytes = -1; 1.360 } 1.361 return skippedBytes; 1.362 } 1.363 1.364 int BufferedFile::BytesAvailable() 1.365 { 1.366 int available = pFile->BytesAvailable(); 1.367 // Adjust available size based on buffers 1.368 switch(BufferMode) 1.369 { 1.370 case ReadBuffer: 1.371 available += DataSize-Pos; 1.372 break; 1.373 case WriteBuffer: 1.374 available -= Pos; 1.375 if (available<0) 1.376 available= 0; 1.377 break; 1.378 default: 1.379 break; 1.380 } 1.381 return available; 1.382 } 1.383 1.384 bool BufferedFile::Flush() 1.385 { 1.386 FlushBuffer(); 1.387 return pFile->Flush(); 1.388 } 1.389 1.390 // Seeking could be optimized better.. 1.391 int BufferedFile::Seek(int offset, int origin) 1.392 { 1.393 if (BufferMode == ReadBuffer) 1.394 { 1.395 if (origin == Seek_Cur) 1.396 { 1.397 // Seek can fall either before or after Pos in the buffer, 1.398 // but it must be within bounds. 1.399 if (((unsigned(offset) + Pos)) <= DataSize) 1.400 { 1.401 Pos += offset; 1.402 return int (FilePos - DataSize + Pos); 1.403 } 1.404 1.405 // Lightweight buffer "Flush". We do this to avoid an extra seek 1.406 // back operation which would take place if we called FlushBuffer directly. 1.407 origin = Seek_Set; 1.408 OVR_ASSERT(((FilePos - DataSize + Pos) + (UInt64)offset) < ~(UInt64)0); 1.409 offset = (int)(FilePos - DataSize + Pos) + offset; 1.410 Pos = DataSize = 0; 1.411 } 1.412 else if (origin == Seek_Set) 1.413 { 1.414 if (((unsigned)offset - (FilePos-DataSize)) <= DataSize) 1.415 { 1.416 OVR_ASSERT((FilePos-DataSize) < ~(UInt64)0); 1.417 Pos = (unsigned)offset - (unsigned)(FilePos-DataSize); 1.418 return offset; 1.419 } 1.420 Pos = DataSize = 0; 1.421 } 1.422 else 1.423 { 1.424 FlushBuffer(); 1.425 } 1.426 } 1.427 else 1.428 { 1.429 FlushBuffer(); 1.430 } 1.431 1.432 /* 1.433 // Old Seek Logic 1.434 if (origin == Seek_Cur && offset + Pos < DataSize) 1.435 { 1.436 //OVR_ASSERT((FilePos - DataSize) >= (FilePos - DataSize + Pos + offset)); 1.437 Pos += offset; 1.438 OVR_ASSERT(int (Pos) >= 0); 1.439 return int (FilePos - DataSize + Pos); 1.440 } 1.441 else if (origin == Seek_Set && unsigned(offset) >= FilePos - DataSize && unsigned(offset) < FilePos) 1.442 { 1.443 Pos = unsigned(offset - FilePos + DataSize); 1.444 OVR_ASSERT(int (Pos) >= 0); 1.445 return int (FilePos - DataSize + Pos); 1.446 } 1.447 1.448 FlushBuffer(); 1.449 */ 1.450 1.451 1.452 FilePos = pFile->Seek(offset,origin); 1.453 return int (FilePos); 1.454 } 1.455 1.456 SInt64 BufferedFile::LSeek(SInt64 offset, int origin) 1.457 { 1.458 if (BufferMode == ReadBuffer) 1.459 { 1.460 if (origin == Seek_Cur) 1.461 { 1.462 // Seek can fall either before or after Pos in the buffer, 1.463 // but it must be within bounds. 1.464 if (((unsigned(offset) + Pos)) <= DataSize) 1.465 { 1.466 Pos += (unsigned)offset; 1.467 return SInt64(FilePos - DataSize + Pos); 1.468 } 1.469 1.470 // Lightweight buffer "Flush". We do this to avoid an extra seek 1.471 // back operation which would take place if we called FlushBuffer directly. 1.472 origin = Seek_Set; 1.473 offset = (SInt64)(FilePos - DataSize + Pos) + offset; 1.474 Pos = DataSize = 0; 1.475 } 1.476 else if (origin == Seek_Set) 1.477 { 1.478 if (((UInt64)offset - (FilePos-DataSize)) <= DataSize) 1.479 { 1.480 Pos = (unsigned)((UInt64)offset - (FilePos-DataSize)); 1.481 return offset; 1.482 } 1.483 Pos = DataSize = 0; 1.484 } 1.485 else 1.486 { 1.487 FlushBuffer(); 1.488 } 1.489 } 1.490 else 1.491 { 1.492 FlushBuffer(); 1.493 } 1.494 1.495 /* 1.496 OVR_ASSERT(BufferMode != NoBuffer); 1.497 1.498 if (origin == Seek_Cur && offset + Pos < DataSize) 1.499 { 1.500 Pos += int (offset); 1.501 return FilePos - DataSize + Pos; 1.502 } 1.503 else if (origin == Seek_Set && offset >= SInt64(FilePos - DataSize) && offset < SInt64(FilePos)) 1.504 { 1.505 Pos = unsigned(offset - FilePos + DataSize); 1.506 return FilePos - DataSize + Pos; 1.507 } 1.508 1.509 FlushBuffer(); 1.510 */ 1.511 1.512 FilePos = pFile->LSeek(offset,origin); 1.513 return FilePos; 1.514 } 1.515 1.516 int BufferedFile::CopyFromStream(File *pstream, int byteSize) 1.517 { 1.518 // We can't rely on overridden Write() 1.519 // because delegation doesn't override virtual pointers 1.520 // So, just re-implement 1.521 UByte buff[0x4000]; 1.522 int count = 0; 1.523 int szRequest, szRead, szWritten; 1.524 1.525 while(byteSize) 1.526 { 1.527 szRequest = (byteSize > int(sizeof(buff))) ? int(sizeof(buff)) : byteSize; 1.528 1.529 szRead = pstream->Read(buff,szRequest); 1.530 szWritten = 0; 1.531 if (szRead > 0) 1.532 szWritten = Write(buff,szRead); 1.533 1.534 count +=szWritten; 1.535 byteSize-=szWritten; 1.536 if (szWritten < szRequest) 1.537 break; 1.538 } 1.539 return count; 1.540 } 1.541 1.542 // Closing files 1.543 bool BufferedFile::Close() 1.544 { 1.545 switch(BufferMode) 1.546 { 1.547 case WriteBuffer: 1.548 FlushBuffer(); 1.549 break; 1.550 case ReadBuffer: 1.551 // No need to seek back on close 1.552 BufferMode = NoBuffer; 1.553 break; 1.554 default: 1.555 break; 1.556 } 1.557 return pFile->Close(); 1.558 } 1.559 1.560 1.561 // ***** Global path helpers 1.562 1.563 // Find trailing short filename in a path. 1.564 const char* OVR_CDECL GetShortFilename(const char* purl) 1.565 { 1.566 UPInt len = OVR_strlen(purl); 1.567 for (UPInt i=len; i>0; i--) 1.568 if (purl[i]=='\\' || purl[i]=='/') 1.569 return purl+i+1; 1.570 return purl; 1.571 } 1.572 1.573 } // OVR 1.574 1.575 \ No newline at end of file