Files
source/Utils/INIReader.cpp
T
00fb898600 Delete builddefines.h
Nothing was left in it but the include of profiler.h, and 132 translation units
were including it for that alone. Fifteen files were leaning on profiler.h to
drag in <set>, <vector> and <ostream> for them; those now include what they use.

This is the commit that moves line numbers. Removing an include line shifts
__LINE__ by one for everything below it, and __LINE__ is an immediate operand in
every Assert() and DebugMsg() call, so the four game executables differ from
their predecessors by roughly a thousand 32-bit constants each. Every one of
those is accounted for: each is a single immediate that moved by -1 where the
builddefines.h include went away, or +1 where a <set>/<vector> include was
added. Nothing else in .text, .rdata or .data moves, no object file's section
sizes change, and symbolize_crash and Ja2Export stay bit-identical.

The one non-immediate difference is that the 24 Editor translation units of the
non-editor apps stop emitting __Avx2WmemEnabledWeakValue, a 4-byte weak COMDAT
they only ever instantiated through profiler.h's <vector>. It is a UCRT weak
default that other translation units still provide.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 01:07:26 -03:00

357 lines
12 KiB
C++

#include "INIReader.h"
#include "FileMan.h"
#include "DEBUG.H"
#include "Font Control.h"
#include "message.h"
#include <stdio.h>
#include <string.h>
#include <sstream>
// Kaiden: INI reading function definitions:
#include <vfs/Core/vfs.h>
std::set<vfs::Path,vfs::Path::Less> CIniReader::m_merge_files;
std::stack<std::string> iniErrorMessages;
template<typename ValueType>
void PushErrorMessage(std::string const& filename,
std::string const& section,
std::string const& key,
ValueType value, ValueType used_value,
ValueType minVal, ValueType maxVal)
{
std::stringstream errMessage;
errMessage << "The value [" << section << "][" << key << "] = \"" << value << "\" "
<< "in file [" << filename << "] "
<< "is outside the valid range [" << minVal << " , " << maxVal << "]. "
<< used_value << " will be used.";
iniErrorMessages.push(errMessage.str());
}
void CIniReader::RegisterFileForMerging(vfs::Path const& filename)
{
m_merge_files.insert(filename);
}
CIniReader::CIniReader(const CHAR8* szFileName)
{
memset(m_szFileName,0,sizeof(m_szFileName));
strncpy(m_szFileName,szFileName, std::min<int>(strlen(szFileName), sizeof(m_szFileName)-1));
if(m_merge_files.find(szFileName) == m_merge_files.end())
{
m_oProps.initFromIniFile(vfs::Path(szFileName));
}
else
{
vfs::CProfileStack* profs = getVFS()->getProfileStack();
vfs::CProfileStack::Iterator it = profs->begin();
std::stack<vfs::CVirtualProfile*> rev_order;
for(; !it.end(); it.next()) { rev_order.push(it.value()); }
while(!rev_order.empty())
{
vfs::IBaseFile* file = rev_order.top()->getFile(szFileName);
if(file)
{
m_oProps.initFromIniFile(vfs::tReadableFile::cast(file));
}
rev_order.pop();
}
}
// check for override file
{
CHAR8 OvrFileName[256], Drive[128], Dir[128], Name[128], Ext[128];
_splitpath(szFileName, Drive, Dir, Name, Ext);
_makepath(OvrFileName, Drive, Dir, Name, "Override");
if(getVFS()->fileExists(OvrFileName))
m_oProps.initFromIniFile(vfs::Path(OvrFileName));
}
}
CIniReader::CIniReader(const CHAR8* szFileName, BOOLEAN Force_Custom_Data_Path)
{
memset(m_szFileName,0,sizeof(m_szFileName));
// ary-05/05/2009 : force custom data path for potential non existing file -or- force default data path
// : Also, flag file detection to allow functions to determine course of action for case of file [not found/is found].
strncpy(m_szFileName,szFileName, std::min<int>(strlen(szFileName), sizeof(m_szFileName)-1));
if(m_merge_files.find(szFileName) == m_merge_files.end())
{
CIniReader_File_Found = m_oProps.initFromIniFile(vfs::Path(szFileName));
}
else
{
CIniReader_File_Found = TRUE;
vfs::CProfileStack* profs = getVFS()->getProfileStack();
vfs::CProfileStack::Iterator it = profs->begin();
std::stack<vfs::CVirtualProfile*> rev_order;
for(; !it.end(); it.next()) { rev_order.push(it.value()); }
while(!rev_order.empty())
{
vfs::IBaseFile* file = rev_order.top()->getFile(szFileName);
if(file)
{
CIniReader_File_Found = ((CIniReader_File_Found != FALSE) && m_oProps.initFromIniFile(vfs::tReadableFile::cast(file))) ? TRUE : FALSE;
}
rev_order.pop();
}
}
}
void CIniReader::Clear()
{
memset(m_szFileName, 0, MAX_PATH);
m_oProps.clearContainer();
}
int CIniReader::ReadInteger(const CHAR8* szSection, const CHAR8* szKey, int iDefaultValue)
{
return (int)(m_oProps.getIntProperty(szSection, szKey, iDefaultValue));
}
int CIniReader::ReadInteger(const CHAR8* szSection, const CHAR8* szKey, int defaultValue, int minValue, int maxValue)
{
int iniValueReadFromFile = (int)(m_oProps.getIntProperty(szSection, szKey, defaultValue));
//AssertGE(iniValueReadFromFile, minValue);
//AssertLE(iniValueReadFromFile, maxValue);
if (iniValueReadFromFile < minValue)
{
PushErrorMessage(this->m_szFileName, szSection, szKey, iniValueReadFromFile, minValue, minValue, maxValue);
return minValue;
}
else if (iniValueReadFromFile > maxValue)
{
PushErrorMessage(this->m_szFileName, szSection, szKey, iniValueReadFromFile, maxValue, minValue, maxValue);
return maxValue;
}
return iniValueReadFromFile;
}
//float CIniReader::ReadDouble(const STR8 szSection, const STR8 szKey, float fltDefaultValue)
//{
// char szResult[255];
// char szDefault[255];
// float fltResult;
// sprintf(szDefault, "%f",fltDefaultValue);
// GetPrivateProfileString(szSection, szKey, szDefault, szResult, 255, m_szFileName);
// fltResult = (float) atof(szResult);
// return fltResult;
//}
double CIniReader::ReadDouble(const CHAR8* szSection, const CHAR8* szKey, double defaultValue, double minValue, double maxValue)
{
double iniValueReadFromFile;
iniValueReadFromFile = m_oProps.getFloatProperty(szSection, szKey, defaultValue);
//AssertGE(iniValueReadFromFile, minValue);
//AssertLE(iniValueReadFromFile, maxValue);
if (iniValueReadFromFile < minValue)
{
PushErrorMessage(this->m_szFileName, szSection, szKey,iniValueReadFromFile, minValue, minValue, maxValue);
return minValue;
}
else if (iniValueReadFromFile > maxValue)
{
PushErrorMessage(this->m_szFileName, szSection, szKey, iniValueReadFromFile, maxValue, minValue, maxValue);
return maxValue;
}
return iniValueReadFromFile;
}
FLOAT CIniReader::ReadFloat(const CHAR8* szSection, const CHAR8* szKey, FLOAT defaultValue, FLOAT minValue, FLOAT maxValue)
{
FLOAT iniValueReadFromFile;
iniValueReadFromFile = (FLOAT) m_oProps.getFloatProperty(szSection, szKey, (float)defaultValue);
//AssertGE(iniValueReadFromFile, minValue);
//AssertLE(iniValueReadFromFile, maxValue);
if (iniValueReadFromFile < minValue)
{
PushErrorMessage(this->m_szFileName, szSection, szKey, iniValueReadFromFile, minValue, minValue, maxValue);
return minValue;
}
else if (iniValueReadFromFile > maxValue)
{
PushErrorMessage(this->m_szFileName, szSection, szKey, iniValueReadFromFile, maxValue, minValue, maxValue);
return maxValue;
}
return iniValueReadFromFile;
}
void CIniReader::ReadFloatArray(const CHAR8* szSection, const CHAR8* szKey, std::vector<FLOAT>& vec)
{
// read the array as a string
STRING512 textBuffer;
ReadString(szSection, szKey, "", textBuffer, _countof(textBuffer));
std::string str, token;
std::string delim = ",";
size_t offset = 0, prevOffset = 0;
// sanitise input
vec.clear();
str = textBuffer;
str.erase(std::remove(str.begin(), str.end(), ' '), str.end());
// split into array
try
{
do
{
offset = str.find(delim, prevOffset);
token = str.substr(prevOffset, offset - prevOffset);
prevOffset = offset + delim.length();
vec.push_back(std::stof(token.c_str()));
} while (offset != std::string::npos);
}
catch (...)
{
std::stringstream errMessage;
errMessage << "There was an error reading array [" << szSection << "][" << szKey << "] in file [" << m_szFileName << "]. Defaulting to [0].";
iniErrorMessages.push(errMessage.str());
vec.push_back(0);
}
}
void CIniReader::ReadINT32Array(const CHAR8* szSection, const CHAR8* szKey, std::vector<INT32>& vec)
{
// read the array as a string
STRING512 textBuffer;
ReadString(szSection, szKey, "", textBuffer, _countof(textBuffer));
std::string str, token;
std::string delim = ",";
size_t offset = 0, prevOffset = 0;
// sanitise input
vec.clear();
str = textBuffer;
str.erase(std::remove(str.begin(), str.end(), ' '), str.end());
// split into array
try
{
do
{
offset = str.find(delim, prevOffset);
token = str.substr(prevOffset, offset - prevOffset);
prevOffset = offset + delim.length();
vec.push_back(std::stoi(token.c_str()));
} while (offset != std::string::npos);
}
catch (...)
{
std::stringstream errMessage;
errMessage << "There was an error reading array [" << szSection << "][" << szKey << "] in file [" << m_szFileName << "]. Defaulting to [0].";
iniErrorMessages.push(errMessage.str());
vec.push_back(0);
}
}
BOOLEAN CIniReader::ReadBoolean(const CHAR8* szSection, const CHAR8* szKey, bool defaultValue, bool bolDisplayError)
{
vfs::String str = m_oProps.getStringProperty(szSection, szKey, L"");
if( vfs::StrCmp::Equal(str, L"true") )
{
return TRUE;
}
else if( vfs::StrCmp::Equal(str, L"false") )
{
return FALSE;
}
std::string szResult = str.utf8();
char szDefault[255];
sprintf(szDefault, "%s", defaultValue? "TRUE" : "FALSE");
if(bolDisplayError){
std::stringstream errMessage;
errMessage << "The value [" << szSection << "][" << szKey << "] = \"" << szResult << "\" "
<< "in file [" << this->m_szFileName << "] is neither TRUE nor FALSE. The value " << szDefault << " will be used.";
iniErrorMessages.push(errMessage.str());
}
return defaultValue;
}
// ary-05/15/2009 : snippet on how to use CIniReader::ReadString
// const STR8 test_ini_string = new char[255];
// memset(test_ini_string, 0x00, 255);
// iniReader.ReadString("JA2 Game Settings" , "TEST_STRING" , "default string" , test_ini_string , 255 );
void CIniReader::ReadString(const CHAR8* szSection, const CHAR8* szKey, const CHAR8* szDefaultValue, STR8 input_buffer, size_t buffer_size)
{
std::string s = m_oProps.getStringProperty(szSection, szKey, szDefaultValue).utf8();
int len = std::min<unsigned int>(s.length(),buffer_size-1);
strncpy(input_buffer, s.c_str(), len);
input_buffer[len] = 0;
}
// WANNE - MP: Old version, currently used by Multiplayer
STR8 CIniReader::ReadString(const CHAR8* szSection, const CHAR8* szKey, const CHAR8* szDefaultValue)
{
// >>>>> Memory Leak <<<<<
STR8 szResult = new char[255];
memset(szResult, 0x00, 255);
std::string s = m_oProps.getStringProperty(szSection, szKey, szDefaultValue).utf8();
strncpy(szResult, s.c_str(), std::min<int>(s.length(),254));
return szResult;
}
UINT8 CIniReader::ReadUINT8(const CHAR8* szSection, const CHAR8* szKey, UINT8 defaultValue, UINT8 minValue, UINT8 maxValue)
{
UINT8 iniValueReadFromFile;
iniValueReadFromFile = (UINT8) this->ReadUINT( szSection, szKey, (UINT32) defaultValue, (UINT32) minValue, (UINT32) maxValue);
return iniValueReadFromFile;
}
UINT16 CIniReader::ReadUINT16(const CHAR8* szSection, const CHAR8* szKey, UINT16 defaultValue, UINT16 minValue, UINT16 maxValue)
{
UINT16 iniValueReadFromFile;
iniValueReadFromFile = (UINT16) this->ReadUINT( szSection, szKey, (UINT32) defaultValue, (UINT32) minValue, (UINT32) maxValue);
return iniValueReadFromFile;
}
UINT32 CIniReader::ReadUINT32(const CHAR8* szSection, const CHAR8* szKey, UINT32 defaultValue, UINT32 minValue, UINT32 maxValue)
{
UINT32 iniValueReadFromFile;
iniValueReadFromFile = (UINT32) this->ReadUINT( szSection, szKey, (UINT32) defaultValue, (UINT32) minValue, (UINT32) maxValue);
return iniValueReadFromFile;
}
UINT32 CIniReader::ReadUINT(const CHAR8* szSection, const CHAR8* szKey, UINT32 defaultValue, UINT32 minValue, UINT32 maxValue )
{
UINT32 iniValueReadFromFile;
iniValueReadFromFile = (UINT32) m_oProps.getUIntProperty(szSection, szKey, defaultValue);
//AssertGE(iniValueReadFromFile, minValue);
//AssertLE(iniValueReadFromFile, maxValue);
if (iniValueReadFromFile < minValue)
{
PushErrorMessage(this->m_szFileName, szSection, szKey, iniValueReadFromFile, minValue, minValue, maxValue);
iniValueReadFromFile = minValue;
}
else if (iniValueReadFromFile > maxValue)
{
PushErrorMessage(this->m_szFileName, szSection, szKey, iniValueReadFromFile, maxValue, minValue, maxValue);
iniValueReadFromFile = maxValue;
}
return iniValueReadFromFile;
}