Templated stream operators

There are two templated stream operators, operator<< and operator>> that can be used to externalise and internalise data of all types. They use a syntax that is familiar to users of C++ iostreams, or Java streams.

An object can be externalised to a stream, using a write stream:

      
       
      
      writeStream << object;
     

and later, assuming the operation starts from the appropriate place on the stream, the data can be internalised again, using a read stream:

      
       
      
      readStream >> object;
     

The implementation of the operators depends on the type of object on which they are called.

Implementation for a class defining ExternalizeL() & InternalizeL()

For a class that defines and implements the ExternalizeL() and InternalizeL() functions, the Store framework:

  • implements operator<< by calling the ExternalizeL() member function of that class.

  • implements operator>> by calling the InternalizeL() member function of that class.

Implementation for standard types and classes

The Store framework provides the necessary implementation for the operators to externalise and internalise the following:

  • The basic types: TInt8 , TInt16 , TInt32 , TInt64 , TUint8 , TUint16 , TUint32 , TReal32 and TReal64 .

  • The graphics API classes: TPoint , TSize and TRect .

  • The UID Manipulation API class: TUid .

  • The Dynamic Buffers API classes: CBufFlat and CBufSeg .

Implementation for non-class types

For non-class types, for example enumerators, a specialized implementation of the operators must be defined and implemented for that specific non-class type. The definition of the operators must conform to the templated definitions.

For example, for a class TSimple that contains an enumeration of type TXxx as a data member:

       
        
       
       enum  TXxx {EX1,EX2,EX3};
      
       
        
       
       class TSimple
          {
    public :
          void ExternalizeL(RWriteStream& aStream) const;
          void InternalizeL(RReadStream& aStream);
    public :
          TXxx     iTheEnum;
          ...
          TUint    iUintValue;
          ...
          };
      

The iTheEnum data member is externalised using operator<< and internalised using operator>> :

       
        
       
       void TSimple::ExternalizeL(RWriteStream& aStream) const
          {
          aStream << iTheEnum;
          ...
          }
      
       
        
       
       void TSimple::InternalizeL(RReadStream& aStream)
          {
          aStream >> iTheEnum;
          ...
          }
      

As TXxx is a non-class type, the operators are implemented:

       
        
       
       RWriteStream& operator<<(RWriteStream& aStream, const TXxx& anXxx)
          {
          aStream.WriteInt8L(anXxx);
          return aStream;
          }
      
       
        
       
       RReadStream&  operator>>(RReadStream&  aStream, TXxx& anXxx)
          {
          anXxx = TXxx(aStream.ReadInt8L());
          return aStream;
          }
      

The enumerator value is written to the stream using RWriteStream::WriteInt8L() . Implicit here is the assumption that the enumeration can be represented by just 8 bits.

Implementation for a class without ExternalizeL() & InternalizeL()

The operators may be used on class types that do not define and implement InternalizeL() and ExternalizeL() functions. This is done by defining and implementing some extra global functions.

In practice, it is much simpler to define and implement InternlizeL() and ExternalizeL() for a class, and all new classes should include these functions. However, there may be rare situations, for example, when porting classes, where it may be undesirable to define them.

To support the use of the operators for such a class, for example, for the class TNonStore defined as:

       
        
       
       class TNonStore
          {
    public :
          void  SetBuffer(const TDesC& aData);
          TPtrC GetBuffer() const;
    private :
          TBuf<32> iBuffer;
    public :
          TInt     iIntValue;
          TUint    iUintValue;
          TReal    iRealValue;
          };
      
  • implement the following Externalization() and Internalization() global functions:

             
              
             
             inline Externalize::Function Externalization(const TNonstore*)
              {return Externalize::Function();}
            
             
              
             
             inline Internalize::Function Internalization(TNonstore*)
              {return Internalize::Function();}
            
  • declare the following ExternalizeL() and InternalizeL() global functions:

             
              
             
             void ExternalizeL(const TNonstore& aClass,RWriteStream& aStream);
            
             
              
             
             void InternalizeL(TNonstore& aClass,RReadStream& aStream);
            
  • implement the ExternalizeL() and InternalizeL() global functions to implement the streaming of TNonstore 's components. For this example class:

             
              
             
             void ExternalizeL(const TNonStore& aClass,RWriteStream& aStream)
              {
              aStream.WriteInt32L(aClass.iIntValue);
              aStream.WriteUint32L(aClass.iUintValue);
              aStream.WriteReal64L(aClass.iRealValue);
              aStream << aClass.GetBuffer();
              }
    
        void InternalizeL(TNonStore& aClass,RReadStream& aStream)
              {
              aClass.iIntValue  = aStream.ReadInt32L();
              aClass.iUintValue = aStream.ReadUint32L();
              aClass.iRealValue = aStream.ReadReal64L();
              TBuf<32> temp;
              aStream >> temp;
              aClass.SetBuffer(temp);
              }