⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pckunpck.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/* ***** BEGIN LICENSE BLOCK ***** 
 * Version: RCSL 1.0/RPSL 1.0 
 *  
 * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
 *      
 * The contents of this file, and the files included with this file, are 
 * subject to the current version of the RealNetworks Public Source License 
 * Version 1.0 (the "RPSL") available at 
 * http://www.helixcommunity.org/content/rpsl unless you have licensed 
 * the file under the RealNetworks Community Source License Version 1.0 
 * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
 * in which case the RCSL will apply. You may also obtain the license terms 
 * directly from RealNetworks.  You may not use this file except in 
 * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
 * applicable to this file, the RCSL.  Please see the applicable RPSL or 
 * RCSL for the rights, obligations and limitations governing use of the 
 * contents of the file.  
 *  
 * This file is part of the Helix DNA Technology. RealNetworks is the 
 * developer of the Original Code and owns the copyrights in the portions 
 * it created. 
 *  
 * This file, and the files included with this file, is distributed and made 
 * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
 * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
 * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
 * 
 * Technology Compatibility Kit Test Suite(s) Location: 
 *    http://www.helixcommunity.org/content/tck 
 * 
 * Contributor(s): 
 *  
 * ***** END LICENSE BLOCK ***** */ 

// system
#include "hlxclib/stdarg.h" /* for va_arg */
#include "safestring.h"
#ifndef _SYMBIAN
#include "hlxclib/memory.h"
#endif
#include "hlxclib/string.h"
#include "hlxclib/stdlib.h"
#include "hlxclib/time.h"
// include
#include "hxtypes.h"
#include "hxwintyp.h"
#include "hxcom.h"
#include "hxcomm.h"
// pncont
#include "hxbuffer.h"
#include "chxpckts.h"
#include "rtsputil.h" /* for Base64 utils */
#include "hxslist.h"
#include "pckunpck.h"

/*
 * constants
 */

// ascii string, buffer, pointer, uint, double, flag (BOOL), IHXValues
const char* const kFormatSpecs = "abpudfv";

// these types have implicit "parsability" so we omit the "x:" type specifier
// a string starts with '"', flag is a 'T' or 'F', uint is all decimal digits,
// and an IHXValues begins with '['
const char* const kOptTypes = "afuv";

// chars we need to escape/unescape (note they have 1:1 positioning)
const char* const kScaryChars = "\"\n\t\r\\";
const char* const kUnScaryChars = "\"ntr\\"; // these must correspond 1:1

// decimals
const char* const kDecimals = "1234567890";


/*
 * PackBuffer
 *
 * USAGE:
 *
 * IHXBuffer* pBuffer;
 * PackBuffer(pBuffer, "uu", 10, 20);
 * PackBuffer(pBuffer, "a", "foobar");
 * PackBuffer(pBuffer, "aua", 10, "foobar", 20);
 *
 * More advanced: (passing a buffer)
 * IHXBuffer* pTheBuffer;
 * PackBuffer(pBuffer, "uabu", 10, "foobar", pTheBuffer, 20);
 *
 * Still more advanced: (passing an IUnknown)
 * IHXSomeObject* pObj;
 * PackBuffer(pBuffer, "uap", 10, "foobar", (IUnknown*)pObj);
 */

HX_RESULT
PackBuffer(REF(IHXBuffer*) pBuffer, const char* pFormat, ...)
{
    va_list vargs;
    va_start(vargs, pFormat);
    return PackBufferV(pBuffer, pFormat, vargs);
}


HX_RESULT
PackBufferV(REF(IHXBuffer*) pBuffer, const char* pFormat, va_list vargs)
{
    // init the out param
    pBuffer = NULL;

    // automatically fail if we've no CCF or a bad formatter is passed
    if (!pFormat || !*pFormat || !strpbrk(pFormat, kFormatSpecs))
    {
	return HXR_FAIL;
    }

    // calculate how much space we'll need for the buffer and
    // make sure the formatter is valid
    UINT32 uBufSize = 1; // null terminator
    CHXStringList packedValuesList;
    va_list vargsOrig;
    va_copy(vargsOrig, vargs);	
    const char* pTemp = pFormat;
    while (*pTemp)
    {
	switch (*pTemp)
	{
	    case 'f':
	    {
		BOOL bFlag = va_arg(vargs, BOOL);
		// XXXNH: optimization... we only put one char for a flag/bool
		uBufSize += 1;
	    }
	    break;

	    case 'd':
	    {
		double dVal = va_arg(vargs, double);
		
		// to preserve precision we base64-ize the double
		uBufSize += (sizeof(double) * 4) / 3 + 10;
	    }
	    break;
	    
	    case 'u':
	    {
		UINT32 u = va_arg(vargs, UINT32);
                // Compute number of hex digits in 'u' & add to uBufSize
                if (u == 0) ++uBufSize;
                else {
                    UINT32 leadingZeroes = 0;
                    if (u <= 0x0000ffff) {leadingZeroes += 4; u <<= 16;}
                    if (u <= 0x00ffffff) {leadingZeroes += 2; u <<= 8;}
                    if (u <= 0x0fffffff) {leadingZeroes += 1; u <<= 4;}
                    uBufSize += 8 - leadingZeroes;
                }
	    }
	    break; 
	    
	    case 'a':
	    {
		const char* pStr = va_arg(vargs, const char*);
		
		int nLen = pStr ? strlen(pStr) + 2 : 2; // add on quotation marks
		while (pStr && *pStr)
		{
		    // double-count chars we'll have to escape
		    if (strchr(kScaryChars, *pStr))
			nLen++;
		    
		    pStr ++;
		}
		uBufSize += nLen;
	    }
	    break;

	    case 'b':
	    {
		IHXBuffer* pBuf = va_arg(vargs, IHXBuffer*);
		if (!pBuf)
		{
		    HX_ASSERT(FALSE);
		    return HXR_FAIL;
		}
		
		// base64 uses roughly 33% more space, plus a couple extra
		uBufSize += (pBuf->GetSize() * 4) / 3 + 10;
	    }
	    break;

	    case 'p':
	    {
		IUnknown* pPointer = va_arg(vargs, IUnknown*);
		uBufSize += 8; // 8 digits for a hex number
	    }
	    break;

	    case 'v':
	    {
		IHXValues* pValues = va_arg(vargs, IHXValues*);
		if (!pValues)
		{
		    HX_ASSERT(FALSE);
		    return HXR_FAIL;
		}
		
		CHXString sTemp;
		if (FAILED(PackValues(sTemp, pValues)))
		{
		    HX_ASSERT(FALSE);
		    return HXR_FAIL;
		}

		packedValuesList.AddTailString(sTemp);
		uBufSize += sTemp.GetLength();
	    }
	    break;
	}

	if (strchr(kOptTypes, *pTemp))
	    uBufSize++; // just the delimiter for "optimized" types
	else
	    uBufSize += 3; // the size of type specifier and delimiter

	// next!
	pTemp++;
    }

    // now allocate our buffer
    CHXBuffer* pCHXBuffer = new CHXBuffer;
    if (!pCHXBuffer)
	return HXR_OUTOFMEMORY;
    pCHXBuffer->AddRef();
    if (SUCCEEDED(pCHXBuffer->SetSize(uBufSize)))
    {
	pBuffer = (IHXBuffer*)pCHXBuffer;
    }
    else
    {
	HX_RELEASE(pCHXBuffer);
	return HXR_OUTOFMEMORY;
    }

    // now pack the args into our buffer
    char* pBufStr = (char*)pBuffer->GetBuffer();
    
    vargs = vargsOrig;
    pTemp = pFormat;
    while (*pTemp)
    {
	// XXXNH: space optimization: omit the type & ':' for certain types
	if (strchr(kOptTypes, *pTemp) == NULL)
	{
	    // start the param
	    *pBufStr = *pTemp; // append the type
	    pBufStr++;
	    *pBufStr = ':'; // and a delimiter
	    pBufStr++;
	}

	// then format the data
	switch (*pTemp)
	{
	    case 'f':
	    {
		BOOL bFlag = va_arg(vargs, BOOL);
		*pBufStr = bFlag ? 'T' : 'F';
		pBufStr++;
	    }
	    break;

	    case 'd':
	    {
		double dVal = va_arg(vargs, double);

		UINT32 uSize = (sizeof(double) * 4) / 3 + 10;
		int nLen = BinTo64((UCHAR*)&dVal, sizeof(double), pBufStr);
		HX_ASSERT(nLen >= 0);
		pBufStr += nLen-1; // -1 because of null terminator
	    }
	    break;
	    
	    case 'u':
	    {
		UINT32 u = va_arg(vargs, UINT32);
		char pNum[16]; /* Flawfinder: ignore */
		SafeSprintf(pNum, sizeof(pNum), "%x", u);
		*pBufStr = '\0';
		strcat(pBufStr, pNum); /* Flawfinder: ignore */
		pBufStr += strlen(pNum);
	    }
	    break; 
	    
	    case 'a':
	    {
		*pBufStr = '"'; // begin quote
		pBufStr++;
		
		const char* pStr = va_arg(vargs, const char*);
		
		while (pStr && *pStr)
		{
		    // double-count chars we'll have to escape
		    const char* pScary = strchr(kScaryChars, *pStr);
		    if (pScary)
		    {
			*pBufStr = '\\';
			pBufStr++;
			*pBufStr = kUnScaryChars[pScary - kScaryChars];
			pBufStr++;
		    }
		    else
		    {
			*pBufStr = *pStr;
			pBufStr++;
		    }
		    pStr++;
		}
		
		*pBufStr = '"'; // end quote
		pBufStr++;
	    }
	    break;

	    case 'b':
	    {
		IHXBuffer* pBuf = va_arg(vargs, IHXBuffer*);
		if (!pBuf)
		{
		    HX_ASSERT(FALSE);
		    return HXR_FAIL;
		}
		
		// base64 uses roughly 33% more space, plus a couple extra
		UINT32 uSize = pBuf->GetSize();
		int nLen = BinTo64(pBuf->GetBuffer(), uSize, pBufStr);
		HX_ASSERT(nLen >= 0);
		pBufStr += nLen-1; // -1 because of null terminator
	    }
	    break;

	    case 'p':
	    {
		IUnknown* pUnknown = va_arg(vargs, IUnknown*);
		char pPointer[9]; /* Flawfinder: ignore */
		SafeSprintf(pPointer, sizeof(pPointer), "%08x", pUnknown);
		*pBufStr = '\0';
		strcat(pBufStr, pPointer); /* Flawfinder: ignore */
		pBufStr += 8;
	    }
	    break;

	    case 'v':
	    {
		IHXValues* pIgnoreMe = va_arg(vargs, IHXValues*);
		LISTPOSITION p = packedValuesList.GetHeadPosition();
		CHXString* psPacked = packedValuesList.GetNext(p);

		*pBufStr = '\0';
		strcat(pBufStr, *psPacked); /* Flawfinder: ignore */
		pBufStr += psPacked->GetLength();
		
		packedValuesList.RemoveHeadString();
	    }
	    break;
	}

	// end the param
	*pBufStr = ';';
	pBufStr++;

	// go to the next formatter
	pTemp++;
    }

    // null terminate!
    *pBufStr = '\0';
    pBufStr++;
    
#ifdef _DEBUG
    // XXXNH: some sanity checking
    pBufStr -= uBufSize;
    if (pBufStr > (char*)(pBuffer->GetBuffer()))
    {
	// XXXNH: we wrote past the end of the buffer!!!!!  We must have
	// miscalculated the space needed...
	HX_ASSERT(FALSE);
	HX_RELEASE(pBuffer);
	return HXR_FAIL;
    }
#endif
    
    return HXR_OK;
}


/*
 * UnpackBuffer
 *
 * works like PackBuffer & sscanf.
 */

int
UnpackBuffer(REF(const char*) pBuffer, const char* pFormat, ...)
{
    va_list vargs;
    va_start(vargs, pFormat);
    return UnpackBufferV(pBuffer, pFormat, vargs);
}

  
int
UnpackBufferV(REF(const char*) pBufStr, const char* pFormat, va_list vargs)
{
    // automatically fail if we've no CCF or a bad formatter is passed
    if (!pFormat || !*pFormat || !strpbrk(pFormat, kFormatSpecs))
	return -1;

    if (!pBufStr)
	return 0;

    // iterate through the args and unpack them from the buffer
    int nRead = 0;
    const char* pTemp = pFormat;
    while (*pTemp)
    {
	// XXXNH: space optimization: omit the type & ':' for certain types
	if (!strchr(kOptTypes, *pTemp))
	{
	    // make sure the types match
	    if (*pTemp != *pBufStr)
		return nRead;
	    pBufStr++;

	    // read the type/value delimiter
	    if (*pBufStr != ':')
		return nRead;
	    pBufStr++;
	}
	
	switch (*pTemp)
	{
	    case 'f':
	    {
		// XXXNH: optimization... we only put one char for a flag/bool
		BOOL* pbFlag = va_arg(vargs, BOOL*);
		if (*pBufStr == 'T')
		    *pbFlag = TRUE;
		else
		    *pbFlag = FALSE;
		pBufStr++;
	    }
	    break;

	    case 'd':
	    {
		double* pdVal = va_arg(vargs, double*);

		const char* pEnd = strchr(pBufStr, ';');
		if (pEnd)
		{
		    int nSize = pEnd - pBufStr;
		    int nLen = BinFrom64(pBufStr, nSize, (UCHAR*)pdVal);
		    HX_ASSERT(nLen == sizeof(double));
		    pBufStr = pEnd;
		}
		else
		    return nRead; // couldn't parse the end of the buffer
	    }
	    break;

	    case 'u':
	    {
		UINT32* puInt = va_arg(vargs, UINT32*);

                // XXXSAB Untested...
                char* pEnd = NULL;
                unsigned long val = strtoul(pBufStr, &pEnd, 16);

		// if (sscanf(pBufStr, "%x", puInt) == 1)
                if (pEnd && pEnd > pBufStr)
		{
		    // advance to the next delimiter
		    pBufStr = strchr(pBufStr, ';');
		}
		else
		    return nRead; // couldn't parse an int!
	    }
	    break;
	    
	    case 'a':
	    {

⌨️ 快捷键说明

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