Wiley.Symbian.OS.C.plus.plus.for.Mobile.Phones.Aug.2007 (779890), страница 29
Текст из файла (страница 29)
If it has been pushed and the callto ReAllocL() changes the address of aTarget then if the callingfunction calls CleanupStack::PopAndDestroy() there will be aUser-44 panic. The copyTextL() method could pop aTarget off thestack and then back on again in case the calling code had pushed it to thecleanup-stack; if the calling code hadn’t pushed it to the cleanup-stackthere will be an E32User-CBase 63 panic.The copyTextL() method could specify as a pre-condition thataTarget must not be on the cleanup-stack before the function is called,but then the calling code would have to TRAP the call to copyTextL() inthe event of a leave. However specifying such a pre-condition inevitablyleads to complexity, is error prone and inelegant. In such a situation, it ispreferable to use an RBuf instead, as described in Section 5.9.Be Aware of the Difference Between %s and %S when FormattingIf you are passing a descriptor to a method that takes a formatting specifier,then be aware that C-style strings are formatted using %s and descriptorsare formatted using %S; the address of the descriptor must be passed asthe argument.
The following code causes an exception:_LIT(KTxtHelloWorld, "Hello World!");TBufC<20> constantBuffer(KTxtHelloWorld);_LIT(KFormatTxt, "%S");console->Printf(KFormatTxt, constantBuffer);// should be &constantBufferUse LIT Instead of LIn older versions of Symbian OS, the _LIT macro and TLitC class didn’texist. The only way of creating a literal was to use the _L macro thatproduces a TPtrC from a literal value and can be used without a name,so you can write the following in your program:TPtrC helloRef(_L("hello"));While this works, it is inefficient and the_LIT macro was created asa more efficient alternative. When using _LIT, no run-time temporary136DESCRIPTORSand no inline constructor code are generated and so the ROM budget issignificantly reduced for components that contain many string literals.The use of _L is deprecated.
It is nevertheless still acceptable to use itin test programs where it is convenient as it doesn’t have to be declaredseparately:User::Panic(_L("Test code panic"), KMyTestCodeError);You may occasionally see the macro _S. Like _L, it too is deprecatedfor production code but it is still used in test code. It is similar to the _Lmacro in the way the string is stored in the program binary but it does notconstruct a temporary TPtrC around the string.TText* text = _S("Hello World\n");_L, _S and _LIT are defined in e32def.h as:#if defined(_UNICODE)#define _L(a) (TPtrC((const TText *)L ## a))#define _S(a) ((const TText *)L ## a)#define _LIT(name,s) static const TLitC<sizeof(L##s)/2>name={sizeof(L##s)/2-1,L##s}#else#define _L(a) (TPtrC((const TText *)(a)))#define _S(a) ((const TText *)a)#define _LIT(name,s) static const TLitC<sizeof(s)>name={sizeof(s)-1,s}#endifAvoid Declaring Literals in Header FilesWhen using literals, try not to declare them in a header file because allCPP files that include it generate a new copy, leading to code bloat.Instead put your _LITs in the CPP file and have a method return areference to it:_LIT(KTxtHelloWorld, "Hello World!");EXPORT_C const TDesC& CMyClass::GetHelloText() const{ return KTxtHelloWorld; }Initialize TPtr Class Data MembersTPtr does not have a default constructor, so when it is used as a datamember of a class, it must be initialized in the constructor initializationlist, otherwise a compilation error is generated.CORRECT USE OF DESCRIPTORS137class CSomeClass : public CBase{...TPtr iPtr;};CSomeClass::CSomeClass() : iPtr(0,0){}Perform Bounds CheckingDescriptors perform checks when data is being inserted or appended andso they panic if the resulting length would be greater than the maximumlength, therefore you should always take care to ensure there is sufficientspace for the operation to succeed:_LIT(KSomeText,"Some Text");void Foo(TDes& aDescriptor){if (aDescriptor.Length() + KSomeText().Length() <=aDescriptor.MaxLength())aDescriptor.Append(KSomeText);else// handle error situation}In order to keep the example code small, the examples in this chapterdo not contain any explicit bounds checking but that doesn’t mean youshould not do it.Implicit bounds checking is performed if you attempt to access an itembeyond the end of the descriptor.
The following code generates a panic:_LIT(KTxtHello, "Hello");TBufC<5> buf(KTxtHello);TChar ch = buf[KTxtHello().Length()];You should also be mindful not to confuse the Length() and Size()methods. Length() returns the conceptual length of a string whileSize() returns the total number of bytes it occupies. These are notalways the same – a narrow string’s size is the same as its length but awide string’s length is half its size."Hello"L"Hello"////////this narrow string’s conceptual length is 5,one byte per characterthis wide string’s conceptual length is also 5,but with two bytes per character its size is 101385.12DESCRIPTORSManipulating DescriptorsThis section provides a brief summary of the descriptor methods available.It is not possible to describe the API in full here due to its large size.
Formore information, consult your SDK.The methods use some descriptor-specific naming conventions:• a method name containing an uppercase F, such as LocateF(),indicates folding, a process that sets everything to upper case andremoves accents• a method name containing LC, such as CopyLC(), indicates lowercase, provided the descriptor is not a heap-based descriptor (RBuf orHBufC); for heap-based descriptors, LC follows the standard Symbianconvention, as in AllocLC(), to mean leave and push to the cleanupstack• a method name containing UC, such as CopyUC(), indicates uppercase• a method name containing an uppercase C, but not preceded by anuppercase L, such as FindC() indicates collation, the process ofremoving any differences between characters so that they can be putin a sequence that allows for straightforward comparisons.FoldingFolding is a relatively simple way of normalizing text for comparisonby removing case distinctions, converting accented characters to characters without accents, etc.
Folding is used for tolerant comparisons, i.e.comparisons that are biased towards a match.For example, the file system uses folding to decide whether two filenames are identical or not. Folding is locale-independent behavior, andmeans that the file system, for example, can be locale-independent.Variants of member methods that fold are provided where appropriate.For example, TDesC16::CompareF()14 for folded comparison.It is important to note that there can be no guarantee that folding isin any way culturally appropriate. It should not be used for comparingstrings in natural language; collation is the correct functionality for this.CollationCollation is a much better and more powerful way to compare stringsand produces a dictionary-like (‘lexicographic’) ordering.
Folding cannot14Be aware that CompareF() is much slower than Compare().MANIPULATING DESCRIPTORS139remove accents or deal with correspondences that are not one-to-one(such as the mapping from German upper case SS to lower case ß). Inaddition, folding cannot optionally ignore punctuation.For languages using the Latin script, for example, collation is aboutdeciding whether to ignore punctuation, whether to fold upper and lowercase, how to treat accents, and so on. In a given locale there is usually astandard set of collation rules that can be used.
Collation should alwaysbe used for comparing strings in natural language.Variants of member functions that use collation are provided whereappropriate. For example, TDesC16::CompareC() for collated comparison.Basic FunctionsUse Length() to find the logical length of data, for example howmany characters it is, and Size() to find out how many bytes thedata occupies. Be careful not to use Size() where you really meanLength().TDes provides MaxLength(), which tells you the maximum lengthof the data area. If the descriptor is intended to hold a string, then thisis the maximum number of characters that the descriptor can hold.
Anymanipulation method that exceeds this causes a panic.If you write your own string-handling methods, you normally constructthem using the descriptor library methods. In some circumstances, youmay wish to access descriptor contents directly, and manipulate themusing C pointers; Ptr() allows you to do this – but be careful. Inparticular, make sure that you honor MaxLength() if you’re modifyingdescriptor data, and make sure that any method you write panics if askedto do something that would overflow the allocated MaxLength(); thestandard way of ensuring this is to call SetLength() before modifyingthe content, which panics if the length exceeds MaxLength().Manipulating Data• TDes::Copy() copies data to the descriptor starting at the beginning,while Append() can copy additional data to the descriptor, startingwhere the existing data stops.