314 lines
7.6 KiB
C++
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;
|
||
|
}
|
||
|
//---------------------------------------------------------------------------
|
||
|
|