<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-12767873</id><updated>2012-04-15T15:23:03.196-07:00</updated><title type='text'>Top Tips for Descriptors</title><subtitle type='html'>Take a tip, leave a tip!  We've made the descriptor mistakes so you don't have to...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://descriptor-tips.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default'/><link rel='alternate' type='text/html' href='http://descriptor-tips.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jo Stichbury</name><uri>http://www.blogger.com/profile/11641972941072027994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://www.whoshavesthebarber.com/pictures/sose.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>12</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-12767873.post-111904599537833103</id><published>2005-06-17T15:02:00.000-07:00</published><updated>2005-06-17T15:06:35.386-07:00</updated><title type='text'>Tip 10: Use operator&gt;&gt; and operator&lt;&lt; to internalize and externalize descriptor data.  But remember that they can leave!</title><content type='html'>When externalizing data to a writable stream, or internalizing it from a readable stream, use the operators crafted for this purpose rather than 'rolling your own'.  This code, which reads/writes the descriptor length using 4 bytes, then the data itself, is awkward and inefficient.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;// Write the contents of aDes to aStream&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;void CMyClass::ExternalizeL(RWriteStream&amp; aStream, const TDesC&amp;amp; aDes) const&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;{// Write the length of aDes&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;aStream.WriteUint32L(aDes.Length());&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;// Write the data from aDes&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;aStream.WriteL(aDes, aDes.Length());&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;}&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;&lt;br /&gt;// Read the contents of aStream and create an HBufC&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;HBufC* CMyClass::InternalizeL(RReadStream&amp; aStream)&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;{// Read the length of aDes&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;TInt size=aStream.ReadUint32L(); &lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;// Allocate a buffer&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;HBufC* heapBuf = HBufC::NewL(size); &lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;// Create a modifiable descriptor over heapBuffer&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;TPtr ptr(heapBuffer-&gt;Des());&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;// Read the descriptor data&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;aStream.ReadL(ptr,size);&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;return (heapBuf);&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you link against estor.lib, you can use the templated stream operators that Symbian OS provides, for much more efficient internalization and externalization.  The length information of the descriptor is compressed to make descriptor storage as compact as possible. &lt;br /&gt;&lt;br /&gt;You can use operator&amp;gt;&amp;gt; to internalize string data, if it was externalized using operator&amp;gt;&amp;gt;, but additionally, the stream data can be passed to HBufC::NewL(), as a read stream, to recreate the descriptor.  Either of these are a significantly more efficient approach to that above:&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;&lt;br /&gt;// Write the contents of aDes to aStream&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;void CMyClass::ExternalizeL(RWriteStream&amp; aStream, const TDesC&amp;amp; aDes) const&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;{&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;aStream &amp;lt;&amp;lt; aDes;&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;}&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;&lt;br /&gt;// Read the contents of aStream and create an HBufC&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;HBufC* CMyClass::InternalizeL(RReadStream&amp; aStream)&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;{// KMaxLength is defined elsewhere as the maximum length read from the stream&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;HBufC* heapBuf = HBufC::NewL(aStream, KMaxLength);  &lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You’ll notice that the ExternalizeL() and InternalizeL functions above are leaving functions. This is because the templated streaming operators, operator&amp;gt;&amp;gt; and operator&amp;lt;&amp;lt;, may leave. They are not suffixed with L because they are operators, and can't be named according to the convention for leaving functions on Symbian OS. This makes it easy to forget that they leave, which isn't helped by the fact that the leave-checking tool LeaveScan doesn't flag them.&lt;br /&gt;&lt;br /&gt;So, if you write code which uses them, you should make a special point of checking that it is leave-safe.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12767873-111904599537833103?l=descriptor-tips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://descriptor-tips.blogspot.com/feeds/111904599537833103/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12767873&amp;postID=111904599537833103' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/111904599537833103'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/111904599537833103'/><link rel='alternate' type='text/html' href='http://descriptor-tips.blogspot.com/2005/06/tip-10-use-operator-to-internalize-and.html' title='Tip 10: Use operator&amp;gt;&amp;gt; and operator&amp;lt;&amp;lt; to internalize and externalize descriptor data.  But remember that they can leave!'/><author><name>Jo Stichbury</name><uri>http://www.blogger.com/profile/11641972941072027994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://www.whoshavesthebarber.com/pictures/sose.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12767873.post-111904531488772679</id><published>2005-06-17T14:44:00.000-07:00</published><updated>2005-06-17T15:00:47.736-07:00</updated><title type='text'>Tip 9: Beware of calling MaxLength() on the TPtr returned from HBufC::Des()</title><content type='html'>There's an interesting side effect to calling &lt;span style="font-family:courier new;"&gt;Des()&lt;/span&gt; on an &lt;span style="font-family:courier new;"&gt;HBufC &lt;/span&gt;to return a modifiable descriptor.&lt;br /&gt;&lt;br /&gt;Recall that &lt;span style="font-family:courier new;"&gt;HBufC &lt;/span&gt;derives from &lt;span style="font-family:courier new;"&gt;TDesC&lt;/span&gt;, and thus &lt;span style="font-family:courier new;"&gt;an HBufC &lt;/span&gt;object doesn’t have a maximum length word, because it is non-modifiable and doesn’t need one.  But when you call &lt;span style="font-family:courier new;"&gt;Des()&lt;/span&gt; to return a modifiable descriptor, a &lt;span style="font-family:courier new;"&gt;TPtr &lt;/span&gt;which references the descriptor data, the modifiable descriptor must have a maximum length value.  So where does it come from?&lt;br /&gt;&lt;br /&gt;Well, in fact, the maximum length of the heap cell in which the &lt;span style="font-family:courier new;"&gt;HBufC &lt;/span&gt;was allocated is used to set the maximum length of the returned &lt;span style="font-family:courier new;"&gt;TPtr&lt;/span&gt;. But beware! This may not necessarily be the length specified when the heap descriptor was allocated. There are two reasons why this can occur, the first of which is the most common:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;   &lt;li&gt;If the length specified wasn't word-aligned (i.e. a multiple of 4 bytes) or &lt;/li&gt;   &lt;li&gt;Because the amount of space left over in the free cell from which the heap cell was allocated was insufficent to create any other heap cells, so was left spare. The minimum size required for a heap cell is approximately 12 bytes so, if there are fewer than 12 bytes in the remaining cell, your descriptor will end up with the surplus tacked on the end. &lt;/li&gt; &lt;/ol&gt;&lt;br /&gt;The result in either case is that the maximum length of a &lt;span style="font-family:courier new;"&gt;TPtr &lt;/span&gt;returned from &lt;span style="font-family:courier new;"&gt;HBufC::Des()&lt;/span&gt; may not be what you expect, given the size specified when the heap descriptor was created - it could be longer.  For example:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;const TInt KMaxBufLength = 9;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;HBufC8* buf = HBufC8::NewL(KMaxBufLength);&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;TPtr8 ptr(buf-&gt;Des());&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;TInt maxLength = ptr.MaxLength(); // maxLength &gt; 9 but may not be 12&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Don’t expect that it is simply rounded up to the next word-aligned value. In the example above, the maximum length is guaranteed to be at least three extra bytes but &lt;span style="font-weight: bold;"&gt;it may be more&lt;/span&gt;, depending on the remaining size of the heap cell from which it was allocated.&lt;br /&gt;&lt;br /&gt;So, if you cannot guarantee that the value of &lt;span style="font-family:courier new;"&gt;MaxLength()&lt;/span&gt; is what you expect, it's safest to use the integer value used to first allocate the &lt;span style="font-family:courier new;"&gt;HBufC&lt;/span&gt;.  If the length of the heap buffer was set to its maximum on creation, you can alternatively use that:&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;br /&gt;const TInt KMaxBufLength = 9;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;HBufC8* buf = HBufC8::NewL(KMaxBufLength);&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;TPtr8 ptr(buf-&gt;Des());&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;TInt unpredictable = ptr.MaxLength(); // maxLength &gt; 9 but may not be 12&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;TInt bufLen = buf-&gt;Length();&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:georgia;"&gt;bufLen will be 0, because the buffer was not set to its maximum length on creation.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:georgia;"&gt;  This is done by calling &lt;span style="font-family:courier new;"&gt;NewMaxL()&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;HBufC8* buf = HBufC8::NewMaxL(KMaxBufLength);&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;TInt bufLen = buf-&gt;Length(); // This will be 9&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;So how does this matter?  &lt;/span&gt;&lt;br /&gt;Well, you can get caught out. Here's an example I used in my book. It illustrates the use of pointers to manipulate the contents of a descriptor and the use of an assertion statement to catch access beyond the descriptor length:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;_LIT(KPanic, "TestPointer");&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;const TInt KBufferLength = 10;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;void TestPointer()&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;{// Create a buffer with length KBufferLength = 10 bytes&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;HBufC8* myBuffer = HBufC8::NewMaxL(KBufferLength);&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;TPtr8 myPtr(myBuffer-&gt;Des());&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;myPtr.Fill('?'); // Fill with '?'&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;br /&gt;// Byte pointer to descriptor in memory&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;TUint8* ptr = (TUint8*)myPtr.Ptr();&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;TInt maxLength = myPtr.MaxLength();&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;br /&gt;for (TInt index = 0; index &amp;lt; maxLength; index++)&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;{// This fails at the end of the buffer (index = 10)&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;// because myPtr.MaxLength() &amp;gt; KBufferLength&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;__ASSERT_DEBUG(index&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;KBufferLength&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;, &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;User::Panic(KPanic, KErrOverflow));&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;(*ptr) = '!'; // Replace the contents with '!'&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;++ptr;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;}&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;br /&gt;}&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12767873-111904531488772679?l=descriptor-tips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://descriptor-tips.blogspot.com/feeds/111904531488772679/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12767873&amp;postID=111904531488772679' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/111904531488772679'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/111904531488772679'/><link rel='alternate' type='text/html' href='http://descriptor-tips.blogspot.com/2005/06/tip-9-beware-of-calling-maxlength-on.html' title='Tip 9: Beware of calling MaxLength() on the TPtr returned from HBufC::Des()'/><author><name>Jo Stichbury</name><uri>http://www.blogger.com/profile/11641972941072027994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://www.whoshavesthebarber.com/pictures/sose.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12767873.post-111862368929645647</id><published>2005-06-12T17:45:00.000-07:00</published><updated>2005-06-12T17:48:09.300-07:00</updated><title type='text'>Tip 8: Don't confuse Size() and Length().</title><content type='html'>The base class TDesC defines both &lt;span style="font-family: courier new;"&gt;Size()&lt;/span&gt; and &lt;span style="font-family: courier new;"&gt;Length()&lt;/span&gt; methods, which are easy to confuse.&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;&lt;br /&gt;Size()&lt;/span&gt; returns the number of &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;bytes&lt;/span&gt; the descriptor occupies.&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Length()&lt;/span&gt; returns the number of &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;characters&lt;/span&gt; the descriptor contains.&lt;br /&gt;&lt;br /&gt;For 8-bit descriptors, where each character occupies a byte, this is the same thing.  However, on all releases of Symbian OS since v5u, the native character width has been 16 bits; that is, each character occupies two bytes.&lt;br /&gt;&lt;br /&gt;Thus, unless you're working with a very old SDK, you'll find that &lt;span style="font-weight: bold;"&gt;&lt;span style="font-family: courier new;"&gt;Size()&lt;/span&gt; always returns a value which is double that of &lt;span style="font-family: courier new;"&gt;Length()&lt;/span&gt;&lt;/span&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12767873-111862368929645647?l=descriptor-tips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://descriptor-tips.blogspot.com/feeds/111862368929645647/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12767873&amp;postID=111862368929645647' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/111862368929645647'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/111862368929645647'/><link rel='alternate' type='text/html' href='http://descriptor-tips.blogspot.com/2005/06/tip-8-dont-confuse-size-and-length.html' title='Tip 8: Don&apos;t confuse Size() and Length().'/><author><name>Jo Stichbury</name><uri>http://www.blogger.com/profile/11641972941072027994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://www.whoshavesthebarber.com/pictures/sose.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12767873.post-111852955210348236</id><published>2005-06-11T14:21:00.000-07:00</published><updated>2005-06-12T17:16:29.520-07:00</updated><title type='text'>Tip 7: For API design, use the descriptor base classes as parameters and return values.</title><content type='html'>In your APIs, use the descriptor base classes &lt;span style="font-family:courier new;"&gt;TDes&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;TDesC&lt;/span&gt; as parameters and return values.  And remember to pass them by reference for efficiency, and &lt;span style="font-weight: bold;"&gt;never&lt;/span&gt; by value.  Thus, descriptor parameters should be passed and returned either as &lt;span style="font-weight: bold;font-family:courier new;" &gt;const&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;span style="font-weight: bold;font-family:courier new;" &gt;TDesC&amp;&lt;/span&gt; for constant descriptors or &lt;span style="font-weight: bold;font-family:courier new;" &gt;TDes&amp;&lt;/span&gt; when modifiable.&lt;br /&gt;&lt;br /&gt;Callers of your API will not want to be constrained, say, to have to use a &lt;span style="font-family:courier new;"&gt;TBuf&lt;/span&gt;, just because your function requires it. And your functions shouldn't care what type of descriptor is passed to them, as long as any modifiable descriptor has a sufficient data area to extend into, as necessary.&lt;br /&gt;&lt;br /&gt;One good reason for this 'agnosticism' is that, if you need to change the implementation later, and have exposed the descriptor type at the API level, you make it harder for yourself to change the code without affecting the API. You really don't want to have to ask your clients to change their code because you've broken source compatibility.&lt;br /&gt;&lt;br /&gt;And anyway, unless you’re taking ownership, if you're implementing a function you shouldn’t need to know if an incoming parameter is stack- or heap-based. Its location and memory layout should be irrelevant. Likewise if you're calling a method, and receiving a descriptor as a return value, you don't need to know what type it is, unless it is a heap descriptor for which you become responsible for cleanup.&lt;br /&gt;&lt;br /&gt;Thus, when defining functions you should always use the abstract base classes as parameters or return values. For example, class &lt;span style="font-family:courier new;"&gt;RFile&lt;/span&gt; defines straightforward file read and write methods as follows:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;IMPORT_C TInt Write(const TDesC8&amp;amp; aDes);&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;IMPORT_C TInt Read(TDes8&amp; aDes) const;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The descriptor to write to the file is a constant descriptor, while to read from the file into a descriptor requires the parameter to be modifiable (the maximum length of the modifiable descriptor determines how much file data can be read into it).&lt;br /&gt;&lt;br /&gt;When writing a function which receives a modifiable descriptor you don’t have to know whether it has sufficient memory for an operation, such as &lt;span style="font-family:courier new;"&gt;Append()&lt;/span&gt;, since the descriptor methods themselves &lt;a href="http://descriptors.blogspot.com/2005/05/memory-management-and-descriptors.html"&gt;make the check and panic&lt;/a&gt; if the operation would cause an overflow. However, you may not want the descriptor methods to panic if the caller has not got a large enough descriptor, because sometimes they cannot know the maximum length required. (Remember, a panic is terminal and in effect causes a 'crash' which can be pretty ugly).&lt;br /&gt;&lt;br /&gt;As an alternative, you could perform your own bounds checking before calling a method on the incoming descriptor, then return an error or leave when you need to indicate to the caller that the descriptor's maximum length is insufficient. In addition, you could write the required length into the 'too short' descriptor supplied (assuming it is at least 4 bytes in length) so the caller can use it to allocate a descriptor of the correct minimum length.&lt;br /&gt;&lt;br /&gt;There are occasions when you pass and return heap descriptors, &lt;span style="font-family:courier new;"&gt;HBufC&lt;/span&gt;, by reference or pointer.  I'll go into this in a separate post.&lt;br /&gt;&lt;br /&gt;See also, &lt;a href="http://descriptors.blogspot.com/2005/05/how-do-i-use-descriptors-as-parameters.html"&gt;this&lt;/a&gt; FAQ ("How do I use descriptors as parameters?") and &lt;a href="http://descriptors.blogspot.com/2005/05/how-do-i-use-heap-descriptors-as.html"&gt;this&lt;/a&gt; one, which covers returning them ("How do I use heap descriptors as return types?").&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12767873-111852955210348236?l=descriptor-tips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://descriptor-tips.blogspot.com/feeds/111852955210348236/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12767873&amp;postID=111852955210348236' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/111852955210348236'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/111852955210348236'/><link rel='alternate' type='text/html' href='http://descriptor-tips.blogspot.com/2005/06/tip-7-for-api-design-use-descriptor.html' title='Tip 7: For API design, use the descriptor base classes as parameters and return values.'/><author><name>Jo Stichbury</name><uri>http://www.blogger.com/profile/11641972941072027994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://www.whoshavesthebarber.com/pictures/sose.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12767873.post-111566628286958628</id><published>2005-05-09T12:15:00.000-07:00</published><updated>2005-05-09T12:18:44.550-07:00</updated><title type='text'>Tip 6: Need to read from an HBufC? Don't call Des().</title><content type='html'>To read from a descriptor, you only need it to be non-modifiable, a &lt;span style="font-family:courier new;"&gt;TDesC&lt;/span&gt;.  Class &lt;span style="font-family:courier new;"&gt;HBufC &lt;/span&gt;derives from &lt;span style="font-family:courier new;"&gt;TDesC&lt;/span&gt;, so it has access to all the non-modifiable functions implemented by &lt;span style="font-family:courier new;"&gt;TDesC&lt;/span&gt;. All you need to do is dereference the pointer.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;_LIT(KBert, "Bert");&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;HBufC* bert = KBert.AllocL();&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;TPtrC halfOfBert = bert-&gt;Left(2);&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;One of the most common mistakes made when using descriptors is to call &lt;span style="font-family:courier new;"&gt;Des()&lt;span style="font-family: georgia;"&gt; &lt;/span&gt;&lt;/span&gt;on an &lt;span style="font-family:courier new;"&gt;HBufC*&lt;/span&gt; when you only need a constant descriptor.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;_LIT(KBert, "Bert");&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;HBufC* bert = KBert().AllocL();&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;TPtrC halfOfBert = bert-&gt;Des().Left(2);  // Unnecessary call to Des()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It won’t do any harm, but is totally unnecessary and wastes time, space and typing&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12767873-111566628286958628?l=descriptor-tips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://descriptor-tips.blogspot.com/feeds/111566628286958628/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12767873&amp;postID=111566628286958628' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/111566628286958628'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/111566628286958628'/><link rel='alternate' type='text/html' href='http://descriptor-tips.blogspot.com/2005/05/tip-6-need-to-read-from-hbufc-dont.html' title='Tip 6: Need to read from an HBufC? Don&apos;t call Des().'/><author><name>Jo Stichbury</name><uri>http://www.blogger.com/profile/11641972941072027994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://www.whoshavesthebarber.com/pictures/sose.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12767873.post-111566601625006183</id><published>2005-05-09T12:07:00.000-07:00</published><updated>2005-06-05T14:38:58.056-07:00</updated><title type='text'>Tip 5: Need to modify an HBufC? Call Des().</title><content type='html'>An &lt;span style="font-family:courier new;"&gt;HBufC &lt;/span&gt;is derived from &lt;span style="font-family:courier new;"&gt;TDesC&lt;/span&gt;, and inherits non-modifiable descriptor functionality.  Because it is not derived from &lt;span style="font-family:courier new;"&gt;TDes&lt;/span&gt;, it isn’t modifiable. So to write into it, you have to create a modifiable descriptor over the data area. This is done by calling &lt;span style="font-family:courier new;"&gt;HBufC::Des()&lt;/span&gt; which returns a &lt;span style="font-family:courier new;"&gt;TPtr &lt;/span&gt;and thus gives you access to all the modification functions such as &lt;span style="font-family:courier new;"&gt;Format()&lt;/span&gt;, &lt;span style="font-family:courier new;"&gt;Append()&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;Fill()&lt;/span&gt;&lt;span style="font-family:georgia;"&gt;:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;HBufC* robert = HBufC::NewL(4); // Read Only Bert&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;TPtr rwbert(robert-&gt;Des()); // Read Write Bert&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;_LIT(KBert, "Bert");&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;rwbert.Copy(KBert); // The data area of robert now contains Bert&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Remember that that there must be space in the &lt;span style="font-family:courier new;"&gt;HBufC&lt;/span&gt; for the required change because descriptors don’t resize themselves automatically. If there isn’t, it will still compile - but you’ll get a panic at runtime, as described in &lt;a href="http://descriptor-tips.blogspot.com/2005/05/tip-2-check-that-there-is-sufficient.html"&gt;Tip 2&lt;/a&gt;. This code will fail:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;HBufC* robert = HBufC::NewL(&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;2&lt;/span&gt;); // Read Only Bert&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;TPtr rwbert(robert-&gt;Des()); // Read Write Bert&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;_LIT(KBert, "Bert");&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;rwbert.Copy(KBert); // Panic! Not enough memory allocated to hold "Bert"&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The reason why there is no HBuf class is discussed &lt;a href="http://descriptors.blogspot.com/2005/05/why-is-there-no-hbuf-class.html"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12767873-111566601625006183?l=descriptor-tips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://descriptor-tips.blogspot.com/feeds/111566601625006183/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12767873&amp;postID=111566601625006183' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/111566601625006183'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/111566601625006183'/><link rel='alternate' type='text/html' href='http://descriptor-tips.blogspot.com/2005/05/tip-5-need-to-modify-hbufc-call-des.html' title='Tip 5: Need to modify an HBufC? Call Des().'/><author><name>Jo Stichbury</name><uri>http://www.blogger.com/profile/11641972941072027994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://www.whoshavesthebarber.com/pictures/sose.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12767873.post-111566555485646095</id><published>2005-05-09T12:04:00.000-07:00</published><updated>2005-05-28T17:56:59.720-07:00</updated><title type='text'>Tip 4: Need a larger or unknown length descriptor? Use HBufC.</title><content type='html'>Heap-based descriptors, &lt;span style="font-family:courier new;"&gt;HBufC&lt;/span&gt;, are allocated on the heap at run time. They can be used as local variables or as class members. As with all heap-based objects, memory leaks must be avoided through use of the cleanup stack - for local variables - or deleted by a destructor if ownership is through a member variable.&lt;br /&gt;&lt;br /&gt;There's more about HBufC in the FAQ blog &lt;a href="http://descriptors.blogspot.com/2005/05/how-do-i-use-heap-based-buffer.html"&gt;here&lt;/a&gt;&lt;span style="text-decoration: underline;"&gt;&lt;/span&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12767873-111566555485646095?l=descriptor-tips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://descriptor-tips.blogspot.com/feeds/111566555485646095/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12767873&amp;postID=111566555485646095' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/111566555485646095'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/111566555485646095'/><link rel='alternate' type='text/html' href='http://descriptor-tips.blogspot.com/2005/05/tip-4-need-larger-or-unknown-length.html' title='Tip 4: Need a larger or unknown length descriptor? Use HBufC.'/><author><name>Jo Stichbury</name><uri>http://www.blogger.com/profile/11641972941072027994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://www.whoshavesthebarber.com/pictures/sose.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12767873.post-111566541835075813</id><published>2005-05-09T11:58:00.000-07:00</published><updated>2005-05-09T12:06:29.123-07:00</updated><title type='text'>Tip 3: Need a small known length descriptor? Use TBuf or TBufC.</title><content type='html'>These are suitable for when you know the required length at compile time. The recommended maximum length is 256 bytes or fewer (remember that’s 128 characters, a &lt;span style="font-family:courier new;"&gt;TBuf&lt;128&gt;&lt;/span&gt;, because each character occupies 2 bytes). &lt;br /&gt;&lt;br /&gt;Larger stack buffers are &lt;a href="http://descriptors.blogspot.com/2005/05/large-stack-based-descriptors.html"&gt;not recommended&lt;/a&gt;.  You should limit the size of stack based buffers by putting larger sized descriptor data on the heap using &lt;span style="font-family:courier new;"&gt;HBufC&lt;/span&gt; objects - or by making your larger &lt;span style="font-family:courier new;"&gt;TBuf &lt;/span&gt;objects member variables of C classes, which are always created on the heap. This is because stack space per process is limited on Symbian OS devices, typically to 8 or 12 KB. So if you use significantly larger buffers on the stack, you risk running out of space.&lt;br /&gt;&lt;br /&gt;The Windows emulator will actually extend the program stack, so you may not realize there’s a problem until you deploy your code on an actual phone. How will you realize? Well, attempts to use the stack will result in access to memory which is not mapped into the address space of the process the code is running in. An access violation occurs, which generates an exception and a KERN-EXEC 3 panic. Which is fatal.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12767873-111566541835075813?l=descriptor-tips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://descriptor-tips.blogspot.com/feeds/111566541835075813/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12767873&amp;postID=111566541835075813' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/111566541835075813'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/111566541835075813'/><link rel='alternate' type='text/html' href='http://descriptor-tips.blogspot.com/2005/05/tip-3-need-small-known-length.html' title='Tip 3: Need a small known length descriptor? Use TBuf or TBufC.'/><author><name>Jo Stichbury</name><uri>http://www.blogger.com/profile/11641972941072027994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://www.whoshavesthebarber.com/pictures/sose.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12767873.post-111566356569126134</id><published>2005-05-09T11:23:00.000-07:00</published><updated>2005-05-09T14:02:35.663-07:00</updated><title type='text'>Tip 2: Check that there is sufficient space before writing to a descriptor</title><content type='html'>An attempt to access an area outside the area allocated for descriptor data will cause a panic in both debug and release builds, because the descriptor functions use &lt;a href="http://www.symbian.com/developer/techlib/v8.1adocs/doc_source/reference/reference-cpp/N101BA/SystemMacros/ASSERTALWAYSMacro.html"&gt;&lt;span style="font-family:courier new;"&gt;__ASSERT_ALWAYS&lt;/span&gt;&lt;/a&gt; to check for out-of-bounds access. A panic causes your code will stop executing immediately, whether running in an application, server or test framework. So be absolutely certain that there is space in your target descriptor, if necessary, by doing a check first by using the &lt;span style="font-family:courier new;"&gt;Length()&lt;/span&gt; or &lt;span style="font-family:courier new;"&gt;MaxLength()&lt;/span&gt; methods.&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;_LIT8(KImageGif, “image/gif”); // 9 characters&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;TBuf8&lt;8&gt; mimeType8;            // Space for only 8 characters&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;mimeType8.Copy(KImageGif);     // Panic!&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12767873-111566356569126134?l=descriptor-tips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://descriptor-tips.blogspot.com/feeds/111566356569126134/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12767873&amp;postID=111566356569126134' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/111566356569126134'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/111566356569126134'/><link rel='alternate' type='text/html' href='http://descriptor-tips.blogspot.com/2005/05/tip-2-check-that-there-is-sufficient.html' title='Tip 2: Check that there is sufficient space before writing to a descriptor'/><author><name>Jo Stichbury</name><uri>http://www.blogger.com/profile/11641972941072027994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://www.whoshavesthebarber.com/pictures/sose.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12767873.post-111566172688220285</id><published>2005-05-09T10:54:00.000-07:00</published><updated>2005-05-09T14:00:56.760-07:00</updated><title type='text'>Tip 1: Never instantiate a TDes or a TDesC</title><content type='html'>The default constructors of &lt;a href="http://www.symbian.com/developer/techlib/v8.1adocs/doc_source/reference/reference-cpp/N101BA/Descriptors/TDes16Class.html#%3a%3aTDes16"&gt;&lt;span style="font-family:courier new;"&gt;TDes&lt;/span&gt;&lt;/a&gt; and &lt;a href="http://www.symbian.com/developer/techlib/v8.1adocs/doc_source/reference/reference-cpp/N101BA/Descriptors/TDesC16Class.html#%3a%3aTDesC16"&gt;&lt;span style="font-family:courier new;"&gt;TDesC&lt;/span&gt;&lt;/a&gt; are declared private so the compiler won’t let you construct them directly. But there is no copy constructor declared for either class, so the compiler won’t complain if you make a copy of a valid descriptor (in fact, it will go as far as to help you, by invoking an implicitly generated copy constructor). &lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;br /&gt;_LIT(KExample, "Fred");&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;TPtrC original(KExample); &lt;span style="color: rgb(51, 204, 0);"&gt;// a valid TDesC-derived descriptor&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 204, 0);font-family:courier new;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 204, 0);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;// Shallow copy the type and length into base class object&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;TDesC copy(original); &lt;span style="color: rgb(51, 204, 0);"&gt;// Uses the implicit copy constructor&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Your code probably won’t crash if it has been written safely, but you will rarely have a valid reason for doing this. The code will fail to work anyway, because &lt;span style="font-family:courier new;"&gt;TDes&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;TDesC&lt;/span&gt; contain no string data, so in effect are abstract classes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12767873-111566172688220285?l=descriptor-tips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://descriptor-tips.blogspot.com/feeds/111566172688220285/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12767873&amp;postID=111566172688220285' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/111566172688220285'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/111566172688220285'/><link rel='alternate' type='text/html' href='http://descriptor-tips.blogspot.com/2005/05/tip-1-never-instantiate-tdes-or-tdesc.html' title='Tip 1: Never instantiate a TDes or a TDesC'/><author><name>Jo Stichbury</name><uri>http://www.blogger.com/profile/11641972941072027994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://www.whoshavesthebarber.com/pictures/sose.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12767873.post-111852011659163088</id><published>2005-05-08T13:00:00.000-07:00</published><updated>2005-06-11T13:01:56.593-07:00</updated><title type='text'>How do I search this blog?</title><content type='html'>You can use the Search bar at the top of the page or the Google site search at the bottom.&lt;br /&gt;Or simply use the "Find" capability of your browser.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12767873-111852011659163088?l=descriptor-tips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://descriptor-tips.blogspot.com/feeds/111852011659163088/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=12767873&amp;postID=111852011659163088' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/111852011659163088'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/111852011659163088'/><link rel='alternate' type='text/html' href='http://descriptor-tips.blogspot.com/2005/05/how-do-i-search-this-blog.html' title='How do I search this blog?'/><author><name>Jo Stichbury</name><uri>http://www.blogger.com/profile/11641972941072027994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://www.whoshavesthebarber.com/pictures/sose.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-12767873.post-114831916910584543</id><published>2005-05-03T10:29:00.000-07:00</published><updated>2006-12-30T13:46:48.106-08:00</updated><title type='text'>NEWS: 22/05/2006</title><content type='html'>Please note that the links in this blog to the sister blog (&lt;a href="http://descriptors.blogspot.com"&gt;Descriptors FAQ&lt;/a&gt;) are currently broken.  It's happened because I've been updating the FAQ blog in preparation for a new look, format and home.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/12767873-114831916910584543?l=descriptor-tips.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/114831916910584543'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/12767873/posts/default/114831916910584543'/><link rel='alternate' type='text/html' href='http://descriptor-tips.blogspot.com/2005/05/news-22052006.html' title='NEWS: 22/05/2006'/><author><name>Jo Stichbury</name><uri>http://www.blogger.com/profile/11641972941072027994</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://www.whoshavesthebarber.com/pictures/sose.jpg'/></author></entry></feed>
