windows-nt/Source/XPSP1/NT/shell/themes/themeldr/scanner.cpp
2020-09-26 16:20:57 +08:00

314 lines
7.6 KiB
C++

//---------------------------------------------------------------------------
// 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;
}
//---------------------------------------------------------------------------