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