The protocol for restoring a compound object is the RestoreL() function. This is true whether the object has been stored in-line or out-of-line, and should be prototyped as:
void RestoreL(CStreamStore& aStore,TStreamId anId);
The function takes a reference to the store in which streams are stored and a stream ID. In some cases, the design of a class may be such that it maintains a pointer or reference to the store. In this event, the CStreamStore argument would be redundant.
If an object's components have been stored in-line, then all of these components have been written to the same single stream.
For the example class CCompound, defined as:
CCompound class : public CBase { ... TInt iDdata; CComponentA* iCompA; CComponentB* iCompB; ... }
RestoreL() is implemented as:
void CCompound::RestoreL(CStreamStore& aStore,TStreamId anId) { RStoreReadStream instream; instream.OpenLC(aStore,anId); InternalizeL(instream); CleanupStack::PopAndDestroy(); }
where the stream ID passed to the function is the ID of the single stream containing the data.
If an object's components have been stored out-of-line, then all of these components have been written to separate streams.
For the example class CCompound, defined as:
CCompound class : public CBase { ... TInt iDdata; TSwizzle<CComponentA> iCompA; TSwizzle<CComponentB> iCompB; ... }
RestoreL() is implemented as:
void CCompound::RestoreL(CStreamStore& aStore,TStreamId anId) { RStoreReadStream stream; // Construct a read stream. stream.OpenLC(aStore,anId); // Open the head stream. InternalizeL(stream); // Internalise top level stream containing CCompound // and the IDs of its components. RestoreComponentsL(aStore); // Restore components. CleanupStack::PopAndDestroy(); }
where the stream ID passed to the function is the ID of the head stream.
InternalizeL() internalises CCompound's data members and the stream IDs of its components:
void CCompound::InternalizeL(RReadStream& aStream) { aStream >> iDataA; aStream >> iCompA; aStream >> iCompB; }
RestoreComponentsL() constructs each component object and restores them from their respective stream networks.
void CCompound::RestoreComponentsL(CStreamStore& aStore) { CComponentA* ptrA = new (ELeave) CComponentA; CleanupStack::PushL(ptrA); ptrA->RestoreL(aStore,iCompA.AsId()); iCompA = ptrA; CleanupStack::Pop(); CComponentB* ptrB = new (ELeave) CComponentB; CleanupStack::PushL(ptrB); ptrB->RestoreL(aStore,iCompB.AsId()); iCompB = ptrB CleanupStack::Pop(); }
In general, an application might want to defer the loading of some components. This would mean either changing the implementation of RestoreComponents() or adding new functionality to the class. The use of Swizzles is important here as they simplify the handling of the dual representation of an object as a pointer to an in-memory object or as an ID of a stream.
Typically, an application might use code such as:
if (iCompA.IsId()) { iCompA = CComponentA::NewL(iStore,iCompA.AsId()); }
to test whether the component is currently represented by a stream ID or by a pointer to an in-memory object. If a stream ID, then the component would be restored. In this small code fragment, an overloaded NewL() function is used both to construct and to restore the component object. Once this code has executed, the component is represented by a pointer.
See also