Externalising a Swizzle

Typically, externalizing a Swizzle is a two stage process which involves:

  • externalizing the in-memory object which the Swizzle represents, to its own stream

  • externalizing the resulting stream ID.

For example, given a container type object, CClassABC, with a data member TSwizzle<CClassB> iB representing a CClassB object in memory, the diagram below illustrates the result of storing the container object.

The following code fragments illustrates the process.

iB is a CClassB type component of a class CClassABC, and is represented by a Swizzle. The data member is defined as:

class CCClassABC : public CBase
    {
    ...
    TSwizzle<CClassB> iB;
    ...
    }

Typically, a CClassB object is constructed and assigned to iB; this uses the Swizzle’s assignment operator:

iB = CClassB::NewL();

The Swizzle now represents the CClassB object by pointer.

The StoreL() member function of CClassABC constructs a store map, an object of type CStoreMap, before calling StoreComponentsL() to externalise the swizzled CClassB object to its own stream.

TStreamId CClassABC::StoreL() const
    {
    CStoreMap* map=CStoreMap::NewLC(iStore);
       StoreComponentsL(*map);
 
       RStoreWriteStream stream(*map);
       TStreamId id=stream.CreateLC(iStore);
       ExternalizeL(stream);
       stream.CommitL();

       map->Reset();
       CleanupStack::PopAndDestroy(2);
       return id;
       }

The variable iStore is a member of CClassABC containing a reference to the store.

StoreComponentsL() externalises the swizzled CClassB object by calling CClassB ’s own StoreL() member function which constructs a stream, externalises itself to the stream and returns the ID of that stream:

void CClassABC::StoreComponentsL(CStoreMap& aMap) const
          {
          ...
          TStreamId id;
          if (iB)
                {
                id = iB->StoreL(iStore); // Id of the CClassB stream 
                aMap.BindL(iB,id);
                }
          ...
          }

The Swizzle must represent the CClassB type object as a pointer, i.e. the swizzled object must be in memory. The operator-> applied to the Swizzle iB gives access to the StoreL() member function of the CClassB object.

The condition if (iB) is equivalent to if (iB.IsPtr()) and returns true only if the Swizzle represents the CClassB object as a pointer . The act of externalizing the CClassB object, does not, and need not change the way that the Swizzle represents that object. Here, the CClassB object remains in memory and the Swizzle maintains its representation of it as a pointer, even after it has been externalised.

The Stream ID of the externalised CClassB object is stored in the store map along with the associated Swizzle using CStoreMap ’s BindL() member function .The store map is used again later when the stream ID is externalised as part of CClassABC ’s data.

The ExternalizeL() member function of CClassABC externalises CClassABC's member data. This includes the stream ID of the externalised CClassB object which is externalised by applying the templated stream operator<< to the Swizzle iB.

void CCompound::ExternalizeL(RWriteStream& aStream) const
    {
    ...
    aStream << iB
    ...
    }

At this point, the Swizzle still represents the CClassB object as a pointer, and the object itself is still in memory.

The mechanism underlying the implementation of the stream operator<<, assumes that the stream ID associated with the Swizzle has been placed in the store map. It also assumes that the RStoreWriteStream object has been constructed, specifying the store map as an externalizer.

The end result of the operation aStream << iB;, is to externalise, to the stream, the stream ID associated with the Swizzle iB. The following diagram shows this: