diff --git a/src/script/api/script_basestation.cpp b/src/script/api/script_basestation.cpp index 788d549500..4835edc4bd 100644 --- a/src/script/api/script_basestation.cpp +++ b/src/script/api/script_basestation.cpp @@ -40,7 +40,7 @@ EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY); EnforcePrecondition(false, IsValidBaseStation(station_id)); EnforcePrecondition(false, name != nullptr); - const char *text = name->GetDecodedText(); + const std::string &text = name->GetDecodedText(); EnforcePreconditionEncodedText(false, text); EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_STATION_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG); diff --git a/src/script/api/script_company.cpp b/src/script/api/script_company.cpp index 33c0c0ea48..b35234f5a7 100644 --- a/src/script/api/script_company.cpp +++ b/src/script/api/script_company.cpp @@ -48,7 +48,7 @@ CCountedPtr counter(name); EnforcePrecondition(false, name != nullptr); - const char *text = name->GetDecodedText(); + const std::string &text = name->GetDecodedText(); EnforcePreconditionEncodedText(false, text); EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_COMPANY_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG); @@ -69,7 +69,7 @@ CCountedPtr counter(name); EnforcePrecondition(false, name != nullptr); - const char *text = name->GetDecodedText(); + const std::string &text = name->GetDecodedText(); EnforcePreconditionEncodedText(false, text); EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_PRESIDENT_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG); diff --git a/src/script/api/script_error.hpp b/src/script/api/script_error.hpp index 6d3d476f7b..f4b3832ef5 100644 --- a/src/script/api/script_error.hpp +++ b/src/script/api/script_error.hpp @@ -42,7 +42,7 @@ * @param string The string that is checked. */ #define EnforcePreconditionEncodedText(returnval, string) \ - if (StrEmpty(string)) { \ + if (string.empty()) { \ ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_FAILED); \ return returnval; \ } diff --git a/src/script/api/script_goal.cpp b/src/script/api/script_goal.cpp index d908f4e720..8260a7d436 100644 --- a/src/script/api/script_goal.cpp +++ b/src/script/api/script_goal.cpp @@ -34,7 +34,7 @@ EnforcePrecondition(GOAL_INVALID, ScriptObject::GetCompany() == OWNER_DEITY); EnforcePrecondition(GOAL_INVALID, goal != nullptr); - const char *text = goal->GetEncodedText(); + const std::string &text = goal->GetEncodedText(); EnforcePreconditionEncodedText(GOAL_INVALID, text); EnforcePrecondition(GOAL_INVALID, company == ScriptCompany::COMPANY_INVALID || ScriptCompany::ResolveCompanyID(company) != ScriptCompany::COMPANY_INVALID); @@ -71,9 +71,10 @@ EnforcePrecondition(false, IsValidGoal(goal_id)); EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY); EnforcePrecondition(false, goal != nullptr); - EnforcePrecondition(false, !StrEmpty(goal->GetEncodedText())); + const std::string &text = goal->GetEncodedText(); + EnforcePreconditionEncodedText(false, text); - return ScriptObject::Command::Do(goal_id, goal->GetEncodedText()); + return ScriptObject::Command::Do(goal_id, text); } /* static */ bool ScriptGoal::SetProgress(GoalID goal_id, Text *progress) @@ -83,12 +84,7 @@ EnforcePrecondition(false, IsValidGoal(goal_id)); EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY); - /* Ensure null as used for empty string. */ - if (progress != nullptr && StrEmpty(progress->GetEncodedText())) { - progress = nullptr; - } - - return ScriptObject::Command::Do(goal_id, progress != nullptr ? std::string{ progress->GetEncodedText() } : std::string{}); + return ScriptObject::Command::Do(goal_id, progress != nullptr ? progress->GetEncodedText() : std::string{}); } /* static */ bool ScriptGoal::SetCompleted(GoalID goal_id, bool completed) @@ -114,7 +110,7 @@ EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY); EnforcePrecondition(false, question != nullptr); - const char *text = question->GetEncodedText(); + const std::string &text = question->GetEncodedText(); EnforcePreconditionEncodedText(false, text); uint min_buttons = (type == QT_QUESTION ? 1 : 0); EnforcePrecondition(false, CountBits(buttons) >= min_buttons && CountBits(buttons) <= 3); diff --git a/src/script/api/script_group.cpp b/src/script/api/script_group.cpp index dbf4c0280e..9910dae3a4 100644 --- a/src/script/api/script_group.cpp +++ b/src/script/api/script_group.cpp @@ -57,7 +57,7 @@ EnforcePrecondition(false, IsValidGroup(group_id)); EnforcePrecondition(false, name != nullptr); - const char *text = name->GetDecodedText(); + const std::string &text = name->GetDecodedText(); EnforcePreconditionEncodedText(false, text); EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_GROUP_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG); diff --git a/src/script/api/script_industry.cpp b/src/script/api/script_industry.cpp index a27ea1a6e3..7ca847f05a 100644 --- a/src/script/api/script_industry.cpp +++ b/src/script/api/script_industry.cpp @@ -53,14 +53,9 @@ { CCountedPtr counter(text); - const char *encoded_text = nullptr; - if (text != nullptr) { - encoded_text = text->GetEncodedText(); - EnforcePreconditionEncodedText(false, encoded_text); - } EnforcePrecondition(false, IsValidIndustry(industry_id)); - return ScriptObject::Command::Do(industry_id, std::string{ encoded_text ? encoded_text : "" }); + return ScriptObject::Command::Do(industry_id, text != nullptr ? text->GetEncodedText() : std::string{}); } /* static */ ScriptIndustry::CargoAcceptState ScriptIndustry::IsCargoAccepted(IndustryID industry_id, CargoID cargo_id) diff --git a/src/script/api/script_industry.hpp b/src/script/api/script_industry.hpp index 95133da0ec..f5e435d2dd 100644 --- a/src/script/api/script_industry.hpp +++ b/src/script/api/script_industry.hpp @@ -84,7 +84,7 @@ public: /** * Set the custom text of an industry, shown in the GUI. * @param industry_id The industry to set the custom text of. - * @param text The text to set it to (can be either a raw string, or a ScriptText object). If null is passed, the text will be removed. + * @param text The text to set it to (can be either a raw string, or a ScriptText object). If null, or an empty string, is passed, the text will be removed. * @pre IsValidIndustry(industry_id). * @return True if the action succeeded. * @api -ai diff --git a/src/script/api/script_league.cpp b/src/script/api/script_league.cpp index d50eff8446..928c9e2971 100644 --- a/src/script/api/script_league.cpp +++ b/src/script/api/script_league.cpp @@ -32,11 +32,11 @@ EnforcePrecondition(LEAGUE_TABLE_INVALID, ScriptObject::GetCompany() == OWNER_DEITY); EnforcePrecondition(LEAGUE_TABLE_INVALID, title != nullptr); - const char *encoded_title = title->GetEncodedText(); + const std::string &encoded_title = title->GetEncodedText(); EnforcePreconditionEncodedText(LEAGUE_TABLE_INVALID, encoded_title); - auto encoded_header = (header != nullptr ? std::string{ header->GetEncodedText() } : std::string{}); - auto encoded_footer = (footer != nullptr ? std::string{ footer->GetEncodedText() } : std::string{}); + const std::string &encoded_header = (header != nullptr ? header->GetEncodedText() : std::string{}); + const std::string &encoded_footer = (footer != nullptr ? footer->GetEncodedText() : std::string{}); if (!ScriptObject::Command::Do(&ScriptInstance::DoCommandReturnLeagueTableID, encoded_title, encoded_header, encoded_footer)) return LEAGUE_TABLE_INVALID; @@ -63,12 +63,11 @@ if (company == ScriptCompany::COMPANY_INVALID) c = INVALID_COMPANY; EnforcePrecondition(LEAGUE_TABLE_ELEMENT_INVALID, text != nullptr); - const char *encoded_text_ptr = text->GetEncodedText(); - EnforcePreconditionEncodedText(LEAGUE_TABLE_ELEMENT_INVALID, encoded_text_ptr); - std::string encoded_text = encoded_text_ptr; // save into string so GetEncodedText can reuse the internal buffer + const std::string &encoded_text = text->GetEncodedText(); + EnforcePreconditionEncodedText(LEAGUE_TABLE_ELEMENT_INVALID, encoded_text); EnforcePrecondition(LEAGUE_TABLE_ELEMENT_INVALID, score != nullptr); - const char *encoded_score = score->GetEncodedText(); + const std::string &encoded_score = score->GetEncodedText(); EnforcePreconditionEncodedText(LEAGUE_TABLE_ELEMENT_INVALID, encoded_score); EnforcePrecondition(LEAGUE_TABLE_ELEMENT_INVALID, IsValidLink(Link((::LinkType)link_type, link_target))); @@ -91,7 +90,7 @@ if (company == ScriptCompany::COMPANY_INVALID) c = INVALID_COMPANY; EnforcePrecondition(false, text != nullptr); - const char *encoded_text = text->GetEncodedText(); + const std::string &encoded_text = text->GetEncodedText(); EnforcePreconditionEncodedText(false, encoded_text); EnforcePrecondition(false, IsValidLink(Link((::LinkType)link_type, link_target))); @@ -107,7 +106,7 @@ EnforcePrecondition(false, IsValidLeagueTableElement(element)); EnforcePrecondition(false, score != nullptr); - const char *encoded_score = score->GetEncodedText(); + const std::string &encoded_score = score->GetEncodedText(); EnforcePreconditionEncodedText(false, encoded_score); return ScriptObject::Command::Do(element, rating, encoded_score); diff --git a/src/script/api/script_news.cpp b/src/script/api/script_news.cpp index 119cbc735c..0939c8a3b4 100644 --- a/src/script/api/script_news.cpp +++ b/src/script/api/script_news.cpp @@ -25,7 +25,7 @@ CCountedPtr counter(text); EnforcePrecondition(false, text != nullptr); - const char *encoded = text->GetEncodedText(); + const std::string &encoded = text->GetEncodedText(); EnforcePreconditionEncodedText(false, encoded); EnforcePrecondition(false, type == NT_ECONOMY || type == NT_SUBSIDIES || type == NT_GENERAL); EnforcePrecondition(false, company == ScriptCompany::COMPANY_INVALID || ScriptCompany::ResolveCompanyID(company) != ScriptCompany::COMPANY_INVALID); diff --git a/src/script/api/script_sign.cpp b/src/script/api/script_sign.cpp index c95093a791..269d3e69dc 100644 --- a/src/script/api/script_sign.cpp +++ b/src/script/api/script_sign.cpp @@ -38,7 +38,7 @@ EnforcePrecondition(false, IsValidSign(sign_id)); EnforcePrecondition(false, name != nullptr); - const char *text = name->GetDecodedText(); + const std::string &text = name->GetDecodedText(); EnforcePreconditionEncodedText(false, text); EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_SIGN_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG); @@ -73,7 +73,7 @@ EnforcePrecondition(INVALID_SIGN, ::IsValidTile(location)); EnforcePrecondition(INVALID_SIGN, name != nullptr); - const char *text = name->GetDecodedText(); + const std::string &text = name->GetDecodedText(); EnforcePreconditionEncodedText(INVALID_SIGN, text); EnforcePreconditionCustomError(INVALID_SIGN, ::Utf8StringLength(text) < MAX_LENGTH_SIGN_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG); diff --git a/src/script/api/script_story_page.cpp b/src/script/api/script_story_page.cpp index f767472e02..970e983a70 100644 --- a/src/script/api/script_story_page.cpp +++ b/src/script/api/script_story_page.cpp @@ -49,7 +49,7 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type) if (company == ScriptCompany::COMPANY_INVALID) c = INVALID_COMPANY; if (!ScriptObject::Command::Do(&ScriptInstance::DoCommandReturnStoryPageID, - (::CompanyID)c, title != nullptr ? std::string{ title->GetEncodedText() } : std::string{})) return STORY_PAGE_INVALID; + (::CompanyID)c, title != nullptr ? title->GetEncodedText() : std::string{})) return STORY_PAGE_INVALID; /* In case of test-mode, we return StoryPageID 0 */ return (ScriptStoryPage::StoryPageID)0; @@ -63,7 +63,12 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type) EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, ScriptObject::GetCompany() == OWNER_DEITY); EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, IsValidStoryPage(story_page_id)); - EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, !StoryPageElementTypeRequiresText(btype) || (text != nullptr && !StrEmpty(text->GetEncodedText()))); + std::string encoded_text; + if (StoryPageElementTypeRequiresText(btype)) { + EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, text != nullptr); + encoded_text = text->GetEncodedText(); + EnforcePreconditionEncodedText(STORY_PAGE_ELEMENT_INVALID, encoded_text); + } EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, type != SPET_LOCATION || ::IsValidTile(reference)); EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, type != SPET_GOAL || ScriptGoal::IsValidGoal((ScriptGoal::GoalID)reference)); EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, type != SPET_GOAL || !(StoryPage::Get(story_page_id)->company == INVALID_COMPANY && Goal::Get(reference)->company != INVALID_COMPANY)); @@ -90,7 +95,7 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type) reftile, (::StoryPageID)story_page_id, (::StoryPageElementType)type, refid, - StoryPageElementTypeRequiresText(btype) ? std::string{ text->GetEncodedText() } : std::string{})) return STORY_PAGE_ELEMENT_INVALID; + encoded_text)) return STORY_PAGE_ELEMENT_INVALID; /* In case of test-mode, we return StoryPageElementID 0 */ return (ScriptStoryPage::StoryPageElementID)0; @@ -107,7 +112,12 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type) StoryPage *p = StoryPage::Get(pe->page); ::StoryPageElementType type = pe->type; - EnforcePrecondition(false, !StoryPageElementTypeRequiresText(type) || (text != nullptr && !StrEmpty(text->GetEncodedText()))); + std::string encoded_text; + if (StoryPageElementTypeRequiresText(type)) { + EnforcePrecondition(false, text != nullptr); + encoded_text = text->GetEncodedText(); + EnforcePreconditionEncodedText(false, encoded_text); + } EnforcePrecondition(false, type != ::SPET_LOCATION || ::IsValidTile(reference)); EnforcePrecondition(false, type != ::SPET_GOAL || ScriptGoal::IsValidGoal((ScriptGoal::GoalID)reference)); EnforcePrecondition(false, type != ::SPET_GOAL || !(p->company == INVALID_COMPANY && Goal::Get(reference)->company != INVALID_COMPANY)); @@ -130,10 +140,7 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type) NOT_REACHED(); } - return ScriptObject::Command::Do(reftile, - story_page_element_id, - refid, - StoryPageElementTypeRequiresText(type) ? std::string{ text->GetEncodedText() } : std::string{}); + return ScriptObject::Command::Do(reftile, story_page_element_id, refid, encoded_text); } /* static */ uint32 ScriptStoryPage::GetPageSortValue(StoryPageID story_page_id) @@ -157,7 +164,7 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type) EnforcePrecondition(false, IsValidStoryPage(story_page_id)); EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY); - return ScriptObject::Command::Do(story_page_id, title != nullptr ? std::string{ title->GetEncodedText() } : std::string{}); + return ScriptObject::Command::Do(story_page_id, title != nullptr ? title->GetEncodedText() : std::string{}); } /* static */ ScriptCompany::CompanyID ScriptStoryPage::GetCompany(StoryPageID story_page_id) diff --git a/src/script/api/script_text.cpp b/src/script/api/script_text.cpp index c9040b1d88..d01f3b93f1 100644 --- a/src/script/api/script_text.cpp +++ b/src/script/api/script_text.cpp @@ -18,15 +18,10 @@ #include "../../safeguards.h" -RawText::RawText(const char *text) : text(stredup(text)) +RawText::RawText(const char *text) : text(text) { } -RawText::~RawText() -{ - free(this->text); -} - ScriptText::ScriptText(HSQUIRRELVM vm) : ZeroedMemoryAllocator() @@ -177,7 +172,7 @@ SQInteger ScriptText::_set(HSQUIRRELVM vm) return this->_SetParam(k, vm); } -const char *ScriptText::GetEncodedText() +const std::string ScriptText::GetEncodedText() { static char buf[1024]; int param_count = 0; @@ -208,7 +203,7 @@ char *ScriptText::_GetEncodedText(char *p, char *lastofp, int ¶m_count) return p; } -const char *Text::GetDecodedText() +const std::string Text::GetDecodedText() { const std::string &encoded_text = this->GetEncodedText(); diff --git a/src/script/api/script_text.hpp b/src/script/api/script_text.hpp index 64cf2e7993..66ab2bd47d 100644 --- a/src/script/api/script_text.hpp +++ b/src/script/api/script_text.hpp @@ -21,17 +21,17 @@ class Text : public ScriptObject { public: /** * Convert a ScriptText to a normal string. - * @return A string (in a static buffer), or nullptr. + * @return A string. * @api -all */ - virtual const char *GetEncodedText() = 0; + virtual const std::string GetEncodedText() = 0; /** * Convert a #ScriptText into a decoded normal string. - * @return A string (in a static buffer), or nullptr. + * @return A string. * @api -all */ - const char *GetDecodedText(); + const std::string GetDecodedText(); }; /** @@ -41,11 +41,10 @@ public: class RawText : public Text { public: RawText(const char *text); - ~RawText(); - const char *GetEncodedText() override { return this->text; } + const std::string GetEncodedText() override { return this->text; } private: - const char *text; + const std::string text; }; /** @@ -125,7 +124,7 @@ public: /** * @api -all */ - virtual const char *GetEncodedText(); + virtual const std::string GetEncodedText(); private: StringID string; diff --git a/src/script/api/script_town.cpp b/src/script/api/script_town.cpp index 047cbe1a69..a3108f6839 100644 --- a/src/script/api/script_town.cpp +++ b/src/script/api/script_town.cpp @@ -44,29 +44,23 @@ { CCountedPtr counter(name); - const char *text = nullptr; + EnforcePrecondition(false, IsValidTown(town_id)); + std::string text; if (name != nullptr) { text = name->GetDecodedText(); - EnforcePreconditionEncodedText(false, text); EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_TOWN_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG); } - EnforcePrecondition(false, IsValidTown(town_id)); - return ScriptObject::Command::Do(town_id, text != nullptr ? std::string{ text } : std::string{}); + return ScriptObject::Command::Do(town_id, text); } /* static */ bool ScriptTown::SetText(TownID town_id, Text *text) { CCountedPtr counter(text); - const char *encoded_text = nullptr; - if (text != nullptr) { - encoded_text = text->GetEncodedText(); - EnforcePreconditionEncodedText(false, encoded_text); - } EnforcePrecondition(false, IsValidTown(town_id)); - return ScriptObject::Command::Do(town_id, encoded_text != nullptr ? std::string{ encoded_text } : std::string{}); + return ScriptObject::Command::Do(town_id, text != nullptr ? text->GetEncodedText() : std::string{}); } /* static */ int32 ScriptTown::GetPopulation(TownID town_id) @@ -294,10 +288,9 @@ layout = (RoadLayout) (byte)_settings_game.economy.town_layout; } - const char *text = nullptr; + std::string text; if (name != nullptr) { text = name->GetDecodedText(); - EnforcePreconditionEncodedText(false, text); EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_TOWN_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG); } uint32 townnameparts; @@ -306,7 +299,7 @@ return false; } - return ScriptObject::Command::Do(tile, (::TownSize)size, city, (::TownLayout)layout, false, townnameparts, text != nullptr ? std::string{ text } : std::string{}); + return ScriptObject::Command::Do(tile, (::TownSize)size, city, (::TownLayout)layout, false, townnameparts, text); } /* static */ ScriptTown::TownRating ScriptTown::GetRating(TownID town_id, ScriptCompany::CompanyID company_id) diff --git a/src/script/api/script_town.hpp b/src/script/api/script_town.hpp index d64d12ef6b..b9e2791a74 100644 --- a/src/script/api/script_town.hpp +++ b/src/script/api/script_town.hpp @@ -147,7 +147,7 @@ public: /** * Rename a town. * @param town_id The town to rename - * @param name The new name of the town. If null is passed, the town name will be reset to the default name. + * @param name The new name of the town. If null, or an empty string, is passed, the town name will be reset to the default name. * @pre IsValidTown(town_id). * @return True if the action succeeded. * @api -ai @@ -157,7 +157,7 @@ public: /** * Set the custom text of a town, shown in the GUI. * @param town_id The town to set the custom text of. - * @param text The text to set it to (can be either a raw string, or a ScriptText object). If null is passed, the text will be removed. + * @param text The text to set it to (can be either a raw string, or a ScriptText object). If null, or an empty string, is passed, the text will be removed. * @pre IsValidTown(town_id). * @return True if the action succeeded. * @api -ai @@ -401,7 +401,7 @@ public: * @param size The town size of the new town. * @param city True if the new town should be a city. * @param layout The town layout of the new town. - * @param name The name of the new town. Pass null to use a random town name. + * @param name The name of the new town. Pass null, or an empty string, to use a random town name. * @game @pre no company mode in scope || ScriptSettings.GetValue("economy.found_town") != 0. * @ai @pre ScriptSettings.GetValue("economy.found_town") != 0. * @game @pre no company mode in scope || size != TOWN_SIZE_LARGE. diff --git a/src/script/api/script_vehicle.cpp b/src/script/api/script_vehicle.cpp index 851d72f3b8..9450605c25 100644 --- a/src/script/api/script_vehicle.cpp +++ b/src/script/api/script_vehicle.cpp @@ -244,7 +244,7 @@ EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY); EnforcePrecondition(false, IsValidVehicle(vehicle_id)); EnforcePrecondition(false, name != nullptr); - const char *text = name->GetDecodedText(); + const std::string &text = name->GetDecodedText(); EnforcePreconditionEncodedText(false, text); EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_VEHICLE_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG);