String and Descriptors

in

The choice of Symbian not to use common types and functions for handling strings and binary buffer may look quite surprising for many developers new to this platform. And probably more than one developer has spent a couple of hours wondering about the respective merits of Tbuf, TbufC, HbufC,...

The main characteristics of Symbian descriptors are:
-  strings and binary data are threated the same way
-  data can reside in any memory location, either ROM or RAM, on the stack or on the heap
-  a descriptor object maintains pointer and length information to describe its data. Some descriptors also include a maximum length

The following diagram shows the descriptor classes hierarchy:

descriptors.png

All descriptors inherits from the abstract class TDesC. They come in three types:
-  Buffer descriptors - where the data is part of the descriptor object and the descriptor object lives on the program stack: TBufand TBufC,
-  Heap descriptors - where the data is part of the descriptor object and the descriptor object lives on the heap: HBufC,
-  Pointer descriptors - where the descriptor object is separate from the data it represents: TPtr and TPtrC.

An analogy with classical C/C++ gives:
-  TPtrC should be used where const char * used to
-  TBufCwhere char [] used to.

The other classes have no equivalent.

Here is how data are organized within each class:

descriptors3.png

TDes and TDesC are abstract classes so you cannot instantiate them. Their main use is in as argument of function manipulating strings and binary data. In such function, you will use:
-  const TDesC& for read-only string or data
-  TDes& for passing string or data you want to modify.

All the descriptors can have some width specifier: TDes8, TDes16, TDesC8, TDesC16, TBuf8, TBuf16,... 8 specifies that the descriptor handle 8 bits data, and 16 stands for 16 bits. Generally, you will use the neutral form (TDes, TDesC,...) for text data and the 8 bits version (TDesc8,...) for binary content.

Litterals

Strings constant are often defined using the _L() or _LIT() macros.

_L() produces a TPtrC from a literal value. It is typically used to pass a string to a function:

NEikonEnvironment::MessageBox(_L("Error: init file not found!"));

_LIT() generates named constant that can be reused across your application:

_LIT(KMyFile,"c:\\System\\Apps\\MyApp\\MyFile.jpg");

The result of the _LIT() macro (KmyFile on the example above) is a literal descriptor TLitC which can be used wherever a TDesC& could.

Usage

The most commonly used function are defined in TDesC. They are:
-  Ptr() to get a pointer on the descriptor data
-  Length() to get the number of characters in the descriptor data.
-  Size() to get the number of bytes in the descriptor data.
-  Compare() or operators ==, !=, >= and <= for descriptor data comparison
-  the operator [] can be used - as in C/C++ - to get a single char from a descriptor string

Several functions pictured above comes in several flavors:
-  Append() and Num() have several variants that cannot been described here but are well described in the Symbian Developer Library.
-  Compare()has variants named CompareC() and CompareF(). So do Copy(), Find(), Locate(), and Match() : all of these have a C and/or F variant. C stands for Collatedand F for Folded.

Collating and Folding

Folding is a relatively simple way of normalizing text for comparison by removing case distinctions, converting accented characters to characters without accents etc. Folding is typically used for tolerant comparisons

Collation is a much better and more powerful way to compare strings and produces a dictionary-like ('lexicographic') ordering. For languages using the Latin script, for example, collation is about deciding whether to ignore punctuation, whether to fold upper and lower case, how to treat accents, and so on. In a given locale there is usually a standard set of collation rules that can be used.


> String and Descriptors

Very good article to get started with. A follow-up describing conversions between Descriptors would be nice? I.e. which have to be cast and which can be assigned directly, etc...

> String and Descriptors

Maybe memory representation of TPtr in the diagram is wrong too?

58->

Memory representation

1. I agree with gogo.
5 8 ->
TPtr inherits from TDes which inherits form TDesC. iLength, iMaxLength and then iPtr

2. TPtr and TPtrC do not have to necessarily point to data on the heap, do they?

2. TPtr and TPtrC do not

2. TPtr and TPtrC do not have to necessarily point to data on the heap, do they?

No they don't ! A TPtr can point to data on the stack of course !

Ok ok, It's just that the

Ok ok, It's just that the image above can suggest that for someone totally fresh to descriptors.

Conversions

The TBufC objects can be used to initialize TBuf provided integer template parameter should be same. Likely, can TPtr be initiazed with TPtrC?

Conversions

Not directly because you loose the "constness" of the descriptor in that case.

> String and Descriptors

Indirectly how?? Can u plz tell me.

> String and Descriptors

_LIT(KHello,"Hello"); TBufC<10> buf(KHello);

According to the diagramatic description of TBufC whether the object'buf' contains 10 followed by "Hello" or 5 followed by "Hello"

> String and Descriptors

The first thing a new user may want to do with descriptors is to use them as strings. And the first thing you'd probably want to do is display them, say using a console print statement or a RDebug print statement. That way you can find out what your Descriptor operations are doing.

Unfortunately, tutorials on Descriptors tend to leave this out. However a Descriptor can be printed quite easily. Assume test is an RTest object and aDes is a TBufC.

test.print(_L("The Descriptor says %S"), &aDes);

Will print out the contents of the descriptor. The important features are the Capital '%S' and using the Address of the descriptor as a parameter.

> String and Descriptors

It seems the diagramatic representation of HBufC is wrong. The data section first octet should represent the length of the buffer.


| 5 | N | E | W | L | C |


> String and Descriptors

I found that this article is very good for starters. Moreover, the diagramatic representation of TPtr,TPtrC,HBufC... made my fundamentals regarding descriptors more stronger. Thanx a lot. I think the diagramatic representation of HBufC is wrong.Please verify.If so, kindly change the diagaram.

> String and Descriptors

Shouldn't "All descriptors inherits from the abstract class TDes" be "All descriptors inherits from the abstract class TDesC"?

> String and Descriptors

You're definitely right....... Thanks to have noticed this!

> String and Descriptors

sir,

how to copy the contents of a TPtrC to TBuf. in general how to copy the contents of a pointer descriptor to a buffer descriptor. please help me. please email the suggestion to praveenbm5@yahoo.com

thank you,

Praveen