--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/securityanddataprivacytools/securitytools/certapp/store--/s32file.cpp Wed Jul 08 11:25:26 2009 +0100
@@ -0,0 +1,1502 @@
+/*
+* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "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 <s32file.h>
+#include "s32file_private.h"
+#include <e32err.h>
+#include <fstream>
+#include <set>
+#include "us_std.h"
+#include "filestream.h"
+#include "logger.h"
+using namespace store_private;
+
+//The offset of the header of a permanent file store.
+//Since all permanent file store operations work in their own coordinate system, where physical file offset 32 is
+//logical offset 0, KPermanentStoreHeaderOffset is set with -16, which means that the physical file offset is 32 - 16 = 16.
+const TInt KPermanentStoreHeaderOffset=-16;
+
+//Permanent file store header length: sizeof(backup TOC ref) + sizeof(handle) + sizeof(TOC ref) + sizeof(crc) = 4 + 4 + 4 + 2 = 14
+const TInt KPermanentStoreHeaderLength=14;
+
+//Backup TOC ref length - 4 bytes
+const TInt KPermanentStoreBackupLength=4;
+
+const TInt KFileStoreStartOffset=sizeof(TCheckedUid);
+
+const TInt KBaseOffset=KFileStoreStartOffset-KPermanentStoreHeaderOffset;
+
+//
+const TInt KMaskHandleHash=0xff000000;
+const TInt KHandleInvalid=0x80000000;
+const TInt KHandleTocBase=0x40000000;
+const TInt KMaskHandleClear=0x30000000;
+const TInt KMaskHandleGen=0x0f000000;
+const TInt KIncHandleGen=0x01000000;
+//
+const TInt KMaxHandleIndex=0x00ffffff;
+const TInt KMaskHandleIndex=0x00ffffff;
+const TInt KSizeHandleIndex=3;
+//
+const TInt KTocDeltaCap = 64; //up to 64 entries in a delta TOC
+const TInt KTocDeltaMagic = 2;
+const TInt KMaxTocDeltaMagic = KMaxTUint16;
+const TInt KTocDelta=KHandleInvalid;
+//
+const TInt KOffsetTocHeader=-12;
+const TInt KSizeTocEntry=5; //base toc entry size is 5 bytes (when stored in the file, 8 bytes when presented in memory)
+const TInt KSizeTocDeltaEntry=8;//delta toc entry size is 8 bytes
+const TInt KSizeTocDeltaExtra=7;
+const TInt KElementsTocBuf=48;
+const TInt KBackTocBuf=20*KSizeTocEntry;
+const TInt KSizeTocBuf=KElementsTocBuf*KSizeTocEntry;
+
+enum TFrameType16
+ {
+ EFrameFree16=0x0000,
+ EFrameData16=0x4000,
+ EFrameDescriptive16=0x8000,
+ EFrameContinuation16=0xc000
+ };
+typedef TUint16 TFrameDes16;
+const TInt KSizeFrameDes16=sizeof(TFrameDes16);
+const TInt KShiftFrameDes16=1;
+//
+const TInt KMaskFrame16=0xffff;
+const TInt KMaskFrameType16=0xc000;
+#if defined(__SMALL_FRAME)
+const TInt KMaskFrameLength16=0xf;
+const TInt KShiftFrameLength16=4;
+#else
+const TInt KMaskFrameLength16=0x3fff;
+const TInt KShiftFrameLength16=14;
+#endif
+//
+const TInt KFrameOpen16=0;
+const TInt KFrameMinLength16=1;
+const TInt KFrameMaxLength16=KMaskFrameLength16;
+const TInt KFrameFullLength16=KMaskFrameLength16+1;
+//
+const TInt KFrameNonexistent16=-1;
+
+TUint32 frame2File(TUint32 anOffset)
+{
+ // The frame offset appears to be to calculated as an offset into
+ // a series of maximal length frames. Each maximal frame can hold
+ // 0x4000 bytes of data and has a 2 byte header. Therefore a frame
+ // offset of x needs an extra 2 bytes for each maximal frame. The
+ // base is the first byte of the payload of the first frame, so we
+ // do not need to allow for the header of the first frame.
+ //
+ // anOffset>>KShiftFrameLength16 gives the number of maximal
+ // frames. The left shift multiples by 2 to give minimum space
+ // required for frame headers. Adding to the original gives the
+ // file offset.
+ //
+ // This logic is still used even if space for the target frame is
+ // really ocupied by a series of smaller frames.
+ anOffset += (anOffset>>KShiftFrameLength16<<KShiftFrameDes16);
+
+ // Add 32 to allow for file header
+ anOffset += KBaseOffset;
+ return anOffset;
+}
+
+TUint32 file2Frame(TUint32 aFileOffset)
+{
+ // subtract 32 to allow for file header
+ aFileOffset -= KBaseOffset;
+
+ // File offset is to the first byte of payload of a stream. We
+ // need to remove the 2 byte frame header for the (theoretical)
+ // maximal length frames before it.
+
+ // Calculate the number of (theoretical) maximal length frames before the file position
+ // n = aFileOffset/0x4002
+ TInt n=aFileOffset/(KFrameFullLength16+KSizeFrameDes16);
+
+ // Subtract the frame header length for each maximal frame
+ aFileOffset -= n<<KShiftFrameDes16;
+
+ return aFileOffset;
+}
+
+
+
+//TPermanentStoreHeader class.
+//
+//Represents the data kept in the permanent store file header.
+//Data members:
+// - iBackup - "backup TOC reference", 32-bits integer, which keeps the 31-bit file offset of the backup TOC.
+// Plays important role in the "store commit" procedure.
+// The LSB is a "dirty" bit. If during the store opening phase the dirty bit is found to be set,
+// then it means - the previous "store commit" operation has not been completed successfully and
+// the backup TOC shall be used instead of the TOC;
+// - iHandle - 32-bit stream handle (MSB - invalid/deleted, 3 bits - unused, 4 bits - generation counter, 24 bits - stream handle).
+// Plays important role in the "stream relocation" procedure during store compaction.
+// iHandle keeps the handle of the stream being relocated, so if the commit phase fails, the original stream entry
+// can be restored at the moment when the store is reopened;
+// - iRef - Current "TOC reference". Represents a file offset, where the current TOC is;
+// - iCrc - 16-bit CRC, protecting iBackup, iHandle, iRef;
+class TPermanentStoreHeader
+ {
+public:
+ TPermanentStoreHeader() : iBackup(0), iHandle(0), iRef(0), iCrc(0) {}
+ TUint8* Ptr();
+ const TUint8* Ptr() const;
+ TBool IsValid() const;
+//
+ TPermanentStoreHeader(TInt aToc);
+ TPermanentStoreHeader(TInt aBackupToc,TInt aHandle,TInt aReference);
+//
+ TBool IsDirty() const;
+ void MarkDirty();
+ void SetBackupToc(TInt aBackupToc);
+ TInt BackupToc() const;
+//
+ TInt Handle() const;
+ TInt Reference() const;
+private:
+ void Set(TInt aBackupToc,TInt aHandle,TInt aReference);
+private:
+ TUint32 iBackup;
+ TInt32 iHandle;
+ TInt32 iRef;
+ TUint16 iCrc;
+public:
+ // Changes for port
+ void InternalizeL(RReadStream &aStream);
+ void ExternalizeL(RWriteStream &aStream) const;
+ };
+
+// Class TPermanentStoreHeader
+TUint8* TPermanentStoreHeader::Ptr()
+ {return REINTERPRET_CAST(TUint8*,&iBackup);}
+const TUint8* TPermanentStoreHeader::Ptr() const
+ {return REINTERPRET_CAST(const TUint8*,&iBackup);}
+
+
+TPermanentStoreHeader::TPermanentStoreHeader(TInt aToc)
+{Set(aToc,0,aToc);}
+
+TPermanentStoreHeader::TPermanentStoreHeader(TInt aBackupToc,TInt aHandle,TInt aReference)
+{
+ __ASSERT_DEBUG(aHandle!=0,User::Invariant());
+ Set(aBackupToc,aHandle,aReference);
+}
+
+TBool TPermanentStoreHeader::IsDirty() const
+{
+ return iBackup&0x1;
+}
+
+void TPermanentStoreHeader::MarkDirty()
+{
+ iBackup|=0x1;
+}
+
+void TPermanentStoreHeader::SetBackupToc(TInt aBackupToc)
+{
+ __ASSERT_DEBUG(aBackupToc>=0,User::Invariant());
+ iBackup=TUint32(aBackupToc)<<1;
+}
+
+TInt TPermanentStoreHeader::BackupToc() const
+{
+ return iBackup>>1;
+}
+
+TInt TPermanentStoreHeader::Handle() const
+{
+ return iHandle;
+}
+TInt TPermanentStoreHeader::Reference() const
+{
+ return iRef;
+}
+
+
+TBool TPermanentStoreHeader::IsValid() const
+{
+ if (IsDirty())
+ return EFalse;
+
+ TUint16 crc=0;
+ Mem::Crc(crc,Ptr(),_FOFF(TPermanentStoreHeader,iCrc));
+
+ return crc==iCrc;
+}
+
+//Sets the "backup TOC ref", "handle" and "TOC ref" in current TPermanentStoreHeader object.
+//16-bit CRC is calculated, based on the values of the input parameters, and stored together with them in the
+//TPermanentStoreHeader object.
+void TPermanentStoreHeader::Set(TInt aBackupToc,TInt aHandle,TInt aReference)
+ {
+ iBackup=TUint32(aBackupToc)<<1;
+ iHandle=aHandle;
+ iRef=aReference;
+ iCrc=0;
+ Mem::Crc(iCrc,Ptr(),_FOFF(TPermanentStoreHeader,iCrc));
+ __ASSERT_DEBUG(IsValid(),User::Invariant());
+ }
+
+
+void TPermanentStoreHeader::InternalizeL(RReadStream &aStream)
+{
+ aStream >> iBackup;
+ aStream >> iHandle;
+ aStream >> iRef;
+ aStream >> iCrc;
+}
+
+void TPermanentStoreHeader::ExternalizeL(RWriteStream &aStream) const
+{
+ aStream << iBackup;
+ aStream << iHandle;
+ aStream << iRef;
+ aStream << iCrc;
+}
+
+struct TocHeader
+ {
+ TInt32 iPrimary;
+ TInt32 iAvail;
+ TUint32 iCount;
+ void ExternalizeL(RWriteStream &aStream) const;
+ void InternalizeL(RReadStream &aStream);
+ };
+
+void TocHeader::ExternalizeL(RWriteStream &aStream) const
+{
+ aStream << iPrimary;
+ aStream << iAvail;
+ aStream << iCount;
+}
+
+void TocHeader::InternalizeL(RReadStream &aStream)
+{
+ aStream >> iPrimary;
+ aStream >> iAvail;
+ aStream >> iCount;
+}
+
+struct STocEntry
+ {
+ TInt32 handle;
+ TInt32 ref;
+ void ExternalizeL(RWriteStream &aStream) const;
+ void InternalizeL(RReadStream &aStream);
+ };
+
+
+void STocEntry::ExternalizeL(RWriteStream &aStream) const
+{
+ aStream.WriteL((TUint8*)&handle + KSizeHandleIndex, KSizeTocEntry);
+}
+
+void STocEntry::InternalizeL(RReadStream &aStream)
+{
+ aStream.ReadL((TUint8*)&handle + KSizeHandleIndex, KSizeTocEntry);
+}
+
+
+CStreamStore::~CStreamStore()
+{
+}
+
+
+TStreamId CPersistentStore::Root()
+{
+ return iRoot;
+}
+
+void CPersistentStore::SetRootL(TStreamId anId)
+{
+ iRoot = anId;
+}
+
+void CFileStore::SetTypeL(const TUidType& aType)
+{
+ if(aType != KPermanentFileStoreLayoutUid) FatalError();
+}
+
+
+CFileStore *CPermanentFileStore::ReplaceLC(RFs &aFs, const TDesC &aName, TUint aFileMode)
+{
+ (void) aFs;
+ return new CPermanentFileStore(aName, aFileMode);
+}
+
+CPermanentFileStore* CPermanentFileStore::OpenLC(RFs& aFs,const TDesC& aName,TUint aFileMode)
+{
+ (void) aFs;
+ CPermanentFileStore *pfs = new CPermanentFileStore(aName, aFileMode);
+ pfs->ReadInData();
+ return pfs;
+}
+
+CPermanentFileStore::CPermanentFileStore(const TDesC& aName,TUint aFileMode)
+ : iWritable(false), iFileIn(), iFileOut(), iLastStreamIdCreated(0),
+ iStreams()
+{
+ TBuf8<KMaxName> utf8Name;
+ utf8Name.Copy(aName);
+
+ std::string name((const char *)utf8Name.Ptr(), utf8Name.Length());
+
+ if(aFileMode & EFileWrite)
+ {
+ iFileOut.reset(new FileWriteStream(name));
+ iWritable = true;
+ }
+ else
+ {
+ iFileIn.reset(new FileReadStream(name));
+ }
+}
+
+CPermanentFileStore::~CPermanentFileStore()
+{
+ while(!iStreams.empty())
+ {
+ MemStreamBuf *p = (*iStreams.begin()).second;
+ iStreams.erase(iStreams.begin());
+ delete p;
+ }
+}
+
+
+MemStreamBuf *CPermanentFileStore::CreateStoreWriteStream()
+{
+ TStreamId id = ++iLastStreamIdCreated;
+ MemStreamBuf *handler = new MemStreamBuf(*this, id);
+
+ MemStreamBufPtrMap::value_type value(id, handler);
+ std::pair<MemStreamBufPtrMap::iterator, bool> ret = iStreams.insert(value);
+
+ if(!ret.second)
+ {
+ // Insert failed
+ FatalError();
+ }
+
+
+ return handler;
+}
+
+MemStreamBuf *CPermanentFileStore::CreateStoreReadStream(TStreamId aId) const
+{
+ MemStreamBufPtrMap::const_iterator it = iStreams.find(TUint32(aId));
+ if(it == iStreams.end())
+ {
+ // Lookup failed
+ dbg << Log::Indent() << "StreamId 0x" << aId << " does not exist in store!" << Log::Endl();
+ FatalError();
+ }
+ return (*it).second;
+}
+
+bool CPermanentFileStore::Writable() const
+{
+ return iWritable;
+}
+
+
+
+void CPermanentFileStore::CommitL()
+{
+ if(!iWritable) FatalError();
+
+ TCheckedUid id(KPermanentFileStoreLayoutUid);
+
+ *iFileOut << id;
+
+ // Write an empty header, we will correct the fields later
+ TPermanentStoreHeader tmpheader(0);
+ *iFileOut << tmpheader;
+
+ //
+ // Now write out the streams
+ //
+ std::vector<TUint> streamOffsets;
+ for(MemStreamBufPtrMap::const_iterator streamIt = iStreams.begin();
+ streamIt != iStreams.end();
+ ++streamIt)
+ {
+ const MemStreamBuf::StreamData &streamData((*streamIt).second->GetData());
+
+ // Record the offset to the first byte of the payload for use in the TOC
+ streamOffsets.push_back(TUint32(iFileOut->iSnk->TellL(MStreamBuf::EWrite))+KSizeFrameDes16);
+
+ TUint32 dataAvailable = streamData.size();
+ MemStreamBuf::StreamData::const_iterator dataIt = streamData.begin();
+ TUint32 currentType = EFrameData16;
+ while(dataAvailable)
+ {
+ TUint32 toWrite;
+ TFrameDes16 frame;
+
+ TUint32 fileOffset = TUint32(iFileOut->iSnk->TellL(MStreamBuf::EWrite))+KSizeFrameDes16;
+ TUint32 frameOffset = file2Frame(fileOffset);
+ TUint32 nextAnchor = ((frameOffset + KFrameFullLength16) & ~KMaskFrameLength16);
+ if(dataAvailable >= (nextAnchor-frameOffset))
+ {
+ // We have enough data to write an "Open" frame to
+ // take the frame offset up to the next multiple of
+ // 0x4000
+ toWrite = (nextAnchor-frameOffset);
+ frame = currentType | KFrameOpen16;
+ }
+ else
+ {
+ // Write a normal frame
+ toWrite = (dataAvailable < TUint32(KMaskFrameLength16)) ? (dataAvailable) : (KMaskFrameLength16);
+ frame = currentType | toWrite;
+ }
+
+ // Write frame
+ *iFileOut << frame;
+ // Write payload
+ while(toWrite--)
+ {
+ *iFileOut << *dataIt;
+ ++dataIt;
+ --dataAvailable;
+ }
+ // Set type of next frame to continuation
+ currentType = EFrameContinuation16;
+ }
+ }
+
+ //
+ // Now write the TOC
+ //
+ TInt tocLength = sizeof(TocHeader) + (iStreams.size() * KSizeTocEntry);
+ // Check toc frame length is not too long
+ if(tocLength > KMaskFrameLength16)
+ {
+ FatalError();
+ }
+ // Write TOC frame
+ TFrameDes16 frame = tocLength | EFrameDescriptive16;
+ *iFileOut << frame;
+
+ TStreamPos pos = iFileOut->iSnk->TellL(MStreamBuf::EWrite);
+
+ // First the header
+ TUint32 tocFrameOffset = file2Frame(pos);
+ TUint32 tocCookedFrameOffset = tocFrameOffset - KOffsetTocHeader;
+
+ TocHeader tocheader;
+ tocheader.iPrimary = iRoot;
+ tocheader.iAvail = 0;
+ tocheader.iCount = iStreams.size();
+ *iFileOut << tocheader;
+
+ // Now write the TOC entries
+ for(TUint i = 0; i < streamOffsets.size(); ++i)
+ {
+ STocEntry tocEntry = { 0, file2Frame(streamOffsets[i]) };
+ *iFileOut << tocEntry;
+ }
+
+
+ //
+ // Now overwrite the header with one containing the correct master
+ // TOC offset
+ //
+ TPermanentStoreHeader realheader(tocCookedFrameOffset);
+ // For some reason the real store code creates a header with a
+ // checksum which assumes iBackup == iRef but the iBackup value on
+ // disk is set to 0...
+ realheader.SetBackupToc(0);
+ iFileOut->iSnk->SeekL(MStreamBuf::EWrite, EStreamBeginning, sizeof(TCheckedUid));
+ *iFileOut << realheader;
+
+
+ iFileOut->Close();
+}
+
+void CPermanentFileStore::ReadInData()
+{
+ prog << Log::Indent() << "Reading store" << Log::Endl();
+ AutoIndent ai(prog);
+
+ TUint lastStreamIndex = 0;
+ TCheckedUid id;
+
+ *iFileIn >> id;
+
+ if(id.UidType() != KPermanentFileStoreLayoutUid)
+ {
+ dbg << Log::Indent() << "Invalid store" << Log::Endl();
+ FatalError();
+ }
+
+ TPermanentStoreHeader header;
+
+ *iFileIn >> header;
+
+ // - If the dirty bit is set, the backup TOC will be used;
+ // - If the dirty bit is not set, and the backup TOC ref is not the same as the TOC ref,
+ // then it means the the backup TOC ref has not been written successfully, so the TOC ref will be used;
+ TInt toc=header.BackupToc();
+ if (!header.IsDirty())
+ {
+ prog << Log::Indent() << "Store header is clean" << Log::Endl();
+ TInt handle=header.Handle();
+ TInt ref=header.Reference();
+ if (handle==0&&toc!=ref)
+ { // toc pointer not backed up, validate as if it was
+ toc=ref;
+ // iState|=EBackup;
+ header.SetBackupToc(toc);
+ }
+ if (!header.IsValid()) // not a permanent store or damaged beyond recognition
+ {
+ dbg << Log::Indent() << "Store header checksum failed check1" << Log::Endl();
+ __LEAVE(KErrNotSupported);
+ }
+
+ //
+ if (toc<0||((handle&~KMaskStreamIdValue)!=0&&handle!=KHandleTocBase)||ref<0||(handle!=0&&ref>=toc+KOffsetTocHeader))
+ {
+ dbg << Log::Indent() << "Store header fields invalid" << Log::Endl();
+ __LEAVE(KErrCorrupt); // integrity compromised
+ }
+ //
+ // iReloc=handle;
+ // iTarget=ref;
+ }
+ else
+ {
+ dbg << Log::Indent() << "Store header dirty" << Log::Endl();
+ }
+
+ //
+ // if (iToc!=0 && iToc!=toc) // refresh produced a different toc
+ // __LEAVE(KErrCorrupt);
+ // iToc=toc;
+
+
+ if(!header.IsValid())
+ {
+ dbg << Log::Indent() << "Store header checksum failed check2" << Log::Endl();
+ FatalError();
+ }
+
+ // All offset values are to the payload of frame structures (see RFrame16Buf)
+ // Convert to a file offset.
+ TInt tocFileOffset = frame2File(toc + KOffsetTocHeader);
+ prog << Log::Indent() << "TOC file offset 0x" << tocFileOffset << Log::Endl();
+
+ // nb. We do not validate the length of the "descriptive" stream
+ // which contains the TocHeader (aka STocHead) and the table of stream offsets.
+
+ iFileIn->iSrc->SeekL(MStreamBuf::ERead, EStreamBeginning, tocFileOffset);
+ TocHeader h;
+ *iFileIn >> h;
+ if ((h.iPrimary&~(KMaskStreamIdValue|static_cast<TUint>(KTocDelta)))!=0||
+ h.iAvail>0||(h.iAvail&KMaskHandleClear)!=0||(h.iCount&~KMaskHandleIndex)!=0)
+ {
+ // Corrupt
+ dbg << Log::Indent() << "Corrupt TOC in input file" << Log::Endl();
+ FatalError();
+ }
+ std::set<TUint32> streamIdsReadExGenField; // IDs of streams already read, EXCLUDING generation field
+ if (h.iPrimary & KTocDelta)
+ {
+ AutoIndent ai(prog);
+ prog << Log::Indent() << "Found Delta TOC" << Log::Endl();
+ // Process TOC-delta
+ TInt oldToc = toc;
+ // Find and read in the delta entries and then continue to read in the base entries
+ // Read offset to base TOC
+ iFileIn->iSrc->ReadL(&toc, sizeof(toc));
+ // All offset values are to the payload of frame structures (see RFrame16Buf)
+ // Convert to a file offset.
+ tocFileOffset = frame2File(toc + KOffsetTocHeader);
+
+ if((tocFileOffset < 0) || (tocFileOffset>oldToc))
+ {
+ dbg << Log::Indent() << "Invalid TOC in delta TOC" << Log::Endl();
+ FatalError(); // Corrupt
+ }
+
+ // Read/discard the magic value - Not sure what this should be
+ TUint16 magic;
+ iFileIn->iSrc->ReadL(&magic, sizeof(magic));
+
+ // Read count of delta toc entries
+ TInt8 n;
+ iFileIn->iSrc->ReadL(&n, sizeof(n));
+
+ prog << Log::Indent() << "Delta TOC entries " << int(n) << Log::Endl();
+ for(int deltaTocEntry=1; deltaTocEntry <= n; ++deltaTocEntry)
+ {
+ AutoIndent ai(prog);
+ prog << Log::Indent() << "Delta TOC entry " << deltaTocEntry << Log::Endl();
+
+ STocEntry e = {0,0};
+ // Read delta toc entry.
+ //
+ // The main TOC entries are truncated to 5 bytes so only
+ // include the flag bits of the handle and not the stream.
+ // They gain streamids starting from 1.
+ //
+ // The delta TOC contains complete stream IDs, and these
+ // entries take precedence over the matching (implicitly
+ // numbered) entry in the base TOC.
+ iFileIn->iSrc->ReadL(&e, sizeof(e));
+
+ if ((e.handle&KMaskHandleClear)!=0 ||
+ e.handle>=0 && (e.ref<KFrameNonexistent16) ||
+ e.handle<0 && (e.ref>0 || (e.ref&KMaskHandleClear)!=0))
+ {
+ dbg << Log::Indent() << "Invalid delta TOC entry" << Log::Endl();
+ __LEAVE(KErrCorrupt);
+ FatalError();
+ }
+
+ if(e.handle & KHandleInvalid)
+ {
+ // Stream marked as deleted, skip it
+ prog << Log::Indent() << "Delta TOC entry marked as deleted" << Log::Endl();
+ continue;
+ }
+
+ // We do not deal with any other special cases correctly
+ if(((e.handle&(KMaskHandleHash-KMaskHandleGen)) != 0) || (e.ref < 0))
+ {
+ dbg << Log::Indent() << "store-- does not support handle flags 0x" << e.handle << "in delta toc" << Log::Endl();
+ FatalError();
+ }
+
+ prog << Log::Indent()
+ << "streamId 0x" << e.handle << " frame offset 0x" << e.ref
+ << " file offset 0x" << frame2File(e.ref) << Log::Endl();
+
+ if(!streamIdsReadExGenField.insert(e.handle & ~KMaskHandleHash).second)
+ {
+ dbg << Log::Indent() << "store-- corrupt input? Multiple entries for stream ID " << (e.handle & ~KMaskHandleHash) << "encountered in delta toc!" << Log::Endl();
+ FatalError();
+ }
+
+
+ // Remember where we are...
+ TStreamPos here = iFileIn->iSrc->TellL(MStreamBuf::ERead);
+ // Read the stream frame
+ ReadStreamData(e.handle, e.ref);
+ // restore position to continue reading delta toc
+ iFileIn->iSrc->SeekL(MStreamBuf::ERead, EStreamBeginning, here);
+ }
+ }
+
+ iRoot = TInt(h.iPrimary) & ~KTocDelta;
+ prog << Log::Indent() << "Root stream ID is " << iRoot << Log::Endl();
+
+ prog << Log::Indent() << "Processing main TOC at file offset 0x" << tocFileOffset << Log::Endl();
+
+ for(TUint tocIndex=0; tocIndex < h.iCount; ++tocIndex)
+ {
+ // Read in streams
+ TStreamId baseStreamId = ++lastStreamIndex;
+ prog << Log::Indent() << "Entry " << std::dec << baseStreamId << std::hex << Log::Endl();
+ AutoIndent ai(prog);
+
+ // Check if we have already read in this stream id from the delta toc
+ // Note we only compare the base of the stream ID excluding the generation field.
+ if(streamIdsReadExGenField.find(baseStreamId) != streamIdsReadExGenField.end())
+ {
+ prog << Log::Indent() << "Already read from delta TOC" << Log::Endl();
+ continue; // Already read from delta toc
+ }
+
+ // Seek to the STocEntry for the stream
+ iFileIn->iSrc->SeekL(MStreamBuf::ERead, EStreamBeginning, tocFileOffset+sizeof(TocHeader)+KSizeTocEntry*(tocIndex));
+
+
+ STocEntry e = {0,0};
+ // Only the last 5 bytes of the entry are saved to disk.
+ // Because we are little endian this is the MSB of the handle and the whole ref.
+ *iFileIn >> e;
+
+ if ((e.handle&KMaskHandleClear)!=0 ||
+ e.handle>=0 && (e.ref<KFrameNonexistent16) ||
+ e.handle<0 && (e.ref>0 || (e.ref&KMaskHandleClear)!=0))
+ {
+ __LEAVE(KErrCorrupt);
+ FatalError();
+ }
+
+ if(e.handle & KHandleInvalid)
+ {
+ // Stream deleted, skip it
+ prog << Log::Indent() << "Marked as deleted" << Log::Endl();
+ continue;
+ }
+
+ // We do not deal with any other special cases correctly
+ if(((e.handle & (KMaskHandleHash-KMaskHandleGen)) != 0) || (e.ref < 0))
+ {
+ dbg << Log::Indent() << "store-- does not support handle flags 0x" << e.handle << "in main toc" << Log::Endl();
+ FatalError();
+ }
+
+ TStreamId streamId = baseStreamId | e.handle;
+ if(!streamIdsReadExGenField.insert(baseStreamId).second)
+ {
+ dbg << Log::Indent() << "store-- internal error for stream ID " << baseStreamId << "encountered in delta toc!" << Log::Endl();
+ FatalError();
+ }
+
+ // Read the stream frame
+ // prog << Log::Indent() << "Reading stream 0x" << streamId << " frame offset 0x" << e.ref << Log::Endl();
+ ReadStreamData(streamId, e.ref);
+ }
+}
+
+
+void CPermanentFileStore::ReadStreamData(TStreamId aStreamId, TInt aFrameOffset)
+{
+ TInt fileOffset = frame2File(aFrameOffset);
+ TFrameDes16 frame;
+ iFileIn->iSrc->SeekL(MStreamBuf::ERead, EStreamBeginning, fileOffset - sizeof(frame));
+
+ // Frame runs from fileOffset to fileOffset+2+frame
+ std::auto_ptr<MemStreamBuf> apStream(new MemStreamBuf(*this, aStreamId));
+
+ enum {
+ EFirst, EContinuation, ELast
+ } state = EFirst;
+
+ while(state != ELast)
+ {
+ iFileIn->iSrc->ReadL(&frame, sizeof(frame));
+
+ // Store uses offsets to the first byte of the payload of a frame, so that is what we display
+ TUint32 fileOffset = iFileIn->iSrc->TellL(MStreamBuf::ERead);
+ prog << Log::Indent() << "ReadStreamData State " << int(state) << " offset " << file2Frame(fileOffset) << "[" << fileOffset << "]" << Log::Endl();
+
+ TUint32 frameType = (frame & KMaskFrameType16);
+ if(frameType == EFrameFree16)
+ {
+ dbg << Log::Indent() << "Encountered a deleted frame in data stream" << Log::Endl();
+ FatalError();
+ }
+
+ if((frameType == EFrameData16) && (state != EFirst))
+ {
+ dbg << Log::Indent() << "Non-continuation frame encountered in middle of data stream" << Log::Endl();
+ FatalError();
+ }
+
+ if(frameType == EFrameDescriptive16)
+ {
+ dbg << Log::Indent() << "Descriptive frame encountered in data stream" << Log::Endl();
+ FatalError();
+ }
+
+ if((frameType == EFrameContinuation16) && (state != EContinuation))
+ {
+ dbg << Log::Indent() << "Continuation frame encountered at start of stream" << Log::Endl();
+ FatalError();
+ }
+
+ TInt len = (frame & KMaskFrameLength16);
+ if (len == KFrameOpen16)
+ {
+ prog << Log::Indent() << "\"Open\" frame length" << Log::Endl();
+ len = KFrameFullLength16 - file2Frame(fileOffset);
+ state = EContinuation;
+ }
+ else
+ {
+ state = ELast;
+ }
+
+ prog << Log::Indent() << "Type 0x" << frameType << " length " << std::dec << len << std::hex << Log::Endl();
+ apStream->AppendFromFile(iFileIn->iSrc, len);
+ };
+
+ MemStreamBufPtrMap::value_type value(aStreamId, apStream.get());
+ std::pair<MemStreamBufPtrMap::iterator, bool> ret = iStreams.insert(value);
+ if(!ret.second)
+ {
+ // Insert failed
+ FatalError();
+ }
+
+ apStream.release();
+}
+
+RReadStream::RReadStream()
+ : iSrc(0)
+{
+}
+
+void RReadStream::Close()
+{
+ iSrc = false;
+}
+
+RStoreReadStream::RStoreReadStream()
+ : RReadStream()
+{
+}
+
+
+void RStoreReadStream::OpenLC(const CStreamStore& aStore, TStreamId aId)
+{
+ iSrc = aStore.CreateStoreReadStream(aId);
+}
+
+
+
+RWriteStream::RWriteStream()
+ : iSnk(0)
+{
+}
+
+
+
+
+
+TStreamId RStoreWriteStream::CreateLC(CStreamStore& aStore)
+{
+ MemStreamBuf *s = aStore.CreateStoreWriteStream();
+ iSnk = s;
+ return s->StreamId();
+}
+
+EXPORT_C void RReadStream::ReadL(TDes8& aDes)
+/** Reads sufficient data from this stream to fill the specified 8 bit descriptor up to its maximum length.
+No other information is read from this read stream.
+
+@param aDes A reference to a modifiable descriptor which is to receive the data read from this stream. Passing the build
+independent type TDes& allows the compiler to choose the appropriate ReadL() variant (i.e the 8 bit or the 16 bit) at build time.*/
+ {
+ ReadL(aDes,aDes.MaxLength());
+ }
+
+EXPORT_C void RReadStream::ReadL(TDes8& aDes,TInt aLength)
+/** Reads data of specified length from this stream into the specified 8 bit descriptor. No other information is read
+from this stream.
+
+@param aDes A reference to a modifiable type descriptor which is to receive the data read from this stream.
+Passing the build independent type TDes& allows the compiler to choose the appropriate ReadL() variant (i.e the 8 bit
+or the 16 bit) at build time.
+@param aLength The length of data to be read from this stream. This value must be non-negative and must not be greater than the maximum length of the descriptor otherwise the function raises a USER 11 panic.*/
+ {
+ __ASSERT_DEBUG(aLength<=aDes.MaxLength(),Panic(EStreamReadBeyondEnd));
+ aDes.SetLength(aLength);
+ ReadL((TUint8*)aDes.Ptr(),aLength);
+ }
+
+#if 0
+EXPORT_C void RReadStream::ReadL(TDes8& aDes,TChar aDelim)
+/** Reads data from this stream into the 8 bit descriptor, until either the specified delimiter is encountered or the descriptor is filled to its maximum length.
+The resulting data in aDes always includes the delimiter aDelim, if aDes is large enough.
+
+@param aDes A reference to a modifiable type descriptor which is to receive the data read from this stream. Passing
+the build independent type TDes& allows the compiler to choose the appropriate ReadL() variant (i.e the 8 bit or the 16 bit) at build time.
+@param aDelim The delimiter marking the end of the data in the stream.*/
+
+ {
+ __ASSERT_DEBUG(iSrc!=NULL,Panic(EStreamNotOpen));
+ TUint8* ptr=(TUint8*)aDes.Ptr();
+ TDelimitedInput8 input(ptr,aDes.MaxLength(),aDelim);
+ do
+ {
+ iSrc->ReadL(input);
+ } while (!input.Done());
+ aDes.SetLength(input.Ptr()-ptr);
+ }
+#endif
+
+EXPORT_C void RReadStream::ReadL(TUint8* aPtr,TInt aLength)
+/** Reads data of specified length from this stream into the location defined by the specified TUint8 pointer.
+
+@param aPtr The target location for the streamed in data.
+@param aLength The length of data to be streamed in.*/
+ {
+ __ASSERT_DEBUG(aLength>=0,Panic(EStreamReadLengthNegative));
+ if (aLength==0)
+ return;
+// void *p = NULL;
+ __ASSERT_DEBUG(iSrc!=NULL,Panic(EStreamNotOpen));
+ TInt len=iSrc->ReadL(aPtr,aLength);
+ __ASSERT_DEBUG(len>=0&&len<=aLength,Panic(EStreamReadInBreach));
+ if (len<aLength)
+ __LEAVE(KErrEof);
+ }
+
+EXPORT_C void RReadStream::ReadL(TInt aLength)
+/** Discards data of specified length read from this stream.
+
+@param aLength The length of data to be discarded from this read stream.*/
+ {
+ __ASSERT_DEBUG(aLength>=0,Panic(EStreamReadLengthNegative));
+ if (aLength==0)
+ return;
+//
+ __ASSERT_DEBUG(iSrc!=NULL,Panic(EStreamNotOpen));
+
+#if 1
+ iSrc->SeekL(MStreamBuf::ERead, EStreamMark, aLength);
+#else
+ TNullInput input;
+ TInt len=iSrc->ReadL(input,aLength);
+ __ASSERT_DEBUG(len>=0&&len<=aLength,Panic(EStreamReadInBreach));
+ if (len<aLength)
+ __LEAVE(KErrEof);
+#endif
+ }
+
+EXPORT_C void RReadStream::ReadL(TDes16& aDes)
+/** Reads sufficient data from this stream to fill the specified 16 bit descriptor up to its maximum length.
+No other information is read from this read stream.
+
+@param aDes A reference to a modifiable type descriptor which is to receive the data read from this stream. Passing
+the build independent type TDes& allows the compiler to choose the appropriate ReadL() variant (i.e the 8 bit or the 16
+bit) at build time.*/
+ {
+ ReadL(aDes,aDes.MaxLength());
+ }
+
+EXPORT_C void RReadStream::ReadL(TDes16& aDes,TInt aLength)
+/** Reads data of specified length from this stream into the specified 16 bit descriptor. No other information is read from this stream.
+
+@param aDes A reference to a modifiable type descriptor which is to receive the data read from this stream. Passing the
+build independent type TDes& allows the compiler to choose the appropriate ReadL() variant (i.e the 8 bit or the 16 bit)
+at build time.
+@param aLength The length of data to be read from this stream. This value must be non-negative and must not be greater
+than the maximum length of the descriptor otherwise the function raises a USER 11 panic.*/
+ {
+ __ASSERT_DEBUG(aLength<=aDes.MaxLength(),Panic(EStreamReadBeyondEnd));
+ aDes.SetLength(aLength);
+ ReadL((TUint16*)aDes.Ptr(),aLength);
+ }
+
+#if 0
+EXPORT_C void RReadStream::ReadL(TDes16& aDes,TChar aDelim)
+/** Reads data from this stream into the 16 bit descriptor, until either the specified delimiter is encountered or
+the descriptor is filled to its maximum length.
+The resulting data in aDes always includes the delimiter aDelim, if aDes is large enough.
+
+@param aDes A reference to a modifiable type descriptor which is to receive the data read from this stream. Passing
+the build independent type TDes& allows the compiler to choose the appropriate ReadL() variant (i.e the 8 bit or the 16 bit) at build time.
+@param aDelim The delimiter marking the end of the data in the stream.*/
+ {
+ __ASSERT_DEBUG(iSrc!=NULL,Panic(EStreamNotOpen));
+ TUint16* ptr=(TUint16*)aDes.Ptr();
+ TDelimitedInput16 input(ptr,aDes.MaxLength(),aDelim);
+ do
+ {
+ iSrc->ReadL(input);
+ } while (!input.Done());
+ aDes.SetLength(input.Ptr()-ptr);
+ }
+#endif
+
+EXPORT_C void RReadStream::ReadL(TUint16* aPtr,TInt aLength)
+/** Reads data of specified length from this stream into the specified 16 bit descriptor.
+ No other information is read from this stream.
+
+@param aDes A reference to a modifiable type descriptor which is to receive the data read from this stream. Passing the build independent type TDes& allows the compiler to choose the appropriate ReadL() variant (i.e the 8 bit or the 16 bit) at build time.
+@param aLength The length of data to be read from this stream. This value must be non-negative and must not be greater than the maximum length of the descriptor otherwise the function raises a USER 11 panic.*/
+ {
+ __ASSERT_DEBUG(aLength>=0,Panic(EStreamReadLengthNegative));
+ ReadL((TUint8*)aPtr,aLength<<1); // platform dependency
+ }
+
+EXPORT_C TInt8 RReadStream::ReadInt8L()
+/** Internalises a TInt8 value The function reads an 8Â bit value from this stream
+and interprets it as a TInt8.
+
+@return The 8 bit value read from this stream. */
+ {
+ TInt8 val;
+ ReadL((TUint8*)&val,1); // platform dependency
+ return val;
+ }
+
+EXPORT_C TInt16 RReadStream::ReadInt16L()
+/** Internalises a TInt16 value. The function reads a 16Â bit value from this stream
+and interprets it as a TInt16.
+
+@return The 16 bit value read from this stream. */
+ {
+ TInt16 val;
+ ReadL((TUint8*)&val,2); // platform dependency
+ return val;
+ }
+
+EXPORT_C TInt32 RReadStream::ReadInt32L()
+/** Internalises a TInt32 value. The function reads a 32Â bit value from this stream
+and interprets it as a TInt32.
+
+@return The 32Â bit value read from this stream. */
+ {
+ TInt32 val;
+ ReadL((TUint8*)&val,4); // platform dependency
+ return val;
+ }
+
+EXPORT_C TUint8 RReadStream::ReadUint8L()
+/** Internalises a TUint8 value. The function reads an 8Â bit value from this stream
+and interprets it as a TUint8.
+
+@return The 8Â bit value read from this stream. */
+ {
+ TUint8 val;
+ ReadL(&val,1);
+ return val;
+ }
+
+EXPORT_C TUint16 RReadStream::ReadUint16L()
+/** Internalises a TUint16 value. The function reads a 16Â bit value from this
+stream and interprets it as a TUint16.
+
+@return The 16Â bit value read from this stream. */
+ {
+ TUint16 val;
+ ReadL((TUint8*)&val,2); // platform dependency
+ return val;
+ }
+
+EXPORT_C TUint32 RReadStream::ReadUint32L()
+/** Internalises a TUint32 value. The function reads a 32Â bit value from this
+stream and interprets it as a TUint32.
+
+@return The 32Â bit value read from this stream. */
+ {
+ TUint32 val;
+ ReadL((TUint8*)&val,4); // platform dependency
+ return val;
+ }
+
+
+EXPORT_C void RWriteStream::Close()
+/** Commits data to the stream before freeing resources used by the stream. This
+ensures that any buffered data is written to the stream.
+
+Note that the function cannot leave. Any errors arising from the attempt to
+commit data to the stream are ignored. */
+ {
+ if (iSnk==NULL)
+ return;
+//
+ iSnk->Close();
+ iSnk=NULL;
+ }
+
+EXPORT_C void RWriteStream::Release()
+/** Frees resources before abandoning the stream. The function is called after
+data has been committed to the stream.
+
+Note that if a cleanup item for the stream was placed on the cleanup stack
+when the stream was opened (e.g by a call to RStoreWriteStreamss CreateLC(),
+OpenLC(), ReplaceLC() or RDictionaryStores AssignLC() etc), then this function
+need not be called explicitly; clean up is implicitly done by CleanupStack::PopAndDestroy(). */
+ {
+ if (iSnk==NULL)
+ return;
+//
+ iSnk->Release();
+ iSnk=NULL;
+ }
+
+EXPORT_C void RWriteStream::CommitL()
+/** Ensures that any buffered data is written to the stream. Once committed, it
+is not possible to roll back the newly written data. */
+ {
+ if (iSnk==NULL)
+ return;
+//
+ iSnk->SynchL();
+ }
+
+
+EXPORT_C void RWriteStream::WriteL(const TDesC8& aDes)
+/** Writes the content of the 8 bit descriptor to the stream. No other information
+is written to this write stream.
+
+@param aDes A reference to a descriptor. Passing the build independent type
+TDesC& allows the compiler to choose the appropriate WriteL() variant (i.e
+the 8 bit or the 16 bit) at build time. */
+ {
+ WriteL(aDes.Ptr(),aDes.Length());
+ }
+
+EXPORT_C void RWriteStream::WriteL(const TDesC8& aDes,TInt aLength)
+/** Writes data of the specified length from the 8 bit descriptor to the stream.
+No other information is written to this write stream.
+
+@param aDes A reference to a descriptor. Passing the build independent type
+TDesC& allows the compiler to choose the appropriate WriteL() variant (i.e
+the 8 bit or the 16 bit) at build time.
+@param aLength The length of data to be written to this stream. */
+
+ {
+ __ASSERT_DEBUG(aLength<=aDes.Length(),Panic(EStreamWriteBeyondEnd));
+ WriteL(aDes.Ptr(),aLength);
+ }
+
+EXPORT_C void RWriteStream::WriteL(const TUint8* aPtr,TInt aLength)
+/** Writes 8 bit data of the specified length from the specified location to this
+write stream.
+
+@param aPtr The location from where data is to be streamed out.
+@param aLength The length of data to be streamed out. */
+
+ {
+ __ASSERT_DEBUG(aLength>=0,Panic(EStreamWriteLengthNegative));
+ if (aLength==0)
+ return;
+//
+ __ASSERT_DEBUG(iSnk!=NULL,Panic(EStreamNotOpen));
+ iSnk->WriteL(aPtr,aLength);
+ }
+
+#if 0
+EXPORT_C void RWriteStream::WriteL(RReadStream &aStream)
+/** Writes the content of the specified read stream to this write stream.
+
+@param aStream A reference to a read stream which is to be written to this
+stream. */
+
+ {
+ __ASSERT_DEBUG(iSnk!=NULL,Panic(EStreamNotOpen));
+ TSourceOutput output(aStream.iSrc);
+ iSnk->WriteL(output);
+ }
+#endif
+
+#if 0
+EXPORT_C void RWriteStream::WriteL(RReadStream& aStream,TInt aLength)
+/** Writes data of the specified length from the specified read stream to this
+stream.
+
+@param aStream A reference to a read stream part of whose content is to be
+written to this stream.
+@param aLength The length of data from the read stream to be written to this
+write stream. */
+
+ {
+ __ASSERT_DEBUG(aLength>=0,Panic(EStreamWriteLengthNegative));
+ if (aLength==0)
+ return;
+//
+ __ASSERT_DEBUG(iSnk!=NULL,Panic(EStreamNotOpen));
+ TSourceOutput output(aStream.iSrc);
+ TInt len=iSnk->WriteL(output,aLength);
+ __ASSERT_DEBUG(len>=0&&len<=aLength,Panic(EStreamReadInBreach));
+ if (len<aLength)
+ __LEAVE(KErrEof);
+ }
+#endif
+
+EXPORT_C void RWriteStream::WriteL(const TDesC16& aDes)
+/** Writes the content of the 16 bit descriptor to the stream. No other information
+is written to this write stream.
+
+@param aDes A reference to a descriptor. Passing the build independent type
+TDesC& allows the compiler to choose the appropriate WriteL() variant (i.e
+the 8 bit or the 16 bit) at build time. */
+
+ {
+ WriteL(aDes.Ptr(),aDes.Length());
+ }
+
+EXPORT_C void RWriteStream::WriteL(const TDesC16& aDes,TInt aLength)
+/** Writes data of the specified length from the 16 bit descriptor to the stream.
+No other information is written to this write stream.
+
+@param aDes A reference to a descriptor. Passing the build independent type
+TDesC& allows the compiler to choose the appropriate WriteL() variant (i.e
+the 8 bit or the 16 bit) at build time.
+@param aLength The length of data to be written to this stream. */
+
+ {
+ __ASSERT_DEBUG(aLength<=aDes.Length(),Panic(EStreamWriteBeyondEnd));
+ WriteL(aDes.Ptr(),aLength);
+ }
+
+EXPORT_C void RWriteStream::WriteL(const TUint16* aPtr,TInt aLength)
+/** Writes 16 bit data of the specified length from the specified location to this
+write stream.
+
+@param aPtr The location from where data is to be streamed out.
+@param aLength The length of data to be streamed out. */
+
+ {
+ __ASSERT_DEBUG(aLength>=0,Panic(EStreamWriteLengthNegative));
+ WriteL((const TUint8*)aPtr,aLength<<1); // platform dependency
+ }
+
+EXPORT_C void RWriteStream::WriteInt8L(TInt aValue)
+/** Writes a TInt value as an 8Â bit value to this stream.
+
+@param aValue The value to be written to this stream. */
+
+ {
+ WriteL((const TUint8*)&aValue,1); // platform dependency
+ }
+
+EXPORT_C void RWriteStream::WriteInt16L(TInt aValue)
+/** Writes a TInt value as a 16Â bit value to this stream.
+
+@param aValue The value to be written to this stream. */
+ {
+ WriteL((const TUint8*)&aValue,2); // platform dependency
+ }
+
+EXPORT_C void RWriteStream::WriteInt32L(TInt32 aValue)
+/** Writes a TInt32 value as a 32 bit value to this stream.
+
+@param aValue The value to be written to this stream. */
+
+ {
+ WriteL((const TUint8*)&aValue,4); // platform dependency
+ }
+
+EXPORT_C void RWriteStream::WriteUint8L(TUint aValue)
+/** Writes a TUint value as an 8 bit value to this stream.
+
+@param aValue The value to be written to this stream. */
+ {
+ WriteL((const TUint8*)&aValue,1); // platform dependency
+ }
+
+EXPORT_C void RWriteStream::WriteUint16L(TUint aValue)
+/** Writes a TUint value as a 16 bit value to this stream.
+
+@param aValue The value to be written to this stream. */
+
+ {
+ WriteL((const TUint8*)&aValue,2); // platform dependency
+ }
+
+EXPORT_C void RWriteStream::WriteUint32L(TUint32 aValue)
+/** Writes a TUint32 value as a 32 bit value to this stream.
+
+@param aValue The value to be written to this stream. */
+ {
+ WriteL((const TUint8*)&aValue,4); // platform dependency
+ }
+
+
+namespace store_private
+{
+
+MemStreamBuf::MemStreamBuf(const CStreamStore& aStore, TStreamId aId)
+ : iStore(&aStore), iStreamId(aId), iCurrentReadIndex(0), iCurrentWriteIndex(0), iData()
+{
+}
+
+MemStreamBuf::MemStreamBuf(const CStreamStore& aStore, TStreamId aId,
+ MStreamBuf *aStreamIn, std::streamoff aOffset, TUint32 aLength)
+ : iStore(&aStore), iStreamId(aId), iCurrentReadIndex(0), iCurrentWriteIndex(0), iData()
+{
+
+
+ aStreamIn->SeekL(MStreamBuf::ERead, EStreamBeginning, aOffset);
+ while(aLength)
+ {
+ TUint8 data;
+ aStreamIn->ReadL(&data, 1);
+ iData.push_back(data);
+ --aLength;
+ }
+
+}
+
+void MemStreamBuf::AppendFromFile(MStreamBuf *aStreamIn, TUint32 aLength)
+{
+ while(aLength)
+ {
+ TUint8 data;
+ aStreamIn->ReadL(&data, 1);
+ iData.push_back(data);
+ --aLength;
+ }
+}
+
+
+
+TStreamId MemStreamBuf::StreamId() const
+{
+ return iStreamId;
+}
+
+const std::vector<TUint8> &MemStreamBuf::GetData() const
+{
+ return iData;
+}
+
+
+TInt MemStreamBuf::DoReadL(TAny *aPtr,TInt aMaxLength)
+{
+ char *p = reinterpret_cast<char *>(aPtr);
+ for(TInt i=0; i < aMaxLength; ++i)
+ {
+ *p++ = iData[iCurrentReadIndex++];
+ }
+ return aMaxLength;
+}
+
+void MemStreamBuf::DoWriteL(const TUint8* aPtr,TInt aLength)
+{
+ for(TInt i=0; i < aLength; ++i)
+ {
+ if(iCurrentWriteIndex == iData.size())
+ {
+ iData.push_back(aPtr[i]);
+ }
+ else
+ {
+ iData[iCurrentWriteIndex] = aPtr[i];
+ }
+ ++iCurrentWriteIndex;
+ }
+}
+
+TStreamPos MemStreamBuf::DoSeekL(TMark aMark,TStreamLocation aLocation,TInt anOffset)
+{
+ if(aMark != ERead && aMark != EWrite)
+ {
+ FatalError();
+ }
+
+ TUint32 *p = (aMark == ERead) ? (&iCurrentReadIndex) : (&iCurrentWriteIndex);
+
+ switch(aLocation)
+ {
+ case EStreamBeginning:
+ *p = anOffset;
+ break;
+
+ case EStreamMark:
+ *p += anOffset;
+ break;
+
+ case EStreamEnd:
+ *p = iData.size() + anOffset;
+ break;
+
+ default:
+ FatalError();
+ }
+
+ if(*p > iData.size())
+ {
+ // nb we allow a seek 1 byte off end of data
+ FatalError();
+ }
+ return *p;
+}
+
+void MemStreamBuf::DoRelease()
+{
+}
+
+}; // end of namespace store_private
+
+const TInt KShiftCardinality8=1;
+const TInt KShiftCardinality16=2;
+const TInt KShiftCardinality32=3;
+//
+const TInt KDefaultIoBufSize=0xc00;
+const TInt KFilterIoBufSize=0x100;
+
+EXPORT_C void TCardinality::ExternalizeL(RWriteStream& aStream) const
+/** Externalises this object to a write stream.
+
+The existence of this function means that the standard templated operator<<()
+can be used to externalise objects of this class.
+
+@param aStream Stream to which the object should be externalised.
+@see operator<<() */
+ {
+ TUint n=iCount;
+ if (n<=(KMaxTUint8>>KShiftCardinality8))
+ aStream.WriteUint8L((n<<KShiftCardinality8));
+ else if (n<=(KMaxTUint16>>KShiftCardinality16))
+ aStream.WriteUint16L((n<<KShiftCardinality16)+0x1);
+ else
+ {
+ __ASSERT_DEBUG(n<=(TUint)KMaxCardinality,Panic(EStreamCardinalityOutOfRange));
+ aStream.WriteUint32L((n<<KShiftCardinality32)+0x3);
+ }
+ }
+
+EXPORT_C void TCardinality::InternalizeL(RReadStream& aStream)
+/** Internalizes this object from a read stream.
+
+The existence of this function means that the standard templated operator>>()
+can be used to internalise objects of this class.
+
+@param aStream Stream store from which the objet is to be internalised.
+@see operator>>() */
+ {
+ TUint n=aStream.ReadUint8L();
+ if ((n&0x1)==0)
+ n>>=KShiftCardinality8;
+ else if ((n&0x2)==0)
+ {
+ n+=aStream.ReadUint8L()<<8;
+ n>>=KShiftCardinality16;
+ }
+ else if ((n&0x4)==0)
+ {
+ aStream.ReadL((TUint8*)&iCount,sizeof(TUint32)-sizeof(TUint8));
+ n+=TUint(iCount)<<8; // platform dependency
+ n>>=KShiftCardinality32;
+ }
+ else
+ __LEAVE(KErrCorrupt);
+//
+ __ASSERT_DEBUG(n<=(TUint)KMaxCardinality,User::Invariant());
+ iCount=n;
+ }
+
+EXPORT_C void TCardinality::__DbgChkRange(TInt aCount)
+//
+// Check for a negative count.
+//
+ {
+ if(!(aCount<=KMaxCardinality)) FatalError();
+ }
+
+void CleanupStack::PopAndDestroy(RWriteStream *aStream)
+{
+ aStream->Close();
+}
+void CleanupStack::PopAndDestroy(RReadStream *aStream)
+{
+ aStream->Close();
+}
+
+void CleanupStack::PopAndDestroy(CFileStore *aStore)
+{
+ delete aStore;
+}
+
+
+// End of file