Use unicode multi-table for remaining hot path lookups

Results in a 15% improvement in the unicode throughput benchmark
This commit is contained in:
Kovid Goyal 2025-03-24 15:04:33 +05:30
parent 2c0bc79be1
commit 9f7643078c
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
10 changed files with 69465 additions and 69013 deletions

View file

@ -327,37 +327,6 @@ def create_header(path: str, include_data_types: bool = True) -> Generator[Calla
p('END_ALLOW_CASE_RANGE')
def gen_emoji() -> None:
with create_header('kitty/emoji.h') as p:
p('static inline bool\nis_emoji(char_type code) {')
p('\tswitch(code) {')
for spec in get_ranges(list(all_emoji)):
write_case(spec, p)
p('\t\t\treturn true;')
p('\t\tdefault: return false;')
p('\t}')
p('\treturn false;\n}')
p('static inline bool\nis_symbol(char_type code) {')
p('\tswitch(code) {')
for spec in get_ranges(list(all_symbols)):
write_case(spec, p)
p('\t\t\treturn true;')
p('\t\tdefault: return false;')
p('\t}')
p('\treturn false;\n}')
p('static inline bool\nis_narrow_emoji(char_type code) {')
p('\tswitch(code) {')
for spec in get_ranges(list(narrow_emoji)):
write_case(spec, p)
p('\t\t\treturn true;')
p('\t\tdefault: return false;')
p('\t}')
p('\treturn false;\n}')
def category_test(
name: str,
p: Callable[..., None],
@ -422,29 +391,11 @@ def gen_ucd() -> None:
with create_header('kitty/unicode-data.c') as p:
p('#include "unicode-data.h"')
p('START_ALLOW_CASE_RANGE')
category_test(
'is_combining_char', p,
(),
'Combining and default ignored characters',
extra_chars=marks,
least_check_return='false'
)
category_test(
'is_ignored_char', p, 'Cc Cs'.split(),
'Control characters and non-characters',
extra_chars=non_characters,
ascii_range='false'
)
category_test(
'is_non_rendered_char', p, 'Cc Cs Cf'.split(),
'Other_Default_Ignorable_Code_Point and soft hyphen',
extra_chars=property_maps['Other_Default_Ignorable_Code_Point'] | set(range(0xfe00, 0xfe0f + 1)),
ascii_range='false'
)
category_test('is_word_char', p, {c for c in class_maps if c[0] in 'LN'}, 'L and N categories')
category_test('is_CZ_category', p, cz, 'C and Z categories')
category_test('is_P_category', p, {c for c in class_maps if c[0] == 'P'}, 'P category (punctuation)')
def gen_names() -> None:
aliases_map: dict[int, set[str]] = {}
for word, codepoints in word_search_map.items():
@ -641,6 +592,9 @@ class CharProps(NamedTuple):
is_extended_pictographic: bool = True
is_non_rendered: bool = True
is_emoji_presentation_base: bool = True
is_emoji: bool = True
is_symbol: bool = True
is_combining_char: bool = True
@property
def go_fields(self) -> Iterable[str]:
@ -675,12 +629,21 @@ def as_go(self) -> str:
@property
def as_c(self) -> str:
return ('{'
f' .shifted_width={self.width + width_shift}, .grapheme_break=GBP_{self.grapheme_break},'
f' .indic_conjunct_break=ICB_{self.indic_conjunct_break},'
f' .is_invalid={int(self.is_invalid)}, .is_extended_pictographic={int(self.is_extended_pictographic)},'
f' .is_non_rendered={int(self.is_non_rendered)}, .is_emoji_presentation_base={int(self.is_emoji_presentation_base)}'
' }')
parts = []
for f in self._fields:
x = getattr(self, f)
match f:
case 'width':
x += width_shift
f = 'shifted_width'
case 'grapheme_break':
x = f'GBP_{x}'
case 'indic_conjunct_break':
x = f'ICB_{x}'
case _:
x = int(x)
parts.append(f'.{f}={x}')
return '{' + ', '.join(parts) + '}'
def generate_enum(p: Callable[..., None], gp: Callable[..., None], name: str, *items: str, prefix: str = '') -> None:
@ -728,8 +691,9 @@ def aw(s: Iterable[int], width: int) -> None:
prop_array = tuple(
CharProps(
width=width_map.get(ch, 1), grapheme_break=gs_map.get(ch, 'None'), indic_conjunct_break=icb_map.get(ch, 'None'),
is_invalid=ch in invalid, is_non_rendered=ch in non_printing,
is_invalid=ch in invalid, is_non_rendered=ch in non_printing, is_emoji=ch in all_emoji, is_symbol=ch in all_symbols,
is_extended_pictographic=ch in extended_pictographic, is_emoji_presentation_base=ch in emoji_presentation_bases,
is_combining_char=ch in marks,
) for ch in range(sys.maxunicode + 1))
t1, t2, shift, mask, bytesz = splitbins(prop_array, 2)
print(f'Size of character properties table: {bytesz/1024:.1f}KB')
@ -763,7 +727,6 @@ def main(args: list[str]=sys.argv) -> None:
parse_eaw()
parse_grapheme_segmentation()
gen_ucd()
gen_emoji()
gen_names()
gen_rowcolumn_diacritics()
gen_test_data()

68228
kitty/char-props-data.h generated

File diff suppressed because one or more lines are too long

View file

@ -18,7 +18,9 @@ typedef union CharProps {
uint8_t shifted_width : 3;
uint8_t is_non_rendered : 1;
uint8_t is_emoji_presentation_base : 1;
uint8_t : 3;
uint8_t is_emoji : 1;
uint8_t is_symbol : 1;
uint8_t is_combining_char : 1;
};
uint16_t val;
} CharProps;

1041
kitty/emoji.h generated

File diff suppressed because it is too large Load diff

View file

@ -10,7 +10,7 @@
#include "pyport.h"
#include "charsets.h"
#include "state.h"
#include "emoji.h"
#include "char-props.h"
#include "unicode-data.h"
#include "decorations.h"
#include "glyph-cache.h"
@ -582,8 +582,9 @@ face_has_codepoint(const void* face, char_type cp) {
static bool
has_emoji_presentation(const CPUCell *c, const ListOfChars *lc) {
bool is_text_presentation;
return c->is_multicell && lc->count && is_emoji(lc->chars[0]) && (
( (is_text_presentation = is_narrow_emoji(lc->chars[0])) && lc->count > 1 && lc->chars[1] == VS16 ) ||
CharProps cp;
return c->is_multicell && lc->count && (cp = char_props_for(lc->chars[0])).is_emoji && (
( (is_text_presentation = wcwidth_std(cp) < 2) && lc->count > 1 && lc->chars[1] == VS16 ) ||
( !is_text_presentation && (lc->count == 1 || lc->chars[1] != VS15) )
);
}
@ -593,7 +594,7 @@ has_cell_text(bool(*has_codepoint)(const void*, char_type ch), const void* face,
RAII_ListOfChars(llc);
if (!has_codepoint(face, lc->chars[0])) goto not_found;
for (unsigned i = 1; i < lc->count; i++) {
if (!is_non_rendered_char(lc->chars[i])) {
if (!char_props_for(lc->chars[i]).is_non_rendered) {
ensure_space_for_chars(&llc, llc.count+1);
llc.chars[llc.count++] = lc->chars[i];
}
@ -1803,7 +1804,7 @@ is_non_emoji_dingbat(char_type ch) {
START_ALLOW_CASE_RANGE
case 0x2700 ... 0x27bf:
case 0x1f100 ... 0x1f1ff:
return !is_emoji(ch);
return !char_props_for(ch).is_emoji;
END_ALLOW_CASE_RANGE
}
return false;
@ -1866,7 +1867,7 @@ render_line(FONTS_DATA_HANDLE fg_, Line *line, index_type lnum, Cursor *cursor,
cell_font.font_idx = font_for_cell(fg, cpu_cell, gpu_cell, &is_main_font, &is_emoji_presentation, line->text_cache, lc);
if (
cell_font.font_idx != MISSING_FONT &&
((!is_main_font && !is_emoji_presentation && is_symbol(first_ch)) || (cell_font.font_idx != BOX_FONT && (is_private_use(first_ch))) || is_non_emoji_dingbat(first_ch))
((!is_main_font && !is_emoji_presentation && char_props_for(first_ch).is_symbol) || (cell_font.font_idx != BOX_FONT && (is_private_use(first_ch))) || is_non_emoji_dingbat(first_ch))
) {
unsigned int desired_cells = 1;
if (cell_font.font_idx > 0) {

View file

@ -9,7 +9,6 @@
#include <hb.h>
#include <hb-ft.h>
#include "charsets.h"
#include "unicode-data.h"
#include "char-props.h"
#include "wcswidth.h"
#include FT_BITMAP_H
@ -409,7 +408,7 @@ static bool
process_codepoint(RenderCtx *ctx, RenderState *rs, char_type codep, char_type next_codep) {
bool add_to_current_buffer = false;
Face *fallback_font = NULL;
if (is_combining_char(codep)) {
if (char_props_for(codep).is_combining_char) {
add_to_current_buffer = true;
} else if (glyph_id_for_codepoint(&main_face, codep) > 0) {
add_to_current_buffer = rs->current_face == &main_face;

View file

@ -1087,7 +1087,7 @@ draw_text_loop(Screen *self, const uint32_t *chars, size_t num_chars, text_loop_
draw_control_char(self, s, ch);
continue;
}
if (self->cursor->x < self->columns && s->cp[self->cursor->x].is_multicell && !is_combining_char(ch)) {
if (self->cursor->x < self->columns && s->cp[self->cursor->x].is_multicell && !char_props_for(ch).is_combining_char) {
if (s->cp[self->cursor->x].y) {
move_cursor_past_multicell(self, 1);
init_text_loop_line(self, s);
@ -1096,8 +1096,9 @@ draw_text_loop(Screen *self, const uint32_t *chars, size_t num_chars, text_loop_
int char_width = 1;
if (ch > DEL) { // not printable ASCII
if (is_ignored_char(ch)) continue;
if (UNLIKELY(is_combining_char(ch))) {
CharProps cp = char_props_for(ch);
if (cp.is_invalid) continue;
if (UNLIKELY(cp.is_combining_char)) {
if (UNLIKELY(is_flag_codepoint(ch))) {
if (draw_second_flag_codepoint(self, ch)) continue;
} else {
@ -1105,7 +1106,7 @@ draw_text_loop(Screen *self, const uint32_t *chars, size_t num_chars, text_loop_
continue;
}
}
char_width = wcwidth_std(char_props_for(ch));
char_width = wcwidth_std(cp);
if (UNLIKELY(char_width < 1)) {
if (char_width == 0) continue;
char_width = 1;
@ -1281,8 +1282,9 @@ screen_handle_multicell_command(Screen *self, const MultiCellCommand *cmd, const
mcd.natural_width = true;
for (unsigned i = 0; i < self->lc->count; i++) {
char_type ch = self->lc->chars[i];
if (is_ignored_char(ch)) continue;
if (is_combining_char(ch)) {
CharProps cp = char_props_for(ch);
if (cp.is_invalid) continue;
if (cp.is_combining_char) {
if (is_flag_codepoint(ch)) {
if (lc.count == 1) {
if (is_flag_pair(lc.chars[0], ch)) {

802
kitty/unicode-data.c generated
View file

@ -7,808 +7,6 @@ START_ALLOW_CASE_RANGE
#include "unicode-data.h"
START_ALLOW_CASE_RANGE
bool
is_combining_char(char_type code) {
// Combining and default ignored characters (6475 codepoints) {{{
if (LIKELY(code < 173)) return false;
switch(code) {
case 0xad:
return true;
case 0x300 ... 0x36f:
return true;
case 0x483 ... 0x489:
return true;
case 0x591 ... 0x5bd:
return true;
case 0x5bf:
return true;
case 0x5c1 ... 0x5c2:
return true;
case 0x5c4 ... 0x5c5:
return true;
case 0x5c7:
return true;
case 0x600 ... 0x605:
return true;
case 0x610 ... 0x61a:
return true;
case 0x61c:
return true;
case 0x64b ... 0x65f:
return true;
case 0x670:
return true;
case 0x6d6 ... 0x6dd:
return true;
case 0x6df ... 0x6e4:
return true;
case 0x6e7 ... 0x6e8:
return true;
case 0x6ea ... 0x6ed:
return true;
case 0x70f:
return true;
case 0x711:
return true;
case 0x730 ... 0x74a:
return true;
case 0x7a6 ... 0x7b0:
return true;
case 0x7eb ... 0x7f3:
return true;
case 0x7fd:
return true;
case 0x816 ... 0x819:
return true;
case 0x81b ... 0x823:
return true;
case 0x825 ... 0x827:
return true;
case 0x829 ... 0x82d:
return true;
case 0x859 ... 0x85b:
return true;
case 0x890 ... 0x891:
return true;
case 0x897 ... 0x89f:
return true;
case 0x8ca ... 0x903:
return true;
case 0x93a ... 0x93c:
return true;
case 0x93e ... 0x94f:
return true;
case 0x951 ... 0x957:
return true;
case 0x962 ... 0x963:
return true;
case 0x981 ... 0x983:
return true;
case 0x9bc:
return true;
case 0x9be ... 0x9c4:
return true;
case 0x9c7 ... 0x9c8:
return true;
case 0x9cb ... 0x9cd:
return true;
case 0x9d7:
return true;
case 0x9e2 ... 0x9e3:
return true;
case 0x9fe:
return true;
case 0xa01 ... 0xa03:
return true;
case 0xa3c:
return true;
case 0xa3e ... 0xa42:
return true;
case 0xa47 ... 0xa48:
return true;
case 0xa4b ... 0xa4d:
return true;
case 0xa51:
return true;
case 0xa70 ... 0xa71:
return true;
case 0xa75:
return true;
case 0xa81 ... 0xa83:
return true;
case 0xabc:
return true;
case 0xabe ... 0xac5:
return true;
case 0xac7 ... 0xac9:
return true;
case 0xacb ... 0xacd:
return true;
case 0xae2 ... 0xae3:
return true;
case 0xafa ... 0xaff:
return true;
case 0xb01 ... 0xb03:
return true;
case 0xb3c:
return true;
case 0xb3e ... 0xb44:
return true;
case 0xb47 ... 0xb48:
return true;
case 0xb4b ... 0xb4d:
return true;
case 0xb55 ... 0xb57:
return true;
case 0xb62 ... 0xb63:
return true;
case 0xb82:
return true;
case 0xbbe ... 0xbc2:
return true;
case 0xbc6 ... 0xbc8:
return true;
case 0xbca ... 0xbcd:
return true;
case 0xbd7:
return true;
case 0xc00 ... 0xc04:
return true;
case 0xc3c:
return true;
case 0xc3e ... 0xc44:
return true;
case 0xc46 ... 0xc48:
return true;
case 0xc4a ... 0xc4d:
return true;
case 0xc55 ... 0xc56:
return true;
case 0xc62 ... 0xc63:
return true;
case 0xc81 ... 0xc83:
return true;
case 0xcbc:
return true;
case 0xcbe ... 0xcc4:
return true;
case 0xcc6 ... 0xcc8:
return true;
case 0xcca ... 0xccd:
return true;
case 0xcd5 ... 0xcd6:
return true;
case 0xce2 ... 0xce3:
return true;
case 0xcf3:
return true;
case 0xd00 ... 0xd03:
return true;
case 0xd3b ... 0xd3c:
return true;
case 0xd3e ... 0xd44:
return true;
case 0xd46 ... 0xd48:
return true;
case 0xd4a ... 0xd4d:
return true;
case 0xd57:
return true;
case 0xd62 ... 0xd63:
return true;
case 0xd81 ... 0xd83:
return true;
case 0xdca:
return true;
case 0xdcf ... 0xdd4:
return true;
case 0xdd6:
return true;
case 0xdd8 ... 0xddf:
return true;
case 0xdf2 ... 0xdf3:
return true;
case 0xe31:
return true;
case 0xe34 ... 0xe3a:
return true;
case 0xe47 ... 0xe4e:
return true;
case 0xeb1:
return true;
case 0xeb4 ... 0xebc:
return true;
case 0xec8 ... 0xece:
return true;
case 0xf18 ... 0xf19:
return true;
case 0xf35:
return true;
case 0xf37:
return true;
case 0xf39:
return true;
case 0xf3e ... 0xf3f:
return true;
case 0xf71 ... 0xf84:
return true;
case 0xf86 ... 0xf87:
return true;
case 0xf8d ... 0xf97:
return true;
case 0xf99 ... 0xfbc:
return true;
case 0xfc6:
return true;
case 0x102b ... 0x103e:
return true;
case 0x1056 ... 0x1059:
return true;
case 0x105e ... 0x1060:
return true;
case 0x1062 ... 0x1064:
return true;
case 0x1067 ... 0x106d:
return true;
case 0x1071 ... 0x1074:
return true;
case 0x1082 ... 0x108d:
return true;
case 0x108f:
return true;
case 0x109a ... 0x109d:
return true;
case 0x115f ... 0x1160:
return true;
case 0x135d ... 0x135f:
return true;
case 0x1712 ... 0x1715:
return true;
case 0x1732 ... 0x1734:
return true;
case 0x1752 ... 0x1753:
return true;
case 0x1772 ... 0x1773:
return true;
case 0x17b4 ... 0x17d3:
return true;
case 0x17dd:
return true;
case 0x180b ... 0x180f:
return true;
case 0x1885 ... 0x1886:
return true;
case 0x18a9:
return true;
case 0x1920 ... 0x192b:
return true;
case 0x1930 ... 0x193b:
return true;
case 0x1a17 ... 0x1a1b:
return true;
case 0x1a55 ... 0x1a5e:
return true;
case 0x1a60 ... 0x1a7c:
return true;
case 0x1a7f:
return true;
case 0x1ab0 ... 0x1ace:
return true;
case 0x1b00 ... 0x1b04:
return true;
case 0x1b34 ... 0x1b44:
return true;
case 0x1b6b ... 0x1b73:
return true;
case 0x1b80 ... 0x1b82:
return true;
case 0x1ba1 ... 0x1bad:
return true;
case 0x1be6 ... 0x1bf3:
return true;
case 0x1c24 ... 0x1c37:
return true;
case 0x1cd0 ... 0x1cd2:
return true;
case 0x1cd4 ... 0x1ce8:
return true;
case 0x1ced:
return true;
case 0x1cf4:
return true;
case 0x1cf7 ... 0x1cf9:
return true;
case 0x1dc0 ... 0x1dff:
return true;
case 0x200b ... 0x200f:
return true;
case 0x202a ... 0x202e:
return true;
case 0x2060 ... 0x206f:
return true;
case 0x20d0 ... 0x20f0:
return true;
case 0x2cef ... 0x2cf1:
return true;
case 0x2d7f:
return true;
case 0x2de0 ... 0x2dff:
return true;
case 0x302a ... 0x302f:
return true;
case 0x3099 ... 0x309a:
return true;
case 0x3164:
return true;
case 0xa66f ... 0xa672:
return true;
case 0xa674 ... 0xa67d:
return true;
case 0xa69e ... 0xa69f:
return true;
case 0xa6f0 ... 0xa6f1:
return true;
case 0xa802:
return true;
case 0xa806:
return true;
case 0xa80b:
return true;
case 0xa823 ... 0xa827:
return true;
case 0xa82c:
return true;
case 0xa880 ... 0xa881:
return true;
case 0xa8b4 ... 0xa8c5:
return true;
case 0xa8e0 ... 0xa8f1:
return true;
case 0xa8ff:
return true;
case 0xa926 ... 0xa92d:
return true;
case 0xa947 ... 0xa953:
return true;
case 0xa980 ... 0xa983:
return true;
case 0xa9b3 ... 0xa9c0:
return true;
case 0xa9e5:
return true;
case 0xaa29 ... 0xaa36:
return true;
case 0xaa43:
return true;
case 0xaa4c ... 0xaa4d:
return true;
case 0xaa7b ... 0xaa7d:
return true;
case 0xaab0:
return true;
case 0xaab2 ... 0xaab4:
return true;
case 0xaab7 ... 0xaab8:
return true;
case 0xaabe ... 0xaabf:
return true;
case 0xaac1:
return true;
case 0xaaeb ... 0xaaef:
return true;
case 0xaaf5 ... 0xaaf6:
return true;
case 0xabe3 ... 0xabea:
return true;
case 0xabec ... 0xabed:
return true;
case 0xfb1e:
return true;
case 0xfe00 ... 0xfe0f:
return true;
case 0xfe20 ... 0xfe2f:
return true;
case 0xfeff:
return true;
case 0xffa0:
return true;
case 0xfff0 ... 0xfffb:
return true;
case 0x101fd:
return true;
case 0x102e0:
return true;
case 0x10376 ... 0x1037a:
return true;
case 0x10a01 ... 0x10a03:
return true;
case 0x10a05 ... 0x10a06:
return true;
case 0x10a0c ... 0x10a0f:
return true;
case 0x10a38 ... 0x10a3a:
return true;
case 0x10a3f:
return true;
case 0x10ae5 ... 0x10ae6:
return true;
case 0x10d24 ... 0x10d27:
return true;
case 0x10d69 ... 0x10d6d:
return true;
case 0x10eab ... 0x10eac:
return true;
case 0x10efc ... 0x10eff:
return true;
case 0x10f46 ... 0x10f50:
return true;
case 0x10f82 ... 0x10f85:
return true;
case 0x11000 ... 0x11002:
return true;
case 0x11038 ... 0x11046:
return true;
case 0x11070:
return true;
case 0x11073 ... 0x11074:
return true;
case 0x1107f ... 0x11082:
return true;
case 0x110b0 ... 0x110ba:
return true;
case 0x110bd:
return true;
case 0x110c2:
return true;
case 0x110cd:
return true;
case 0x11100 ... 0x11102:
return true;
case 0x11127 ... 0x11134:
return true;
case 0x11145 ... 0x11146:
return true;
case 0x11173:
return true;
case 0x11180 ... 0x11182:
return true;
case 0x111b3 ... 0x111c0:
return true;
case 0x111c9 ... 0x111cc:
return true;
case 0x111ce ... 0x111cf:
return true;
case 0x1122c ... 0x11237:
return true;
case 0x1123e:
return true;
case 0x11241:
return true;
case 0x112df ... 0x112ea:
return true;
case 0x11300 ... 0x11303:
return true;
case 0x1133b ... 0x1133c:
return true;
case 0x1133e ... 0x11344:
return true;
case 0x11347 ... 0x11348:
return true;
case 0x1134b ... 0x1134d:
return true;
case 0x11357:
return true;
case 0x11362 ... 0x11363:
return true;
case 0x11366 ... 0x1136c:
return true;
case 0x11370 ... 0x11374:
return true;
case 0x113b8 ... 0x113c0:
return true;
case 0x113c2:
return true;
case 0x113c5:
return true;
case 0x113c7 ... 0x113ca:
return true;
case 0x113cc ... 0x113d0:
return true;
case 0x113d2:
return true;
case 0x113e1 ... 0x113e2:
return true;
case 0x11435 ... 0x11446:
return true;
case 0x1145e:
return true;
case 0x114b0 ... 0x114c3:
return true;
case 0x115af ... 0x115b5:
return true;
case 0x115b8 ... 0x115c0:
return true;
case 0x115dc ... 0x115dd:
return true;
case 0x11630 ... 0x11640:
return true;
case 0x116ab ... 0x116b7:
return true;
case 0x1171d ... 0x1172b:
return true;
case 0x1182c ... 0x1183a:
return true;
case 0x11930 ... 0x11935:
return true;
case 0x11937 ... 0x11938:
return true;
case 0x1193b ... 0x1193e:
return true;
case 0x11940:
return true;
case 0x11942 ... 0x11943:
return true;
case 0x119d1 ... 0x119d7:
return true;
case 0x119da ... 0x119e0:
return true;
case 0x119e4:
return true;
case 0x11a01 ... 0x11a0a:
return true;
case 0x11a33 ... 0x11a39:
return true;
case 0x11a3b ... 0x11a3e:
return true;
case 0x11a47:
return true;
case 0x11a51 ... 0x11a5b:
return true;
case 0x11a8a ... 0x11a99:
return true;
case 0x11c2f ... 0x11c36:
return true;
case 0x11c38 ... 0x11c3f:
return true;
case 0x11c92 ... 0x11ca7:
return true;
case 0x11ca9 ... 0x11cb6:
return true;
case 0x11d31 ... 0x11d36:
return true;
case 0x11d3a:
return true;
case 0x11d3c ... 0x11d3d:
return true;
case 0x11d3f ... 0x11d45:
return true;
case 0x11d47:
return true;
case 0x11d8a ... 0x11d8e:
return true;
case 0x11d90 ... 0x11d91:
return true;
case 0x11d93 ... 0x11d97:
return true;
case 0x11ef3 ... 0x11ef6:
return true;
case 0x11f00 ... 0x11f01:
return true;
case 0x11f03:
return true;
case 0x11f34 ... 0x11f3a:
return true;
case 0x11f3e ... 0x11f42:
return true;
case 0x11f5a:
return true;
case 0x13430 ... 0x13440:
return true;
case 0x13447 ... 0x13455:
return true;
case 0x1611e ... 0x1612f:
return true;
case 0x16af0 ... 0x16af4:
return true;
case 0x16b30 ... 0x16b36:
return true;
case 0x16f4f:
return true;
case 0x16f51 ... 0x16f87:
return true;
case 0x16f8f ... 0x16f92:
return true;
case 0x16fe4:
return true;
case 0x16ff0 ... 0x16ff1:
return true;
case 0x1bc9d ... 0x1bc9e:
return true;
case 0x1bca0 ... 0x1bca3:
return true;
case 0x1cf00 ... 0x1cf2d:
return true;
case 0x1cf30 ... 0x1cf46:
return true;
case 0x1d165 ... 0x1d169:
return true;
case 0x1d16d ... 0x1d182:
return true;
case 0x1d185 ... 0x1d18b:
return true;
case 0x1d1aa ... 0x1d1ad:
return true;
case 0x1d242 ... 0x1d244:
return true;
case 0x1da00 ... 0x1da36:
return true;
case 0x1da3b ... 0x1da6c:
return true;
case 0x1da75:
return true;
case 0x1da84:
return true;
case 0x1da9b ... 0x1da9f:
return true;
case 0x1daa1 ... 0x1daaf:
return true;
case 0x1e000 ... 0x1e006:
return true;
case 0x1e008 ... 0x1e018:
return true;
case 0x1e01b ... 0x1e021:
return true;
case 0x1e023 ... 0x1e024:
return true;
case 0x1e026 ... 0x1e02a:
return true;
case 0x1e08f:
return true;
case 0x1e130 ... 0x1e136:
return true;
case 0x1e2ae:
return true;
case 0x1e2ec ... 0x1e2ef:
return true;
case 0x1e4ec ... 0x1e4ef:
return true;
case 0x1e5ee ... 0x1e5ef:
return true;
case 0x1e8d0 ... 0x1e8d6:
return true;
case 0x1e944 ... 0x1e94a:
return true;
case 0x1f1e6 ... 0x1f1ff:
return true;
case 0x1f3fb ... 0x1f3ff:
return true;
case 0xe0000 ... 0xe0fff:
return true;
} // }}}
return false;
}
bool
is_ignored_char(char_type code) {
// Control characters and non-characters (2179 codepoints) {{{
if (LIKELY(0x20 <= code && code <= 0x7e)) return false;
switch(code) {
case 0x0 ... 0x1f:
return true;
case 0x7f ... 0x9f:
return true;
case 0xd800 ... 0xdfff:
return true;
case 0xfdd0 ... 0xfdef:
return true;
case 0xfffe ... 0xffff:
return true;
case 0x1fffe ... 0x1ffff:
return true;
case 0x2fffe ... 0x2ffff:
return true;
case 0x3fffe ... 0x3ffff:
return true;
case 0x4fffe ... 0x4ffff:
return true;
case 0x5fffe ... 0x5ffff:
return true;
case 0x6fffe ... 0x6ffff:
return true;
case 0x7fffe ... 0x7ffff:
return true;
case 0x8fffe ... 0x8ffff:
return true;
case 0x9fffe ... 0x9ffff:
return true;
case 0xafffe ... 0xaffff:
return true;
case 0xbfffe ... 0xbffff:
return true;
case 0xcfffe ... 0xcffff:
return true;
case 0xdfffe ... 0xdffff:
return true;
case 0xefffe ... 0xeffff:
return true;
case 0xffffe ... 0xfffff:
return true;
case 0x10fffe ... 0x10ffff:
return true;
} // }}}
return false;
}
bool
is_non_rendered_char(char_type code) {
// Other_Default_Ignorable_Code_Point and soft hyphen (6075 codepoints) {{{
if (LIKELY(0x20 <= code && code <= 0x7e)) return false;
switch(code) {
case 0x0 ... 0x1f:
return true;
case 0x7f ... 0x9f:
return true;
case 0xad:
return true;
case 0x34f:
return true;
case 0x600 ... 0x605:
return true;
case 0x61c:
return true;
case 0x6dd:
return true;
case 0x70f:
return true;
case 0x890 ... 0x891:
return true;
case 0x8e2:
return true;
case 0x115f ... 0x1160:
return true;
case 0x17b4 ... 0x17b5:
return true;
case 0x180e:
return true;
case 0x200b ... 0x200f:
return true;
case 0x202a ... 0x202e:
return true;
case 0x2060 ... 0x206f:
return true;
case 0x3164:
return true;
case 0xd800 ... 0xdfff:
return true;
case 0xfe00 ... 0xfe0f:
return true;
case 0xfeff:
return true;
case 0xffa0:
return true;
case 0xfff0 ... 0xfffb:
return true;
case 0x110bd:
return true;
case 0x110cd:
return true;
case 0x13430 ... 0x1343f:
return true;
case 0x1bca0 ... 0x1bca3:
return true;
case 0x1d173 ... 0x1d17a:
return true;
case 0xe0000 ... 0xe00ff:
return true;
case 0xe01f0 ... 0xe0fff:
return true;
} // }}}
return false;
}
bool
is_word_char(char_type code) {
// L and N categories (142939 codepoints) {{{

View file

@ -5,12 +5,9 @@
// Converts row/column diacritics to numbers.
int diacritic_to_num(char_type ch);
bool is_combining_char(char_type ch);
bool is_ignored_char(char_type ch);
bool is_word_char(char_type ch);
bool is_CZ_category(char_type);
bool is_P_category(char_type);
bool is_non_rendered_char(char_type);
static inline bool
is_excluded_from_url(uint32_t ch) {

File diff suppressed because one or more lines are too long