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 + -
显示快捷键?