chxavescapedstring.cpp

来自「symbian 下的helix player源代码」· C++ 代码 · 共 282 行

CPP
282
字号
/************************************************************************
 * chxavescapedstring.cpp
 * ----------------------
 *
 * Synopsis:
 * String manipulation.  Remove escape chars.
 *
 * Target:
 * Symbian OS
 *
 *
 * (c) 1995-2003 RealNetworks, Inc. Patents pending. All rights reserved.
 *
 *****************************************************************************/
 
#include <ctype.h>

#include "hxstring.h"
#include "char_stack.h"
#include "chxavmisc.h"
#include "hxassert.h"

#include "chxavescapedstring.h"

namespace
{

// These are non-alphanumeric characters that are legal and do not
// have to be escaped
const char k_legalChars[] = { 
    '$', '-', '_', '.',            // safe  RFC2068 Sec 3.2.1
    '!', '*', '\'', '(', ')', ',', // extra RFC2068 Sec 3.2.1
    '\0'
};


// These are extra characters that are legal for path strings
// and should not be escaped
const char k_pathChars[] = {
    ':', '@', '&', '=',       // pchar  RFC2068 Sec 3.2.1
    ';',                      // params RFC2068 Sec 3.2.1
    '/',                      // path   RFC2068 Sec 3.2.1
    '+',                      // pchar (must be last)
    '\0'
};

// These are extra characters that are legal for query strings
// and should not be escaped
const char k_queryChars[] = {
    ';', '/', '?', ':', '@', '&', '=', '+', // reserved RFC2068 Sec 3.2.1
    '\0'
};

inline
bool IsEscaped(const char* pBuf, int len)
{
    bool ret = false;

    if ((len >= 3) &&
	(pBuf[0] == '%') &&
	(isxdigit(pBuf[1])) &&
	(isxdigit(pBuf[2])))
	ret = true;	

    return ret;
}

inline 
int Hex2Char(char ch)
{
    int ret = 0;

    if ((ch >= 'a') && (ch <= 'f'))
	ret =  10 + ch - 'a';
    else if ((ch >= 'A') && (ch <= 'F'))
	ret =  10 + ch - 'A';
    else
	ret = ch - '0';
    
    return ret;
}

inline
bool IsAlphaNum(unsigned char ch)
{
    bool ret = false;
    
    if (((ch >= 0x30) && (ch < 0x3a)) ||  // 0-9
	((ch >= 0x41) && (ch < 0x5b)) ||  // A-Z
	((ch >= 0x61) && (ch < 0x7b)))    // a-z
	ret = true;
    
    return ret;
}

inline
bool IsSpecialChar(char ch, const char* pExtraLegal)
{
    bool ret = true;

    if ((IsAlphaNum(ch)) ||
	(strchr(k_legalChars, ch))||
	(strchr(pExtraLegal, ch)))
	ret = false;
       
    return ret;
}

inline
char MakeHex(unsigned char ch)
{
    static const char z_hexBuf[] = "0123456789ABCDEF";
    HX_ASSERT(ch >= 0 && ch < ARRAY_COUNT(z_hexBuf));
    return z_hexBuf[ch];
}


CHXString UnEscapeStr(const CHXString& escapedStr)
{
    int len = escapedStr.GetLength();
    const char* pCur = escapedStr;

    CharStack newStr;

    while(len)
    {
	if (IsEscaped(pCur,len))
	{
	    // Contruct the character from the escape sequence and
	    // copy it into the new string
	    *newStr = (Hex2Char(pCur[1]) << 4) | Hex2Char(pCur[2]);
	    newStr++;

	    pCur += 2;
	    len -= 2;
	}
	else
	{
	    // Just copy the character
	    *newStr = *pCur;
	    newStr++;
	}

	pCur++;
	len--;
    }

    return newStr.Finish();
}



CHXString EscapeStr(const CHXString& unescapedStr,
				    const char* pExtraLegal)
{
    int len = unescapedStr.GetLength();
    const char* pCur = unescapedStr;
    
    CharStack newPath;

    while (len)
    {
	if (IsSpecialChar(*pCur, pExtraLegal))
	{
	    // Escape this character
	    *newPath = '%';
	    newPath++;
	    
	    *newPath = MakeHex((*pCur >> 4) & 0x0f);
	    newPath++;
	    
	    *newPath = MakeHex(*pCur & 0xf);
	    newPath++;
	}
	else
	{
	    *newPath = *pCur;
	    newPath++;
	}

	pCur++;
	len--; 
    }

    return newPath.Finish();
}

bool ValidStr(const CHXString& escapedStr,
			       const char* pExtraLegal)
{
    bool ret = true;

    int len = escapedStr.GetLength();
    const char* pCur = escapedStr;

    CharStack newStr;

    while(len)
    {
	if (IsSpecialChar(*pCur, pExtraLegal) &&
	    !IsEscaped(pCur,len))
	{
	    // The escaped string has an illegal character in it
	    ret = false;
	    break;
	}

	pCur++;
	len--;
    }

    return ret;
}

} // ns anon


CHXAvEscapedString::CHXAvEscapedString()
{}

CHXAvEscapedString::CHXAvEscapedString(const char* pEscapedStr) :
    m_escaped(pEscapedStr),
    m_unEscaped(UnEscapeStr(m_escaped))
{}

CHXAvEscapedString::CHXAvEscapedString(const CHXString& escapedStr) :
    m_escaped(escapedStr),
    m_unEscaped(UnEscapeStr(m_escaped))
{}

bool CHXAvEscapedString::operator == (const CHXAvEscapedString& rhs) const
{
    return (bool)(m_escaped == rhs.m_escaped);
}

bool CHXAvEscapedString::operator != (const CHXAvEscapedString& rhs) const
{
    return (bool)(m_escaped != rhs.m_escaped);
}

bool CHXAvEscapedString::ValidPath() const
{
    return ValidStr(m_escaped, k_pathChars);
}

bool CHXAvEscapedString::ValidQuery() const
{
    return ValidStr(m_escaped, k_queryChars);
}


void CHXAvEscapedString::EscapePathStr(const CHXString& unescapedPath, bool bForcePlusEscape)
{
    m_unEscaped = unescapedPath;

    CHXString strPathChars = k_pathChars;
    if(bForcePlusEscape)
    {
        //
        // RFC 1738 2.2: characters that are not required to be encoded
        // (including alphanumerics) may be encoded within the scheme-specific
        // part of a URL, as long as they are not being used for a reserved
        // purpose.
        //

        // force '+' to be escaped so other unescaping logic doesn't mis-intepret it as a space
        INT32 cchPathChars = strPathChars.GetLength();
        HX_ASSERT(strPathChars.Find('+') == cchPathChars -1);
        strPathChars.SetAt(cchPathChars - 1, '\0');
    }
    m_escaped = EscapeStr(unescapedPath, strPathChars);
}

void CHXAvEscapedString::EscapeQueryStr(const CHXString& unescapedQuery)
{
    m_unEscaped = unescapedQuery;
    m_escaped = EscapeStr(unescapedQuery,
			  k_queryChars);
}


⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?