diff --git a/src/openrct2-ui/TextComposition.cpp b/src/openrct2-ui/TextComposition.cpp index 66184cb926..8f76d37c4e 100644 --- a/src/openrct2-ui/TextComposition.cpp +++ b/src/openrct2-ui/TextComposition.cpp @@ -85,9 +85,7 @@ void TextComposition::HandleMessage(const SDL_Event* e) break; } - utf8* newText = String::Duplicate(e->text.text); - Insert(newText); - Memory::Free(newText); + Insert(e->text.text); console.RefreshCaret(_session.SelectionStart); WindowUpdateTextbox(); diff --git a/src/openrct2-ui/windows/ScenarioSelect.cpp b/src/openrct2-ui/windows/ScenarioSelect.cpp index 80d3a8e2ea..112b861958 100644 --- a/src/openrct2-ui/windows/ScenarioSelect.cpp +++ b/src/openrct2-ui/windows/ScenarioSelect.cpp @@ -539,14 +539,14 @@ static void WindowScenarioselectPaint(WindowBase* w, DrawPixelInfo* dpi) if (scenario->Highscore != nullptr) { // TODO: Should probably be translatable - const utf8* completedByName = "???"; - if (!String::IsNullOrEmpty(scenario->Highscore->name)) + u8string completedByName = "???"; + if (!scenario->Highscore->name.empty()) { completedByName = scenario->Highscore->name; } ft = Formatter(); ft.Add(STR_STRING); - ft.Add(completedByName); + ft.Add(completedByName.c_str()); ft.Add(scenario->Highscore->company_value); screenPos.y += DrawTextWrapped(*dpi, screenPos, 170, STR_COMPLETED_BY_WITH_COMPANY_VALUE, ft); } @@ -623,16 +623,15 @@ static void WindowScenarioselectScrollpaint(WindowBase* w, DrawPixelInfo* dpi, i { window_scenarioselect_widgets[WIDX_SCENARIOLIST].width() - 45, y + 1 }); // Draw completion score - const utf8* completedByName = "???"; - if (!String::IsNullOrEmpty(scenario->Highscore->name)) + u8string completedByName = "???"; + if (!scenario->Highscore->name.empty()) { completedByName = scenario->Highscore->name; } - SafeStrCpy(buffer, completedByName, 64); ft = Formatter(); ft.Add(STR_COMPLETED_BY); ft.Add(STR_STRING); - ft.Add(buffer); + ft.Add(completedByName.c_str()); DrawTextBasic( *dpi, { scrollCentre, y + scenarioTitleHeight + 1 }, format, ft, { FontStyle::Small, TextAlignment::CENTRE }); diff --git a/src/openrct2/core/String.cpp b/src/openrct2/core/String.cpp index 8bb306a563..ccdd7d0fbf 100644 --- a/src/openrct2/core/String.cpp +++ b/src/openrct2/core/String.cpp @@ -403,35 +403,6 @@ namespace String return buffer; } - utf8* Duplicate(const std::string& src) - { - return String::Duplicate(src.c_str()); - } - - utf8* Duplicate(const utf8* src) - { - utf8* result = nullptr; - if (src != nullptr) - { - size_t srcSize = SizeOf(src) + 1; - result = Memory::Allocate(srcSize); - std::memcpy(result, src, srcSize); - } - return result; - } - - utf8* DiscardUse(utf8** ptr, utf8* replacement) - { - Memory::Free(*ptr); - *ptr = replacement; - return replacement; - } - - utf8* DiscardDuplicate(utf8** ptr, const utf8* replacement) - { - return DiscardUse(ptr, String::Duplicate(replacement)); - } - std::vector Split(std::string_view s, std::string_view delimiter) { if (delimiter.empty()) diff --git a/src/openrct2/core/String.hpp b/src/openrct2/core/String.hpp index e4c34ab8d4..49389b0804 100644 --- a/src/openrct2/core/String.hpp +++ b/src/openrct2/core/String.hpp @@ -82,18 +82,6 @@ namespace String u8string StdFormat(const utf8* format, ...); u8string Format_VA(const utf8* format, va_list args); utf8* AppendFormat(utf8* buffer, size_t bufferSize, const utf8* format, ...); - utf8* Duplicate(const std::string& src); - utf8* Duplicate(const utf8* src); - - /** - * Helper method to free the string a string pointer points to and set it to a replacement string. - */ - utf8* DiscardUse(utf8** ptr, utf8* replacement); - - /** - * Helper method to free the string a string pointer points to and set it to a copy of a replacement string. - */ - utf8* DiscardDuplicate(utf8** ptr, const utf8* replacement); /** * Splits the given string by a delimiter and returns the values as a new string array. diff --git a/src/openrct2/scenario/ScenarioRepository.cpp b/src/openrct2/scenario/ScenarioRepository.cpp index c1fa517d8f..6b7a4c78aa 100644 --- a/src/openrct2/scenario/ScenarioRepository.cpp +++ b/src/openrct2/scenario/ScenarioRepository.cpp @@ -117,8 +117,6 @@ static int32_t ScenarioIndexEntryCompareByIndex(const ScenarioIndexEntry& entryA static void ScenarioHighscoreFree(ScenarioHighscoreEntry* highscore) { - SafeFree(highscore->fileName); - SafeFree(highscore->name); SafeDelete(highscore); } @@ -465,7 +463,7 @@ public: // Check if record company value has been broken or the highscore is the same but no name is registered ScenarioHighscoreEntry* highscore = scenario->Highscore; if (highscore == nullptr || companyValue > highscore->company_value - || (String::IsNullOrEmpty(highscore->name) && companyValue == highscore->company_value)) + || (highscore->name.empty() && companyValue == highscore->company_value)) { if (highscore == nullptr) { @@ -475,15 +473,13 @@ public: } else { - if (!String::IsNullOrEmpty(highscore->name)) + if (!highscore->name.empty()) { highscore->timestamp = Platform::GetDatetimeNowUTC(); } - SafeFree(highscore->fileName); - SafeFree(highscore->name); } - highscore->fileName = String::Duplicate(Path::GetFileName(scenario->Path)); - highscore->name = String::Duplicate(name); + highscore->fileName = Path::GetFileName(scenario->Path); + highscore->name = name != nullptr ? name : ""; highscore->company_value = companyValue; SaveHighscores(); return true; @@ -493,10 +489,19 @@ public: } private: - ScenarioIndexEntry* GetByFilename(const utf8* filename) + ScenarioIndexEntry* GetByFilename(u8string_view filename) { - const ScenarioRepository* repo = this; - return const_cast(repo->GetByFilename(filename)); + for (auto& scenario : _scenarios) + { + const auto scenarioFilename = Path::GetFileName(scenario.Path); + + // Note: this is always case insensitive search for cross platform consistency + if (String::Equals(filename, scenarioFilename, true)) + { + return &scenario; + } + } + return nullptr; } ScenarioIndexEntry* GetByPath(const utf8* path) @@ -623,8 +628,8 @@ private: for (uint32_t i = 0; i < numHighscores; i++) { ScenarioHighscoreEntry* highscore = InsertHighscore(); - highscore->fileName = fs.ReadString(); - highscore->name = fs.ReadString(); + highscore->fileName = fs.ReadStdString(); + highscore->name = fs.ReadStdString(); highscore->company_value = fileVersion == 1 ? fs.ReadValue() : fs.ReadValue(); highscore->timestamp = fs.ReadValue(); } @@ -684,9 +689,8 @@ private: // Check if legacy highscore is better if (scBasic.CompanyValue > highscore->company_value) { - SafeFree(highscore->name); std::string name = RCT2StringToUTF8(scBasic.CompletedBy, RCT2LanguageId::EnglishUK); - highscore->name = String::Duplicate(name.c_str()); + highscore->name = name; highscore->company_value = scBasic.CompanyValue; highscore->timestamp = DATETIME64_MIN; break; @@ -696,9 +700,9 @@ private: if (notFound) { ScenarioHighscoreEntry* highscore = InsertHighscore(); - highscore->fileName = String::Duplicate(scBasic.Path); + highscore->fileName = scBasic.Path; std::string name = RCT2StringToUTF8(scBasic.CompletedBy, RCT2LanguageId::EnglishUK); - highscore->name = String::Duplicate(name.c_str()); + highscore->name = name; highscore->company_value = scBasic.CompanyValue; highscore->timestamp = DATETIME64_MIN; } @@ -728,7 +732,6 @@ private: ScenarioHighscoreEntry* InsertHighscore() { auto highscore = new ScenarioHighscoreEntry(); - std::memset(highscore, 0, sizeof(ScenarioHighscoreEntry)); _highscores.push_back(highscore); return highscore; } diff --git a/src/openrct2/scenario/ScenarioRepository.h b/src/openrct2/scenario/ScenarioRepository.h index d55c49d643..f887147ee0 100644 --- a/src/openrct2/scenario/ScenarioRepository.h +++ b/src/openrct2/scenario/ScenarioRepository.h @@ -11,6 +11,7 @@ #pragma once #include "../common.h" +#include "../core/String.hpp" #include "../scenario/Scenario.h" #include @@ -19,10 +20,10 @@ struct RCTObjectEntry; struct ScenarioHighscoreEntry { - utf8* fileName; - utf8* name; - money64 company_value; - datetime64 timestamp; + u8string fileName; + u8string name; + money64 company_value{}; + datetime64 timestamp{}; }; enum class ScenarioSource : uint8_t