202 lines
4.9 KiB
C++
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);
|
|
}
|