diff -r 000000000000 -r 08ec8eefde2f persistentstorage/store/UFILE/UF_BUF.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/persistentstorage/store/UFILE/UF_BUF.CPP Fri Jan 22 11:06:30 2010 +0200 @@ -0,0 +1,663 @@ +// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include "UF_STD.H" +#include "S32FILEBUFSIZE.H" + +//#define MAP_ROM_FILES +#ifdef _DEBUG +//#define IO_TRACING +//#define SIMULATE_PARTIAL_WRITE +#endif + +#ifdef IO_TRACING +#include +_LIT(KTraceWrite,"RFile::Write [%d,%d)\n"); +#define _TRACE_WRITE(p,l) RDebug::Print(KTraceWrite,(p),(p)+(l)) +_LIT(KTraceRead,"RFile::Read [%d,%d)\n"); +#define _TRACE_READ(p,l) RDebug::Print(KTraceRead,(p),(p)+(l)) +_LIT(KTraceSize,"RFile::Size\n"); +#define _TRACE_SIZE() RDebug::Print(KTraceSize) +_LIT(KTraceFlush,"RFile::Flush\n"); +#define _TRACE_FLUSH() RDebug::Print(KTraceFlush) +_LIT(KTraceSetSize,"RFile::SetSize %d\n"); +#define _TRACE_SETSIZE(s) RDebug::Print(KTraceSetSize,(s)) +#else +#define _TRACE_WRITE(p,l) +#define _TRACE_READ(p,l) +#define _TRACE_SIZE() +#define _TRACE_FLUSH() +#define _TRACE_SETSIZE(s) +#endif + +EXPORT_C RFileBuf::RFileBuf() + : iBase(NULL),iSize(KDefaultFileBufSize),iWLim(NULL) +/** Constructs the object with a default intermediate buffer size. + +The size of the intermediate buffer is the value of the constant KDefaultFileBufSize. */ + {} + +EXPORT_C RFileBuf::RFileBuf(TInt aSize) + : iBase(NULL),iSize(aSize),iWLim(NULL) +/** Constructs the object with the specified intermediate buffer size. + +If the intermediate buffer size is zero, then the class provides an MStreamBuf +interface to unbuffered file I/O. + +@param aSize The size of the intermediate buffer. */ + {} + +RFileBuf::RFileBuf(TCapture aCapture) +// +// Take over from the buffer wrapped inside aCapture. +// + { + RFileBuf& buf=aCapture.Object(); + iBase=buf.iBase; + iSize=buf.iSize; + SetBuf(ERead,buf.Ptr(ERead),buf.End(ERead)); + SetBuf(EWrite,buf.Ptr(EWrite),buf.End(EWrite)); + SetLimit(EWrite,buf.Limit(EWrite)); + buf.iBase=NULL; + buf.SetBuf(ERead|EWrite,NULL,NULL); + iFile=buf.File(); + buf.Detach(); + SetPos(ERead,buf.Pos(ERead)); + SetPos(EWrite,buf.Pos(EWrite)); + iExt=buf.iExt; + } + +EXPORT_C void RFileBuf::Reset() +/** Frees the intermediate buffer. + +If there is any read data in the intermediate buffer, then the function reverts +the read position within the stream. + +The intermediate buffer must not contain any outstanding write data, otherwise +the function raises a STORE-File 6 panic. */ + { + __ASSERT_ALWAYS(Span(EWrite)==0,Panic(EFileWriteOutstanding)); + MovePos(ERead,Lag(ERead)); + Free(); + } + +EXPORT_C TInt RFileBuf::Open(RFs& aFs,const TDesC& aName,TUint aFileMode) +/** Opens the specified file and attaches it to this stream buffer. + +If the file cannot be opened, then it is not attached to this stream buffer. + +@param aFs Handle to a file server session through which the file is opened. +@param aName The name of the file to be opened. +@param aFileMode The mode in which the file is to be accessed. The mode is +defined by the TFileMode type. +@return KErrNone, if successful, otherwise one of the other system wide error +codes. +@see Attach() +@see TFileMode +@see RFile */ + { + RFile file; + TInt r=file.Open(aFs,aName,aFileMode); + if (r==KErrNone) + Attach(file); + return r; + } + +EXPORT_C TInt RFileBuf::Create(RFs& aFs,const TDesC& aName,TUint aFileMode) +/** Creates a file with the specified name and attaches it to this stream buffer. + +The file must not already exist. + +If the file cannot be created and opened, then it is not attached to this +stream buffer. + +@param aFs Handle to a file server session through which the file is created. +@param aName The name of the file to be created. +@param aFileMode The mode in which the file is to be accessed. The mode is +defined by the TFileMode type. +@return KErrNone, if successful, otherwise one of the other system wide error +codes. +@see Attach() +@see TFileMode +@see RFile */ + { + RFile file; + TInt r=file.Create(aFs,aName,aFileMode); + if (r==KErrNone) + Attach(file); + return r; + } + +EXPORT_C TInt RFileBuf::Replace(RFs& aFs,const TDesC& aName,TUint aFileMode) +/** Replaces the file with the specified name and attaches it to this stream buffer. + +If there is an existing file with the same name, then this function overwrites +it. If the file does not already exist, it is created. + +If the file cannot be replaced, then it is not attached to this stream buffer. + +@param aFs Handle to a file server session through which the file is replaced. +@param aName The name of the file to be replaced. +@param aFileMode The mode in which the file is to be accessed. The mode is +defined by the TFileMode type. +@return KErrNone, if successful, otherwise one of the other system wide error +codes. +@see Attach() +@see TFileMode +@see RFile */ + { + RFile file; + TInt r=file.Replace(aFs,aName,aFileMode); + if (r==KErrNone) + Attach(file); + return r; + } + +EXPORT_C TInt RFileBuf::Temp(RFs& aFs,const TDesC& aPath,TFileName& aName,TUint aFileMode) +/** Creates and opens a temporary file with a unique name and attaches it to this +stream buffer. + +@param aFs Handle to a file server session through which the file is created. +@param aPath The directory in which the file is created. +@param aName On return, contains the full path and file name of the file. The +filename is guaranteed to be unique within the specified directory. +@param aFileMode The mode in which the file is to be accessed. The mode is +defined by the TFileMode type. +@see Attach() +@see TFileMode +@see RFile */ + { + RFile file; + TInt r=file.Temp(aFs,aPath,aName,aFileMode); + if (r==KErrNone) + Attach(file); + return r; + } + +EXPORT_C void RFileBuf::Attach(RFile& aFile,TInt aPos) +/** Attaches the specified file to this stream buffer. + +The function also re-sets the intermediate buffer's read and write marks to +the beginning of the intermediate buffer and sets the read and write stream +positions to the specified offset within the file. + +@param aFile The file to be attached. +@param aPos The offset within the file to which the read and write stream positions +are set. By default this is zero. +@see Detach() +@see Reattach() */ + { + __ASSERT_ALWAYS(Span(EWrite)==0,Panic(EFileWriteOutstanding)); + TUint8* base=iBase; + SetBuf(ERead|EWrite,base,base); + iFile=aFile; + aFile=RFile(); + SetPos(ERead|EWrite,aPos); + iExt=-1; + } + +EXPORT_C void RFileBuf::Close() +/** Writes any outstanding data from the intermediate buffer before freeing the +intermediate buffer and closing the attached file. */ + { + TInt lag=Span(EWrite); + if (lag>0) + { + _TRACE_WRITE(Pos(EWrite),lag); + File().Write(Pos(EWrite),TPtrC8(iBase,lag)); + } + Free(); + File().Close(); + } + +EXPORT_C void RFileBuf::SetSizeL(TInt aSize) +/** Changes the size of the file attached to this buffer to the specified value. + +Writes any outstanding data from the intermediate buffer to the stream hosted +by the file. Any data in the intermediate buffer that would lie beyond the +end of the truncated file, is not written. + +@param aSize The new size of the file. */ + { + TUint8* base=iBase; + TInt pos=Pos(EWrite); + TInt excess=aSize-pos; + if (excess>0) + FileWriteL(base,Min(excess,Span(EWrite)),0); + MovePos(ERead,Lag(ERead)); + SetBuf(ERead,base,base); +// + _TRACE_SETSIZE(aSize); + TInt r=File().SetSize(aSize); + if (r!=KErrNone) + { + SetPos(EWrite,pos); + iExt=-1; + __LEAVE(r); + } +// + SetPos(EWrite,Min(pos+Lag(EWrite), aSize)); + SetBuf(EWrite,base,base); + iExt=aSize; + } + +EXPORT_C TInt RFileBuf::UnderflowL(TInt aMaxLength) +// +// Fill the buffer's read area. +// + { + __ASSERT_DEBUG(Avail(ERead)==0,User::Invariant()); + TUint8* base=iBase; + if (base==NULL) + { +#if defined(MAP_ROM_FILES) + if (Ptr(ERead)) + return 0; // memory mapped ROM file + TInt pos=0; + TInt err = File().Seek(ESeekAddress,pos); + if (err==KErrNone) + { // memory map a ROM file into the read zone + base=(TUint8*)pos; + TInt len=EndL(); + SetPos(ERead,len); + SetBuf(ERead,base,base+len); + return len; + } +#endif + base=AllocL(); + } + + TInt lag=Pos(ERead)-Pos(EWrite); + TInt span=Span(EWrite); + if (lag>=0&&lag=0,Panic(EFileReadLengthNegative)); + __ASSERT_DEBUG(aMaxLength>0,Panic(EFileReadNoTransfer)); + TInt avail=Avail(ERead); + __ASSERT_DEBUG(avail>=0&&Avail(EWrite)>=0,User::Invariant()); + if (avail>0) + { + TInt len=Min(aMaxLength,avail); + TUint8* ptr=Ptr(ERead); + aPtr=Mem::Copy(aPtr,ptr,len); + SetPtr(ERead,ptr+len); + aMaxLength-=len; + if (aMaxLength==0) + return len; // that's it + } + __ASSERT_DEBUG(Avail(ERead)==0,User::Invariant()); + if (aMaxLength=0,Panic(EFileWriteLengthNegative)); + __ASSERT_DEBUG(aLength>0,Panic(EFileWriteNoTransfer)); + TInt avail=Avail(EWrite); + __ASSERT_DEBUG(Avail(ERead)>=0&&avail>=0,User::Invariant()); + if (avail>0) + { + TInt len=Min(aLength,avail); + SetPtr(EWrite,Mem::Copy(Ptr(EWrite),aPtr,len)); + aLength-=len; + if (aLength==0) + return; // done +// + aPtr=(TUint8*)aPtr+len; + } + __ASSERT_DEBUG(Avail(EWrite)==0,User::Invariant()); + if (aLengthend) + { + anOffset=end; + r=KErrEof; + } +// + __ASSERT_ALWAYS(!(aMark&~(ERead|EWrite)),Panic(EFileMarkInvalid)); + if (aMark&ERead) + { + TInt lag=anOffset-Pos(ERead); +#if defined(MAP_ROM_FILES) + if (base==NULL&&End(ERead)!=NULL) // memory mapped + SetPtr(ERead,End(ERead)+lag); + else +#endif + if (lag>=base-End(ERead)&&lag<=0) + SetPtr(ERead,End(ERead)+lag); + else + { + SetPos(ERead,anOffset); + SetBuf(ERead,base,base); + } + } + if (aMark&EWrite) + { + TInt lag=anOffset-Pos(EWrite); + TInt span=Span(EWrite); + if (lag>=0&&lag<=span) + { + SetLimit(EWrite,base+span); + SetPtr(EWrite,base+lag); + } + else + { + FileWriteL(base,span,0); + SetPos(EWrite,anOffset); + SetBuf(EWrite,base,base); + } + } + __LEAVE_IF_ERROR(r); + return TStreamPos(anOffset); + } + +TUint8* RFileBuf::AllocL() +// +// Allocate space and return a pointer to this buffer's buffer space +// + { + __ASSERT_DEBUG(iBase==NULL && iSize>0,User::Invariant()); +// + TUint8* base=(TUint8*)User::AllocL(iSize); + iBase=base; + SetBuf(ERead|EWrite,base,base); + return base; + } + +void RFileBuf::Free() +// +// Free this buffer's buffer space. +// + { + User::Free(iBase); + iBase=NULL; + SetBuf(ERead|EWrite,NULL,NULL); + } + +void RFileBuf::SetPos(TMark aMark,TInt aPos) +// +// Set the file position for the mark(s) indicated by aMark +// + { + __ASSERT_ALWAYS(!(aMark&~(ERead|EWrite)),Panic(EFileMarkInvalid)); + if (aMark&ERead) + SetPos(ERead,aPos); + if (aMark&EWrite) + SetPos(EWrite,aPos); + } + +TInt RFileBuf::FileReadL(TAny* aPtr,TInt aMaxLength) +// +// Read from the file at the current read position. +// + { + __ASSERT_DEBUG(aMaxLength>=0,Panic(EFileReadLengthNegative)); + if (aMaxLength==0) + return 0; +// + TPtr8 des((TUint8*)aPtr,aMaxLength); + TInt pos=Pos(ERead); + __LEAVE_IF_ERROR(File().Read(pos,des)); + TInt len=des.Length(); + _TRACE_READ(pos,len); + pos+=len; + if (len=0,Panic(EFileWriteLengthNegative)); + if (aLength==0) + return; +// + TInt ext=iExt; + iExt=-1; + TInt pos=Pos(EWrite); + _TRACE_WRITE(pos,aLength); +#ifdef SIMULATE_PARTIAL_WRITE + TPtrC8 ptr((TUint8*)aPtr,aLength); + TInt partial = aLength >> 1; + if (partial) + { + __LEAVE_IF_ERROR(File().Write(pos, ptr.Left(partial))); + } + __LEAVE_IF_ERROR(File().Write(pos + partial, ptr.Mid(partial))); +#else + +#if defined SYSLIBS_TEST && defined _DEBUG + const TInt KDefaultMediaBlockSize = 512; + TInt startSectorAddr = pos & ~(KDefaultMediaBlockSize - 1); + TInt endSectorAddr = (pos + aLength - 1) & ~(KDefaultMediaBlockSize - 1); + if(startSectorAddr != endSectorAddr && aLength < KDefaultMediaBlockSize) + { + TInt len1 = startSectorAddr + KDefaultMediaBlockSize - pos; + TInt len2 = aLength - len1; + __LEAVE_IF_ERROR(File().Write(pos, TPtrC8((TUint8*)aPtr, len1))); + __LEAVE_IF_ERROR(File().Write(pos + len1, TPtrC8((TUint8*)aPtr + len1, len2))); + } + else + { + __LEAVE_IF_ERROR(File().Write(pos,TPtrC8((TUint8*)aPtr,aLength))); + } +#else //SYSLIBS_TEST + __LEAVE_IF_ERROR(File().Write(pos,TPtrC8((TUint8*)aPtr,aLength))); +#endif//SYSLIBS_TEST + +#endif + pos+=aLength; + if (ext>=0) + iExt=Max(pos,ext); + SetPos(EWrite,pos-aRewind); + } + +TInt RFileBuf::EndL() +// +// Determine the end of the file. +// + { + TInt ext=iExt; + if (ext<0) + { + _TRACE_SIZE(); + __LEAVE_IF_ERROR(File().Size(ext)); + iExt=ext; + } + return Max(ext,Reach(EWrite)); + } + +TInt RFileBuf::Mark(TMark aMark) const +// +// Return the position of the mark indicated by aMark. +// + { + if (aMark==ERead) + return Mark(ERead); +// + __ASSERT_ALWAYS(aMark==EWrite,Panic(EFileMarkInvalid)); + return Mark(EWrite); + } +