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.