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;
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;
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] |
Public Member Functions | |
---|---|
~CSBGenericDataType () | |
IMPORT_C TSBDerivedType | DerivedTypeL () |
IMPORT_C const TDesC8 & | Externalise () |
IMPORT_C CSBGenericDataType * | NewL (const TDesC8 &) |
Protected Member Functions | |
---|---|
CSBGenericDataType () | |
void | ConstructL (const TDesC8 &) |
void | InitialiseL ( TInt &) |
void | PackDescriptorTypeAdvance (const TDesC16 &, TInt &) |
void | PackDescriptorTypeAdvance (const TDesC8 &, TInt &) |
void | UnpackDescriptorTypeAdvance ( TDesC16 &, TInt &) |
void | UnpackTPtrAdvance ( TPtrC16 &, TInt &) |
void | UnpackTPtrAdvance ( TPtrC8 &, TInt &) |
Protected Attributes | |
---|---|
HBufC8 * | iDataBuffer |
TInt | iDerivedTypeOffset |
TInt | iSize |
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
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
const TDesC8 & aDes | descriptor containing the buffer of data |
void | InitialiseL | ( | TInt & | aOffset | ) | [protected, virtual] |
Initialise all of member data offsets inside the base and derived classes
TInt & aOffset | The running offset indicating the position in the descriptor that has been parsed up to |
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
const TDesC8 & aDes | descriptor containing the buffer of data |
void | PackDescriptorTypeAdvance | ( | const TDesC16 & | aDes, |
TInt & | aOffset | |||
) | [protected] |
void | PackDescriptorTypeAdvance | ( | const TDesC8 & | aDes, |
TInt & | aOffset | |||
) | [protected] |
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.
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.
void | UnpackTPtrAdvance | ( | TPtrC8 & | aDes, |
TInt & | aOffset | |||
) | [protected] |
TInt | iSize | [protected] |
Cumulative size of the derived type. All ctors in the inheritence tree increment with their size
Copyright ©2010 Nokia Corporation and/or its subsidiary(-ies).
All rights
reserved. Unless otherwise stated, these materials are provided under the terms of the Eclipse Public License
v1.0.