mirror of
https://github.com/electronicarts/CNC_TS_and_RA2_Mission_Editor.git
synced 2025-04-30 09:01:41 -04:00
* '+=' supported . * introduced registry list value deduplication . * TechnoType listing now parse data both from ini and map . * added UT case .
165 lines
3.9 KiB
C++
165 lines
3.9 KiB
C++
#pragma once
|
|
|
|
#include <afx.h>
|
|
#include "IniFile.h"
|
|
#include <vector>
|
|
#include <map>
|
|
|
|
using IndiceStorage = std::vector<CString>;
|
|
using SequencedSection = std::vector<CString>;
|
|
class IniSectionGroup;
|
|
|
|
/*
|
|
* @brief This class uses to simulation a combination of a few ini dictionaries, to
|
|
act as they are inside a same ini
|
|
*/
|
|
class IniFileGroup
|
|
{
|
|
friend class IniMegaFile;
|
|
public:
|
|
|
|
using StorageType = std::vector<const CIniFile*>;
|
|
|
|
IniFileGroup() = default;
|
|
|
|
|
|
const CString& GetString(const CString& section, const CString& key) const;
|
|
CString GetStringOr(const CString& section, const CString& key, const CString& def) const;
|
|
IniSectionGroup GetSection(const CString& section) const;
|
|
|
|
bool GetBool(const CString& pSection, const CString& pKey, bool def = false) const
|
|
{
|
|
return INIHelper::StringToBool(GetString(pSection, pKey), def);
|
|
}
|
|
int GetInteger(const CString& pSection, const CString& pKey, int def = 0) const
|
|
{
|
|
return INIHelper::StringToInteger(GetString(pSection, pKey), def);
|
|
}
|
|
|
|
auto Size() const { return m_group.size(); }
|
|
|
|
void Append(const CIniFile& INI);
|
|
const CIniFile* Nth(int idx) const;
|
|
|
|
auto begin() const { return m_group.begin(); }
|
|
auto end() const { return m_group.end(); }
|
|
bool empty() const { return m_group.empty(); }
|
|
|
|
private:
|
|
StorageType m_group;
|
|
};
|
|
|
|
class IniSectionGroup
|
|
{
|
|
using KvIter = CIniFileSection::Container::const_iterator;
|
|
using GroupIter = IniFileGroup::StorageType::const_iterator;
|
|
public:
|
|
class Iterator;
|
|
friend class Iterator;
|
|
class Iterator {
|
|
public:
|
|
Iterator(const CString& section,
|
|
GroupIter groupIter,
|
|
GroupIter groupIterEnd,
|
|
KvIter kvIter,
|
|
KvIter kvIterEnd
|
|
) :
|
|
m_section(section),
|
|
m_groupIter(groupIter),
|
|
m_groupIterEnd(groupIterEnd),
|
|
m_kvIter(kvIter),
|
|
m_kvIterEnd(kvIterEnd)
|
|
{
|
|
}
|
|
Iterator& operator++() {
|
|
// section content still working
|
|
if (m_kvIter != std::prev(m_kvIterEnd)) {
|
|
m_kvIter++;
|
|
return *this;
|
|
}
|
|
m_groupIter++;
|
|
if (m_groupIter != m_groupIterEnd) {
|
|
auto [beg, end] = IniSectionGroup::acquireNextKvGroup(m_section, m_groupIter, m_groupIterEnd);
|
|
m_kvIter = beg;
|
|
m_kvIterEnd = end;
|
|
} else {
|
|
m_kvIter = m_kvIterEnd;// to make (==) works
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
auto const& operator*() const {
|
|
return *m_kvIter;
|
|
}
|
|
bool operator==(const Iterator& rhs) const {
|
|
return m_groupIter == rhs.m_groupIter;
|
|
}
|
|
|
|
private:
|
|
GroupIter m_groupIter;
|
|
GroupIter m_groupIterEnd;
|
|
KvIter m_kvIter;
|
|
KvIter m_kvIterEnd;
|
|
const CString& m_section;
|
|
};
|
|
|
|
IniSectionGroup(IniFileGroup&& source, const CString& secName) :
|
|
m_source(std::move(source)),
|
|
m_section(secName)
|
|
{
|
|
}
|
|
|
|
IniSectionGroup(const IniFileGroup& source, const CString& secName) :
|
|
IniSectionGroup(IniFileGroup(source), secName)
|
|
{
|
|
}
|
|
|
|
Iterator begin() const {
|
|
auto groupBeg = m_source.begin();
|
|
auto [secItBeg, secItEnd] = acquireNextKvGroup(groupBeg);
|
|
return Iterator(m_section, groupBeg, m_source.end(), secItBeg, secItEnd);
|
|
}
|
|
|
|
Iterator end() const {
|
|
auto secItEnd = KvIter{};
|
|
if (!m_source.empty()) {
|
|
auto const& sec = (*std::prev(m_source.end()))->GetSection(m_section);
|
|
secItEnd = sec.end();
|
|
}
|
|
return Iterator(m_section, m_source.end(), m_source.end(), secItEnd, secItEnd);
|
|
}
|
|
|
|
bool HasValue(const CString& expected) const {
|
|
for (auto const& [_, val] : *this) {
|
|
if (val == expected) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private:
|
|
// attention: beginning iter
|
|
static std::pair< KvIter, KvIter> acquireNextKvGroup(const CString& section, GroupIter& beg, const GroupIter end) {
|
|
|
|
auto secItBeg = KvIter{};
|
|
auto secItEnd = KvIter{};
|
|
for (; beg != end; ++beg) {
|
|
auto const& sec = (*beg)->GetSection(section);
|
|
if (sec.Size() == 0) {
|
|
continue;
|
|
}
|
|
secItBeg = sec.begin();
|
|
secItEnd = sec.end();
|
|
break;
|
|
}
|
|
return { secItBeg, secItEnd };
|
|
}
|
|
|
|
std::pair< KvIter, KvIter> acquireNextKvGroup(GroupIter& beg) const {
|
|
return acquireNextKvGroup(m_section, beg, m_source.end());
|
|
}
|
|
|
|
const IniFileGroup m_source;
|
|
CString m_section;
|
|
};
|