//--------------------------------------------------------------------------- // Scanner.cpp - supports parsing general text files & lines with // a ";" style comment (rest of line is comment) //--------------------------------------------------------------------------- #include "stdafx.h" #include "scanner.h" #include "utils.h" //--------------------------------------------------------------------------- CScanner::CScanner(LPCWSTR pszTextToScan) { ResetAll(FALSE); _p = pszTextToScan; _pSymbol = NULL; } //--------------------------------------------------------------------------- CScanner::~CScanner() { ResetAll(TRUE); } //--------------------------------------------------------------------------- void CScanner::UseSymbol(LPCWSTR pszSymbol) { if (pszSymbol == NULL) { if (_pSymbol && *_p) { _p = _pSymbol; } _pSymbol = NULL; } else { _pSymbol = _p; _p = pszSymbol; } } //--------------------------------------------------------------------------- BOOL CScanner::ReadNextLine() { if ((! _pszMultiLineBuffer) || (! *_pszMultiLineBuffer)) // end of multiple lines { _fEndOfFile = TRUE; return FALSE; } WCHAR *q = _szLineBuff; while ((*_pszMultiLineBuffer) && (*_pszMultiLineBuffer != '\r') && (*_pszMultiLineBuffer != '\n')) *q++ = *_pszMultiLineBuffer++; *q = 0; if (*_pszMultiLineBuffer == '\r') _pszMultiLineBuffer++; if (*_pszMultiLineBuffer == '\n') _pszMultiLineBuffer++; _p = _szLineBuff; _fBlankSoFar = TRUE; _iLineNum++; return TRUE; } //--------------------------------------------------------------------------- BOOL CScanner::SkipSpaces() { while (1) { while (IsSpace(*_p)) _p++; if ((! *_p) || (*_p == ';')) // end of line { if ((_fBlankSoFar) && (! _fEndOfFile)) { ReadNextLine(); continue; } if (*_p == ';') // comment _p += lstrlen(_p); // skip to end of line return FALSE; } //---- good chars on this line ---- _fBlankSoFar = FALSE; break; } return (*_p != 0); } //--------------------------------------------------------------------------- BOOL CScanner::GetId(LPWSTR pszIdBuff, DWORD dwMaxLen) { if (! dwMaxLen) // must have at least 1 space for NULL terminator return FALSE; SkipSpaces(); WCHAR *v = pszIdBuff; while ((IsNameChar(FALSE)) && (--dwMaxLen)) *v++ = *_p++; *v = 0; if (v == pszIdBuff) // no chars found return FALSE; if (IsNameChar(FALSE)) // ran out of room return FALSE; return TRUE; } //--------------------------------------------------------------------------- BOOL CScanner::GetIdPair(LPWSTR pszIdBuff, LPWSTR pszValueBuff, DWORD dwMaxLen) { if (! dwMaxLen) // must have at least 1 space for NULL terminator return FALSE; if (!GetId(pszIdBuff, dwMaxLen)) return FALSE; if (!GetChar('=')) return FALSE; SkipSpaces(); // Take everything until the end of line lstrcpyn(pszValueBuff, _p, dwMaxLen); return TRUE; } //--------------------------------------------------------------------------- BOOL CScanner::GetFileName(LPWSTR pszFileNameBuff, DWORD dwMaxLen) { if (! dwMaxLen) // must have at least 1 space for NULL terminator return FALSE; SkipSpaces(); WCHAR *v = pszFileNameBuff; while ((IsFileNameChar(FALSE)) && (--dwMaxLen)) *v++ = *_p++; *v = 0; if (v == pszFileNameBuff) // no chars found return FALSE; if (IsFileNameChar(FALSE)) // ran out of room return FALSE; return TRUE; } //--------------------------------------------------------------------------- BOOL CScanner::GetNumber(int *piVal) { SkipSpaces(); if (! IsNumStart()) return FALSE; *piVal = string2number(_p); if ((_p[0] == '0') && ((_p[1] == 'x') || (_p[1] == 'X'))) // hex num _p += 2; else _p++; // skip over digit or sign //---- skip over number --- while (IsHexDigit(*_p)) _p++; return TRUE; } //--------------------------------------------------------------------------- BOOL CScanner::IsNameChar(BOOL fOkToSkip) { if (fOkToSkip) SkipSpaces(); return ((IsCharAlphaNumericW(*_p)) || (*_p == '_') || (*_p == '-')); } //--------------------------------------------------------------------------- BOOL CScanner::IsFileNameChar(BOOL fOkToSkip) { if (fOkToSkip) SkipSpaces(); return ((IsCharAlphaNumericW(*_p)) || (*_p == '_') || (*_p == '-') || (*_p == ':') || (*_p == '\\') || (*_p == '.')); } //--------------------------------------------------------------------------- BOOL CScanner::IsNumStart() { SkipSpaces(); return ((IsDigit(*_p)) || (*_p == '-') || (*_p == '+')); } //--------------------------------------------------------------------------- BOOL CScanner::GetChar(const WCHAR val) { SkipSpaces(); if (*_p != val) return FALSE; _p++; // skip over WCHAR return TRUE; } //--------------------------------------------------------------------------- BOOL CScanner::GetKeyword(LPCWSTR pszKeyword) { SkipSpaces(); int len = lstrlenW(pszKeyword); LPWSTR p = (LPWSTR)alloca( (len+1)*sizeof(WCHAR)); if (! p) return FALSE; lstrcpynW(p, _p, len); if (AsciiStrCmpI(p, pszKeyword)==0) { _p += len; return TRUE; } return FALSE; } //--------------------------------------------------------------------------- BOOL CScanner::EndOfLine() { SkipSpaces(); return (*_p == 0); } //--------------------------------------------------------------------------- BOOL CScanner::EndOfFile() { return _fEndOfFile; } //--------------------------------------------------------------------------- BOOL CScanner::AttachLine(LPCWSTR pszLine) { ResetAll(TRUE); _p = pszLine; return TRUE; } //--------------------------------------------------------------------------- BOOL CScanner::AttachMultiLineBuffer(LPCWSTR pszBuffer, LPCWSTR pszFileName) { ResetAll(TRUE); _p = _szLineBuff; _pszMultiLineBuffer = pszBuffer; lstrcpy_truncate(_szFileName, pszFileName, ARRAYSIZE(_szFileName)); return TRUE; } //--------------------------------------------------------------------------- HRESULT CScanner::AttachFile(LPCWSTR pszFileName) { ResetAll(TRUE); HRESULT hr = AllocateTextFile(pszFileName, &_pszFileText, NULL); if (FAILED(hr)) return hr; _pszMultiLineBuffer = _pszFileText; lstrcpy_truncate(_szFileName, pszFileName, ARRAYSIZE(_szFileName)); return S_OK; } //--------------------------------------------------------------------------- void CScanner::ResetAll(BOOL fPossiblyAllocated) { _iLineNum = 0; _fEndOfFile = FALSE; _pszMultiLineBuffer = NULL; _fUnicodeInput = TRUE; _fBlankSoFar = TRUE; *_szFileName = 0; *_szLineBuff = 0; _p = _szLineBuff; if (fPossiblyAllocated) { if (_pszFileText) { LocalFree(_pszFileText); _pszFileText = NULL; } } else _pszFileText = NULL; } //--------------------------------------------------------------------------- BOOL CScanner::ForceNextLine() { ReadNextLine(); if (! SkipSpaces()) return FALSE; return TRUE; } //---------------------------------------------------------------------------