diff -r 675a964f4eb5 -r 35751d3474b7 securityanddataprivacytools/securitytools/certapp/store--/s32file.cpp --- a/securityanddataprivacytools/securitytools/certapp/store--/s32file.cpp Tue Jul 21 01:04:32 2009 +0100 +++ b/securityanddataprivacytools/securitytools/certapp/store--/s32file.cpp Thu Sep 10 14:01:51 2009 +0300 @@ -1,1502 +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 -#include "s32file_private.h" -#include -#include -#include -#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<=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 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 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 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(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 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.ref0 || (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.ref0 || (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 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 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=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 (lenReadL(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=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 &MemStreamBuf::GetData() const -{ - return iData; -} - - -TInt MemStreamBuf::DoReadL(TAny *aPtr,TInt aMaxLength) -{ - char *p = reinterpret_cast(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<>KShiftCardinality16)) - aStream.WriteUint16L((n<>() -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 +/* +* 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 +#include "s32file_private.h" +#include +#include +#include +#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<=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 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 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 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(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 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.ref0 || (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.ref0 || (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 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 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=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 (lenReadL(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=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 &MemStreamBuf::GetData() const +{ + return iData; +} + + +TInt MemStreamBuf::DoReadL(TAny *aPtr,TInt aMaxLength) +{ + char *p = reinterpret_cast(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<>KShiftCardinality16)) + aStream.WriteUint16L((n<>() +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