Enhance:ini registry sequence (#121)

* '+=' supported .
* introduced registry list value deduplication .
* TechnoType listing now parse data both from ini and map .
* added UT case .
This commit is contained in:
Zero Fanker 2024-12-01 14:09:30 -05:00 committed by GitHub
parent 3e90dca667
commit 93e956e7ac
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 164 additions and 50 deletions

View file

@ -24,10 +24,12 @@
#include "stdafx.h"
#include "IniFile.h"
#include "Helpers.h"
#include <string>
#include <algorithm>
#include <stdexcept>
#include <set>
#include <unordered_set>
#ifdef _DEBUG
@ -92,64 +94,121 @@ CIniFileSection::~CIniFileSection()
value_pairs.clear();
};
bool isSectionRegistry(const CString& secName)
{
static std::unordered_set<std::string_view> registryNames = {
"BuildingTypes",
"InfantryTypes",
"AircraftTypes",
"VehicleTypes",
"Animations",
};
auto const nameView = std::string_view(secName.GetString(), secName.GetLength());
return registryNames.find(nameView) != registryNames.end();
}
WORD CIniFile::InsertFile(const CString& filename, const char* Section, BOOL bNoSpaces)
{
return InsertFile(std::string(filename.GetString()), Section, bNoSpaces);
}
WORD CIniFile::InsertFile(const std::string& filename, const char* Section, BOOL bNoSpaces)
WORD CIniFile::InsertFile(const std::string& filename, const char* pSectionSpecified, BOOL bNoSpaces)
{
if (filename.size() == 0)
if (filename.size() == 0) {
return 1;
}
fstream file;
file.open(filename, ios::in);
if (!file.good())
if (!file.good()) {
return 2;
}
//char cSec[256];
//char cLine[4096];
//memset(cSec, 0, 256);
//memset(cLine, 0, 4096);
CString cSec;
std::string cLine;
CString curSecParsed;
std::string curLineParsed;
const auto npos = std::string::npos;
#if 0
std::map<CString, std::list<std::pair<CString, CString>>> registryMap;
#endif
std::set<CString> registryValues;
while (!file.eof()) {
std::getline(file, cLine);
std::getline(file, curLineParsed);
// strip to left side of newline or comment
cLine.erase(std::find_if(cLine.begin(), cLine.end(), [](const char c) { return c == '\r' || c == '\n' || c == ';'; }), cLine.end());
curLineParsed.erase(std::find_if(curLineParsed.begin(), curLineParsed.end(), [](const char c) { return c == '\r' || c == '\n' || c == ';'; }), curLineParsed.end());
const auto openBracket = cLine.find('[');
const auto closeBracket = cLine.find(']');
const auto equals = cLine.find('=');
const auto openBracketPos = curLineParsed.find('[');
const auto closeBracketPos = curLineParsed.find(']');
const auto equalPos = curLineParsed.find('=');
if (openBracket != npos && closeBracket != npos && openBracket < closeBracket && (equals == npos || equals > openBracket)) {
if ((Section != nullptr) && cSec == Section)
return 0; // the section we want to insert is finished
if (openBracketPos != npos && closeBracketPos != npos && openBracketPos < closeBracketPos && (equalPos == npos || equalPos > openBracketPos)) {
if ((pSectionSpecified != nullptr) && curSecParsed == pSectionSpecified) {
break; // the section we want to insert is finished
}
cSec = cLine.substr(openBracket + 1, closeBracket - openBracket - 1).c_str();
} else if (equals != npos && !cSec.IsEmpty()) {
if (Section == NULL || cSec == Section) {
curSecParsed = curLineParsed.substr(openBracketPos + 1, closeBracketPos - openBracketPos - 1).c_str();
registryValues.clear();
continue;
}
if (equalPos != npos && !curSecParsed.IsEmpty()) {
if (pSectionSpecified == NULL || curSecParsed == pSectionSpecified) {
// a value is set and we have a valid current section!
CString name = cLine.substr(0, equals).c_str();
CString value = cLine.substr(equals + 1, cLine.size() - equals - 1).c_str();
CString keyName = curLineParsed.substr(0, equalPos).c_str();
CString value = curLineParsed.substr(equalPos + 1, curLineParsed.size() - equalPos - 1).c_str();
auto& curSectionMap = sections[curSecParsed];
if (bNoSpaces) {
name.Trim();
keyName.Trim();
value.Trim();
}
sections[cSec].SetString(name, value);
if (isSectionRegistry(curSecParsed) && IsNumeric(keyName)) {
auto const [_, inserted] = registryValues.insert(value);
// WW's duplicated record, skip
if (!inserted) {
continue;
}
}
// this is a duplicated number, and already added
// so we will append in the end of the list later
#if 0
if (IsNumeric(keyName) && curSectionMap.Exists(keyName)) {
registryMap[curSecParsed].push_back({ keyName, value });
}
#endif
// special handling for +=
if (keyName == '+') {
keyName += value;
}
curSectionMap.SetString(keyName, value);
}
}
}
// now we append all items to the list
#if 0
for (auto const& [secName, registry] : registryMap) {
auto& secMap = sections[secName];
for (auto const& [key, value] : registry) {
secMap.SetString("auto" + key, value);
}
}
#endif
file.close();
@ -183,7 +242,12 @@ BOOL CIniFile::SaveFile(const std::string& Filename) const
for (auto const& sec : sections) {
file << "[" << sec.first << "]" << endl;
for (auto const& pair : sec.second) {
file << pair.first << "=" << pair.second << endl;
auto keyName = pair.first;
// restore +=
if (keyName[0] == '+') {
keyName = '+';
}
file << keyName << "=" << pair.second << endl;
}
file << endl;
}