OpenTTD Source 20250312-master-gcdcc6b491d
stringfilter.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#include "stdafx.h"
11#include "string_func.h"
12#include "strings_func.h"
13#include "stringfilter_type.h"
14#include "gfx_func.h"
15
16#include "safeguards.h"
17
18static const char32_t STATE_WHITESPACE = ' ';
19static const char32_t STATE_WORD = 'w';
20static const char32_t STATE_QUOTE1 = '\'';
21static const char32_t STATE_QUOTE2 = '"';
22
27void StringFilter::SetFilterTerm(std::string_view str)
28{
29 this->word_index.clear();
30 this->word_index.shrink_to_fit();
31 this->word_matches = 0;
32
33 char32_t state = STATE_WHITESPACE;
34 auto pos = str.begin();
35 auto word_begin = str.end();
36 auto word_end = pos;
37
38 /* Helper to prevent duplicating code. */
39 auto add_word = [&] () {
40 if (word_begin != str.end()) {
41 this->word_index.emplace_back(std::string(word_begin, word_end + 1), false);
42 word_begin = str.end();
43 }
44 };
45
46 for (size_t len; pos < str.end(); pos += len) {
47 char32_t c;
48 len = Utf8Decode(&c, pos);
49
50 if (state == STATE_WORD && IsWhitespace(c)) {
51 /* Finish word */
52 add_word();
53 state = STATE_WHITESPACE;
54 continue;
55 }
56
57 if (state == STATE_WHITESPACE) {
58 /* Skip whitespace */
59 if (IsWhitespace(c)) continue;
60 state = STATE_WORD;
61 }
62
63 if (c == STATE_QUOTE1 || c == STATE_QUOTE2) {
64 if (state == c) {
65 /* Stop quoting */
66 state = STATE_WORD;
67 continue;
68 } else if (state == STATE_WORD) {
69 /* Start quoting */
70 state = c;
71 continue;
72 }
73 }
74
75 /* Add to word */
76 if (word_begin == str.end()) {
77 word_begin = pos;
78 }
79 word_end = pos;
80 }
81
82 /* Add the last word of the string. */
83 add_word();
84}
85
90{
91 this->word_matches = 0;
92 for (WordState &ws : this->word_index) {
93 ws.match = false;
94 }
95}
96
105void StringFilter::AddLine(const char *str)
106{
107 if (str == nullptr) return;
108
109 bool match_case = this->case_sensitive != nullptr && *this->case_sensitive;
110 for (WordState &ws : this->word_index) {
111 if (!ws.match) {
112 if (this->locale_aware) {
113 if (match_case ? StrNaturalContains(str, ws.word) : StrNaturalContainsIgnoreCase(str, ws.word)) {
114 ws.match = true;
115 this->word_matches++;
116 }
117 } else {
118 if ((match_case ? strstr(str, ws.word.c_str()) : strcasestr(str, ws.word.c_str())) != nullptr) {
119 ws.match = true;
120 this->word_matches++;
121 }
122 }
123 }
124 }
125}
Functions related to the gfx engine.
A number of safeguards to prevent using unsafe methods.
Definition of base types and functions in a cross-platform compatible way.
bool StrNaturalContains(const std::string_view str, const std::string_view value)
Checks if a string is contained in another string with a locale-aware comparison that is case sensiti...
Definition string.cpp:678
size_t Utf8Decode(char32_t *c, const char *s)
Decode and consume the next UTF-8 encoded character.
Definition string.cpp:437
bool StrNaturalContainsIgnoreCase(const std::string_view str, const std::string_view value)
Checks if a string is contained in another string with a locale-aware comparison that is case insensi...
Definition string.cpp:705
Functions related to low-level strings.
bool IsWhitespace(char32_t c)
Check whether UNICODE character is whitespace or not, i.e.
Searching and filtering using a stringterm.
Functions related to OTTD's strings.
State of a single filter word.
uint word_matches
Summary of filter state: Number of words matched.
void SetFilterTerm(std::string_view str)
Set the term to filter on.
std::vector< WordState > word_index
Word index and filter state.
bool locale_aware
Match words using the current locale.
void ResetState()
Reset the matching state to process a new item.
const bool * case_sensitive
Match case-sensitively (usually a static variable).
void AddLine(const char *str)
Pass another text line from the current item to the filter.