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