From 877349c13d133f2694ba1f72603a85d543e616c2 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Fri, 5 May 2023 00:04:52 +0200 Subject: [PATCH] Codechange: use std::string for text file name resolution --- src/ai/ai_gui.cpp | 2 +- src/base_media_base.h | 10 ++++---- src/game/game_gui.cpp | 2 +- src/network/core/tcp_content.cpp | 8 +++--- src/network/core/tcp_content_type.h | 4 ++- src/network/network_content_gui.cpp | 6 ++--- src/newgrf_config.cpp | 6 ++--- src/newgrf_config.h | 3 ++- src/newgrf_gui.cpp | 6 ++--- src/script/script_config.cpp | 4 +-- src/script/script_config.hpp | 4 +-- src/script/script_gui.cpp | 6 ++--- src/settings_gui.cpp | 10 ++++---- src/textfile_gui.cpp | 38 ++++++++++++----------------- src/textfile_gui.h | 5 ++-- 15 files changed, 56 insertions(+), 58 deletions(-) diff --git a/src/ai/ai_gui.cpp b/src/ai/ai_gui.cpp index edd7e48348..ac2daee27d 100644 --- a/src/ai/ai_gui.cpp +++ b/src/ai/ai_gui.cpp @@ -285,7 +285,7 @@ struct AIConfigWindow : public Window { this->SetWidgetDisabledState(WID_AIC_MOVE_DOWN, this->selected_slot == INVALID_COMPANY || !IsEditable((CompanyID)(this->selected_slot + 1))); for (TextfileType tft = TFT_BEGIN; tft < TFT_END; tft++) { - this->SetWidgetDisabledState(WID_AIC_TEXTFILE + tft, this->selected_slot == INVALID_COMPANY || (AIConfig::GetConfig(this->selected_slot)->GetTextfile(tft, this->selected_slot) == nullptr)); + this->SetWidgetDisabledState(WID_AIC_TEXTFILE + tft, this->selected_slot == INVALID_COMPANY || !AIConfig::GetConfig(this->selected_slot)->GetTextfile(tft, this->selected_slot).has_value()); } } }; diff --git a/src/base_media_base.h b/src/base_media_base.h index 84c12d0858..d78539f730 100644 --- a/src/base_media_base.h +++ b/src/base_media_base.h @@ -137,17 +137,17 @@ struct BaseSet { /** * Search a textfile file next to this base media. * @param type The type of the textfile to search for. - * @return The filename for the textfile, \c nullptr otherwise. + * @return The filename for the textfile. */ - const char *GetTextfile(TextfileType type) const + std::optional GetTextfile(TextfileType type) const { for (uint i = 0; i < NUM_FILES; i++) { - const char *textfile = ::GetTextfile(type, BASESET_DIR, this->files[i].filename.c_str()); - if (textfile != nullptr) { + auto textfile = ::GetTextfile(type, BASESET_DIR, this->files[i].filename); + if (textfile.has_value()) { return textfile; } } - return nullptr; + return std::nullopt; } }; diff --git a/src/game/game_gui.cpp b/src/game/game_gui.cpp index 0d941d884a..0885f38db6 100644 --- a/src/game/game_gui.cpp +++ b/src/game/game_gui.cpp @@ -405,7 +405,7 @@ struct GSConfigWindow : public Window { this->SetWidgetDisabledState(WID_GSC_CHANGE, (_game_mode == GM_NORMAL) || !IsEditable()); for (TextfileType tft = TFT_BEGIN; tft < TFT_END; tft++) { - this->SetWidgetDisabledState(WID_GSC_TEXTFILE + tft, GameConfig::GetConfig()->GetTextfile(tft, (CompanyID)OWNER_DEITY) == nullptr); + this->SetWidgetDisabledState(WID_GSC_TEXTFILE + tft, !GameConfig::GetConfig()->GetTextfile(tft, (CompanyID)OWNER_DEITY).has_value()); } this->RebuildVisibleSettings(); HideDropDownMenu(this); diff --git a/src/network/core/tcp_content.cpp b/src/network/core/tcp_content.cpp index dbbb70dcaa..913a8b9bdc 100644 --- a/src/network/core/tcp_content.cpp +++ b/src/network/core/tcp_content.cpp @@ -49,11 +49,11 @@ bool ContentInfo::IsValid() const /** * Search a textfile file next to this file in the content list. * @param type The type of the textfile to search for. - * @return The filename for the textfile, \c nullptr otherwise. + * @return The filename for the textfile. */ -const char *ContentInfo::GetTextfile(TextfileType type) const +std::optional ContentInfo::GetTextfile(TextfileType type) const { - if (this->state == INVALID) return nullptr; + if (this->state == INVALID) return std::nullopt; const char *tmp; switch (this->type) { default: NOT_REACHED(); @@ -88,7 +88,7 @@ const char *ContentInfo::GetTextfile(TextfileType type) const tmp = FindScenario(this, true); break; } - if (tmp == nullptr) return nullptr; + if (tmp == nullptr) return std::nullopt; return ::GetTextfile(type, GetContentInfoSubDir(this->type), tmp); } diff --git a/src/network/core/tcp_content_type.h b/src/network/core/tcp_content_type.h index 5daae39dc6..7ac64c6e35 100644 --- a/src/network/core/tcp_content_type.h +++ b/src/network/core/tcp_content_type.h @@ -12,6 +12,8 @@ #ifndef NETWORK_CORE_TCP_CONTENT_TYPE_H #define NETWORK_CORE_TCP_CONTENT_TYPE_H +#include + /** The values in the enum are important; they are used as database 'keys' */ enum ContentType { CONTENT_TYPE_BEGIN = 1, ///< Helper to mark the begin of the types @@ -75,7 +77,7 @@ struct ContentInfo { bool IsSelected() const; bool IsValid() const; - const char *GetTextfile(TextfileType type) const; + std::optional GetTextfile(TextfileType type) const; }; #endif /* NETWORK_CORE_TCP_CONTENT_TYPE_H */ diff --git a/src/network/network_content_gui.cpp b/src/network/network_content_gui.cpp index 3f8c97e348..7d53329069 100644 --- a/src/network/network_content_gui.cpp +++ b/src/network/network_content_gui.cpp @@ -43,8 +43,8 @@ struct ContentTextfileWindow : public TextfileWindow { ContentTextfileWindow(TextfileType file_type, const ContentInfo *ci) : TextfileWindow(file_type), ci(ci) { - const char *textfile = this->ci->GetTextfile(file_type); - this->LoadTextfile(textfile, GetContentInfoSubDir(this->ci->type)); + auto textfile = this->ci->GetTextfile(file_type); + this->LoadTextfile(textfile.value(), GetContentInfoSubDir(this->ci->type)); } StringID GetTypeString() const @@ -998,7 +998,7 @@ public: this->SetWidgetDisabledState(WID_NCL_SELECT_UPDATE, !show_select_upgrade); this->SetWidgetDisabledState(WID_NCL_OPEN_URL, this->selected == nullptr || this->selected->url.empty()); for (TextfileType tft = TFT_BEGIN; tft < TFT_END; tft++) { - this->SetWidgetDisabledState(WID_NCL_TEXTFILE + tft, this->selected == nullptr || this->selected->state != ContentInfo::ALREADY_HERE || this->selected->GetTextfile(tft) == nullptr); + this->SetWidgetDisabledState(WID_NCL_TEXTFILE + tft, this->selected == nullptr || this->selected->state != ContentInfo::ALREADY_HERE || !this->selected->GetTextfile(tft).has_value()); } this->GetWidget(WID_NCL_CANCEL)->widget_data = this->filesize_sum == 0 ? STR_AI_SETTINGS_CLOSE : STR_AI_LIST_CANCEL; diff --git a/src/newgrf_config.cpp b/src/newgrf_config.cpp index 77f82fcb2b..b2b29a5b89 100644 --- a/src/newgrf_config.cpp +++ b/src/newgrf_config.cpp @@ -785,9 +785,9 @@ char *GRFBuildParamList(char *dst, const GRFConfig *c, const char *last) /** * Search a textfile file next to this NewGRF. * @param type The type of the textfile to search for. - * @return The filename for the textfile, \c nullptr otherwise. + * @return The filename for the textfile. */ -const char *GRFConfig::GetTextfile(TextfileType type) const +std::optional GRFConfig::GetTextfile(TextfileType type) const { - return ::GetTextfile(type, NEWGRF_DIR, this->filename.c_str()); + return ::GetTextfile(type, NEWGRF_DIR, this->filename); } diff --git a/src/newgrf_config.h b/src/newgrf_config.h index 3e5a56739a..cc7b899ea1 100644 --- a/src/newgrf_config.h +++ b/src/newgrf_config.h @@ -17,6 +17,7 @@ #include "fileio_type.h" #include "textfile_type.h" #include "newgrf_text.h" +#include /** GRF config bit flags */ enum GCF_Flags { @@ -184,7 +185,7 @@ struct GRFConfig : ZeroedMemoryAllocator { void CopyParams(const GRFConfig &src); - const char *GetTextfile(TextfileType type) const; + std::optional GetTextfile(TextfileType type) const; const char *GetName() const; const char *GetDescription() const; const char *GetURL() const; diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp index f4fb441dd7..663de441c2 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -545,8 +545,8 @@ struct NewGRFTextfileWindow : public TextfileWindow { NewGRFTextfileWindow(TextfileType file_type, const GRFConfig *c) : TextfileWindow(file_type), grf_config(c) { - const char *textfile = this->grf_config->GetTextfile(file_type); - this->LoadTextfile(textfile, NEWGRF_DIR); + auto textfile = this->grf_config->GetTextfile(file_type); + this->LoadTextfile(textfile.value(), NEWGRF_DIR); } void SetStringParameters(int widget) const override @@ -1285,7 +1285,7 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { const GRFConfig *selected_config = (this->avail_sel == nullptr) ? this->active_sel : this->avail_sel; for (TextfileType tft = TFT_BEGIN; tft < TFT_END; tft++) { - this->SetWidgetDisabledState(WID_NS_NEWGRF_TEXTFILE + tft, selected_config == nullptr || selected_config->GetTextfile(tft) == nullptr); + this->SetWidgetDisabledState(WID_NS_NEWGRF_TEXTFILE + tft, selected_config == nullptr || !selected_config->GetTextfile(tft).has_value()); } this->SetWidgetDisabledState(WID_NS_OPEN_URL, selected_config == nullptr || StrEmpty(selected_config->GetURL())); diff --git a/src/script/script_config.cpp b/src/script/script_config.cpp index 29ab7af430..a36d7046f0 100644 --- a/src/script/script_config.cpp +++ b/src/script/script_config.cpp @@ -234,9 +234,9 @@ std::string ScriptConfig::SettingsToString() const return string; } -const char *ScriptConfig::GetTextfile(TextfileType type, CompanyID slot) const +std::optional ScriptConfig::GetTextfile(TextfileType type, CompanyID slot) const { - if (slot == INVALID_COMPANY || this->GetInfo() == nullptr) return nullptr; + if (slot == INVALID_COMPANY || this->GetInfo() == nullptr) return std::nullopt; return ::GetTextfile(type, (slot == OWNER_DEITY) ? GAME_DIR : AI_DIR, this->GetInfo()->GetMainScript()); } diff --git a/src/script/script_config.hpp b/src/script/script_config.hpp index be788d0526..342d5ad362 100644 --- a/src/script/script_config.hpp +++ b/src/script/script_config.hpp @@ -184,9 +184,9 @@ public: * Search a textfile file next to this script. * @param type The type of the textfile to search for. * @param slot #CompanyID to check status of. - * @return The filename for the textfile, \c nullptr otherwise. + * @return The filename for the textfile. */ - const char *GetTextfile(TextfileType type, CompanyID slot) const; + std::optional GetTextfile(TextfileType type, CompanyID slot) const; void SetToLoadData(ScriptInstance::ScriptData *data); ScriptInstance::ScriptData *GetToLoadData(); diff --git a/src/script/script_gui.cpp b/src/script/script_gui.cpp index d060620af1..aeec99445f 100644 --- a/src/script/script_gui.cpp +++ b/src/script/script_gui.cpp @@ -643,11 +643,11 @@ struct ScriptTextfileWindow : public TextfileWindow { void OnInvalidateData(int data = 0, bool gui_scope = true) override { - const char *textfile = GetConfig(slot)->GetTextfile(file_type, slot); - if (textfile == nullptr) { + auto textfile = GetConfig(slot)->GetTextfile(file_type, slot); + if (!textfile.has_value()) { this->Close(); } else { - this->LoadTextfile(textfile, (slot == OWNER_DEITY) ? GAME_DIR : AI_DIR); + this->LoadTextfile(textfile.value(), (slot == OWNER_DEITY) ? GAME_DIR : AI_DIR); } } }; diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 1be6742b92..6e51539b5e 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -101,8 +101,8 @@ struct BaseSetTextfileWindow : public TextfileWindow { BaseSetTextfileWindow(TextfileType file_type, const TBaseSet* baseset, StringID content_type) : TextfileWindow(file_type), baseset(baseset), content_type(content_type) { - const char *textfile = this->baseset->GetTextfile(file_type); - this->LoadTextfile(textfile, BASESET_DIR); + auto textfile = this->baseset->GetTextfile(file_type); + this->LoadTextfile(textfile.value(), BASESET_DIR); } void SetStringParameters(int widget) const override @@ -704,9 +704,9 @@ struct GameOptionsWindow : Window { this->GetWidget(WID_GO_BASE_GRF_STATUS)->SetDataTip(missing_files ? STR_EMPTY : STR_GAME_OPTIONS_BASE_GRF_STATUS, STR_NULL); for (TextfileType tft = TFT_BEGIN; tft < TFT_END; tft++) { - this->SetWidgetDisabledState(WID_GO_BASE_GRF_TEXTFILE + tft, BaseGraphics::GetUsedSet() == nullptr || BaseGraphics::GetUsedSet()->GetTextfile(tft) == nullptr); - this->SetWidgetDisabledState(WID_GO_BASE_SFX_TEXTFILE + tft, BaseSounds::GetUsedSet() == nullptr || BaseSounds::GetUsedSet()->GetTextfile(tft) == nullptr); - this->SetWidgetDisabledState(WID_GO_BASE_MUSIC_TEXTFILE + tft, BaseMusic::GetUsedSet() == nullptr || BaseMusic::GetUsedSet()->GetTextfile(tft) == nullptr); + this->SetWidgetDisabledState(WID_GO_BASE_GRF_TEXTFILE + tft, BaseGraphics::GetUsedSet() == nullptr || !BaseGraphics::GetUsedSet()->GetTextfile(tft).has_value()); + this->SetWidgetDisabledState(WID_GO_BASE_SFX_TEXTFILE + tft, BaseSounds::GetUsedSet() == nullptr || !BaseSounds::GetUsedSet()->GetTextfile(tft).has_value()); + this->SetWidgetDisabledState(WID_GO_BASE_MUSIC_TEXTFILE + tft, BaseMusic::GetUsedSet() == nullptr || !BaseMusic::GetUsedSet()->GetTextfile(tft).has_value()); } missing_files = BaseMusic::GetUsedSet()->GetNumInvalid() == 0; diff --git a/src/textfile_gui.cpp b/src/textfile_gui.cpp index 021d7326d5..86a370045f 100644 --- a/src/textfile_gui.cpp +++ b/src/textfile_gui.cpp @@ -333,9 +333,9 @@ static void Xunzip(byte **bufp, size_t *sizep) /** * Loads the textfile text from file and setup #lines. */ -/* virtual */ void TextfileWindow::LoadTextfile(const char *textfile, Subdirectory dir) +/* virtual */ void TextfileWindow::LoadTextfile(const std::string &textfile, Subdirectory dir) { - if (textfile == nullptr) return; + if (textfile.empty()) return; this->lines.clear(); @@ -350,19 +350,14 @@ static void Xunzip(byte **bufp, size_t *sizep) if (read != filesize) return; -#if defined(WITH_ZLIB) || defined(WITH_LIBLZMA) - const char *suffix = strrchr(textfile, '.'); - if (suffix == nullptr) return; -#endif - #if defined(WITH_ZLIB) /* In-place gunzip */ - if (strcmp(suffix, ".gz") == 0) Gunzip((byte**)&this->text, &filesize); + if (StrEndsWith(textfile, ".gz")) Gunzip((byte**)&this->text, &filesize); #endif #if defined(WITH_LIBLZMA) /* In-place xunzip */ - if (strcmp(suffix, ".xz") == 0) Xunzip((byte**)&this->text, &filesize); + if (StrEndsWith(textfile, ".xz")) Xunzip((byte**)&this->text, &filesize); #endif if (!this->text) return; @@ -409,7 +404,7 @@ static void Xunzip(byte **bufp, size_t *sizep) * @param filename The filename of the content to look for. * @return The path to the textfile, \c nullptr otherwise. */ -const char *GetTextfile(TextfileType type, Subdirectory dir, const char *filename) +std::optional GetTextfile(TextfileType type, Subdirectory dir, const std::string &filename) { static const char * const prefixes[] = { "readme", @@ -418,17 +413,16 @@ const char *GetTextfile(TextfileType type, Subdirectory dir, const char *filenam }; static_assert(lengthof(prefixes) == TFT_END); - const char *prefix = prefixes[type]; + std::string_view prefix = prefixes[type]; - if (filename == nullptr) return nullptr; + if (filename.empty()) return std::nullopt; - static char file_path[MAX_PATH]; - strecpy(file_path, filename, lastof(file_path)); + auto slash = filename.find_last_of(PATHSEPCHAR); + if (slash == std::string::npos) return std::nullopt; - char *slash = strrchr(file_path, PATHSEPCHAR); - if (slash == nullptr) return nullptr; + std::string_view base_path(filename.data(), slash + 1); - static const char * const exts[] = { + static const std::initializer_list extensions{ "txt", #if defined(WITH_ZLIB) "txt.gz", @@ -438,15 +432,15 @@ const char *GetTextfile(TextfileType type, Subdirectory dir, const char *filenam #endif }; - for (size_t i = 0; i < lengthof(exts); i++) { - seprintf(slash + 1, lastof(file_path), "%s_%s.%s", prefix, GetCurrentLanguageIsoCode(), exts[i]); + for (auto &extension : extensions) { + std::string file_path = fmt::format("{}{}_{}.{}", base_path, prefix, GetCurrentLanguageIsoCode(), extension); if (FioCheckFileExists(file_path, dir)) return file_path; - seprintf(slash + 1, lastof(file_path), "%s_%.2s.%s", prefix, GetCurrentLanguageIsoCode(), exts[i]); + file_path = fmt::format("{}{}_{:.2s}.{}", base_path, prefix, GetCurrentLanguageIsoCode(), extension); if (FioCheckFileExists(file_path, dir)) return file_path; - seprintf(slash + 1, lastof(file_path), "%s.%s", prefix, exts[i]); + file_path = fmt::format("{}{}.{}", base_path, prefix, extension); if (FioCheckFileExists(file_path, dir)) return file_path; } - return nullptr; + return std::nullopt; } diff --git a/src/textfile_gui.h b/src/textfile_gui.h index cdcae73888..d7d0a8391d 100644 --- a/src/textfile_gui.h +++ b/src/textfile_gui.h @@ -14,8 +14,9 @@ #include "strings_func.h" #include "textfile_type.h" #include "window_gui.h" +#include -const char *GetTextfile(TextfileType type, Subdirectory dir, const char *filename); +std::optional GetTextfile(TextfileType type, Subdirectory dir, const std::string &filename); /** Window for displaying a textfile */ struct TextfileWindow : public Window, MissingGlyphSearcher { @@ -51,7 +52,7 @@ struct TextfileWindow : public Window, MissingGlyphSearcher { bool Monospace() override; void SetFontNames(FontCacheSettings *settings, const char *font_name, const void *os_data) override; - virtual void LoadTextfile(const char *textfile, Subdirectory dir); + virtual void LoadTextfile(const std::string &textfile, Subdirectory dir); private: uint ReflowContent();