// UC_DES16.CPP
//
// Copyright (c) 1994-1999 Symbian Ltd.  All rights reserved.
//

#include "uc_std.h"

inline TUint16 *memCopy(TAny *aPtr,const TAny *aSrc,TInt aLength)
//
// Copy 16 bit values.
//
	{

	return((TUint16 *)Mem::Copy(aPtr,aSrc,aLength<<1));
	}

#pragma warning( disable : 4705 )	// statement has no effect
EXPORT_C TDesC16::TDesC16(const TUint16 *aString)
//
// Constructor for TPtrC16
//
	{

#if defined(__DESC_NO_BIT_FIELDS__)
	iLength=User::StringLength(aString)|(EPtrC<<KShiftDesType16);
#else
	iLength=User::StringLength(aString);
	iType=EPtrC;
#endif
	((SPtrC16 *)this)->ptr=aString;
	}

EXPORT_C TDesC16::TDesC16(const TUint16 *aBuf,TInt aLength)
//
// Constructor for TPtrC16
//
	{

	__ASSERT_ALWAYS(aLength>=0,Panic(ETDes16LengthNegative));
#if defined(__DESC_NO_BIT_FIELDS__)
	iLength=aLength|(EPtrC<<KShiftDesType16);
#else
	iLength=aLength;
	iType=EPtrC;
#endif
	((SPtrC16 *)this)->ptr=aBuf;
	}

EXPORT_C TDesC16::TDesC16(const TDesC16 &aDes)
//
// Constructor for TPtrC16
//
	{

#if defined(__DESC_NO_BIT_FIELDS__)
	iLength=aDes.Length()|(EPtrC<<KShiftDesType16);
#else
	iLength=aDes.Length();
	iType=EPtrC;
#endif
	((SPtrC16 *)this)->ptr=aDes.Ptr();
	}

EXPORT_C TDesC16::TDesC16(const TPtr16 &aTPtr)
//
// Constructor for TPtr16
//
	{

#if defined(__DESC_NO_BIT_FIELDS__)
	iLength=aTPtr.Length()|(EPtr<<KShiftDesType16);
#else
	iLength=aTPtr.Length();
	iType=EPtr;
#endif
	((SPtr16 *)this)->maxLength=aTPtr.MaxLength();
	((SPtr16 *)this)->ptr=(TUint16*)aTPtr.Ptr();
	}

EXPORT_C TDesC16::TDesC16(TBufCBase16 *aLcb)
//
// Constructor for TBufC16.
//
	{

#if defined(__DESC_NO_BIT_FIELDS__)
	iLength=(TUint)aLcb|(EBufC<<KShiftDesType16);
#else
	iLength=(TUint)aLcb;
	iType=EBufC;
#endif
	}

EXPORT_C TDesC16::TDesC16(TUint16 *aBuf,TInt aLength,TInt aMaxLength)
//
// Constructor for TPtr16.
//
	{

	__ASSERT_ALWAYS(aMaxLength>=0,Panic(ETDes16MaxLengthNegative));
	__ASSERT_ALWAYS(aLength>=0 && aLength<=aMaxLength,Panic(ETDes16LengthOutOfRange));
#if defined(__DESC_NO_BIT_FIELDS__)
	iLength=aLength|(EPtr<<KShiftDesType16);
#else
	iLength=aLength;
	iType=EPtr;
#endif
	((SPtr16 *)this)->maxLength=aMaxLength;
	((SPtr16 *)this)->ptr=aBuf;
	}

EXPORT_C TDesC16::TDesC16(TBufCBase16 &aLcb,TInt aMaxLength)
//
// Constructor for TBufCBase16.
//
	{

	Set(aLcb,aMaxLength);
	}

EXPORT_C TDesC16::TDesC16(TInt aLength,TInt aMaxLength)
//
// Constructor for TBuf16.
//
	{

	__ASSERT_ALWAYS(aMaxLength>=0,Panic(ETDes16MaxLengthNegative));
	__ASSERT_ALWAYS(aLength>=0 && aLength<=aMaxLength,Panic(ETDes16LengthOutOfRange));
#if defined(__DESC_NO_BIT_FIELDS__)
	iLength=aLength|(EBuf<<KShiftDesType16);
#else
	iLength=aLength;
	iType=EBuf;
#endif
	((SBuf16 *)this)->maxLength=aMaxLength;
	}
#pragma warning( default : 4705 )

EXPORT_C TInt TDesC16::Type() const
//
// Return the descriptor type
//
	{

#if defined(__DESC_NO_BIT_FIELDS__)
	return(iLength>>KShiftDesType16);
#else
	return(iType);
#endif
	}

EXPORT_C void TDesC16::DoSetLength(TInt aLength)
//
// Set the length of the descriptor.
//
	{

#if defined(__DESC_NO_BIT_FIELDS__)
	iLength=(iLength&(~KMaskDesLength16))|aLength;
#else
	iLength=aLength;
#endif
	if (Type()==EBufCPtr)
		((SBufCPtr16 *)this)->ptr->length=aLength; // Relies on iType==0 for an TBufC
	}

EXPORT_C void TDesC16::DoSetType(TInt aType)
//
// Set the type of the descriptor
//
	{

#if defined(__DESC_NO_BIT_FIELDS__)
	iLength=(iLength&KMaskDesLength16)|(aType<<KShiftDesType16);
#else
	iType=aType;
#endif
	}

EXPORT_C void TDesC16::Set(TBufCBase16 &aLcb,TInt aMaxLength)
//
// Set value for a TBufCBase16.
//
	{

	TInt len=aLcb.Length();
	__ASSERT_ALWAYS(len<=aMaxLength,Panic(ETDes16LengthOutOfRange));
#if defined(__DESC_NO_BIT_FIELDS__)
	iLength=len|(EBufCPtr<<KShiftDesType16);
#else
	iLength=len;
	iType=EBufCPtr;
#endif
	((SBufCPtr16 *)this)->maxLength=aMaxLength;
	((SBufCPtr16 *)this)->ptr=(SBufC16 *)(&aLcb);
	}

EXPORT_C void TDesC16::SetHBufC()
//
// Set up the members of TDesC16 for a HBufC16.
//
	{

#if defined(__DESC_NO_BIT_FIELDS__)
	iLength=(EBufC<<KShiftDesType16);
#else
	iLength=0;
	iType=EBufC;
#endif
	}

EXPORT_C const TUint16 *TDesC16::Ptr() const
//
// Return a pointer to the buffer.
//
	{

	switch (Type())
		{
	case EBufC:
		return(&((SBufC16 *)this)->buf[0]);
	case EPtrC:
		return(((SPtrC16 *)this)->ptr);
	case EPtr:
		return(((SPtr16 *)this)->ptr);
	case EBuf:
		return(&((SBuf16 *)this)->buf[0]);
	case EBufCPtr:
		return(&((SBufCPtr16 *)this)->ptr->buf[0]);
		}
	Panic(ETDes16BadDescriptorType);
	return(NULL);
	}

EXPORT_C const TUint16 &TDesC16::AtC(TInt anIndex) const
//
// Return a reference to the character in the buffer.
//
	{

	__ASSERT_ALWAYS(anIndex>=0 && anIndex<Length(),Panic(ETDes16IndexOutOfRange));
	return(Ptr()[anIndex]);
	}

EXPORT_C TInt TDesC16::Compare(const TDesC16 &aDes) const
//
// Compare a descriptor to this descriptor.
//
	{

	return(Mem::Compare(Ptr(),Length(),aDes.Ptr(),aDes.Length()));
	}

EXPORT_C TInt TDesC16::CompareF(const TDesC16 &aDes) const
//
// Compare a descriptor to this descriptor folded.
//
	{

	return(Mem::CompareF(Ptr(),Length(),aDes.Ptr(),aDes.Length()));
	}

EXPORT_C TInt TDesC16::CompareC(const TDesC16 &aDes) const
//
// Compare a descriptor to this descriptor collated.
//
	{

	return(Mem::CompareC(Ptr(),Length(),aDes.Ptr(),aDes.Length()));
	}

#ifdef _UNICODE
// Compare two descriptors using the supplied collation rules.
EXPORT_C TInt TDesC16::CompareC(const TDesC16& aDes,const TInt16* aCollationRuleSet) const
	{
	return Mem::CompareC(Ptr(),Length(),aDes.Ptr(),aDes.Length(),aCollationRuleSet);
	}
#endif

#ifdef _UNICODE
/*
Compare two descriptors using collation rules specified by unique identifier.
Place the identifier of the rules actually used in aActualCollationRulesId.
*/
EXPORT_C TInt TDesC16::CompareC(const TDesC16& aDes,TUint32 aDesiredCollationRulesId,TUint32& aActualCollationRulesId) const
	{
	return Mem::CompareC(Ptr(),Length(),aDes.Ptr(),aDes.Length(),aDesiredCollationRulesId,aActualCollationRulesId);
	}
#endif

EXPORT_C TInt TDesC16::Find(const TUint16 *pS,TInt aLenS) const
//
// Find the location of pS in pB.
//
	{

	if (!aLenS)
		return(0);
	__ASSERT_ALWAYS(aLenS>0,Panic(ETDes8LengthNegative));
	const TUint16 *pB=Ptr();
	TInt aLenB=Length();
	const TUint16 *pC=pB-1;			// using pre-increment addressing
	TInt i=aLenB-aLenS;
	if (i>=0)
		{
		const TUint16* pEndS=pS+aLenS-1;		// using pre-increment addressing
		const TUint16 *pEndB=pB+i;			// using pre-increment addressing
		TUint s=*pS;
		for (;;)
			{
			do
				{
				if (pC==pEndB)
					return KErrNotFound;
				} while (*++pC!=s);
			const TUint16 *p1=pC;
			const TUint16 *p2=pS;
			do
				{
				if (p2==pEndS)
					return (pC-pB);
				} while (*++p1==*++p2);
			}
		}
	return(KErrNotFound);
	}

EXPORT_C TInt TDesC16::Find(const TDesC16 &aDes) const
//
// Find a descriptor to this descriptor.
//
	{

	return(Find(aDes.Ptr(),aDes.Length()));
	}

EXPORT_C TInt TDesC16::FindF(const TUint16 *pS,TInt aLenS) const
//
// Find the location of pS in pB folded.
//
	{
	
	return(Exec::Find16(*this,pS,aLenS,EMatchFolded));
	}

EXPORT_C TInt TDesC16::FindF(const TDesC16 &aDes) const
//
// Find a descriptor to this descriptor folded.
//
	{

	return(FindF(aDes.Ptr(),aDes.Length()));
	}

EXPORT_C TInt TDesC16::FindC(const TUint16 *pS,TInt aLenS) const
//
// Find the location of pS in pB collated.
//
	{

	return(Exec::Find16(*this,pS,aLenS,EMatchCollated));
	}

EXPORT_C TInt TDesC16::FindC(const TDesC16 &aDes) const
//
// Find a descriptor to this descriptor collated.
//
	{

	return(FindC(aDes.Ptr(),aDes.Length()));
	}

EXPORT_C TInt TDesC16::Locate(TChar aChar) const
//
// Locate character aChar in the descriptor.
//
	{

	const TUint16 *pBuf=Ptr();
	const TUint16 *pB=pBuf-1;
	const TUint16 *pE=pB+Length();
	do
		{
		if (pB==pE)
			return KErrNotFound;
		} while (*++pB!=aChar);
	return pB-pBuf;
	}

EXPORT_C TInt TDesC16::LocateF(TChar aChar) const
//
// Locate character aChar in the descriptor folded.
//
	{

	return(Exec::LocateF16(*this,aChar));
	}

EXPORT_C TInt TDesC16::LocateReverse(TChar aChar) const
//
// Locate character aChar in the descriptor in reverse.
//
	{

	TInt len=Length();
	if (len==0)
		return(KErrNotFound);
	const TUint16 *pB=Ptr();
	const TUint16 *pE=pB+len-1;
	while (pE>=pB)
		{
		if (*pE==aChar)
			break;
		pE--;
		}
	return(pE<pB ? KErrNotFound : pE-pB);
	}

EXPORT_C TInt TDesC16::LocateReverseF(TChar aChar) const
//
// Locate character aChar in the descriptor in reverse folded.
//
	{

	TInt len=Length();
	if (len==0)
		return(KErrNotFound);
	const TUint16 *pB=Ptr();
	const TUint16 *pE=pB+len-1;
	aChar.Fold();
	while (pE>=pB)
		{
		TCharF c(*pE);
		if (c==aChar)
			break;
		pE--;
		}
	return(pE<pB ? KErrNotFound : pE-pB);
	}

EXPORT_C HBufC16 *TDesC16::Alloc() const
//
// Allocate a HBufC and then copy this descriptor into it.
//
	{

	HBufC16 *pH=HBufC16::New(Length());
	if (pH)
		*pH=(*this);
	return(pH);
	}

EXPORT_C HBufC16 *TDesC16::AllocL() const
//
// Allocate a HBufC and then copy this descriptor into it.
//
	{

	HBufC16 *pH=HBufC16::NewL(Length());
	*pH=(*this);
	return(pH);
	}

EXPORT_C HBufC16 *TDesC16::AllocLC() const
//
// Allocate a HBufC and then copy this descriptor into it.
//
	{

	HBufC16 *pH=HBufC16::NewLC(Length());
	*pH=(*this);
	return(pH);
	}

EXPORT_C TPtrC16 TDesC16::Left(TInt aLength) const
//
// Extract the left portion of the descriptor.
//
	{

	__ASSERT_ALWAYS(aLength>=0 && aLength<=Length(),Panic(ETDes16PosOutOfRange));
	return(TPtrC16(Ptr(),aLength));
	}

EXPORT_C TPtrC16 TDesC16::Right(TInt aLength) const
//
// Extract the right portion of the descriptor.
//
	{

	TInt len=Length();
	__ASSERT_ALWAYS(aLength>=0 && aLength<=len,Panic(ETDes16PosOutOfRange));
    return(TPtrC16(Ptr()+len-aLength,aLength));
	}

EXPORT_C TPtrC16 TDesC16::Mid(TInt aPos) const
//
// Extract the middle portion of the descriptor.
//
	{

	TInt len=Length();
	__ASSERT_ALWAYS(aPos>=0 && aPos<=len,Panic(ETDes16PosOutOfRange));
    return(TPtrC16(Ptr()+aPos,len-aPos));
	}

EXPORT_C TPtrC16 TDesC16::Mid(TInt aPos,TInt aLength) const
//
// Extract the middle portion of the descriptor.
//
	{

	__ASSERT_ALWAYS(aPos>=0 && (aPos+aLength)<=Length(),Panic(ETDes16PosOutOfRange));
    return(TPtrC16(Ptr()+aPos,aLength));
	}

EXPORT_C TBufCBase16::TBufCBase16()
//
// Constructor
//
	: TDesC16((TBufCBase16 *)NULL)
	{}

EXPORT_C TBufCBase16::TBufCBase16(const TUint16 *aString,TInt aMaxLength)
//
// Constructor
//
	: TDesC16((TBufCBase16 *)User::StringLength(aString))
	{

	TInt len=Length();
	__ASSERT_ALWAYS(len<=aMaxLength,Panic(ETDes16LengthOutOfRange));
	memCopy(WPtr(),aString,len);
	}

EXPORT_C TBufCBase16::TBufCBase16(const TDesC16 &aDes,TInt aMaxLength)
//
// Constructor
//
	: TDesC16((TBufCBase16 *)aDes.Length())
	{

	TInt len=Length();
	__ASSERT_ALWAYS(len<=aMaxLength,Panic(ETDes16LengthOutOfRange));
	memCopy(WPtr(),aDes.Ptr(),len);
	}

EXPORT_C void TBufCBase16::Copy(const TUint16 *aString,TInt aMaxLength)
//
// Copy from a string.
//
	{

	TInt len=User::StringLength(aString);
	__ASSERT_ALWAYS(len<=aMaxLength,Panic(ETDes16Overflow));
	memCopy(WPtr(),aString,len);
	DoSetLength(len);
	}

EXPORT_C void TBufCBase16::Copy(const TDesC16 &aDes,TInt aMaxLength)
//
// Copy from a descriptor.
//
	{

	TInt len=aDes.Length();
	__ASSERT_ALWAYS(len<=aMaxLength,Panic(ETDes16Overflow));
	memCopy(WPtr(),aDes.Ptr(),len);
	DoSetLength(len);
	}

EXPORT_C void TBufCBase16::Copy(const TBufCBase16 &aLcb,TInt aMaxLength)
//
// Copy from another TBufC16.
//
	{

	TInt len=aLcb.Length();
	__ASSERT_ALWAYS(len<=aMaxLength,Panic(ETDes16Overflow));
	memCopy(WPtr(),aLcb.Ptr(),len);
	DoSetLength(len);
	}

EXPORT_C TPtr16 TBufCBase16::DoDes(TInt aMaxLength)
//
// Convert a TBufC16 to TPtr16.
//
	{

	return(TPtr16(*this,aMaxLength));
	}

EXPORT_C HBufC16 *HBufC16::New(TInt aMaxLength)
//
// Create a new HBufC16 with maximum size aMaxLength.
//
	{

	__ASSERT_ALWAYS(aMaxLength>=0,Panic(ETDes16MaxLengthNegative));
	HBufC16 *pH=(HBufC16 *)User::Alloc((aMaxLength*sizeof(TUint16))+sizeof(TDesC16));
	if (pH)
		pH->SetHBufC();
	return(pH);
	}

EXPORT_C HBufC16 *HBufC16::NewL(TInt aMaxLength)
//
// Create a new HBufC16 with maximum size aMaxLength.
//
	{

	__ASSERT_ALWAYS(aMaxLength>=0,Panic(ETDes16MaxLengthNegative));
	HBufC16 *pH=(HBufC16 *)User::AllocL((aMaxLength*sizeof(TUint16))+sizeof(TDesC16));
	pH->SetHBufC();
	return(pH);
	}

EXPORT_C HBufC16 *HBufC16::NewLC(TInt aMaxLength)
//
// Create a new HBufC16 with maximum size aMaxLength.
//
	{

	__ASSERT_ALWAYS(aMaxLength>=0,Panic(ETDes16MaxLengthNegative));
	HBufC16 *pH=(HBufC16 *)User::AllocLC((aMaxLength*sizeof(TUint16))+sizeof(TDesC16));
	pH->SetHBufC();
	return(pH);
	}

EXPORT_C HBufC16 *HBufC16::NewMax(TInt aMaxLength)
//
// Create a new HBufC16 with maximum size aMaxLength.
//
	{

	HBufC16 *pH=New(aMaxLength);
	if (pH)
		pH->Des().SetLength(aMaxLength);
	return(pH);
	}

EXPORT_C HBufC16 *HBufC16::NewMaxL(TInt aMaxLength)
//
// Create a new HBufC16 with maximum size aMaxLength.
//
	{

	HBufC16 *pH=NewL(aMaxLength);
	pH->Des().SetLength(aMaxLength);
	return(pH);
	}

EXPORT_C HBufC16 *HBufC16::NewMaxLC(TInt aMaxLength)
//
// Create a new HBufC16 with maximum size aMaxLength.
//
	{

	HBufC16 *pH=NewLC(aMaxLength);
	pH->Des().SetLength(aMaxLength);
	return(pH);
	}

EXPORT_C HBufC16 &HBufC16::operator=(const TUint16 *aString)
//
// Assignment
//
	{

	Copy(aString,(User::AllocLen(this)-sizeof(TDesC16))/sizeof(TUint16));
	return(*this);
	}

EXPORT_C HBufC16 &HBufC16::operator=(const TDesC16 &aDes)
//
// Assignment
//
	{

	Copy(aDes,(User::AllocLen(this)-sizeof(TDesC16))/sizeof(TUint16));
	return(*this);
	}

EXPORT_C HBufC16 &HBufC16::operator=(const HBufC16 &aLcb)
//
// Assignment
//
	{

	Copy(aLcb,(User::AllocLen(this)-sizeof(TDesC16))/sizeof(TUint16));
	return(*this);
	}

EXPORT_C HBufC16 *HBufC16::ReAlloc(TInt aMaxLength)
//
// Re-Allocate.
//
	{

	__ASSERT_ALWAYS(aMaxLength>=0,Panic(ETDes16MaxLengthNegative));
	__ASSERT_ALWAYS(Length()<=aMaxLength,Panic(ETDes16ReAllocTooSmall));
	return((HBufC16 *)User::ReAlloc(this,(aMaxLength*sizeof(TUint16))+sizeof(TDesC16)));
	}

EXPORT_C HBufC16 *HBufC16::ReAllocL(TInt aMaxLength)
//
// Re-Allocate.
//
	{

	__ASSERT_ALWAYS(aMaxLength>=0,Panic(ETDes16MaxLengthNegative));
	__ASSERT_ALWAYS(Length()<=aMaxLength,Panic(ETDes16ReAllocTooSmall));
	return((HBufC16 *)User::ReAllocL(this,(aMaxLength*sizeof(TUint16))+sizeof(TDesC16)));
	}

EXPORT_C TPtr16 HBufC16::Des()
//
// Create a writeable descriptor.
//
	{

	return(TPtr16(*this,(User::AllocLen(this)-sizeof(TDesC16))/sizeof(TUint16)));
	}

EXPORT_C TDes16 &TDes16::operator=(const TUint16 *aString)
//
// Assign a string
//
    {

    Copy(aString);
    return(*this);
    }

EXPORT_C TDes16 &TDes16::operator=(const TDesC16 &aDes)
//
// Assign a constant descriptor.
//
    {

    Copy(aDes);
    return(*this);
    }

EXPORT_C TDes16 &TDes16::operator=(const TDes16 &aDes)
//
// Assign a descriptor.
//
    {

    Copy(aDes);
    return(*this);
    }

EXPORT_C void TDes16::SetLength(TInt aLength)
//
// Set the length of the descriptor, checking the length is O.K.
//
	{

	__ASSERT_ALWAYS(aLength>=0 && aLength<=MaxLength(),Panic(ETDes16Overflow));
	DoSetLength(aLength);
  	}

EXPORT_C void TDes16::SetMax()
//
// Set the length to MaxLength().
//
	{

	SetLength(iMaxLength);
	}

EXPORT_C void TDes16::Copy(const TUint16 *aString)
//
// Copy a string to this descriptor.
//
	{

	TInt len=User::StringLength(aString);
	SetLength(len);
	TUint16 *pT=WPtr();
	while (len--)
		*pT++=(*aString++);
	}

EXPORT_C void TDes16::Copy(const TUint16 *aBuf,TInt aLength)
//
// Copy the aLength characters to the descriptor.
//
	{

	SetLength(aLength);
	TUint16 *pT=WPtr();
	while (aLength--)
		*pT++=(*aBuf++);
	}

EXPORT_C void TDes16::Copy(const TDesC16 &aDes)
//
// Copy a descriptor to this descriptor.
//
	{

	TInt len=aDes.Length();
	SetLength(len);
	const TUint16 *pS=aDes.Ptr();
	const TUint16 *pE=pS+len;
	TUint16 *pT=WPtr();
	while (pS<pE)
		*pT++=(*pS++);
	}

EXPORT_C void TDes16::Copy(const TDesC8 &aDes)
//
// Copy a descriptor 16 to this descriptor.
//
	{

	TInt len=aDes.Length();
	SetLength(len);
	const TUint8 *pS=aDes.Ptr();
	const TUint8 *pE=pS+len;
	TUint16 *pT=WPtr();
	while (pS<pE)
		*pT++=(*pS++);
	}

EXPORT_C void TDes16::Append(TChar aChar)
//
// Add a character at the end of the string.
//
	{

	TInt len=Length();
	TUint16 *pB=WPtr()+len;
	SetLength(len+1);
	*pB++=(TUint16)aChar;
	}

EXPORT_C void TDes16::Append(const TUint16 *aBuf,TInt aLength)
//
// Append aLength from aBuf characters to the descriptor.
//
	{

	__ASSERT_ALWAYS(aLength>=0,Panic(ETDes16LengthNegative));
	TInt len=Length();
	TUint16 *pT=WPtr()+len;
	SetLength(len+aLength);
	while (aLength--)
		*pT++=(*aBuf++);
	}

EXPORT_C void TDes16::Append(const TDesC16 &aDes)
//
// Append a descriptor to this descriptor.
//
	{

	TInt len=Length();
	TInt n=aDes.Length();
	const TUint16 *pS=aDes.Ptr();
	const TUint16 *pE=pS+n;
	TUint16 *pT=WPtr()+len;
	SetLength(len+n);
	while (pS<pE)
		*pT++=(*pS++);
	}

EXPORT_C void TDes16::Swap(TDes16 &aDes)
//
// Swap the contents of the two descriptors.
//
	{

	TInt l=Length();
	TInt r=aDes.Length();
	aDes.SetLength(l);
	SetLength(r);
	TInt s=Min(l,r);
	l-=s;
	r-=s;
	TUint16 *pL=WPtr();
	TUint16 *pR=aDes.WPtr();
	while (s--)
		{
		TChar a=(*pL);
		*pL++=(*pR);
		*pR++=(TUint16)a;
		}
	while (l--)
		*pR++=(*pL++);
	while (r--)
		*pL++=(*pR++);
	}

EXPORT_C void TDes16::Fill(TChar aChar)
//
// Fill the descriptor with aChar.
//
	{

	TUint16 *pB=WPtr();
	TUint16 *pE=pB+Length();
	while (pB<pE)
		*pB++=(TUint16)aChar;
	}

EXPORT_C void TDes16::Fill(TChar aChar,TInt aLength)
//
// Fill the descriptor with aChar, for length aLength, checking for length.
//
	{

	SetLength(aLength);
	TUint16 *pB=WPtr();
	TUint16 *pE=pB+aLength;
	while (pB<pE)
		*pB++=(TUint16)aChar;
	}

EXPORT_C void TDes16::AppendFill(TChar aChar,TInt aLength)
//
// Append fill the descriptor with aChar, for length aLength, checking for length.
//
	{

	TInt len=Length();
	TUint16 *pB=WPtr()+len;
	SetLength(len+aLength);
	TUint16 *pE=pB+aLength;
	while (pB<pE)
		*pB++=(TUint16)aChar;
	}

EXPORT_C void TDes16::ZeroTerminate()
//
// Zero terminate at Length().
//
	{

	TInt len=Length();
	__ASSERT_ALWAYS(len<MaxLength(),Panic(ETDes16Overflow));
	WPtr()[len]=0;
	}

EXPORT_C void TDes16::Zero()
//
// Zero the buffer.
//
	{

	SetLength(0);
	}

EXPORT_C const TUint16 *TDes16::PtrZ()
//
// Return a pointer to a 0 terminated string.
//
	{

	ZeroTerminate();
	return(Ptr());
	}

EXPORT_C void TDes16::FillZ()
//
// Fill the descriptor with 0.
//
	{

    Mem::FillZ(WPtr(),Length()*2);
	}

EXPORT_C void TDes16::FillZ(TInt aLength)
//
// Fill the descriptor with 0, for length aLength, checking for length.
//
	{

	SetLength(aLength);
	FillZ();
	}

EXPORT_C void TDes16::Fold()
//
// Convert the descriptor to folded.
//
	{

	TUint16 *pB=WPtr();
	TInt len=Length();
	while (len--)
		{
		TCharF c(*pB);
		*pB++=(TUint16)c;
		}
	}

EXPORT_C void TDes16::Collate()
//
// Convert the descriptor to collated.
//
	{

	TUint16 *pB=WPtr();
	TInt len=Length();
	while (len--)
		{
		TChar c=User::Collate(*pB);
		*pB++=(TUint16)c;
		}
	}

EXPORT_C void TDes16::LowerCase()
//
// Convert the descriptor to lower case.
//
	{

	TUint16 *pB=WPtr();
	TInt len=Length();
	while (len--)
		{
		TCharLC c(*pB);
		*pB++=(TUint16)c;
		}
	}

EXPORT_C void TDes16::UpperCase()
//
// Convert the descriptor to upper case.
//
	{

	TUint16 *pB=WPtr();
	TInt len=Length();
	while (len--)
		{
		TCharUC c(*pB);
		*pB++=(TUint16)c;
		}
	}

EXPORT_C void TDes16::Capitalize()
//
// Convert the descriptor to capitalised.
//
	{

	TUint16 *pB=WPtr();
	TInt len=Length();
	if (len--)
		{
		TChar c(*pB);
#ifdef _UNICODE
		c.TitleCase();
#else
		c.UpperCase();
#endif
		*pB++=(TUint16)c;
		while (len--)
			{
			TCharLC c=(*pB);
			c.LowerCase();
			*pB++=(TUint16)c;
			}
		}
	}

EXPORT_C void TDes16::CopyF(const TDesC16 &aDes)
//
// Copy a descriptor to this descriptor folded.
//
	{

	TInt len=aDes.Length();
	SetLength(len);
	const TUint16 *pS=aDes.Ptr();
	TUint16 *pT=WPtr();
	while (len--)
		{
		TCharF c(*pS++);
		*pT++=(TUint16)c;
		}
	}

EXPORT_C void TDes16::CopyC(const TDesC16 &aDes)
//
// Copy a descriptor to this descriptor collated.
//
	{

	TInt len=aDes.Length();
	SetLength(len);
	const TUint16 *pS=aDes.Ptr();
	TUint16 *pT=WPtr();
	while (len--)
		{
		TChar c=User::Collate(*pS++);
		*pT++=(TUint16)c;
		}
	}

EXPORT_C void TDes16::CopyLC(const TDesC16 &aDes)
//
// Copy a descriptor to this descriptor lower case.
//
	{

	TInt len=aDes.Length();
	SetLength(len);
	const TUint16 *pS=aDes.Ptr();
	TUint16 *pT=WPtr();
	while (len--)
		{
		TCharLC c(*pS++);
		*pT++=(TUint16)c;
		}
	}

EXPORT_C void TDes16::CopyUC(const TDesC16 &aDes)
//
// Copy a descriptor to this descriptor upper case.
//
	{

	TInt len=aDes.Length();
	SetLength(len);
	const TUint16 *pS=aDes.Ptr();
	TUint16 *pT=WPtr();
	while (len--)
		{
		TCharUC c(*pS++);
		*pT++=(TUint16)c;
		}
	}

EXPORT_C void TDes16::CopyCP(const TDesC16 &aDes)
//
// Copy a descriptor to this descriptor capitalised.
//
	{

	TInt len=aDes.Length();
	SetLength(len);
	const TUint16 *pS=aDes.Ptr();
	TUint16 *pT=WPtr();
	if (len--)
		{
		TChar c(*pS++);
#ifdef _UNICODE
		c.TitleCase();
#else
		c.UpperCase();
#endif
		*pT++=(TUint16)c;
		while (len--)
			{
			TCharLC c=(*pS++);
			*pT++=(TUint16)c;
			}
		}
	}

EXPORT_C void TDes16::Repeat(const TUint16 *aBuf,TInt aLength)
//
// Repeat a aBuf as many times as possible in the descriptor.
//
	{

	__ASSERT_ALWAYS(aLength>=0,Panic(ETDes16LengthNegative));
	TUint16 *pB=WPtr();
	TInt len=Length();
	if (len && aLength)
		{
		while (len)
			{
			TInt i=Min(len,aLength);
			pB=memCopy(pB,aBuf,i);
			len-=i;
			}
		}
	}

EXPORT_C void TDes16::Repeat(const TDesC16 &aDes)
//
// Repeat a aDes as many times as possible in the descriptor.
//
	{

	Repeat(aDes.Ptr(),aDes.Length());
	}

EXPORT_C void TDes16::Trim()
//
// Trim spaces from both ends of a descriptor.
//
	{

	TrimLeft();
	TrimRight();
	}

EXPORT_C void TDes16::TrimAll()
//
// Trim spaces from both ends of a descriptor and convert multiple spaces
// to singles spaces within the descriptor.
//
	{

	TrimLeft();
	TrimRight();
	TUint16 *pBuf=(TUint16 *)Ptr();
	TUint16 *pSrc=pBuf;
	TUint16 *pDst=pBuf;
	TInt len=Length();
	TInt spaces=0;
	while (len--)
		{
		TChar c=*pSrc;
		if (c.IsSpace())
			{
			if (spaces++==0)
				{
				if (pDst!=pSrc)
					*pDst=*pSrc;
				pDst++;
				}
			}
		else
			{
			spaces=0;
			if (pDst!=pSrc)
				*pDst=*pSrc;
			pDst++;
			}
		pSrc++;
		}
	Delete(pDst-pBuf, pSrc-pDst);
	}

EXPORT_C void TDes16::TrimLeft()
//
// Trim spaces from the left end of the descriptor.
//
	{

	const TUint16 *pBuf=Ptr();
	const TUint16 *pB=pBuf;
	TInt len=Length();
	while (len--)
		{
		TChar c=(*pB);
		if (!c.IsSpace())
			break;
		pB++;
		}
	Delete(0,pB-pBuf);
	}

EXPORT_C void TDes16::TrimRight()
//
// Trim spaces from the rigth end of the descriptor.
//
	{

	TInt len=Length();
	if (len==0)
		return;
	const TUint16 *pB=Ptr()+len-1;
	TInt s=len;
	while (s)
		{
		TChar c=(*pB--);
		if (!c.IsSpace())
			break;
		s--;
		}
	Delete(s,len-s);
	}

EXPORT_C void TDes16::Insert(TInt aPos,const TDesC16 &aDes)
//
// Insert a descriptor into this descriptor.
//
	{

	TInt len=Length();
	__ASSERT_ALWAYS(aPos>=0 && aPos<=len,Panic(ETDes16PosOutOfRange));
	TInt s=aDes.Length();
	__ASSERT_ALWAYS((len+s)<=MaxLength(),Panic(ETDes16Overflow));
	TUint16 *pB=WPtr();
	memCopy(pB+aPos+s,pB+aPos,len-aPos);
	memCopy(pB+aPos,aDes.Ptr(),aDes.Length());
	SetLength(len+s);
	}

EXPORT_C void TDes16::Delete(TInt aPos,TInt aLength)
//
// Delete a portion of the descriptor.
//
	{

	TInt len=Length();
	__ASSERT_ALWAYS(aPos>=0 && aPos<=len,Panic(ETDes16PosOutOfRange));
	TInt d=Min(len-aPos,aLength);
	TUint16 *pB=WPtr();
	memCopy(pB+aPos,pB+aPos+d,len-aPos-d);
	SetLength(len-d);
	}

EXPORT_C void TDes16::Replace(TInt aPos,TInt aLength,const TDesC16 &aDes)
//
// Replace part of this descriptor.
//
	{

	TInt len=Length();
	__ASSERT_ALWAYS(aPos>=0 && aPos<=len,Panic(ETDes16PosOutOfRange));
	__ASSERT_ALWAYS(aLength>=0 && aPos+aLength<=len,Panic(ETDes16LengthOutOfRange));
	TInt s=aDes.Length();
	TInt maxlen=MaxLength();
	__ASSERT_ALWAYS(s>=0 && s<=maxlen,Panic(ETDes16RemoteLengthOutOfRange));
	__ASSERT_ALWAYS((len+s-aLength)<=maxlen,Panic(ETDes16Overflow));
	TUint16 *pB=WPtr();
	memCopy(pB+aPos+s,pB+aPos+aLength,len-aPos-aLength);
	memCopy(pB+aPos,aDes.Ptr(),s);
	SetLength(len+s-aLength);
	}

EXPORT_C void TDes16::Justify(const TDesC16 &aDes,TInt aWidth,TAlign anAlignment,TChar aFill)
//
// Justify a descriptor in the descriptor.
//
	{

    Zero();
    AppendJustify(aDes.Ptr(),aDes.Length(),aWidth,anAlignment,aFill);
    }

EXPORT_C void TDes16::AppendJustify(const TDesC16 &aDes,TInt aWidth,TAlign anAlignment,TChar aFill)
//
// Append a justified descriptor to the descriptor.
//
	{

    AppendJustify(aDes.Ptr(),aDes.Length(),aWidth,anAlignment,aFill);
    } 

EXPORT_C void TDes16::AppendJustify(const TDesC16 &aDes,TInt aLength,TInt aWidth,TAlign anAlignment,TChar aFill)
//
// Append a justified buffer to the descriptor.
//
	{

    AppendJustify(aDes.Ptr(),aLength,aWidth,anAlignment,aFill);
    } 

EXPORT_C void TDes16::AppendJustify(const TUint16 *aString,TInt aWidth,TAlign anAlignment,TChar aFill)
//
// Append a justified string to the descriptor.
//
	{

    AppendJustify(aString,User::StringLength(aString),aWidth,anAlignment,aFill);
    } 

EXPORT_C void TDes16::AppendJustify(const TUint16 *aString,TInt aLength,TInt aWidth,TAlign anAlignment,TChar aFill)
//
// Justify a buffer into the descriptor, in a field aWidth wide.
//
	{

	__ASSERT_ALWAYS(aLength>=0,Panic(ETDes16LengthNegative));
	if (aWidth==KDefaultJustifyWidth)
		aWidth=aLength;
	if (aLength>aWidth)
		aLength=aWidth;
	TInt offset=Length();
	AppendFill(aFill,aWidth);
	TInt r=aWidth-aLength;
	if (anAlignment==ECenter)
		r>>=1;
	else if (anAlignment==ELeft)
		r=0;
	memCopy(WPtr()+offset+r,aString,aLength);
	}

EXPORT_C void TDes16::Num(TInt aVal)
//
// Convert a signed int to the descriptor.
//
	{

    Zero();
    AppendNum(aVal);
    }

EXPORT_C void TDes16::Num(TUint aVal,TRadix aRadix)
//
// Convert an unsigned int to the descriptor.
//
	{

    Zero();
    AppendNum(aVal,aRadix);
    }

EXPORT_C void TDes16::NumUC(TUint aVal,TRadix aRadix)
//
// Convert an unsigned int to the descriptor converting to upper case.
//
	{

    Zero();
    AppendNumUC(aVal,aRadix);
    }

EXPORT_C void TDes16::NumFixedWidth(TUint aVal,TRadix aRadix,TInt aWidth)
//
// Convert an unsigned int to the descriptor.
// Store aWidth characters, with leading zeros if necessary.
//
	{

    Zero();
    AppendNumFixedWidth(aVal,aRadix,aWidth);
    }

EXPORT_C void TDes16::NumFixedWidthUC(TUint aVal,TRadix aRadix,TInt aWidth)
//
// Convert an unsigned int to the descriptor converting to upper case.
// Store aWidth characters, with leading zeros if necessary.
//
	{

    Zero();
    AppendNumFixedWidthUC(aVal,aRadix,aWidth);
    }

EXPORT_C void TDes16::Num(TInt64 aVal)
//
// Convert an unsigned int to the descriptor.
//
	{

	Zero();
	AppendNum(aVal);
	}

EXPORT_C void TDes16::Num(TInt64 aVal,TRadix aRadix)
//
// Convert an unsigned int to the descriptor.
//
	{

	Zero();
	AppendNum(aVal,aRadix);
	}

EXPORT_C void TDes16::NumUC(TInt64 aVal,TRadix aRadix)
//
// Convert an unsigned int to the descriptor.
//
	{

	Zero();
	AppendNumUC(aVal,aRadix);
	}

EXPORT_C void TDes16::AppendNum(TInt aVal)
//
// Convert a signed integer into the descriptor.
//
	{

	TUint v=aVal;
	if (aVal<0)
		{
		Append('-');
		v=(-aVal);
		}
	AppendNum(v,EDecimal);
	}

EXPORT_C void TDes16::AppendNum(TUint aVal,TRadix aRadix)
//
// Convert an unsigned integer into the descriptor.
//
	{

	if (aVal>=(TUint)aRadix)
		{
		AppendNum(aVal/aRadix,aRadix);
		aVal=(aVal%aRadix);
		}
	Append(aVal+(aVal<10 ? '0' : ('a'-10)));
	}

EXPORT_C void TDes16::AppendNumUC(TUint aVal,TRadix aRadix)
//
// Convert an unsigned integer into the descriptor in upper case.
//
	{

	if (aVal>=(TUint)aRadix)
		{
		AppendNumUC(aVal/aRadix,aRadix);
		aVal=(aVal%aRadix);
		}
	Append(aVal+(aVal<10 ? '0' : ('A'-10)));
	}

EXPORT_C void TDes16::AppendNumFixedWidth(TUint aVal,TRadix aRadix,TInt aWidth)
//
// Convert an unsigned integer into the descriptor.
// Store aWidth characters, with leading zeros if necessary.
//
	{

	TBuf16<32> buf;
	buf.Num(aVal,aRadix);
	if (buf.Length()>=aWidth)
		Append(buf.Left(aWidth));
	else
		{
		TInt i=aWidth-buf.Length();
		while(i--)
			Append(TChar('0'));
		Append(buf);
		}
	}

EXPORT_C void TDes16::AppendNumFixedWidthUC(TUint aVal,TRadix aRadix,TInt aWidth)
//
// Convert an unsigned integer into the descriptor in upper case.
// Store aWidth characters, with leading zeros if necessary.
//
	{

	TBuf16<32> buf;
	buf.NumUC(aVal,aRadix);
	if (buf.Length()>=aWidth)
		Append(buf.Left(aWidth));
	else
		{
		TInt i=aWidth-buf.Length();
		while(i--)
			Append(TChar('0'));
		Append(buf);
		}
	}

EXPORT_C void TDes16::AppendNum(TInt64 aVal)
//
// Convert a TInt64 into the descriptor.
//
	{

	if (aVal<0)
		{
		Append('-');
		aVal=-aVal;
		}
	AppendNum(aVal,EDecimal);
	}

EXPORT_C void TDes16::AppendNum(TInt64 aVal,TRadix aRadix)
//
// Convert a TInt64 into the descriptor, treat as unsigned.
//
	{

	if (aVal.High()==0)
		AppendNum(aVal.Low(),aRadix);
	else
		{
		TInt64 radix((TUint)aRadix);
		TInt64 shifted=aVal;
		shifted>>=1;
		shifted.Set(shifted.High()&0x7fffffffu,shifted.Low());
		AppendNum(shifted/(radix>>1),aRadix);
		if (aVal.High()&0x80000000u)
			{
			aVal+=TInt64(0x80000000u,0);
			if (aRadix==EDecimal)
				{
				if (aVal>=2)
					aVal-=2;
				 else
					aVal+=8;
				}
			}
		aVal=(aVal%radix);
		Append(aVal.Low()+(aVal.Low()<10 ? '0' : ('a'-10)));
		}
	}

EXPORT_C void TDes16::AppendNumUC(TInt64 aVal,TRadix aRadix)
//
// Convert a TInt64 into the descriptor, treat as unsigned.
//
	{

	if (aVal.High()==0)
		AppendNumUC(aVal.Low(),aRadix);
	else
		{
		TInt64 radix((TUint)aRadix);
		AppendNumUC(aVal/radix,aRadix);
		aVal=(aVal%radix);
		Append(aVal.Low()+(aVal.Low()<10 ? '0' : ('A'-10)));
		}
	}

EXPORT_C void TDes16::Format(TRefByValue<const TDesC16> aFmt,...)
//
// Convert arguments to the descriptor.
//
	{

    VA_LIST list;
    VA_START(list,aFmt);
    FormatList(aFmt,list);
    }

EXPORT_C void TDes16::FormatList(const TDesC16 &aFmt,VA_LIST aList)
//
// Convert arguments to the descriptor.
//
	{

    Zero();
    AppendFormatList(aFmt,aList);
    }

EXPORT_C void TDes16::AppendFormat(TRefByValue<const TDesC16> aFmt,TDes16Overflow *aOverflowHandler,...)
//
// Convert arguments to the descriptor.
//
	{

	VA_LIST list;
	VA_START(list, aOverflowHandler);
	AppendFormatList(aFmt,list,aOverflowHandler);
	}

EXPORT_C void TDes16::AppendFormat(TRefByValue<const TDesC16> aFmt,...)
//
// Convert arguments to the descriptor.
//
	{

    VA_LIST list;
    VA_START(list,aFmt);
    AppendFormatList(aFmt,list);
    }

EXPORT_C TPtrC16::TPtrC16()
//
// Default constructor
//
	: TDesC16((const TText16 *)NULL,0)
	{}

EXPORT_C TPtrC16::TPtrC16(const TDesC16 &aDes)
//
// Constructor
//
	: TDesC16(aDes)
	{}

EXPORT_C TPtrC16::TPtrC16(const TPtrC16 &aDes)
//
// Copy constructor
//
	: TDesC16(aDes)
	{}

EXPORT_C TPtrC16::TPtrC16(const TUint16 *aString)
//
// Constructor
//
	: TDesC16(aString)
	{}

EXPORT_C TPtrC16::TPtrC16(const TUint16 *aBuf,TInt aLength)
//
// Constructor
//
	: TDesC16(aBuf,aLength)
	{}

EXPORT_C void TPtrC16::Set(const TUint16 *aBuf,TInt aLength)
//
// Copy constructor by another name.
//
	{

	__ASSERT_ALWAYS(aLength>=0,Panic(ETDes16Overflow));
	DoSetLength(aLength);
	iPtr=aBuf;
	}

EXPORT_C void TPtrC16::Set(const TDesC16 &aDes)
//
// Copy constructor by another name.
//
	{

	DoSetLength(aDes.Length());
	iPtr=aDes.Ptr();
	}

EXPORT_C TPtr16::TPtr16(TUint16 *aBuf,TInt aMaxLength)
//
// Constructor
//
	: TDes16(aBuf,0,aMaxLength)
	{}

EXPORT_C TPtr16::TPtr16(TUint16 *aBuf,TInt aLength,TInt aMaxLength)
//
// Constructor
//
	: TDes16(aBuf,aLength,aMaxLength)
	{}

EXPORT_C TPtr16::TPtr16(TBufCBase16 &aLcb,TInt aMaxLength)
//
// Constructor
//
	: TDes16(aLcb,aMaxLength)
	{}

EXPORT_C TPtr16::TPtr16(const TPtr16& aTPtr)
//
// Copy constructor
//
	: TDes16(aTPtr)
	{}

EXPORT_C void TPtr16::Set(TUint16 *aBuf,TInt aLength,TInt aMaxLength)
//
// Set the contents of the pointer.
//
	{

	__ASSERT_ALWAYS(aMaxLength>=0,Panic(ETDes16MaxLengthNegative));
	__ASSERT_ALWAYS(aLength>=0 && aLength<=aMaxLength,Panic(ETDes16LengthOutOfRange));
	iPtr=aBuf;
	iMaxLength=aMaxLength;
	DoSetType(EPtr);
	DoSetLength(aLength);
	}

EXPORT_C void TPtr16::Set(TPtr16 &aPtr)
//
// Copy constructor by another name.
//
	{

	if (aPtr.Type()==EBufCPtr)
		TDesC16::Set(*((TBufCBase16 *)aPtr.iPtr),aPtr.MaxLength());
	else
		{
		iPtr=aPtr.WPtr();
		iMaxLength=aPtr.MaxLength();
		DoSetType(EPtr);
		DoSetLength(aPtr.Length());
		}
	}

EXPORT_C void TDesC16::__DbgTestInvariant() const
//
// Test that the class obeys its invariant.
//
    {

#if defined(_DEBUG)
	switch (Type())
		{
	case EBufC:
	case EPtrC:
	case EPtr:
	case EBuf:
	case EBufCPtr:
		break;
	default:
		User::Invariant();
		}
	if (Ptr()==NULL)
		User::Invariant();
#endif
    }

EXPORT_C void TPtrC16::__DbgTestInvariant() const
//
// Test that the class obeys its invariant.
//
    {

#if defined(_DEBUG)
	TDesC16::__DbgTestInvariant(); // Test base class
	if (iPtr==NULL || Type()!=EPtrC)
		User::Invariant();
#endif
	}

EXPORT_C void TDes16::__DbgTestInvariant() const
//
// Test that the class obeys its invariant.
//
    {

#if defined(_DEBUG)
	TDesC16::__DbgTestInvariant(); // Test base class
	if (Length()>MaxLength() || !(Type()==EPtr || Type()==EBufCPtr || Type()==EBuf))
		User::Invariant();
#endif
	}

EXPORT_C void HBufC16::__DbgTestInvariant() const
//
// Test that the class obeys its invariant.
//
    {

#if defined(_DEBUG)
	TDesC16::__DbgTestInvariant(); // Test base class
	if (Length()>(TInt)(User::AllocLen(this)-sizeof(TDesC16)) || Type()!=EBufCPtr)
		User::Invariant();
#endif
	}

EXPORT_C void TPtr16::__DbgTestInvariant() const
//
// Test that the class obeys its invariant.
//
    {

#if defined(_DEBUG)
	TDes16::__DbgTestInvariant(); // Test base class
	if (iPtr==NULL || !(Type()==EPtr || Type()==EBufCPtr))
		User::Invariant();
#endif
	}

