OpenTTD Source  20240917-master-g9ab0a47812
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 "core/alloc_func.hpp"
12 #include "string_func.h"
13 #include "strings_func.h"
14 #include "stringfilter_type.h"
15 #include "gfx_func.h"
16 
17 #include "safeguards.h"
18 
19 static const char32_t STATE_WHITESPACE = ' ';
20 static const char32_t STATE_WORD = 'w';
21 static const char32_t STATE_QUOTE1 = '\'';
22 static const char32_t STATE_QUOTE2 = '"';
23 
28 void StringFilter::SetFilterTerm(const char *str)
29 {
30  this->word_index.clear();
31  this->word_index.shrink_to_fit();
32  this->word_matches = 0;
33  free(this->filter_buffer);
34 
35  assert(str != nullptr);
36 
37  char *dest = MallocT<char>(strlen(str) + 1);
38  this->filter_buffer = dest;
39 
40  char32_t state = STATE_WHITESPACE;
41  const char *pos = str;
42  WordState *word = nullptr;
43  size_t len;
44  for (;; pos += len) {
45  char32_t c;
46  len = Utf8Decode(&c, pos);
47 
48  if (c == 0 || (state == STATE_WORD && IsWhitespace(c))) {
49  /* Finish word */
50  if (word != nullptr) {
51  *(dest++) = '\0';
52  word = nullptr;
53  }
54  state = STATE_WHITESPACE;
55  if (c != 0) continue; else break;
56  }
57 
58  if (state == STATE_WHITESPACE) {
59  /* Skip whitespace */
60  if (IsWhitespace(c)) continue;
61  state = STATE_WORD;
62  }
63 
64  if (c == STATE_QUOTE1 || c == STATE_QUOTE2) {
65  if (state == c) {
66  /* Stop quoting */
67  state = STATE_WORD;
68  continue;
69  } else if (state == STATE_WORD) {
70  /* Start quoting */
71  state = c;
72  continue;
73  }
74  }
75 
76  /* Add to word */
77  if (word == nullptr) {
78  word = &this->word_index.emplace_back(WordState{ dest, false });
79  }
80 
81  memcpy(dest, pos, len);
82  dest += len;
83  }
84 }
85 
90 void StringFilter::SetFilterTerm(const std::string &str)
91 {
92  this->SetFilterTerm(str.c_str());
93 }
94 
99 {
100  this->word_matches = 0;
101  for (WordState &ws : this->word_index) {
102  ws.match = false;
103  }
104 }
105 
114 void StringFilter::AddLine(const char *str)
115 {
116  if (str == nullptr) return;
117 
118  bool match_case = this->case_sensitive != nullptr && *this->case_sensitive;
119  for (WordState &ws : this->word_index) {
120  if (!ws.match) {
121  if (this->locale_aware) {
122  if (match_case ? StrNaturalContains(str, ws.start) : StrNaturalContainsIgnoreCase(str, ws.start)) {
123  ws.match = true;
124  this->word_matches++;
125  }
126  } else {
127  if ((match_case ? strstr(str, ws.start) : strcasestr(str, ws.start)) != nullptr) {
128  ws.match = true;
129  this->word_matches++;
130  }
131  }
132  }
133  }
134 }
135 
144 void StringFilter::AddLine(const std::string &str)
145 {
146  AddLine(str.c_str());
147 }
148 
158 {
159  AddLine(GetString(str));
160 }
StringFilter::SetFilterTerm
void SetFilterTerm(const char *str)
Set the term to filter on.
Definition: stringfilter.cpp:28
StringID
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:16
StringFilter::AddLine
void AddLine(const char *str)
Pass another text line from the current item to the filter.
Definition: stringfilter.cpp:114
gfx_func.h
free
void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: stdafx.h:334
StringFilter::WordState
State of a single filter word.
Definition: stringfilter_type.h:33
safeguards.h
stdafx.h
string_func.h
strings_func.h
StringFilter::case_sensitive
const bool * case_sensitive
Match case-sensitively (usually a static variable).
Definition: stringfilter_type.h:42
StringFilter::word_matches
uint word_matches
Summary of filter state: Number of words matched.
Definition: stringfilter_type.h:40
alloc_func.hpp
StringFilter::ResetState
void ResetState()
Reset the matching state to process a new item.
Definition: stringfilter.cpp:98
GetString
std::string GetString(StringID string)
Resolve the given StringID into a std::string with all the associated DParam lookups and formatting.
Definition: strings.cpp:319
StringFilter::filter_buffer
const char * filter_buffer
Parsed filter string. Words separated by 0.
Definition: stringfilter_type.h:38
IsWhitespace
bool IsWhitespace(char32_t c)
Check whether UNICODE character is whitespace or not, i.e.
Definition: string_func.h:249
stringfilter_type.h
StringFilter::locale_aware
bool locale_aware
Match words using the current locale.
Definition: stringfilter_type.h:43
StringFilter::word_index
std::vector< WordState > word_index
Word index and filter state.
Definition: stringfilter_type.h:39
Utf8Decode
size_t Utf8Decode(char32_t *c, const char *s)
Decode and consume the next UTF-8 encoded character.
Definition: string.cpp:419
StrNaturalContains
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:637
StrNaturalContainsIgnoreCase
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:664