Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Symbian OS Explained - Effective C++ Programming For Smartphones (2005) [eng].pdf
Скачиваний:
60
Добавлен:
16.08.2013
Размер:
2.62 Mб
Скачать

60

DESCRIPTORS: SYMBIAN OS STRINGS

5.3 Pointer Descriptors

The string data of a pointer descriptor is separate from the descriptor object itself and can be stored in ROM, on the heap or on the stack. The memory that holds the data is not ”owned” by the descriptor and is not managed through it. Thus, if it is on the heap, the memory is created, reallocated if necessary, and destroyed using a heap descriptor pointer (HBufC, described below). If a pointer descriptor is referencing a stackbased string, the memory in question will already have been allocated on the stack. The pointer descriptors themselves are usually stack-based, but they can be used on the heap, for example as a member variable of a CBase-derived class. Pointer descriptors are agnostic about where the memory they point to is actually stored.

In a non-modifiable pointer descriptor (TPtrC), the pointer to the data follows the length word, thus the total size of the descriptor object is two words. In a modifiable pointer descriptor (TPtr), it follows the maximum length word and the descriptor object is three words in length. Figure 5.1 compares the memory layouts of TPtr and TPtrC.

TPtrC

 

 

 

 

 

 

 

 

 

 

 

iLength

iPtr

 

 

Hello World!

 

12

 

 

 

 

 

 

 

 

ROM, heap or stack

 

 

 

 

TDesC

TPtrC

 

 

TPtr

 

 

 

 

 

 

 

 

 

 

iLength

iMaxLength

iPtr

 

 

 

12

12

 

 

 

 

 

 

 

 

 

 

TDesC

TDes

TPtr

Figure 5.1 Memory layouts of pointer descriptors

TPtrC

TPtrC is the equivalent of using const char* when handling strings in C. The data can be accessed but not modified: that is, the data in the descriptor is constant. All the non-modifiable operations defined in the TDesC base class are accessible to objects of type TPtrC. The class also defines a range of constructors to allow TPtrC to be constructed from another descriptor, a pointer into memory or a zero-terminated C string.

POINTER DESCRIPTORS

61

// Literal descriptors are described later in this chapter _LIT(KLiteralDes, "Sixty zippers were quickly picked from the woven

jute bag");

TPtrC pangramPtr(KLiteralDes);

// Constructed from a literal descriptor

TPtrC copyPtr(pangramPtr);

// Copy constructed from another TPtrC

TBufC<100> constBuffer(KLiteralDes); // Constant buffer descriptor

TPtrC ptr(constBuffer);

// Constructed from a TBufC

//TText8 is a single (8-bit) character, equivalent to unsigned char const TText8* cString = (TText8*)"Waltz, bad nymph, for quick jigs

vex";

//Constructed from a zero-terminated C string

TPtrC8 anotherPtr(cString);

TUint8* memoryLocation; // Pointer into memory initialized elsewhere TInt length; // Length of memory to be represented

...

TPtrC8 memPtr(memoryLocation,length); // Constructed from a pointer

The pointer itself may be changed to point at different string data – the Set() methods in TPtrC are defined for that purpose. If you want to indicate that the data your TPtrC points at should not be changed, you can declare the TPtrC to be const, which typically generates a compiler warning if an attempt is made to call Set() upon it. It will not fail, however, since the rules of const-ness in C++ are such that both const and non-const functions may be called on a const object.

// Literal descriptors are described later in this chapter _LIT(KLiteralDes1, "Sixty zippers were quickly picked from the woven jute

bag");

_LIT(KLiteralDes2, "Waltz, bad nymph, for quick jigs vex");

TPtrC alpha(KLiteralDes1);

TPtrC beta(KLiteralDes2);

alpha.Set(KLiteralDes2); // alpha points to the data in KLiteralDes2 beta.Set(KLiteralDes1); // beta points to the data in KLiteralDes1

const TPtrC gamma(beta); //

Points to

the data in beta, KLiteralDes1

gamma.Set(alpha);

//

Generates

a warning, but points to alpha

TPtr

TPtr is the modifiable pointer descriptor class for access to and modification of a character string or binary data. All the modifiable and non-modifiable base class operations of TDes and TDesC respectively may be performed on a TPtr.

62

DESCRIPTORS: SYMBIAN OS STRINGS

The class defines constructors to allow objects of type TPtr to be constructed from a pointer into an address in memory, setting the length and maximum length as appropriate.

The compiler also generates implicit default and copy constructors, since they are not explicitly declared protected or private in the class. A TPtr object may be copy constructed from another modifiable pointer descriptor, for example, by calling the Des() method on a non-modifiable buffer, which returns a TPtr as shown below:

_LIT(KLiteralDes1, "Jackdaws love my big sphinx of quartz"); TBufC<60> buf(KLiteralDes1); // TBufC are described later

TPtr ptr(buf.Des()); // Copy construction; can modify the data in buf TInt length = ptr.Length(); // Length = 12

TInt maxLength = ptr.MaxLength(); // Maximum length = 60, as for buf

TUint8* memoryLocation;

// Valid pointer into memory

...

 

 

TInt len = 12;

// Length of data to

be represented

TInt maxLen = 32;

// Maximum length to

be represented

// Construct a pointer descriptor from a pointer into memory

TPtr8 memPtr(memoryLocation, maxLen); // length = 0, max length = 32 TPtr8 memPtr2(memoryLocation, len, maxLen); // length = 12, max = 32

In addition, the class provides an assignment operator, operator =(), to copy data into the memory referenced by the pointer (from another modifiable pointer descriptor, a non-modifiable pointer or a zero-termin- ated string). If the length of the data to be copied exceeds the maximum length of the descriptor, a panic will be raised. Like TPtrC, this class also defines a Set() method to change the descriptor to point at different data.

_LIT(KLiteralDes1, "Jackdaws love my big sphinx of quartz");

TBufC<60> buf(KLiteralDes1);

// TBufC are described later

TPtr ptr(buf.Des());

// Points to the contents of buf

TUint16* memoryLocation;

// Valid pointer into memory

...

TInt maxLen = 40; // Maximum length to be represented

TPtr memPtr(memoryLocation, maxLen); // length = 12, max length = 40

// Copy and replace

memPtr = ptr; // memPtr data is KLiteralDes1 (37 bytes), maxLength = 40

_LIT(KLiteralDes2, "The quick brown fox jumps over the lazy dog");

TBufC<100> buf2(KLiteralDes2);

//

TBufC are

described later

TPtr ptr2(buf2.Des());

//

Points to

the data in buf

STACK-BASED BUFFER DESCRIPTORS

63

// Replace what ptr points to

ptr.Set(ptr2); // ptr points to contents of buf2, max length = 100 memPtr = ptr2; // Attempt to update memPtr which panics because the

// contents of ptr2 (43 bytes) exceeds max length of memPtr (40 bytes)

You should be careful not to confuse Set(), which resets your descriptor to point at a new data area (with corresponding modification to the length and maximum length members) with operator =() which merely copies data into the existing descriptor (and may modify the descriptor length but not its maximum length).

5.4 Stack-Based Buffer Descriptors

The stack-based buffer descriptors may be modifiable or non-modifiable. The string data forms part of the descriptor object, located after the length word in a non-modifiable descriptor and after the maximum length word in a modifiable buffer descriptor. Figure 5.2 compares the memory layouts of TBuf and TBufC.

TBufC <12>

 

 

 

 

 

 

 

iLength

iBuf

 

 

12

Hello World!

 

 

 

 

 

 

TDesC

TBufC

 

 

TBufC <15>

 

 

 

 

 

 

iLength

iMaxLength

iBuf

 

12

15

Hello World!

 

 

 

 

 

TDesC

TDes

TBuf

Figure 5.2 Buffer descriptors

These descriptors are useful for fixed-size or relatively small strings, say up to the length of a 256-character filename. Being stack-based, they should be used when they have a lifetime that coincides with that of their creator. They may be considered equivalent to char[] in C, but with the benefit of overflow checking.

64

DESCRIPTORS: SYMBIAN OS STRINGS

TBufC<n>

This is the non-modifiable buffer class, used to hold constant string or binary data. The class derives from TBufCBase (which derives from TDesC, and exists as an inheritance convenience rather than to be used directly). TBufC<n> is a thin template class which uses an integer value to determine the size of the data area allocated for the buffer descriptor object. Chapter 19 describes the thin template pattern and its role in Symbian OS code.

The class defines several constructors that allow non-modifiable buffers to be constructed from a copy of any other descriptor or from a zeroterminated string. They can also be created empty and filled later since, although the data is non-modifiable, the entire contents of the buffer may be replaced by calling the assignment operator defined by the class. The replacement data may be another non-modifiable descriptor or a zero-terminated string, but in each case the new data length must not exceed the length specified in the template parameter when the buffer was created.

_LIT(KPalindrome, "Satan, oscillate my metallic sonatas");

TBufC<50>

buf1(KPalindrome); //

Constructed

from

literal descriptor

TBufC<50>

buf2(buf1);

//

Constructed

from

buf1

// Constructed from a NULL-terminated C string TBufC<30> buf3((TText*)"Never odd or even");

TBufC<50> buf4; // Constructed empty, length = 0

// Copy and replace

buf4 = buf1; // buf4 contains data copied from buf1, length modified buf1 = buf3; // buf1 contains data copied from buf3, length modified buf3 = buf2; // Panic! Max length of buf3 is insufficient for buf2 data

The class also defines a Des() method which returns a modifiable pointer descriptor for the data represented by the buffer. So, while the content of a non-modifiable buffer descriptor cannot normally be altered directly, other than by complete replacement of the data, it is possible to change the data indirectly by creating a modifiable pointer descriptor into the buffer. When the data is modified through the pointer descriptor, the lengths of both the pointer descriptor and the constant buffer descriptor are changed although, of course, the length is not automatically extended because the descriptor classes do not provide memory management.

_LIT8(KPalindrome, "Satan, oscillate my metallic sonatas"); TBufC8<40> buf(KPalindrome); // Constructed from literal descriptor TPtr8 ptr(buf.Des()); // data is the string in buf, max length = 40

// Illustrates the use of ptr to copy and replace contents of buf ptr = (TText8*)"Do Geese see God?";