506 lines
11 KiB
C++
506 lines
11 KiB
C++
/*++
|
||
|
||
Copyright (c) 1996 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
parsers.cxx
|
||
|
||
Abstract:
|
||
|
||
Common text parsing functions (generally moved here from other protocols)
|
||
|
||
Contents:
|
||
ExtractWord
|
||
ExtractDword
|
||
ExtractInt
|
||
SkipWhitespace
|
||
SkipSpaces
|
||
SkipLine
|
||
FindToken
|
||
NiceNum
|
||
|
||
Author:
|
||
|
||
Richard L Firth (rfirth) 03-Jul-1996
|
||
|
||
Revision History:
|
||
|
||
03-Jul-1996 rfirth
|
||
Created
|
||
|
||
--*/
|
||
|
||
#include <wininetp.h>
|
||
|
||
//
|
||
// functions
|
||
//
|
||
|
||
|
||
BOOL
|
||
ExtractWord(
|
||
IN OUT LPSTR* pString,
|
||
IN DWORD NumberLength,
|
||
OUT LPWORD pConvertedNumber
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
pulls a <NumberLength> character number out of a string.
|
||
|
||
Assumes: 1. The number to be converted is an unsigned short
|
||
2. A whole number is contained within *pString
|
||
|
||
Arguments:
|
||
|
||
pString - pointer to pointer to string from which to get number
|
||
|
||
NumberLength - number of characters that comprise number string, if
|
||
not equal to 0, else if 0, we don't know the length
|
||
of the number string a priori
|
||
|
||
pConvertedNumber - pointer to variable where converted number written
|
||
|
||
Return Value:
|
||
|
||
BOOL
|
||
TRUE - number converted OK
|
||
|
||
FALSE - one of the characters in the number is not a digit
|
||
|
||
--*/
|
||
|
||
{
|
||
WORD number;
|
||
BOOL exact;
|
||
LPSTR string;
|
||
|
||
//
|
||
// if the caller doesn't know how many characters comprise the number, then
|
||
// we will convert until the next non-digit character, or until we have
|
||
// converted the maximum number of digits that can comprise an unsigned
|
||
// short value
|
||
//
|
||
|
||
if (NumberLength == 0) {
|
||
NumberLength = sizeof("65535") - 1;
|
||
exact = FALSE;
|
||
} else {
|
||
exact = TRUE;
|
||
}
|
||
number = 0;
|
||
string = *pString;
|
||
while (NumberLength && isdigit(*string)) {
|
||
number = number * 10 + (WORD)((BYTE)(*string++) - (BYTE)'0');
|
||
--NumberLength;
|
||
}
|
||
*pConvertedNumber = number;
|
||
*pString = string;
|
||
|
||
//
|
||
// if we were asked to convert a certain number of characters but failed
|
||
// because we hit a non-digit character, then return FALSE. Anything else
|
||
// (we converted required number of characters, or the caller didn't know
|
||
// how many characters comprised the number) is TRUE
|
||
//
|
||
|
||
return (exact && (NumberLength != 0)) ? FALSE : TRUE;
|
||
}
|
||
|
||
|
||
BOOL
|
||
ExtractDword(
|
||
IN OUT LPSTR* pString,
|
||
IN DWORD NumberLength,
|
||
OUT LPDWORD pConvertedNumber
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
pulls a <NumberLength> character number out of a string.
|
||
|
||
Assumes: 1. The number to be converted is an unsigned long
|
||
2. A whole number is contained within *pString
|
||
|
||
Arguments:
|
||
|
||
pString - pointer to pointer to string from which to get number
|
||
|
||
NumberLength - number of characters that comprise number string, if
|
||
not equal to 0, else if 0, we don't know the length
|
||
of the number string a priori
|
||
|
||
pConvertedNumber - pointer to variable where converted number written
|
||
|
||
Return Value:
|
||
|
||
BOOL
|
||
TRUE - number converted OK
|
||
|
||
FALSE - one of the characters in the number is not a digit
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD number;
|
||
BOOL exact;
|
||
|
||
//
|
||
// if the caller doesn't know how many characters comprise the number, then
|
||
// we will convert until the next non-digit character, or until we have
|
||
// converted the maximum number of digits that can comprise an unsigned
|
||
// short value
|
||
//
|
||
|
||
if (NumberLength == 0) {
|
||
NumberLength = sizeof("4294967295") - 1;
|
||
exact = FALSE;
|
||
} else {
|
||
exact = TRUE;
|
||
}
|
||
for (number = 0; isdigit(**pString) && NumberLength--; ) {
|
||
number = number * 10 + (DWORD)((BYTE)*((*pString)++) - (BYTE)'0');
|
||
}
|
||
*pConvertedNumber = number;
|
||
|
||
//
|
||
// if we were asked to convert a certain number of characters but failed
|
||
// because we hit a non-digit character, then return FALSE. Anything else
|
||
// (we converted required number of characters, or the caller didn't know
|
||
// how many characters comprised the number) is TRUE
|
||
//
|
||
|
||
return (exact && (NumberLength != 0)) ? FALSE : TRUE;
|
||
}
|
||
|
||
|
||
BOOL
|
||
ExtractInt(
|
||
IN OUT LPSTR* pString,
|
||
IN DWORD NumberLength,
|
||
OUT LPINT pConvertedNumber
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
pulls a <NumberLength> character number out of a string.
|
||
|
||
Assumes: 1. The number to be converted is an signed integer (32-bits)
|
||
|
||
Arguments:
|
||
|
||
pString - pointer to pointer to string from which to get number
|
||
|
||
NumberLength - number of characters that comprise number string, if
|
||
not equal to 0, else if 0, we don't know the length
|
||
of the number string a priori
|
||
|
||
pConvertedNumber - pointer to variable where converted number written
|
||
|
||
Return Value:
|
||
|
||
BOOL
|
||
TRUE - number converted OK
|
||
|
||
FALSE - one of the characters in the number is not a digit
|
||
|
||
--*/
|
||
|
||
{
|
||
int number;
|
||
int sign;
|
||
BOOL exact;
|
||
|
||
if ((**pString == '-') || (**pString == '+')) {
|
||
sign = (**pString == '-') ? -1 : +1;
|
||
if (NumberLength) {
|
||
--NumberLength;
|
||
}
|
||
++*pString;
|
||
} else {
|
||
sign = 1;
|
||
}
|
||
|
||
//
|
||
// if the caller doesn't know how many characters comprise the number, then
|
||
// we will convert until the next non-digit character, or until we have
|
||
// converted the maximum number of digits that can comprise an unsigned
|
||
// short value
|
||
//
|
||
|
||
if (NumberLength == 0) {
|
||
NumberLength = sizeof("2147483647") - 1;
|
||
exact = FALSE;
|
||
} else {
|
||
exact = TRUE;
|
||
}
|
||
for (number = 0; isdigit(**pString) && NumberLength; ) {
|
||
number = number * 10 + (INT)(((BYTE)**pString) - (BYTE)'0');
|
||
++*pString;
|
||
--NumberLength;
|
||
}
|
||
*pConvertedNumber = number * sign;
|
||
|
||
//
|
||
// if we were asked to convert a certain number of characters but failed
|
||
// because we hit a non-digit character, then return FALSE. Anything else
|
||
// (we converted required number of characters, or the caller didn't know
|
||
// how many characters comprised the number) is TRUE
|
||
//
|
||
|
||
return (exact && (NumberLength != 0)) ? FALSE : TRUE;
|
||
}
|
||
|
||
|
||
BOOL
|
||
SkipWhitespace(
|
||
IN OUT LPSTR* lpBuffer,
|
||
IN OUT LPDWORD lpBufferLength
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Skips any whitespace characters
|
||
|
||
Arguments:
|
||
|
||
lpBuffer - pointer to pointer to buffer
|
||
|
||
lpBufferLength - pointer to remaining buffer length
|
||
|
||
Return Value:
|
||
|
||
BOOL
|
||
Success - TRUE
|
||
|
||
Failure - FALSE. No more data left in buffer
|
||
|
||
--*/
|
||
|
||
{
|
||
while ((*lpBufferLength != 0) && isspace(**lpBuffer)) {
|
||
++*lpBuffer;
|
||
--*lpBufferLength;
|
||
}
|
||
return *lpBufferLength != 0;
|
||
}
|
||
|
||
|
||
BOOL
|
||
SkipSpaces(
|
||
IN OUT LPSTR* lpBuffer,
|
||
IN OUT LPDWORD lpBufferLength
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Skips any space characters. We only look for the actual space character
|
||
|
||
Arguments:
|
||
|
||
lpBuffer - pointer to pointer to buffer
|
||
|
||
lpBufferLength - pointer to remaining buffer length
|
||
|
||
Return Value:
|
||
|
||
BOOL
|
||
Success - TRUE
|
||
|
||
Failure - FALSE. No more data left in buffer
|
||
|
||
--*/
|
||
|
||
{
|
||
while ((*lpBufferLength != 0) && (**lpBuffer == ' ')) {
|
||
++*lpBuffer;
|
||
--*lpBufferLength;
|
||
}
|
||
return *lpBufferLength != 0;
|
||
}
|
||
|
||
|
||
BOOL
|
||
SkipLine(
|
||
IN OUT LPSTR* lpBuffer,
|
||
IN OUT LPDWORD lpBufferLength
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Positions text pointer at start of next non-empty line
|
||
|
||
Arguments:
|
||
|
||
lpBuffer - pointer to string. Updated on output
|
||
|
||
lpBufferLength - pointer to remaining length of string. Updated on output
|
||
|
||
Return Value:
|
||
|
||
BOOL
|
||
TRUE - found start of next non-empty line
|
||
|
||
FALSE - ran out of buffer
|
||
|
||
--*/
|
||
|
||
{
|
||
while ((*lpBufferLength != 0) && (**lpBuffer != '\r') && (**lpBuffer != '\n')) {
|
||
++*lpBuffer;
|
||
--*lpBufferLength;
|
||
}
|
||
while ((*lpBufferLength != 0) && ((**lpBuffer == '\r') || (**lpBuffer == '\n'))) {
|
||
++*lpBuffer;
|
||
--*lpBufferLength;
|
||
}
|
||
return *lpBufferLength != 0;
|
||
}
|
||
|
||
|
||
#undef isspace
|
||
#define isspace(ch) ((ch==0x20) || ((ch >= 0x09) && (ch <= 0x0d)))
|
||
|
||
BOOL
|
||
FindToken(
|
||
IN OUT LPSTR* lpBuffer,
|
||
IN OUT LPDWORD lpBufferLength
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Moves over the current token, past any spaces, and to the start of the next
|
||
token
|
||
|
||
Arguments:
|
||
|
||
lpBuffer - pointer to pointer to buffer
|
||
|
||
lpBufferLength - pointer to remaining buffer length
|
||
|
||
Return Value:
|
||
|
||
BOOL
|
||
Success - TRUE
|
||
|
||
Failure - FALSE. No more data left in buffer
|
||
|
||
--*/
|
||
|
||
{
|
||
while ((*lpBufferLength != 0) && !isspace(**lpBuffer)) {
|
||
++*lpBuffer;
|
||
--*lpBufferLength;
|
||
}
|
||
while ((*lpBufferLength != 0) && isspace(**lpBuffer)) {
|
||
++*lpBuffer;
|
||
--*lpBufferLength;
|
||
}
|
||
return *lpBufferLength != 0;
|
||
}
|
||
|
||
|
||
LPSTR
|
||
NiceNum(
|
||
OUT LPSTR Buffer,
|
||
IN SIZE_T Number,
|
||
IN int FieldWidth
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Converts a number to a string. The string is very human-sensible (i.e.
|
||
1,234,567 instead of 1234567. Sometimes its hard to make out these numbers
|
||
when your salary is so large)
|
||
|
||
Arguments:
|
||
|
||
Buffer - place to put resultant string
|
||
|
||
Number - to convert
|
||
|
||
FieldWidth - maximum width of the field, or 0 for "don't care"
|
||
|
||
Return Value:
|
||
|
||
LPSTR
|
||
pointer to Buffer
|
||
|
||
--*/
|
||
|
||
{
|
||
int i;
|
||
|
||
if (Number == 0) {
|
||
if (FieldWidth == 0) {
|
||
Buffer[0] = '0';
|
||
Buffer[1] = '\0';
|
||
} else {
|
||
memset(Buffer, ' ', FieldWidth);
|
||
Buffer[FieldWidth - 1] = '0';
|
||
Buffer[FieldWidth] = '\0';
|
||
}
|
||
} else {
|
||
|
||
//
|
||
// if the caller specified zero for the field width then work out how
|
||
// many characters the string will occupy
|
||
//
|
||
|
||
if (FieldWidth == 0) {
|
||
|
||
SIZE_T n;
|
||
|
||
n = Number;
|
||
++FieldWidth;
|
||
while (n >= 10) {
|
||
n /= 10;
|
||
++FieldWidth;
|
||
}
|
||
|
||
FieldWidth += (FieldWidth / 3) - (((FieldWidth % 3) == 0) ? 1 : 0);
|
||
}
|
||
|
||
//
|
||
// now create the representation
|
||
//
|
||
|
||
Buffer[FieldWidth] = '\0';
|
||
Buffer += FieldWidth;
|
||
i = 0;
|
||
while (Number && FieldWidth) {
|
||
*--Buffer = (char)((Number % 10) + '0');
|
||
--FieldWidth;
|
||
Number /= 10;
|
||
if ((++i == 3) && FieldWidth) {
|
||
if (Number) {
|
||
*--Buffer = ',';
|
||
--FieldWidth;
|
||
i = 0;
|
||
}
|
||
}
|
||
}
|
||
while (FieldWidth--) {
|
||
*--Buffer = ' ';
|
||
}
|
||
}
|
||
return Buffer;
|
||
}
|