mirror of
https://github.com/libretro/scummvm.git
synced 2025-03-06 10:17:14 +00:00
StdioStream implemented with Symbian file handling.
svn-id: r34400
This commit is contained in:
parent
c4fcd2b578
commit
c9262dd6e2
280
backends/fs/symbian/symbianstream.cpp
Normal file
280
backends/fs/symbian/symbianstream.cpp
Normal file
@ -0,0 +1,280 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "backends/fs/StdioStream.h"
|
||||
#include "common/system.h"
|
||||
#include "backends/platform/symbian/src/SymbianOS.h"
|
||||
|
||||
#include <f32file.h>
|
||||
|
||||
#define KInputBufferLength 128
|
||||
|
||||
// Symbian libc file functionality in order to provide shared file handles
|
||||
class TSymbianFileEntry {
|
||||
public:
|
||||
RFile _fileHandle;
|
||||
char _inputBuffer[KInputBufferLength];
|
||||
TInt _inputBufferLen;
|
||||
TInt _inputPos;
|
||||
TInt _lastError;
|
||||
TBool _eofReached;
|
||||
};
|
||||
|
||||
TSymbianFileEntry* CreateSymbianFileEntry(const char* name, const char* mode) {
|
||||
TSymbianFileEntry* fileEntry = new TSymbianFileEntry;
|
||||
fileEntry->_inputPos = KErrNotFound;
|
||||
fileEntry->_lastError = 0;
|
||||
fileEntry->_eofReached = EFalse;
|
||||
|
||||
if (fileEntry != NULL) {
|
||||
TInt modeLen = strlen(mode);
|
||||
|
||||
TPtrC8 namePtr((unsigned char*) name, strlen(name));
|
||||
TFileName tempFileName;
|
||||
tempFileName.Copy(namePtr);
|
||||
|
||||
TInt fileMode = EFileRead;
|
||||
|
||||
if (mode[0] == 'a')
|
||||
fileMode = EFileWrite;
|
||||
|
||||
if (!((modeLen > 1 && mode[1] == 'b') || (modeLen > 2 && mode[2] == 'b'))) {
|
||||
fileMode |= EFileStreamText;
|
||||
}
|
||||
|
||||
if ((modeLen > 1 && mode[1] == '+') || (modeLen > 2 && mode[2] == '+')) {
|
||||
fileMode = fileMode| EFileWrite;
|
||||
}
|
||||
|
||||
fileMode = fileMode| EFileShareAny;
|
||||
|
||||
switch(mode[0]) {
|
||||
case 'a':
|
||||
if (fileEntry->_fileHandle.Open(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), tempFileName, fileMode) != KErrNone) {
|
||||
if (fileEntry->_fileHandle.Create(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), tempFileName, fileMode) != KErrNone) {
|
||||
delete fileEntry;
|
||||
fileEntry = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
if (fileEntry->_fileHandle.Open(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), tempFileName, fileMode) != KErrNone) {
|
||||
delete fileEntry;
|
||||
fileEntry = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
if (fileEntry->_fileHandle.Replace(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), tempFileName, fileMode) != KErrNone) {
|
||||
delete fileEntry;
|
||||
fileEntry = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return fileEntry;
|
||||
}
|
||||
|
||||
size_t ReadData(const void* ptr, size_t size, size_t numItems, TSymbianFileEntry* handle) {
|
||||
TSymbianFileEntry* entry = ((TSymbianFileEntry*)(handle));
|
||||
TUint32 totsize = size*numItems;
|
||||
TPtr8 pointer ( (unsigned char*) ptr, totsize);
|
||||
|
||||
// Nothing cached and we want to load at least KInputBufferLength bytes
|
||||
if(totsize >= KInputBufferLength) {
|
||||
TUint32 totLength = 0;
|
||||
if(entry->_inputPos != KErrNotFound)
|
||||
{
|
||||
TPtr8 cacheBuffer( (unsigned char*) entry->_inputBuffer+entry->_inputPos, entry->_inputBufferLen - entry->_inputPos, KInputBufferLength);
|
||||
pointer.Append(cacheBuffer);
|
||||
entry->_inputPos = KErrNotFound;
|
||||
totLength+=pointer.Length();
|
||||
pointer.Set(totLength+(unsigned char*) ptr, 0, totsize-totLength);
|
||||
}
|
||||
|
||||
entry->_lastError = entry->_fileHandle.Read(pointer);
|
||||
|
||||
totLength+=pointer.Length();
|
||||
|
||||
pointer.Set((unsigned char*) ptr, totLength, totsize);
|
||||
|
||||
}
|
||||
else {
|
||||
// Nothing in buffer
|
||||
if(entry->_inputPos == KErrNotFound) {
|
||||
TPtr8 cacheBuffer( (unsigned char*) entry->_inputBuffer, KInputBufferLength);
|
||||
entry->_lastError = entry->_fileHandle.Read(cacheBuffer);
|
||||
|
||||
if(cacheBuffer.Length() >= totsize) {
|
||||
pointer.Copy(cacheBuffer.Left(totsize));
|
||||
entry->_inputPos = totsize;
|
||||
entry->_inputBufferLen = cacheBuffer.Length();
|
||||
}
|
||||
else {
|
||||
pointer.Copy(cacheBuffer);
|
||||
entry->_inputPos = KErrNotFound;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
TPtr8 cacheBuffer( (unsigned char*) entry->_inputBuffer, entry->_inputBufferLen, KInputBufferLength);
|
||||
|
||||
if(entry->_inputPos+totsize < entry->_inputBufferLen) {
|
||||
pointer.Copy(cacheBuffer.Mid(entry->_inputPos, totsize));
|
||||
entry->_inputPos+=totsize;
|
||||
}
|
||||
else {
|
||||
|
||||
pointer.Copy(cacheBuffer.Mid(entry->_inputPos, entry->_inputBufferLen-entry->_inputPos));
|
||||
cacheBuffer.SetLength(0);
|
||||
entry->_lastError = entry->_fileHandle.Read(cacheBuffer);
|
||||
|
||||
if(cacheBuffer.Length() >= totsize-pointer.Length()) {
|
||||
TUint32 restSize = totsize-pointer.Length();
|
||||
pointer.Append(cacheBuffer.Left(restSize));
|
||||
entry->_inputPos = restSize;
|
||||
entry->_inputBufferLen = cacheBuffer.Length();
|
||||
}
|
||||
else {
|
||||
pointer.Append(cacheBuffer);
|
||||
entry->_inputPos = KErrNotFound;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if((numItems * size) != pointer.Length() && entry->_lastError == KErrNone) {
|
||||
entry->_eofReached = ETrue;
|
||||
}
|
||||
|
||||
return pointer.Length() / size;
|
||||
}
|
||||
|
||||
StdioStream::StdioStream(void *handle) : _handle(handle) {
|
||||
assert(handle);
|
||||
}
|
||||
|
||||
StdioStream::~StdioStream() {
|
||||
((TSymbianFileEntry*)(_handle))->_fileHandle.Close();
|
||||
|
||||
delete (TSymbianFileEntry*)(_handle);
|
||||
}
|
||||
|
||||
bool StdioStream::ioFailed() const {
|
||||
return eos() || ((TSymbianFileEntry*)(_handle))->_lastError != 0;
|
||||
}
|
||||
|
||||
void StdioStream::clearIOFailed() {
|
||||
((TSymbianFileEntry*)(_handle))->_lastError = 0;
|
||||
}
|
||||
|
||||
bool StdioStream::eos() const {
|
||||
TSymbianFileEntry* entry = ((TSymbianFileEntry*)(_handle));
|
||||
|
||||
return entry->_eofReached != 0;
|
||||
}
|
||||
|
||||
uint32 StdioStream::pos() const {
|
||||
TInt pos = 0;
|
||||
TSymbianFileEntry* entry = ((TSymbianFileEntry*)(_handle));
|
||||
|
||||
entry->_lastError = entry->_fileHandle.Seek(ESeekCurrent, pos);
|
||||
if(entry->_lastError == KErrNone && entry->_inputPos != KErrNotFound)
|
||||
{
|
||||
pos+=(entry->_inputPos - entry->_inputBufferLen);
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
uint32 StdioStream::size() const {
|
||||
|
||||
TInt length = 0;
|
||||
((TSymbianFileEntry*)(_handle))->_fileHandle.Size(length);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
void StdioStream::seek(int32 offs, int whence) {
|
||||
assert(_handle);
|
||||
|
||||
TSeek seekMode = ESeekStart;
|
||||
TInt pos = offs;
|
||||
TSymbianFileEntry* entry = ((TSymbianFileEntry*)(_handle));
|
||||
|
||||
switch(whence) {
|
||||
case SEEK_SET:
|
||||
seekMode = ESeekStart;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
seekMode = ESeekCurrent;
|
||||
if(entry->_inputPos != KErrNotFound) {
|
||||
pos+=(entry->_inputPos - entry->_inputBufferLen);
|
||||
}
|
||||
break;
|
||||
case SEEK_END:
|
||||
seekMode = ESeekEnd;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
entry->_inputPos = KErrNotFound;
|
||||
entry->_eofReached = EFalse;
|
||||
if (entry->_fileHandle.Seek(seekMode, pos) != 0)
|
||||
{
|
||||
((TSymbianFileEntry *)(_handle))->_lastError = 0; // FIXME: why do we call clearerr here?
|
||||
}
|
||||
}
|
||||
|
||||
uint32 StdioStream::read(void *ptr, uint32 len) {
|
||||
return (uint32)ReadData((byte *)ptr, 1, len, (TSymbianFileEntry *)_handle);
|
||||
}
|
||||
|
||||
uint32 StdioStream::write(const void *ptr, uint32 len) {
|
||||
TPtrC8 pointer( (unsigned char*) ptr, len);
|
||||
|
||||
((TSymbianFileEntry*)(_handle))->_inputPos = KErrNotFound;
|
||||
((TSymbianFileEntry*)(_handle))->_lastError = ((TSymbianFileEntry*)(_handle))->_fileHandle.Write(pointer);
|
||||
((TSymbianFileEntry*)(_handle))->_eofReached = EFalse;
|
||||
|
||||
if (((TSymbianFileEntry*)(_handle))->_lastError == KErrNone) {
|
||||
return len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void StdioStream::flush() {
|
||||
((TSymbianFileEntry*)(_handle))->_fileHandle.Flush();
|
||||
}
|
||||
|
||||
StdioStream *StdioStream::makeFromPath(const Common::String &path, bool writeMode) {
|
||||
void *handle = CreateSymbianFileEntry(path.c_str(), writeMode ? "wb" : "rb");
|
||||
if (handle)
|
||||
return new StdioStream(handle);
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user