Symbian OS<br />Descriptors<br />v2.0a – 21 May 2008<br />1<br />Andreas Jakl, 2008<br />
Disclaimer<br />These slides are provided free of charge at http://www.symbianresources.com and are used during Symbian OS...
Contents<br />Literals<br />Descriptors<br />TDes / TDesC<br />TBuf / TBufC<br />TPtr / TPtrC<br />HBufC<br />RBuf<br />De...
Introduction<br />Why are they different to Strings?<br />Andreas Jakl, 2008<br />4<br />
Andreas Jakl, 2008<br />5<br />h<br />e<br />l<br />l<br />o<br />�<br />Strings in C<br />char* hello = &quot;hello&quot;...
Descriptors – Introduction<br />Descriptor = Symbian OS string<br />“self-describing”<br />Holds length as well as type (=...
Descriptors – Motivation<br />Why no normal strings?<br />Minimal memory usage<br />Required efficiency<br />ROM (Literals...
Unicode<br />Symbian OS uses 16-bit text since Symbian OS v5u+<br />All descriptors available twice<br />8 bit (e.g. TBuf8...
Literals<br />_L, _LIT<br />Andreas Jakl, 2008<br />9<br />
Literals<br />In reality _LIT is a macro, expands to create a:<br />Constant descriptor, compiled to program binary<br />N...
_LIT-Macro<br />TLitChas the same memory layout like a descriptor<br /> can be used as a constant descriptor for function...
_L-Macro<br />_L(“Hello”)<br />Can be used directly as parameter<br />console-&gt;Printf(_L(“Hello”));<br />User::Panic(_L...
Comparison<br />Andreas Jakl, 2008<br />13<br />_L(“Hello”)<br />(through macro)  TPtrC hello(_L(“Hello”))<br />_LIT(KHel...
Descriptors<br />TDes, TDesC<br />Andreas Jakl, 2008<br />14<br />
Modifiable?<br />Do these methods modify the data?<br />Andreas Jakl, 2008<br />15<br />
Modifiable – Solution<br />Do these methods modify the data?<br />Andreas Jakl, 2008<br />16<br /><br /><br /><br /><b...
Constant – Modifiable?<br />Modifiable (derived from TDes)<br />Allow to modify data (replace chars, appending, ...)<br />...
Inheritance Hierarchy<br />Abstract base class because of:<br />Generalisation(use base type for parameters!)<br />Provide...
TDesC / TDes<br />Base class of all other descriptors (except Literals)<br />Provide basic functionality<br />TDesC: Read-...
Storing the Length<br />Constant (TDesC)<br />Modifiable (TDes)<br />Andreas Jakl, 2008<br />20<br />&lt;length&gt;<br />&...
Type<br />For Completeness:<br />All Descriptors and Literals also store the type of the Descriptor (Stack, Heap, ROM, …)<...
Stack-Based Buffer Descriptors<br />TBuf, TBufC<br />Andreas Jakl, 2008<br />22<br />
Buffer Descriptors<br />Comparable to (const) char[]of C<br />Directly contain the string<br />Use C++ templates to specif...
Size, Length, MaxLength<br />TBuf&lt;9&gt; with text “Hello”<br />Andreas Jakl, 2008<br />24<br />9<br />‘H’<br />5<br />‘...
Initializing the TBuf<br />Debugging in Carbide.c++: Assigning Strings<br />Andreas Jakl, 2008<br />25<br />// Define cons...
Using the TBuf<br />Andreas Jakl, 2008<br />26<br />_LIT(KHelloWorld, &quot;Hello World&quot;);	// Defines constant string...
Using the TBuf<br />Andreas Jakl, 2008<br />27<br />_LIT(KHelloWorld, &quot;Hello World&quot;);	// Defines constant string...
Maximum Length<br />Andreas Jakl, 2008<br />28<br />_LIT(KHello, &quot;Hello &quot;);			// Defines constant string literal...
Pointer Descriptors<br />TPtr, TPtrC<br />Andreas Jakl, 2008<br />29<br />
Pointer Descriptors<br />Comparable to (const) char* of C<br />Can point to text on the heap, stack or ROM<br />Do NOT own...
TPtr – Example<br />Andreas Jakl, 2008<br />31<br />_LIT(KHelloWorld, &quot;Hello World&quot;);	// Defines constant string...
TPtrC: “=” versus “Set“<br />Andreas Jakl, 2008<br />32<br />// Create two literals<br />_LIT(KHi, &quot;Hi&quot;);<br />_...
Heap-Based Buffer Descriptors<br />HBufC, RBuf<br />Andreas Jakl, 2008<br />33<br />
Use Heap-Based Buffer when…<br />String data is not in ROM and not on stack<br />Stack size is a lot more limited than the...
Constant Heap Descriptor<br />Comparable to (char*) malloc(length+1) of C<br />Data is stored on the heap<br />Andreas Jak...
HBufC Example<br />Andreas Jakl, 2008<br />36<br />Shorter variant:<br />HBufC* hBuf = KHello().AllocLC();<br />(Function ...
Modifying HBufC<br />Modify HBufC through apointer descriptor:<br />Andreas Jakl, 2008<br />37<br />_LIT(KHello, &quot;Hel...
HBufC – Memory View<br />Andreas Jakl, 2008<br />38<br />TPtr<br />12<br />12<br />0x02704174<br />iLength(TDesC)<br />iPt...
RBuf<br />Available since Symbian OS 8<br />Owns and points to modifiable string data on the heap<br />Behaves like a hand...
RBuf – Memory Layout<br />Andreas Jakl, 2008<br />40<br />Heap<br />RBuf points directly to its owned data:<br />‘H’<br />...
RBuf – Construction<br />Creating an RBuf:<br />Allocate own memoryRBufbuf;buf.CreateL(TIntaMaxLength);	// Create RBuf wit...
Using the RBuf<br />Andreas Jakl, 2008<br />42<br />_LIT(KHelloWorld, &quot;Hello World!&quot;);<br />RBufheapBuf;<br />//...
RBuf – Memory view<br />Andreas Jakl, 2008<br />43<br />Heap<br />0x027d4174<br />Hello World<br />Stack<br />Data iscopie...
RBuf and HBufC<br />Andreas Jakl, 2008<br />44<br />_LIT(KHelloWorld, &quot;Hello World!&quot;);<br />HBufC* hptr;<br />//...
RBuf & HBufC – Memory View<br />Andreas Jakl, 2008<br />45<br />Heap<br />0x027d4174<br />Hello World<br />11<br />Stack<b...
One more Example<br />It’s recommended to use RBuf instead of HBufC*<br />Andreas Jakl, 2008<br />46<br />// Function retu...
RBuf vs. HBufC?<br />Theoretically:<br />Use HBufC for constant data<br />Use RBuf for modifiable data<br />However:<br />...
Summary<br />Abstract (TDes, TDesC)<br />Base class of other descriptors<br />Cannot be instantiated<br />Used for functio...
Lots of types? Decide:<br />Andreas Jakl, 2008<br />49<br />Is the descriptor modifiable?<br />YES<br />NO<br />Has the me...
Quiz<br />Andreas Jakl, 2008<br />50<br />TDesC::AllocLC()“Creates a new 16-bit heap descriptor, initializes it with a cop...
Quiz – Solution<br />Assign variables to the memory view:<br />Andreas Jakl, 2008<br />51<br />_LIT(KHello1, “Hello”);<br ...
Using Descriptors in Functions<br />The daily life of a Symbian OS developer …<br />Andreas Jakl, 2008<br />52<br />
Function Arguments<br />void MyFunction(TBuf&lt;8&gt;aText)<br />What if caller uses an RBuf, TPtr or TBuf&lt;9&gt;?<br />...
Example<br />TInterrorCode = RFile.Read(TDes8& aDes);<br />Function can find out max. length (aDes.MaxLength())<br />Calle...
Return HBufC*<br />Make sure calling function knows it takes ownership!<br />Don’t forget the cleanup stack if it is neces...
Better: RBuf<br />Creating a specific RBuf in a function:<br />Andreas Jakl, 2008<br />56<br />RBufmyBuf;<br />myBuf.Clean...
Returning a TPtrC<br />What’s wrong with the following code?<br />Andreas Jakl, 2008<br />57<br />TPtrCGetText() { <br />/...
Returning a TPtrC – Solution<br />bufPtr does not own the data<br />buf is a local variable and ceases to exist when funct...
Unicode and Binary<br />Painless conversion<br />Andreas Jakl, 2008<br />59<br />Conversion is more important than you mig...
Converting from Unicode<br />Simple conversion by stripping alternate characters:<br />Andreas Jakl, 2008<br />60<br />TBu...
Converting to Unicode<br />Simple conversion by padding each character with trailing zero:<br />Andreas Jakl, 2008<br />61...
Proper Conversion<br />Use conversion library (charconv.lib)<br />Requires:<br />#include &lt;charconv.h&gt;<br />#include...
More about Descriptor Usage<br />Other things you should know<br />Andreas Jakl, 2008<br />63<br />
TLex<br />General string-parsing functions suitable for numeric format conversions and syntactical-element parsing<br />e....
Conversion String  Number<br />String  Number: Provided by TDes<br />Number  String: Simple use of TLex<br />Andreas Ja...
Formatting Text<br />Integrate variables into text<br />Appending text or numbers<br />Simplest way: use the AppendNum()-f...
Formatting Text<br />Format strings<br />Use placeholders for elements<br />Full syntax in the SDK help: » Symbian OS vXX ...
TFileName<br />Definition of TFileName(e32const.h / e32cmn.h):<br />const TIntKMaxFileName=0x100;		// = Decimal 256typedef...
Test your Knowledge<br />Did you understand everything?<br />Andreas Jakl, 2008<br />69<br />
ASD-like Question – Easy <br />Which of the following statements about descriptors are correct?<br />A. All descriptor cla...
Solution<br />A.Incorrect. RBuf derives from TDesC as well.<br />B. Correct.<br />C. Correct.<br />D. Incorrect. The NULL ...
ASD-like Question – Medium<br />Andreas Jakl, 2008<br />72<br />_LIT(KHello, &quot;Hello!&quot;);<br />TBufC&lt;6&gt; hell...
Solution<br />A.Incorrect. TBufC does not have a MaxLength()-function. This is defined in TDes base class.<br />B. Correct...
ASD-like Question – Hard<br />Andreas Jakl, 2008<br />74<br />Which of the following uses of a descriptor should be recons...
Solution<br />A.Reconsider. TFileName should be passed by reference, not by value. <br />B. OK.<br />C. Reconsider. Use ge...
Resources<br />Famous blogs with answers to common problems:<br />http://descriptors.blogspot.com/<br />http://descriptor-...
Thanks for your attention<br />That’s it!<br />Andreas Jakl, 2008<br />77<br />
Upcoming SlideShare
Loading in …5
×

Symbian OS - Descriptors

4,400 views

Published on

Everything you need to know about Descriptors, the Symbian OS-way of dealing with text. Includes several examples. The challenges lets you try out many of the concepts behind descriptors by programming most parts of an application according to exact instructions.

Contents

* Literals
* Descriptors
* TDes / TDesC
* TBuf / TBufC
* TPtr / TPtrC
* HBufC
* RBuf
* Descriptors and function parameters / return values
* Converting to/from Unicode
* String -> Number conversion

Published in: Technology
1 Comment
4 Likes
Statistics
Notes
  • very good tutorial for symbian descriptors
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
4,400
On SlideShare
0
From Embeds
0
Number of Embeds
192
Actions
Shares
0
Downloads
0
Comments
1
Likes
4
Embeds 0
No embeds

No notes for slide

Symbian OS - Descriptors

  1. 1. Symbian OS<br />Descriptors<br />v2.0a – 21 May 2008<br />1<br />Andreas Jakl, 2008<br />
  2. 2. Disclaimer<br />These slides are provided free of charge at http://www.symbianresources.com and are used during Symbian OS courses at the University of Applied Sciences in Hagenberg, Austria ( http://www.fh-hagenberg.at/ )<br />Respecting the copyright laws, you are allowed to use them:<br />for your own, personal, non-commercial use<br />in the academic environment<br />In all other cases (e.g. for commercial training), please contact andreas.jakl@fh-hagenberg.at<br />The correctness of the contents of these materials cannot be guaranteed. Andreas Jakl is not liable for incorrect information or damage that may arise from using the materials.<br />Parts of these materials are based on information from Symbian Press-books published by John Wiley & Sons, Ltd. This document contains copyright materials which are proprietary to Symbian, UIQ, Nokia and SonyEricsson. “S60™” is a trademark of Nokia. “UIQ™” is a trademark of UIQ Technology. Pictures of mobile phones or applications are copyright their respective manufacturers / developers. “Symbian ™”, “Symbian OS ™” and all other Symbian-based marks and logos are trademarks of Symbian Software Limited and are used under license. © Symbian Software Limited 2006. <br />Andreas Jakl, 2008<br />2<br />
  3. 3. Contents<br />Literals<br />Descriptors<br />TDes / TDesC<br />TBuf / TBufC<br />TPtr / TPtrC<br />HBufC<br />RBuf<br />Descriptorsasfunctionparameters / returnvalues<br />Convertingto/from Unicode<br />String Numberconversion<br />Andreas Jakl, 2008<br />3<br />
  4. 4. Introduction<br />Why are they different to Strings?<br />Andreas Jakl, 2008<br />4<br />
  5. 5. Andreas Jakl, 2008<br />5<br />h<br />e<br />l<br />l<br />o<br /><br />Strings in C<br />char* hello = &quot;hello&quot;;<br />Memory view:<br />Function strlen()<br />Reads from the beginning to &apos;&apos; and counts number of chars<br />char*<br />0x64243184<br />
  6. 6. Descriptors – Introduction<br />Descriptor = Symbian OS string<br />“self-describing”<br />Holds length as well as type (= memory layout)<br />Different to:<br />CString (C++), Java Strings, ...  for descriptors, allocation and cleanup is managed by programmer<br />C strings  Descriptors protect against buffer overrun and don’t use termination<br />Andreas Jakl, 2008<br />6<br />
  7. 7. Descriptors – Motivation<br />Why no normal strings?<br />Minimal memory usage<br />Required efficiency<br />ROM (Literals: _LIT!) – Stack – Heap?<br />Constant – modifiable?<br />Unicode(TBuf16 – TBuf8)<br />Take a long time to get used to <br />Andreas Jakl, 2008<br />7<br />
  8. 8. Unicode<br />Symbian OS uses 16-bit text since Symbian OS v5u+<br />All descriptors available twice<br />8 bit (e.g. TBuf8)<br />Used for binary data and ASCII text<br />16 bit (e.g. TBuf16)<br />Normally not used explicitly, instead:<br />Build independent (e.g. TBuf)<br />Currently always Unicode<br />typedef’d to 16 bit version<br />Use this for normal strings<br />Andreas Jakl, 2008<br />8<br />
  9. 9. Literals<br />_L, _LIT<br />Andreas Jakl, 2008<br />9<br />
  10. 10. Literals<br />In reality _LIT is a macro, expands to create a:<br />Constant descriptor, compiled to program binary<br />Not localisable  only use for testing, very simple applications or fixed strings (e.g. for protocols)!<br />_LIT(KHello, “Hello”);<br />Builds a named object called KHello of type TLitC16<br />Stores the string Hello into the object<br />The string is written to the program binary<br />Andreas Jakl, 2008<br />10<br />
  11. 11. _LIT-Macro<br />TLitChas the same memory layout like a descriptor<br /> can be used as a constant descriptor for function parameters (const TDesC&)<br />_LIT(KHello, &quot;Hello!&quot;);console-&gt;Printf(KHello);iLabel-&gt;SetTextL(KHello);<br /> can be casted to a descriptor through ()-operator<br />TInt length = KHello().Length(); // == 6<br />Andreas Jakl, 2008<br />11<br />
  12. 12. _L-Macro<br />_L(“Hello”)<br />Can be used directly as parameter<br />console-&gt;Printf(_L(“Hello”));<br />User::Panic(_L(“example.dll”), KErrNotSupported);<br />Creates temporary TPtrC inefficient, deprecated!<br />Both macros defined in e32def.h<br />Andreas Jakl, 2008<br />12<br />
  13. 13. Comparison<br />Andreas Jakl, 2008<br />13<br />_L(“Hello”)<br />(through macro)  TPtrC hello(_L(“Hello”))<br />_LIT(KHello, “Hello”);<br />ROM<br />ROM<br />Stack (temporary)<br />‘H’<br />5<br />‘e’<br />‘l’<br />‘l’<br />‘o’<br />‘’<br />‘H’<br />5<br />‘e’<br />‘l’<br />‘l’<br />‘o’<br />‘’<br />&lt;ptr&gt;<br />For completeness:<br />Literals are actually ‘’-terminated because of the standard C++ compiler, but the additional ‘’-char not reflected in the saved length<br />All other descriptors are not ‘’-terminated!<br />
  14. 14. Descriptors<br />TDes, TDesC<br />Andreas Jakl, 2008<br />14<br />
  15. 15. Modifiable?<br />Do these methods modify the data?<br />Andreas Jakl, 2008<br />15<br />
  16. 16. Modifiable – Solution<br />Do these methods modify the data?<br />Andreas Jakl, 2008<br />16<br /><br /><br /><br /><br /><br /><br /><br /><br /> TDesC<br /> TDes<br />defined in ...<br />
  17. 17. Constant – Modifiable?<br />Modifiable (derived from TDes)<br />Allow to modify data (replace chars, appending, ...)<br />Non-modifiable (derived from TDesC)<br />Constant data (read-only)<br />Modify it anyway? Possible, if data is not in ROM:<br />Get modifiable pointer descriptor to data using myText.Des();<br />Andreas Jakl, 2008<br />17<br />
  18. 18. Inheritance Hierarchy<br />Abstract base class because of:<br />Generalisation(use base type for parameters!)<br />Provide basic functions shared by all types (e.g. Compare(), Find(), Mid(), ...)<br />Andreas Jakl, 2008<br />18<br />constant<br />modifiable<br />
  19. 19. TDesC / TDes<br />Base class of all other descriptors (except Literals)<br />Provide basic functionality<br />TDesC: Read-only access (compare, search, ...)<br />TDes: Inherits from TDesC and adds modification functions.Saves maximum length to prevent overflow.<br />Cannot be instantiated<br />Allow polymorphic use of descriptors<br /> Commonly used in function parameters<br />Don’t care where data is stored<br />Andreas Jakl, 2008<br />19<br />
  20. 20. Storing the Length<br />Constant (TDesC)<br />Modifiable (TDes)<br />Andreas Jakl, 2008<br />20<br />&lt;length&gt;<br />&lt;string data&gt;<br />Depending on descriptor type:can directly contain the data or <br />be a pointer to data on the stack,<br />heap or ROM<br />4 bytes<br />&lt;length&gt;<br />&lt;max.length&gt;<br />&lt;string data&gt;<br />4 bytes<br />4 bytes<br />
  21. 21. Type<br />For Completeness:<br />All Descriptors and Literals also store the type of the Descriptor (Stack, Heap, ROM, …)<br />First 4 bits of iLength reduces max. length to 28 bits<br />Used in common methods of TDesand TDesCto execute correct code depending on type using switch()-statement<br />(Alternative: virtual functions, but that’d cause overhead)<br />Andreas Jakl, 2008<br />21<br />The type is normally not relevantfor the developer, therefore it is omitted in following slides for clarity<br />TDesC<br />&lt;length&gt;<br />&lt;string data&gt;<br />&lt;type&gt;<br />4 bit<br />28 bit<br />4 bytes (32 bit)<br />
  22. 22. Stack-Based Buffer Descriptors<br />TBuf, TBufC<br />Andreas Jakl, 2008<br />22<br />
  23. 23. Buffer Descriptors<br />Comparable to (const) char[]of C<br />Directly contain the string<br />Use C++ templates to specify length (parameter)<br />Andreas Jakl, 2008<br />23<br />TBufC&lt;5&gt;<br />Constant:<br />‘H’<br />5<br />‘e’<br />‘l’<br />‘l’<br />‘o’<br />iLength(TDesC)<br />Modifiable:<br />TBuf&lt;9&gt;<br />9<br />‘H’<br />5<br />‘e’<br />‘l’<br />‘l’<br />‘o’<br />iLength(TDesC)<br />iMaxLength(TDes)<br />
  24. 24. Size, Length, MaxLength<br />TBuf&lt;9&gt; with text “Hello”<br />Andreas Jakl, 2008<br />24<br />9<br />‘H’<br />5<br />‘e’<br />‘l’<br />‘l’<br />‘o’<br />...<br />4 bytes<br />4 bytes<br />2<br />2<br />Unicode characters!<br />Length()  5 (characters)<br />MaxLength()  9 (characters)<br />Size()  10 (bytes)<br />MaxSize()  18 (bytes)<br />
  25. 25. Initializing the TBuf<br />Debugging in Carbide.c++: Assigning Strings<br />Andreas Jakl, 2008<br />25<br />// Define constant string literal<br />_LIT(KString1, &quot;Hello &quot;);<br />_LIT(KString2, &quot;World&quot;);<br />// Copy KString1 into new TBuf with max. length of 15<br />TBuf&lt;15&gt; buf1(KString1);<br />// Same as above, this time using Copy() and KString2<br />TBuf&lt;15&gt; buf2; // Initialize empty TBuf with max. length of 15<br />buf2.Copy(KString2);<br />// Append contents of buf2 to buf1<br />buf1.Append(buf2);<br />// Create constant descriptor based on KString1<br />TBufC&lt;15&gt; cBuf1(KString1);<br />// Replace contents of cBuf1 with contents of buf1<br />cBuf1 = buf1;<br />
  26. 26. Using the TBuf<br />Andreas Jakl, 2008<br />26<br />_LIT(KHelloWorld, &quot;Hello World&quot;); // Defines constant string literal<br />constTIntmaxLength = 15;<br />// Create a modifiable buffer<br />TBuf&lt;maxLength&gt; buf; <br />TIntcurLength = buf.Length(); // ...... ?<br />TInt maxLength2 = buf.MaxLength(); // ...... ?<br />// Set the contents of the buffer<br />buf = KHelloWorld;<br />curLength = buf.Length(); // ...... ?<br />TIntcurSize = buf.Size(); // ...... ?<br />TTextch = buf[1]; // ...... ?<br />
  27. 27. Using the TBuf<br />Andreas Jakl, 2008<br />27<br />_LIT(KHelloWorld, &quot;Hello World&quot;); // Defines constant string literal<br />constTIntmaxLength = 15;<br />// Create a modifiable buffer<br />TBuf&lt;maxLength&gt; buf; <br />TIntcurLength = buf.Length(); // == 0<br />TInt maxLength2 = buf.MaxLength(); // == 20<br />// Set the contents of the buffer<br />buf = KHelloWorld;<br />curLength = buf.Length(); // == 11<br />TIntcurSize = buf.Size(); // == 22<br />TTextch = buf[1]; // == ‘e’<br />
  28. 28. Maximum Length<br />Andreas Jakl, 2008<br />28<br />_LIT(KHello, &quot;Hello &quot;); // Defines constant string literal<br />TBuf&lt;15&gt; buf(KHello); // buf == “Hello ”<br />buf.Append(KHello); // buf == “Hello Hello “<br />buf.Append(KHello); // Exceeds maximum length  Panic!<br />SDK-Doc for USER 11-panic:<br />“This panic is raised when any operation that moves or copies data to a 16-bit variant descriptor, causes the length of that descriptor to exceed its maximum length. […]”<br />
  29. 29. Pointer Descriptors<br />TPtr, TPtrC<br />Andreas Jakl, 2008<br />29<br />
  30. 30. Pointer Descriptors<br />Comparable to (const) char* of C<br />Can point to text on the heap, stack or ROM<br />Do NOT own the data they point to!<br />Andreas Jakl, 2008<br />30<br />‘H’<br />‘e’<br />‘l’<br />‘l’<br />‘o’<br />Constant:<br />TPtrC<br />0x64243184<br />5<br />ROM, heaporstack<br />iLength(TDesC)<br />iPtr(TPtrC)<br />‘H’<br />‘e’<br />‘l’<br />‘l’<br />‘o’<br />TPtr<br />Modifiable:<br />0x64243184<br />5<br />9<br />ROM, heaporstack<br />iLength(TDesC)<br />iPtr(TPtrC)<br />iMaxLength(TDes)<br />
  31. 31. TPtr – Example<br />Andreas Jakl, 2008<br />31<br />_LIT(KHelloWorld, &quot;Hello World&quot;); // Defines constant string literal<br />// Create a constant buffer with contents of string literal<br />TBufC&lt;13&gt; buf (KHelloWorld);<br />// Get a pointer descriptor for the text<br />TPtrptr = buf.Des();<br />// Replace the 6th char with an &apos;!&apos;, even though TBufC is actually constant!<br />ptr[5] = &apos;!&apos;; // buf: &quot;Hello!World&quot;<br />TBufC&lt;13&gt; (Stack)<br />‘H’<br />11<br />‘e’<br />‘l’<br />‘l’<br />‘o’<br />‘!’<br />‘W’<br />‘o’<br />‘r’<br />‘l’<br />‘d’<br />TPtr(Stack)<br />iLength(TDesC)<br />11<br />13<br />0x0303FE5C<br />Data iscopiedto thestack<br />KHelloWorld(ROM)<br />iLength(TDesC)<br />iPtr(TPtrC)<br />iMaxLength(TDes)<br />‘H’<br />11<br />‘e’<br />‘l’<br />‘l’<br />‘o’<br />‘ ’<br />‘W’<br />‘o’<br />‘r’<br />‘l’<br />‘d’<br />‘’<br />iLength<br />
  32. 32. TPtrC: “=” versus “Set“<br />Andreas Jakl, 2008<br />32<br />// Create two literals<br />_LIT(KHi, &quot;Hi&quot;);<br />_LIT(KSymbian, &quot;Symbian&quot;);<br />// Constant buffer descriptors, copy data from ROM to Stack<br />TBufC&lt;10&gt; bufHi(KHi);<br />TBufC&lt;10&gt; bufSymbian(KSymbian);<br />// ptr1 and ptr2 point to string data owned by TBufC&apos;s<br />TPtr ptr1(bufHi.Des());<br />TPtr ptr2(bufSymbian.Des());<br />ptr1 = ptr2;<br />ptr1.Set(ptr2);<br />ptr1  bufHi: “Symbian”<br />ptr2  bufSymbian: “Symbian”<br />bufHi: “Symbian”<br />bufSymbian: “Symbian”<br />… copies Data from buffer pointed toptr2 to buffer pointed to by ptr1<br />ptr1  bufSymbian: “Symbian”<br />ptr2  bufSymbian: “Symbian”<br />bufHi: “Hi”<br />bufSymbian: “Symbian”<br />… sets ptr1 to point to same bufferas ptr2<br />
  33. 33. Heap-Based Buffer Descriptors<br />HBufC, RBuf<br />Andreas Jakl, 2008<br />33<br />
  34. 34. Use Heap-Based Buffer when…<br />String data is not in ROM and not on stack<br />Stack size is a lot more limited than the heap!<br />Length of buffer is not known at compile time, e.g.<br />Loading strings from resource file<br />Getting strings from UI (query dialogs, ...)<br />Receiving response from the web<br />Longer lifetime than creator<br />e.g. passing to an asynchronous function<br />Andreas Jakl, 2008<br />34<br />
  35. 35. Constant Heap Descriptor<br />Comparable to (char*) malloc(length+1) of C<br />Data is stored on the heap<br />Andreas Jakl, 2008<br />35<br />Heap<br />‘H’<br />5<br />‘e’<br />‘l’<br />‘l’<br />‘o’<br />HBufC*<br />0x64243184<br />Same layout as TBufC<br />
  36. 36. HBufC Example<br />Andreas Jakl, 2008<br />36<br />Shorter variant:<br />HBufC* hBuf = KHello().AllocLC();<br />(Function of TDesC, creates and returns heap buffer based on a copy of its own data)<br />_LIT(KHello, &quot;Hello&quot;);<br />// Create new HBufC with length of 5<br />HBufC* hBuf = HBufC::NewLC(KHello().Length());<br />// Copy data of KHello to heap allocated by hBuf<br />*hBuf = KHello;<br />[…]<br />// Do cleanup<br />CleanupStack::PopAndDestroy(1);<br />Heap<br />‘H’<br />5<br />‘e’<br />‘l’<br />‘l’<br />‘o’<br />HBufC*<br />0x64243184<br />KHello (ROM)<br />Data is copiedto the heap<br />‘H’<br />5<br />‘e’<br />‘l’<br />‘l’<br />‘o’<br />‘’<br />iLength<br />
  37. 37. Modifying HBufC<br />Modify HBufC through apointer descriptor:<br />Andreas Jakl, 2008<br />37<br />_LIT(KHello, &quot;Hello!&quot;);<br />_LIT(KWorld, &quot;World!&quot;);<br />HBufC* buf = HBufC::NewLC(KHello().Length());<br />*buf = KHello; // buf holds &quot;Hello!&quot;, Length = 6<br />// Increase heap buffer size - still holds &quot;Hello!&quot;<br />buf = buf-&gt;ReAllocL(KHello().Length() + KWorld().Length());<br />// New memory area has been reserved – update reference on CleanupStack!<br />CleanupStack::Pop(buf);<br />CleanupStack::PushL(buf);<br />// Create pointer descriptor based on heap descriptor<br />TPtrptr(buf-&gt;Des()); // Length = 6, MaxLength = 12<br />ptr[KHello().Length() - 1] = &apos; &apos;; // buf holds &quot;Hello &quot;<br />ptr.Append(KWorld); // buf holds &quot;Hello World!&quot;<br />CleanupStack::PopAndDestroy(buf);<br />To access the data of an HBufC* (e.g. to use it for a TDesC&-parameter), you can write *hptr instead of creating a TPtrC with hptr-&gt;Des();<br />
  38. 38. HBufC – Memory View<br />Andreas Jakl, 2008<br />38<br />TPtr<br />12<br />12<br />0x02704174<br />iLength(TDesC)<br />iPtr(TPtrC)<br />iMaxLength(TDes)<br />Heap<br />HBufC*<br />0x02704174<br />‘H’<br />12<br />‘e’<br />‘l’<br />‘l’<br />‘o’<br />‘ ’<br />‘W’<br />‘o’<br />‘r’<br />‘l’<br />‘d’<br />‘!’<br />
  39. 39. RBuf<br />Available since Symbian OS 8<br />Owns and points to modifiable string data on the heap<br />Behaves like a handle to a resource (Close() to free)<br />Resize possible, but has to be done manually<br />Similar to:<br />TPtr, but owns data it points to<br />HBufC, but easier to use<br />Can be wrapper for HBufC-Object<br />Andreas Jakl, 2008<br />39<br />
  40. 40. RBuf – Memory Layout<br />Andreas Jakl, 2008<br />40<br />Heap<br />RBuf points directly to its owned data:<br />‘H’<br />‘e’<br />‘l’<br />‘l’<br />‘o’<br />RBuf<br />0x64243184<br />5<br />9<br />iLength(TDesC)<br />*iEPtrType(RBuf)<br />iMaxLength(TDes)<br />C++ Union (only one of both variables are used, depending on type)<br />Heap<br />RBuf points to owned HBufC:<br />‘H’<br />5<br />‘e’<br />‘l’<br />‘l’<br />‘o’<br />RBuf<br />5<br />9<br />0x64243184<br />= contents of old HBufC<br />iLength(TDesC)<br />*iEBufCPtrType(RBuf)<br />iMaxLength(TDes)<br />
  41. 41. RBuf – Construction<br />Creating an RBuf:<br />Allocate own memoryRBufbuf;buf.CreateL(TIntaMaxLength); // Create RBuf with max. lengthor: buf.CreateL(constTDesC &aDes); // Copy data to own memory<br />Transfer ownership of HBufC(wrapper for HBufC)RBufbuf(HBufC* aHBuf); // Transfer ownership of HBufC-dataor: buf.Assign(HBufC* aHBuf);<br />Transfer ownership of existing memory areabuf.Assign(TUint16 *aHeapCell, TIntaMaxLength);<br />Andreas Jakl, 2008<br />41<br />
  42. 42. Using the RBuf<br />Andreas Jakl, 2008<br />42<br />_LIT(KHelloWorld, &quot;Hello World!&quot;);<br />RBufheapBuf;<br />// Create RBuf, copy contents of KHelloWorld<br />heapBuf.CreateL(KHelloWorld);<br />// Make sure Close() is called on RBuf in case of Leave<br />heapBuf.CleanupClosePushL();<br />[…]<br />// Calls Close() on the RBuf<br />CleanupStack::PopAndDestroy();<br />Directly points to string data(ASCII 72 = “H” of “Hello World”)<br />
  43. 43. RBuf – Memory view<br />Andreas Jakl, 2008<br />43<br />Heap<br />0x027d4174<br />Hello World<br />Stack<br />Data iscopiedto theheap<br />*iEPtrType<br />ROM<br />11<br />iMaxLength<br />RBufheapBuf<br />Hello World<br />11<br />11<br />iLength<br />
  44. 44. RBuf and HBufC<br />Andreas Jakl, 2008<br />44<br />_LIT(KHelloWorld, &quot;Hello World!&quot;);<br />HBufC* hptr;<br />// Create heap descriptor which can hold up to 15 items. Current lenght = 0<br />hptr = HBufC::NewL(15);<br />// Assigns data to heap descriptor. Current length = 12<br />*hptr = KHelloWorld;<br />// Ownership of heap descriptor passed to RBuf<br />RBufbuf(hptr);<br />// Close buffer and free resources - do not delete HBuf!<br />buf.Close();<br />
  45. 45. RBuf & HBufC – Memory View<br />Andreas Jakl, 2008<br />45<br />Heap<br />0x027d4174<br />Hello World<br />11<br />Stack<br />Data is copiedto the heap<br />*iEBufCPtrType<br />11<br />iMaxLength<br />RBuf buf<br />ROM<br />11<br />iLength<br />Hello World<br />11<br />HBufC* hptr<br />... don’t delete twice, now the RBuf owns the memory!<br />
  46. 46. One more Example<br />It’s recommended to use RBuf instead of HBufC*<br />Andreas Jakl, 2008<br />46<br />// Function returns HBufC*, we use RBuf to wrap it  simpler handling for us!<br />RBufresString (iEikonEnv-&gt;AllocReadResourceL(someResourceId));<br />// Leaving functions ahead, so push the RBuf on the CleanupStack<br />resString.CleanupClosePushL();<br />// Use modifiable descriptor to append new text...<br />resString.ReAllocL(resString.Length() + 4);<br />resString.Append(_L(&quot;-Foo&quot;));<br />[…]<br />// Assign text to a label, resString is a TDesC as well, so it works without changes!<br />SetLabelL(ELabel, resString);<br />CleanupStack::PopAndDestroy(); // calls resString.Close();<br />
  47. 47. RBuf vs. HBufC?<br />Theoretically:<br />Use HBufC for constant data<br />Use RBuf for modifiable data<br />However:<br />As RBuf is a lot easier to use, consider always using RBuf<br />Most Symbian OS APIs operate using HBufC<br />Either also use HBufC for these cases<br />Or wrap HBufC with RBuf<br />Andreas Jakl, 2008<br />47<br />
  48. 48. Summary<br />Abstract (TDes, TDesC)<br />Base class of other descriptors<br />Cannot be instantiated<br />Used for function parameters<br />Literal (TLitC _LIT())<br />Used to store non-modifiable, literal strings in code<br />Buffer (TBuf, TBufC)<br />Data is stored on the stack<br />Size specified at compile time<br />Heap (HBufC, RBuf)<br />Data stored on the heap<br />Size specified at run-time<br />Pointer (TPtr, TPtrC)<br />References data stored outside the class<br />Andreas Jakl, 2008<br />48<br />
  49. 49. Lots of types? Decide:<br />Andreas Jakl, 2008<br />49<br />Is the descriptor modifiable?<br />YES<br />NO<br />Has the memory for the descriptor data already been allocated elsewhere (heap or stack)?<br />Has the memory for the descriptor data already been allocated elsewhere (heap or stack)?<br />YES<br />YES<br />TPtr<br />TPtrC<br />Will the memory allocated be stack- or heap-based?<br />Will the memory allocated be stack- or heap-based?<br />HEAP<br />HEAP<br />RBuf<br />HBufC<br />STACK<br />STACK<br />TBuf<br />TBufC<br />
  50. 50. Quiz<br />Andreas Jakl, 2008<br />50<br />TDesC::AllocLC()“Creates a new 16-bit heap descriptor, initializes it with a copy of this descriptor&apos;s data, and puts a pointer to the descriptor onto the cleanup stack.”<br />Assign variables to the memory view:<br />_LIT(KHello1, “Hello”);<br />TPtrChello2 (KHello1);<br />TBufC&lt;5&gt; hello3(KHello1);<br />HBufC* hello4 = KHello1().AllocLC();<br />Heap<br />hello<br />5<br />Stack<br />…?<br />hello<br />…?<br />5<br />ROM<br />…?<br />…?<br />hello<br />5<br />5<br />
  51. 51. Quiz – Solution<br />Assign variables to the memory view:<br />Andreas Jakl, 2008<br />51<br />_LIT(KHello1, “Hello”);<br />TPtrChello2 (KHello1);<br />TBufC&lt;5&gt; hello3(KHello1);<br />HBufC* hello4 = KHello1().AllocLC();<br />Heap<br />hello<br />5<br />Stack<br />hello4<br />hello<br />hello3<br />5<br />ROM<br />KHello1<br />hello2<br />hello<br />5<br />5<br />
  52. 52. Using Descriptors in Functions<br />The daily life of a Symbian OS developer …<br />Andreas Jakl, 2008<br />52<br />
  53. 53. Function Arguments<br />void MyFunction(TBuf&lt;8&gt;aText)<br />What if caller uses an RBuf, TPtr or TBuf&lt;9&gt;?<br /> References for base classes (TDes&, const TDesC&) should always be used<br />void SomeFunction(const TDesC& aReadOnlyDescriptor, TDes& aReadWriteDescriptor);<br />Andreas Jakl, 2008<br />53<br />
  54. 54. Example<br />TInterrorCode = RFile.Read(TDes8& aDes);<br />Function can find out max. length (aDes.MaxLength())<br />Caller can get number of bytes read: des.Length()<br />Compare that to the Win32-API …<br />BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped); <br />Andreas Jakl, 2008<br />54<br />
  55. 55. Return HBufC*<br />Make sure calling function knows it takes ownership!<br />Don’t forget the cleanup stack if it is necessary!<br />Andreas Jakl, 2008<br />55<br />HBufC* CreateSomeDescriptorL() { _LIT(KBert, &quot;bert&quot;);<br />// Createheap-baseddescriptorHBufC* newBert = KBert().AllocL();<br />// Return ourHBufC*return (newBert);}<br />HBufC* CreateSomeDescriptorLC() { _LIT(KBert, &quot;bert&quot;); HBufC* newBert = KBert().AllocLC(); return (newBert);}<br />
  56. 56. Better: RBuf<br />Creating a specific RBuf in a function:<br />Andreas Jakl, 2008<br />56<br />RBufmyBuf;<br />myBuf.CleanupClosePushL();<br />GetSomeDataL(myBuf);<br />console-&gt;Printf(myBuf);<br />CleanupStack::PopAndDestroy(myBuf);<br />voidGetSomeDataL(RBuf&aBuf) { _LIT(KHello, &quot;Hello&quot;);<br />// Allocatememory and copy „Hello“ to RBufaBuf.CreateL(KHello);<br />}<br />
  57. 57. Returning a TPtrC<br />What’s wrong with the following code?<br />Andreas Jakl, 2008<br />57<br />TPtrCGetText() { <br />// CreateTBufCbased on literaldescriptor<br /> _LIT(KMyText, &quot;My Text&quot;);TBufC&lt;7&gt; buf(KMyText());<br />// Create a TPtrCbased on bufTPtrCbufPtr(buf);<br />// Return theTPtrCreturn (bufPtr);}<br />
  58. 58. Returning a TPtrC – Solution<br />bufPtr does not own the data<br />buf is a local variable and ceases to exist when function is left<br /> Target of bufPtris no longer valid!<br />Andreas Jakl, 2008<br />58<br />TPtrCGetText() { <br />// CreateTBufCbased on literaldescriptor<br /> _LIT(KMyText, &quot;My Text&quot;);TBufC&lt;7&gt; buf(KMyText());<br />// Create a TPtrCbased on bufTPtrCbufPtr(buf);<br />// Return theTPtrCreturn (bufPtr);}<br />
  59. 59. Unicode and Binary<br />Painless conversion<br />Andreas Jakl, 2008<br />59<br />Conversion is more important than you might think: e.g. socket communication is 8 bit!<br />
  60. 60. Converting from Unicode<br />Simple conversion by stripping alternate characters:<br />Andreas Jakl, 2008<br />60<br />TBuf8&lt;3&gt; cat(_L8(&quot;cat&quot;)); // _L used for simplicity<br />TBuf16&lt;3&gt; dog(_L16(&quot;dog&quot;));<br />cat.Copy(dog); // cat now contains &quot;dog&quot;<br />TDes8 cat<br />TDes16 dog<br />cat.Copy(dog);<br />Strips -padding<br />TDes8 cat<br />
  61. 61. Converting to Unicode<br />Simple conversion by padding each character with trailing zero:<br />Andreas Jakl, 2008<br />61<br />TBuf8&lt;5&gt; small(_L8(&quot;small&quot;));<br />TBuf16&lt;5&gt; large(_L16(&quot;large&quot;));<br />large.Copy(small); // large now contains &quot;small&quot;<br />TDes8 small<br />TDes16 large<br />large.Copy(small);<br />Adds -padding<br />TDes8 large<br />
  62. 62. Proper Conversion<br />Use conversion library (charconv.lib)<br />Requires:<br />#include &lt;charconv.h&gt;<br />#include &lt;utf.h&gt;<br />Library: charconv.lib<br />Andreas Jakl, 2008<br />62<br />// Russian text saved as UTF8<br />_LIT8(KString8, &quot;Телефон&quot;);<br />TBufC8&lt;20&gt; source8(KString8);<br />// Create target 16 bit buffer for Unicode string<br />RBuf target16;<br />target16.CreateL(source8.Length());<br />target16.CleanupClosePushL();<br />// Use conversion library to convert from UTF8 to Unicode<br />CnvUtfConverter::ConvertToUnicodeFromUtf8(target16, source8);<br />// Print results and do cleanup<br />console-&gt;Printf(target16);<br />CleanupStack::PopAndDestroy(1);<br />
  63. 63. More about Descriptor Usage<br />Other things you should know<br />Andreas Jakl, 2008<br />63<br />
  64. 64. TLex<br />General string-parsing functions suitable for numeric format conversions and syntactical-element parsing<br />e.g. parse GPS data (NMEA)<br />Powerful, but very complex<br />More information at:<br />http://descriptors.blogspot.com/2005/08/35-how-do-i-use-tlex.html<br />Andreas Jakl, 2008<br />64<br />
  65. 65. Conversion String  Number<br />String  Number: Provided by TDes<br />Number  String: Simple use of TLex<br />Andreas Jakl, 2008<br />65<br />_LIT(KTestString1, &quot;54321&quot;);<br />// Convertstring to number<br />TLexlex(KTestString1());<br />TIntvalue = 0;<br />User::LeaveIfError(lex.Val(value));<br />ASSERT(value==54321);<br />// Convertnumber to string<br />TBuf&lt;8&gt; buf;<br />buf.Num(value);<br />
  66. 66. Formatting Text<br />Integrate variables into text<br />Appending text or numbers<br />Simplest way: use the AppendNum()-function defined in TDes<br />Make sure the target descriptor is large enough!<br />Andreas Jakl, 2008<br />66<br />_LIT(KText, &quot;Number &quot;);<br />TBuf&lt;15&gt; myText(KText);<br />myText.AppendNum(1);<br />console-&gt;Printf(myText);<br />
  67. 67. Formatting Text<br />Format strings<br />Use placeholders for elements<br />Full syntax in the SDK help: » Symbian OS vXX » Symbian OS guide » Base » Using User Library (E32) » Buffers and Strings » Using Descriptors » How to Use Descriptors » Format string syntax<br />Console (format syntax directly integrated)<br />Andreas Jakl, 2008<br />67<br />_LIT(KName, &quot;Joe Bloggs&quot;);<br />_LIT(KText, &quot;Name: %S, Age: %d&quot;);<br />TBuf&lt;30&gt; myText;<br />myText.Format(KText, &KName, 27);<br />console-&gt;Printf(myText);<br />TInt result = 0;<br />_LIT(KFormatCompare1, &quot;Compare() using str1 and str2 = %d &quot;);<br />console-&gt;Printf(KFormatCompare1, result);<br />
  68. 68. TFileName<br />Definition of TFileName(e32const.h / e32cmn.h):<br />const TIntKMaxFileName=0x100; // = Decimal 256typedefTBuf&lt;KMaxFileName&gt; TFileName;<br />Required size on the stack: 520 bytes<br />2 x 256 data bytes (Unicode), 8 bytes for descriptor obj.<br />Standard stack size in Symbian OS: 8kB<br />Therefore:<br />Do not allocate TFileName on the stack (however: instance var. of CBase-class is on the heap!)<br />Do not pass it by value!<br />… use RBuf instead!<br />Andreas Jakl, 2008<br />68<br />
  69. 69. Test your Knowledge<br />Did you understand everything?<br />Andreas Jakl, 2008<br />69<br />
  70. 70. ASD-like Question – Easy <br />Which of the following statements about descriptors are correct?<br />A. All descriptor classes, except RBuf, derive from TDesC.<br />B. The first four bytes of a descriptor store the descriptor’s length and type.<br />C. The descriptor classes do not use virtual functions to avoid the overhead of a virtual function pointer in every descriptor object.<br />D. Modifiable descriptors use the NULL terminator to indicate the end of the descriptor data.<br />E. All descriptors have “wide”, 16-bit characters.<br />Andreas Jakl, 2008<br />70<br />Copyright Meme Education, 2006<br />http://www.meme-education.com/<br />
  71. 71. Solution<br />A.Incorrect. RBuf derives from TDesC as well.<br />B. Correct.<br />C. Correct.<br />D. Incorrect. The NULL terminator is not used by descriptors. Only Literals are -terminated because of the C++-compiler, but this is hidden from the developers.<br />E. Incorrect. Descriptors are available as 8 bit and 16 bit variants.<br />Andreas Jakl, 2008<br />71<br />
  72. 72. ASD-like Question – Medium<br />Andreas Jakl, 2008<br />72<br />_LIT(KHello, &quot;Hello!&quot;);<br />TBufC&lt;6&gt; hello(KHello);<br />_LIT(KBye, &quot;Goodbye!&quot;);<br />TBufC&lt;8&gt; bye(KBye);<br />TPtrfoo(hello.Des());<br />TIntlen = foo.Length();<br />TIntmaxLen = foo.MaxLength();<br />TPtr bar(bye.Des());<br />foo.Set(bar);<br />len = foo.Length();<br />maxLen = foo.MaxLength();<br />foo.Copy(KHello);<br />len = foo.Length();<br />maxLen = foo.MaxLength();<br />Which of the following statements are correct?<br />A. After executing line 2, a call to hello.MaxLength() returns 6.<br />B. After executing line 6, len = 6; After line 7, maxLen = 6.<br />C. After executing line 9, hello contains “Goodbye!”.<br />D. After executing line 10, len = 8; After line 11, maxLen = 8.<br />E. After executing line 13, len = 6; After line 14, maxLen = 6.<br />Copyright Meme Education, 2006<br />http://www.meme-education.com/<br />
  73. 73. Solution<br />A.Incorrect. TBufC does not have a MaxLength()-function. This is defined in TDes base class.<br />B. Correct.<br />C. Incorrect. After the Set()-function, the foo-TPtr points to the same memory as the bar-TPtr. The buffers are not altered however. This would be the case with =.<br />D. Correct. <br />E. Incorrect. MaxLength = 8, as foo is now pointing to the buffer of the bar-TPtr, which is the bye-TBuf with a max. length of 8.<br />Andreas Jakl, 2008<br />73<br />
  74. 74. ASD-like Question – Hard<br />Andreas Jakl, 2008<br />74<br />Which of the following uses of a descriptor should be reconsidered?<br />A. USE 1<br />B. USE 2<br />C. USE 3<br />D. USE 4<br />E. USE 5<br />classCTestClass : publicCBase {<br />public:<br />staticCTestClass* NewL(constTFileNameaFilename); // USE 1<br />public:<br />inlineconstTDesC& FileName() {return (iFileName);}; // USE 2<br />voidSendDataL(constTBufC&lt;20&gt;& aData); // USE 3<br />voidReceiveDataL(TDes& aData); // USE 4<br />private:<br /> // Construction code omitted for clarity<br />private:<br />TFileNameiFileName; // USE 5<br />};<br />Copyright Meme Education, 2006<br />http://www.meme-education.com/<br />
  75. 75. Solution<br />A.Reconsider. TFileName should be passed by reference, not by value. <br />B. OK.<br />C. Reconsider. Use generic parameter instead (const TDesC& aData).<br />D. OK. <br />E. OK. <br />Andreas Jakl, 2008<br />75<br />
  76. 76. Resources<br />Famous blogs with answers to common problems:<br />http://descriptors.blogspot.com/<br />http://descriptor-tips.blogspot.com/<br />Detailed information in the books:<br />Symbian OS C++ for Mobile Phones, Vol. 3<br />Symbian OS Explained<br />Andreas Jakl, 2008<br />76<br />Unfortunately this book do not cover the most recent addition to Symbian OS, the RBuf. Apart from this minor disadvantage, it is very useful.<br />
  77. 77. Thanks for your attention<br />That’s it!<br />Andreas Jakl, 2008<br />77<br />

×