refactored ini management, fixing performance issue and logic error from very low level .

This commit is contained in:
Zero Fanker 2024-03-31 19:57:33 -04:00
parent 13677476df
commit c559292183
3 changed files with 190 additions and 174 deletions

View file

@ -33,7 +33,10 @@
#include <map>
#include <CString>
#include <fstream>
#include <unordered_map>
#include <vector>
#include <ios>
#include "IniHelper.h"
using namespace std;
@ -49,30 +52,92 @@ public:
class CIniFileSection
{
public:
static const CString EmptyValue;
CIniFileSection();
virtual ~CIniFileSection();
CString GetValueByName(const CString& name, const CString& defaultValue = CString()) const;
[[deprecated("instead use GetString or TryGetString")]]
CString& AccessValueByName(const CString& name);
auto begin() noexcept
{
return values.begin();
auto const& Nth(size_t index) const {
ASSERT(index < value_pairs.size());
return this->value_pairs[index];
}
const CString* TryGetString(const CString& key) const {
auto const it = value_pos.find(key);
if (it != value_pos.end()) {
return &this->value_pairs[it->second].second;
}
return nullptr;
}
const CString& GetString(const CString& key) const {
if (auto const ret = TryGetString(key)) {
return *ret;
}
return EmptyValue;
}
CString GetStringOr(const CString& key, const CString& defaultValue) const {
auto const it = value_pos.find(key);
if (it != value_pos.end()) {
return this->value_pairs[it->second].second;
}
return defaultValue;
}
int GetInteger(const CString& key, int def = 0)const {
return INIHelper::StringToInteger(this->GetString(key), def);
}
size_t Size() const { return value_pos.size(); }
bool Exists(const CString& key) const {
auto const it = value_pos.find(key);
return it != value_pos.end();
}
void Assign(const CString& key, const CString& value) {
return this->Assign(key, CString(value));
}
void Assign(const CString& key, CString&& value) {
auto const it = value_pos.find(key);
// new, never had one
if (it == value_pos.end()) {
this->value_pairs.push_back({ key, std::move(value) });
value_pos[key] = value_pairs.size();
return;
}
value_pairs[it->second].second = std::move(value);
}
bool HasValue(const CString& val) const {
return this->FindValue(val) >= 0;
}
void RemoveAt(size_t idx) {
ASSERT(idx < value_pairs.size());
for (auto affectedIdx = idx + 1; affectedIdx < value_pairs.size(); ++affectedIdx) {
auto const& kvPair = value_pairs[affectedIdx];
auto const it = value_pos.find(kvPair.first);
ASSERT(it != value_pos.end());
it->second--;
}
auto const itErased = value_pairs.erase(value_pairs.begin() + idx);
ASSERT(value_pos.erase(itErased->first), 1);
}
auto begin() const noexcept
{
return values.begin();
}
auto end() noexcept
{
return values.end();
return value_pairs.begin();
}
auto end() const noexcept
{
return values.end();
return value_pairs.end();
}
[[deprecated("instead use iterators or for_each")]]
@ -87,28 +152,45 @@ public:
[[deprecated("instead use iterators or for_each")]]
const CString* GetValueName(std::size_t index) const noexcept;
[[deprecated("instead use iterators or for_each")]]
const CString* GetValue(std::size_t index) const noexcept;
[[deprecated("instead use iterators or for_each")]]
CString* GetValue(std::size_t index) noexcept;
public:
map<CString, CString, SortDummy> values;
map<CString, int, SortDummy> value_orig_pos;
private:
map<CString, int, SortDummy> value_pos{};
vector<std::pair<CString, CString>> value_pairs{};// sequenced
mutable bool isRegistry{false};
};
class CIniFile
{
static const CIniFileSection EmptySection;
public:
void DeleteEndingSpaces(BOOL bValueNames, BOOL bValues);
void DeleteLeadingSpaces(BOOL bValueNames, BOOL bValues);
const CString* GetSectionName(std::size_t Index) const noexcept;
const CIniFileSection* GetSection(std::size_t index) const;
CIniFileSection* GetSection(std::size_t index);
const CIniFileSection* GetSection(const CString& section) const;
CIniFileSection* GetSection(const CString& section);
const CIniFileSection* TryGetSection(std::size_t index) const;
CIniFileSection* TryGetSection(std::size_t index);
const CIniFileSection* TryGetSection(const CString& section) const
{
auto pMutThis = const_cast<std::remove_cv_t<std::remove_pointer_t<decltype(this)>>*>(this);
return pMutThis->TryGetSection(section);
}
CIniFileSection* TryGetSection(const CString& section)
{
auto it = sections.find(section);
if (it != sections.end()) {
return &it->second;
}
return nullptr;
}
const CIniFileSection& GetSection(const CString& section) const {
auto const it = sections.find(section);
if (it != sections.end()) {
return it->second;
}
return EmptySection;
}
CString GetValueByName(const CString& sectionName, const CString& valueName, const CString& defaultValue) const;
void Clear();
WORD InsertFile(const CString& filename, const char* Section, BOOL bNoSpaces = FALSE);
@ -118,6 +200,32 @@ public:
WORD LoadFile(const CString& filename, BOOL bNoSpaces = FALSE);
WORD LoadFile(const std::string& filename, BOOL bNoSpaces = FALSE);
const CString& GetString(const CString& section, const CString& key) const {
auto const it = sections.find(section);
if (it != sections.end()) {
return it->second.GetString(key);
}
return CIniFileSection::EmptyValue;
}
const bool GetBool(const CString& section, const CString& key, bool def = false) const {
auto const& str = this->GetString(section, key);
return INIHelper::StingToBool(str, def);
}
void Assign(const CString& section, const CString& key, CString&& value) {
auto const it = sections.find(section);
if (it != sections.end()) {
it->second.Assign(key, value);
return;
}
auto&& newSec = CIniFileSection{};
newSec.Assign(key, value);
ASSERT(sections.insert({ key, std::move(newSec) }).second == true);
}
void Assign(const CString& section, const CString& key, const CString& value) {
return this->Assign(section, key, CString(value));
}
auto begin() noexcept
{
@ -139,12 +247,12 @@ public:
return sections.end();
}
map<CString, CIniFileSection> sections;
CIniFile();
virtual ~CIniFile();
private:
std::string m_filename;
map<CString, CIniFileSection> sections;
};
#endif // !defined(AFX_INIFILE_H__96455620_6528_11D3_99E0_DB2A1EF71411__INCLUDED_)