sl@0: // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include "readers.h" sl@0: sl@0: // sl@0: // sl@0: // sl@0: CFileReader::CFileReader(RFile* aFile) sl@0: : CBufferReader(iFileBuffer, CReader::EFile), sl@0: iFile(aFile) sl@0: { sl@0: } sl@0: sl@0: sl@0: // sl@0: // sl@0: // sl@0: CFileReader::~CFileReader() sl@0: { sl@0: } sl@0: sl@0: sl@0: // sl@0: // sl@0: // sl@0: CFileReader* CFileReader::NewLC(RFile* aFile) sl@0: { sl@0: CFileReader* self = new(ELeave) CFileReader(aFile); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: return self; sl@0: } sl@0: sl@0: sl@0: // sl@0: // sl@0: // sl@0: void CFileReader::ConstructL() sl@0: { sl@0: TInt pos = 0; sl@0: User::LeaveIfError(iFile->Seek(ESeekStart, pos)); sl@0: User::LeaveIfError(iFile->Read(iFileBuffer)); sl@0: } sl@0: sl@0: sl@0: // sl@0: // Checks if there is aAmount of data left in the buffer. sl@0: // It is important to call the base-class implementation first sl@0: // to ensure correct operation. sl@0: // sl@0: TBool CFileReader::CheckEnoughData(TInt aAmount) sl@0: { sl@0: if (CBufferReader::CheckEnoughData(aAmount)) sl@0: { sl@0: return ETrue; sl@0: } sl@0: sl@0: // Try to read more data. sl@0: TInt bufPos = CBufferReader::Position(); sl@0: TInt err = PhysicallySeekAndRead(bufPos - iFileBuffer.Length()); sl@0: if (err == KErrNone) sl@0: { sl@0: // The read may have succeeded but that sl@0: // still doesn't mean we have enough data. sl@0: return (aAmount <= iFileBuffer.Length()); sl@0: } sl@0: sl@0: return EFalse; sl@0: } sl@0: sl@0: sl@0: // sl@0: // sl@0: // sl@0: void CFileReader::Reset() sl@0: { sl@0: CBufferReader::Reset(); // This will reset iBufPos. sl@0: sl@0: if (iFilePos != 0) sl@0: { sl@0: // We need to seek to the start and fill the buffer. sl@0: iFilePos = 0; sl@0: TInt filepos = 0; sl@0: TInt err = iFile->Seek(ESeekStart, filepos); sl@0: if (err == KErrNone) sl@0: { sl@0: err = iFile->Read(iFileBuffer); sl@0: } sl@0: sl@0: if (err != KErrNone) sl@0: { sl@0: iFileBuffer.Zero(); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // There's no need to seek and read. sl@0: iFilePos = 0; sl@0: } sl@0: } sl@0: sl@0: sl@0: // sl@0: // sl@0: // sl@0: void CFileReader::SeekL(TInt aOffset) sl@0: { sl@0: TInt err = CReader::Seek(aOffset); sl@0: if (err == KErrUnderflow) sl@0: { sl@0: TInt bufPos = CBufferReader::Position(); sl@0: aOffset += bufPos - iFileBuffer.Length(); sl@0: User::LeaveIfError(PhysicallySeekAndRead(aOffset)); sl@0: } sl@0: } sl@0: sl@0: sl@0: // sl@0: // It could be possible for a 64-bit field in formats such as MPEG4 sl@0: // to have values that would fit in a 32-bit variable. In this case sl@0: // we can use it for seeking. This function checks if a 64-bit value sl@0: // is compatible with RFile's 32-bit operations. sl@0: // sl@0: void CFileReader::SeekL(TInt64 aOffset) sl@0: { sl@0: if (aOffset < KMinTInt64) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: if (aOffset > KMaxTInt64) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: if (aOffset < (TInt64)KMaxTInt) sl@0: { sl@0: TInt low = (TInt)I64LOW(aOffset); sl@0: SeekL(low); sl@0: } sl@0: else sl@0: { sl@0: TInt err = CReader::Seek(aOffset); sl@0: if (err == KErrUnderflow) sl@0: { sl@0: TInt64 bufPos = CBufferReader::Position(); sl@0: aOffset += bufPos - iFileBuffer.Length(); sl@0: User::LeaveIfError(PhysicallySeekAndRead(aOffset)); sl@0: } sl@0: } sl@0: } sl@0: sl@0: // sl@0: // This function seeks forward/backward aOffset bytes sl@0: // and fills the buffer from that point. sl@0: // sl@0: TInt CFileReader::PhysicallySeekAndRead(TInt aOffset) sl@0: { sl@0: TInt err; sl@0: sl@0: // New buffer contents so read from the start of it. sl@0: CBufferReader::Reset(); sl@0: sl@0: iFilePos = aOffset; sl@0: err = iFile->Seek(ESeekCurrent, aOffset); sl@0: sl@0: if (err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: sl@0: err = iFile->Read(iFileBuffer); sl@0: if (err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: return (iFileBuffer.Length() == 0 ? KErrEof : KErrNone); sl@0: } sl@0: TInt CFileReader::PhysicallySeekAndRead(TInt64 aOffset) sl@0: { sl@0: TInt err; sl@0: // New buffer contents so read from the start of it. sl@0: CBufferReader::Reset(); sl@0: sl@0: iFilePos = aOffset; sl@0: RFile64* tempfile; sl@0: tempfile = static_cast (iFile); sl@0: sl@0: err = tempfile->Seek(ESeekCurrent, iFilePos); sl@0: if (err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: sl@0: err = iFile->Read(iFileBuffer); sl@0: if (err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: sl@0: return (iFileBuffer.Length() == 0 ? KErrEof : KErrNone); sl@0: } sl@0: