Refactor memory handling in Changelog.cpp

This commit is contained in:
Ted John 2018-01-19 12:41:14 +00:00
parent ba5bc415c7
commit badb90ba20
1 changed files with 59 additions and 58 deletions

View File

@ -14,16 +14,17 @@
*****************************************************************************/
#pragma endregion
#include <fstream>
#include <vector>
#include <openrct2/Context.h>
#include <openrct2/OpenRCT2.h>
#include <openrct2/core/Math.hpp>
#include <openrct2/core/Memory.hpp>
#include <openrct2-ui/windows/Window.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2/core/String.hpp>
#include <openrct2/localisation/Localisation.h>
#include <openrct2/platform/platform.h>
#include <openrct2/util/Util.h>
#include <openrct2-ui/windows/Window.h>
#include <openrct2-ui/interface/Widget.h>
enum {
WIDX_BACKGROUND,
@ -89,10 +90,8 @@ static rct_window_event_list window_changelog_events = {
static bool window_changelog_read_file();
static void window_changelog_dispose_file();
static char *_changelogText = nullptr;
static size_t _changelogTextSize = 0;
static char **_changelogLines = nullptr;
static sint32 _changelogNumLines = 0;
static std::string _changelogText;
static std::vector<const char *> _changelogLines;
static sint32 _changelogLongestLineWidth = 0;
rct_window * window_changelog_open()
@ -164,7 +163,7 @@ static void window_changelog_resize(rct_window *w)
static void window_changelog_scrollgetsize(rct_window *w, sint32 scrollIndex, sint32 *width, sint32 *height)
{
*width = _changelogLongestLineWidth + 4;
*height = _changelogNumLines * 11;
*height = (sint32)(_changelogLines.size() * 11);
}
static void window_changelog_invalidate(rct_window *w)
@ -192,73 +191,76 @@ static void window_changelog_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi,
sint32 x = 3;
sint32 y = 3;
for (sint32 i = 0; i < _changelogNumLines; i++) {
gfx_draw_string(dpi, _changelogLines[i], w->colours[0], x, y);
for (auto line : _changelogLines)
{
gfx_draw_string(dpi, (char *)line, w->colours[0], x, y);
y += 11;
}
}
static bool window_changelog_read_file()
static std::string GetChangelogText()
{
window_changelog_dispose_file();
utf8 path[MAX_PATH];
platform_get_changelog_path(path, sizeof(path));
if (!readentirefile(path, (void**)&_changelogText, &_changelogTextSize)) {
#if defined(_WIN32) && !defined(__MINGW32__)
auto pathW = String::ToUtf16(path);
auto fs = std::ifstream(pathW, std::ios::out | std::ios::app);
#else
auto fs = std::ifstream(path, std::ios::out | std::ios::app);
#endif
return std::string((std::istreambuf_iterator<char>(fs)), std::istreambuf_iterator<char>());
}
static bool window_changelog_read_file()
{
try
{
_changelogText = GetChangelogText();
}
catch (const std::bad_alloc &)
{
log_error("Unable to allocate memory for changelog.txt");
return false;
}
catch (const std::exception &)
{
log_error("Unable to read changelog.txt");
return false;
}
void* new_memory = realloc(_changelogText, _changelogTextSize + 1);
if (new_memory == nullptr) {
log_error("Failed to reallocate memory for changelog text");
return false;
}
_changelogText = (char*)new_memory;
_changelogText[_changelogTextSize++] = 0;
char *start = _changelogText;
if (_changelogTextSize >= 3 && utf8_is_bom(_changelogText))
auto * start = _changelogText.data();
if (_changelogText.size() >= 3 && utf8_is_bom(start))
{
start += 3;
}
sint32 changelogLinesCapacity = 8;
_changelogLines = Memory::Allocate<utf8*>(changelogLinesCapacity * sizeof(char*));
_changelogLines[0] = start;
_changelogNumLines = 1;
char *ch = start;
while (*ch != 0) {
_changelogLines.clear();
_changelogLines.push_back(start);
auto ch = start;
while (*ch != '\0')
{
uint8 c = *ch;
if (c == '\n') {
if (c == '\n')
{
*ch++ = 0;
_changelogNumLines++;
if (_changelogNumLines > changelogLinesCapacity) {
changelogLinesCapacity *= 2;
new_memory = realloc(_changelogLines, changelogLinesCapacity * sizeof(char*));
if (new_memory == nullptr) {
log_error("Failed to reallocate memory for change log lines");
return false;
}
_changelogLines = (char**)new_memory;
}
_changelogLines[_changelogNumLines - 1] = ch;
} else if (c < 32 || c > 122) {
// A character that won't be drawn or change state.
_changelogLines.push_back(ch);
}
else if (utf8_is_format_code(c))
{
*ch++ = FORMAT_OUTLINE_OFF;
} else {
}
else
{
ch++;
}
}
new_memory = realloc(_changelogLines, _changelogNumLines * sizeof(char*));
if (new_memory == nullptr) {
log_error("Failed to reallocate memory for change log lines");
return false;
}
_changelogLines = (char**)new_memory;
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
_changelogLongestLineWidth = 0;
for (sint32 i = 0; i < _changelogNumLines; i++) {
sint32 width = gfx_get_string_width(_changelogLines[i]);
for (auto line : _changelogLines)
{
auto width = gfx_get_string_width(line);
_changelogLongestLineWidth = Math::Max(width, _changelogLongestLineWidth);
}
return true;
@ -266,8 +268,7 @@ static bool window_changelog_read_file()
static void window_changelog_dispose_file()
{
SafeFree(_changelogText);
SafeFree(_changelogLines);
_changelogTextSize = 0;
_changelogNumLines = 0;
_changelogText = std::string();
_changelogLines.clear();
_changelogLines.shrink_to_fit();
}