1#ifndef YAZE_APP_EDITOR_MESSAGE_MESSAGE_LIST_QUERY_H_
2#define YAZE_APP_EDITOR_MESSAGE_MESSAGE_LIST_QUERY_H_
25 return static_cast<char>(std::tolower(c));
29 std::string_view needle) {
33 if (needle.size() > haystack.size()) {
36 for (
size_t i = 0; i + needle.size() <= haystack.size(); ++i) {
38 for (
size_t j = 0; j < needle.size(); ++j) {
39 if (
AsciiLower(
static_cast<unsigned char>(haystack[i + j])) !=
40 AsciiLower(
static_cast<unsigned char>(needle[j]))) {
53 if (query.size() >= 2 && query[0] ==
'0' &&
54 (query[1] ==
'x' || query[1] ==
'X')) {
55 return query.substr(2);
57 if (!query.empty() && (query[0] ==
'$' || query[0] ==
'#')) {
58 return query.substr(1);
64 std::string_view query) {
66 if (query.empty() || width <= 0 || width >= 16) {
70 static const char* digits =
"0123456789ABCDEF";
71 uint32_t remaining = value;
72 for (
int i = width - 1; i >= 0; --i) {
73 buf[i] = digits[remaining & 0xF];
77 std::string_view(buf,
static_cast<size_t>(width)), query);
82 const int written = std::snprintf(buf,
sizeof(buf),
"%d", value);
87 std::string_view(buf,
static_cast<size_t>(written)), query);
92 std::string_view contents,
bool expanded,
94 std::string_view query) {
110 const int id_width = display_id > 0xFFFF ? 6 : 4;
118 if (index >= text.size()) {
121 return std::isalnum(
static_cast<unsigned char>(text[index])) != 0;
126 std::string_view needle,
130 if (needle.empty() || start > text.size()) {
133 for (
size_t i = start; i + needle.size() <= text.size(); ++i) {
135 for (
size_t j = 0; j < needle.size(); ++j) {
136 unsigned char left =
static_cast<unsigned char>(text[i + j]);
137 unsigned char right =
static_cast<unsigned char>(needle[j]);
138 if (!case_sensitive) {
139 left =
static_cast<unsigned char>(
AsciiLower(left));
140 right =
static_cast<unsigned char>(
AsciiLower(right));
151 const bool start_ok = (i == 0) || !
IsWordChar(text, i - 1);
152 const bool end_ok = !
IsWordChar(text, i + needle.size());
153 if (!start_ok || !end_ok) {
164 std::string_view needle,
168 if (needle.empty() || before == 0) {
171 std::optional<size_t> last;
175 if (before != std::string::npos && *found >= before) {
180 if (from > text.size()) {
189 size_t max_chars = 96) {
191 line.reserve(std::min(text.size(), max_chars + 3));
192 for (
char c : text) {
193 if (c ==
'\n' || c ==
'\r') {
197 if (line.size() >= max_chars) {
bool IsWordChar(std::string_view text, size_t index)
std::string_view StripHexPrefix(std::string_view query)
bool ContainsCaseInsensitive(std::string_view haystack, std::string_view needle)
char AsciiLower(unsigned char c)
std::string MessageListPreview(std::string_view text, size_t max_chars=96)
bool DecimalContains(int value, std::string_view query)
bool HexDigitsContain(uint32_t value, int width, std::string_view query)
std::optional< size_t > FindNextTextMatch(std::string_view text, std::string_view needle, size_t start, bool case_sensitive, bool whole_word)
std::optional< size_t > FindPreviousTextMatch(std::string_view text, std::string_view needle, size_t before, bool case_sensitive, bool whole_word)
bool MessageListQueryMatches(int display_id, uint32_t address, std::string_view contents, bool expanded, MessageBankFilter bank, std::string_view query)