📄 parse.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Module Name:
parse.cpp
Abstract:
Notes:
--*/
#include "precomp.h"
#ifndef _PREFAST_
#pragma warning( disable: 4068 )
#endif
BOOL EncodedStringSizeToUnicodeStringSize(ENCODING_TYPE enc, size_t cbIn, size_t &cbOut)
{
BOOL bResult = TRUE;
switch (enc)
{
case ENCODING_GSMDEFAULT:
// In GSM mode, 1 byte of data maps to 2-bytes (1 char) of unicode
cbOut = cbIn<<1;
break;
case ENCODING_GSMDEFAULT_HEX:
// In hex mode, 2 bytes of hex data map to 2-bytes (1 char) of unicode
cbOut = cbIn;
break;
case ENCODING_GSMDEFAULT_UNICODE:
// in unicode mode, 4 chars map to 2-bytes (1 char) of unicode
cbOut = ( cbIn / 2 );
break;
case ENCODING_GSMDEFAULT_UTF8:
// in utf-8 mode, 1 char map to at most 2-bytes (1 char) of unicode
cbOut = cbIn<<1;
break;
default:
bResult = FALSE;
}
return bResult;
}
//
// Determine if a string starts with another
//
BOOL MatchStringBeginning(const LPCSTR szString, const LPCSTR szMatch, LPCSTR& rszPointer)
{
// FUNCTION_TRACE(MatchStringBeginning);
BOOL fRet = FALSE;
LPCSTR szTemp = strstr(szString, szMatch);
if (!szTemp)
{
goto End;
}
fRet = (szTemp == szString);
if (fRet)
{
rszPointer = szString + strlen(szMatch);
}
End:
return fRet;
}
//
// Determine if a string matches the end of another
//
BOOL MatchStringEnd(const LPCSTR szString, const LPCSTR szMatch, LPCSTR& rszPointer)
{
// FUNCTION_TRACE(MatchStringEnd);
UINT cbString = strlen(szString);
UINT cbMatch = strlen(szMatch);
BOOL fRet = FALSE;
if (cbString >= cbMatch)
{
fRet = !strcmp(szString + cbString - cbMatch, szMatch);
}
if (fRet)
{
rszPointer = szString + cbString;
DEBUGCHK('\0' == *rszPointer);
}
return fRet;
}
//
// Determine if a string contains another
//
BOOL MatchStringAnywhere(const LPCSTR szString, const LPCSTR szMatch, LPCSTR& rszPointer)
{
// FUNCTION_TRACE(MatchStringAnywhere);
BOOL fRet = FALSE;
LPCSTR szTemp = strstr(szString, szMatch);
if (!szTemp)
{
goto End;
}
rszPointer = szTemp + strlen(szMatch);
fRet = TRUE;
End:
return fRet;
}
//
// Determine if an array of bytes matches the end of another
//
BOOL MatchBytesEnd(const BYTE* const pbBytes, const UINT cbBytes, const BYTE* const pbMatch, const UINT cbMatch,
const BYTE*& rpbPointer)
{
// FUNCTION_TRACE(MatchBytesEnd);
BOOL fRet = FALSE;
if (cbBytes >= cbMatch)
{
fRet = !memcmp(pbBytes + cbBytes - cbMatch, pbMatch, cbMatch);
}
if (fRet)
{
rpbPointer = pbBytes + cbBytes;
}
return fRet;
}
//
// Determine if an array of bytes contains another
//
BOOL MatchBytesAnywhere(const BYTE* const pbBytes, const UINT cbBytes, const BYTE* const pbMatch, const UINT cbMatch,
const BYTE*& rpbPointer)
{
// FUNCTION_TRACE(MatchBytesAnywhere);
const BYTE* pbWalk = pbBytes;
const BYTE* pbEnd = pbBytes + cbBytes;
BOOL fRet = FALSE;
while (pbWalk < pbEnd)
{
if (!memcmp(pbWalk, pbMatch, cbMatch))
{
rpbPointer = pbWalk + cbMatch;
fRet = TRUE;
break;
}
pbWalk++;
}
return fRet;
}
BOOL ParseDWord(const LPCSTR szData, const BOOL fLeadingZerosAllowed, DWORD& rdw, LPCSTR& rszPointer)
{
// FUNCTION_TRACE(ParseDWord);
int nLeadingDigit = -1;
BOOL Found=FALSE;
// Skip any spaces
SkipChars(szData, rszPointer, " ");
rdw = 0;
while (*rszPointer >= '0' && *rszPointer <= '9')
{
if (!fLeadingZerosAllowed)
{
// Test for leading 0s
if (-1 == nLeadingDigit)
{
// Leading digit hasn't been set yet -- set it now
nLeadingDigit = *rszPointer - '0';
}
else if (!nLeadingDigit)
{
// Leading digit is 0 and we got another digit
// This means that we have leading 0s -- reset the pointer and punt
Found=FALSE;
goto Error;
}
}
rdw = rdw * 10 + (*rszPointer - '0');
rszPointer++;
Found=TRUE;
}
// Skip past any spaces
SkipChars(rszPointer, rszPointer, " ");
Error:
if (!Found)
{
rszPointer = szData;
}
return Found;
}
BOOL ParseHexDWord(const LPCSTR szData, const BOOL fLeadingZerosAllowed, DWORD& rdw, LPCSTR& rszPointer)
{
// FUNCTION_TRACE(ParseHexDWord);
int nLeadingDigit = -1;
UINT nDigit;
rszPointer = szData;
rdw = 0;
while ((*rszPointer >= '0' && *rszPointer <= '9') ||
(*rszPointer >= 'A' && *rszPointer <= 'F') ||
(*rszPointer >= 'a' && *rszPointer <= 'f'))
{
if (!fLeadingZerosAllowed)
{
// Test for leading 0s
if (-1 == nLeadingDigit)
{
// Leading digit hasn't been set yet -- set it now
nLeadingDigit = *rszPointer - '0';
}
else if (!nLeadingDigit)
{
// Leading digit is 0 and we got another digit
// This means that we have leading 0s -- reset the pointer and punt
rszPointer = szData;
goto Error;
}
}
// Calculate the digit value
if (*rszPointer >= 'A' && *rszPointer <= 'F')
{
nDigit = 10 + *rszPointer - 'A';
}
else if (*rszPointer >= 'a' && *rszPointer <= 'f')
{
nDigit = 10 + *rszPointer - 'a';
}
else
{
nDigit = *rszPointer - '0';
}
rdw = rdw * 16 + nDigit;
rszPointer++;
}
Error:
return (rszPointer > szData);
}
//
//
//
BOOL ParseUInt(const LPCSTR szData, const BOOL fLeadingZerosAllowed, UINT& rnInt, LPCSTR& rszPointer)
{
return ParseDWord(szData, fLeadingZerosAllowed, (DWORD&)rnInt, rszPointer);
}
//
//
//
BOOL ParseIntAsUInt(const LPCSTR szData, UINT& rnInit, LPCSTR& rszPointer)
{
BOOL fNegative = FALSE;
rszPointer = szData;
if (*rszPointer == '-')
{
fNegative = TRUE;
++rszPointer;
}
if (!ParseUInt(rszPointer, FALSE, rnInit, rszPointer))
return FALSE;
if (fNegative)
{
rnInit = ~rnInit + 1;
}
return TRUE;
}
//
//
//
BOOL ParseUIntAndVerifyAbove(const LPCSTR szData, const BOOL fLeadingZerosAllowed, UINT nUpperBound, UINT& rnInt, LPCSTR& rszPointer)
{
BOOL fRet;
// Parse the number
fRet = ParseUInt(szData, fLeadingZerosAllowed, rnInt, rszPointer);
// Verify that the number is greater than the upper bound
if (fRet && rnInt >= nUpperBound)
{
fRet = FALSE;
rszPointer = szData;
}
return fRet;
}
//
//
//
BOOL ParseUIntAndVerifyBelow(const LPCSTR szData, const BOOL fLeadingZerosAllowed, UINT nLowerBound, UINT& rnInt, LPCSTR& rszPointer)
{
BOOL fRet;
// Parse the number
fRet = ParseUInt(szData, fLeadingZerosAllowed, rnInt, rszPointer);
// Verify that the number is less than the lower bound
if (fRet && rnInt <= nLowerBound)
{
fRet = FALSE;
rszPointer = szData;
}
return fRet;
}
//
//
//
BOOL ParseHexUInt(const LPCSTR szData, const BOOL fLeadingZerosAllowed, UINT& rnInt, LPCSTR& rszPointer)
{
return ParseHexDWord(szData, fLeadingZerosAllowed, (DWORD&)rnInt, rszPointer);
}
BOOL ParseFixedPoint(const LPCSTR szData, DWORD &rdwFixedPoint, LPCSTR& rszPointer)
{
// FUNCTION_TRACE(ParseDouble);
UINT dwIntPart;
UINT dwFracPart;
LPCSTR szFracStart;
rszPointer = szData;
// Parse the integer part
if (!ParseUInt(rszPointer, TRUE, dwIntPart, rszPointer))
{
goto Error;
}
// Shift up by 16 bits
dwIntPart <<= 16;
// Parse decimal separator ("." -- this is what GSM uses)
if ('.' != *rszPointer)
{
goto Error;
}
// Advance pointer past decimal point
rszPointer++;
// Parse the fractional part
szFracStart=rszPointer;
if (!ParseUInt(rszPointer, TRUE, dwFracPart, rszPointer))
{
goto Error;
}
// Shift up by 16 bits
dwFracPart <<= 16;
// Now normalize to lie in the lowest 16 bits.
UINT dwDivisor;
dwDivisor = 1;
while (szFracStart<rszPointer)
{
dwDivisor*=10;
szFracStart++;
}
dwFracPart/=dwDivisor;
rdwFixedPoint = dwIntPart+dwFracPart;
Error:
return (rszPointer > szData);
}
#if 0 // Not currently used
//
// NOTE: parsing code for the decimal part is imprecise;
// if higher precision needed, re-write this code.
//
BOOL ParseDouble(const LPCSTR szData, double& rdbDouble, LPCSTR& rszPointer)
{
// FUNCTION_TRACE(ParseDouble);
UINT nIntPart;
double dbDivisor;
rszPointer = szData;
rdbDouble = 0.0;
// Parse the integer part
if (!ParseUInt(rszPointer, TRUE, nIntPart, rszPointer))
{
goto Error;
}
rdbDouble = (double)nIntPart;
// Parse decimal separator ("." -- this is what GSM uses)
if ('.' != *rszPointer)
{
goto Error;
}
// Advance pointer past decimal point
rszPointer++;
// Parse decimal part
dbDivisor = 10.0;
while (*rszPointer >= '0' && *rszPointer <= '9')
{
rdbDouble += (*rszPointer - '0') / dbDivisor;
dbDivisor *= 10;
rszPointer++;
}
Error:
return (rszPointer > szData);
}
#endif
//
//
//
BOOL ParseString(const LPCSTR szData, __out_bcount( cbOut ) const LPSTR szOut, const UINT cbOut, LPCSTR& rszPointer)
{
// FUNCTION_TRACE(ParseString);
LPSTR pchOut;
LPCSTR szOutEnd;
BOOL fRet = FALSE;
rszPointer = szData;
pchOut = szOut;
szOutEnd = szOut + cbOut;
// Skip over the leading quote
if (*rszPointer != '\"')
{
goto Error;
}
rszPointer++;
while (pchOut < szOutEnd - 1)
{
if (!*rszPointer)
{
// We hit the end of the string -- fail
goto Error;
}
else if ('\"' == *rszPointer)
{
// Terminating quote -- skip over it and bail out
rszPointer++;
fRet = TRUE;
break;
}
else
{
*pchOut++ = *rszPointer++;
}
}
*pchOut = '\0';
Error:
if (!fRet)
{
rszPointer = szData;
}
return fRet;
}
#define CAST_CTOW(c) ((WCHAR)((BYTE)(c)))
#pragma prefast( suppress: 5457, "Currently PREfast does not support __out_ecount( pwszOutEnd - pwszOut )." )
BOOL ParseStringGSMW(LPCSTR pszIn, const LPCSTR pszInEnd, LPWSTR pwszOut, const LPCWSTR pwszOutEnd)
{
// Handle empty string
if (pszIn==pszInEnd)
{
*pwszOut = L'\0';
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -