Console text filtering and match highlighting lowercased a full copy of every line, and of every drawn segment, on each pass. - A new alloc-free ASCII case-insensitive substring search folds both sides on the fly, so neither the filter test nor the highlight scan allocates a lowercased copy per line any more. - Both call sites use it; the case-insensitive match behaviour is unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
53 lines
2.2 KiB
C++
53 lines
2.2 KiB
C++
#include "console_output_model.h"
|
|
|
|
#include <algorithm>
|
|
#include <cctype>
|
|
|
|
namespace dragonx {
|
|
namespace ui {
|
|
|
|
size_t FindCaseInsensitive(const char* hay, size_t hayLen, const std::string& needleLower, size_t from)
|
|
{
|
|
const size_t n = needleLower.size();
|
|
if (n == 0) return from <= hayLen ? from : std::string::npos;
|
|
if (hayLen < n) return std::string::npos;
|
|
auto fold = [](unsigned char c) { return (c >= 'A' && c <= 'Z') ? static_cast<unsigned char>(c + 32) : c; };
|
|
for (size_t i = from; i + n <= hayLen; ++i) {
|
|
size_t j = 0;
|
|
while (j < n && fold(static_cast<unsigned char>(hay[i + j])) == fold(static_cast<unsigned char>(needleLower[j]))) ++j;
|
|
if (j == n) return i;
|
|
}
|
|
return std::string::npos;
|
|
}
|
|
|
|
bool consoleLinePassesFilter(const std::string& lineText,
|
|
ConsoleChannel channel,
|
|
const ConsoleOutputFilter& filter)
|
|
{
|
|
if (!filter.daemonMessagesEnabled &&
|
|
(channel == ConsoleChannel::Daemon || channel == ConsoleChannel::Xmrig)) return false;
|
|
if (!filter.rpcTraceEnabled && channel == ConsoleChannel::Rpc) return false;
|
|
if (!filter.appMessagesEnabled && channel == ConsoleChannel::App) return false;
|
|
if (filter.errorsOnly && channel != ConsoleChannel::Error) return false;
|
|
if (!filter.text.empty()) {
|
|
if (FindCaseInsensitive(lineText.data(), lineText.size(), filter.text, 0) == std::string::npos) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool ExtendFlatVisibleIndices(std::vector<int>& visible, std::uint64_t oldFirst, std::uint64_t oldEnd,
|
|
std::uint64_t newFirst, int n, const std::function<bool(int)>& passes)
|
|
{
|
|
const std::uint64_t newEnd = newFirst + static_cast<std::uint64_t>(n < 0 ? 0 : n);
|
|
if (newFirst < oldFirst || newFirst > oldEnd || newEnd < oldEnd) return false;
|
|
const int shift = static_cast<int>(newFirst - oldFirst);
|
|
visible.erase(visible.begin(), std::lower_bound(visible.begin(), visible.end(), shift));
|
|
for (int& idx : visible) idx -= shift;
|
|
for (int i = static_cast<int>(oldEnd - newFirst); i < n; ++i)
|
|
if (passes(i)) visible.push_back(i);
|
|
return true;
|
|
}
|
|
|
|
} // namespace ui
|
|
} // namespace dragonx
|