Converting containers and lists

Symbian and Qt both provide an extensive set of array types for purposes such as containers, lists and hash maps. In some cases conversion can be avoided but in other cases the conversion is only possible using item-by-item iteration.

Symbian containers and lists

Symbian C++ provides a large number of array classes, which should be used in preference to standard C/C++ arrays because of the protection they provide against memory overruns etc. The arrays behave much like standard C++ arrays (stl::vector<>); they are indexed by an integer, elements can be of any type (or pointer to a type), the array does its internal reallocation when adding or deleting.

The topic Arrays And Lists Overview gives an overview of the different array classes. There are four main categories:

  • CArrayX (CArrayFixFlat, CArrayVarFlat, CArrayPakFlat, CArrayPtrFlat, CArrayFixSeg, CArrayVarSeg, CArrayPtrSeg)

  • RArrays (RArray, RPointerArray)

  • Fixed Array (TFixedArray)

  • Descriptor Arrays (CDesC16ArrayFlat, CDesC8ArraySeg, CDesC8ArrayFlat, CDesC8ArraySeg, CPtrC8Array, CPtrC16Array)

The array naming convention uses Fix where the elements of the array all have the same length and are copied directly into the array buffer (for example, TPoint, TRect) and Var where the elements of the array are pointers to objects of variable lengths contained elsewhere on the heap (such asHBufC* or TAny*). Pak (for ‘packed’ array) is used where the elements of the array are of variable length but are copied into the array buffer with each preceded by its length (for example, T class objects of variable length). Ptr is used where the elements of the array are pointers to CBase-derived objects.

In general use the Descriptor arrays for storing lists of strings as they have convenient methods for sorting and finding matching strings. Otherwise use the RArray classes in preference to the CArrayX classes. The exception to this rule is when the array is likely to be resized often - in which case you might use one of the segmented variants. Symbian provides a number of templated associative arrays:
  • RHashMap - associative array with key type K and value type V, using a probe-sequence hash table. Both the key and value objects are copied into the table when they are added. A bitwise binary copy is used here, so neither of the types K and V may implement a nontrivial copy constructor.

  • RPtrHashSet - unordered extensional set of objects of type T using a probe-sequence hash table. The objects are not copied into the set when they are added; rather the set stores pointers to the contained objects.

  • RPtrHashMap - an associative array with key type K and value type V, using a probe-sequence hash table. Neither the key nor value objects are copied into the table when they are added - only pointers are stored.

In addition to the Symbian C++ array classes, you can also use STL containers provided by Open C and Open C++.

Qt containers and lists

Qt allows you to use STL containers, or to use its own general purpose template-based container classes. The Qt classes are designed to be lighter, safer and easier to use than STL classes. They are implicitly shared, reentrant, and thread-safe in situations where they are used as read-only containers by all threads used to access them.

Qt provides both sequential containers (QList,QLinkedList, QVector, QStack, and QQueue), and associative containers (QMap, QMultiMap, QHash, QMultiHash, and QSet). There are also specialist classes like QCache and QContiguousCache that provide efficient hash-lookup of objects in a limited cache storage, and non-template specialisations like QStringList (inherits from QListQList<QString>) that make it easier to work with lists of strings.

The containers can be traversed using either java-style or STL-style iterators, or using the convenient foreach keyword. Qt provides a set of Generic Algorithms that you can use to sort, find, fill, count, delete items in the container (on container types that have an STL iterator).

The template classes store items of a specified type T. The value type T can be a basic type, a pointer type, a class that has a default constructor, a copy constructor and an assignment operator, or a container that meets the same criteria as a class.

The Qt container classes are well documented in the Qt reference: Container classes. There is also an excellent discussion in C++ GUI Programming with Qt 4 , Second Edition, Jasmin Blanchette and Mark Summerfield, Prentice Hall (2006) (the first edition is available free online here).

Converting between Qt and Symbian containers and lists

There is no need to convert container/lists if you're using the standard STL containers, as these are supported by both Qt and the Symbian platform.

If you do need to convert between Qt and Symbian arrays, this usually a matter of iterating through one container, converting each contained object into the correct type for the environment (e.g. QString vs descriptor), and then adding it to the new container.

When converting to Qt, QList is the best "general use" re-sizable container template if you have less than 1000 items (its implemented as an array-list but provides very fast prepends and appends). If you're working with lists of strings, use QStringList instead. When converting to Symbian C++, use a descriptor array for strings, or RArray for other objects that are greater than 4 bytes in size (unless you're expecting a lot of array re-sizing).

The following fragment shows conversion of a set of integers from an RArray to a QList:

RArray<TInt> intArrayToList;
QList<int> integerList;
...   
for (int i = 0; i < count; i++) {
integerList.append(intArrayToList[i]);
}

This fragment shows a QList of integers being imported into an RArray, using foreach to iterate the QList. Note that a TInt is typdef of signed int:

QList<int> integerList;
RArray<TInt> listToIntArray;
... 
foreach (int integerItem, integerList) {
listToIntArray.Append(integerItem);
}

Converting lists of strings uses exactly the same approach, except that you use a QStringList rather than a QList, a descriptor array instead of an RArray, and you need to convert the contained string to the correct format for the environment, as discussed in the Strings sections of Converting strings and buffers between Symbian and Qt.

The following code shows how CDesCArrayFlat is converted to QStringList:

CDesCArrayFlat* arrayToStringList;
...
QStringList qlistOfStrings;
for (int i = 0; i < count; i++) {
qlistOfStrings.append(QString::fromUtf16(
arrayToStringList->MdcaPoint(i).Ptr(),
arrayToStringList->MdcaPoint(i).Length()));
}

Copyright note

Most of the material in this topic is based with permission on a Symbian Foundation wiki article Apps:Using Qt and Symbian C++ Together . The version used was that available at Symbian Foundation on 3 November 2010. The content in this page is licensed under the Creative Commons Attribution-Share Alike 2.0 UK: England & Wales License (http://creativecommons.org/licenses/by-sa/2.0/uk).