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