/*++ 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 // // functions // BOOL ExtractWord( IN OUT LPSTR* pString, IN DWORD NumberLength, OUT LPWORD pConvertedNumber ) /*++ Routine Description: pulls a 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 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 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; }