|
1 /* |
|
2 * Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <s32file.h> |
|
20 #include "s32file_private.h" |
|
21 #include <e32err.h> |
|
22 #include <fstream> |
|
23 #include <set> |
|
24 #include "us_std.h" |
|
25 #include "filestream.h" |
|
26 #include "logger.h" |
|
27 using namespace store_private; |
|
28 |
|
29 //The offset of the header of a permanent file store. |
|
30 //Since all permanent file store operations work in their own coordinate system, where physical file offset 32 is |
|
31 //logical offset 0, KPermanentStoreHeaderOffset is set with -16, which means that the physical file offset is 32 - 16 = 16. |
|
32 const TInt KPermanentStoreHeaderOffset=-16; |
|
33 |
|
34 //Permanent file store header length: sizeof(backup TOC ref) + sizeof(handle) + sizeof(TOC ref) + sizeof(crc) = 4 + 4 + 4 + 2 = 14 |
|
35 const TInt KPermanentStoreHeaderLength=14; |
|
36 |
|
37 //Backup TOC ref length - 4 bytes |
|
38 const TInt KPermanentStoreBackupLength=4; |
|
39 |
|
40 const TInt KFileStoreStartOffset=sizeof(TCheckedUid); |
|
41 |
|
42 const TInt KBaseOffset=KFileStoreStartOffset-KPermanentStoreHeaderOffset; |
|
43 |
|
44 // |
|
45 const TInt KMaskHandleHash=0xff000000; |
|
46 const TInt KHandleInvalid=0x80000000; |
|
47 const TInt KHandleTocBase=0x40000000; |
|
48 const TInt KMaskHandleClear=0x30000000; |
|
49 const TInt KMaskHandleGen=0x0f000000; |
|
50 const TInt KIncHandleGen=0x01000000; |
|
51 // |
|
52 const TInt KMaxHandleIndex=0x00ffffff; |
|
53 const TInt KMaskHandleIndex=0x00ffffff; |
|
54 const TInt KSizeHandleIndex=3; |
|
55 // |
|
56 const TInt KTocDeltaCap = 64; //up to 64 entries in a delta TOC |
|
57 const TInt KTocDeltaMagic = 2; |
|
58 const TInt KMaxTocDeltaMagic = KMaxTUint16; |
|
59 const TInt KTocDelta=KHandleInvalid; |
|
60 // |
|
61 const TInt KOffsetTocHeader=-12; |
|
62 const TInt KSizeTocEntry=5; //base toc entry size is 5 bytes (when stored in the file, 8 bytes when presented in memory) |
|
63 const TInt KSizeTocDeltaEntry=8;//delta toc entry size is 8 bytes |
|
64 const TInt KSizeTocDeltaExtra=7; |
|
65 const TInt KElementsTocBuf=48; |
|
66 const TInt KBackTocBuf=20*KSizeTocEntry; |
|
67 const TInt KSizeTocBuf=KElementsTocBuf*KSizeTocEntry; |
|
68 |
|
69 enum TFrameType16 |
|
70 { |
|
71 EFrameFree16=0x0000, |
|
72 EFrameData16=0x4000, |
|
73 EFrameDescriptive16=0x8000, |
|
74 EFrameContinuation16=0xc000 |
|
75 }; |
|
76 typedef TUint16 TFrameDes16; |
|
77 const TInt KSizeFrameDes16=sizeof(TFrameDes16); |
|
78 const TInt KShiftFrameDes16=1; |
|
79 // |
|
80 const TInt KMaskFrame16=0xffff; |
|
81 const TInt KMaskFrameType16=0xc000; |
|
82 #if defined(__SMALL_FRAME) |
|
83 const TInt KMaskFrameLength16=0xf; |
|
84 const TInt KShiftFrameLength16=4; |
|
85 #else |
|
86 const TInt KMaskFrameLength16=0x3fff; |
|
87 const TInt KShiftFrameLength16=14; |
|
88 #endif |
|
89 // |
|
90 const TInt KFrameOpen16=0; |
|
91 const TInt KFrameMinLength16=1; |
|
92 const TInt KFrameMaxLength16=KMaskFrameLength16; |
|
93 const TInt KFrameFullLength16=KMaskFrameLength16+1; |
|
94 // |
|
95 const TInt KFrameNonexistent16=-1; |
|
96 |
|
97 TUint32 frame2File(TUint32 anOffset) |
|
98 { |
|
99 // The frame offset appears to be to calculated as an offset into |
|
100 // a series of maximal length frames. Each maximal frame can hold |
|
101 // 0x4000 bytes of data and has a 2 byte header. Therefore a frame |
|
102 // offset of x needs an extra 2 bytes for each maximal frame. The |
|
103 // base is the first byte of the payload of the first frame, so we |
|
104 // do not need to allow for the header of the first frame. |
|
105 // |
|
106 // anOffset>>KShiftFrameLength16 gives the number of maximal |
|
107 // frames. The left shift multiples by 2 to give minimum space |
|
108 // required for frame headers. Adding to the original gives the |
|
109 // file offset. |
|
110 // |
|
111 // This logic is still used even if space for the target frame is |
|
112 // really ocupied by a series of smaller frames. |
|
113 anOffset += (anOffset>>KShiftFrameLength16<<KShiftFrameDes16); |
|
114 |
|
115 // Add 32 to allow for file header |
|
116 anOffset += KBaseOffset; |
|
117 return anOffset; |
|
118 } |
|
119 |
|
120 TUint32 file2Frame(TUint32 aFileOffset) |
|
121 { |
|
122 // subtract 32 to allow for file header |
|
123 aFileOffset -= KBaseOffset; |
|
124 |
|
125 // File offset is to the first byte of payload of a stream. We |
|
126 // need to remove the 2 byte frame header for the (theoretical) |
|
127 // maximal length frames before it. |
|
128 |
|
129 // Calculate the number of (theoretical) maximal length frames before the file position |
|
130 // n = aFileOffset/0x4002 |
|
131 TInt n=aFileOffset/(KFrameFullLength16+KSizeFrameDes16); |
|
132 |
|
133 // Subtract the frame header length for each maximal frame |
|
134 aFileOffset -= n<<KShiftFrameDes16; |
|
135 |
|
136 return aFileOffset; |
|
137 } |
|
138 |
|
139 |
|
140 |
|
141 //TPermanentStoreHeader class. |
|
142 // |
|
143 //Represents the data kept in the permanent store file header. |
|
144 //Data members: |
|
145 // - iBackup - "backup TOC reference", 32-bits integer, which keeps the 31-bit file offset of the backup TOC. |
|
146 // Plays important role in the "store commit" procedure. |
|
147 // The LSB is a "dirty" bit. If during the store opening phase the dirty bit is found to be set, |
|
148 // then it means - the previous "store commit" operation has not been completed successfully and |
|
149 // the backup TOC shall be used instead of the TOC; |
|
150 // - iHandle - 32-bit stream handle (MSB - invalid/deleted, 3 bits - unused, 4 bits - generation counter, 24 bits - stream handle). |
|
151 // Plays important role in the "stream relocation" procedure during store compaction. |
|
152 // iHandle keeps the handle of the stream being relocated, so if the commit phase fails, the original stream entry |
|
153 // can be restored at the moment when the store is reopened; |
|
154 // - iRef - Current "TOC reference". Represents a file offset, where the current TOC is; |
|
155 // - iCrc - 16-bit CRC, protecting iBackup, iHandle, iRef; |
|
156 class TPermanentStoreHeader |
|
157 { |
|
158 public: |
|
159 TPermanentStoreHeader() : iBackup(0), iHandle(0), iRef(0), iCrc(0) {} |
|
160 TUint8* Ptr(); |
|
161 const TUint8* Ptr() const; |
|
162 TBool IsValid() const; |
|
163 // |
|
164 TPermanentStoreHeader(TInt aToc); |
|
165 TPermanentStoreHeader(TInt aBackupToc,TInt aHandle,TInt aReference); |
|
166 // |
|
167 TBool IsDirty() const; |
|
168 void MarkDirty(); |
|
169 void SetBackupToc(TInt aBackupToc); |
|
170 TInt BackupToc() const; |
|
171 // |
|
172 TInt Handle() const; |
|
173 TInt Reference() const; |
|
174 private: |
|
175 void Set(TInt aBackupToc,TInt aHandle,TInt aReference); |
|
176 private: |
|
177 TUint32 iBackup; |
|
178 TInt32 iHandle; |
|
179 TInt32 iRef; |
|
180 TUint16 iCrc; |
|
181 public: |
|
182 // Changes for port |
|
183 void InternalizeL(RReadStream &aStream); |
|
184 void ExternalizeL(RWriteStream &aStream) const; |
|
185 }; |
|
186 |
|
187 // Class TPermanentStoreHeader |
|
188 TUint8* TPermanentStoreHeader::Ptr() |
|
189 {return REINTERPRET_CAST(TUint8*,&iBackup);} |
|
190 const TUint8* TPermanentStoreHeader::Ptr() const |
|
191 {return REINTERPRET_CAST(const TUint8*,&iBackup);} |
|
192 |
|
193 |
|
194 TPermanentStoreHeader::TPermanentStoreHeader(TInt aToc) |
|
195 {Set(aToc,0,aToc);} |
|
196 |
|
197 TPermanentStoreHeader::TPermanentStoreHeader(TInt aBackupToc,TInt aHandle,TInt aReference) |
|
198 { |
|
199 __ASSERT_DEBUG(aHandle!=0,User::Invariant()); |
|
200 Set(aBackupToc,aHandle,aReference); |
|
201 } |
|
202 |
|
203 TBool TPermanentStoreHeader::IsDirty() const |
|
204 { |
|
205 return iBackup&0x1; |
|
206 } |
|
207 |
|
208 void TPermanentStoreHeader::MarkDirty() |
|
209 { |
|
210 iBackup|=0x1; |
|
211 } |
|
212 |
|
213 void TPermanentStoreHeader::SetBackupToc(TInt aBackupToc) |
|
214 { |
|
215 __ASSERT_DEBUG(aBackupToc>=0,User::Invariant()); |
|
216 iBackup=TUint32(aBackupToc)<<1; |
|
217 } |
|
218 |
|
219 TInt TPermanentStoreHeader::BackupToc() const |
|
220 { |
|
221 return iBackup>>1; |
|
222 } |
|
223 |
|
224 TInt TPermanentStoreHeader::Handle() const |
|
225 { |
|
226 return iHandle; |
|
227 } |
|
228 TInt TPermanentStoreHeader::Reference() const |
|
229 { |
|
230 return iRef; |
|
231 } |
|
232 |
|
233 |
|
234 TBool TPermanentStoreHeader::IsValid() const |
|
235 { |
|
236 if (IsDirty()) |
|
237 return EFalse; |
|
238 |
|
239 TUint16 crc=0; |
|
240 Mem::Crc(crc,Ptr(),_FOFF(TPermanentStoreHeader,iCrc)); |
|
241 |
|
242 return crc==iCrc; |
|
243 } |
|
244 |
|
245 //Sets the "backup TOC ref", "handle" and "TOC ref" in current TPermanentStoreHeader object. |
|
246 //16-bit CRC is calculated, based on the values of the input parameters, and stored together with them in the |
|
247 //TPermanentStoreHeader object. |
|
248 void TPermanentStoreHeader::Set(TInt aBackupToc,TInt aHandle,TInt aReference) |
|
249 { |
|
250 iBackup=TUint32(aBackupToc)<<1; |
|
251 iHandle=aHandle; |
|
252 iRef=aReference; |
|
253 iCrc=0; |
|
254 Mem::Crc(iCrc,Ptr(),_FOFF(TPermanentStoreHeader,iCrc)); |
|
255 __ASSERT_DEBUG(IsValid(),User::Invariant()); |
|
256 } |
|
257 |
|
258 |
|
259 void TPermanentStoreHeader::InternalizeL(RReadStream &aStream) |
|
260 { |
|
261 aStream >> iBackup; |
|
262 aStream >> iHandle; |
|
263 aStream >> iRef; |
|
264 aStream >> iCrc; |
|
265 } |
|
266 |
|
267 void TPermanentStoreHeader::ExternalizeL(RWriteStream &aStream) const |
|
268 { |
|
269 aStream << iBackup; |
|
270 aStream << iHandle; |
|
271 aStream << iRef; |
|
272 aStream << iCrc; |
|
273 } |
|
274 |
|
275 struct TocHeader |
|
276 { |
|
277 TInt32 iPrimary; |
|
278 TInt32 iAvail; |
|
279 TUint32 iCount; |
|
280 void ExternalizeL(RWriteStream &aStream) const; |
|
281 void InternalizeL(RReadStream &aStream); |
|
282 }; |
|
283 |
|
284 void TocHeader::ExternalizeL(RWriteStream &aStream) const |
|
285 { |
|
286 aStream << iPrimary; |
|
287 aStream << iAvail; |
|
288 aStream << iCount; |
|
289 } |
|
290 |
|
291 void TocHeader::InternalizeL(RReadStream &aStream) |
|
292 { |
|
293 aStream >> iPrimary; |
|
294 aStream >> iAvail; |
|
295 aStream >> iCount; |
|
296 } |
|
297 |
|
298 struct STocEntry |
|
299 { |
|
300 TInt32 handle; |
|
301 TInt32 ref; |
|
302 void ExternalizeL(RWriteStream &aStream) const; |
|
303 void InternalizeL(RReadStream &aStream); |
|
304 }; |
|
305 |
|
306 |
|
307 void STocEntry::ExternalizeL(RWriteStream &aStream) const |
|
308 { |
|
309 aStream.WriteL((TUint8*)&handle + KSizeHandleIndex, KSizeTocEntry); |
|
310 } |
|
311 |
|
312 void STocEntry::InternalizeL(RReadStream &aStream) |
|
313 { |
|
314 aStream.ReadL((TUint8*)&handle + KSizeHandleIndex, KSizeTocEntry); |
|
315 } |
|
316 |
|
317 |
|
318 CStreamStore::~CStreamStore() |
|
319 { |
|
320 } |
|
321 |
|
322 |
|
323 TStreamId CPersistentStore::Root() |
|
324 { |
|
325 return iRoot; |
|
326 } |
|
327 |
|
328 void CPersistentStore::SetRootL(TStreamId anId) |
|
329 { |
|
330 iRoot = anId; |
|
331 } |
|
332 |
|
333 void CFileStore::SetTypeL(const TUidType& aType) |
|
334 { |
|
335 if(aType != KPermanentFileStoreLayoutUid) FatalError(); |
|
336 } |
|
337 |
|
338 |
|
339 CFileStore *CPermanentFileStore::ReplaceLC(RFs &aFs, const TDesC &aName, TUint aFileMode) |
|
340 { |
|
341 (void) aFs; |
|
342 return new CPermanentFileStore(aName, aFileMode); |
|
343 } |
|
344 |
|
345 CPermanentFileStore* CPermanentFileStore::OpenLC(RFs& aFs,const TDesC& aName,TUint aFileMode) |
|
346 { |
|
347 (void) aFs; |
|
348 CPermanentFileStore *pfs = new CPermanentFileStore(aName, aFileMode); |
|
349 pfs->ReadInData(); |
|
350 return pfs; |
|
351 } |
|
352 |
|
353 CPermanentFileStore::CPermanentFileStore(const TDesC& aName,TUint aFileMode) |
|
354 : iWritable(false), iFileIn(), iFileOut(), iLastStreamIdCreated(0), |
|
355 iStreams() |
|
356 { |
|
357 TBuf8<KMaxName> utf8Name; |
|
358 utf8Name.Copy(aName); |
|
359 |
|
360 std::string name((const char *)utf8Name.Ptr(), utf8Name.Length()); |
|
361 |
|
362 if(aFileMode & EFileWrite) |
|
363 { |
|
364 iFileOut.reset(new FileWriteStream(name)); |
|
365 iWritable = true; |
|
366 } |
|
367 else |
|
368 { |
|
369 iFileIn.reset(new FileReadStream(name)); |
|
370 } |
|
371 } |
|
372 |
|
373 CPermanentFileStore::~CPermanentFileStore() |
|
374 { |
|
375 while(!iStreams.empty()) |
|
376 { |
|
377 MemStreamBuf *p = (*iStreams.begin()).second; |
|
378 iStreams.erase(iStreams.begin()); |
|
379 delete p; |
|
380 } |
|
381 } |
|
382 |
|
383 |
|
384 MemStreamBuf *CPermanentFileStore::CreateStoreWriteStream() |
|
385 { |
|
386 TStreamId id = ++iLastStreamIdCreated; |
|
387 MemStreamBuf *handler = new MemStreamBuf(*this, id); |
|
388 |
|
389 MemStreamBufPtrMap::value_type value(id, handler); |
|
390 std::pair<MemStreamBufPtrMap::iterator, bool> ret = iStreams.insert(value); |
|
391 |
|
392 if(!ret.second) |
|
393 { |
|
394 // Insert failed |
|
395 FatalError(); |
|
396 } |
|
397 |
|
398 |
|
399 return handler; |
|
400 } |
|
401 |
|
402 MemStreamBuf *CPermanentFileStore::CreateStoreReadStream(TStreamId aId) const |
|
403 { |
|
404 MemStreamBufPtrMap::const_iterator it = iStreams.find(TUint32(aId)); |
|
405 if(it == iStreams.end()) |
|
406 { |
|
407 // Lookup failed |
|
408 dbg << Log::Indent() << "StreamId 0x" << aId << " does not exist in store!" << Log::Endl(); |
|
409 FatalError(); |
|
410 } |
|
411 return (*it).second; |
|
412 } |
|
413 |
|
414 bool CPermanentFileStore::Writable() const |
|
415 { |
|
416 return iWritable; |
|
417 } |
|
418 |
|
419 |
|
420 |
|
421 void CPermanentFileStore::CommitL() |
|
422 { |
|
423 if(!iWritable) FatalError(); |
|
424 |
|
425 TCheckedUid id(KPermanentFileStoreLayoutUid); |
|
426 |
|
427 *iFileOut << id; |
|
428 |
|
429 // Write an empty header, we will correct the fields later |
|
430 TPermanentStoreHeader tmpheader(0); |
|
431 *iFileOut << tmpheader; |
|
432 |
|
433 // |
|
434 // Now write out the streams |
|
435 // |
|
436 std::vector<TUint> streamOffsets; |
|
437 for(MemStreamBufPtrMap::const_iterator streamIt = iStreams.begin(); |
|
438 streamIt != iStreams.end(); |
|
439 ++streamIt) |
|
440 { |
|
441 const MemStreamBuf::StreamData &streamData((*streamIt).second->GetData()); |
|
442 |
|
443 // Record the offset to the first byte of the payload for use in the TOC |
|
444 streamOffsets.push_back(TUint32(iFileOut->iSnk->TellL(MStreamBuf::EWrite))+KSizeFrameDes16); |
|
445 |
|
446 TUint32 dataAvailable = streamData.size(); |
|
447 MemStreamBuf::StreamData::const_iterator dataIt = streamData.begin(); |
|
448 TUint32 currentType = EFrameData16; |
|
449 while(dataAvailable) |
|
450 { |
|
451 TUint32 toWrite; |
|
452 TFrameDes16 frame; |
|
453 |
|
454 TUint32 fileOffset = TUint32(iFileOut->iSnk->TellL(MStreamBuf::EWrite))+KSizeFrameDes16; |
|
455 TUint32 frameOffset = file2Frame(fileOffset); |
|
456 TUint32 nextAnchor = ((frameOffset + KFrameFullLength16) & ~KMaskFrameLength16); |
|
457 if(dataAvailable >= (nextAnchor-frameOffset)) |
|
458 { |
|
459 // We have enough data to write an "Open" frame to |
|
460 // take the frame offset up to the next multiple of |
|
461 // 0x4000 |
|
462 toWrite = (nextAnchor-frameOffset); |
|
463 frame = currentType | KFrameOpen16; |
|
464 } |
|
465 else |
|
466 { |
|
467 // Write a normal frame |
|
468 toWrite = (dataAvailable < TUint32(KMaskFrameLength16)) ? (dataAvailable) : (KMaskFrameLength16); |
|
469 frame = currentType | toWrite; |
|
470 } |
|
471 |
|
472 // Write frame |
|
473 *iFileOut << frame; |
|
474 // Write payload |
|
475 while(toWrite--) |
|
476 { |
|
477 *iFileOut << *dataIt; |
|
478 ++dataIt; |
|
479 --dataAvailable; |
|
480 } |
|
481 // Set type of next frame to continuation |
|
482 currentType = EFrameContinuation16; |
|
483 } |
|
484 } |
|
485 |
|
486 // |
|
487 // Now write the TOC |
|
488 // |
|
489 TInt tocLength = sizeof(TocHeader) + (iStreams.size() * KSizeTocEntry); |
|
490 // Check toc frame length is not too long |
|
491 if(tocLength > KMaskFrameLength16) |
|
492 { |
|
493 FatalError(); |
|
494 } |
|
495 // Write TOC frame |
|
496 TFrameDes16 frame = tocLength | EFrameDescriptive16; |
|
497 *iFileOut << frame; |
|
498 |
|
499 TStreamPos pos = iFileOut->iSnk->TellL(MStreamBuf::EWrite); |
|
500 |
|
501 // First the header |
|
502 TUint32 tocFrameOffset = file2Frame(pos); |
|
503 TUint32 tocCookedFrameOffset = tocFrameOffset - KOffsetTocHeader; |
|
504 |
|
505 TocHeader tocheader; |
|
506 tocheader.iPrimary = iRoot; |
|
507 tocheader.iAvail = 0; |
|
508 tocheader.iCount = iStreams.size(); |
|
509 *iFileOut << tocheader; |
|
510 |
|
511 // Now write the TOC entries |
|
512 for(TUint i = 0; i < streamOffsets.size(); ++i) |
|
513 { |
|
514 STocEntry tocEntry = { 0, file2Frame(streamOffsets[i]) }; |
|
515 *iFileOut << tocEntry; |
|
516 } |
|
517 |
|
518 |
|
519 // |
|
520 // Now overwrite the header with one containing the correct master |
|
521 // TOC offset |
|
522 // |
|
523 TPermanentStoreHeader realheader(tocCookedFrameOffset); |
|
524 // For some reason the real store code creates a header with a |
|
525 // checksum which assumes iBackup == iRef but the iBackup value on |
|
526 // disk is set to 0... |
|
527 realheader.SetBackupToc(0); |
|
528 iFileOut->iSnk->SeekL(MStreamBuf::EWrite, EStreamBeginning, sizeof(TCheckedUid)); |
|
529 *iFileOut << realheader; |
|
530 |
|
531 |
|
532 iFileOut->Close(); |
|
533 } |
|
534 |
|
535 void CPermanentFileStore::ReadInData() |
|
536 { |
|
537 prog << Log::Indent() << "Reading store" << Log::Endl(); |
|
538 AutoIndent ai(prog); |
|
539 |
|
540 TUint lastStreamIndex = 0; |
|
541 TCheckedUid id; |
|
542 |
|
543 *iFileIn >> id; |
|
544 |
|
545 if(id.UidType() != KPermanentFileStoreLayoutUid) |
|
546 { |
|
547 dbg << Log::Indent() << "Invalid store" << Log::Endl(); |
|
548 FatalError(); |
|
549 } |
|
550 |
|
551 TPermanentStoreHeader header; |
|
552 |
|
553 *iFileIn >> header; |
|
554 |
|
555 // - If the dirty bit is set, the backup TOC will be used; |
|
556 // - If the dirty bit is not set, and the backup TOC ref is not the same as the TOC ref, |
|
557 // then it means the the backup TOC ref has not been written successfully, so the TOC ref will be used; |
|
558 TInt toc=header.BackupToc(); |
|
559 if (!header.IsDirty()) |
|
560 { |
|
561 prog << Log::Indent() << "Store header is clean" << Log::Endl(); |
|
562 TInt handle=header.Handle(); |
|
563 TInt ref=header.Reference(); |
|
564 if (handle==0&&toc!=ref) |
|
565 { // toc pointer not backed up, validate as if it was |
|
566 toc=ref; |
|
567 // iState|=EBackup; |
|
568 header.SetBackupToc(toc); |
|
569 } |
|
570 if (!header.IsValid()) // not a permanent store or damaged beyond recognition |
|
571 { |
|
572 dbg << Log::Indent() << "Store header checksum failed check1" << Log::Endl(); |
|
573 __LEAVE(KErrNotSupported); |
|
574 } |
|
575 |
|
576 // |
|
577 if (toc<0||((handle&~KMaskStreamIdValue)!=0&&handle!=KHandleTocBase)||ref<0||(handle!=0&&ref>=toc+KOffsetTocHeader)) |
|
578 { |
|
579 dbg << Log::Indent() << "Store header fields invalid" << Log::Endl(); |
|
580 __LEAVE(KErrCorrupt); // integrity compromised |
|
581 } |
|
582 // |
|
583 // iReloc=handle; |
|
584 // iTarget=ref; |
|
585 } |
|
586 else |
|
587 { |
|
588 dbg << Log::Indent() << "Store header dirty" << Log::Endl(); |
|
589 } |
|
590 |
|
591 // |
|
592 // if (iToc!=0 && iToc!=toc) // refresh produced a different toc |
|
593 // __LEAVE(KErrCorrupt); |
|
594 // iToc=toc; |
|
595 |
|
596 |
|
597 if(!header.IsValid()) |
|
598 { |
|
599 dbg << Log::Indent() << "Store header checksum failed check2" << Log::Endl(); |
|
600 FatalError(); |
|
601 } |
|
602 |
|
603 // All offset values are to the payload of frame structures (see RFrame16Buf) |
|
604 // Convert to a file offset. |
|
605 TInt tocFileOffset = frame2File(toc + KOffsetTocHeader); |
|
606 prog << Log::Indent() << "TOC file offset 0x" << tocFileOffset << Log::Endl(); |
|
607 |
|
608 // nb. We do not validate the length of the "descriptive" stream |
|
609 // which contains the TocHeader (aka STocHead) and the table of stream offsets. |
|
610 |
|
611 iFileIn->iSrc->SeekL(MStreamBuf::ERead, EStreamBeginning, tocFileOffset); |
|
612 TocHeader h; |
|
613 *iFileIn >> h; |
|
614 if ((h.iPrimary&~(KMaskStreamIdValue|static_cast<TUint>(KTocDelta)))!=0|| |
|
615 h.iAvail>0||(h.iAvail&KMaskHandleClear)!=0||(h.iCount&~KMaskHandleIndex)!=0) |
|
616 { |
|
617 // Corrupt |
|
618 dbg << Log::Indent() << "Corrupt TOC in input file" << Log::Endl(); |
|
619 FatalError(); |
|
620 } |
|
621 std::set<TUint32> streamIdsReadExGenField; // IDs of streams already read, EXCLUDING generation field |
|
622 if (h.iPrimary & KTocDelta) |
|
623 { |
|
624 AutoIndent ai(prog); |
|
625 prog << Log::Indent() << "Found Delta TOC" << Log::Endl(); |
|
626 // Process TOC-delta |
|
627 TInt oldToc = toc; |
|
628 // Find and read in the delta entries and then continue to read in the base entries |
|
629 // Read offset to base TOC |
|
630 iFileIn->iSrc->ReadL(&toc, sizeof(toc)); |
|
631 // All offset values are to the payload of frame structures (see RFrame16Buf) |
|
632 // Convert to a file offset. |
|
633 tocFileOffset = frame2File(toc + KOffsetTocHeader); |
|
634 |
|
635 if((tocFileOffset < 0) || (tocFileOffset>oldToc)) |
|
636 { |
|
637 dbg << Log::Indent() << "Invalid TOC in delta TOC" << Log::Endl(); |
|
638 FatalError(); // Corrupt |
|
639 } |
|
640 |
|
641 // Read/discard the magic value - Not sure what this should be |
|
642 TUint16 magic; |
|
643 iFileIn->iSrc->ReadL(&magic, sizeof(magic)); |
|
644 |
|
645 // Read count of delta toc entries |
|
646 TInt8 n; |
|
647 iFileIn->iSrc->ReadL(&n, sizeof(n)); |
|
648 |
|
649 prog << Log::Indent() << "Delta TOC entries " << int(n) << Log::Endl(); |
|
650 for(int deltaTocEntry=1; deltaTocEntry <= n; ++deltaTocEntry) |
|
651 { |
|
652 AutoIndent ai(prog); |
|
653 prog << Log::Indent() << "Delta TOC entry " << deltaTocEntry << Log::Endl(); |
|
654 |
|
655 STocEntry e = {0,0}; |
|
656 // Read delta toc entry. |
|
657 // |
|
658 // The main TOC entries are truncated to 5 bytes so only |
|
659 // include the flag bits of the handle and not the stream. |
|
660 // They gain streamids starting from 1. |
|
661 // |
|
662 // The delta TOC contains complete stream IDs, and these |
|
663 // entries take precedence over the matching (implicitly |
|
664 // numbered) entry in the base TOC. |
|
665 iFileIn->iSrc->ReadL(&e, sizeof(e)); |
|
666 |
|
667 if ((e.handle&KMaskHandleClear)!=0 || |
|
668 e.handle>=0 && (e.ref<KFrameNonexistent16) || |
|
669 e.handle<0 && (e.ref>0 || (e.ref&KMaskHandleClear)!=0)) |
|
670 { |
|
671 dbg << Log::Indent() << "Invalid delta TOC entry" << Log::Endl(); |
|
672 __LEAVE(KErrCorrupt); |
|
673 FatalError(); |
|
674 } |
|
675 |
|
676 if(e.handle & KHandleInvalid) |
|
677 { |
|
678 // Stream marked as deleted, skip it |
|
679 prog << Log::Indent() << "Delta TOC entry marked as deleted" << Log::Endl(); |
|
680 continue; |
|
681 } |
|
682 |
|
683 // We do not deal with any other special cases correctly |
|
684 if(((e.handle&(KMaskHandleHash-KMaskHandleGen)) != 0) || (e.ref < 0)) |
|
685 { |
|
686 dbg << Log::Indent() << "store-- does not support handle flags 0x" << e.handle << "in delta toc" << Log::Endl(); |
|
687 FatalError(); |
|
688 } |
|
689 |
|
690 prog << Log::Indent() |
|
691 << "streamId 0x" << e.handle << " frame offset 0x" << e.ref |
|
692 << " file offset 0x" << frame2File(e.ref) << Log::Endl(); |
|
693 |
|
694 if(!streamIdsReadExGenField.insert(e.handle & ~KMaskHandleHash).second) |
|
695 { |
|
696 dbg << Log::Indent() << "store-- corrupt input? Multiple entries for stream ID " << (e.handle & ~KMaskHandleHash) << "encountered in delta toc!" << Log::Endl(); |
|
697 FatalError(); |
|
698 } |
|
699 |
|
700 |
|
701 // Remember where we are... |
|
702 TStreamPos here = iFileIn->iSrc->TellL(MStreamBuf::ERead); |
|
703 // Read the stream frame |
|
704 ReadStreamData(e.handle, e.ref); |
|
705 // restore position to continue reading delta toc |
|
706 iFileIn->iSrc->SeekL(MStreamBuf::ERead, EStreamBeginning, here); |
|
707 } |
|
708 } |
|
709 |
|
710 iRoot = TInt(h.iPrimary) & ~KTocDelta; |
|
711 prog << Log::Indent() << "Root stream ID is " << iRoot << Log::Endl(); |
|
712 |
|
713 prog << Log::Indent() << "Processing main TOC at file offset 0x" << tocFileOffset << Log::Endl(); |
|
714 |
|
715 for(TUint tocIndex=0; tocIndex < h.iCount; ++tocIndex) |
|
716 { |
|
717 // Read in streams |
|
718 TStreamId baseStreamId = ++lastStreamIndex; |
|
719 prog << Log::Indent() << "Entry " << std::dec << baseStreamId << std::hex << Log::Endl(); |
|
720 AutoIndent ai(prog); |
|
721 |
|
722 // Check if we have already read in this stream id from the delta toc |
|
723 // Note we only compare the base of the stream ID excluding the generation field. |
|
724 if(streamIdsReadExGenField.find(baseStreamId) != streamIdsReadExGenField.end()) |
|
725 { |
|
726 prog << Log::Indent() << "Already read from delta TOC" << Log::Endl(); |
|
727 continue; // Already read from delta toc |
|
728 } |
|
729 |
|
730 // Seek to the STocEntry for the stream |
|
731 iFileIn->iSrc->SeekL(MStreamBuf::ERead, EStreamBeginning, tocFileOffset+sizeof(TocHeader)+KSizeTocEntry*(tocIndex)); |
|
732 |
|
733 |
|
734 STocEntry e = {0,0}; |
|
735 // Only the last 5 bytes of the entry are saved to disk. |
|
736 // Because we are little endian this is the MSB of the handle and the whole ref. |
|
737 *iFileIn >> e; |
|
738 |
|
739 if ((e.handle&KMaskHandleClear)!=0 || |
|
740 e.handle>=0 && (e.ref<KFrameNonexistent16) || |
|
741 e.handle<0 && (e.ref>0 || (e.ref&KMaskHandleClear)!=0)) |
|
742 { |
|
743 __LEAVE(KErrCorrupt); |
|
744 FatalError(); |
|
745 } |
|
746 |
|
747 if(e.handle & KHandleInvalid) |
|
748 { |
|
749 // Stream deleted, skip it |
|
750 prog << Log::Indent() << "Marked as deleted" << Log::Endl(); |
|
751 continue; |
|
752 } |
|
753 |
|
754 // We do not deal with any other special cases correctly |
|
755 if(((e.handle & (KMaskHandleHash-KMaskHandleGen)) != 0) || (e.ref < 0)) |
|
756 { |
|
757 dbg << Log::Indent() << "store-- does not support handle flags 0x" << e.handle << "in main toc" << Log::Endl(); |
|
758 FatalError(); |
|
759 } |
|
760 |
|
761 TStreamId streamId = baseStreamId | e.handle; |
|
762 if(!streamIdsReadExGenField.insert(baseStreamId).second) |
|
763 { |
|
764 dbg << Log::Indent() << "store-- internal error for stream ID " << baseStreamId << "encountered in delta toc!" << Log::Endl(); |
|
765 FatalError(); |
|
766 } |
|
767 |
|
768 // Read the stream frame |
|
769 // prog << Log::Indent() << "Reading stream 0x" << streamId << " frame offset 0x" << e.ref << Log::Endl(); |
|
770 ReadStreamData(streamId, e.ref); |
|
771 } |
|
772 } |
|
773 |
|
774 |
|
775 void CPermanentFileStore::ReadStreamData(TStreamId aStreamId, TInt aFrameOffset) |
|
776 { |
|
777 TInt fileOffset = frame2File(aFrameOffset); |
|
778 TFrameDes16 frame; |
|
779 iFileIn->iSrc->SeekL(MStreamBuf::ERead, EStreamBeginning, fileOffset - sizeof(frame)); |
|
780 |
|
781 // Frame runs from fileOffset to fileOffset+2+frame |
|
782 std::auto_ptr<MemStreamBuf> apStream(new MemStreamBuf(*this, aStreamId)); |
|
783 |
|
784 enum { |
|
785 EFirst, EContinuation, ELast |
|
786 } state = EFirst; |
|
787 |
|
788 while(state != ELast) |
|
789 { |
|
790 iFileIn->iSrc->ReadL(&frame, sizeof(frame)); |
|
791 |
|
792 // Store uses offsets to the first byte of the payload of a frame, so that is what we display |
|
793 TUint32 fileOffset = iFileIn->iSrc->TellL(MStreamBuf::ERead); |
|
794 prog << Log::Indent() << "ReadStreamData State " << int(state) << " offset " << file2Frame(fileOffset) << "[" << fileOffset << "]" << Log::Endl(); |
|
795 |
|
796 TUint32 frameType = (frame & KMaskFrameType16); |
|
797 if(frameType == EFrameFree16) |
|
798 { |
|
799 dbg << Log::Indent() << "Encountered a deleted frame in data stream" << Log::Endl(); |
|
800 FatalError(); |
|
801 } |
|
802 |
|
803 if((frameType == EFrameData16) && (state != EFirst)) |
|
804 { |
|
805 dbg << Log::Indent() << "Non-continuation frame encountered in middle of data stream" << Log::Endl(); |
|
806 FatalError(); |
|
807 } |
|
808 |
|
809 if(frameType == EFrameDescriptive16) |
|
810 { |
|
811 dbg << Log::Indent() << "Descriptive frame encountered in data stream" << Log::Endl(); |
|
812 FatalError(); |
|
813 } |
|
814 |
|
815 if((frameType == EFrameContinuation16) && (state != EContinuation)) |
|
816 { |
|
817 dbg << Log::Indent() << "Continuation frame encountered at start of stream" << Log::Endl(); |
|
818 FatalError(); |
|
819 } |
|
820 |
|
821 TInt len = (frame & KMaskFrameLength16); |
|
822 if (len == KFrameOpen16) |
|
823 { |
|
824 prog << Log::Indent() << "\"Open\" frame length" << Log::Endl(); |
|
825 len = KFrameFullLength16 - file2Frame(fileOffset); |
|
826 state = EContinuation; |
|
827 } |
|
828 else |
|
829 { |
|
830 state = ELast; |
|
831 } |
|
832 |
|
833 prog << Log::Indent() << "Type 0x" << frameType << " length " << std::dec << len << std::hex << Log::Endl(); |
|
834 apStream->AppendFromFile(iFileIn->iSrc, len); |
|
835 }; |
|
836 |
|
837 MemStreamBufPtrMap::value_type value(aStreamId, apStream.get()); |
|
838 std::pair<MemStreamBufPtrMap::iterator, bool> ret = iStreams.insert(value); |
|
839 if(!ret.second) |
|
840 { |
|
841 // Insert failed |
|
842 FatalError(); |
|
843 } |
|
844 |
|
845 apStream.release(); |
|
846 } |
|
847 |
|
848 RReadStream::RReadStream() |
|
849 : iSrc(0) |
|
850 { |
|
851 } |
|
852 |
|
853 void RReadStream::Close() |
|
854 { |
|
855 iSrc = false; |
|
856 } |
|
857 |
|
858 RStoreReadStream::RStoreReadStream() |
|
859 : RReadStream() |
|
860 { |
|
861 } |
|
862 |
|
863 |
|
864 void RStoreReadStream::OpenLC(const CStreamStore& aStore, TStreamId aId) |
|
865 { |
|
866 iSrc = aStore.CreateStoreReadStream(aId); |
|
867 } |
|
868 |
|
869 |
|
870 |
|
871 RWriteStream::RWriteStream() |
|
872 : iSnk(0) |
|
873 { |
|
874 } |
|
875 |
|
876 |
|
877 |
|
878 |
|
879 |
|
880 TStreamId RStoreWriteStream::CreateLC(CStreamStore& aStore) |
|
881 { |
|
882 MemStreamBuf *s = aStore.CreateStoreWriteStream(); |
|
883 iSnk = s; |
|
884 return s->StreamId(); |
|
885 } |
|
886 |
|
887 EXPORT_C void RReadStream::ReadL(TDes8& aDes) |
|
888 /** Reads sufficient data from this stream to fill the specified 8 bit descriptor up to its maximum length. |
|
889 No other information is read from this read stream. |
|
890 |
|
891 @param aDes A reference to a modifiable descriptor which is to receive the data read from this stream. Passing the build |
|
892 independent type TDes& allows the compiler to choose the appropriate ReadL() variant (i.e the 8 bit or the 16 bit) at build time.*/ |
|
893 { |
|
894 ReadL(aDes,aDes.MaxLength()); |
|
895 } |
|
896 |
|
897 EXPORT_C void RReadStream::ReadL(TDes8& aDes,TInt aLength) |
|
898 /** Reads data of specified length from this stream into the specified 8 bit descriptor. No other information is read |
|
899 from this stream. |
|
900 |
|
901 @param aDes A reference to a modifiable type descriptor which is to receive the data read from this stream. |
|
902 Passing the build independent type TDes& allows the compiler to choose the appropriate ReadL() variant (i.e the 8 bit |
|
903 or the 16 bit) at build time. |
|
904 @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.*/ |
|
905 { |
|
906 __ASSERT_DEBUG(aLength<=aDes.MaxLength(),Panic(EStreamReadBeyondEnd)); |
|
907 aDes.SetLength(aLength); |
|
908 ReadL((TUint8*)aDes.Ptr(),aLength); |
|
909 } |
|
910 |
|
911 #if 0 |
|
912 EXPORT_C void RReadStream::ReadL(TDes8& aDes,TChar aDelim) |
|
913 /** 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. |
|
914 The resulting data in aDes always includes the delimiter aDelim, if aDes is large enough. |
|
915 |
|
916 @param aDes A reference to a modifiable type descriptor which is to receive the data read from this stream. Passing |
|
917 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. |
|
918 @param aDelim The delimiter marking the end of the data in the stream.*/ |
|
919 |
|
920 { |
|
921 __ASSERT_DEBUG(iSrc!=NULL,Panic(EStreamNotOpen)); |
|
922 TUint8* ptr=(TUint8*)aDes.Ptr(); |
|
923 TDelimitedInput8 input(ptr,aDes.MaxLength(),aDelim); |
|
924 do |
|
925 { |
|
926 iSrc->ReadL(input); |
|
927 } while (!input.Done()); |
|
928 aDes.SetLength(input.Ptr()-ptr); |
|
929 } |
|
930 #endif |
|
931 |
|
932 EXPORT_C void RReadStream::ReadL(TUint8* aPtr,TInt aLength) |
|
933 /** Reads data of specified length from this stream into the location defined by the specified TUint8 pointer. |
|
934 |
|
935 @param aPtr The target location for the streamed in data. |
|
936 @param aLength The length of data to be streamed in.*/ |
|
937 { |
|
938 __ASSERT_DEBUG(aLength>=0,Panic(EStreamReadLengthNegative)); |
|
939 if (aLength==0) |
|
940 return; |
|
941 // void *p = NULL; |
|
942 __ASSERT_DEBUG(iSrc!=NULL,Panic(EStreamNotOpen)); |
|
943 TInt len=iSrc->ReadL(aPtr,aLength); |
|
944 __ASSERT_DEBUG(len>=0&&len<=aLength,Panic(EStreamReadInBreach)); |
|
945 if (len<aLength) |
|
946 __LEAVE(KErrEof); |
|
947 } |
|
948 |
|
949 EXPORT_C void RReadStream::ReadL(TInt aLength) |
|
950 /** Discards data of specified length read from this stream. |
|
951 |
|
952 @param aLength The length of data to be discarded from this read stream.*/ |
|
953 { |
|
954 __ASSERT_DEBUG(aLength>=0,Panic(EStreamReadLengthNegative)); |
|
955 if (aLength==0) |
|
956 return; |
|
957 // |
|
958 __ASSERT_DEBUG(iSrc!=NULL,Panic(EStreamNotOpen)); |
|
959 |
|
960 #if 1 |
|
961 iSrc->SeekL(MStreamBuf::ERead, EStreamMark, aLength); |
|
962 #else |
|
963 TNullInput input; |
|
964 TInt len=iSrc->ReadL(input,aLength); |
|
965 __ASSERT_DEBUG(len>=0&&len<=aLength,Panic(EStreamReadInBreach)); |
|
966 if (len<aLength) |
|
967 __LEAVE(KErrEof); |
|
968 #endif |
|
969 } |
|
970 |
|
971 EXPORT_C void RReadStream::ReadL(TDes16& aDes) |
|
972 /** Reads sufficient data from this stream to fill the specified 16 bit descriptor up to its maximum length. |
|
973 No other information is read from this read stream. |
|
974 |
|
975 @param aDes A reference to a modifiable type descriptor which is to receive the data read from this stream. Passing |
|
976 the build independent type TDes& allows the compiler to choose the appropriate ReadL() variant (i.e the 8 bit or the 16 |
|
977 bit) at build time.*/ |
|
978 { |
|
979 ReadL(aDes,aDes.MaxLength()); |
|
980 } |
|
981 |
|
982 EXPORT_C void RReadStream::ReadL(TDes16& aDes,TInt aLength) |
|
983 /** Reads data of specified length from this stream into the specified 16 bit descriptor. No other information is read from this stream. |
|
984 |
|
985 @param aDes A reference to a modifiable type descriptor which is to receive the data read from this stream. Passing the |
|
986 build independent type TDes& allows the compiler to choose the appropriate ReadL() variant (i.e the 8 bit or the 16 bit) |
|
987 at build time. |
|
988 @param aLength The length of data to be read from this stream. This value must be non-negative and must not be greater |
|
989 than the maximum length of the descriptor otherwise the function raises a USER 11 panic.*/ |
|
990 { |
|
991 __ASSERT_DEBUG(aLength<=aDes.MaxLength(),Panic(EStreamReadBeyondEnd)); |
|
992 aDes.SetLength(aLength); |
|
993 ReadL((TUint16*)aDes.Ptr(),aLength); |
|
994 } |
|
995 |
|
996 #if 0 |
|
997 EXPORT_C void RReadStream::ReadL(TDes16& aDes,TChar aDelim) |
|
998 /** Reads data from this stream into the 16 bit descriptor, until either the specified delimiter is encountered or |
|
999 the descriptor is filled to its maximum length. |
|
1000 The resulting data in aDes always includes the delimiter aDelim, if aDes is large enough. |
|
1001 |
|
1002 @param aDes A reference to a modifiable type descriptor which is to receive the data read from this stream. Passing |
|
1003 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. |
|
1004 @param aDelim The delimiter marking the end of the data in the stream.*/ |
|
1005 { |
|
1006 __ASSERT_DEBUG(iSrc!=NULL,Panic(EStreamNotOpen)); |
|
1007 TUint16* ptr=(TUint16*)aDes.Ptr(); |
|
1008 TDelimitedInput16 input(ptr,aDes.MaxLength(),aDelim); |
|
1009 do |
|
1010 { |
|
1011 iSrc->ReadL(input); |
|
1012 } while (!input.Done()); |
|
1013 aDes.SetLength(input.Ptr()-ptr); |
|
1014 } |
|
1015 #endif |
|
1016 |
|
1017 EXPORT_C void RReadStream::ReadL(TUint16* aPtr,TInt aLength) |
|
1018 /** Reads data of specified length from this stream into the specified 16 bit descriptor. |
|
1019 No other information is read from this stream. |
|
1020 |
|
1021 @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. |
|
1022 @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.*/ |
|
1023 { |
|
1024 __ASSERT_DEBUG(aLength>=0,Panic(EStreamReadLengthNegative)); |
|
1025 ReadL((TUint8*)aPtr,aLength<<1); // platform dependency |
|
1026 } |
|
1027 |
|
1028 EXPORT_C TInt8 RReadStream::ReadInt8L() |
|
1029 /** Internalises a TInt8 value The function reads an 8Â bit value from this stream |
|
1030 and interprets it as a TInt8. |
|
1031 |
|
1032 @return The 8 bit value read from this stream. */ |
|
1033 { |
|
1034 TInt8 val; |
|
1035 ReadL((TUint8*)&val,1); // platform dependency |
|
1036 return val; |
|
1037 } |
|
1038 |
|
1039 EXPORT_C TInt16 RReadStream::ReadInt16L() |
|
1040 /** Internalises a TInt16 value. The function reads a 16Â bit value from this stream |
|
1041 and interprets it as a TInt16. |
|
1042 |
|
1043 @return The 16 bit value read from this stream. */ |
|
1044 { |
|
1045 TInt16 val; |
|
1046 ReadL((TUint8*)&val,2); // platform dependency |
|
1047 return val; |
|
1048 } |
|
1049 |
|
1050 EXPORT_C TInt32 RReadStream::ReadInt32L() |
|
1051 /** Internalises a TInt32 value. The function reads a 32Â bit value from this stream |
|
1052 and interprets it as a TInt32. |
|
1053 |
|
1054 @return The 32Â bit value read from this stream. */ |
|
1055 { |
|
1056 TInt32 val; |
|
1057 ReadL((TUint8*)&val,4); // platform dependency |
|
1058 return val; |
|
1059 } |
|
1060 |
|
1061 EXPORT_C TUint8 RReadStream::ReadUint8L() |
|
1062 /** Internalises a TUint8 value. The function reads an 8Â bit value from this stream |
|
1063 and interprets it as a TUint8. |
|
1064 |
|
1065 @return The 8Â bit value read from this stream. */ |
|
1066 { |
|
1067 TUint8 val; |
|
1068 ReadL(&val,1); |
|
1069 return val; |
|
1070 } |
|
1071 |
|
1072 EXPORT_C TUint16 RReadStream::ReadUint16L() |
|
1073 /** Internalises a TUint16 value. The function reads a 16Â bit value from this |
|
1074 stream and interprets it as a TUint16. |
|
1075 |
|
1076 @return The 16Â bit value read from this stream. */ |
|
1077 { |
|
1078 TUint16 val; |
|
1079 ReadL((TUint8*)&val,2); // platform dependency |
|
1080 return val; |
|
1081 } |
|
1082 |
|
1083 EXPORT_C TUint32 RReadStream::ReadUint32L() |
|
1084 /** Internalises a TUint32 value. The function reads a 32Â bit value from this |
|
1085 stream and interprets it as a TUint32. |
|
1086 |
|
1087 @return The 32Â bit value read from this stream. */ |
|
1088 { |
|
1089 TUint32 val; |
|
1090 ReadL((TUint8*)&val,4); // platform dependency |
|
1091 return val; |
|
1092 } |
|
1093 |
|
1094 |
|
1095 EXPORT_C void RWriteStream::Close() |
|
1096 /** Commits data to the stream before freeing resources used by the stream. This |
|
1097 ensures that any buffered data is written to the stream. |
|
1098 |
|
1099 Note that the function cannot leave. Any errors arising from the attempt to |
|
1100 commit data to the stream are ignored. */ |
|
1101 { |
|
1102 if (iSnk==NULL) |
|
1103 return; |
|
1104 // |
|
1105 iSnk->Close(); |
|
1106 iSnk=NULL; |
|
1107 } |
|
1108 |
|
1109 EXPORT_C void RWriteStream::Release() |
|
1110 /** Frees resources before abandoning the stream. The function is called after |
|
1111 data has been committed to the stream. |
|
1112 |
|
1113 Note that if a cleanup item for the stream was placed on the cleanup stack |
|
1114 when the stream was opened (e.g by a call to RStoreWriteStreamss CreateLC(), |
|
1115 OpenLC(), ReplaceLC() or RDictionaryStores AssignLC() etc), then this function |
|
1116 need not be called explicitly; clean up is implicitly done by CleanupStack::PopAndDestroy(). */ |
|
1117 { |
|
1118 if (iSnk==NULL) |
|
1119 return; |
|
1120 // |
|
1121 iSnk->Release(); |
|
1122 iSnk=NULL; |
|
1123 } |
|
1124 |
|
1125 EXPORT_C void RWriteStream::CommitL() |
|
1126 /** Ensures that any buffered data is written to the stream. Once committed, it |
|
1127 is not possible to roll back the newly written data. */ |
|
1128 { |
|
1129 if (iSnk==NULL) |
|
1130 return; |
|
1131 // |
|
1132 iSnk->SynchL(); |
|
1133 } |
|
1134 |
|
1135 |
|
1136 EXPORT_C void RWriteStream::WriteL(const TDesC8& aDes) |
|
1137 /** Writes the content of the 8 bit descriptor to the stream. No other information |
|
1138 is written to this write stream. |
|
1139 |
|
1140 @param aDes A reference to a descriptor. Passing the build independent type |
|
1141 TDesC& allows the compiler to choose the appropriate WriteL() variant (i.e |
|
1142 the 8 bit or the 16 bit) at build time. */ |
|
1143 { |
|
1144 WriteL(aDes.Ptr(),aDes.Length()); |
|
1145 } |
|
1146 |
|
1147 EXPORT_C void RWriteStream::WriteL(const TDesC8& aDes,TInt aLength) |
|
1148 /** Writes data of the specified length from the 8 bit descriptor to the stream. |
|
1149 No other information is written to this write stream. |
|
1150 |
|
1151 @param aDes A reference to a descriptor. Passing the build independent type |
|
1152 TDesC& allows the compiler to choose the appropriate WriteL() variant (i.e |
|
1153 the 8 bit or the 16 bit) at build time. |
|
1154 @param aLength The length of data to be written to this stream. */ |
|
1155 |
|
1156 { |
|
1157 __ASSERT_DEBUG(aLength<=aDes.Length(),Panic(EStreamWriteBeyondEnd)); |
|
1158 WriteL(aDes.Ptr(),aLength); |
|
1159 } |
|
1160 |
|
1161 EXPORT_C void RWriteStream::WriteL(const TUint8* aPtr,TInt aLength) |
|
1162 /** Writes 8 bit data of the specified length from the specified location to this |
|
1163 write stream. |
|
1164 |
|
1165 @param aPtr The location from where data is to be streamed out. |
|
1166 @param aLength The length of data to be streamed out. */ |
|
1167 |
|
1168 { |
|
1169 __ASSERT_DEBUG(aLength>=0,Panic(EStreamWriteLengthNegative)); |
|
1170 if (aLength==0) |
|
1171 return; |
|
1172 // |
|
1173 __ASSERT_DEBUG(iSnk!=NULL,Panic(EStreamNotOpen)); |
|
1174 iSnk->WriteL(aPtr,aLength); |
|
1175 } |
|
1176 |
|
1177 #if 0 |
|
1178 EXPORT_C void RWriteStream::WriteL(RReadStream &aStream) |
|
1179 /** Writes the content of the specified read stream to this write stream. |
|
1180 |
|
1181 @param aStream A reference to a read stream which is to be written to this |
|
1182 stream. */ |
|
1183 |
|
1184 { |
|
1185 __ASSERT_DEBUG(iSnk!=NULL,Panic(EStreamNotOpen)); |
|
1186 TSourceOutput output(aStream.iSrc); |
|
1187 iSnk->WriteL(output); |
|
1188 } |
|
1189 #endif |
|
1190 |
|
1191 #if 0 |
|
1192 EXPORT_C void RWriteStream::WriteL(RReadStream& aStream,TInt aLength) |
|
1193 /** Writes data of the specified length from the specified read stream to this |
|
1194 stream. |
|
1195 |
|
1196 @param aStream A reference to a read stream part of whose content is to be |
|
1197 written to this stream. |
|
1198 @param aLength The length of data from the read stream to be written to this |
|
1199 write stream. */ |
|
1200 |
|
1201 { |
|
1202 __ASSERT_DEBUG(aLength>=0,Panic(EStreamWriteLengthNegative)); |
|
1203 if (aLength==0) |
|
1204 return; |
|
1205 // |
|
1206 __ASSERT_DEBUG(iSnk!=NULL,Panic(EStreamNotOpen)); |
|
1207 TSourceOutput output(aStream.iSrc); |
|
1208 TInt len=iSnk->WriteL(output,aLength); |
|
1209 __ASSERT_DEBUG(len>=0&&len<=aLength,Panic(EStreamReadInBreach)); |
|
1210 if (len<aLength) |
|
1211 __LEAVE(KErrEof); |
|
1212 } |
|
1213 #endif |
|
1214 |
|
1215 EXPORT_C void RWriteStream::WriteL(const TDesC16& aDes) |
|
1216 /** Writes the content of the 16 bit descriptor to the stream. No other information |
|
1217 is written to this write stream. |
|
1218 |
|
1219 @param aDes A reference to a descriptor. Passing the build independent type |
|
1220 TDesC& allows the compiler to choose the appropriate WriteL() variant (i.e |
|
1221 the 8 bit or the 16 bit) at build time. */ |
|
1222 |
|
1223 { |
|
1224 WriteL(aDes.Ptr(),aDes.Length()); |
|
1225 } |
|
1226 |
|
1227 EXPORT_C void RWriteStream::WriteL(const TDesC16& aDes,TInt aLength) |
|
1228 /** Writes data of the specified length from the 16 bit descriptor to the stream. |
|
1229 No other information is written to this write stream. |
|
1230 |
|
1231 @param aDes A reference to a descriptor. Passing the build independent type |
|
1232 TDesC& allows the compiler to choose the appropriate WriteL() variant (i.e |
|
1233 the 8 bit or the 16 bit) at build time. |
|
1234 @param aLength The length of data to be written to this stream. */ |
|
1235 |
|
1236 { |
|
1237 __ASSERT_DEBUG(aLength<=aDes.Length(),Panic(EStreamWriteBeyondEnd)); |
|
1238 WriteL(aDes.Ptr(),aLength); |
|
1239 } |
|
1240 |
|
1241 EXPORT_C void RWriteStream::WriteL(const TUint16* aPtr,TInt aLength) |
|
1242 /** Writes 16 bit data of the specified length from the specified location to this |
|
1243 write stream. |
|
1244 |
|
1245 @param aPtr The location from where data is to be streamed out. |
|
1246 @param aLength The length of data to be streamed out. */ |
|
1247 |
|
1248 { |
|
1249 __ASSERT_DEBUG(aLength>=0,Panic(EStreamWriteLengthNegative)); |
|
1250 WriteL((const TUint8*)aPtr,aLength<<1); // platform dependency |
|
1251 } |
|
1252 |
|
1253 EXPORT_C void RWriteStream::WriteInt8L(TInt aValue) |
|
1254 /** Writes a TInt value as an 8Â bit value to this stream. |
|
1255 |
|
1256 @param aValue The value to be written to this stream. */ |
|
1257 |
|
1258 { |
|
1259 WriteL((const TUint8*)&aValue,1); // platform dependency |
|
1260 } |
|
1261 |
|
1262 EXPORT_C void RWriteStream::WriteInt16L(TInt aValue) |
|
1263 /** Writes a TInt value as a 16Â bit value to this stream. |
|
1264 |
|
1265 @param aValue The value to be written to this stream. */ |
|
1266 { |
|
1267 WriteL((const TUint8*)&aValue,2); // platform dependency |
|
1268 } |
|
1269 |
|
1270 EXPORT_C void RWriteStream::WriteInt32L(TInt32 aValue) |
|
1271 /** Writes a TInt32 value as a 32 bit value to this stream. |
|
1272 |
|
1273 @param aValue The value to be written to this stream. */ |
|
1274 |
|
1275 { |
|
1276 WriteL((const TUint8*)&aValue,4); // platform dependency |
|
1277 } |
|
1278 |
|
1279 EXPORT_C void RWriteStream::WriteUint8L(TUint aValue) |
|
1280 /** Writes a TUint value as an 8 bit value to this stream. |
|
1281 |
|
1282 @param aValue The value to be written to this stream. */ |
|
1283 { |
|
1284 WriteL((const TUint8*)&aValue,1); // platform dependency |
|
1285 } |
|
1286 |
|
1287 EXPORT_C void RWriteStream::WriteUint16L(TUint aValue) |
|
1288 /** Writes a TUint value as a 16 bit value to this stream. |
|
1289 |
|
1290 @param aValue The value to be written to this stream. */ |
|
1291 |
|
1292 { |
|
1293 WriteL((const TUint8*)&aValue,2); // platform dependency |
|
1294 } |
|
1295 |
|
1296 EXPORT_C void RWriteStream::WriteUint32L(TUint32 aValue) |
|
1297 /** Writes a TUint32 value as a 32 bit value to this stream. |
|
1298 |
|
1299 @param aValue The value to be written to this stream. */ |
|
1300 { |
|
1301 WriteL((const TUint8*)&aValue,4); // platform dependency |
|
1302 } |
|
1303 |
|
1304 |
|
1305 namespace store_private |
|
1306 { |
|
1307 |
|
1308 MemStreamBuf::MemStreamBuf(const CStreamStore& aStore, TStreamId aId) |
|
1309 : iStore(&aStore), iStreamId(aId), iCurrentReadIndex(0), iCurrentWriteIndex(0), iData() |
|
1310 { |
|
1311 } |
|
1312 |
|
1313 MemStreamBuf::MemStreamBuf(const CStreamStore& aStore, TStreamId aId, |
|
1314 MStreamBuf *aStreamIn, std::streamoff aOffset, TUint32 aLength) |
|
1315 : iStore(&aStore), iStreamId(aId), iCurrentReadIndex(0), iCurrentWriteIndex(0), iData() |
|
1316 { |
|
1317 |
|
1318 |
|
1319 aStreamIn->SeekL(MStreamBuf::ERead, EStreamBeginning, aOffset); |
|
1320 while(aLength) |
|
1321 { |
|
1322 TUint8 data; |
|
1323 aStreamIn->ReadL(&data, 1); |
|
1324 iData.push_back(data); |
|
1325 --aLength; |
|
1326 } |
|
1327 |
|
1328 } |
|
1329 |
|
1330 void MemStreamBuf::AppendFromFile(MStreamBuf *aStreamIn, TUint32 aLength) |
|
1331 { |
|
1332 while(aLength) |
|
1333 { |
|
1334 TUint8 data; |
|
1335 aStreamIn->ReadL(&data, 1); |
|
1336 iData.push_back(data); |
|
1337 --aLength; |
|
1338 } |
|
1339 } |
|
1340 |
|
1341 |
|
1342 |
|
1343 TStreamId MemStreamBuf::StreamId() const |
|
1344 { |
|
1345 return iStreamId; |
|
1346 } |
|
1347 |
|
1348 const std::vector<TUint8> &MemStreamBuf::GetData() const |
|
1349 { |
|
1350 return iData; |
|
1351 } |
|
1352 |
|
1353 |
|
1354 TInt MemStreamBuf::DoReadL(TAny *aPtr,TInt aMaxLength) |
|
1355 { |
|
1356 char *p = reinterpret_cast<char *>(aPtr); |
|
1357 for(TInt i=0; i < aMaxLength; ++i) |
|
1358 { |
|
1359 *p++ = iData[iCurrentReadIndex++]; |
|
1360 } |
|
1361 return aMaxLength; |
|
1362 } |
|
1363 |
|
1364 void MemStreamBuf::DoWriteL(const TUint8* aPtr,TInt aLength) |
|
1365 { |
|
1366 for(TInt i=0; i < aLength; ++i) |
|
1367 { |
|
1368 if(iCurrentWriteIndex == iData.size()) |
|
1369 { |
|
1370 iData.push_back(aPtr[i]); |
|
1371 } |
|
1372 else |
|
1373 { |
|
1374 iData[iCurrentWriteIndex] = aPtr[i]; |
|
1375 } |
|
1376 ++iCurrentWriteIndex; |
|
1377 } |
|
1378 } |
|
1379 |
|
1380 TStreamPos MemStreamBuf::DoSeekL(TMark aMark,TStreamLocation aLocation,TInt anOffset) |
|
1381 { |
|
1382 if(aMark != ERead && aMark != EWrite) |
|
1383 { |
|
1384 FatalError(); |
|
1385 } |
|
1386 |
|
1387 TUint32 *p = (aMark == ERead) ? (&iCurrentReadIndex) : (&iCurrentWriteIndex); |
|
1388 |
|
1389 switch(aLocation) |
|
1390 { |
|
1391 case EStreamBeginning: |
|
1392 *p = anOffset; |
|
1393 break; |
|
1394 |
|
1395 case EStreamMark: |
|
1396 *p += anOffset; |
|
1397 break; |
|
1398 |
|
1399 case EStreamEnd: |
|
1400 *p = iData.size() + anOffset; |
|
1401 break; |
|
1402 |
|
1403 default: |
|
1404 FatalError(); |
|
1405 } |
|
1406 |
|
1407 if(*p > iData.size()) |
|
1408 { |
|
1409 // nb we allow a seek 1 byte off end of data |
|
1410 FatalError(); |
|
1411 } |
|
1412 return *p; |
|
1413 } |
|
1414 |
|
1415 void MemStreamBuf::DoRelease() |
|
1416 { |
|
1417 } |
|
1418 |
|
1419 }; // end of namespace store_private |
|
1420 |
|
1421 const TInt KShiftCardinality8=1; |
|
1422 const TInt KShiftCardinality16=2; |
|
1423 const TInt KShiftCardinality32=3; |
|
1424 // |
|
1425 const TInt KDefaultIoBufSize=0xc00; |
|
1426 const TInt KFilterIoBufSize=0x100; |
|
1427 |
|
1428 EXPORT_C void TCardinality::ExternalizeL(RWriteStream& aStream) const |
|
1429 /** Externalises this object to a write stream. |
|
1430 |
|
1431 The existence of this function means that the standard templated operator<<() |
|
1432 can be used to externalise objects of this class. |
|
1433 |
|
1434 @param aStream Stream to which the object should be externalised. |
|
1435 @see operator<<() */ |
|
1436 { |
|
1437 TUint n=iCount; |
|
1438 if (n<=(KMaxTUint8>>KShiftCardinality8)) |
|
1439 aStream.WriteUint8L((n<<KShiftCardinality8)); |
|
1440 else if (n<=(KMaxTUint16>>KShiftCardinality16)) |
|
1441 aStream.WriteUint16L((n<<KShiftCardinality16)+0x1); |
|
1442 else |
|
1443 { |
|
1444 __ASSERT_DEBUG(n<=(TUint)KMaxCardinality,Panic(EStreamCardinalityOutOfRange)); |
|
1445 aStream.WriteUint32L((n<<KShiftCardinality32)+0x3); |
|
1446 } |
|
1447 } |
|
1448 |
|
1449 EXPORT_C void TCardinality::InternalizeL(RReadStream& aStream) |
|
1450 /** Internalizes this object from a read stream. |
|
1451 |
|
1452 The existence of this function means that the standard templated operator>>() |
|
1453 can be used to internalise objects of this class. |
|
1454 |
|
1455 @param aStream Stream store from which the objet is to be internalised. |
|
1456 @see operator>>() */ |
|
1457 { |
|
1458 TUint n=aStream.ReadUint8L(); |
|
1459 if ((n&0x1)==0) |
|
1460 n>>=KShiftCardinality8; |
|
1461 else if ((n&0x2)==0) |
|
1462 { |
|
1463 n+=aStream.ReadUint8L()<<8; |
|
1464 n>>=KShiftCardinality16; |
|
1465 } |
|
1466 else if ((n&0x4)==0) |
|
1467 { |
|
1468 aStream.ReadL((TUint8*)&iCount,sizeof(TUint32)-sizeof(TUint8)); |
|
1469 n+=TUint(iCount)<<8; // platform dependency |
|
1470 n>>=KShiftCardinality32; |
|
1471 } |
|
1472 else |
|
1473 __LEAVE(KErrCorrupt); |
|
1474 // |
|
1475 __ASSERT_DEBUG(n<=(TUint)KMaxCardinality,User::Invariant()); |
|
1476 iCount=n; |
|
1477 } |
|
1478 |
|
1479 EXPORT_C void TCardinality::__DbgChkRange(TInt aCount) |
|
1480 // |
|
1481 // Check for a negative count. |
|
1482 // |
|
1483 { |
|
1484 if(!(aCount<=KMaxCardinality)) FatalError(); |
|
1485 } |
|
1486 |
|
1487 void CleanupStack::PopAndDestroy(RWriteStream *aStream) |
|
1488 { |
|
1489 aStream->Close(); |
|
1490 } |
|
1491 void CleanupStack::PopAndDestroy(RReadStream *aStream) |
|
1492 { |
|
1493 aStream->Close(); |
|
1494 } |
|
1495 |
|
1496 void CleanupStack::PopAndDestroy(CFileStore *aStore) |
|
1497 { |
|
1498 delete aStore; |
|
1499 } |
|
1500 |
|
1501 |
|
1502 // End of file |