Some examples about how to use descriptors and their associated methods

In this post I will try to outline the some of the functions from TDesC, inherited by rest of the classes and which are currently used when programming with descriptors.

Afterwards I will give some example about how the five types of descriptors are used (HBufC, TBuf, TBufC, TPtr, TPtrC).

Some of the methods defined in TDesC which I saw that are more frequently used are the following:

TDesC::Length

inline TInt Length() const;

as you may see this takes no parameter and returns the length in “characters” that the data pointed by the descriptor has. In case of 16-bit descriptors this returns half the the number of bytes, in case of 8-bit descriptors this returns exactly the number of bytes that data pointed to has. (this is the discussion about the differences between Size() and Length())


_LIT(KText,"Hello World!");
TBufC<16> buf1(KText); // buf1 is the existing descriptor
TPtrC ptr(buf1); // data in buf1 now accessible through ptr
ptr.Length(); // returns the length of the data (i.e. 12)

TDesC::Size

inline TInt Size() const;

We already had a discussion about this, we can skip it.

TDesC::Ptr

IMPORT_C const TUint8 *Ptr() const;

returns a pointer to the data  represented by the descriptor.  Do not worry if you do not understand what  IMPORT_C is meaning, me, I’m also not understanding its significance. All I can say about those macros (IMPORT_C and EXPORT_C) is that they are useful when you want to link to them with another executable application, DLL or EXE. Those macros are making your code accessible outside your program.

TDesC::Compare

IMPORT_C TInt Compare(const TDesC8 &aDes) const;

compares the current descriptor with the one passed as parameter

See below how it is used:

_LIT16(Kabcd,  "abcd");
_LIT16(Kabcde, "abcde");
_LIT16(Kabc,   "abc");
_LIT16(Kabcx,  "abcx");
...
TBufC16<8> str(Kabcd);
...
str.Compare(Kabcde);    // returns -ve
str.Compare(Kabc);      // returns +ve
str.Compare(Kabcd);     // returns zero
str.Compare(Kabcx);     // returns -ve

TDesC::Match

IMPORT_C TInt Match(const TDesC8 &aDes) const;

searches for a matching pattern which is supplied as argument

Below how it is used:

_LIT16(KAtoZ,"abcdefghijklmnopqrstuvwxyz");
TBufC16<32> str(KAtoZ);
...
_LIT16(KMatch1,"*ijk*");
str.Match(KMatch1);          //returns 8

_LIT16(KMatch2,”*i?k*”);
str.Match(KMatch2);          //        8

_LIT16(KMatch3,”ijk*”);
str.Match(KMatch3);          //         KErrNotFound

_LIT16(KMatch4,”abcd”);
str.Match(KMatch4);          //        KErrNotFound

_LIT16(KMatch5,”*i*mn*”);
str.Match(KMatch5);          //        8

_LIT16(KMatch6,”abcdef*”);
str.Match(KMatch6);          //      0

TDesC::Locate

IMPORT_C TInt Locate(TChar aChar) const;

searches for the first occurence of the data supplied as parameter. Oooops ! TChar ! Am I seeing good? Haven’t I just told you that character types were just replaced by descriptors? Actually this is is representing only a character, not an array.

_LIT16(Kabcd,"abcd");
TBufC16<8> str(Kabcd);
...
str.Locate('d');   // returns 3
str.Locate('a');   // returns 0
str.Locate('b');   // returns 1
str.Locate('x');   // returns KErrNotFound

TDesC::Find

IMPORT_C TInt Find(const TDesC16 &aDes) const;

searches for the first occurence of the specified data sequence. The difference with respect to Locate consists in the fact that the search is not only for a single
character but for the start of a certain character sequence.

_LIT16(KAtoZ,"abcdefghijklmnopqrstuvwxyz");
TBufC16<32> str(KAtoZ);
...
_LIT16(KFind1,"abc");
str.Find(KFind1);            // returns 0

_LIT16(KFInd2,”bcde”);
str.Find(KFInd2);            // returns 1

_LIT16(KFind3,”uvwxyz”);
str.Find(KFind3);            // returns 20

_LIT16(KFind4,”0123″);
str.Find(KFind4);            // returns KErrNotFound

TDesC::Left

IMPORT_C TPtrC16 Left(TInt aLength) const;

extracts the leftmost part of data

_LIT8(KData,"abcdefg");
TBufC8<8> str(KData);
str.Left(4); // the result is "abcd" , first 4 characters are extracted

TDes::Copy

IMPORT_C void Copy(const TDesC8 &aDes);

Copies data into this descriptor replacing any existing data. The length of this descriptor is set to reflect the new data.


_LIT8(Kabcdefg,"abcdefg");
_LIT8(Kabc,"abc");
_LIT8(Kabcdefghi,"abcdefghi");
...
TBuf8 str;
...
str.Copy(Kabcdefg); // copies "abcdefg" to str
str.Length(); // returns 7
str.MaxLength(); // returns 8
...
str.Copy(Kabc); // copies "abc" to str
str.Length(); // returns 3
str.MaxLength(); // returns 8
...
str.Copy(Kabcdefghi)); // Panics !!

TDes::Repeat

IMPORT_C void Repeat(const TUint8 *aBuf, TInt aLength);

Copies data with repetition into this descriptor, from a memory location specified by pointer, replacing any existing data.
Copying proceeds until this descriptor is filled up to its current length. If it cannot contain a whole number of copies of the source data, then the last copy is truncated.

The example below could clarify its use:

_LIT8(Kab,"ab");
_LIT8(Kabc,"abc");
_LIT8(Kabcde,"abcde");
...
TBuf8 tgt(8); // length of tgt is the same as the
... // maximum which is 8
... // following strings generated in tgt
...
tgt.Repeat(Kab); // "abababab"
tgt.Repeat(Kabc); // "abcabcab"
tgt.Repeat(Kabcde); // "abcdeabc"
...
... // changing length to 7 has the
... // following effect
tgt.SetLength(7);
tgt.Repeat(Kab); // "abababa"
tgt.Repeat(Kabc); // "abcabca"
tgt.Repeat(Kabcde); // "abcdeab"

TDes::Insert

IMPORT_C void Insert(TInt aPos, const TDesC8 &aDes);

Inserts data into this descriptor. The length of this descriptor is changed to reflect the extra data.

_LIT8(Kabc,"abc")
_LIT8(KUVWXYZ,"UVWXYZ")
_LIT8(KVWXYZ,"VWXYZ")
_LIT8(KWXYZ,"WXYZ")
_LIT8(KXYZ,"XYZ)
...
TBuf8 tgt(3);
... // generates the strings:
tgt = Kabc;
tgt.Insert(0,kXYZ); // "XYZabc"
...
tgt = Kabc;
tgt.Insert(1,KXYZ); // "aXYZbc"
...
tgt = Kabc;
tgt.Insert(tgt.Length(),KXYZ); // "abcXYZ"
...
tgt = Kabc;
tgt.Insert(tgt.Length()+1,KXYZ); // ----> Panic !!
...
tgt = Kabc;
tgt.Insert(1,KWXYZ); // "aWXYZbc"
...
tgt = Kabc;
tgt.Insert(1,KVWXYZ); // "aVWXYZbc"
...
tgt = Kabc;
tgt.Insert(1,KUVWXYZ); // ----> Panic !!

TDes::Replace

IMPORT_C void Replace(TInt aPos, TInt aLength, const TDesC8 &aDes);

Replaces data in this descriptor. The specified length can be different to the length of the replacement data. The length of this descriptor changes to reflect the change of data.

_LIT8(Kabcd,"abcd");
_LIT8(Ku,"u");
_LIT8(Kuv,"uv");
_LIT8(Kuvw,"uvw");
_LIT8(Kuvwxyz,"uvwxyz");
...
TBuf8 tgt(4);
... // generates the strings:
tgt = Kabcd;
tgt.Replace(0,1,Ku)); // "ubcd"
...
tgt = Kabcd;
tgt.Replace(0,1,Kuv); // "uvbcd"
...
tgt = Kabcd;
tgt.Replace(0,1,Kuvw); // "uvwbcd"
...
tgt = Kabcd;
tgt.Replace(0,1,Kuvwxyz); // ----> Panics !!
...
tgt = Kabcd;
tgt.Replace(1,2,Ku); // "aud"
...
tgt = Kabcd;
tgt.Replace(1,2,KNullDesC8);// "ad"
...
tgt = Kabcd;
tgt.Replace(1,4,Kuvw); // ----> Panics !!
...
tgt = Kabcd;
tgt.Replace(3,1,Kuvw); // "abcuvw"
...
tgt = Kabcd;
tgt.Replace(4,0,Kuvw); // "abcduvw"

Also Append() function, as well as its variants, worth studying, but I will stop here with TDesC and TDes methods presentation.

I will give you just some examples about how TBuf and TBufC are used.

TBuf has to be quite trivial:

_LIT(KText,"Hello World!");
...
TBufC buf1; // length of buf1 is 0
...
buf1 = KText; // data assigned

One of the most interesting and exciting of descriptors is that you can modify the content of a TBufC via a TPtr method. Something quite similar to modifying a constant variable in C, not directly through its own name, but through a pointer to it. (I wrote about this in a previous post).

Here’s the magic below:


_LIT(KText,"Hello World!");
_LIT(KExtraText," & Hi");
...
TBufC buf1(KText);
...
TPtr ptr = buf1.Des();
...
ptr.Delete((ptr.Length()-1),1);
ptr.Append(KExtraText);

What is the code above doing? Deletes the last character in buf1 and adds the characters “&Hi” so that buf1 now contains the text “HelloWorld&Hi” and its length is 16. Note that the length of both buf1 and ptr change to reflect the data that they now both represent. Note that any attempt to append more data raises a panic.

TBuf is much more flexible, you can change it, delete data from it, replace data, append data.

_LIT(KText,"Hello World!");
...
TBuf buf1; // length of buf1 is 0
...
buf1 = KText; // data assigned

_LIT(KText,"Hello World!");
...
TBuf buf1(KText);
TBuf buf2(buf1); // buf2 constructed from the data in buf1

A very very helpful resource in this way is, I say it again, the Nokia Forum Library. Every descriptor class is documented as well as their corresponding methods. Simple examples about how to use them are also provided.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: