Wiley.Developing.Software.for.Symbian.OS.2nd.Edition.Dec.2007 (779887), страница 42
Текст из файла (страница 42)
*/CleanupStack::PopAndDestroy(myArray);Figure 6.17 shows how CDesCArray is stored, when MyDes andMyDes1 are appended.To use the descriptor arrays, you need to include file badesca.h andlink to library bafl.lib.Since copies of the descriptors are made and referenced in the array,it does not matter if the user deletes the objects after they are added tothe array. Of course, the disadvantage of using this type of array is that208STRINGS, BUFFERS, AND DATA COLLECTIONSCDesCArrayFlatHBufC* HBufC*My StringCopies DataMy StringTest One TwoTest One TwoFigure 6.17 CDesCArrayFlatyou have overheads in both performance (doing the copy) and memory(duplicating descriptor data in memory).An array class that begins with CPtrC contains descriptor pointers(TPtrC’s) as its elements.If the descriptor array were of type CPtrCArray instead of CDesCArrayFlat in the previous example, it would be stored as shown inFigure 6.18.Unlike the CDesC array classes, CPtrC classes do not have to copyor store the data in the descriptors that are added to the array, since theysimply point to the descriptor data.
However, you need to make sure thatyou do not add any descriptors to the array that may go out of scope orbe otherwise deleted, since the array would contain a TPtrC pointing toan undefined area.CPtrCArrayTPtrCTPtrCMy StringTest One TwoFigure 6.18CPtrCArrayARRAYS2096.8.3 Dynamic ArraysSymbian provides a set of classes for implementing dynamic arrays.
Likedescriptor arrays, dynamic arrays are based on dynamic buffers, and arethus expandable. However, unlike descriptor arrays, templates are usedso that the array can contain items of any data type, as defined by the user.A wide assortment of dynamic array classes exists. Here is a sampleof them:•CArrayFixFlat<class T>: Holds fixed-length objects of type Tand uses a flat dynamic buffer.•CArrayFixSeg<class T>: Holds fixed-length objects of type T anduses a segmented dynamic buffer.•CArrayPtrFlat<class T>: Holds pointers to type T objects usinga flat dynamic buffer.•CArrayPtrSeg<class T>: Holds pointers to type T objects using asegmented dynamic buffer.•RArray<class T>: A full-featured, efficient array class for fixedlength data of type T, using a flat buffer.•RPointerArray<class T>: Same as RArray, but holds pointersto type T objects, which can be of variable size, and located onthe heap.Although the classes that begin with CArray provide more data representations, for the most part RArray and RPointerArray have practicallyeverything you need and are the most efficient, so I will cover these inmore detail.RArrayAn example declaration of an RArray is as follows:RArray<TExampleClass> myArray;This will define a dynamic array myArray that contains objects of typeTExampleClass.
Note that this is similar to TFixedArray except anarray size is not specified with the template. This is because the size isdynamic and not preallocated as it is for TFixedArray.The R at the beginning of RArray indicates that this class can bedeclared as an automatic variable; doing so will result in class data beingstored on the stack. Unlike some other R classes, this one also has heapstorage associated with it – in fact, the dynamic buffer that holds the dataitself resides on the heap, rather like the RBuf discussed in section 6.3.5.210STRINGS, BUFFERS, AND DATA COLLECTIONSTherefore, you always need to call the Close() method of RArray tofree the heap data storage when finished with the array.In addition to these default declarations, the following constructors arealso provided:RArray(TInt aGranularity)This specifies how the array is to be expanded in the background.RArray<TExampleClass> myArray(10), for example, will causethe memory for myArray to be expanded in units of ten items.
Thedefault is eight.RArray(TInt aGranularity, TInt aKeyOffset)In addition to granularity, this version of the constructor specifies the classoffset of an integer that acts as a key for the list. A key is a data member ofthe array element class that is used as a reference value when searching,inserting, and sorting the objects in the array. For example, if you sort thearray, the objects in the array are ordered based on comparing the arrayelement’s data members that are defined as the key.The FOFF(class,membername) macro is used to specify this keyvalue location in the array data members.The following example creates an array of TAccount elements usingTAccount::iAccountNumber as the array’s key:class TAccount{public:TAccount();TInt iAccountNumber;};RArray<TAccount> myAccounts(10,_FOFF(TAccount,iAccountNumber));Inserting and appending array dataInsert() and Append() methods are provided to add data to thearray. Insert() inserts the data at the specified position and shuffleseverything up.
Append() adds data to the object at the end of the array.If the number of data items exceeds the memory allocated by the array,the array memory is automatically expanded by the number of data itemsspecified as the granularity.You can also insert items in the list in key order using InsertInSignedKeyOrder(const &T aItem) and InsertInUnsignedKeyOrder(const &T aItem) functions. These functions insert aItemordered by the value in the data object’s key value whose location wasARRAYS211given in the RArray constructor (assuming the correct overridden constructor was used).
InsertInSignedKeyOrder() treats the key as asigned value; InsertInUnsignedKeyOrder() treats the key as anunsigned value.To provide maximum flexibility, RArray also allows you to create yourown callback function that will compare two array members (supplied asarguments to your callback) and determine their relation.
The functionreturns a negative value if the first is less than the second, positive ifit is more, and 0 if equal. This callback is wrapped in a class calledTLinearOrder. The function InsertInOrder(const &T aEntry,TLinearOrder<T>aOrder) is then used to insert the item in the orderdetermined by the callback function of TLinearOrder.TLinearOrder can also be supplied to the RArray sort methods sothat the array can be sorted in a flexible way.Versions of these functions that leave on error also exist.Finding data in an arrayUse the find methods to locate an element within the array.
Thesefunctions will return the index of the array element that matches specifieddata, or KErrNotFound if the data was not found in the array.Find(const &T aObject) does a linear search for an array elementwhose integer key matches the key value of aObject (T is the typespecified in the template argument supplied when creating the array).You can also implement a callback function to do the element comparesyourself (returns 1 if a match, 0 otherwise). Then wrap this callback inthe class TIdentityRelation, and use Find(const &T aObject,TIdentityRelation) to find the object using your callback functionfor comparing elements.The find functions that end in Order() assume that your array is inorder so that a more efficient binary search can be done to find a match.FindInOrder() does a binary search assuming that your array isalready ordered by an ordering callback, supplied as a TLinearOrdertype.
FindInSignedKeyOrder(const &T aObject) and FindInUnsignedKeyOrder(const &T aObject) will do a binary search ofthe object assuming the list is currently ordered by key value (treating keyvalue as signed and unsigned, respectively).Versions of these functions that leave on error also exist.Sorting an arraySort(TLinearOrder<T> anOrder) sorts the array using the TLinearOrder callback.SortSigned() and SortUnsigned() orders all the objects inthe array by the integer key value assigned in the RArray constructor – treating the key as signed and unsigned, respectively.212STRINGS, BUFFERS, AND DATA COLLECTIONSMiscellaneous array functionsTo remove an element, call Remove(TInt aIndex). The element atthat position is removed and the list is shuffled down.Call Reset() or Close() before destroying the array – these willfree all the memory allocated on the heap.
Reset() frees all heapmemory and prepares the array for reuse.An example using RArrayThe following is an example of how to use class RArray:class TTenant // T class representing a tenant{public:TTenant(const TDesC& aName,TInt aNum){iName.Copy(aName),iApartmentNum=aNum;}TBuf<40> iName;TInt iApartmentNum;};void TestArrayL(){/* Define array of tenants, use the apartment number as the array’s key */RArray<TTenant> renters(10,_FOFF(TTenant,iApartmentNum));/* Add some tenants to the array, random apartment order */TTenant renter1(_L("Sue"),520);TTenant renter2(_L("Bob"),132);TTenant renter3(_L("Sally"),1004);User::LeaveIfError(renters.Append(renter1));// if append fails, leaveUser::LeaveIfError(renters.Append(renter2));User::LeaveIfError(renters.Append(renter3));/* Sort array to be in order of apartment numbers (the key) */renters.SortUnsigned();/* Insert new tenant, in apartment number order */TTenant newRenter(_L("Pippin"),755);User::LeaveIfError(renters.InsertInUnsignedKeyOrder(newRenter));/* Print list of tenants, will be in order of apartment now */_LIT(KFormat1,"Name=%S, Unit=%d\n");for (TInt i=0;i<renters.Count();i++){console->Printf(KFormat1,&renters[i].iName,renters[i].iApartmentNum);}/* See who is at apartment 520 */TTenant findT(KNullDesC,520);TInt index;index = renters.FindInUnsignedKeyOrder(findT);if (index != KErrNotFound){_LIT(KFormat2,"Who’s at apartment 520? %S!");console->Printf(KFormat2,&renters[index].iName);}renters.Close(); /* must be done to free the RArray heap memory */}OTHER DATA COLLECTION CLASSES213The example in output is as follows:Name=Bob, Unit=132Name=Sue, Unit=520Name=Pippin, Unit=755Name=Sally, Unit=1004Who’s at apartment 520? Sue!The example illustrates how to set and use a key for the array, includinginsert data in key order, and finding data in the array using the key.RPointerArrayRPointerArray is like RArray except that pointers to the objects areheld in the array instead of copies of the objects themselves.
When usingthese, ensure that you do not delete the objects after they are added tothe array (and before deleting the array) since this could result in a panicwhen the elements are accessed.RPointerArray is declared as follows:RPointerArray<CExampleClass> myArray;This is like RArray, except that in this case an array of pointers totype CExampleClass is stored.
The granularity of the array can also bespecified, but note that keys are not supported for this type of array.Items can be added to the array via Append(const T* anEntry)and Insert(const T* anEntry, TInt aPos) where T is the typepassed in the template when declaring the pointer array. You can alsoinsert objects in order of pointer addresses with InsertInAddressOrder(const T* anEntry) and InsertInAddressOrderAllowingRepeats(const T* anEntry).These functions return KErrNone if successful, otherwise they returna system error code. Versions of these functions that leave on error arealso available.Although integer keys are not supported as they are in RArray, youcan specify your own function wrapped in TLinearOrder to performsorting and to perform binary searches.