📄 pckunpck.cpp
字号:
// 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -