singrdk/base/boot/Singldr/inifile.cpp

202 lines
4.9 KiB
C++

//////////////////////////////////////////////////////////////////////////////
//
// inifile.cpp - Parser/Iterator for ini file generated by DistroBuilder
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Note: The format is assumed to be:
//
// #############################################
// # Header comment
// #############################################
// Hash-MD5=XXX Size=XXX Path=XXX/YYY/ZZZ
// Hash-MD5=XXX Size=XXX Path=XXX/YYY/ZZZ
// ...
// ############################################
//
#include "inifile.h"
#pragma warning(disable: 4505) // Compiler generated constructor unreferenced
// ----------------------------------------------------------------------------
// Utility routines
static bool IsWhitespace(UINT8 value)
{
return (bool)(value == (UINT8)' ' || value == (UINT8)'\t');
}
static LPUINT8
SkipWhitespace(LPUINT8 pBuffer, LPUINT8 pBufferEnd)
{
while (pBuffer != pBufferEnd && IsWhitespace(*pBuffer)) {
pBuffer++;
}
return pBuffer;
}
static LPUINT8
SkipLine(LPUINT8 pBuffer, LPUINT8 pBufferEnd)
{
// Skip ASCII text
while (pBuffer != pBufferEnd && *pBuffer >= 32) {
pBuffer++;
}
// Skip control characters
while (pBuffer != pBufferEnd && *pBuffer < 32) {
pBuffer++;
}
return pBuffer;
}
static LPUINT8
SkipComments(LPUINT8 pBuffer, UINT32 cbBuffer)
{
LPUINT8 pBufferEnd = pBuffer + cbBuffer;
while (pBuffer != pBufferEnd) {
pBuffer = SkipWhitespace(pBuffer, pBufferEnd);
if (*pBuffer != '#') {
return pBuffer;
}
pBuffer = SkipLine(pBuffer, pBufferEnd);
}
return pBufferEnd;
}
static bool
ReverseMatch(LPUINT8 pBufferA, LPUINT8 pBufferB, INT8 nLength)
{
while (--nLength >= 0) {
if (*pBufferA-- != *pBufferB--) {
return 0;
}
}
return 1;
}
static LPUINT8
FindAndSkipString(LPCSTR pChars, INT8 nChars,
LPUINT8 pBuffer, LPUINT8 pBufferEnd)
{
pBuffer += nChars - 1;
if (pBuffer > pBufferEnd) {
return pBufferEnd;
}
while (pBuffer < pBufferEnd) {
if (*pBuffer == pChars[nChars - 1] &&
ReverseMatch(pBuffer, (LPUINT8)(pChars + nChars - 1), nChars)) {
return pBuffer + 1;
}
pBuffer++;
}
return pBufferEnd;
}
static UINT32
ParseFileSize(LPUINT8 pBuffer, LPUINT8 pBufferEnd)
{
UINT32 nBytes = 0;
pBuffer = FindAndSkipString("Size=", 5, pBuffer, pBufferEnd);
while (pBuffer != pBufferEnd &&
*pBuffer >= (UINT8)'0' && *pBuffer <= (UINT8)'9') {
nBytes *= 10;
nBytes += (UINT32)(*pBuffer - (UINT8)'0');
pBuffer++;
}
return nBytes;
}
static LPUINT8
ParseFileName(LPUINT8 pBuffer, LPUINT8 pBufferEnd)
{
pBuffer = FindAndSkipString("Path=", 5, pBuffer, pBufferEnd);
// Force null termination
for (LPUINT8 pTemp = pBuffer; pTemp != pBufferEnd; pTemp++) {
if (*pTemp < 32) {
*pTemp = 0;
break;
}
}
return pBuffer;
}
static LPUINT8 SkipToEndOfFile(LPUINT8 pBuffer, LPUINT8 pBufferEnd)
{
// Last line of file is a comment.
while (pBuffer != pBufferEnd && *pBuffer != '#') {
pBuffer++;
}
return pBuffer;
}
// ----------------------------------------------------------------------------
// IniFile class
IniFile::IniFile(LPUINT8 pBuffer, UINT32 cbBuffer) __far
{
this->_pBuffer = SkipComments(pBuffer, cbBuffer);
this->_pBufferEnd = SkipToEndOfFile(this->_pBuffer, pBuffer + cbBuffer);
this->_pCurrent = this->_pBuffer;
}
UINT16
IniFile::GetFileCount() __far
{
LPUINT8 pBuffer = this->_pBuffer;
UINT16 nFiles = 0;
while (pBuffer != this->_pBufferEnd) {
if (ParseFileSize(pBuffer, this->_pBufferEnd) == 0) {
break;
}
pBuffer = SkipLine(pBuffer, this->_pBufferEnd);
nFiles++;
}
return nFiles;
}
UINT32
IniFile::GetTotalBytes() __far
{
LPUINT8 pBuffer = this->_pBuffer;
UINT32 nTotalBytes = 0;
while (pBuffer != this->_pBufferEnd) {
nTotalBytes += ParseFileSize(pBuffer, this->_pBufferEnd);
pBuffer = SkipLine(pBuffer, this->_pBufferEnd);
}
return nTotalBytes;
}
UINT32
IniFile::GetCurrentFileSize() __far
{
return ParseFileSize(this->_pCurrent, this->_pBufferEnd);
}
LPUINT8
IniFile::GetCurrentFileName() __far
{
LPUINT8 pFileName = ParseFileName(this->_pCurrent, this->_pBufferEnd);
if (pFileName != this->_pBufferEnd) {
return pFileName;
}
return NULL;
}
void
IniFile::Rewind() __far
{
this->_pCurrent = this->_pBuffer;
}
bool
IniFile::MoveNext() __far
{
this->_pCurrent = SkipLine(this->_pCurrent, this->_pBufferEnd);
return (bool)(this->_pCurrent != this->_pBufferEnd);
}