chxavstringutils.cpp
来自「symbian 下的helix player源代码」· C++ 代码 · 共 467 行
CPP
467 行
/************************************************************************
* chxavstringutils.cpp
* --------------------
*
* Synopsis:
* Contains the implementation of the CHXAvStringUtils class. This class is a
* implements helper static functions to go from our CHXString in helix to
* Symbian's descriptor classes.
*
* Target:
* Symbian OS
*
*
* (c) 1995-2003 RealNetworks, Inc. Patents pending. All rights reserved.
*
*****************************************************************************/
// Symbian includes...
#include <aknpopup.h>
#include <akntitle.h>
#include <eikenv.h>
#include <coemain.h>
#include <stdlib.h>
#include <charconv.h>
#include <utf.h>
// Helix includes...
#include "hxassert.h"
#include "hxstring.h"
//#include "hlxosstr.h"
#include "hxstring.h"
#include "hxsym_debug.h"
#include "hxbuffer.h"
// Includes from this project...
#include "chxavmisc.h"
#include "chxavutil.h"
#include "chxavcleanupstack.h"
namespace CHXAvStringUtils
{
// assume input comprises single-byte characters and copy out as utf16 (uts-2)
void CopyRaw(const char* in, TDes& out, TInt count) // XXXLCM move this helpers
{
TInt cch = min(count, out.MaxLength());
out.SetLength(cch);
for (TInt idx = 0; idx < cch; ++idx)
{
out[idx] = (in[idx] & 0xff);
}
}
// return octets needed to encode given unicode character
TUint CalcUTF8OctetsForConversion(UINT16 ch) // XXXLCM move this helpers
{
// utf8 encodes 1-6 bytes per character
static const unsigned int z_UTF8Bounds[] = {
0x80, 0x800, 0x10000, 0x200000, 0x4000000, 0x80000000};
HX_ASSERT(ch < 0x80000000);
TUint cchNeeded = 0;
for(TInt idx = 0; idx < ARRAY_COUNT(z_UTF8Bounds); ++idx)
{
if (ch < z_UTF8Bounds[idx])
{
cchNeeded = idx + 1;
break;
}
}
HX_ASSERT(cchNeeded > 0);
return cchNeeded;
}
// return octets needed to encode given unicode string
TUint CalcUTF8OctetsForConversion(const TDesC& in) // XXXLCM move this helpers
{
TUint cchTotal = 0;
TInt cch = in.Length();
for (TInt idx = 0; idx < cch; ++idx)
{
cchTotal += CalcUTF8OctetsForConversion(in[idx]);
}
return cchTotal;
}
TInt GetUtf8TrailingOctetCount(char ch)
{
HX_ASSERT((ch & 0xc0) == 0xc0); // first char in utf8 multibyte char sequence begins with '11...'
TInt count = 0;
if ((ch & 0x20) == 0)
{
// '110...'
count = 1;
}
else if( (ch & 0x10) == 0)
{
// '1110...'
count = 2;
}
else if( (ch & 0x08) == 0)
{
// '11110...'
count = 3;
}
else if( (ch & 0x04) == 0)
{
// '111110...'
count = 4;
}
else if( (ch & 0x02) == 0)
{
// '1111110...'
count = 5;
}
else
{
// '1111111...' not a valid utf-8 character
count = -1;
}
return count;
}
bool IsValidUtf8(const char* pText, TInt cchText)
{
HX_ASSERT(cchText != 0);
HX_ASSERT(pText);
bool bIsValid = true;
TInt idx = 0;
while(idx < cchText)
{
char ch = pText[idx++];
if( (ch & 0x80) == 0 )
{
// plain ascii char (0 - 127) that is also a valid utf8 char
continue;
}
else if( (ch & 0x40) == 0 )
{
// first char in multibyte utf8 char sequence never begins with '10...'
bIsValid = false;
break;
}
else
{
TInt trailCount = GetUtf8TrailingOctetCount(ch);
const TInt k_maxUtf8TrailingOctets = 5;
HX_ASSERT(trailCount <= k_maxUtf8TrailingOctets);
if(-1 == trailCount)
{
bIsValid = false;
break;
}
if( idx + trailCount > cchText )
{
// can't verify this multibyte utf-8 char
bIsValid = false;
break;
}
// verify that each trailing octet begins with '10' as two most-significant bits
for(TInt idxTrail = 0; idxTrail < trailCount; ++idxTrail)
{
// each trailing octet must begin with '10...'
ch = pText[idx++];
if( (ch & 0xc0) != 0x80 )
{
bIsValid = false;
break;
}
}
if( !bIsValid )
{
break;
}
}
}
return bIsValid;
}
/*
* DesToString
* -----------
* convert from unicode to utf-8 string
*
*/
void
DesToString(const TDesC& in, CHXString& out)
{
out = "";
TInt cch = in.Length();
if( cch )
{
TInt cchNeeded = CalcUTF8OctetsForConversion(in);
HBufC8* pbuf = HBufC8::New(cchNeeded);
if(pbuf)
{
TPtr8 ptrOut = pbuf->Des();
TInt cchUnconverted = CnvUtfConverter::ConvertFromUnicodeToUtf8(ptrOut, in);
HX_ASSERT(cchUnconverted == 0);
if(cchUnconverted == 0)
{
out = CHXString(reinterpret_cast<const char*>(ptrOut.Ptr()), ptrOut.Length());
}
HX_DELETE(pbuf);
}
}
}
/*
* StringToDes
* -----------
* convert from utf-8 or ansi (single-byte) string to unicode descriptor
*
*/
void StringToDes(const CHXString& in, TDes& out)
{
if(in.GetLength() > 0)
{
// scan the string to see if it looks like utf8; CnvUtfConverter doesn't fail in every case for non utf8 input (e.g., copyright char)
if( IsValidUtf8(in, in.GetLength()) )
{
TPtrC8 from( reinterpret_cast<const TUint8*>(static_cast<const char*>(in)) );
TInt cchUnconverted = CnvUtfConverter::ConvertToUnicodeFromUtf8(out, from);
HX_ASSERT(0 == cchUnconverted);
}
else
{
// assume string is ansi single-byte format
DPRINTF(SYMP_INFO, ("StringToDes(): input not utf-8? assuming single-byte\n"));
CopyRaw(in, out, in.GetLength());
}
}
else
{
out.Zero();
}
}
/*
* StringToHBuf
* ------------
* Takes a string and returns the HBufC equivalent.
*
*/
HBufC*
StringToHBuf(const CHXString& s)
{
HBufC* buf = HBufC::NewMax(s.GetLength());
TPtr des = buf->Des();
StringToDes(s, des);
return buf;
}
CHXString
DescToString(const TDesC& desc)
{
CHXString str;
DesToString(desc, str);
return str;
}
void
Replace(TPtr& ptr, char oldChar, char newChar)
{
for (TInt idx = 0; idx < ptr.Length(); ++idx)
{
if (ptr[idx] == oldChar)
{
ptr[idx] = newChar;
}
}
}
/*
* AllocTextL
* ------------------
* concatenate strings
*
*/
////////////////////////////////////////
//
// return one + two + three
//
HBufC* AllocTextL(const TDesC& one, const TDesC& two, const TDesC& three)
{
HBufC* pNewString = HBufC::NewL(one.Length() + two.Length() + three.Length());
TPtr ptr = pNewString->Des();
ptr.Copy(one);
ptr.Append(two);
ptr.Append(three);
return pNewString;
}
////////////////////////////////////////////////////////////
//
HBufC*
AllocTextL(const CHXString& str)
{
HBufC* pText = HBufC::NewL(str.GetLength());
TPtr ptr = pText->Des();
StringToDes(str, ptr);
return pText;
}
#if defined(DEBUG)
// for resource text helpers below
_LIT(KNumericArg, "%d");
_LIT(KStringArg, "%S");
_LIT(KRealArg, "%f");
_LIT(KRealArgPrecision, "%.1f");
_LIT(KHexArg, "%x");
#endif
HBufC* AllocResTextL(TInt resId)
{
return CEikonEnv::Static()->AllocReadResourceL(resId);
}
//////////////////////////////////////
// alloc text with TInt arg sprintf'd into text loaded from resId
//
HBufC* AllocResFormatTextL(TInt resId, TInt arg)
{
HBufC* pFormatString = CEikonEnv::Static()->AllocReadResourceL(resId);
HX_ASSERT(KErrNotFound != pFormatString->Find(KNumericArg));
AUTO_PUSH_POP_DEL(pFormatString);
HBufC* pText = HBufC::NewL(pFormatString->Length() + CHXAvUtil::KMaxInt32Chars);
pText->Des().Format(*pFormatString, arg);
return pText;
}
//////////////////////////////////////
// alloc text with double arg sprintf'd into text loaded from resId
//
HBufC* AllocResFormatTextL(TInt resId, double arg)
{
HBufC* pFormatString = CEikonEnv::Static()->AllocReadResourceL(resId);
HX_ASSERT( KErrNotFound != pFormatString->Find(KRealArg) || KErrNotFound != pFormatString->Find(KRealArgPrecision) );
AUTO_PUSH_POP_DEL(pFormatString);
HBufC* pText = HBufC::NewL(pFormatString->Length() + CHXAvUtil::KMaxDoubleChars);
pText->Des().Format(*pFormatString, arg);
return pText;
}
HBufC* AllocResFormatTextL(TInt resId, const TDesC& desc)
{
HBufC* pFormatString = CEikonEnv::Static()->AllocReadResourceL(resId);
HX_ASSERT(KErrNotFound != pFormatString->Find(KStringArg));
AUTO_PUSH_POP_DEL(pFormatString);
HBufC* pText = HBufC::NewL(pFormatString->Length() + desc.Length());
pText->Des().Format(*pFormatString, &desc);
return pText;
}
HBufC* AllocFormatTextL(const TDesC& formatString, TInt arg)
{
HX_ASSERT(KErrNotFound != formatString.Find(KNumericArg));
const TUint k_cchNumericPart = CHXAvUtil::KMaxInt32Chars * 2; // account for commas, decimals added
HBufC* pText = HBufC::NewL(formatString.Length() + k_cchNumericPart);
pText->Des().Format(formatString, arg);
return pText;
}
HBufC* AllocFormatTextHexArgL(const TDesC& formatString, TUint hexArg)
{
HX_ASSERT(KErrNotFound != formatString.Find(KHexArg));
const TUint k_cchNumericPart = CHXAvUtil::KMaxInt32Chars * 2;
HBufC* pText = HBufC::NewL(formatString.Length() + k_cchNumericPart);
pText->Des().Format(formatString, hexArg);
return pText;
}
////////////////////////////////////
//
// allocate modified text string if textIn is too large to fit in cxDisplay
//
// if pTextOut is NULL upon return, the original text is small enough to fit
//
// caller should de-allocate pTextOut
//
void
GetTruncatedDisplayTextL(const TDesC& textIn,
const CFont* pFont,
TInt cxDisplay, HBufC*& pTextOut,
bool bUseEllipsis)
{
_LIT(KEllipsisText, "...");
HX_ASSERT(pFont != 0);
pTextOut = 0;
if (pFont->TextWidthInPixels(textIn) > cxDisplay)
{
// text is too big to fit in our rect...
TInt cxEllipsis = pFont->TextWidthInPixels(KEllipsisText);
if( cxDisplay < cxEllipsis )
{
// not enough room for ellipsis
// NP_ASSERT(false);
bUseEllipsis = false;
}
TInt textInCount = 0;
TInt totalCount = 0;
if(bUseEllipsis)
{
textInCount = pFont->TextCount(textIn, cxDisplay - cxEllipsis);
totalCount = textInCount + KEllipsisText().Length();
}
else
{
textInCount = pFont->TextCount(textIn, cxDisplay);
totalCount = textInCount;
}
pTextOut = HBufC::NewMaxL(totalCount);
TPtr des = pTextOut->Des();
// copy clipped text
des.Copy(textIn.Left(textInCount));
// get rid of trailing space before ellipsis
des.TrimRight();
// add ellipsis
if( bUseEllipsis )
{
des.Append(KEllipsisText);
}
}
}
} // ns CHXAvStringUtils
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?