You Are Here:

Community: Blogs

Open Source Bluetooth PAN's Forum Nokia Blog

Symbian, Descriptors and Unicode

Carbider | 20 January, 2009 11:41

    While programming Bluetooth data transmission routines I've come across an encoding issue at Symbian. The task was to send and receive Unicode strings encoded in UTF-16. The data was moved by RSocket class.

The thing is, the RSocket's read and write methods are taking the 8 bit descriptors only (representing the binary data), so we need to convert the 8 bit descriptors to 16 bit and vice versa. 
For example, we need to receive some UTF-16 string in Russian language from the server and display it on screen.

Some documents here suggest several solutions on converting descriptors, but they don't work as needed. Let me explain why.

The two common methods of conversion are:

1. To use Copy() method of first the descriptor to copy contents of the second one.

Example:

RBuf8  buf8     ;
RBuf16 buf16    ;

buf16.Copy(buf8);

As a result, the contents of buf8 descriptor would not be simply copied to buf16, but each character would be expanded to 16 bits.
So the string “Hello” would become something like “_H_E_L_L_O” after expanding.




Image 1 – Example of how the Copy() method works, and what we actually need.

On the contrary, when converting the 16 bit descriptor to an 8 bit descriptor, the contents of the first would be collapsed. 

That is a behavior of Copy() method.

2. The second method is to use a CnvUtfConverter class provided in Symbian.

Example:

HBufC8 *heap8;
HBufC  *heap16 = CnvUtfConverter::ConvertToUnicodeFromUtf8L(*heap8);

This method will convert between the Unicode and UTF-8. That is again is not what I needed. What I need is the conversion between the descriptor classes themselves but not transforming their contents, that should stay without any change.

Solving

So to read the Unicode string presented in binary format from socket and display it on screen, we need to convert the descriptor's body (8 bit descriptor to 16 bit descriptor) but not the descriptor's contents.

Here is a method on how can it be done.
To pass the descriptor's contents from the descriptor of one type to another, we have to copy contents somehow. I chose the memcpy() function. If you find a better (or safer) way, please submit it here. 
Example:

Copy the contents of 8 bit descriptor to the 16 bit one.
(without memory allocation routines)

TBuf8       sourceBuf8        ;
TBuf16      destBuf16         ;

TInt len = sourceBuf8.Length();
aOutDest.FillZ(len/2 ); // necessary to set the size memcpy((TAny *)destBuf16.Ptr(), (TAny *)sourceBuf8.Ptr(), len);



This works smoothly for S60 3rd FP1, both emulator and Nokia E90 device.

I wrote the CBinaryConverter class that has two methods, doing these operations. It is attached to this post.

Example of using CBinaryConverter class:



RBuf8 source                      ;
RBuf   dest                       ;  // the same as Rbuf16
TInt destLength                   ;
source.Create(100                );

// Receive the 8 bit descriptor from socket that contains 16 bit data iActiveSocket->RecvOneOrMore(source, 0, iStatus, iLen );
destLength = source.Length() / 2 ; // 16 bit chars instead of 8 bit
dest.CleanupClosePushL() ; // to Cleanup Stack dest.Create( destLength );
//Conversion CBinaryConverter::copy8BitInto16BitDescriptorL(source, dest );
// Show the note CAknInformationNote *iInfNote ; iInfNote = new (ELeave) CAknInformationNote(); iInfNote->ExecuteLD(dest );
CleanupStack::PopAndDestroy(&dest); // Pop RBuf from the Cleanup Stack


Screenshot of the application, that controls Juke Box holding songs in English and Russian languages over Bluetooth:




Download the source code

Download zip package:
BinaryConverter_class.zip

Or view directly:

BinaryConverter.cpp
BinaryConverter.h

 




--
Cheers
Konstantine



RSSComments

TPckg* classes

laa-laa | 20/01/2009, 12:49

laa-laa

Note that there are the TPckg family of templated wrapper classes (TPckg, TPckgC, TPckgBuf) for packaging any fixed-size data (e.g. T class instances) in a 8-bit descriptor and extracting such packages.

Lauri

TPtr/C16

wizard_hu_ | 20/01/2009, 21:05

Based on how 8-bit descriptors look like in the memory I would trust that [0] is word-aligned and try
TPtrC ptr16(static_cast(&buf8[0]),buf8.Size()/2);

Response

Carbider | 21/01/2009, 13:14

Carbider

Thanks for discussion guys!
With last suggestion I could repeat the trick in this manner:

const TUint8* tempBuf_1 = &buf8[0];
TUint8* tempBuf_2 = const_cast(tempBuf_1 );
TUint16* tempBuf_3 = (TUint16*)(tempBuf_2);
TPtrC ptr16(tempBuf_3, destLength);
buf16.Copy(ptr16);

You must login to post comments. Login
 

Rate This

 
 
Bookmark this page: DeliciousDiggFacebookGoogleYahooStumbleUponRedditDiigoTechnocratiTwitter  Share this page Share this page Print this Page Print this page Invite a friend Invite a friend
京ICP备05048969号    Email Newsletters Press Terms & Conditions Privacy Policy Sitemap Contact Us © 2009 Nokia 
RDF Facets: qdcZidentifierQSxhttpE3aE2fE2fblogsE2eforumE2enokiaE2ecomE2fblogE2fopenE2dsourceE2dbluetoothE2dpansE2dforumE2dnokiaE2dblogE2f2009E2f01E2f20E2fsymbianE2ddescriptorsE2dandE2dunicodeX qdcZtypeQUqfnZE45E78cludedFromGeneralE4cistingsQ qdcZtypeQUqfntypeZBlogContentQ qdcZtypeQUqfntypeZBlogE45ntryQ qdcZtypeQUqfntypeZCommunityContentQ qdcZtypeQUqfntypeZE52esourceQ qdcZtypeQUqfntypeZWebpageQ qdcZtypeQUqmarsZManagedE52esourceQ qdcZtypeQUqwebZInformationE52esourceQ qdcZtypeQUqwebZPageQ qdcZtypeQUqwebZE52esourceQ qdcZtypeQUqrdfsZE52esourceQ qfnZtopicQUxhttpE3aE2fE2fswE2enokiaE2ecomE2fFNE2d1E2fBlogTopicE2fgeneralX qfnZtopicQUqfnTopicZconnectivityQ qfnZtopicQUqfnTopicZcppQ qfnZtopicQUqfnTopicZseriesE5f60Q qfnZtypeQUqfntypeZBlogContentQ qfnZtypeQUqfntypeZBlogE45ntryQ qfnZtypeQUqfntypeZCommunityContentQ qfnZtypeQUqfntypeZE52esourceQ qfnZtypeQUqfntypeZWebpageQ qfnZuserE5ftagQSxconnectivityX qfnZuserE5ftagQSxs60X qfnZuserE5ftagQSxsymbianE2dcE2bE2bX qmarsZlanguageQUxhttpE3aE2fE2fswE2enokiaE2ecomE2flanguageE2d1E2fenX qrdfZtypeQUqfnZE45E78cludedFromGeneralE4cistingsQ qrdfZtypeQUqfntypeZBlogContentQ qrdfZtypeQUqfntypeZBlogE45ntryQ qrdfZtypeQUqfntypeZCommunityContentQ qrdfZtypeQUqfntypeZE52esourceQ qrdfZtypeQUqfntypeZWebpageQ qrdfZtypeQUqmarsZManagedE52esourceQ qrdfZtypeQUqwebZInformationE52esourceQ qrdfZtypeQUqwebZPageQ qrdfZtypeQUqwebZE52esourceQ qrdfZtypeQUqrdfsZE52esourceQ