Codechange: replace C-style strings with C++-style strings in textfile (#10772)

pull/532/head
Patric Stout 1 year ago committed by GitHub
parent 90529ea48b
commit febe394806
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -221,9 +221,14 @@ static void StrMakeValidInPlace(T &dst, const char *str, const char *last, Strin
str += len;
continue;
}
/* Replace the undesirable character with a question mark */
str += len;
if ((settings & SVS_REPLACE_WITH_QUESTION_MARK) != 0) *dst++ = '?';
if ((settings & SVS_REPLACE_TAB_CR_NL_WITH_SPACE) != 0 && (c == '\r' || c == '\n' || c == '\t')) {
/* Replace the tab, carriage return or newline with a space. */
*dst++ = ' ';
} else if ((settings & SVS_REPLACE_WITH_QUESTION_MARK) != 0) {
/* Replace the undesirable character with a question mark */
*dst++ = '?';
}
}
}
@ -263,7 +268,7 @@ void StrMakeValidInPlace(char *str, StringValidationSettings settings)
* @param str The string to validate.
* @param settings The settings for the string validation.
*/
std::string StrMakeValid(const std::string &str, StringValidationSettings settings)
std::string StrMakeValid(std::string_view str, StringValidationSettings settings)
{
auto buf = str.data();
auto last = buf + str.size();

@ -40,7 +40,7 @@ int CDECL seprintf(char *str, const char *last, const char *format, ...) WARN_FO
std::string FormatArrayAsHex(span<const byte> data);
void StrMakeValidInPlace(char *str, const char *last, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK) NOACCESS(2);
[[nodiscard]] std::string StrMakeValid(const std::string &str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK);
[[nodiscard]] std::string StrMakeValid(std::string_view str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK);
void StrMakeValidInPlace(char *str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK);
void str_fix_scc_encoded(char *str, const char *last) NOACCESS(2);

@ -47,8 +47,14 @@ static const WChar CHAR_TD_PDF = 0x202C; ///< Restore the text-direction state t
enum StringValidationSettings {
SVS_NONE = 0, ///< Allow nothing and replace nothing.
SVS_REPLACE_WITH_QUESTION_MARK = 1 << 0, ///< Replace the unknown/bad bits with question marks.
SVS_ALLOW_NEWLINE = 1 << 1, ///< Allow newlines.
SVS_ALLOW_NEWLINE = 1 << 1, ///< Allow newlines; replaces '\r\n' with '\n' during processing.
SVS_ALLOW_CONTROL_CODE = 1 << 2, ///< Allow the special control codes.
/**
* Replace tabs ('\t'), carriage returns ('\r') and newlines ('\n') with spaces.
* When #SVS_ALLOW_NEWLINE is set, a '\n' or '\r\n' combination are not replaced with a space. A lone '\r' is replaced with a space.
* When #SVS_REPLACE_WITH_QUESTION_MARK is set, this replacement runs first.
*/
SVS_REPLACE_TAB_CR_NL_WITH_SPACE = 1 << 3,
};
DECLARE_ENUM_AS_BIT_SET(StringValidationSettings)

@ -2103,9 +2103,13 @@ bool MissingGlyphSearcher::FindMissingGlyphs()
}
this->Reset();
for (const char *text = this->NextString(); text != nullptr; text = this->NextString()) {
for (auto text = this->NextString(); text.has_value(); text = this->NextString()) {
auto src = text->cbegin();
FontSize size = this->DefaultSize();
for (WChar c = Utf8Consume(&text); c != '\0'; c = Utf8Consume(&text)) {
while (src != text->cend()) {
WChar c = Utf8Consume(src);
if (c >= SCC_FIRST_FONT && c <= SCC_LAST_FONT) {
size = (FontSize)(c - SCC_FIRST_FONT);
} else if (!IsInsideMM(c, SCC_SPRITE_START, SCC_SPRITE_END) && IsPrintable(c) && !IsTextDirectionChar(c) && c != '?' && GetGlyph(size, c) == question_mark[size]) {
@ -2144,9 +2148,9 @@ class LanguagePackGlyphSearcher : public MissingGlyphSearcher {
return FS_NORMAL;
}
const char *NextString() override
std::optional<std::string_view> NextString() override
{
if (this->i >= TEXT_TAB_END) return nullptr;
if (this->i >= TEXT_TAB_END) return std::nullopt;
const char *ret = _langpack.offsets[_langpack.langtab_start[this->i] + this->j];

@ -261,9 +261,9 @@ public:
/**
* Get the next string to search through.
* @return The next string or nullptr if there is none.
* @return The next string or nullopt if there is none.
*/
virtual const char *NextString() = 0;
virtual std::optional<std::string_view> NextString() = 0;
/**
* Get the default (font) size of the string.

@ -70,11 +70,6 @@ TextfileWindow::TextfileWindow(TextfileType file_type) : Window(&_textfile_desc)
this->hscroll->SetStepSize(10); // Speed up horizontal scrollbar
}
/* virtual */ TextfileWindow::~TextfileWindow()
{
free(this->text);
}
/**
* Get the total height of the content displayed in this window, if wrapping is disabled.
* @return the height in pixels
@ -199,9 +194,9 @@ void TextfileWindow::SetupScrollbars(bool force_reflow)
return FS_MONO;
}
/* virtual */ const char *TextfileWindow::NextString()
/* virtual */ std::optional<std::string_view> TextfileWindow::NextString()
{
if (this->search_iterator >= this->lines.size()) return nullptr;
if (this->search_iterator >= this->lines.size()) return std::nullopt;
return this->lines[this->search_iterator++].text;
}
@ -344,48 +339,48 @@ static void Xunzip(byte **bufp, size_t *sizep)
FILE *handle = FioFOpenFile(textfile, "rb", dir, &filesize);
if (handle == nullptr) return;
this->text = ReallocT(this->text, filesize);
size_t read = fread(this->text, 1, filesize, handle);
char *buf = MallocT<char>(filesize);
size_t read = fread(buf, 1, filesize, handle);
fclose(handle);
if (read != filesize) return;
if (read != filesize) {
free(buf);
return;
}
#if defined(WITH_ZLIB)
/* In-place gunzip */
if (StrEndsWith(textfile, ".gz")) Gunzip((byte**)&this->text, &filesize);
if (StrEndsWith(textfile, ".gz")) Gunzip((byte**)&buf, &filesize);
#endif
#if defined(WITH_LIBLZMA)
/* In-place xunzip */
if (StrEndsWith(textfile, ".xz")) Xunzip((byte**)&this->text, &filesize);
if (StrEndsWith(textfile, ".xz")) Xunzip((byte**)&buf, &filesize);
#endif
if (!this->text) return;
if (buf == nullptr) return;
/* Add space for trailing \0 */
this->text = ReallocT(this->text, filesize + 1);
this->text[filesize] = '\0';
/* Replace tabs and line feeds with a space since StrMakeValidInPlace removes those. */
for (char *p = this->text; *p != '\0'; p++) {
if (*p == '\t' || *p == '\r') *p = ' ';
}
std::string_view sv_buf(buf, filesize);
/* Check for the byte-order-mark, and skip it if needed. */
char *p = this->text + (strncmp(u8"\ufeff", this->text, 3) == 0 ? 3 : 0);
if (StrStartsWith(sv_buf, u8"\ufeff")) sv_buf.remove_prefix(3);
/* Make sure the string is a valid UTF-8 sequence. */
StrMakeValidInPlace(p, this->text + filesize, SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE);
/* Replace any invalid characters with a question-mark. This copies the buf in the process. */
this->text = StrMakeValid(sv_buf, SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE | SVS_REPLACE_TAB_CR_NL_WITH_SPACE);
free(buf);
/* Split the string on newlines. */
std::string_view p(this->text);
int row = 0;
this->lines.emplace_back(row, p);
for (; *p != '\0'; p++) {
if (*p == '\n') {
*p = '\0';
this->lines.emplace_back(++row, p + 1);
}
auto next = p.find_first_of('\n');
while (next != std::string_view::npos) {
this->lines.emplace_back(row, p.substr(0, next));
p.remove_prefix(next + 1);
row++;
next = p.find_first_of('\n');
}
this->lines.emplace_back(row, p);
/* Calculate maximum text line length. */
uint max_length = 0;

@ -19,25 +19,14 @@ std::optional<std::string> GetTextfile(TextfileType type, Subdirectory dir, cons
/** Window for displaying a textfile */
struct TextfileWindow : public Window, MissingGlyphSearcher {
struct Line {
int top; ///< Top scroll position.
int bottom; ///< Bottom scroll position.
const char *text; ///< Pointer to text buffer.
Line(int top, const char *text) : top(top), bottom(top + 1), text(text) {}
};
TextfileType file_type; ///< Type of textfile to view.
Scrollbar *vscroll; ///< Vertical scrollbar.
Scrollbar *hscroll; ///< Horizontal scrollbar.
char *text; ///< Lines of text from the NewGRF's textfile.
std::vector<Line> lines; ///< #text, split into lines in a table with lines.
uint search_iterator; ///< Iterator for the font check search.
uint max_length; ///< Maximum length of unwrapped text line.
TextfileWindow(TextfileType file_type);
~TextfileWindow();
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override;
void OnClick(Point pt, int widget, int click_count) override;
@ -47,13 +36,24 @@ struct TextfileWindow : public Window, MissingGlyphSearcher {
void Reset() override;
FontSize DefaultSize() override;
const char *NextString() override;
std::optional<std::string_view> NextString() override;
bool Monospace() override;
void SetFontNames(FontCacheSettings *settings, const char *font_name, const void *os_data) override;
virtual void LoadTextfile(const std::string &textfile, Subdirectory dir);
private:
struct Line {
int top; ///< Top scroll position.
int bottom; ///< Bottom scroll position.
std::string_view text; ///< Pointer to text buffer.
Line(int top, std::string_view text) : top(top), bottom(top + 1), text(text) {}
};
std::string text; ///< Lines of text from the NewGRF's textfile.
std::vector<Line> lines; ///< #text, split into lines in a table with lines.
uint ReflowContent();
uint GetContentHeight();
void SetupScrollbars(bool force_reflow);

Loading…
Cancel
Save