Codechange: Add const versions of GetItem/GetGroup, and sprinkle liberally.

Non-const version of GetItem is not needed.
This commit is contained in:
Peter Nelson 2023-10-11 00:38:57 +01:00 committed by Peter Nelson
parent 17ba9d8c96
commit 69e20e79ab
10 changed files with 73 additions and 58 deletions

View File

@ -95,7 +95,7 @@ struct BaseSet {
return Tnum_files - this->valid_files; return Tnum_files - this->valid_files;
} }
bool FillSetDetails(IniFile &ini, const std::string &path, const std::string &full_filename, bool allow_empty_filename = true); bool FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename, bool allow_empty_filename = true);
/** /**
* Get the description for the given ISO code. * Get the description for the given ISO code.
@ -244,7 +244,7 @@ struct GraphicsSet : BaseSet<GraphicsSet, MAX_GFT, true> {
PaletteType palette; ///< Palette of this graphics set PaletteType palette; ///< Palette of this graphics set
BlitterType blitter; ///< Blitter of this graphics set BlitterType blitter; ///< Blitter of this graphics set
bool FillSetDetails(IniFile &ini, const std::string &path, const std::string &full_filename); bool FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename);
static MD5File::ChecksumResult CheckMD5(const MD5File *file, Subdirectory subdir); static MD5File::ChecksumResult CheckMD5(const MD5File *file, Subdirectory subdir);
}; };
@ -301,7 +301,7 @@ struct MusicSet : BaseSet<MusicSet, NUM_SONGS_AVAILABLE, false> {
/** Number of valid songs in set. */ /** Number of valid songs in set. */
byte num_available; byte num_available;
bool FillSetDetails(IniFile &ini, const std::string &path, const std::string &full_filename); bool FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename);
}; };
/** All data/functions related with replacing the base music */ /** All data/functions related with replacing the base music */

View File

@ -39,15 +39,15 @@ extern void CheckExternalFiles();
* @return true if loading was successful. * @return true if loading was successful.
*/ */
template <class T, size_t Tnum_files, bool Tsearch_in_tars> template <class T, size_t Tnum_files, bool Tsearch_in_tars>
bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(IniFile &ini, const std::string &path, const std::string &full_filename, bool allow_empty_filename) bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename, bool allow_empty_filename)
{ {
IniGroup *metadata = ini.GetGroup("metadata"); const IniGroup *metadata = ini.GetGroup("metadata");
if (metadata == nullptr) { if (metadata == nullptr) {
Debug(grf, 0, "Base " SET_TYPE "set detail loading: metadata missing."); Debug(grf, 0, "Base " SET_TYPE "set detail loading: metadata missing.");
Debug(grf, 0, " Is {} readable for the user running OpenTTD?", full_filename); Debug(grf, 0, " Is {} readable for the user running OpenTTD?", full_filename);
return false; return false;
} }
IniItem *item; const IniItem *item;
fetch_metadata("name"); fetch_metadata("name");
this->name = *item->value; this->name = *item->value;
@ -74,9 +74,9 @@ bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(IniFile &ini, const
this->fallback = (item != nullptr && item->value && *item->value != "0" && *item->value != "false"); this->fallback = (item != nullptr && item->value && *item->value != "0" && *item->value != "false");
/* For each of the file types we want to find the file, MD5 checksums and warning messages. */ /* For each of the file types we want to find the file, MD5 checksums and warning messages. */
IniGroup *files = ini.GetGroup("files"); const IniGroup *files = ini.GetGroup("files");
IniGroup *md5s = ini.GetGroup("md5s"); const IniGroup *md5s = ini.GetGroup("md5s");
IniGroup *origin = ini.GetGroup("origin"); const IniGroup *origin = ini.GetGroup("origin");
for (uint i = 0; i < Tnum_files; i++) { for (uint i = 0; i < Tnum_files; i++) {
MD5File *file = &this->files[i]; MD5File *file = &this->files[i];
/* Find the filename first. */ /* Find the filename first. */

View File

@ -347,13 +347,13 @@ void GfxLoadSprites()
UpdateCursorSize(); UpdateCursorSize();
} }
bool GraphicsSet::FillSetDetails(IniFile &ini, const std::string &path, const std::string &full_filename) bool GraphicsSet::FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename)
{ {
bool ret = this->BaseSet<GraphicsSet, MAX_GFT, true>::FillSetDetails(ini, path, full_filename, false); bool ret = this->BaseSet<GraphicsSet, MAX_GFT, true>::FillSetDetails(ini, path, full_filename, false);
if (ret) { if (ret) {
IniGroup *metadata = ini.GetGroup("metadata"); const IniGroup *metadata = ini.GetGroup("metadata");
assert(metadata != nullptr); /* ret can't be true if metadata isn't present. */ assert(metadata != nullptr); /* ret can't be true if metadata isn't present. */
IniItem *item; const IniItem *item;
fetch_metadata("palette"); fetch_metadata("palette");
this->palette = ((*item->value)[0] == 'D' || (*item->value)[0] == 'd') ? PAL_DOS : PAL_WINDOWS; this->palette = ((*item->value)[0] == 'D' || (*item->value)[0] == 'd') ? PAL_DOS : PAL_WINDOWS;

View File

@ -274,12 +274,12 @@ HotkeyList::~HotkeyList()
* Load HotkeyList from IniFile. * Load HotkeyList from IniFile.
* @param ini IniFile to load from. * @param ini IniFile to load from.
*/ */
void HotkeyList::Load(IniFile &ini) void HotkeyList::Load(const IniFile &ini)
{ {
IniGroup *group = ini.GetGroup(this->ini_group); const IniGroup *group = ini.GetGroup(this->ini_group);
if (group == nullptr) return; if (group == nullptr) return;
for (Hotkey &hotkey : this->items) { for (Hotkey &hotkey : this->items) {
IniItem *item = group->GetItem(hotkey.name); const IniItem *item = group->GetItem(hotkey.name);
if (item != nullptr) { if (item != nullptr) {
hotkey.keycodes.clear(); hotkey.keycodes.clear();
if (item->value.has_value()) ParseHotkeys(hotkey, item->value->c_str()); if (item->value.has_value()) ParseHotkeys(hotkey, item->value->c_str());

View File

@ -40,7 +40,7 @@ struct HotkeyList {
HotkeyList(const std::string &ini_group, const std::vector<Hotkey> &items, GlobalHotkeyHandlerFunc global_hotkey_handler = nullptr); HotkeyList(const std::string &ini_group, const std::vector<Hotkey> &items, GlobalHotkeyHandlerFunc global_hotkey_handler = nullptr);
~HotkeyList(); ~HotkeyList();
void Load(IniFile &ini); void Load(const IniFile &ini);
void Save(IniFile &ini) const; void Save(IniFile &ini) const;
int CheckMatch(uint16_t keycode, bool global_only = false) const; int CheckMatch(uint16_t keycode, bool global_only = false) const;

View File

@ -49,9 +49,9 @@ IniGroup::IniGroup(const std::string &name, IniGroupType type) : type(type)
* @param name name of the item to find. * @param name name of the item to find.
* @return the requested item or nullptr if not found. * @return the requested item or nullptr if not found.
*/ */
IniItem *IniGroup::GetItem(const std::string &name) const IniItem *IniGroup::GetItem(const std::string &name) const
{ {
for (IniItem &item : this->items) { for (const IniItem &item : this->items) {
if (item.name == name) return &item; if (item.name == name) return &item;
} }
@ -111,6 +111,20 @@ IniLoadFile::IniLoadFile(const IniGroupNameList &list_group_names, const IniGrou
{ {
} }
/**
* Get the group with the given name.
* @param name name of the group to find.
* @return The requested group or \c nullptr if not found.
*/
const IniGroup *IniLoadFile::GetGroup(const std::string &name) const
{
for (const IniGroup &group : this->groups) {
if (group.name == name) return &group;
}
return nullptr;
}
/** /**
* Get the group with the given name. * Get the group with the given name.
* @param name name of the group to find. * @param name name of the group to find.

View File

@ -39,7 +39,7 @@ struct IniGroup {
IniGroup(const std::string &name, IniGroupType type); IniGroup(const std::string &name, IniGroupType type);
IniItem *GetItem(const std::string &name); const IniItem *GetItem(const std::string &name) const;
IniItem &GetOrCreateItem(const std::string &name); IniItem &GetOrCreateItem(const std::string &name);
IniItem &CreateItem(const std::string &name); IniItem &CreateItem(const std::string &name);
void RemoveItem(const std::string &name); void RemoveItem(const std::string &name);
@ -58,6 +58,7 @@ struct IniLoadFile {
IniLoadFile(const IniGroupNameList &list_group_names = {}, const IniGroupNameList &seq_group_names = {}); IniLoadFile(const IniGroupNameList &list_group_names = {}, const IniGroupNameList &seq_group_names = {});
virtual ~IniLoadFile() { } virtual ~IniLoadFile() { }
const IniGroup *GetGroup(const std::string &name) const;
IniGroup *GetGroup(const std::string &name); IniGroup *GetGroup(const std::string &name);
IniGroup &GetOrCreateGroup(const std::string &name); IniGroup &GetOrCreateGroup(const std::string &name);
IniGroup &CreateGroup(const std::string &name); IniGroup &CreateGroup(const std::string &name);

View File

@ -116,14 +116,14 @@ template <class Tbase_set>
return BaseMedia<Tbase_set>::used_set != nullptr; return BaseMedia<Tbase_set>::used_set != nullptr;
} }
bool MusicSet::FillSetDetails(IniFile &ini, const std::string &path, const std::string &full_filename) bool MusicSet::FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename)
{ {
bool ret = this->BaseSet<MusicSet, NUM_SONGS_AVAILABLE, false>::FillSetDetails(ini, path, full_filename); bool ret = this->BaseSet<MusicSet, NUM_SONGS_AVAILABLE, false>::FillSetDetails(ini, path, full_filename);
if (ret) { if (ret) {
this->num_available = 0; this->num_available = 0;
IniGroup *names = ini.GetGroup("names"); const IniGroup *names = ini.GetGroup("names");
IniGroup *catindex = ini.GetGroup("catindex"); const IniGroup *catindex = ini.GetGroup("catindex");
IniGroup *timingtrim = ini.GetGroup("timingtrim"); const IniGroup *timingtrim = ini.GetGroup("timingtrim");
uint tracknr = 1; uint tracknr = 1;
for (uint i = 0; i < lengthof(this->songinfo); i++) { for (uint i = 0; i < lengthof(this->songinfo); i++) {
const std::string &filename = this->files[i].filename; const std::string &filename = this->files[i].filename;
@ -133,7 +133,7 @@ bool MusicSet::FillSetDetails(IniFile &ini, const std::string &path, const std::
this->songinfo[i].filename = filename; // non-owned pointer this->songinfo[i].filename = filename; // non-owned pointer
IniItem *item = catindex != nullptr ? catindex->GetItem(_music_file_names[i]) : nullptr; const IniItem *item = catindex != nullptr ? catindex->GetItem(_music_file_names[i]) : nullptr;
if (item != nullptr && item->value.has_value() && !item->value->empty()) { if (item != nullptr && item->value.has_value() && !item->value->empty()) {
/* Song has a CAT file index, assume it's MPS MIDI format */ /* Song has a CAT file index, assume it's MPS MIDI format */
this->songinfo[i].filetype = MTT_MPSMIDI; this->songinfo[i].filetype = MTT_MPSMIDI;

View File

@ -586,8 +586,8 @@ const std::string &StringSettingDesc::Read(const void *object) const
*/ */
static void IniLoadSettings(IniFile &ini, const SettingTable &settings_table, const char *grpname, void *object, bool only_startup) static void IniLoadSettings(IniFile &ini, const SettingTable &settings_table, const char *grpname, void *object, bool only_startup)
{ {
IniGroup *group; const IniGroup *group;
IniGroup *group_def = ini.GetGroup(grpname); const IniGroup *group_def = ini.GetGroup(grpname);
for (auto &desc : settings_table) { for (auto &desc : settings_table) {
const SettingDesc *sd = GetSettingDesc(desc); const SettingDesc *sd = GetSettingDesc(desc);
@ -605,7 +605,7 @@ static void IniLoadSettings(IniFile &ini, const SettingTable &settings_table, co
group = group_def; group = group_def;
} }
IniItem *item = nullptr; const IniItem *item = nullptr;
if (group != nullptr) item = group->GetItem(s); if (group != nullptr) item = group->GetItem(s);
if (item == nullptr && group != group_def && group_def != nullptr) { if (item == nullptr && group != group_def && group_def != nullptr) {
/* For settings.xx.yy load the settings from [settings] yy = ? in case the previous /* For settings.xx.yy load the settings from [settings] yy = ? in case the previous
@ -780,7 +780,7 @@ bool ListSettingDesc::IsDefaultValue(void *) const
*/ */
static void IniLoadSettingList(IniFile &ini, const char *grpname, StringList &list) static void IniLoadSettingList(IniFile &ini, const char *grpname, StringList &list)
{ {
IniGroup *group = ini.GetGroup(grpname); const IniGroup *group = ini.GetGroup(grpname);
if (group == nullptr) return; if (group == nullptr) return;
@ -894,9 +894,9 @@ static void ValidateSettings()
} }
} }
static void AILoadConfig(IniFile &ini, const char *grpname) static void AILoadConfig(const IniFile &ini, const char *grpname)
{ {
IniGroup *group = ini.GetGroup(grpname); const IniGroup *group = ini.GetGroup(grpname);
/* Clean any configured AI */ /* Clean any configured AI */
for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) { for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
@ -923,9 +923,9 @@ static void AILoadConfig(IniFile &ini, const char *grpname)
} }
} }
static void GameLoadConfig(IniFile &ini, const char *grpname) static void GameLoadConfig(const IniFile &ini, const char *grpname)
{ {
IniGroup *group = ini.GetGroup(grpname); const IniGroup *group = ini.GetGroup(grpname);
/* Clean any configured GameScript */ /* Clean any configured GameScript */
GameConfig::GetConfig(GameConfig::SSS_FORCE_NEWGAME)->Change(std::nullopt); GameConfig::GetConfig(GameConfig::SSS_FORCE_NEWGAME)->Change(std::nullopt);
@ -933,7 +933,7 @@ static void GameLoadConfig(IniFile &ini, const char *grpname)
/* If no group exists, return */ /* If no group exists, return */
if (group == nullptr || group->items.empty()) return; if (group == nullptr || group->items.empty()) return;
IniItem &item = group->items.front(); const IniItem &item = group->items.front();
GameConfig *config = GameConfig::GetConfig(AIConfig::SSS_FORCE_NEWGAME); GameConfig *config = GameConfig::GetConfig(AIConfig::SSS_FORCE_NEWGAME);
@ -987,9 +987,9 @@ static bool DecodeHexText(const char *pos, uint8_t *dest, size_t dest_size)
* @param grpname Group name containing the configuration of the GRF. * @param grpname Group name containing the configuration of the GRF.
* @param is_static GRF is static. * @param is_static GRF is static.
*/ */
static GRFConfig *GRFLoadConfig(IniFile &ini, const char *grpname, bool is_static) static GRFConfig *GRFLoadConfig(const IniFile &ini, const char *grpname, bool is_static)
{ {
IniGroup *group = ini.GetGroup(grpname); const IniGroup *group = ini.GetGroup(grpname);
GRFConfig *first = nullptr; GRFConfig *first = nullptr;
GRFConfig **curr = &first; GRFConfig **curr = &first;
@ -1088,9 +1088,9 @@ static GRFConfig *GRFLoadConfig(IniFile &ini, const char *grpname, bool is_stati
return first; return first;
} }
static IniFileVersion LoadVersionFromConfig(IniFile &ini) static IniFileVersion LoadVersionFromConfig(const IniFile &ini)
{ {
IniGroup *group = ini.GetGroup("version"); const IniGroup *group = ini.GetGroup("version");
if (group == nullptr) return IFV_0; if (group == nullptr) return IFV_0;
auto version_number = group->GetItem("ini_version"); auto version_number = group->GetItem("ini_version");
@ -1247,16 +1247,16 @@ static void RemoveEntriesFromIni(IniFile &ini, const SettingTable &table)
* @param[out] old_item The old item to base upgrading on. * @param[out] old_item The old item to base upgrading on.
* @return Whether upgrading should happen; if false, old_item is a nullptr. * @return Whether upgrading should happen; if false, old_item is a nullptr.
*/ */
bool IsConversionNeeded(ConfigIniFile &ini, std::string group, std::string old_var, std::string new_var, IniItem **old_item) bool IsConversionNeeded(const ConfigIniFile &ini, const std::string &group, const std::string &old_var, const std::string &new_var, const IniItem **old_item)
{ {
*old_item = nullptr; *old_item = nullptr;
IniGroup *igroup = ini.GetGroup(group); const IniGroup *igroup = ini.GetGroup(group);
/* If the group doesn't exist, there is nothing to convert. */ /* If the group doesn't exist, there is nothing to convert. */
if (igroup == nullptr) return false; if (igroup == nullptr) return false;
IniItem *tmp_old_item = igroup->GetItem(old_var); const IniItem *tmp_old_item = igroup->GetItem(old_var);
IniItem *new_item = igroup->GetItem(new_var); const IniItem *new_item = igroup->GetItem(new_var);
/* If the old item doesn't exist, there is nothing to convert. */ /* If the old item doesn't exist, there is nothing to convert. */
if (tmp_old_item == nullptr) return false; if (tmp_old_item == nullptr) return false;
@ -1301,9 +1301,9 @@ void LoadFromConfig(bool startup)
/* Move no_http_content_downloads and use_relay_service from generic_ini to private_ini. */ /* Move no_http_content_downloads and use_relay_service from generic_ini to private_ini. */
if (generic_version < IFV_NETWORK_PRIVATE_SETTINGS) { if (generic_version < IFV_NETWORK_PRIVATE_SETTINGS) {
IniGroup *network = generic_ini.GetGroup("network"); const IniGroup *network = generic_ini.GetGroup("network");
if (network != nullptr) { if (network != nullptr) {
IniItem *no_http_content_downloads = network->GetItem("no_http_content_downloads"); const IniItem *no_http_content_downloads = network->GetItem("no_http_content_downloads");
if (no_http_content_downloads != nullptr) { if (no_http_content_downloads != nullptr) {
if (no_http_content_downloads->value == "true") { if (no_http_content_downloads->value == "true") {
_settings_client.network.no_http_content_downloads = true; _settings_client.network.no_http_content_downloads = true;
@ -1312,7 +1312,7 @@ void LoadFromConfig(bool startup)
} }
} }
IniItem *use_relay_service = network->GetItem("use_relay_service"); const IniItem *use_relay_service = network->GetItem("use_relay_service");
if (use_relay_service != nullptr) { if (use_relay_service != nullptr) {
if (use_relay_service->value == "never") { if (use_relay_service->value == "never") {
_settings_client.network.use_relay_service = UseRelayService::URS_NEVER; _settings_client.network.use_relay_service = UseRelayService::URS_NEVER;
@ -1325,7 +1325,7 @@ void LoadFromConfig(bool startup)
} }
} }
IniItem *old_item; const IniItem *old_item;
if (generic_version < IFV_GAME_TYPE && IsConversionNeeded(generic_ini, "network", "server_advertise", "server_game_type", &old_item)) { if (generic_version < IFV_GAME_TYPE && IsConversionNeeded(generic_ini, "network", "server_advertise", "server_game_type", &old_item)) {
auto old_value = BoolSettingDesc::ParseSingleValue(old_item->value->c_str()); auto old_value = BoolSettingDesc::ParseSingleValue(old_item->value->c_str());

View File

@ -193,11 +193,11 @@ static const char *DEFAULTS_GROUP_NAME = "defaults"; ///< Name of the group con
* @param ifile Loaded INI data. * @param ifile Loaded INI data.
* @param group_name Name of the group to copy. * @param group_name Name of the group to copy.
*/ */
static void DumpGroup(IniLoadFile &ifile, const char * const group_name) static void DumpGroup(const IniLoadFile &ifile, const char * const group_name)
{ {
IniGroup *grp = ifile.GetGroup(group_name); const IniGroup *grp = ifile.GetGroup(group_name);
if (grp != nullptr && grp->type == IGT_SEQUENCE) { if (grp != nullptr && grp->type == IGT_SEQUENCE) {
for (IniItem &item : grp->items) { for (const IniItem &item : grp->items) {
if (!item.name.empty()) { if (!item.name.empty()) {
_stored_output.Add(item.name.c_str()); _stored_output.Add(item.name.c_str());
_stored_output.Add("\n", 1); _stored_output.Add("\n", 1);
@ -213,9 +213,9 @@ static void DumpGroup(IniLoadFile &ifile, const char * const group_name)
* @param defaults Fallback group to search, \c nullptr skips the search. * @param defaults Fallback group to search, \c nullptr skips the search.
* @return Text of the item if found, else \c nullptr. * @return Text of the item if found, else \c nullptr.
*/ */
static const char *FindItemValue(const char *name, IniGroup *grp, IniGroup *defaults) static const char *FindItemValue(const char *name, const IniGroup *grp, const IniGroup *defaults)
{ {
IniItem *item = grp->GetItem(name); const IniItem *item = grp->GetItem(name);
if (item == nullptr && defaults != nullptr) item = defaults->GetItem(name); if (item == nullptr && defaults != nullptr) item = defaults->GetItem(name);
if (item == nullptr || !item->value.has_value()) return nullptr; if (item == nullptr || !item->value.has_value()) return nullptr;
return item->value->c_str(); return item->value->c_str();
@ -228,7 +228,7 @@ static const char *FindItemValue(const char *name, IniGroup *grp, IniGroup *defa
* @param default_grp Default values for items not set in @grp. * @param default_grp Default values for items not set in @grp.
* @param output Output to use for result. * @param output Output to use for result.
*/ */
static void DumpLine(IniItem *item, IniGroup *grp, IniGroup *default_grp, OutputStore &output) static void DumpLine(const IniItem *item, const IniGroup *grp, const IniGroup *default_grp, OutputStore &output)
{ {
static const int MAX_VAR_LENGTH = 64; static const int MAX_VAR_LENGTH = 64;
@ -292,28 +292,28 @@ static void DumpLine(IniItem *item, IniGroup *grp, IniGroup *default_grp, Output
* Output all non-special sections through the template / template variable expansion system. * Output all non-special sections through the template / template variable expansion system.
* @param ifile Loaded INI data. * @param ifile Loaded INI data.
*/ */
static void DumpSections(IniLoadFile &ifile) static void DumpSections(const IniLoadFile &ifile)
{ {
static const auto special_group_names = {PREAMBLE_GROUP_NAME, POSTAMBLE_GROUP_NAME, DEFAULTS_GROUP_NAME, TEMPLATES_GROUP_NAME, VALIDATION_GROUP_NAME}; static const auto special_group_names = {PREAMBLE_GROUP_NAME, POSTAMBLE_GROUP_NAME, DEFAULTS_GROUP_NAME, TEMPLATES_GROUP_NAME, VALIDATION_GROUP_NAME};
IniGroup *default_grp = ifile.GetGroup(DEFAULTS_GROUP_NAME); const IniGroup *default_grp = ifile.GetGroup(DEFAULTS_GROUP_NAME);
IniGroup *templates_grp = ifile.GetGroup(TEMPLATES_GROUP_NAME); const IniGroup *templates_grp = ifile.GetGroup(TEMPLATES_GROUP_NAME);
IniGroup *validation_grp = ifile.GetGroup(VALIDATION_GROUP_NAME); const IniGroup *validation_grp = ifile.GetGroup(VALIDATION_GROUP_NAME);
if (templates_grp == nullptr) return; if (templates_grp == nullptr) return;
/* Output every group, using its name as template name. */ /* Output every group, using its name as template name. */
for (IniGroup &grp : ifile.groups) { for (const IniGroup &grp : ifile.groups) {
/* Exclude special group names. */ /* Exclude special group names. */
if (std::find(std::begin(special_group_names), std::end(special_group_names), grp.name) != std::end(special_group_names)) continue; if (std::find(std::begin(special_group_names), std::end(special_group_names), grp.name) != std::end(special_group_names)) continue;
IniItem *template_item = templates_grp->GetItem(grp.name); // Find template value. const IniItem *template_item = templates_grp->GetItem(grp.name); // Find template value.
if (template_item == nullptr || !template_item->value.has_value()) { if (template_item == nullptr || !template_item->value.has_value()) {
FatalError("Cannot find template {}", grp.name); FatalError("Cannot find template {}", grp.name);
} }
DumpLine(template_item, &grp, default_grp, _stored_output); DumpLine(template_item, &grp, default_grp, _stored_output);
if (validation_grp != nullptr) { if (validation_grp != nullptr) {
IniItem *validation_item = validation_grp->GetItem(grp.name); // Find template value. const IniItem *validation_item = validation_grp->GetItem(grp.name); // Find template value.
if (validation_item != nullptr && validation_item->value.has_value()) { if (validation_item != nullptr && validation_item->value.has_value()) {
DumpLine(validation_item, &grp, default_grp, _post_amble_output); DumpLine(validation_item, &grp, default_grp, _post_amble_output);
} }