pckunpck.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:55k
- /* ***** 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 = ""ntr\";
- 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 = ' ';
- 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 = ' ';
- 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 = ' ';
- 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 = ' ';
- 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':
- {
- CHXString* pTemp = va_arg(vargs, CHXString*);
- HX_ASSERT(pTemp);
- if (!pTemp)
- return nRead; // invalid CHXString*?
- pTemp->Empty();
- // read the begin quote
- if (*pBufStr != '"')
- return nRead;
- pBufStr++;
- // read till we run out of buffer OR hit the end quote
- BOOL bEscaped = FALSE;
- while (*pBufStr && (bEscaped || *pBufStr != '"'))
- {
- if (bEscaped)
- {
- const char* pScary = strchr(kUnScaryChars, *pBufStr);
- HX_ASSERT(pScary);
- if (pScary)
- {
- *pTemp += kScaryChars[pScary - kUnScaryChars];
- }
- }
- else
- {
- if (*pBufStr == '\')
- {
- bEscaped = TRUE;
- }
- else
- {
- *pTemp += *pBufStr;
- }
- }
- pBufStr++;
- }
- // read the end quote!
- if (*pBufStr != '"')
- return nRead;
- pBufStr++;
- }
- break;
- case 'b':
- {
- IHXBuffer** ppBuf = va_arg(vargs, IHXBuffer**);
- HX_ASSERT(ppBuf);
- if (!ppBuf)
- return nRead;
- CHXBuffer* pCHXBuffer = new CHXBuffer;
- if (!pCHXBuffer)
- return nRead;
-
- pCHXBuffer->AddRef();
- *ppBuf = (IHXBuffer*)pCHXBuffer;
- HX_RESULT res = HXR_FAIL;
- const char* pEnd = strchr(pBufStr, ';');
- if (pEnd)
- {
- UINT32 uSize = pEnd - pBufStr;
- CHXString sTemp(pBufStr, uSize);
- uSize = (uSize * 3) / 4; // we need 75% the space
-
- res = (*ppBuf)->SetSize(uSize);
- if (SUCCEEDED(res))
- {
-
- UCHAR* pDecodeBuf = (*ppBuf)->GetBuffer();
- HX_ASSERT(pDecodeBuf);
-
- UINT32 nLen = BinFrom64(sTemp,
- sTemp.GetLength()+1,
- pDecodeBuf);
- HX_ASSERT(nLen <= uSize);
- (*ppBuf)->SetSize(nLen);
-
- // go the the end of the buffer
- pBufStr = pEnd;
- }
- }
-
- if (FAILED(res))
- {
- HX_RELEASE(*ppBuf);
- return nRead;
- }
- }
- break;
- case 'p':
- {
- IUnknown** ppUnk = va_arg(vargs, IUnknown**);
- HX_ASSERT(ppUnk);
- if (!ppUnk)
- return nRead;
- // XXXSAB untested...
- char* pEnd = NULL;
- char tmpBuf[9];
- SafeStrCpy(tmpBuf, pBufStr, 8);
- tmpBuf[9] = 0;
- unsigned long val = strtoul(tmpBuf, &pEnd, 16);
- // if (sscanf(pBufStr, "%08x", ppUnk) != 1)
- if (pEnd && pEnd > tmpBuf)
- {
- *ppUnk = NULL;
- return nRead;
- }
- pBufStr = strchr(pBufStr, ';');
- }
- break;
- case 'v':
- {
- IHXValues** ppValues = va_arg(vargs, IHXValues**);
- if (!ppValues)
- {
- HX_ASSERT(FALSE);
- return nRead;
- }
- if (FAILED(UnpackValues(pBufStr, *ppValues)))
- {
- HX_RELEASE(*ppValues);
- return nRead;
- }
- }
- break;
- }
- // mark another param read
- nRead++;
- // find the next delimiter
- if (!pBufStr || *pBufStr != ';')
- return nRead;
- pBufStr++;
-
- pTemp++;
- }
-
- return nRead;
- }
- HX_RESULT
- PackValues(REF(CHXString) sBuffer, IHXValues* pValues)
- {
- if (!pValues)
- return HXR_FAIL;
-
- sBuffer = '[';
-
- ULONG32 uVal = 0;
- const char* pName = NULL;
- HX_RESULT res = pValues->GetFirstPropertyULONG32(pName, uVal);
- while (SUCCEEDED(res))
- {
- sBuffer += pName;
- sBuffer += '=';
- sBuffer.AppendULONG(uVal);
- sBuffer += ',';
-
- res = pValues->GetNextPropertyULONG32(pName, uVal);
- }
- IHXBuffer* pValBuf = NULL;
- res = pValues->GetFirstPropertyCString(pName, pValBuf);
- while (SUCCEEDED(res))
- {
- sBuffer += pName;
- sBuffer += "="";
- const char* pStr = (const char*)pValBuf->GetBuffer();
- while (*pStr)
- {
- // double-count chars we'll have to escape
- const char* pScary = strchr(kScaryChars, *pStr);
- if (pScary)
- {
- sBuffer += '\';
- sBuffer += kUnScaryChars[pScary - kScaryChars];
- }
- else
- {
- sBuffer += *pStr;
- }
- pStr++;
- }
- sBuffer += "",";
- HX_RELEASE(pValBuf);
- res = pValues->GetNextPropertyCString(pName, pValBuf);
- }
- res = pValues->GetFirstPropertyBuffer(pName, pValBuf);
- while (SUCCEEDED(res))
- {
- sBuffer += pName;
- sBuffer += '=';
- CHXString sTemp;
- UINT32 uSize = (pValBuf->GetSize() * 4) / 3 + 10;
- char* pTemp = (char*)sTemp.GetBuffer(uSize);
- if (pTemp)
- {
- // int nLen = BinTo64(pValBuf->GetBuffer(), uSize, pTemp);
- int nLen = BinTo64(pValBuf->GetBuffer(), pValBuf->GetSize(), pTemp);
- sTemp.ReleaseBuffer();
-
- HX_ASSERT(nLen >= 0);
- }
-
- HX_RELEASE(pValBuf);
-
- sBuffer += sTemp;
- sBuffer += ',';
- res = pValues->GetNextPropertyBuffer(pName, pValBuf);
- }
- UINT32 uSize = sBuffer.GetLength();
- sBuffer.SetAt(uSize-1, ']');
- return HXR_OK;
- }
- HX_RESULT
- Bufferize(REF(IHXBuffer*) pBuffer, void* pData, UINT32 uSize)
- {
- CHXBuffer* pCHXBuffer = new CHXBuffer;
- if (!pCHXBuffer)
- return HXR_OUTOFMEMORY;
- pCHXBuffer->AddRef();
- HX_RESULT res = pCHXBuffer->Set((UCHAR*)pData, uSize);
- if (SUCCEEDED(res))
- {
- pBuffer = (IHXBuffer*)pCHXBuffer;
- }
- else
- {
- HX_RELEASE(pCHXBuffer);
- }
-
- return res;
- }
- HX_RESULT
- UnpackValues(REF(const char*) pBuffer, REF(IHXValues*) pValues,
- BOOL bCreateValues)
- {
- HX_ASSERT(pBuffer);
- if (!pBuffer)
- return HXR_POINTER;
-
- if (*pBuffer != '[')
- return HXR_FAIL;
- if (bCreateValues)
- {
- CHXHeader* pCHXHeader = new CHXHeader;
- if (!pCHXHeader)
- return HXR_OUTOFMEMORY;
- pCHXHeader->AddRef();
- pValues = (IHXValues*)pCHXHeader;
- }
- else
- {
- // The input said to NOT create the IHXValues,
- // but use the passed-in one, so if we don't
- // *have* a passed-in one, then that's an error.
- if (!pValues)
- {
- return HXR_FAIL;
- }
- }
- // eat the '['
- pBuffer++;
- HX_RESULT res = HXR_FAIL;
- while (*pBuffer)
- {
- res = HXR_FAIL;
-
- // find the end of the property name
- const char* pEnd = strchr(pBuffer, '=');
- HX_ASSERT(pEnd);
- if (!pEnd)
- break;
- // parse the name
- CHXString sName(pBuffer, pEnd - pBuffer);
- pBuffer = pEnd+1;
- if (*pBuffer == '"')
- {
- pBuffer++;
- // looks like a string
- CHXString sValue;
-
- BOOL bEscaped = FALSE;
- while (*pBuffer != '"' && !bEscaped && *pBuffer)
- {
- if (bEscaped)
- {
- const char* pScary = strchr(kUnScaryChars, *pBuffer);
- HX_ASSERT(pScary);
- if (pScary)
- {
- sValue += kScaryChars[pScary - kUnScaryChars];
- }
- }
- else
- {
- if (*pBuffer == '\')
- {
- bEscaped = TRUE;
- }
- else
- {
- sValue += *pBuffer;
- }
- }
- pBuffer++;
- }
-
- // read the end quote!
- if (*pBuffer == '"')
- {
- pBuffer++;
-
- IHXBuffer* pStrBuf = NULL;
- res = Bufferize(pStrBuf,
- (void*)(const char*)sValue,
- sValue.GetLength()+1);
- if (SUCCEEDED(res))
- {
- res = pValues->SetPropertyCString(sName, pStrBuf);
- HX_RELEASE(pStrBuf);
- }
- }
- }
- else
- {
- // is it an int or base64 buffer?
- // how many digits do we have?
- size_t sz = strspn(pBuffer, kDecimals);
-
- // where does the next property begin?
- pEnd = strpbrk(pBuffer, ",]");
- HX_ASSERT(pEnd);
- if (!pEnd)
- break;
- // so were there *only* decimal digits?
- if (pBuffer + sz == pEnd)
- {
- CHXString sNumber(pBuffer, sz);
- ULONG32 uValue = strtoul((const char*) sNumber, NULL, 10);
- res = pValues->SetPropertyULONG32(sName, uValue);
- }
- else
- {
- // nope-- looks like a base64 buffer
- UINT32 uSize = pEnd - pBuffer;
- UINT32 uBinSize = (uSize * 3) / 4 + 10;
- res = HXR_OUTOFMEMORY;
- CHXBuffer* pTempBuf = new CHXBuffer;
- if (!pTempBuf)
- break;
- pTempBuf->AddRef();
- res = pTempBuf->SetSize(uBinSize);
- if (SUCCEEDED(res))
- {
- UCHAR* pTemp = pTempBuf->GetBuffer();
- UINT32 nLen = BinFrom64(pBuffer, uSize, pTemp);
- HX_ASSERT(nLen <= uBinSize && nLen > 0);
- pTempBuf->SetSize(nLen);
- res = pValues->SetPropertyBuffer(sName, pTempBuf);
- }
- HX_RELEASE(pTempBuf);
- }
- // advance to the end
- pBuffer = pEnd;
- }
- // did we fail during the property parsing?
- if (FAILED(res))
- break;
-
- // are we done?
- if (*pBuffer == ']')
- {
- pBuffer++;
- break;
- }
- // ready for next?
- if (*pBuffer != ',')
- {
- res = HXR_FAIL;
- break;
- }
- pBuffer++;
- }
- if (FAILED(res))
- HX_RELEASE(pValues);
- return res;
- }
- #ifdef _DEBUG
- void
- TestBufferPacking()
- {
- IHXBuffer* pParams = NULL;
- HX_RESULT res = PackBuffer(pParams, "uuuuuu", 0, 1, 2, 3, 4, 5);
- HX_ASSERT(SUCCEEDED(res));
- if (SUCCEEDED(res))
- {
- int nums[6];
- const char* pTemp = (const char*)pParams->GetBuffer();
- int nCount = UnpackBuffer(pTemp, "uuuuuu", nums, nums+1, nums+2, nums+3, nums+4, nums+5);
- HX_ASSERT(nCount == 6);
- HX_ASSERT(*pTemp == ' ');
- for (int i = 0; i < 6; i++)
- {
- HX_ASSERT(nums[i] == i);
- }
- HX_RELEASE(pParams);
- }
- res = PackBuffer(pParams, "uauau", 10, "foo", 20, "bar", 50);
- HX_ASSERT(SUCCEEDED(res));
- if (SUCCEEDED(res))
- {
- CHXString sArg2, sArg4;
- UINT32 nArg1, nArg3, nArg5;
- const char* pTemp = (const char*)pParams->GetBuffer();
- int nCount = UnpackBuffer(pTemp, "uauau", &nArg1, &sArg2, &nArg3, &sArg4, &nArg5);
- HX_ASSERT(nCount == 5);
- HX_ASSERT(*pTemp == ' ');
- HX_ASSERT(nArg1 == 10 && nArg3 == 20 && nArg5 == 50);
- HX_ASSERT(sArg2 == "foo" && sArg4 == "bar");
- HX_RELEASE(pParams);
- }
- res = PackBuffer(pParams, "fuda", TRUE, 666, 12.3456789, "foobar");
- HX_ASSERT(SUCCEEDED(res));
- if (SUCCEEDED(res))
- {
- BOOL bArg1;
- UINT32 nArg2;
- double dArg3;
- CHXString sArg4;
-
- const char* pTemp = (const char*)pParams->GetBuffer();
- int nCount = UnpackBuffer(pTemp, "fuda", &bArg1, &nArg2, &dArg3, &sArg4);
- HX_ASSERT(nCount == 4);
- HX_ASSERT(*pTemp == ' ');
- HX_ASSERT(bArg1 == TRUE && nArg2 == 666 && dArg3 == 12.3456789);
- HX_ASSERT(sArg4 == "foobar");
-
- HX_RELEASE(pParams);
- }
- CHXBuffer* pTempBuf = new CHXBuffer;
- HX_ASSERT(pTempBuf);
- if (pTempBuf)
- {
- HX_ADDREF(pTempBuf);
- res = pTempBuf->SetSize(4096);
- HX_ASSERT(SUCCEEDED(res));
- if (SUCCEEDED(res))
- {
- // fill up the buffer
- UCHAR* pData = pTempBuf->GetBuffer();
- int i;
- for (i = 0; i < 4096; i++)
- {
- pData[i] = i & 0xff;
- }
-
- res = PackBuffer(pParams, "ufbau", 69, FALSE, pTempBuf, "foobar", 666);
- HX_ASSERT(SUCCEEDED(res));
- if (SUCCEEDED(res))
- {
- UINT32 nArg1, nArg5;
- BOOL bArg2;
- IHXBuffer* pArg3;
- CHXString sArg4;
-
- const char* pTemp = (const char*)pParams->GetBuffer();
- int nCount = UnpackBuffer(pTemp, "ufbau", &nArg1, &bArg2, &pArg3, &sArg4, &nArg5);
- HX_ASSERT(nCount == 5);
- HX_ASSERT(*pTemp == ' ');
-
- HX_ASSERT(nArg1 == 69 && bArg2 == FALSE && nArg5 == 666);
- HX_ASSERT(sArg4 == "foobar");
- HX_ASSERT(pArg3 && pArg3->GetSize() == 4096);
- if (pArg3 && pArg3->GetSize() == 4096)
- {
- pData = pArg3->GetBuffer();
- for (i = 0; i < 4096; i++)
- {
- HX_ASSERT(pData[i] == (i & 0xff));
- }
- }
- HX_RELEASE(pArg3);
- }
- }
-
- HX_RELEASE(pTempBuf);
- }
- }
- #endif
- UINT32 GetBinaryPackedSize(IHXValues* pValues)
- {
- UINT32 ulRet = 0;
- if (pValues)
- {
- // Run through the ULONG32 properties
- const char* pszName = NULL;
- UINT32 ulValue = 0;
- HX_RESULT rv = pValues->GetFirstPropertyULONG32(pszName, ulValue);
- while (SUCCEEDED(rv))
- {
- // Add size of name/value type character: 'u'
- ulRet += 1;
- // Add size of name string plus NULL terminator
- ulRet += (UINT32) strlen(pszName) + 1;
- // Add 4 bytes for packing ULONG32
- ulRet += 4;
- // Get next ULONG32 prop
- rv = pValues->GetNextPropertyULONG32(pszName, ulValue);
- }
- // Run through the CString properties
- IHXBuffer* pValue = NULL;
- rv = pValues->GetFirstPropertyCString(pszName, pValue);
- while (SUCCEEDED(rv))
- {
- // Add size of name/value type character: 'c'
- ulRet += 1;
- // Add size of name string plus NULL terminator
- ulRet += (UINT32) strlen(pszName) + 1;
- // Add size of value string plus NULL terminator
- ulRet += strlen((const char*) pValue->GetBuffer()) + 1;
- // Get next CString prop
- HX_RELEASE(pValue);
- rv = pValues->GetNextPropertyCString(pszName, pValue);
- }
- // Run through the Buffer properties
- rv = pValues->GetFirstPropertyBuffer(pszName, pValue);
- while (SUCCEEDED(rv))
- {
- // Add size of name/value type character: 'b'
- ulRet += 1;
- // Add size of name string plus NULL terminator
- ulRet += (UINT32) strlen(pszName) + 1;
- // Add size of value buffer size (4 bytes)
- ulRet += 4;
- // Add size of value buffer
- ulRet += pValue->GetSize();
- // Get next Buffer prop
- HX_RELEASE(pValue);
- rv = pValues->GetNextPropertyBuffer(pszName, pValue);
- }
- }
- return ulRet;
- }
- HX_RESULT PackValuesBinary(IHXBuffer* pBuffer,
- IHXValues* pValues)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pValues && pBuffer)
- {
- // Make sure the buffer is big enough
- UINT32 ulMinSize = GetBinaryPackedSize(pValues);
- // Is our buffer big enough?
- if (ulMinSize && pBuffer->GetSize() >= ulMinSize)
- {
- // Ok, pack that puppy
- BYTE* pBuf = pBuffer->GetBuffer();
- if (pBuf)
- {
- // Clear the return value
- retVal = HXR_OK;
- // Run through the ULONG32 properties
- const char* pszName = NULL;
- UINT32 ulValue = 0;
- HX_RESULT rv = pValues->GetFirstPropertyULONG32(pszName, ulValue);
- while (SUCCEEDED(rv))
- {
- // Copy name/value type character: 'u'
- *pBuf++ = (BYTE) 'u';
- // Copy name string plus NULL terminator
- UINT32 ulBytes = (UINT32) strlen(pszName) + 1;
- memcpy(pBuf, pszName, ulBytes);
- pBuf += ulBytes;
- // Copy ULONG32 in big-endian format (high byte first)
- *pBuf++ = (BYTE) ((ulValue >> 24) & 0x000000FF);
- *pBuf++ = (BYTE) ((ulValue >> 16) & 0x000000FF);
- *pBuf++ = (BYTE) ((ulValue >> 8) & 0x000000FF);
- *pBuf++ = (BYTE) ( ulValue & 0x000000FF);
- // Get next ULONG32 prop
- rv = pValues->GetNextPropertyULONG32(pszName, ulValue);
- }
- // Run through the CString properties
- IHXBuffer* pValue = NULL;
- rv = pValues->GetFirstPropertyCString(pszName, pValue);
- while (SUCCEEDED(rv))
- {
- // Copy name/value type character: 'c'
- *pBuf++ = (BYTE) 'c';
- // Copy name string plus NULL terminator
- UINT32 ulBytes = (UINT32) strlen(pszName) + 1;
- memcpy(pBuf, pszName, ulBytes);
- pBuf += ulBytes;
- // Copy value string plus NULL terminator
- const char* pszValue = (const char*) pValue->GetBuffer();
- ulBytes = (UINT32) strlen(pszValue) + 1;
- memcpy(pBuf, pszValue, ulBytes);
- pBuf += ulBytes;
- // Get next CString prop
- HX_RELEASE(pValue);
- rv = pValues->GetNextPropertyCString(pszName, pValue);
- }
- // Run through the Buffer properties
- rv = pValues->GetFirstPropertyBuffer(pszName, pValue);
- while (SUCCEEDED(rv))
- {
- // Copy name/value type character: 'b'
- *pBuf++ = (BYTE) 'b';
- // Copy name string plus NULL terminator
- UINT32 ulBytes = (UINT32) strlen(pszName) + 1;
- memcpy(pBuf, pszName, ulBytes);
- pBuf += ulBytes;
- // Copy value buffer size in big-endian format
- UINT32 ulSize = pValue->GetSize();
- *pBuf++ = (BYTE) ((ulSize >> 24) & 0x000000FF);
- *pBuf++ = (BYTE) ((ulSize >> 16) & 0x000000FF);
- *pBuf++ = (BYTE) ((ulSize >> 8) & 0x000000FF);
- *pBuf++ = (BYTE) ( ulSize & 0x000000FF);
- // Copy value buffer
- memcpy(pBuf, pValue->GetBuffer(), ulSize);
- pBuf += ulSize;
- // Get next Buffer prop
- HX_RELEASE(pValue);
- rv = pValues->GetNextPropertyBuffer(pszName, pValue);
- }
- }
- }
- }
- return retVal;
- }
- HX_RESULT CreateBuffer(REF(IHXBuffer*) rpBuffer,
- IUnknown* pContext)
- {
- HX_RESULT retVal = HXR_FAIL;
- // Were we given a context?
- if (pContext)
- {
- // Yes, we have a context, use it to create the buffer
- //
- // Get the CCF
- IHXCommonClassFactory* pCCF = NULL;
- retVal = pContext->QueryInterface(IID_IHXCommonClassFactory,
- (void**) &pCCF);
- if (SUCCEEDED(retVal))
- {
- // Create a buffer
- HX_RELEASE(rpBuffer);
- retVal = pCCF->CreateInstance(CLSID_IHXBuffer,
- (void**) &rpBuffer);
- }
- HX_RELEASE(pCCF);
- }
- else
- {
- // No, we don't have a context, so use CHXBuffer
- CHXBuffer* pBuffer = new CHXBuffer();
- if (pBuffer)
- {
- // Assign the out parameter
- HX_RELEASE(rpBuffer);
- rpBuffer = (IHXBuffer*) pBuffer;
- rpBuffer->AddRef();
- // Clear the return value
- retVal = HXR_OK;
- }
- }
- return retVal;
- }
- HX_RESULT CreateValues(REF(IHXValues*) rpValues,
- IUnknown* pContext)
- {
- HX_RESULT retVal = HXR_FAIL;
- // Were we given a context?
- if (pContext)
- {
- // Yes, we have a context, use it to create the IHXValues
- //
- // Get the CCF
- IHXCommonClassFactory* pCCF = NULL;
- retVal = pContext->QueryInterface(IID_IHXCommonClassFactory,
- (void**) &pCCF);
- if (SUCCEEDED(retVal))
- {
- // Create an IHXValues
- HX_RELEASE(rpValues);
- retVal = pCCF->CreateInstance(CLSID_IHXValues,
- (void**) &rpValues);
- }
- HX_RELEASE(pCCF);
- }
- else
- {
- // No, we don't have a context, so use CHXBuffer
- CHXHeader* pValues = new CHXHeader();
- if (pValues)
- {
- // Assign the out parameter
- HX_RELEASE(rpValues);
- rpValues = (IHXValues*) pValues;
- rpValues->AddRef();
- // Clear the return value
- retVal = HXR_OK;
- }
- }
- return retVal;
- }
- HX_RESULT CreateStringBuffer(REF(IHXBuffer*) rpBuffer,
- const char* pszStr,
- IUnknown* pContext)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pszStr)
- {
- // Create a buffer
- IHXBuffer* pBuffer = NULL;
- retVal = CreateBuffer(pBuffer, pContext);
- if (SUCCEEDED(retVal))
- {
- // Set the string into the buffer
- retVal = pBuffer->Set((const UCHAR*) pszStr, strlen(pszStr) + 1);
- if (SUCCEEDED(retVal))
- {
- // Assign the out parameters
- HX_RELEASE(rpBuffer);
- rpBuffer = pBuffer;
- rpBuffer->AddRef();
- }
- }
- HX_RELEASE(pBuffer);
- }
- return retVal;
- }
- HX_RESULT SetCStringProperty(IHXValues* pValues,
- const char* pszName,
- const char* pszValue,
- IUnknown* pContext,
- BOOL bSetAsBufferProp)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pValues && pszName && pszValue)
- {
- // Create value buffer
- IHXBuffer* pValue = NULL;
- retVal = CreateStringBuffer(pValue, pszValue, pContext);
- if (SUCCEEDED(retVal))
- {
- // Set the property
- if (bSetAsBufferProp)
- {
- retVal = pValues->SetPropertyBuffer(pszName, pValue);
- }
- else
- {
- retVal = pValues->SetPropertyCString(pszName, pValue);
- }
- }
- HX_RELEASE(pValue);
- }
- return retVal;
- }
- HX_RESULT SetCStringPropertyWithNullTerm(IHXValues* pValues,
- const char* pszName,
- BYTE* pBuf,
- UINT32 ulLen,
- IUnknown* pContext,
- BOOL bSetAsBufferProp)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pValues && pszName && pBuf && ulLen)
- {
- // Create value buffer
- IHXBuffer* pValue = NULL;
- retVal = CreateBuffer(pValue, pContext);
- if (SUCCEEDED(retVal))
- {
- // Set the buffer size
- retVal = pValue->SetSize(ulLen + 1);
- if (SUCCEEDED(retVal))
- {
- // Get the buffer pointer
- BYTE* pValBuf = pValue->GetBuffer();
- if (pValBuf)
- {
- // memcpy the buffer
- memcpy(pValBuf, pBuf, ulLen); /* Flawfinder: ignore */
- // Add the NULL-terminator
- pValBuf[ulLen] = (BYTE) ' ';
- // Are we setting as a buffer property?
- if (bSetAsBufferProp)
- {
- retVal = pValues->SetPropertyBuffer(pszName, pValue);
- }
- else
- {
- retVal = pValues->SetPropertyCString(pszName, pValue);
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- }
- HX_RELEASE(pValue);
- }
- return retVal;
- }
- HX_RESULT CreateNullTermBuffer(BYTE* pBuf,
- UINT32 ulLen,
- char** ppNTBuf)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pBuf && ulLen && ppNTBuf)
- {
- char* pTmp = new char [ulLen+1];
- if (pTmp)
- {
- // Copy pBuf into the new buf
- memcpy(pTmp, pBuf, ulLen); /* Flawfinder: ignore */
- // NULL-terminate the new buf
- pTmp[ulLen] = ' ';
- // Set the out parameter
- *ppNTBuf = pTmp;
- // Clear the return value
- retVal = HXR_OK;
- }
- }
- return retVal;
- }
- HX_RESULT SetBufferProperty(IHXValues* pValues,
- const char* pszName,
- BYTE* pBuf,
- UINT32 ulLen,
- IUnknown* pContext)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pValues && pszName && pBuf && ulLen)
- {
- // Create value buffer
- IHXBuffer* pValue = NULL;
- retVal = CreateBuffer(pValue, pContext);
- if (SUCCEEDED(retVal))
- {
- // Set the buffer
- retVal = pValue->Set(pBuf, ulLen);
- if (SUCCEEDED(retVal))
- {
- // Set the property
- retVal = pValues->SetPropertyBuffer(pszName, pValue);
- }
- }
- HX_RELEASE(pValue);
- }
- return retVal;
- }
- HX_RESULT UnpackPropertyULONG32(IHXValues* pValues,
- REF(BYTE*) rpBuf,
- BYTE* pLimit,
- IUnknown* pContext)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pValues && rpBuf && pLimit &&
- rpBuf < pLimit && rpBuf[0] == 'u')
- {
- // Skip the 'u' type character
- rpBuf++;
- // Save the beginning of the string
- const char* pszName = (const char*) rpBuf;
- // Search until we find either a NULL or
- // the end of the buffer
- while (rpBuf < pLimit && *rpBuf != 0) ++rpBuf;
- // Did we get a NULL terminator?
- if (rpBuf < pLimit && *rpBuf == 0)
- {
- // We know now that pszName is a valid string
- //
- // Skip the NULL terminator
- ++rpBuf;
- // Now get the ULONG32
- if (rpBuf + 4 <= pLimit)
- {
- // Unpack in big-endian form
- UINT32 ulValue = ((rpBuf[0] << 24) & 0xFF000000) |
- ((rpBuf[1] << 16) & 0x00FF0000) |
- ((rpBuf[2] << 8) & 0x0000FF00) |
- ( rpBuf[3] & 0x000000FF);
- // Skip the ULONG32
- rpBuf += 4;
- // Set the property
- retVal = pValues->SetPropertyULONG32(pszName, ulValue);
- }
- }
- }
- return retVal;
- }
- HX_RESULT UnpackPropertyCString(IHXValues* pValues,
- REF(BYTE*) rpBuf,
- BYTE* pLimit,
- IUnknown* pContext)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pValues && rpBuf && pLimit &&
- rpBuf < pLimit && rpBuf[0] == 'c')
- {
- // Skip the 'c' type character
- rpBuf++;
- // Save the beginning of the string
- const char* pszName = (const char*) rpBuf;
- // Search until we find either a NULL or
- // the end of the buffer
- while (rpBuf < pLimit && *rpBuf != 0) ++rpBuf;
- // Did we get a NULL terminator?
- if (rpBuf < pLimit && *rpBuf == 0)
- {
- // We know now that pszName is a valid string
- //
- // Skip the NULL terminator
- ++rpBuf;
- // Save the beginning of the value string
- const char* pszValue = (const char*) rpBuf;
- // Search until we find either a NULL or
- // the end of the buffer
- while (rpBuf < pLimit && *rpBuf != 0) ++rpBuf;
- // Did we get a NULL terminator?
- if (rpBuf < pLimit && *rpBuf == 0)
- {
- // Skip the NULL terminator
- ++rpBuf;
- // We know now that pszValue is a valid string, so
- // make an IHXBuffer out of it
- IHXBuffer* pValue = NULL;
- retVal = CreateStringBuffer(pValue, pszValue, pContext);
- if (SUCCEEDED(retVal))
- {
- // Set the property
- retVal = pValues->SetPropertyCString(pszName, pValue);
- }
- HX_RELEASE(pValue);
- }
- }
- }
- return retVal;
- }
- HX_RESULT UnpackPropertyBuffer(IHXValues* pValues,
- REF(BYTE*) rpBuf,
- BYTE* pLimit,
- IUnknown* pContext)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pValues && rpBuf && pLimit &&
- rpBuf < pLimit && rpBuf[0] == 'b')
- {
- // Skip the 'b' type character
- rpBuf++;
- // Save the beginning of the string
- const char* pszName = (const char*) rpBuf;
- // Search until we find either a NULL or
- // the end of the buffer
- while (rpBuf < pLimit && *rpBuf != 0) ++rpBuf;
- // Did we get a NULL terminator?
- if (rpBuf < pLimit && *rpBuf == 0)
- {
- // We know now that pszName is a valid string
- //
- // Skip the NULL terminator
- ++rpBuf;
- // Do we have enough bytes to get the buffer length?
- if (rpBuf + 4 <= pLimit)
- {
- // Unpack the buffer length in big-endian form
- UINT32 ulLen = ((rpBuf[0] << 24) & 0xFF000000) |
- ((rpBuf[1] << 16) & 0x00FF0000) |
- ((rpBuf[2] << 8) & 0x0000FF00) |
- ( rpBuf[3] & 0x000000FF);
- // Skip the buffer length
- rpBuf += 4;
- // Do we have enough bytes to get the buffer?
- if (rpBuf + ulLen <= pLimit)
- {
- // Create a buffer
- IHXBuffer* pValue = NULL;
- retVal = CreateBuffer(pValue, pContext);
- if (SUCCEEDED(retVal))
- {
- // Set the buffer
- retVal = pValue->Set(rpBuf, ulLen);
- if (SUCCEEDED(retVal))
- {
- // Skip the buffer bytes
- rpBuf += ulLen;
- // Set the property
- retVal = pValues->SetPropertyBuffer(pszName,
- pValue);
- }
- }
- HX_RELEASE(pValue);
- }
- }
- }
- }
- return retVal;
- }
- HX_RESULT UnpackValuesBinary(IHXValues* pValues,
- IHXBuffer* pBuffer,
- IUnknown* pContext)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pValues && pBuffer)
- {
- retVal = UnpackValuesBinary(pValues,
- pBuffer->GetBuffer(),
- pBuffer->GetSize(),
- pContext);
- }
- return retVal;
- }
- HX_RESULT UnpackValuesBinary(IHXValues* pValues,
- BYTE* pBuf,
- UINT32 ulLen,
- IUnknown* pContext)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pBuf && ulLen)
- {
- // Get the pointer limit
- BYTE* pLimit = pBuf + ulLen;
- // Make sure this is not string format
- if (pBuf[0] != '[')
- {
- // Clear the return value
- retVal = HXR_OK;
- // Loop through the buffer, unpacking name/value pairs
- while (pBuf < pLimit && SUCCEEDED(retVal))
- {
- // Get a property type code
- char c = (char) pBuf[0];
- // Save the buffer pointer
- BYTE* pCur = pBuf;
- // Switch based on type
- switch (c)
- {
- case 'u':
- retVal = UnpackPropertyULONG32(pValues, pBuf,
- pLimit, pContext);
- break;
- case 'c':
- retVal = UnpackPropertyCString(pValues, pBuf,
- pLimit, pContext);
- break;
- case 'b':
- retVal = UnpackPropertyBuffer(pValues, pBuf,
- pLimit, pContext);
- break;
- default:
- retVal = HXR_FAIL;
- break;
- }
- // Do a sanity check: if we succeeded,
- // then we must have advanced the pointer.
- // This will prevent an infinite loop.
- if (SUCCEEDED(retVal) && pCur == pBuf)
- {
- retVal = HXR_FAIL;
- }
- }
- }
- }
- return retVal;
- }
- HX_RESULT PackValues(REF(IHXBuffer*) rpBuffer,
- IHXValues* pValues,
- BOOL bPackBinary,
- IUnknown* pContext)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pValues)
- {
- // Create an output IHXBuffer
- IHXBuffer* pBuffer = NULL;
- retVal = CreateBuffer(pBuffer, pContext);
- if (SUCCEEDED(retVal))
- {
- // Are we supposed to pack this in binary form?
- if (bPackBinary)
- {
- // Pack in binary form
- //
- // First get the size necessary to pack it in binary form
- UINT32 ulBinPackSize = GetBinaryPackedSize(pValues);
- if (ulBinPackSize)
- {
- // Make the buffer this size
- retVal = pBuffer->SetSize(ulBinPackSize);
- if (SUCCEEDED(retVal))
- {
- // Binary pack the buffer
- retVal = PackValuesBinary(pBuffer, pValues);
- if (SUCCEEDED(retVal))
- {
- // Copy the out parameter
- HX_RELEASE(rpBuffer);
- rpBuffer = pBuffer;
- rpBuffer->AddRef();
- }
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- else
- {
- // Pack in a string
- CHXString cTmp;
- retVal = PackValues(cTmp, pValues);
- if (SUCCEEDED(retVal))
- {
- // Now just copy the string into the IHXBuffer
- retVal = pBuffer->Set((const UCHAR*) (const char*) cTmp,
- cTmp.GetLength() + 1);
- if (SUCCEEDED(retVal))
- {
- // Set the out parameter
- HX_RELEASE(rpBuffer);
- rpBuffer = pBuffer;
- rpBuffer->AddRef();
- }
- }
- }
- }
- HX_RELEASE(pBuffer);
- }
- return retVal;
- }
- HX_RESULT UnpackValues(REF(IHXValues*) rpValues,
- IHXBuffer* pBuffer,
- IUnknown* pContext)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pBuffer)
- {
- retVal = UnpackValues(rpValues,
- pBuffer->GetBuffer(),
- pBuffer->GetSize(),
- pContext);
- }
- return retVal;
- }
- HX_RESULT UnpackValues(REF(IHXValues*) rpValues,
- BYTE* pBuf,
- UINT32 ulLen,
- IUnknown* pContext)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pBuf && ulLen)
- {
- // Create an output IHXValues
- IHXValues* pValues = NULL;
- retVal = CreateValues(pValues, pContext);
- if (SUCCEEDED(retVal))
- {
- // Get the string
- const char* pszBuffer = (const char*) pBuf;
- // Is this packed in binary or text? If it's in text
- // form, then it will have a '[' as the first character
- if (pszBuffer[0] != '[')
- {
- // The buffer is binary packed
- retVal = UnpackValuesBinary(pValues, pBuf, ulLen, pContext);
- }
- else
- {
- // The buffer is text packed
- retVal = UnpackValues(pszBuffer, pValues, FALSE);
- }
- if (SUCCEEDED(retVal))
- {
- // Assign the out parameter
- HX_RELEASE(rpValues);
- rpValues = pValues;
- rpValues->AddRef();
- }
- }
- HX_RELEASE(pValues);
- }
- return retVal;
- }
- // This method checks to see if all the properties
- // in pValues1 are in pValues2 and that the value
- // of these properties is indentical. pValues2,
- // however, could still have properties that pValues1
- // doesn't have. AreValuesIdentical() calls
- // AreValuesInclusiveIdentical() in both directions,
- // which establishes absolute equality if both
- // are true.
- BOOL AreValuesInclusiveIdentical(IHXValues* pValues1,
- IHXValues* pValues2)
- {
- BOOL bRet = FALSE;
- if (pValues1 && pValues2)
- {
- // Assume that they are equal, and breakout
- // at the first inequality
- bRet = TRUE;
- // Check the ULONG32 properties
- const char* pszName = NULL;
- UINT32 ulValue1 = 0;
- HX_RESULT rv = pValues1->GetFirstPropertyULONG32(pszName, ulValue1);
- while (SUCCEEDED(rv) && bRet)
- {
- // Lookup this property in pValues2
- UINT32 ulValue2 = 0;
- HX_RESULT rv2 = pValues2->GetPropertyULONG32(pszName, ulValue2);
- // Check for a match
- if (FAILED(rv2) || ulValue1 != ulValue2)
- {
- bRet = FALSE;
- }
- // Get next ULONG32 property
- rv = pValues1->GetNextPropertyULONG32(pszName, ulValue1);
- }
- if (bRet)
- {
- // Check the CString properties
- IHXBuffer* pValue1 = NULL;
- rv = pValues1->GetFirstPropertyCString(pszName, pValue1);
- while (SUCCEEDED(rv) && bRet)
- {
- // Lookup this property in pValues2
- IHXBuffer* pValue2 = NULL;
- HX_RESULT rv2 = pValues2->GetPropertyCString(pszName, pValue2);
- if (FAILED(rv2) ||
- strcmp((const char*) pValue1->GetBuffer(),
- (const char*) pValue2->GetBuffer()) != 0)
- {
- bRet = FALSE;
- }
- HX_RELEASE(pValue2);
- // Get next CString prop
- HX_RELEASE(pValue1);
- rv = pValues1->GetNextPropertyCString(pszName, pValue1);
- }
- if (bRet)
- {
- // Check the buffer properties
- rv = pValues1->GetFirstPropertyBuffer(pszName, pValue1);
- while (SUCCEEDED(rv) && bRet)
- {
- // Lookup this property in pValues2
- IHXBuffer* pValue2 = NULL;
- HX_RESULT rv2 = pValues2->GetPropertyBuffer(pszName, pValue2);
- if (FAILED(rv2) ||
- pValue1->GetSize() != pValue2->GetSize() ||
- memcmp((const void*) pValue1->GetBuffer(),
- (const void*) pValue2->GetBuffer(),
- pValue1->GetSize()) != 0)
- {
- bRet = FALSE;
- }
- HX_RELEASE(pValue2);
- // Get next Buffer prop
- HX_RELEASE(pValue1);
- rv = pValues1->GetNextPropertyBuffer(pszName, pValue1);
- }
- }
- }
- }
- return bRet;
- }
- BOOL AreValuesIdentical(IHXValues* pValues1,
- IHXValues* pValues2)
- {
- BOOL bRet = FALSE;
- // Check if all the properties in pValues1 are
- // in pValues2 and are identical
- bRet = AreValuesInclusiveIdentical(pValues1, pValues2);
- if (bRet)
- {
- // Check if all the properties in pValues2 are
- // in pValues1 and are identical
- bRet = AreValuesInclusiveIdentical(pValues2, pValues1);
- }
- return bRet;
- }
- #ifdef _DEBUG
- HX_RESULT TestValuesPacking(IUnknown* pContext)
- {
- HX_RESULT retVal = HXR_OK;
- // Create an IHXValues
- IHXValues* pValues = NULL;
- retVal = CreateValues(pValues, pContext);
- if (SUCCEEDED(retVal))
- {
- // Populate this IHXValues
- pValues->SetPropertyULONG32("ulong1", 42);
- pValues->SetPropertyULONG32("ulong2", 0xbaadf00d);
- SetCStringProperty(pValues, "cstring1",
- "Rock the Casbah", pContext);
- SetCStringProperty(pValues, "cstring2",
- "Sandinista", pContext);
- UINT32 ulBuf1Len = 128;
- BYTE* pBuf1 = new BYTE [ulBuf1Len];
- if (pBuf1)
- {
- // Fill the buffer with random byte values
- srand(time(NULL));
- for (UINT32 i = 0; i < ulBuf1Len; i++)
- {
- UINT32 ulVal = (UINT32) rand();
- pBuf1[i] = (BYTE) (ulVal & 0x000000FF);
- }
- SetBufferProperty(pValues, "buffer1", pBuf1, ulBuf1Len, pContext);
- // Pack it as text
- IHXBuffer* pBufferText = NULL;
- retVal = PackValues(pBufferText, pValues, FALSE, pContext);
- if (SUCCEEDED(retVal))
- {
- // Now unpack it
- IHXValues* pValuesTextOut = NULL;
- retVal = UnpackValues(pValuesTextOut, pBufferText, pContext);
- if (SUCCEEDED(retVal))
- {
- // Compare them
- if (AreValuesIdentical(pValues, pValuesTextOut))
- {
- // Now pack as binary
- IHXBuffer* pBufferBinary = NULL;
- retVal = PackValues(pBufferBinary, pValues,
- TRUE, pContext);
- if (SUCCEEDED(retVal))
- {
- // Now unpack it
- IHXValues* pValuesBinaryOut = NULL;
- retVal = UnpackValues(pValuesBinaryOut,
- pBufferBinary, pContext);
- if (SUCCEEDED(retVal))
- {
- // Compare them
- if (!AreValuesIdentical(pValues,
- pValuesBinaryOut))
- {
- // Oops - they are not the same
- retVal = HXR_FAIL;
- }
- }
- HX_RELEASE(pValuesBinaryOut);
- }
- HX_RELEASE(pBufferBinary);
- }
- else
- {
- // Oops - they are not the same
- retVal = HXR_FAIL;
- }
- }
- HX_RELEASE(pValuesTextOut);
- }
- HX_RELEASE(pBufferText);
- }
- HX_VECTOR_DELETE(pBuf1);
- }
- HX_RELEASE(pValues);
- return retVal;
- }
- #endif