Using Symbain OS String Descriptors
This article shows startup usage of Symbian OS descriptors.
Introduction
When I was new to Symbian, The first thing I encountered was Symbian OS String handling and manipulations. It was then days of nightmare that struck me :). What I found was that it's a bit tricky to remember the descriptor stuffs, but once you get the trick it’s easy. No, I am not kidding..
So here I am trying to explain how I learned the basic Symbian OS string handling and tried to remember the things. I will not go into a war of words regarding whether having descriptors is a good approach or not, because whether it is good or bad you have to use it :(. Another thing I will not discuss here is how you can do similar things using plain C++ or how to do something with plain C++ string manipulation techniques. This article is just about descriptors.
The prerequisite of this article is a working knowledge of the Symbian OS.
Background
The very first thing you need to do is to remember the descriptor hierarchy. This is very important as all of the five descriptors you are going to use are derived from some classes and you must know from which class they are derived to be able to successfully decide which particular descriptor should be used and in which scenario. I am not going to explain what a buffer descriptor and Heap Descriptor mean, and also what is meant by modifiable and non modifiable descriptors. I believe you must be having enough information about what is meant by the above terminologies. I will also not use 8 and 16 bit variants, as functionality wise there is a similarity between these two and also these are not important in understanding the descriptors. The Symbian Descriptor Hierarchy looks fabulous. (Sorry for not providing fabulous pictures of Descriptor hierarchy). You can have a look at newlc for pictures.
Usage of TPtrC<n>
If you want a literal meaning for this, then it is a "Pointer to a data that cannot be manipulated". The basic thing to remember about TPtrC<n>
is that it contains no manipulation functionalities of its own and that it just contains constructors and set methods, and since it is derived directly from TDesC
it contains all the functionalities of TDesC
.
The pointer will point to data in one of the two ways:
- Create an empty
TPtrC<N>
and then point it to some data usingSet(...)
functions. - Pass the data while constructing by using any one of the overloaded constructors.
Let's see the above statements with the help of a few examples given below:
- Example 1:- Getting
TPtrC
fromTBuf
andTBufC
:LIT(KText , "Test Code"); TBufC<10> Buf ( KText ); OR(/) TBuf<10> Buf ( KText ); // Creation of TPtr using Constructor TPtrC Ptr (Buf); // Creation of TPtr using Member Function TPtrC Ptr1; Ptr1.Set(Buf);
- Example 2:- Getting
TPtrC
fromTText*
:The example below uses
TText16
:TText * text = _S("Hello World\n"); TPtrC ptr(text); // OR TPtrC Ptr1; Ptr1.Set(text); // To store only a part of TText we can use the following // This descriptor pointer will store only Hello TPtrC ptr4 ( text , 5 );
- Example 3:- Getting
TPtrC
from anotherTPtrC
:You can easily assign one
TPtrC
to another.TText * text = _S("Hello World\n"); TPtrC ptr(text); // Get TPtrC from another TPtrC TPtrC p1(ptr); // OR TPtrC p2; p2.Set(ptr);
- Example 4:- Getting
TText *
fromTPtrC
:We can get the
TText *
fromTPtrC
by using thePtr()
member.// Set the TPtrC _LIT(KText , "Test Code"); TBufC<10> Buf ( KText ); TPtrC Ptr1 (Buf); // Get the TText * TText * Text1 = (TText *)Ptr1.Ptr();
Usage of TBufC<n>
The examples used to describe the working TPtrC
gives some understanding about the usage of TBufC<n>
, Nevertheless here are a few examples on how to create TBufC<n>
.
- Example 5:- Instantiating the
TBufC<N>
:// Instantiating the TBufC from Literals _LIT(Ktext, "TestText"); TBufC<10> Buf (Ktext); // or TBufC<10> Buf2; Buf2 = Ktext; // Creating a new TBufC with existing TBufC TBufC<10> Buf3(Buf2);
TBufC<n>
is used generally for text data. For binary data, explicitTBufC8<n>
is used. ThoughTBufC<n>
means that the data cannot be modified ('C' stands for Constant), there are two ways by which this data can be modified:- The data can be replaced by using assignment operator.
- By using
Des()
function to construct aTPtr
modifiable pointer descriptor for the buffer data.
Let's see the first way to change the contents of
TBufC<n>
. - Example 6:- Changing the contents of
TBufC<N>
:// Describe some literals for Testing example _LIT(Ktext , "Test Text"); _LIT(Ktext1 , "Test1Text"); // Generate TPtrC TBufC<10> Buf1 ( Ktext ); TBufC<10> Buf2 ( Ktext1 ); // Change the contents of Buf2 Buf2 = Buf1; // Create an Empty TBufC and assign it to Buf1 TBufC<10> Buf3; Buf3 = Buf1;
Another way of changing the contents of
TBufC<n>
is by using theDes()
member. This member function returnsTPtr
modifiable pointer descriptor using members of theTPtr
. The maximum length of theTPtr
is the value of theTBufC<n>
template parameter. All the manipulating functions are fromTDesC
base. - Example 7:- Changing the contents of
TBufC<N>
usingDes()
:_LIT(Ktext , "Test Text"); _LIT(KXtraText , "New:"); TBufC<10> Buf1 ( Ktext ); TPtr Pointer = Buf1.Des(); // delete the last 4 characters Pointer.Delete(Pointer.Length()-4, 4 ); // the length should be changed now TInt Len = Pointer.Length(); // Append the new one Pointer.Append(KXtraText); Len = Pointer.Length(); // To completly changed the buffer we can use following _LIT(NewText , "New1"); _LIT(NewText1 , "New2"); TBufC<10> Buf2(NewText); // change the context Pointer.Copy(Buf2); // or Directly from literal Pointer.Copy(NewText1); // All the above changed actually changing the contents of Buf1
Working with Heap Descriptor HBufC
HBufC
is the descriptor of choice when we don’t know the size of the data that we want to have in the descriptor. Here 'C' stands for constant that means the data is constant but it can also be changed in two ways as it was changed in the case of TBufC<n>
. First using the assignment operator and another by using the modifiable pointer descriptor, i.e. TPtr
using Des()
member function. There are two things to remember while using the HBufC
.
- If you need to pass
HBufC
to a function that takesTDesC &
as a parameter, you need to simply dereference theHBufC
pointer. - The size of Heap Descriptor buffer can be changed using
ReAlloc
function as opposed toTBufC<N>
.
- Example 8:- Usage of
HBufC
:// Creation of a Heap Descriptor . There are 2 ways to do it // 1st way use either New(), NewL(), or NewLC() // Let see the example for this. This wills construct the HBufC with // a Data space for 15, but the current size is Zero. HBufC * Buf = HBufC::NewL(15); // 2nd way to used the Alloc(), AllocL(), or AllocLC() of // the existing descriptors. The new Heap descriptor is automatically // initialized with the content of descriptor. _LIT (KText , "Test Text"); TBufC<10> CBuf = KText; HBufC * Buf1 = CBuf.AllocL(); // Lets Check the size and Length . The size will be 18 // and length will be 9 TInt BufSize = Buf->Size(); TInt BufLength = Buf->Length(); // Changing what HBufC is pointing to _LIT ( KText1 , "Text1"); // Change the buffer to Point to KText1 using assignment operator *Buf1 = KText1; // And now changing the Data through Modifiable pointer descriptor TPtr Pointer = Buf1->Des(); Pointer.Delete( Pointer.Length() - 2, 2 ); // All operations that were done in case of TBufC<n> // is applicable here also. // here is one such operation _LIT ( KNew, "New:"); Pointer.Append( KNew );
Usage of TPtr
Ahaa, we are using it in place of TBufC<N>
and HBufC
, so we know most of it. So let’s remember how we can create TPtr
.
- Another
TPtr
. - From
TBufC<N>
,HBufC
usingDes()
member function. - From an explicit pointer to the memory and specifying the max length.
- From an explicit pointer to the memory and specifying the data as well as the maximum length.
- Example 9:- Usage of
TPtr
:// First lets see 2nd way of Getting TPtr _LIT(KText, "Test Data"); TBufC<10> NBuf ( KText ); TPtr Pointer = NBuf.Des(); // 1st way TPtr Pointer2 ( Pointer ); //3rd way using a memory area , Data and max length TText * Text = _S("Test Second"); TPtr Pointer3 ( Text ,11, 12); // Now we will see how to replace the data with TPtr ,it can // be done completly by using assignment Operator or copy function _LIT(K1, "Text1"); _LIT(K2, "Text2"); Pointer2 = K1; // Data will be Text1 Pointer.Copy(K2); // Data Will be Text2; // we can also change the length of the data or set it to zero Pointer2.SetLength(2); // Only Te will be there Pointer2.Zero(); // Make length of data as Zero // Data can be altered using the delete function as it used to alter // in the earlier examples.
Usage of TBuf<n>
In this the data doesn't remain constant. The operations, instantiation and assignment will be similar to that of the TBufC<n>
along with the modification functions that can be applied to it as it was applied in the case of TPtr
, like Copy, Delete, assignments etc.. I hope I don’t need to give examples for this section.
History
- Latest update.