Changeset - r27295:4dfa0d5adc00
[Not reviewed]
master
0 7 0
Patric Stout - 13 months ago 2023-05-09 19:35:50
truebrain@openttd.org
Codechange: replace C-style strings with C++-style strings in textfile (#10772)
7 files changed with 63 insertions and 53 deletions:
0 comments (0 inline, 0 general)
src/string.cpp
Show inline comments
 
@@ -221,9 +221,14 @@ static void StrMakeValidInPlace(T &dst, 
 
				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, Stri
 
 * @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();
src/string_func.h
Show inline comments
 
@@ -40,7 +40,7 @@ int CDECL seprintf(char *str, const char
 
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);
src/string_type.h
Show inline comments
 
@@ -47,8 +47,14 @@ static const WChar CHAR_TD_PDF = 0x202C;
 
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)
 

	
src/strings.cpp
Show inline comments
 
@@ -2103,9 +2103,13 @@ bool MissingGlyphSearcher::FindMissingGl
 
	}
 

	
 
	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
 
		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];
 

	
src/strings_func.h
Show inline comments
 
@@ -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.
src/textfile_gui.cpp
Show inline comments
 
@@ -70,11 +70,6 @@ TextfileWindow::TextfileWindow(TextfileT
 
	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(boo
 
	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 *
 
	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;
 
	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);
 
	for (; *p != '\0'; p++) {
 
		if (*p == '\n') {
 
			*p = '\0';
 
			this->lines.emplace_back(++row, p + 1);
 
		}
 
	}
 

	
 
	/* Calculate maximum text line length. */
 
	uint max_length = 0;
src/textfile_gui.h
Show inline comments
 
@@ -19,25 +19,14 @@ std::optional<std::string> GetTextfile(T
 

	
 
/** 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, M
 

	
 
	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);
0 comments (0 inline, 0 general)