sl@0: /** @mainpage sl@0: sl@0: @section Header sl@0:
sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0:
Owner:Application Frameworks & Protocols
Author:Leon Clarke
Last Revised:20 March 2002.
Revision:3.0
Status:Released
Reviewers:
Approval:(PM) Urmi Shah, (ESM) Akin Oyesola, (Architect) Andrew Baldwin
sl@0:
sl@0:
sl@0: sl@0: @section Revision History sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0: sl@0:
DateVersionStatusDescription
21-05-20011.0IssuedIssued
05-07-20011.1Added more detail, in particular about static tables.Issued
05-07-20011.2Minor editorial changes following T3 review comments.Issued
23-07-20011.3Added reference to example code.Issued
09-11-20012.0Added mutiple table support and case-sensitive stringsIssued
20-03-20023.0Incorporated changes following defect fixingReleased
sl@0: sl@0: sl@0: @section Introduction sl@0: sl@0: The string pool is a way of storing strings that makes comparison sl@0: almost instantaneous at the expense of string creation. It is sl@0: particularly efficient at handling string constants that are known sl@0: at compile time. It currently only supports 8 bit strings. The sl@0: basic algorithm is to ensure that the pool only contains one string sl@0: of any particular value, using reference counts to keep track of sl@0: it. Subsequent strings with the same value will actualy refer to sl@0: the same copy. sl@0: sl@0: To use the string pool, you need an RStringPool object. Strings sl@0: from different string pools can't be compared, so there should only sl@0: be 1 string pool open per thread (unless one is in a component that sl@0: doesn't export its use of the string pool). Of course, you can have sl@0: multiple RStringPool objects, as long as they are all handles to sl@0: the same string pool. sl@0: sl@0: Within this object, there are 2 distinct pools of strings, one sl@0: comprising strings that are 'case-sensitive' (represented using the sl@0: RString class) and another representing strings that are 'case-insensitive' (RStringF). Case-sensitive strings behave in a sl@0: straightforward way. Case-insensitive strings should be used in a sl@0: situation where case doesn't matter at all; if you create a new sl@0: RStringF that differs from an existing RStringF only in terms of sl@0: case, when you read back the value of the 'new' string, it will sl@0: have the same value as the 'existing' one. This can be very useful sl@0: in situations where strings are considered case-insensitive, but sl@0: there is a 'traditional case' that is normaly used. As long as the sl@0: first value to be added is in the 'traditional case', all sl@0: subsequent additions will be corrected to match this first entry. sl@0: sl@0: Case-insensitivity assumes a character set of us-ascii (i.e.it only sl@0: considers A-Z to be equivalent to a-z) sl@0: sl@0: If a string has a more complex or different case-sensitivity sl@0: requirement that this model doesn't match, then it may be necessary sl@0: to compare strings outside the pool, which may make the string pool sl@0: inapplicable. sl@0: sl@0: Corresponding to RString and RStringF are the classes RStringToken sl@0: and RStringTokenF. These are smaller (4 bytes long rather than 8) sl@0: but need to be turned into String or StringF classes before you can sl@0: do anything useful with them. In particular, you can't directly sl@0: find the contents of a string token. They should be used when space sl@0: is absoluteley at a premium, for instance storing a lot of strings sl@0: in an array, or similar applications. sl@0: sl@0: @section Static Tables sl@0: sl@0: A very important aspect of the string pool is the concept of static string sl@0: table. This is best thought of as an array of common sl@0: strings. Integers can be transformed into the strings corresponding sl@0: to that index position in the array via the String and StringF sl@0: functions. In addition, a string can be cast back to an integer, sl@0: allowing a switch statement on strings (it returns -1 if the string sl@0: isn't one from any static table of the pool). Another advantage to using the sl@0: static table is that the function to create the string can't leave, sl@0: and the string doesn't need to be closed (although closing it is sl@0: harmless) sl@0: sl@0: Multiple case-insensitive and case-sensitive string tables are supported. sl@0: sl@0: A static table is written as a .st file, and is processed by sl@0: stringtable.pl early in the build process to generate the actual sl@0: cpp and header files at compile time. The format of the .st file is sl@0: basicaly as follows. The first noncomment line consists of sl@0: fstringtable for a case-insensitive table and stringtable sl@0: for a case-sensitive table. Each subsequent non-comment line consists sl@0: of the name of an enum followed by the value of the string. Comment sl@0: lines start with # and can be added anywhere. You can also have sl@0: lines starting in !, which will be output into the header file if sl@0: you want additional comments in the header. e.g. sl@0: sl@0: @code sl@0: # Example String Table sl@0: fstringtable ExampleStringTable sl@0: !// Some types of fruit sl@0: # This comment won't appear in the .h file, but the one above is. sl@0: EApple apple sl@0: EOrange orange sl@0: EBanana banana sl@0: # Some animals sl@0: ECat cat sl@0: EDog dog sl@0: @endcode sl@0: sl@0: The string table name must be a valid C++ class name, and the sl@0: generated code includes a class that contains within it an enum sl@0: corresponding to the elements in the array, so entries in the above sl@0: example could be referred to as MyStringTable::ECat and so on. sl@0: sl@0: The stringpool.pl script takes a .st file and creates .cpp and .h sl@0: files of the same name in the same directory. The easiest way to sl@0: use this is to export the .st file to /epoc32/generated/, create an sl@0: extension makefile that runs the script during the makefile phase sl@0: and then copies the generated .h file to epoc32, and then compile sl@0: the .cpp file as normal from an mmp files. Look at the example code sl@0: in //EPOC/main/generic/bafl/docs/stringtableexample/... for a sl@0: simple example of how to do this. sl@0: sl@0: To be notified when the String Pool is closing you can derive from the mix-in class MStringPoolCloseCallBack and implement the StringPoolClosing() function. The OpenL(const TStringTable& aTable, MStringPoolCloseCallBack& aCallBack) overridden function must be used to register the callback with the String Pool. Where aCallback is the pointer to the callback. The StringPoolClosing() function will then get called when the String Pool is closing. sl@0: sl@0: sl@0: sl@0: **/