conn::CSBGenericDataType Class Reference

class conn::CSBGenericDataType : public CBase

Generic Data Type is a class for representing any type of data owner so that it may be passed through a common interface

Introduction

The CSBEClient Secure backup interface class is designed to perform backup operations on many different types of data owners. This presents a problem in that the interfaces sometimes require arguments that are specific to the data type in question. In addition, we can't predict the new data types that may appear in future, therefore a "generic" data type was proposed that could be passed through interfaces as a base class and contained enough information to enable Runtime Type Identification (RTTI) to be performed.

This approach means that only one interface needs to be maintained for each backup operation whilst still allowing the Secure Backup Engine to determine which type was originally sent by a PC client.

As well as acting as an identifier for different Data Owner's (DO's), it was decided to extend the usage of the class to identify Data Owner's Data as each DO may require specific information to identify data being transferred (such as finished flags etc.)

The identifier is transparent to the user of CSBEClient , meaning that it can be extracted directly from the message sent by the PC into a generic type and passed through to the SBEngine without being instantiated as a derived class.

Usage

The general usage of the generic data type is to extract it from a PC sent message as a CSBGenericDataType object using CSBGenericDataType::NewL(const TDesC8& aDes) .

There are a few conventions that have been followed within the Secure Backup component that a developer must bear in mind:

  • Ownership of the CSBGenericDataType , CSBGenericTransferType or derived object is generally passed between interfaces and as such it is the resposibility of the receiving function to delete it. Unless otherwise stated in the documentation for an interface, this is assumed to be the case;

  • When a CSBGenericDataType or CSBGenericTransferType is to be converted into a derived type, it must be passed in as a parameter to the constructor of the derived type. It must not be downcasted as it may never have been a derived type, and the derived types contain extra member data;

In order to convert a base type to a derived type, a method CSBGenericDataType::DerivedTypeL() that returns a conn::TSBDerivedType can be called to query the base object for it's derived type.

A typical mechanism would be to use a switch statement, switching on the return value of DerivedTypeL() and taking appropriate action with regards to creating a derived object.

Internal Operation

Initialisation

CSBGenericDataType is underneath basically a descriptor buffer. All accessor functions simply extract and pack values from this descriptor. This means that the type can be safely transferred via IPC between processes and safely transferred between a device and a PC independently of communications bearer or transport.

The base class CSBGenericDataType has ownership of the data buffer, iDataBuffer, used to store the member data in and in order to keep the derived classes atomic, a running total size variable is updated by the C++ constructors of each class in the inheritence chain. Because of Symbian's static NewL idiom, all C++ constructors are executed before CSBGenericDataType::ConstructL() is called to instantiate the buffer, hence the size can be guaranteed to be big enough to hold all of the derived type's data.

In order to ensure that the derived types know whereabouts in the descriptor to extract and pack values, an initialisation routine, InitialiseL(TInt& aOffset) , is implemented by each class. Each class is responsible for calling it's parents InitialiseL() , before initialising itself and passing in an offset. The job of the initialisation method is to walk the descriptor, storing the offset's of it's member data. The offset is a reference and is hence updated so that the child class begins unpacking after the parents data ends. In this way, each class is atomic apart from having to explicitly scope it's parent's InitialiseL() method.

Accessing Data

Data is accessed by the use of packing and unpacking bytes directly from the descriptor using the UnpackType, PackType and associated function templates. These will be unpacked in the endianness of the system and therefore the PC will have to ensure that this is taken into account when packing the type into the message.

Although this method suffers in terms of performance, for the reasons of platform independence, this is the most reliable method of packing/unpacking.

Byte Structure

All child classes have their data following on from the parent classes so that the parent classes may remain atomic with respect to the structure of their data. The binary structure of this data type inside the descriptor buffer is as follows. Note that the endianness of the data types specified below is determined by the platform and the PC must pack accordingly:

TSBDerivedType [4-bytes]

Generic Data Type is a class for representing any type of data owner so that it may be passed through a common interface

Introduction

The CSBEClient Secure backup interface class is designed to perform backup operations on many different types of data owners. This presents a problem in that the interfaces sometimes require arguments that are specific to the data type in question. In addition, we can't predict the new data types that may appear in future, therefore a "generic" data type was proposed that could be passed through interfaces as a base class and contained enough information to enable Runtime Type Identification (RTTI) to be performed.

This approach means that only one interface needs to be maintained for each backup operation whilst still allowing the Secure Backup Engine to determine which type was originally sent by a PC client.

As well as acting as an identifier for different Data Owner's (DO's), it was decided to extend the usage of the class to identify Data Owner's Data as each DO may require specific information to identify data being transferred (such as finished flags etc.)

The identifier is transparent to the user of CSBEClient , meaning that it can be extracted directly from the message sent by the PC into a generic type and passed through to the SBEngine without being instantiated as a derived class.

Usage

The general usage of the generic data type is to extract it from a PC sent message as a CSBGenericDataType object using CSBGenericDataType::NewL(const TDesC8& aDes) .

There are a few conventions that have been followed within the Secure Backup component that a developer must bear in mind:

  • Ownership of the CSBGenericDataType , CSBGenericTransferType or derived object is generally passed between interfaces and as such it is the resposibility of the receiving function to delete it. Unless otherwise stated in the documentation for an interface, this is assumed to be the case;

  • When a CSBGenericDataType or CSBGenericTransferType is to be converted into a derived type, it must be passed in as a parameter to the constructor of the derived type. It must not be downcasted as it may never have been a derived type, and the derived types contain extra member data;

In order to convert a base type to a derived type, a method CSBGenericDataType::DerivedTypeL() that returns a conn::TSBDerivedType can be called to query the base object for it's derived type.

A typical mechanism would be to use a switch statement, switching on the return value of DerivedTypeL() and taking appropriate action with regards to creating a derived object.

Internal Operation

Initialisation

CSBGenericDataType is underneath basically a descriptor buffer. All accessor functions simply extract and pack values from this descriptor. This means that the type can be safely transferred via IPC between processes and safely transferred between a device and a PC independently of communications bearer or transport.

The base class CSBGenericDataType has ownership of the data buffer, iDataBuffer, used to store the member data in and in order to keep the derived classes atomic, a running total size variable is updated by the C++ constructors of each class in the inheritence chain. Because of Symbian's static NewL idiom, all C++ constructors are executed before CSBGenericDataType::ConstructL() is called to instantiate the buffer, hence the size can be guaranteed to be big enough to hold all of the derived type's data.

In order to ensure that the derived types know whereabouts in the descriptor to extract and pack values, an initialisation routine, InitialiseL(TInt& aOffset) , is implemented by each class. Each class is responsible for calling it's parents InitialiseL() , before initialising itself and passing in an offset. The job of the initialisation method is to walk the descriptor, storing the offset's of it's member data. The offset is a reference and is hence updated so that the child class begins unpacking after the parents data ends. In this way, each class is atomic apart from having to explicitly scope it's parent's InitialiseL() method.

Accessing Data

Data is accessed by the use of packing and unpacking bytes directly from the descriptor using the UnpackType, PackType and associated function templates. These will be unpacked in the endianness of the system and therefore the PC will have to ensure that this is taken into account when packing the type into the message.

Although this method suffers in terms of performance, for the reasons of platform independence, this is the most reliable method of packing/unpacking.

Byte Structure

All child classes have their data following on from the parent classes so that the parent classes may remain atomic with respect to the structure of their data. The binary structure of this data type inside the descriptor buffer is as follows. Note that the endianness of the data types specified below is determined by the platform and the PC must pack accordingly:

TSBDerivedType [4-bytes]

Inherits from

Constructor & Destructor Documentation

CSBGenericDataType()

CSBGenericDataType ( ) [protected]

C++ Constructor. Any derived types must increment iSize in their C++ constructors in order that when CSBGenericDataType::BaseConstructL() is called, the data buffer is initialised to be large enough to accomodate the data stored by the derived type

~CSBGenericDataType()

IMPORT_C ~CSBGenericDataType ( )

C++ Destructor

Member Functions Documentation

ConstructL(const TDesC8 &)

void ConstructL ( const TDesC8 & aDes ) [protected]

Symbian OS 2nd phase constructor. Called when creating a base class from raw data i.e. off the wire/IPC. Creates the base type data buffer to store object data in

Parameters

const TDesC8 & aDes descriptor containing the buffer of data

DerivedTypeL()

IMPORT_C TSBDerivedType DerivedTypeL ( ) const

Externalise()

IMPORT_C const TDesC8 & Externalise ( ) const

InitialiseL(TInt &)

void InitialiseL ( TInt & aOffset ) [protected, virtual]

Initialise all of member data offsets inside the base and derived classes

Parameters

TInt & aOffset The running offset indicating the position in the descriptor that has been parsed up to

NewL(const TDesC8 &)

IMPORT_C CSBGenericDataType * NewL ( const TDesC8 & aDes ) [static]

Symbian constructor. A base CSBGenericDataType may only be instantiated from a previously externalised data type. This is the method that is used to take a generic data type from either an IPC response or from a message sent by the PC. This method will not take ownership of the descriptor aDes

Parameters

const TDesC8 & aDes descriptor containing the buffer of data

PackDescriptorTypeAdvance(const TDesC16 &, TInt &)

void PackDescriptorTypeAdvance ( const TDesC16 & aDes,
TInt & aOffset
) [protected]

Parameters

const TDesC16 & aDes
TInt & aOffset

PackDescriptorTypeAdvance(const TDesC8 &, TInt &)

void PackDescriptorTypeAdvance ( const TDesC8 & aDes,
TInt & aOffset
) [protected]

Parameters

const TDesC8 & aDes
TInt & aOffset

UnpackDescriptorTypeAdvance(TDesC16 &, TInt &)

void UnpackDescriptorTypeAdvance ( TDesC16 & aDes,
TInt & aOffset
) [protected]

Function to copy a simple type from a specified position in aDes defined by aOffset. aOffset is advanced so that on return, the new offset is stored enabling the next call to UnpackType() to point at the position following this type.

Parameters

TDesC16 & aDes The buffer that contains the type T pointed to by aPtr
TInt & aOffset The running index of where the following type begins. Updated by ExtractPointer

UnpackTPtrAdvance(TPtrC16 &, TInt &)

void UnpackTPtrAdvance ( TPtrC16 & aDes,
TInt & aOffset
) [protected]

Function to copy a simple type from a specified position in aDes defined by aOffset. aOffset is advanced so that on return, the new offset is stored enabling the next call to UnpackType() to point at the position following this type.

Parameters

TPtrC16 & aDes The buffer that contains the type T pointed to by aPtr
TInt & aOffset The running index of where the following type begins. Updated by ExtractPointer

UnpackTPtrAdvance(TPtrC8 &, TInt &)

void UnpackTPtrAdvance ( TPtrC8 & aDes,
TInt & aOffset
) [protected]

Parameters

TPtrC8 & aDes
TInt & aOffset

Member Data Documentation

HBufC8 * iDataBuffer

HBufC8 * iDataBuffer [protected]

the data buffer

TInt iDerivedTypeOffset

TInt iDerivedTypeOffset [protected]

the derived type

TInt iSize

TInt iSize [protected]

Cumulative size of the derived type. All ctors in the inheritence tree increment with their size