Codechange: Split GetItem with GetOrCreateItem. (#10952)

`IniGroup::GetItem()` returns nullptr if the item does not exist, but does not if the create parameter is set to true. Resolve CodeQL warnings with `GetOrCreateItem()` which returns a reference to the item instead.
This commit is contained in:
PeterN 2023-06-05 19:29:52 +01:00 committed by GitHub
parent 3b1407d240
commit 64d6ad50f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 51 additions and 41 deletions

View File

@ -23,7 +23,7 @@ extern void CheckExternalFiles();
* @param name the name of the item to fetch. * @param name the name of the item to fetch.
*/ */
#define fetch_metadata(name) \ #define fetch_metadata(name) \
item = metadata->GetItem(name, false); \ item = metadata->GetItem(name); \
if (item == nullptr || !item->value.has_value() || item->value->empty()) { \ if (item == nullptr || !item->value.has_value() || item->value->empty()) { \
Debug(grf, 0, "Base " SET_TYPE "set detail loading: {} field missing.", name); \ Debug(grf, 0, "Base " SET_TYPE "set detail loading: {} field missing.", name); \
Debug(grf, 0, " Is {} readable for the user running OpenTTD?", full_filename); \ Debug(grf, 0, " Is {} readable for the user running OpenTTD?", full_filename); \
@ -65,7 +65,7 @@ bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(IniFile *ini, const
fetch_metadata("version"); fetch_metadata("version");
this->version = atoi(item->value->c_str()); this->version = atoi(item->value->c_str());
item = metadata->GetItem("fallback", false); item = metadata->GetItem("fallback");
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. */
@ -75,7 +75,7 @@ bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(IniFile *ini, const
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. */
item = files->GetItem(BaseSet<T, Tnum_files, Tsearch_in_tars>::file_names[i], false); item = files->GetItem(BaseSet<T, Tnum_files, Tsearch_in_tars>::file_names[i]);
if (item == nullptr || (!item->value.has_value() && !allow_empty_filename)) { if (item == nullptr || (!item->value.has_value() && !allow_empty_filename)) {
Debug(grf, 0, "No " SET_TYPE " file for: {} (in {})", BaseSet<T, Tnum_files, Tsearch_in_tars>::file_names[i], full_filename); Debug(grf, 0, "No " SET_TYPE " file for: {} (in {})", BaseSet<T, Tnum_files, Tsearch_in_tars>::file_names[i], full_filename);
return false; return false;
@ -93,7 +93,7 @@ bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(IniFile *ini, const
file->filename = path + filename; file->filename = path + filename;
/* Then find the MD5 checksum */ /* Then find the MD5 checksum */
item = md5s->GetItem(filename, false); item = md5s->GetItem(filename);
if (item == nullptr || !item->value.has_value()) { if (item == nullptr || !item->value.has_value()) {
Debug(grf, 0, "No MD5 checksum specified for: {} (in {})", filename, full_filename); Debug(grf, 0, "No MD5 checksum specified for: {} (in {})", filename, full_filename);
return false; return false;
@ -119,8 +119,8 @@ bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(IniFile *ini, const
} }
/* Then find the warning message when the file's missing */ /* Then find the warning message when the file's missing */
item = origin->GetItem(filename, false); item = origin->GetItem(filename);
if (item == nullptr) item = origin->GetItem("default", false); if (item == nullptr) item = origin->GetItem("default");
if (item == nullptr || !item->value.has_value()) { if (item == nullptr || !item->value.has_value()) {
Debug(grf, 1, "No origin warning message specified for: {}", filename); Debug(grf, 1, "No origin warning message specified for: {}", filename);
file->missing_warning.clear(); file->missing_warning.clear();

View File

@ -357,7 +357,7 @@ bool GraphicsSet::FillSetDetails(IniFile *ini, const std::string &path, const st
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;
/* Get optional blitter information. */ /* Get optional blitter information. */
item = metadata->GetItem("blitter", false); item = metadata->GetItem("blitter");
this->blitter = (item != nullptr && (*item->value)[0] == '3') ? BLT_32BPP : BLT_8BPP; this->blitter = (item != nullptr && (*item->value)[0] == '3') ? BLT_32BPP : BLT_8BPP;
} }
return ret; return ret;

View File

@ -278,7 +278,7 @@ void HotkeyList::Load(IniFile *ini)
{ {
IniGroup *group = ini->GetGroup(this->ini_group); IniGroup *group = ini->GetGroup(this->ini_group);
for (Hotkey &hotkey : this->items) { for (Hotkey &hotkey : this->items) {
IniItem *item = group->GetItem(hotkey.name, false); 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());
@ -294,8 +294,8 @@ void HotkeyList::Save(IniFile *ini) const
{ {
IniGroup *group = ini->GetGroup(this->ini_group); IniGroup *group = ini->GetGroup(this->ini_group);
for (const Hotkey &hotkey : this->items) { for (const Hotkey &hotkey : this->items) {
IniItem *item = group->GetItem(hotkey.name, true); IniItem &item = group->GetOrCreateItem(hotkey.name);
item->SetValue(SaveKeycodes(hotkey)); item.SetValue(SaveKeycodes(hotkey));
} }
} }

View File

@ -82,22 +82,32 @@ IniGroup::~IniGroup()
} }
/** /**
* Get the item with the given name, and if it doesn't exist * Get the item with the given name.
* and create is true it creates a new item.
* @param name name of the item to find. * @param name name of the item to find.
* @param create whether to create an item when not found or not.
* @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, bool create) IniItem *IniGroup::GetItem(const std::string &name)
{ {
for (IniItem *item = this->item; item != nullptr; item = item->next) { for (IniItem *item = this->item; item != nullptr; item = item->next) {
if (item->name == name) return item; if (item->name == name) return item;
} }
if (!create) return nullptr; return nullptr;
}
/* otherwise make a new one */ /**
return new IniItem(this, name); * Get the item with the given name, and if it doesn't exist create a new item.
* @param name name of the item to find.
* @return the requested item.
*/
IniItem &IniGroup::GetOrCreateItem(const std::string &name)
{
for (IniItem *item = this->item; item != nullptr; item = item->next) {
if (item->name == name) return *item;
}
/* Item doesn't exist, make a new one. */
return *(new IniItem(this, name));
} }
/** /**

View File

@ -44,7 +44,8 @@ struct IniGroup {
IniGroup(struct IniLoadFile *parent, const std::string &name); IniGroup(struct IniLoadFile *parent, const std::string &name);
~IniGroup(); ~IniGroup();
IniItem *GetItem(const std::string &name, bool create); IniItem *GetItem(const std::string &name);
IniItem &GetOrCreateItem(const std::string &name);
void RemoveItem(const std::string &name); void RemoveItem(const std::string &name);
void Clear(); void Clear();
}; };

View File

@ -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->GetItem(_music_file_names[i], false); IniItem *item = catindex->GetItem(_music_file_names[i]);
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;
@ -158,7 +158,7 @@ bool MusicSet::FillSetDetails(IniFile *ini, const std::string &path, const std::
* the beginning, so we don't start reading e.g. root. */ * the beginning, so we don't start reading e.g. root. */
while (*trimmed_filename == PATHSEPCHAR) trimmed_filename++; while (*trimmed_filename == PATHSEPCHAR) trimmed_filename++;
item = names->GetItem(trimmed_filename, false); item = names->GetItem(trimmed_filename);
if (item != nullptr && item->value.has_value() && !item->value->empty()) break; if (item != nullptr && item->value.has_value() && !item->value->empty()) break;
} }
@ -179,7 +179,7 @@ bool MusicSet::FillSetDetails(IniFile *ini, const std::string &path, const std::
this->songinfo[i].tracknr = tracknr++; this->songinfo[i].tracknr = tracknr++;
} }
item = trimmed_filename != nullptr ? timingtrim->GetItem(trimmed_filename, false) : nullptr; item = trimmed_filename != nullptr ? timingtrim->GetItem(trimmed_filename) : nullptr;
if (item != nullptr && item->value.has_value() && !item->value->empty()) { if (item != nullptr && item->value.has_value() && !item->value->empty()) {
auto endpos = item->value->find(':'); auto endpos = item->value->find(':');
if (endpos != std::string::npos) { if (endpos != std::string::npos) {

View File

@ -590,17 +590,17 @@ static void IniLoadSettings(IniFile &ini, const SettingTable &settings_table, co
group = group_def; group = group_def;
} }
IniItem *item = group->GetItem(s, false); IniItem *item = group->GetItem(s);
if (item == nullptr && group != group_def) { if (item == nullptr && group != group_def) {
/* 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
* did not exist (e.g. loading old config files with a [settings] section */ * did not exist (e.g. loading old config files with a [settings] section */
item = group_def->GetItem(s, false); item = group_def->GetItem(s);
} }
if (item == nullptr) { if (item == nullptr) {
/* For settings.xx.zz.yy load the settings from [zz] yy = ? in case the previous /* For settings.xx.zz.yy load the settings from [zz] yy = ? in case the previous
* did not exist (e.g. loading old config files with a [yapf] section */ * did not exist (e.g. loading old config files with a [yapf] section */
sc = s.find('.'); sc = s.find('.');
if (sc != std::string::npos) item = ini.GetGroup(s.substr(0, sc))->GetItem(s.substr(sc + 1), false); if (sc != std::string::npos) item = ini.GetGroup(s.substr(0, sc))->GetItem(s.substr(sc + 1));
} }
sd->ParseValue(item, object); sd->ParseValue(item, object);
@ -649,7 +649,6 @@ void ListSettingDesc::ParseValue(const IniItem *item, void *object) const
static void IniSaveSettings(IniFile &ini, const SettingTable &settings_table, const char *grpname, void *object, bool) static void IniSaveSettings(IniFile &ini, const SettingTable &settings_table, const char *grpname, void *object, bool)
{ {
IniGroup *group_def = nullptr, *group; IniGroup *group_def = nullptr, *group;
IniItem *item;
for (auto &desc : settings_table) { for (auto &desc : settings_table) {
const SettingDesc *sd = GetSettingDesc(desc); const SettingDesc *sd = GetSettingDesc(desc);
@ -669,11 +668,11 @@ static void IniSaveSettings(IniFile &ini, const SettingTable &settings_table, co
group = group_def; group = group_def;
} }
item = group->GetItem(s, true); IniItem &item = group->GetOrCreateItem(s);
if (!item->value.has_value() || !sd->IsSameValue(item, object)) { if (!item.value.has_value() || !sd->IsSameValue(&item, object)) {
/* The value is different, that means we have to write it to the ini */ /* The value is different, that means we have to write it to the ini */
item->value.emplace(sd->FormatValue(object)); item.value.emplace(sd->FormatValue(object));
} }
} }
} }
@ -773,7 +772,7 @@ static void IniSaveSettingList(IniFile &ini, const char *grpname, StringList &li
group->Clear(); group->Clear();
for (const auto &iter : list) { for (const auto &iter : list) {
group->GetItem(iter, true)->SetValue(""); group->GetOrCreateItem(iter).SetValue("");
} }
} }
@ -1060,7 +1059,7 @@ static IniFileVersion LoadVersionFromConfig(IniFile &ini)
{ {
IniGroup *group = ini.GetGroup("version"); IniGroup *group = ini.GetGroup("version");
auto version_number = group->GetItem("ini_version", false); auto version_number = group->GetItem("ini_version");
/* Older ini-file versions don't have this key yet. */ /* Older ini-file versions don't have this key yet. */
if (version_number == nullptr || !version_number->value.has_value()) return IFV_0; if (version_number == nullptr || !version_number->value.has_value()) return IFV_0;
@ -1121,9 +1120,9 @@ static void GameSaveConfig(IniFile &ini, const char *grpname)
static void SaveVersionInConfig(IniFile &ini) static void SaveVersionInConfig(IniFile &ini)
{ {
IniGroup *group = ini.GetGroup("version"); IniGroup *group = ini.GetGroup("version");
group->GetItem("version_string", true)->SetValue(_openttd_revision); group->GetOrCreateItem("version_string").SetValue(_openttd_revision);
group->GetItem("version_number", true)->SetValue(fmt::format("{:08X}", _openttd_newgrf_version)); group->GetOrCreateItem("version_number").SetValue(fmt::format("{:08X}", _openttd_newgrf_version));
group->GetItem("ini_version", true)->SetValue(std::to_string(INIFILE_VERSION)); group->GetOrCreateItem("ini_version").SetValue(std::to_string(INIFILE_VERSION));
} }
/* Save a GRF configuration to the given group name */ /* Save a GRF configuration to the given group name */
@ -1136,7 +1135,7 @@ static void GRFSaveConfig(IniFile &ini, const char *grpname, const GRFConfig *li
for (c = list; c != nullptr; c = c->next) { for (c = list; c != nullptr; c = c->next) {
std::string key = fmt::format("{:08X}|{}|{}", BSWAP32(c->ident.grfid), std::string key = fmt::format("{:08X}|{}|{}", BSWAP32(c->ident.grfid),
FormatArrayAsHex(c->ident.md5sum), c->filename); FormatArrayAsHex(c->ident.md5sum), c->filename);
group->GetItem(key, true)->SetValue(GRFBuildParamList(c)); group->GetOrCreateItem(key).SetValue(GRFBuildParamList(c));
} }
} }
@ -1224,7 +1223,7 @@ void LoadFromConfig(bool startup)
if (_settings_client.network.server_game_type == SERVER_GAME_TYPE_LOCAL) { if (_settings_client.network.server_game_type == SERVER_GAME_TYPE_LOCAL) {
IniGroup *network = generic_ini.GetGroup("network", false); IniGroup *network = generic_ini.GetGroup("network", false);
if (network != nullptr) { if (network != nullptr) {
IniItem *server_advertise = network->GetItem("server_advertise", false); IniItem *server_advertise = network->GetItem("server_advertise");
if (server_advertise != nullptr && server_advertise->value == "true") { if (server_advertise != nullptr && server_advertise->value == "true") {
_settings_client.network.server_game_type = SERVER_GAME_TYPE_PUBLIC; _settings_client.network.server_game_type = SERVER_GAME_TYPE_PUBLIC;
} }
@ -1240,7 +1239,7 @@ void LoadFromConfig(bool startup)
if (generic_version < IFV_NETWORK_PRIVATE_SETTINGS) { if (generic_version < IFV_NETWORK_PRIVATE_SETTINGS) {
IniGroup *network = generic_ini.GetGroup("network", false); IniGroup *network = generic_ini.GetGroup("network", false);
if (network != nullptr) { if (network != nullptr) {
IniItem *no_http_content_downloads = network->GetItem("no_http_content_downloads", false); 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;
@ -1249,7 +1248,7 @@ void LoadFromConfig(bool startup)
} }
} }
IniItem *use_relay_service = network->GetItem("use_relay_service", false); 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;

View File

@ -229,8 +229,8 @@ static void DumpGroup(IniLoadFile *ifile, const char * const group_name)
*/ */
static const char *FindItemValue(const char *name, IniGroup *grp, IniGroup *defaults) static const char *FindItemValue(const char *name, IniGroup *grp, IniGroup *defaults)
{ {
IniItem *item = grp->GetItem(name, false); IniItem *item = grp->GetItem(name);
if (item == nullptr && defaults != nullptr) item = defaults->GetItem(name, false); 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();
} }
@ -321,14 +321,14 @@ static void DumpSections(IniLoadFile *ifile)
for (sgn = special_group_names; *sgn != nullptr; sgn++) if (grp->name == *sgn) break; for (sgn = special_group_names; *sgn != nullptr; sgn++) if (grp->name == *sgn) break;
if (*sgn != nullptr) continue; if (*sgn != nullptr) continue;
IniItem *template_item = templates_grp->GetItem(grp->name, false); // Find template value. 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, false); // Find template value. 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);
} }