Sunday, June 12, 2005

26. How do I convert between 8 bit and 16 bit descriptors?

TDes defines a set of Copy() methods to copy data from another descriptor of either width, from a pointer to a block of data of a specified length or from a NULL-terminated string. There are also methods for copying with folding,collation or case adjustment.

In each case, the data is copied *from* the source specified in the parameter *into* the modifiable, target, descriptor upon which the method is called. If the length of the 'incoming' data is greater than the target descriptor, a USER 11 panic occurs.

// From the definition of TDes16 in e32des16.h

IMPORT_C void Copy(const TDesC8& aDes); // Copies an 8 bit descriptor
IMPORT_C void Copy(const TDesC16& aDes); // Copies a 16 bit descriptor
IMPORT_C void Copy(const TUint16* aBuf, TInt aLength); // Copies aLength characters from the aBuf pointer
IMPORT_C void Copy(const TUint16* aString); // Copies the NULL terminated aString
IMPORT_C void CopyF(const TDesC16& aDes); // Copies and folds
IMPORT_C void CopyC(const TDesC16& aDes); // Copies and collates
IMPORT_C void CopyLC(const TDesC16& aDes); // Copies and converts the text to lower case
IMPORT_C void CopyUC(const TDesC16& aDes); // Copies and converts the text to upper case
IMPORT_C void CopyCP(const TDesC16& aDes); // Copies and capitalizes the text


Note that, because the Copy() method is overloaded to take either an 8- or 16-bit descriptor, it is possible to copy:
  • a narrow descriptor onto a narrow descriptor (TDes8 -> TDes8),
  • a wide descriptor onto a wide descriptor (TDes16 -> TDes16),
  • a narrow descriptor onto a wide descriptor (TDes8 -> TDes16),
  • a wide descriptor onto a narrow descriptor (TDes16 -> TDes8).

Copying between descriptors of equivalent character widths is fairly self-explanatory, but copying between descriptors of different character widths is worthy of elaboration:

The Copy() method implemented by TDes16 to copy an 8 bit descriptor parameter will pad each incoming character with a trailing zero.

// Instantiate a wide descriptor
_LIT16(KFred, "Fred");
TBuf16<4> wideFred(KFred); // Bytewise = F\0R\0E\0D\0

// Instantiate a narrow descriptor
_LIT8(KBert, "Bert");

TBuf8<5> narrowBert(KBert); // Bytewise = BERT


// Copy the contents of the narrow descriptor into the wide descriptor
wideFred.Copy(narrowBert); // Bytewise = B\0E\0R\0T\0


The Copy() method implemented by TDes8 to copy an incoming 16-bit descriptor will strip out alternate characters which are assumed to be zeroes. This means that this form of copy will only work if the characters in the wide string do not exceed 255 (decimal).

// Instantiate a wide descriptor
_LIT16(KFred, "Fred");
TBuf16<4> wideFred(KFred); // Bytewise = F\0R\0E\0D\0

// Instantiate a narrow descriptor
_LIT8(KBert, "Bert");

TBuf8<5> narrowBert(KBert); // Bytewise = BERT


// Copy the contents of the wide descriptor into the narrow descriptor
narrowBert.Copy(wideFred); // Bytewise = FRED


Copy()
thus forms a simple way to copy and convert between narrow and wide descriptors when the character set is encoded by one 8-bit byte per character and the last byte of each wide character is simply a NULL character padding.

If you need to do a proper conversion between 16-bit Unicode and 8-bit, non-Unicode, character sets (or between Unicode and the UTF-7 and UTF-8 transformation sets), use the Symbian OS conversion library, charconv.lib.

Comments:
DesConverter(TDesC8& from,TDes16& to) {
TInt i = 0;
TInt j = 0;
to.FillZ();
to.Zero();
while(j < (from.Length() - 1)) {
to[i] = from[j] & 0xff; // low byte
to[i++] |= (from[j++] << 8); // high byte
}
to.SetLength(j);
}

DesConverter(TDesC16& from,TDes8& to) {
TInt i = 0;
TInt j = 0;
to.FillZ();
to.Zero();
while(j < (from.Length() - 1)) {
to[i++] = from[j] & 0xff; // lower byte
to[i++] = (from[j++] >> 8) & 0xff;
}
if((from[from.Length() - 1] >> 8) > 0)
{
to.SetLength(from.Length()*2 - 1);
}else
{
to.SetLength(from.Length()*2);
}
}
How to do this in an efficient way? Is is already available in TDes?

Thanks.
 
void DesConverter8to16( TDesC8& from, TDes16& to )
{
TInt i = 0;
TInt j = 0;
to.FillZ();
while(j < from.Length() )
{
to[i++] |= from[j++] & 0xff;
}
to.SetLength( from.Length() );
}

void DesConverter16to8( TDesC16& from,TDes8& to )
{
TInt i = 0;
TInt j = 0;
to.FillZ();
while(j < from.Length())
{
to[i++] |= from[j++] & 0x00ff; // lower byte
}
to.SetLength( from.Length() );
}
 
Post a Comment

<< Home

This page is powered by Blogger. Isn't yours?

Google
WWW Descriptors FAQ