53 std::reverse_copy(
N->Name.begin(),
N->Name.end(), std::back_inserter(
S));
80 bool LongName = NameInfo & 0x40;
82 std::size_t Size = NameInfo & ~0xC0;
94 N.Value = ((
H << 16) | (
M << 8) | L) >> 3;
96 bool HasChildren = L & 0x02;
97 N.HasSibling = L & 0x01;
106 N.HasSibling =
H & 0x80;
107 bool HasChildren =
H & 0x40;
110 N.ChildrenOffset = (
H << 16);
116 N.Size = Offset - Origin;
121 std::size_t &Consummed,
char &PreviousCharInName,
122 char &PreviousCharInNeedle,
bool IsPrefix =
false) {
126 if (!
Name.startswith(Needle))
128 Consummed = Needle.
size();
134 auto NamePos =
Name.begin();
135 auto NeedlePos = Needle.
begin();
137 char PreviousCharInNameOrigin = PreviousCharInName;
138 char PreviousCharInNeedleOrigin = PreviousCharInNeedle;
140 auto IgnoreSpaces = [](
auto It,
auto End,
char &PreviousChar,
141 bool IgnoreEnd =
false) {
143 const auto Next = std::next(It);
147 *It ==
' ' || *It ==
'_' ||
148 (*It ==
'-' && isAlnum(PreviousChar) &&
149 ((Next != End && isAlnum(*Next)) || (Next == End && IgnoreEnd)));
159 NamePos = IgnoreSpaces(NamePos,
Name.end(), PreviousCharInName);
161 IgnoreSpaces(NeedlePos, Needle.
end(), PreviousCharInNeedle, IsPrefix);
162 if (NeedlePos == Needle.
end())
164 if (NamePos ==
Name.end())
166 if (toUpper(*NeedlePos) != toUpper(*NamePos))
171 Consummed = std::distance(
Name.begin(), NamePos);
172 if (NeedlePos != Needle.
end()) {
173 PreviousCharInName = PreviousCharInNameOrigin;
174 PreviousCharInNeedle = PreviousCharInNeedleOrigin;
176 return NeedlePos == Needle.
end();
179 static std::tuple<Node, bool, uint32_t>
181 char PreviousCharInName,
char PreviousCharInNeedle,
184 std::size_t Consummed = 0;
187 PreviousCharInName, PreviousCharInNeedle);
189 return std::make_tuple(
N,
false, 0);
191 if (
Name.size() - Consummed == 0 &&
N.Value != 0xFFFFFFFF)
192 return std::make_tuple(
N,
true,
N.Value);
194 if (
N.hasChildren()) {
200 std::tie(
C, Matches,
Value) =
202 PreviousCharInName, PreviousCharInNeedle, Buffer, &
N);
204 std::reverse_copy(
C.Name.begin(),
C.Name.end(),
205 std::back_inserter(Buffer));
206 return std::make_tuple(
N,
true,
Value);
208 ChildOffset +=
C.Size;
213 return std::make_tuple(
N,
false, 0);
216 static std::tuple<Node, bool, uint32_t>
226 {
"D",
"YAE",
"GS" },
227 {
"DD",
"EO",
"N", },
229 {
"M",
"YEO",
"NH" },
233 {
"SS",
"WAE",
"LM" },
237 {
"C",
"WEO",
"LP" },
256 constexpr
const char32_t
SBase = 0xAC00;
262 char &PreviousInName,
int &Pos,
int Column) {
263 assert(Column == 0 || Column == 1 || Column == 2);
265 char NeedleStart = 0;
267 int Prev = PreviousInName;
268 for (std::size_t
I = 0;
I < CountPerColumn[Column];
I++) {
270 if (
int(Syllable.
size()) <= Len)
272 std::size_t Consummed = 0;
273 char PreviousInNameCopy = PreviousInName;
275 PreviousInNameCopy, NeedleStart);
280 Prev = PreviousInNameCopy;
284 PreviousInName = Prev;
292 std::size_t Consummed = 0;
293 char NameStart = 0, NeedleStart = 0;
295 NameStart, NeedleStart);
299 int L = -1, V = -1,
T = -1;
303 if (L != -1 && V != -1 &&
T != -1 &&
Name.empty()) {
305 Buffer.
append(
"HANGUL SYLLABLE ");
330 {
"CJK UNIFIED IDEOGRAPH-", 0x3400, 0x4DBF},
331 {
"CJK UNIFIED IDEOGRAPH-", 0x4E00, 0x9FFC},
332 {
"CJK UNIFIED IDEOGRAPH-", 0x20000, 0x2A6DD},
333 {
"CJK UNIFIED IDEOGRAPH-", 0x2A700, 0x2B734},
334 {
"CJK UNIFIED IDEOGRAPH-", 0x2B740, 0x2B81D},
335 {
"CJK UNIFIED IDEOGRAPH-", 0x2B820, 0x2CEA1},
336 {
"CJK UNIFIED IDEOGRAPH-", 0x2CEB0, 0x2EBE0},
337 {
"CJK UNIFIED IDEOGRAPH-", 0x30000, 0x3134A},
338 {
"TANGUT IDEOGRAPH-", 0x17000, 0x187F7},
339 {
"TANGUT IDEOGRAPH-", 0x18D00, 0x18D08},
340 {
"KHITAN SMALL SCRIPT CHARACTER-", 0x18B00, 0x18CD5},
341 {
"NUSHU CHARACTER-", 0x1B170, 0x1B2FB},
342 {
"CJK COMPATIBILITY IDEOGRAPH-", 0xF900, 0xFA6D},
343 {
"CJK COMPATIBILITY IDEOGRAPH-", 0xFA70, 0xFAD9},
344 {
"CJK COMPATIBILITY IDEOGRAPH-", 0x2F800, 0x2FA1D},
351 std::size_t Consummed = 0;
352 char NameStart = 0, NeedleStart = 0;
354 NameStart, NeedleStart,
true);
358 unsigned long long V = 0;
366 Buffer.
append(Item.Prefix);
367 Buffer.
append(utohexstr(V,
true));
396 Buffer =
"HANGUL JUNGSEONG O-E";
428 std::size_t LargestEditDistance = 0;
430 Matches.
reserve(MaxMatchesCount + 1);
433 char32_t
Value) ->
bool {
434 if (Distance > LargestEditDistance) {
435 if (Matches.size() == MaxMatchesCount)
437 LargestEditDistance = Distance;
449 Matches.begin(), Matches.end(), Distance,
451 if (Distance == a.Distance)
452 return a.Name < GetName();
453 return a.Distance < Distance;
455 if (It == Matches.end() && Matches.size() == MaxMatchesCount)
460 if (Matches.size() > MaxMatchesCount)
469 Out.reserve(
Name.size());
470 for (
char C :
Name) {
472 Out.push_back(toUpper(
C));
479 const std::size_t Columns =
486 std::vector<char> Distances(
489 auto Get = [&Distances, Columns](
size_t Column, std::size_t Row) ->
char & {
492 return Distances[Row * Columns + Column];
495 for (std::size_t
I = 0;
I < Columns;
I++)
502 auto VisitNode = [&](
const Node &
N, std::size_t Row,
503 auto &VisitNode) ->
void {
505 for (; J <
N.Name.size(); J++) {
506 if (!isAlnum(
N.Name[J]))
511 for (std::size_t
I = 1;
I < Columns;
I++) {
512 const int Delete = Get(
I - 1, Row) + 1;
513 const int Insert = Get(
I, Row - 1) + 1;
516 Get(
I - 1, Row - 1) + (NormalizedName[
I - 1] !=
N.Name[J] ? 1 : 0);
524 unsigned Cost = Get(Columns - 1, Row - 1);
525 if (
N.Value != 0xFFFFFFFF) {
529 if (
N.hasChildren()) {
530 auto ChildOffset =
N.ChildrenOffset;
533 ChildOffset +=
C.Size;
536 VisitNode(
C, Row, VisitNode);
544 VisitNode(Root, 1, VisitNode);