Codechange: use std::string instead of stredup/free for stories

This commit is contained in:
Rubidium 2023-04-27 19:21:06 +02:00 committed by rubidium42
parent 3342967ad9
commit aac95eeaf5
4 changed files with 30 additions and 40 deletions

View File

@ -35,7 +35,7 @@ static const SaveLoad _story_page_elements_desc[] = {
SLE_CONDVAR(StoryPageElement, type, SLE_FILE_U16 | SLE_VAR_U8, SL_MIN_VERSION, SLV_185), SLE_CONDVAR(StoryPageElement, type, SLE_FILE_U16 | SLE_VAR_U8, SL_MIN_VERSION, SLV_185),
SLE_CONDVAR(StoryPageElement, type, SLE_UINT8, SLV_185, SL_MAX_VERSION), SLE_CONDVAR(StoryPageElement, type, SLE_UINT8, SLV_185, SL_MAX_VERSION),
SLE_VAR(StoryPageElement, referenced_id, SLE_UINT32), SLE_VAR(StoryPageElement, referenced_id, SLE_UINT32),
SLE_STR(StoryPageElement, text, SLE_STR | SLF_ALLOW_CONTROL, 0), SLE_SSTR(StoryPageElement, text, SLE_STR | SLF_ALLOW_CONTROL),
}; };
struct STPEChunkHandler : ChunkHandler { struct STPEChunkHandler : ChunkHandler {
@ -77,7 +77,7 @@ static const SaveLoad _story_pages_desc[] = {
SLE_VAR(StoryPage, date, SLE_UINT32), SLE_VAR(StoryPage, date, SLE_UINT32),
SLE_CONDVAR(StoryPage, company, SLE_FILE_U16 | SLE_VAR_U8, SL_MIN_VERSION, SLV_185), SLE_CONDVAR(StoryPage, company, SLE_FILE_U16 | SLE_VAR_U8, SL_MIN_VERSION, SLV_185),
SLE_CONDVAR(StoryPage, company, SLE_UINT8, SLV_185, SL_MAX_VERSION), SLE_CONDVAR(StoryPage, company, SLE_UINT8, SLV_185, SL_MAX_VERSION),
SLE_STR(StoryPage, title, SLE_STR | SLF_ALLOW_CONTROL, 0), SLE_SSTR(StoryPage, title, SLE_STR | SLF_ALLOW_CONTROL),
}; };
struct STPAChunkHandler : ChunkHandler { struct STPAChunkHandler : ChunkHandler {

View File

@ -47,16 +47,16 @@ INSTANTIATE_POOL_METHODS(StoryPage)
* @param text The text parameter of the DoCommand proc * @param text The text parameter of the DoCommand proc
* @return true, if and only if the given parameters are valid for the given page element type and page id. * @return true, if and only if the given parameters are valid for the given page element type and page id.
*/ */
static bool VerifyElementContentParameters(StoryPageID page_id, StoryPageElementType type, TileIndex tile, uint32 reference, const char *text) static bool VerifyElementContentParameters(StoryPageID page_id, StoryPageElementType type, TileIndex tile, uint32 reference, const std::string &text)
{ {
StoryPageButtonData button_data{ reference }; StoryPageButtonData button_data{ reference };
switch (type) { switch (type) {
case SPET_TEXT: case SPET_TEXT:
if (StrEmpty(text)) return false; if (text.empty()) return false;
break; break;
case SPET_LOCATION: case SPET_LOCATION:
if (StrEmpty(text)) return false; if (text.empty()) return false;
if (!IsValidTile(tile)) return false; if (!IsValidTile(tile)) return false;
break; break;
case SPET_GOAL: case SPET_GOAL:
@ -91,14 +91,14 @@ static bool VerifyElementContentParameters(StoryPageID page_id, StoryPageElement
* @param reference The reference parameter of the DoCommand proc (p2) * @param reference The reference parameter of the DoCommand proc (p2)
* @param text The text parameter of the DoCommand proc * @param text The text parameter of the DoCommand proc
*/ */
static void UpdateElement(StoryPageElement &pe, TileIndex tile, uint32 reference, const char *text) static void UpdateElement(StoryPageElement &pe, TileIndex tile, uint32 reference, const std::string &text)
{ {
switch (pe.type) { switch (pe.type) {
case SPET_TEXT: case SPET_TEXT:
pe.text = stredup(text); pe.text = text;
break; break;
case SPET_LOCATION: case SPET_LOCATION:
pe.text = stredup(text); pe.text = text;
pe.referenced_id = tile; pe.referenced_id = tile;
break; break;
case SPET_GOAL: case SPET_GOAL:
@ -107,7 +107,7 @@ static void UpdateElement(StoryPageElement &pe, TileIndex tile, uint32 reference
case SPET_BUTTON_PUSH: case SPET_BUTTON_PUSH:
case SPET_BUTTON_TILE: case SPET_BUTTON_TILE:
case SPET_BUTTON_VEHICLE: case SPET_BUTTON_VEHICLE:
pe.text = stredup(text); pe.text = text;
pe.referenced_id = reference; pe.referenced_id = reference;
break; break;
default: NOT_REACHED(); default: NOT_REACHED();
@ -220,11 +220,7 @@ std::tuple<CommandCost, StoryPageID> CmdCreateStoryPage(DoCommandFlag flags, Com
s->sort_value = _story_page_next_sort_value; s->sort_value = _story_page_next_sort_value;
s->date = TimerGameCalendar::date; s->date = TimerGameCalendar::date;
s->company = company; s->company = company;
if (text.empty()) { s->title = text;
s->title = nullptr;
} else {
s->title = stredup(text.c_str());
}
InvalidateWindowClassesData(WC_STORY_BOOK, -1); InvalidateWindowClassesData(WC_STORY_BOOK, -1);
if (StoryPage::GetNumItems() == 1) InvalidateWindowData(WC_MAIN_TOOLBAR, 0); if (StoryPage::GetNumItems() == 1) InvalidateWindowData(WC_MAIN_TOOLBAR, 0);
@ -259,7 +255,7 @@ std::tuple<CommandCost, StoryPageElementID> CmdCreateStoryPageElement(DoCommandF
if (_current_company != OWNER_DEITY) return { CMD_ERROR, INVALID_STORY_PAGE_ELEMENT }; if (_current_company != OWNER_DEITY) return { CMD_ERROR, INVALID_STORY_PAGE_ELEMENT };
if (!StoryPage::IsValidID(page_id)) return { CMD_ERROR, INVALID_STORY_PAGE_ELEMENT }; if (!StoryPage::IsValidID(page_id)) return { CMD_ERROR, INVALID_STORY_PAGE_ELEMENT };
if (!VerifyElementContentParameters(page_id, type, tile, reference, text.c_str())) return { CMD_ERROR, INVALID_STORY_PAGE_ELEMENT }; if (!VerifyElementContentParameters(page_id, type, tile, reference, text)) return { CMD_ERROR, INVALID_STORY_PAGE_ELEMENT };
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
@ -272,7 +268,7 @@ std::tuple<CommandCost, StoryPageElementID> CmdCreateStoryPageElement(DoCommandF
pe->sort_value = _story_page_element_next_sort_value; pe->sort_value = _story_page_element_next_sort_value;
pe->type = type; pe->type = type;
pe->page = page_id; pe->page = page_id;
UpdateElement(*pe, tile, reference, text.c_str()); UpdateElement(*pe, tile, reference, text);
InvalidateWindowClassesData(WC_STORY_BOOK, page_id); InvalidateWindowClassesData(WC_STORY_BOOK, page_id);
@ -301,10 +297,10 @@ CommandCost CmdUpdateStoryPageElement(DoCommandFlag flags, TileIndex tile, Story
StoryPageID page_id = pe->page; StoryPageID page_id = pe->page;
StoryPageElementType type = pe->type; StoryPageElementType type = pe->type;
if (!VerifyElementContentParameters(page_id, type, tile, reference, text.c_str())) return CMD_ERROR; if (!VerifyElementContentParameters(page_id, type, tile, reference, text)) return CMD_ERROR;
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
UpdateElement(*pe, tile, reference, text.c_str()); UpdateElement(*pe, tile, reference, text);
InvalidateWindowClassesData(WC_STORY_BOOK, pe->page); InvalidateWindowClassesData(WC_STORY_BOOK, pe->page);
} }
@ -325,12 +321,7 @@ CommandCost CmdSetStoryPageTitle(DoCommandFlag flags, StoryPageID page_id, const
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
StoryPage *p = StoryPage::Get(page_id); StoryPage *p = StoryPage::Get(page_id);
free(p->title); p->title = text;
if (text.empty()) {
p->title = nullptr;
} else {
p->title = stredup(text.c_str());
}
InvalidateWindowClassesData(WC_STORY_BOOK, page_id); InvalidateWindowClassesData(WC_STORY_BOOK, page_id);
} }

View File

@ -147,7 +147,7 @@ struct StoryPageElement : StoryPageElementPool::PoolItem<&_story_page_element_po
StoryPageElementType type; ///< Type of page element StoryPageElementType type; ///< Type of page element
uint32 referenced_id; ///< Id of referenced object (location, goal etc.) uint32 referenced_id; ///< Id of referenced object (location, goal etc.)
char *text; ///< Static content text of page element std::string text; ///< Static content text of page element
/** /**
* We need an (empty) constructor so struct isn't zeroed (as C++ standard states) * We need an (empty) constructor so struct isn't zeroed (as C++ standard states)
@ -157,16 +157,16 @@ struct StoryPageElement : StoryPageElementPool::PoolItem<&_story_page_element_po
/** /**
* (Empty) destructor has to be defined else operator delete might be called with nullptr parameter * (Empty) destructor has to be defined else operator delete might be called with nullptr parameter
*/ */
inline ~StoryPageElement() { free(this->text); } inline ~StoryPageElement() { }
}; };
/** Struct about stories, current and completed */ /** Struct about stories, current and completed */
struct StoryPage : StoryPagePool::PoolItem<&_story_page_pool> { struct StoryPage : StoryPagePool::PoolItem<&_story_page_pool> {
uint32 sort_value; ///< A number that increases for every created story page. Used for sorting. The id of a story page is the pool index. uint32 sort_value; ///< A number that increases for every created story page. Used for sorting. The id of a story page is the pool index.
TimerGameCalendar::Date date; ///< Date when the page was created. TimerGameCalendar::Date date; ///< Date when the page was created.
CompanyID company; ///< StoryPage is for a specific company; INVALID_COMPANY if it is global CompanyID company; ///< StoryPage is for a specific company; INVALID_COMPANY if it is global
char *title; ///< Title of story page std::string title; ///< Title of story page
/** /**
* We need an (empty) constructor so struct isn't zeroed (as C++ standard states) * We need an (empty) constructor so struct isn't zeroed (as C++ standard states)
@ -183,7 +183,6 @@ struct StoryPage : StoryPagePool::PoolItem<&_story_page_pool> {
if (spe->page == this->index) delete spe; if (spe->page == this->index) delete spe;
} }
} }
free(this->title);
} }
}; };

View File

@ -60,7 +60,7 @@ protected:
GUIStoryPageList story_pages; ///< Sorted list of pages. GUIStoryPageList story_pages; ///< Sorted list of pages.
GUIStoryPageElementList story_page_elements; ///< Sorted list of page elements that belong to the current page. GUIStoryPageElementList story_page_elements; ///< Sorted list of page elements that belong to the current page.
StoryPageID selected_page_id; ///< Pool index of selected page. StoryPageID selected_page_id; ///< Pool index of selected page.
char selected_generic_title[255]; ///< If the selected page doesn't have a custom title, this buffer is used to store a generic page title. std::string selected_generic_title; ///< If the selected page doesn't have a custom title, this buffer is used to store a generic page title.
StoryPageElementID active_button_id; ///< Which button element the player is currently using StoryPageElementID active_button_id; ///< Which button element the player is currently using
@ -188,9 +188,9 @@ protected:
{ {
/* Generate generic title if selected page have no custom title. */ /* Generate generic title if selected page have no custom title. */
StoryPage *page = this->GetSelPage(); StoryPage *page = this->GetSelPage();
if (page != nullptr && page->title == nullptr) { if (page != nullptr && page->title.empty()) {
SetDParam(0, GetSelPageNum() + 1); SetDParam(0, GetSelPageNum() + 1);
GetString(selected_generic_title, STR_STORY_BOOK_GENERIC_PAGE_ITEM, lastof(selected_generic_title)); selected_generic_title = GetString(STR_STORY_BOOK_GENERIC_PAGE_ITEM);
} }
this->story_page_elements.ForceRebuild(); this->story_page_elements.ForceRebuild();
@ -255,7 +255,7 @@ protected:
for (const StoryPage *p : this->story_pages) { for (const StoryPage *p : this->story_pages) {
bool current_page = p->index == this->selected_page_id; bool current_page = p->index == this->selected_page_id;
DropDownListStringItem *item = nullptr; DropDownListStringItem *item = nullptr;
if (p->title != nullptr) { if (!p->title.empty()) {
item = new DropDownListCharStringItem(p->title, p->index, current_page); item = new DropDownListCharStringItem(p->title, p->index, current_page);
} else { } else {
/* No custom title => use a generic page title with page number. */ /* No custom title => use a generic page title with page number. */
@ -295,7 +295,7 @@ protected:
/* Title lines */ /* Title lines */
height += FONT_HEIGHT_NORMAL; // Date always use exactly one line. height += FONT_HEIGHT_NORMAL; // Date always use exactly one line.
SetDParamStr(0, page->title != nullptr ? page->title : this->selected_generic_title); SetDParamStr(0, !page->title.empty() ? page->title : this->selected_generic_title);
height += GetStringHeight(STR_STORY_BOOK_TITLE, max_width); height += GetStringHeight(STR_STORY_BOOK_TITLE, max_width);
return height; return height;
@ -616,7 +616,7 @@ public:
this->owner = (Owner)this->window_number; this->owner = (Owner)this->window_number;
/* Initialize selected vars. */ /* Initialize selected vars. */
this->selected_generic_title[0] = '\0'; this->selected_generic_title.clear();
this->selected_page_id = INVALID_STORY_PAGE; this->selected_page_id = INVALID_STORY_PAGE;
this->active_button_id = INVALID_STORY_PAGE_ELEMENT; this->active_button_id = INVALID_STORY_PAGE_ELEMENT;
@ -655,7 +655,7 @@ public:
switch (widget) { switch (widget) {
case WID_SB_SEL_PAGE: { case WID_SB_SEL_PAGE: {
StoryPage *page = this->GetSelPage(); StoryPage *page = this->GetSelPage();
SetDParamStr(0, page != nullptr && page->title != nullptr ? page->title : this->selected_generic_title); SetDParamStr(0, page != nullptr && !page->title.empty() ? page->title : this->selected_generic_title);
break; break;
} }
case WID_SB_CAPTION: case WID_SB_CAPTION:
@ -713,7 +713,7 @@ public:
y_offset += line_height; y_offset += line_height;
/* Title */ /* Title */
SetDParamStr(0, page->title != nullptr ? page->title : this->selected_generic_title); SetDParamStr(0, !page->title.empty() ? page->title : this->selected_generic_title);
y_offset = DrawStringMultiLine(0, fr.right, y_offset, fr.bottom, STR_STORY_BOOK_TITLE, TC_BLACK, SA_TOP | SA_HOR_CENTER); y_offset = DrawStringMultiLine(0, fr.right, y_offset, fr.bottom, STR_STORY_BOOK_TITLE, TC_BLACK, SA_TOP | SA_HOR_CENTER);
/* Page elements */ /* Page elements */
@ -773,7 +773,7 @@ public:
for (size_t i = 0; i < this->story_pages.size(); i++) { for (size_t i = 0; i < this->story_pages.size(); i++) {
const StoryPage *s = this->story_pages[i]; const StoryPage *s = this->story_pages[i];
if (s->title != nullptr) { if (!s->title.empty()) {
SetDParamStr(0, s->title); SetDParamStr(0, s->title);
} else { } else {
SetDParamStr(0, this->selected_generic_title); SetDParamStr(0, this->selected_generic_title);
@ -877,7 +877,7 @@ public:
/* Was the last page removed? */ /* Was the last page removed? */
if (this->story_pages.size() == 0) { if (this->story_pages.size() == 0) {
this->selected_generic_title[0] = '\0'; this->selected_generic_title.clear();
} }
/* Verify page selection. */ /* Verify page selection. */