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