Wiley.Developing.Software.for.Symbian.OS.2nd.Edition.Dec.2007 (779887), страница 38
Текст из файла (страница 38)
more code here, can leave on errorsCleanupStack::PopAndDestroy(myRbuf);In this example, the RBuf object myRbuf takes ownership of the rawallocated buffer, buff. CleanupStack::PopAndDestroy() (or a186STRINGS, BUFFERS, AND DATA COLLECTIONSleave if one occurs) invokes the myRbuff Close() method to deletethe buffer. You do not need to call delete on the buff pointer.You can also take ownership of a HBufC descriptor or anotherRBuf descriptor using the RBuf::Assign(HBufC16 *aHbuf) andRBuf::Assign(const RBuf16 aRBuf), respectively.
In addition, youcan take ownership of a HBufC call in the RBuf constructor like thefollowing:HBufC* myHBufC = HBufC::NewL(100);RBuf myRbuf(myHBufC);Multiple RBuf assignmentsYou can assign buffers multiple times in an RBuf, but you need to makesure you free the previous one first via Close() before making a newassignment or you will have an orphaned allocation (and thus memoryleak).
For example:TBuf<100> myTbuf(_L("TBuf stuff"));RBuf myRbuf1;myRbuf1.CreateL(myTbuf);myRbuff.CleanupClosePushL();// ... more code here, can leave on errorsHBufC* HBufC = HBufC::NewL(100);CleanupStack::PopAndDestroy(myRbuf1); // free previous buffermyRbuf1.Assign(HBufC);myRbuf1.CleanupClosePushL();// more code here, can leave on errorsCleanupStack::PopAndDestroy(myRbuf1); // free the HBufCResizing buffersLike HBufC, RBuf provides a ReAlloc() method to change its buffersize (e.g., expanding the buffer when you are running out of room, orshrinking it to just the space needed). Unlike HBufC, however, whereyou would need to update the descriptor’s pointer on ReAlloc() sincethe heap address of HBufC could have changed, the RBuf ReAlloc()works transparently since the heap pointer is stored internal to the class.Like HBufC, a ReAllocL() version of the ReAlloc() also exists forRBuf that performs a leave if an error occurs.6.4 Descriptor MethodsThis section describes the key methods of descriptors and gives examplesof how to use them.DESCRIPTOR METHODS187I have divided the methods into two parts – those methods thatinvolve reading descriptor data only (the TDesC methods) and thosethat involve setting and otherwise modifying the descriptor’s buffer (theTDes methods).
You will see that the overwhelming majority of functionsare for operating on strings.See the SDK API reference for the complete list of descriptor methodsas well as the detailed function prototypes and return status descriptionsfor each descriptor method.6.4.1Non-modifying MethodsThis section describes the key descriptor methods that involve no writingto the descriptor data buffer. These methods are implemented in TDesCand thus can be used by all descriptors.Comparing descriptor dataTo compare the contents of one descriptor to the contents of another, useone of the Compare() methods.For example:des1.Compare(des2);compares the data in descriptor des1 with the data in descriptor des2and returns 0 if the data is the same, or a negative or positive numberif the des2 data is less than or greater than des1 (in alphabetic order),respectively.
Compare() behaves like strcmp() does in C.In addition to Compare(), you can also use CompareF() and CompareC(). These methods are the same as Compare() except that theycompare the data in a normalized form for more tolerant comparisons.CompareF() compares the data normalized via folding. Folding is a simple locale-independent normalization method where case and accentsare ignored. CompareC() performs the compare with a more powerful,locale-dependent normalization known as collation. While folding onlydoes simple one-to-one mappings (e.g., lower to upper case) for comparisons, collation uses a dictionary-like ordering where it can make morecomplex decisions about string differences that can be safely ignored,and these rules are dependent on the locale.The following shows an example of using the compare functions:void CompareExample(){_LIT(KString1,"My String");_LIT(KString2,"MY STRING");_LIT(KString3,"Another string");188STRINGS, BUFFERS, AND DATA COLLECTIONSTBuf<20> str1(KString1);TBuf<20> str2(KString2);TInt res;/* Compare shows a match since str1 is initialized to KString1 */res = str1.Compare(KString1);_LIT(KFormatCompare1,"Compare() string 1 and string 1 = %d\n");console->Printf(KFormatCompare1, res);/* Compare shows a no match since str1 and str2 contents do* not exactly match*/res = str1.Compare(str2) ;_LIT(KFormatCompare2,"Compare() string 1 and string 2 = %d\n");console->Printf(KFormatCompare2, res);/* Compare shows a match since a folded compare is case insensitive */res = str1.CompareF(str2) ;_LIT(KFormatCompare3,"CompareF() string 1 and string 2 = %d\n");console->Printf(KFormatCompare3, res);/* Compare shows a mismatch since string 1 and 3 are different */res = str1.Compare(KString3);_LIT(KFormatCompare4,"Compare() string 1 and string 3 = %d\n");console->Printf(KFormatCompare4, res);}The output from the code is:Compare() string 1 and string 1 = 0Compare() string 1 and string 2 = 32CompareF() string 1 and string 2 = 0Compare() string 1 and string 3 = 12Finding substrings within a descriptorTo locate a substring within a descriptor, you can use Find().
Find()looks for the first occurrence of a substring within a descriptor and returnsits start position, if it is found.For example:des1.Find(KSomeSubString);returns KErrNotFound (–1) if the substring KSomeSubString is notfound in des1, or the starting position of the substring in des1 if thesubstring is found.FindF() and FindC() are the same as Find() except that they usethe tolerant fold and collation comparisons (respectively) to search forthe string.Here is an example of using the Find() functions:void FindExample(){_LIT(KString1,"This is a test string");DESCRIPTOR METHODS189_LIT(KString2,"test");_LIT(KString3,"car");_LIT(KString4,"TEST");TBuf<40> buf(KString1);TInt res;/* Find returns position of "test" in KString1 */res = buf.Find(KString2) ;_LIT(KFormat1,"Find of string 2 in string 1 res = %d\n");console->Printf(KFormat1,res);/* "car" does not occur in KString1, so KErrNotFound reported */res = buf.Find(KString3) ;_LIT(KFormat2,"Find of string 3 in string 1 res = %d\n");console->Printf(KFormat2,res);/* Since FindF does a fold compare, "TEST" is found and position* is returned*/res = buf.FindF(KString4) ;_LIT(KFormat3,"Find of string 4 in string 1 res = %d\n");console->Printf(KFormat3,res);}The output of the code given is:Find of string 2 in string 1 res = 10Find of string 3 in string 1 res = -1Find of string 4 in string 1 res = 10For more powerful searching of substrings within descriptors, youcan use Match() instead of Find().
Match() behaves like Find()except that you can supply wildcard characters when searching for astring match. ‘ *’ represents a sequence of any characters; ‘ ?’ representsan occurrence of any single character. For example:void MatchExample(){_LIT(KString1,"This is test string A");_LIT(KString2,"This is test string ?");_LIT(KString3,"*is test string ?");_LIT(KString4,"*");_LIT(KString5,"*B");TBuf<40> buf(KString1);TInt res;/* A match since ? indicates any single characterres = buf.Match(KString2) ;_LIT(KFormat1,"Match: string 2 and string 1 res =console->Printf(KFormat1,res);/* A match using ’*’ and ’?’ in string */res = buf.Match(KString3) ;_LIT(KFormat2,"Match: string 3 and string 1 res =console->Printf(KFormat2,res);/* ’*’ matches any string */res = buf.Match(KString4) ;_LIT(KFormat3,"Match: string 4 and string 1 res =console->Printf(KFormat3,res);*/%d\n");%d\n");%d\n");190STRINGS, BUFFERS, AND DATA COLLECTIONS/* no match since KString1 does not end in ’B’ */res = buf.Match(KString5) ;_LIT(KFormat4,"Match: string 5 and string 1 res = %d\n");console->Printf(KFormat4,res);}The output of the previous code is as follows:Match:Match:Match:Match:stringstringstringstring2345andandandandstringstringstringstring1111resresresres====050-1Extracting substrings from descriptorsTo extract specific portions of a descriptor string, use the methodsLeft(), Right(), or Mid().
These methods return a TPtrC descriptorthat points to a specified substring within the descriptor the methods areinvoked on.Left() defines a substring starting at the beginning of the descriptorand of a specified length. Right() defines a substring that starts aspecified length before the end of the descriptor. Mid() specifies asubstring that starts from a specified position and is of a specified length.The following shows an example of using all three substring extractionfunctions:void SubstringExample(){_LIT(KString1,"This is my string");TBufC<40> buff(KString1);TPtrC SubStr= buff.Left(4) ;/* Get left 4 characters of string */_LIT(KFormat1,"Left(4): SubStr = \"%S\"\n");console->Printf(KFormat1,&SubStr);/* Get right 3 characters of string */SubStr.Set(buff.Right(3) );_LIT(KFormat2,"Right(3): SubStr = \"%S\"\n");console->Printf(KFormat2,&SubStr);/* get 6 characters in middle, starting at position 8 */SubStr.Set(buff.Mid(8,6) );_LIT(KFormat3,"Mid(8,6): SubStr = \"%S\ "\n");console->Printf(KFormat3,&SubStr);}The output is as follows:Left(4): SubStr = "This"Right(3): SubStr = "ing"Mid(8,6): SubStr = "my str"DESCRIPTOR METHODS1916.4.2 Methods that Write Descriptor DataThis section describes some key TDes class methods that are available toall modifiable descriptors.Copying data to a descriptorWe have already looked at using Copy() to write data into a descriptor.To recap, Copy() will copy data into the descriptor’s buffer, replacingany data that exists, and update the descriptor size to match the size ofthe data copied.