ZRCola/lib/libZRCola/src/highlight.cpp
Simon Rozman 9709cc2845 libZRCola: Make UTF-16 explicit
ZRCola is using UTF-16LE strings internally (thanks to Windows).
However, wchar_t and std::wstring are UTF-32 on other platforms.

Signed-off-by: Simon Rozman <simon@rozman.si>
2022-09-15 14:36:44 +02:00

78 lines
2.7 KiB
C++

/*
SPDX-License-Identifier: GPL-3.0-or-later
Copyright © 2021-2022 Amebis
*/
#include "pch.h"
_Use_decl_annotations_
void ZRCola::highlight_db::Highlight(const char16_t* input, size_t inputMax, std::function<void (hlghtsetid_t set, size_t start, size_t end)> callback) const
{
size_t start = 0;
hlghtsetid_t set = ZRCOLA_HLGHTSETID_DEFAULT;
for (size_t i = 0; i < inputMax;) {
// Find the longest matching highlight at i-th character.
size_t l_match = (size_t)-1;
for (size_t l = 0, r = idxChr.size(), ii = i, j = 0; ii < inputMax && l < r; ii++, j++) {
char16_t c = input[ii];
while (l < r) {
// Test the highlight in the middle of the search area.
size_t m = (l + r) / 2;
// Get the j-th character of the highlight.
// All highlights that get short on characters are lexically ordered before.
// Thus the j-th character is considered 0.
char16_t s = idxChr[m].chr_at(j);
// Do the bisection test.
if (c < s) r = m;
else if (s < c) l = m + 1;
else {
// Character found.
// Narrow the search area on the left to start at the first highlight in the run.
for (size_t r2 = m; l < r2;) {
size_t m2 = (l + r2) / 2;
if (c <= idxChr[m2].chr_at(j)) r2 = m2; else l = m2 + 1;
}
// Narrow the search area on the right to end at the first highlight not in the run.
for (size_t l2 = m + 1; l2 < r;) {
size_t m2 = (l2 + r) / 2;
if (idxChr[m2].chr_at(j) <= c) l2 = m2 + 1; else r = m2;
}
if (j + 1 == idxChr[l].chr_len()) {
// The first highlight of the run was a match (thus far). Save it.
l_match = l;
}
break;
}
}
}
if (l_match < idxChr.size()) {
// The saved highlight was an exact match.
const highlight &hghl = idxChr[l_match];
if (set != hghl.set) {
callback(set, start, i);
start = i;
set = hghl.set;
}
i += hghl.chr_len();
} else {
// The match was not found.
if (set != ZRCOLA_HLGHTSETID_DEFAULT) {
callback(set, start, i);
start = i;
set = ZRCOLA_HLGHTSETID_DEFAULT;
}
i++;
}
}
callback(set, start, inputMax);
}