Codechange: [Script] Don't expose static buffers outside of ScriptText

pull/491/head
glx22 1 year ago committed by Loïc Guilloux
parent e735370318
commit 3559576166

@ -40,7 +40,7 @@
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY); EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
EnforcePrecondition(false, IsValidBaseStation(station_id)); EnforcePrecondition(false, IsValidBaseStation(station_id));
EnforcePrecondition(false, name != nullptr); EnforcePrecondition(false, name != nullptr);
const char *text = name->GetDecodedText(); const std::string &text = name->GetDecodedText();
EnforcePreconditionEncodedText(false, text); EnforcePreconditionEncodedText(false, text);
EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_STATION_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG); EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_STATION_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG);

@ -48,7 +48,7 @@
CCountedPtr<Text> counter(name); CCountedPtr<Text> counter(name);
EnforcePrecondition(false, name != nullptr); EnforcePrecondition(false, name != nullptr);
const char *text = name->GetDecodedText(); const std::string &text = name->GetDecodedText();
EnforcePreconditionEncodedText(false, text); EnforcePreconditionEncodedText(false, text);
EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_COMPANY_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG); EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_COMPANY_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG);
@ -69,7 +69,7 @@
CCountedPtr<Text> counter(name); CCountedPtr<Text> counter(name);
EnforcePrecondition(false, name != nullptr); EnforcePrecondition(false, name != nullptr);
const char *text = name->GetDecodedText(); const std::string &text = name->GetDecodedText();
EnforcePreconditionEncodedText(false, text); EnforcePreconditionEncodedText(false, text);
EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_PRESIDENT_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG); EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_PRESIDENT_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG);

@ -42,7 +42,7 @@
* @param string The string that is checked. * @param string The string that is checked.
*/ */
#define EnforcePreconditionEncodedText(returnval, string) \ #define EnforcePreconditionEncodedText(returnval, string) \
if (StrEmpty(string)) { \ if (string.empty()) { \
ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_FAILED); \ ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_FAILED); \
return returnval; \ return returnval; \
} }

@ -34,7 +34,7 @@
EnforcePrecondition(GOAL_INVALID, ScriptObject::GetCompany() == OWNER_DEITY); EnforcePrecondition(GOAL_INVALID, ScriptObject::GetCompany() == OWNER_DEITY);
EnforcePrecondition(GOAL_INVALID, goal != nullptr); EnforcePrecondition(GOAL_INVALID, goal != nullptr);
const char *text = goal->GetEncodedText(); const std::string &text = goal->GetEncodedText();
EnforcePreconditionEncodedText(GOAL_INVALID, text); EnforcePreconditionEncodedText(GOAL_INVALID, text);
EnforcePrecondition(GOAL_INVALID, company == ScriptCompany::COMPANY_INVALID || ScriptCompany::ResolveCompanyID(company) != ScriptCompany::COMPANY_INVALID); EnforcePrecondition(GOAL_INVALID, company == ScriptCompany::COMPANY_INVALID || ScriptCompany::ResolveCompanyID(company) != ScriptCompany::COMPANY_INVALID);
@ -71,9 +71,10 @@
EnforcePrecondition(false, IsValidGoal(goal_id)); EnforcePrecondition(false, IsValidGoal(goal_id));
EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY); EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY);
EnforcePrecondition(false, goal != nullptr); EnforcePrecondition(false, goal != nullptr);
EnforcePrecondition(false, !StrEmpty(goal->GetEncodedText())); const std::string &text = goal->GetEncodedText();
EnforcePreconditionEncodedText(false, text);
return ScriptObject::Command<CMD_SET_GOAL_TEXT>::Do(goal_id, goal->GetEncodedText()); return ScriptObject::Command<CMD_SET_GOAL_TEXT>::Do(goal_id, text);
} }
/* static */ bool ScriptGoal::SetProgress(GoalID goal_id, Text *progress) /* static */ bool ScriptGoal::SetProgress(GoalID goal_id, Text *progress)
@ -83,12 +84,7 @@
EnforcePrecondition(false, IsValidGoal(goal_id)); EnforcePrecondition(false, IsValidGoal(goal_id));
EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY); EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY);
/* Ensure null as used for empty string. */ return ScriptObject::Command<CMD_SET_GOAL_PROGRESS>::Do(goal_id, progress != nullptr ? progress->GetEncodedText() : std::string{});
if (progress != nullptr && StrEmpty(progress->GetEncodedText())) {
progress = nullptr;
}
return ScriptObject::Command<CMD_SET_GOAL_PROGRESS>::Do(goal_id, progress != nullptr ? std::string{ progress->GetEncodedText() } : std::string{});
} }
/* static */ bool ScriptGoal::SetCompleted(GoalID goal_id, bool completed) /* static */ bool ScriptGoal::SetCompleted(GoalID goal_id, bool completed)
@ -114,7 +110,7 @@
EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY); EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY);
EnforcePrecondition(false, question != nullptr); EnforcePrecondition(false, question != nullptr);
const char *text = question->GetEncodedText(); const std::string &text = question->GetEncodedText();
EnforcePreconditionEncodedText(false, text); EnforcePreconditionEncodedText(false, text);
uint min_buttons = (type == QT_QUESTION ? 1 : 0); uint min_buttons = (type == QT_QUESTION ? 1 : 0);
EnforcePrecondition(false, CountBits(buttons) >= min_buttons && CountBits(buttons) <= 3); EnforcePrecondition(false, CountBits(buttons) >= min_buttons && CountBits(buttons) <= 3);

@ -57,7 +57,7 @@
EnforcePrecondition(false, IsValidGroup(group_id)); EnforcePrecondition(false, IsValidGroup(group_id));
EnforcePrecondition(false, name != nullptr); EnforcePrecondition(false, name != nullptr);
const char *text = name->GetDecodedText(); const std::string &text = name->GetDecodedText();
EnforcePreconditionEncodedText(false, text); EnforcePreconditionEncodedText(false, text);
EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_GROUP_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG); EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_GROUP_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG);

@ -53,14 +53,9 @@
{ {
CCountedPtr<Text> counter(text); CCountedPtr<Text> counter(text);
const char *encoded_text = nullptr;
if (text != nullptr) {
encoded_text = text->GetEncodedText();
EnforcePreconditionEncodedText(false, encoded_text);
}
EnforcePrecondition(false, IsValidIndustry(industry_id)); EnforcePrecondition(false, IsValidIndustry(industry_id));
return ScriptObject::Command<CMD_INDUSTRY_SET_TEXT>::Do(industry_id, std::string{ encoded_text ? encoded_text : "" }); return ScriptObject::Command<CMD_INDUSTRY_SET_TEXT>::Do(industry_id, text != nullptr ? text->GetEncodedText() : std::string{});
} }
/* static */ ScriptIndustry::CargoAcceptState ScriptIndustry::IsCargoAccepted(IndustryID industry_id, CargoID cargo_id) /* static */ ScriptIndustry::CargoAcceptState ScriptIndustry::IsCargoAccepted(IndustryID industry_id, CargoID cargo_id)

@ -84,7 +84,7 @@ public:
/** /**
* Set the custom text of an industry, shown in the GUI. * Set the custom text of an industry, shown in the GUI.
* @param industry_id The industry to set the custom text of. * @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). * @pre IsValidIndustry(industry_id).
* @return True if the action succeeded. * @return True if the action succeeded.
* @api -ai * @api -ai

@ -32,11 +32,11 @@
EnforcePrecondition(LEAGUE_TABLE_INVALID, ScriptObject::GetCompany() == OWNER_DEITY); EnforcePrecondition(LEAGUE_TABLE_INVALID, ScriptObject::GetCompany() == OWNER_DEITY);
EnforcePrecondition(LEAGUE_TABLE_INVALID, title != nullptr); 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); EnforcePreconditionEncodedText(LEAGUE_TABLE_INVALID, encoded_title);
auto encoded_header = (header != nullptr ? std::string{ header->GetEncodedText() } : std::string{}); const std::string &encoded_header = (header != nullptr ? header->GetEncodedText() : std::string{});
auto encoded_footer = (footer != nullptr ? std::string{ footer->GetEncodedText() } : std::string{}); const std::string &encoded_footer = (footer != nullptr ? footer->GetEncodedText() : std::string{});
if (!ScriptObject::Command<CMD_CREATE_LEAGUE_TABLE>::Do(&ScriptInstance::DoCommandReturnLeagueTableID, encoded_title, encoded_header, encoded_footer)) return LEAGUE_TABLE_INVALID; if (!ScriptObject::Command<CMD_CREATE_LEAGUE_TABLE>::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; if (company == ScriptCompany::COMPANY_INVALID) c = INVALID_COMPANY;
EnforcePrecondition(LEAGUE_TABLE_ELEMENT_INVALID, text != nullptr); EnforcePrecondition(LEAGUE_TABLE_ELEMENT_INVALID, text != nullptr);
const char *encoded_text_ptr = text->GetEncodedText(); const std::string &encoded_text = text->GetEncodedText();
EnforcePreconditionEncodedText(LEAGUE_TABLE_ELEMENT_INVALID, encoded_text_ptr); EnforcePreconditionEncodedText(LEAGUE_TABLE_ELEMENT_INVALID, encoded_text);
std::string encoded_text = encoded_text_ptr; // save into string so GetEncodedText can reuse the internal buffer
EnforcePrecondition(LEAGUE_TABLE_ELEMENT_INVALID, score != nullptr); 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); EnforcePreconditionEncodedText(LEAGUE_TABLE_ELEMENT_INVALID, encoded_score);
EnforcePrecondition(LEAGUE_TABLE_ELEMENT_INVALID, IsValidLink(Link((::LinkType)link_type, link_target))); EnforcePrecondition(LEAGUE_TABLE_ELEMENT_INVALID, IsValidLink(Link((::LinkType)link_type, link_target)));
@ -91,7 +90,7 @@
if (company == ScriptCompany::COMPANY_INVALID) c = INVALID_COMPANY; if (company == ScriptCompany::COMPANY_INVALID) c = INVALID_COMPANY;
EnforcePrecondition(false, text != nullptr); EnforcePrecondition(false, text != nullptr);
const char *encoded_text = text->GetEncodedText(); const std::string &encoded_text = text->GetEncodedText();
EnforcePreconditionEncodedText(false, encoded_text); EnforcePreconditionEncodedText(false, encoded_text);
EnforcePrecondition(false, IsValidLink(Link((::LinkType)link_type, link_target))); EnforcePrecondition(false, IsValidLink(Link((::LinkType)link_type, link_target)));
@ -107,7 +106,7 @@
EnforcePrecondition(false, IsValidLeagueTableElement(element)); EnforcePrecondition(false, IsValidLeagueTableElement(element));
EnforcePrecondition(false, score != nullptr); EnforcePrecondition(false, score != nullptr);
const char *encoded_score = score->GetEncodedText(); const std::string &encoded_score = score->GetEncodedText();
EnforcePreconditionEncodedText(false, encoded_score); EnforcePreconditionEncodedText(false, encoded_score);
return ScriptObject::Command<CMD_UPDATE_LEAGUE_TABLE_ELEMENT_SCORE>::Do(element, rating, encoded_score); return ScriptObject::Command<CMD_UPDATE_LEAGUE_TABLE_ELEMENT_SCORE>::Do(element, rating, encoded_score);

@ -25,7 +25,7 @@
CCountedPtr<Text> counter(text); CCountedPtr<Text> counter(text);
EnforcePrecondition(false, text != nullptr); EnforcePrecondition(false, text != nullptr);
const char *encoded = text->GetEncodedText(); const std::string &encoded = text->GetEncodedText();
EnforcePreconditionEncodedText(false, encoded); EnforcePreconditionEncodedText(false, encoded);
EnforcePrecondition(false, type == NT_ECONOMY || type == NT_SUBSIDIES || type == NT_GENERAL); EnforcePrecondition(false, type == NT_ECONOMY || type == NT_SUBSIDIES || type == NT_GENERAL);
EnforcePrecondition(false, company == ScriptCompany::COMPANY_INVALID || ScriptCompany::ResolveCompanyID(company) != ScriptCompany::COMPANY_INVALID); EnforcePrecondition(false, company == ScriptCompany::COMPANY_INVALID || ScriptCompany::ResolveCompanyID(company) != ScriptCompany::COMPANY_INVALID);

@ -38,7 +38,7 @@
EnforcePrecondition(false, IsValidSign(sign_id)); EnforcePrecondition(false, IsValidSign(sign_id));
EnforcePrecondition(false, name != nullptr); EnforcePrecondition(false, name != nullptr);
const char *text = name->GetDecodedText(); const std::string &text = name->GetDecodedText();
EnforcePreconditionEncodedText(false, text); EnforcePreconditionEncodedText(false, text);
EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_SIGN_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG); 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, ::IsValidTile(location));
EnforcePrecondition(INVALID_SIGN, name != nullptr); EnforcePrecondition(INVALID_SIGN, name != nullptr);
const char *text = name->GetDecodedText(); const std::string &text = name->GetDecodedText();
EnforcePreconditionEncodedText(INVALID_SIGN, text); EnforcePreconditionEncodedText(INVALID_SIGN, text);
EnforcePreconditionCustomError(INVALID_SIGN, ::Utf8StringLength(text) < MAX_LENGTH_SIGN_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG); EnforcePreconditionCustomError(INVALID_SIGN, ::Utf8StringLength(text) < MAX_LENGTH_SIGN_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG);

@ -49,7 +49,7 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type)
if (company == ScriptCompany::COMPANY_INVALID) c = INVALID_COMPANY; if (company == ScriptCompany::COMPANY_INVALID) c = INVALID_COMPANY;
if (!ScriptObject::Command<CMD_CREATE_STORY_PAGE>::Do(&ScriptInstance::DoCommandReturnStoryPageID, if (!ScriptObject::Command<CMD_CREATE_STORY_PAGE>::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 */ /* In case of test-mode, we return StoryPageID 0 */
return (ScriptStoryPage::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, ScriptObject::GetCompany() == OWNER_DEITY);
EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, IsValidStoryPage(story_page_id)); 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_LOCATION || ::IsValidTile(reference));
EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, type != SPET_GOAL || ScriptGoal::IsValidGoal((ScriptGoal::GoalID)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)); 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, reftile,
(::StoryPageID)story_page_id, (::StoryPageElementType)type, (::StoryPageID)story_page_id, (::StoryPageElementType)type,
refid, 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 */ /* In case of test-mode, we return StoryPageElementID 0 */
return (ScriptStoryPage::StoryPageElementID)0; return (ScriptStoryPage::StoryPageElementID)0;
@ -107,7 +112,12 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type)
StoryPage *p = StoryPage::Get(pe->page); StoryPage *p = StoryPage::Get(pe->page);
::StoryPageElementType type = pe->type; ::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_LOCATION || ::IsValidTile(reference));
EnforcePrecondition(false, type != ::SPET_GOAL || ScriptGoal::IsValidGoal((ScriptGoal::GoalID)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)); 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(); NOT_REACHED();
} }
return ScriptObject::Command<CMD_UPDATE_STORY_PAGE_ELEMENT>::Do(reftile, return ScriptObject::Command<CMD_UPDATE_STORY_PAGE_ELEMENT>::Do(reftile, story_page_element_id, refid, encoded_text);
story_page_element_id,
refid,
StoryPageElementTypeRequiresText(type) ? std::string{ text->GetEncodedText() } : std::string{});
} }
/* static */ uint32 ScriptStoryPage::GetPageSortValue(StoryPageID story_page_id) /* 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, IsValidStoryPage(story_page_id));
EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY); EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY);
return ScriptObject::Command<CMD_SET_STORY_PAGE_TITLE>::Do(story_page_id, title != nullptr ? std::string{ title->GetEncodedText() } : std::string{}); return ScriptObject::Command<CMD_SET_STORY_PAGE_TITLE>::Do(story_page_id, title != nullptr ? title->GetEncodedText() : std::string{});
} }
/* static */ ScriptCompany::CompanyID ScriptStoryPage::GetCompany(StoryPageID story_page_id) /* static */ ScriptCompany::CompanyID ScriptStoryPage::GetCompany(StoryPageID story_page_id)

@ -18,15 +18,10 @@
#include "../../safeguards.h" #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) : ScriptText::ScriptText(HSQUIRRELVM vm) :
ZeroedMemoryAllocator() ZeroedMemoryAllocator()
@ -177,7 +172,7 @@ SQInteger ScriptText::_set(HSQUIRRELVM vm)
return this->_SetParam(k, vm); return this->_SetParam(k, vm);
} }
const char *ScriptText::GetEncodedText() const std::string ScriptText::GetEncodedText()
{ {
static char buf[1024]; static char buf[1024];
int param_count = 0; int param_count = 0;
@ -208,7 +203,7 @@ char *ScriptText::_GetEncodedText(char *p, char *lastofp, int &param_count)
return p; return p;
} }
const char *Text::GetDecodedText() const std::string Text::GetDecodedText()
{ {
const std::string &encoded_text = this->GetEncodedText(); const std::string &encoded_text = this->GetEncodedText();

@ -21,17 +21,17 @@ class Text : public ScriptObject {
public: public:
/** /**
* Convert a ScriptText to a normal string. * Convert a ScriptText to a normal string.
* @return A string (in a static buffer), or nullptr. * @return A string.
* @api -all * @api -all
*/ */
virtual const char *GetEncodedText() = 0; virtual const std::string GetEncodedText() = 0;
/** /**
* Convert a #ScriptText into a decoded normal string. * Convert a #ScriptText into a decoded normal string.
* @return A string (in a static buffer), or nullptr. * @return A string.
* @api -all * @api -all
*/ */
const char *GetDecodedText(); const std::string GetDecodedText();
}; };
/** /**
@ -41,11 +41,10 @@ public:
class RawText : public Text { class RawText : public Text {
public: public:
RawText(const char *text); RawText(const char *text);
~RawText();
const char *GetEncodedText() override { return this->text; } const std::string GetEncodedText() override { return this->text; }
private: private:
const char *text; const std::string text;
}; };
/** /**
@ -125,7 +124,7 @@ public:
/** /**
* @api -all * @api -all
*/ */
virtual const char *GetEncodedText(); virtual const std::string GetEncodedText();
private: private:
StringID string; StringID string;

@ -44,29 +44,23 @@
{ {
CCountedPtr<Text> counter(name); CCountedPtr<Text> counter(name);
const char *text = nullptr; EnforcePrecondition(false, IsValidTown(town_id));
std::string text;
if (name != nullptr) { if (name != nullptr) {
text = name->GetDecodedText(); text = name->GetDecodedText();
EnforcePreconditionEncodedText(false, text);
EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_TOWN_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG); EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_TOWN_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG);
} }
EnforcePrecondition(false, IsValidTown(town_id));
return ScriptObject::Command<CMD_RENAME_TOWN>::Do(town_id, text != nullptr ? std::string{ text } : std::string{}); return ScriptObject::Command<CMD_RENAME_TOWN>::Do(town_id, text);
} }
/* static */ bool ScriptTown::SetText(TownID town_id, Text *text) /* static */ bool ScriptTown::SetText(TownID town_id, Text *text)
{ {
CCountedPtr<Text> counter(text); CCountedPtr<Text> counter(text);
const char *encoded_text = nullptr;
if (text != nullptr) {
encoded_text = text->GetEncodedText();
EnforcePreconditionEncodedText(false, encoded_text);
}
EnforcePrecondition(false, IsValidTown(town_id)); EnforcePrecondition(false, IsValidTown(town_id));
return ScriptObject::Command<CMD_TOWN_SET_TEXT>::Do(town_id, encoded_text != nullptr ? std::string{ encoded_text } : std::string{}); return ScriptObject::Command<CMD_TOWN_SET_TEXT>::Do(town_id, text != nullptr ? text->GetEncodedText() : std::string{});
} }
/* static */ int32 ScriptTown::GetPopulation(TownID town_id) /* static */ int32 ScriptTown::GetPopulation(TownID town_id)
@ -294,10 +288,9 @@
layout = (RoadLayout) (byte)_settings_game.economy.town_layout; layout = (RoadLayout) (byte)_settings_game.economy.town_layout;
} }
const char *text = nullptr; std::string text;
if (name != nullptr) { if (name != nullptr) {
text = name->GetDecodedText(); text = name->GetDecodedText();
EnforcePreconditionEncodedText(false, text);
EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_TOWN_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG); EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_TOWN_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG);
} }
uint32 townnameparts; uint32 townnameparts;
@ -306,7 +299,7 @@
return false; return false;
} }
return ScriptObject::Command<CMD_FOUND_TOWN>::Do(tile, (::TownSize)size, city, (::TownLayout)layout, false, townnameparts, text != nullptr ? std::string{ text } : std::string{}); return ScriptObject::Command<CMD_FOUND_TOWN>::Do(tile, (::TownSize)size, city, (::TownLayout)layout, false, townnameparts, text);
} }
/* static */ ScriptTown::TownRating ScriptTown::GetRating(TownID town_id, ScriptCompany::CompanyID company_id) /* static */ ScriptTown::TownRating ScriptTown::GetRating(TownID town_id, ScriptCompany::CompanyID company_id)

@ -147,7 +147,7 @@ public:
/** /**
* Rename a town. * Rename a town.
* @param town_id The town to rename * @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). * @pre IsValidTown(town_id).
* @return True if the action succeeded. * @return True if the action succeeded.
* @api -ai * @api -ai
@ -157,7 +157,7 @@ public:
/** /**
* Set the custom text of a town, shown in the GUI. * Set the custom text of a town, shown in the GUI.
* @param town_id The town to set the custom text of. * @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). * @pre IsValidTown(town_id).
* @return True if the action succeeded. * @return True if the action succeeded.
* @api -ai * @api -ai
@ -401,7 +401,7 @@ public:
* @param size The town size of the new town. * @param size The town size of the new town.
* @param city True if the new town should be a city. * @param city True if the new town should be a city.
* @param layout The town layout of the new town. * @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. * @game @pre no company mode in scope || ScriptSettings.GetValue("economy.found_town") != 0.
* @ai @pre 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. * @game @pre no company mode in scope || size != TOWN_SIZE_LARGE.

@ -244,7 +244,7 @@
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY); EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
EnforcePrecondition(false, IsValidVehicle(vehicle_id)); EnforcePrecondition(false, IsValidVehicle(vehicle_id));
EnforcePrecondition(false, name != nullptr); EnforcePrecondition(false, name != nullptr);
const char *text = name->GetDecodedText(); const std::string &text = name->GetDecodedText();
EnforcePreconditionEncodedText(false, text); EnforcePreconditionEncodedText(false, text);
EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_VEHICLE_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG); EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_VEHICLE_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG);

Loading…
Cancel
Save