From 82f7654c911b7f8f6ff3b3324f14ca64fd70b173 Mon Sep 17 00:00:00 2001 From: Hyeseong Kim Date: Fri, 31 Jul 2026 15:34:55 +0900 Subject: [PATCH] replace `InCB_Extend_table` search with simple predicates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to [UCD](https://www.unicode.org/reports/tr44/), the property `InCB=Extend` is defined as: ``` \p{InCB = Extend} ≔ [ \p{gcb=Extend} \p{gcb=ZWJ} - \p{InCB=Linker} - \p{InCB=Consonant} - [\u200C] ] ``` And no `InCB=Consonant` is `gcb=Extend` or `gcb=ZWJ`. So in can be determined with the grapheme category the caller already has and two equality. `scripts/unicode.py` now checks that derivation against the UCD. A future Unicode version that breaks either fact fails the generator instead of silently mis-segmenting Indic text. Also one fact that is `InCB=Linker` and `InCB=Extend` are subset of `gcb=Extend`, any other category rules out both without inspecting the codepoint. This change improves the overall performance of the grapheme APIs by skipping unnecessary category checks and table searches in the hot loop. On my machine, it measures approximately -15 to -20%. --- scripts/unicode.py | 39 +++++++++++++- src/grapheme.rs | 35 +++++++++++-- src/tables.rs | 124 --------------------------------------------- 3 files changed, 68 insertions(+), 130 deletions(-) diff --git a/scripts/unicode.py b/scripts/unicode.py index d253dcd..404b242 100755 --- a/scripts/unicode.py +++ b/scripts/unicode.py @@ -283,6 +283,41 @@ def emit_property_module(f, mod, tbl, emit: "list[str | tuple[str, str]]"): f.write(" }\n\n") f.write("}\n\n") +def check_incb_derivable(grapheme_table, incb_extend, incb_linker): + """Check that `InCB=Extend` can be recovered from the Grapheme_Cluster_Break category. + + `grapheme::is_incb_extend` in src/grapheme.rs derives it as + `[\\p{gcb=Extend} \\p{gcb=ZWJ}] - \\p{InCB=Linker} - U+200C` instead of carrying a range table for it, + which also lets the cursor skip the lookup for every category that is neither `Extend` nor `ZWJ`. + + Both facts are checked here so that a Unicode version which invalidates + either fails loudly instead of silently mis-segmenting Indic text. + """ + extend_or_zwj = set() + for (lo, hi, cat) in grapheme_table: + if cat in ("Extend", "ZWJ"): + extend_or_zwj.update(range(lo, hi + 1)) + linkers = {cp for (lo, hi) in incb_linker for cp in range(lo, hi + 1)} + actual = {cp for (lo, hi) in incb_extend for cp in range(lo, hi + 1)} + + stray = sorted(linkers - extend_or_zwj) + if stray: + raise AssertionError( + "InCB=Linker is no longer a subset of gcb=Extend and gcb=ZWJ (%s); " + "grapheme::is_incb_extend in src/grapheme.rs would miss it" + % [hex(c) for c in stray[:8]]) + + derived = extend_or_zwj - linkers - {0x200C} + if actual != derived: + raise AssertionError( + "InCB=Extend is no longer [gcb=Extend gcb=ZWJ] - InCB=Linker - U+200C; " + "grapheme::is_incb_extend in src/grapheme.rs would be wrong. missing=%s extra=%s" + % ([hex(c) for c in sorted(actual - derived)[:8]], + [hex(c) for c in sorted(derived - actual)[:8]])) + + sys.stderr.write( + "InCB=Extend: %d codepoints, all derivable from the grapheme category\n" % len(actual)) + def emit_break_module(f, break_table, break_cats, name): Name = name.capitalize() f.write("""pub mod %s { @@ -408,7 +443,7 @@ def emit_break_module(f, break_table, break_cats, name): emit_util_mod(rf) for (name, cat, pfuns) in ("general_category", gencats, ["N"]), \ - ("derived_property", derived, ["Alphabetic", ("InCB", "Extend")]): + ("derived_property", derived, ["Alphabetic"]): emit_property_module(rf, name, cat, pfuns) rf.write("""pub fn is_incb_linker(c: char) -> bool { @@ -444,6 +479,8 @@ def emit_break_module(f, break_table, break_cats, name): if chars[0] <= last: raise "Grapheme tables and Extended_Pictographic values overlap; need to store these separately!" last = chars[1] + check_incb_derivable(grapheme_table, derived[("InCB", "Extend")], + derived[("InCB", "Linker")]) emit_break_module(rf, grapheme_table, list(grapheme_cats.keys()), "grapheme") rf.write("\n") diff --git a/src/grapheme.rs b/src/grapheme.rs index d33a351..0b39f0c 100644 --- a/src/grapheme.rs +++ b/src/grapheme.rs @@ -284,6 +284,30 @@ fn check_pair(before: GraphemeCat, after: GraphemeCat) -> PairResult { } } +/// Whether `ch`, whose grapheme category is `cat`, has `Indic_Conjunct_Break=Extend`. +/// +/// `InCB=Extend` is defined as +/// `[\p{gcb=Extend} \p{gcb=ZWJ}] - \p{InCB=Linker} - \p{InCB=Consonant} - U+200C`, +/// and no `InCB=Consonant` is `gcb=Extend` or `gcb=ZWJ`, +/// so the grapheme category the caller already has, plus two equality tests, decides it. +/// +/// That saves a binary search over a range table of its own for every codepoint the cursor walks over. +/// +/// `scripts/unicode.py` checks the derivation against the UCD when it regenerates `src/tables.rs`, +/// so a future Unicode version cannot silently invalidate it. +#[inline] +fn is_incb_extend(cat: GraphemeCat, ch: char) -> bool { + // ZWNJ is `gcb=Extend` but `InCB=None`. + may_be_incb(cat) && ch != '\u{200c}' && !crate::tables::is_incb_linker(ch) +} + +/// Both `InCB=Linker` and `InCB=Extend` are subsets of `gcb=Extend` and `gcb=ZWJ`, +/// so any other category rules out both roles without inspecting the codepoint. +#[inline] +fn may_be_incb(cat: GraphemeCat) -> bool { + matches!(cat, GraphemeCat::GC_Extend | GraphemeCat::GC_ZWJ) +} + impl GraphemeCursor { /// Create a new cursor. The string and initial offset are given at creation /// time, but the contents of the string are not. The `is_extended` parameter @@ -492,7 +516,7 @@ impl GraphemeCursor { // We found an InCB linker incb_linker_count += 1; self.incb_linker_count = Some(incb_linker_count); - } else if tables::derived_property::InCB_Extend(ch) { + } else if is_incb_extend(self.grapheme_category(ch), ch) { // We ignore InCB extends, continue } else { // Prev character is neither linker nor extend, break suppressed iff it's InCB=Consonant @@ -724,10 +748,11 @@ impl GraphemeCursor { if self.cat_before.is_none() { self.cat_before = Some(self.grapheme_category(ch)); } - if crate::tables::is_incb_linker(ch) { - self.incb_linker_count = Some(self.incb_linker_count.map_or(1, |c| c + 1)); - } else if !crate::tables::derived_property::InCB_Extend(ch) { + // ZWNJ is the one `gcb=Extend` that is `InCB=None`. + if !may_be_incb(self.cat_before.unwrap()) || ch == '\u{200c}' { self.incb_linker_count = Some(0); + } else if crate::tables::is_incb_linker(ch) { + self.incb_linker_count = Some(self.incb_linker_count.map_or(1, |c| c + 1)); } if self.cat_before.unwrap() == GraphemeCat::GC_Regional_Indicator { self.ris_count = self.ris_count.map(|c| c + 1); @@ -816,7 +841,7 @@ impl GraphemeCursor { self.incb_linker_count = if incb_linker_count > 0 && crate::tables::is_incb_linker(ch) { Some(incb_linker_count - 1) - } else if crate::tables::derived_property::InCB_Extend(ch) { + } else if is_incb_extend(self.grapheme_category(ch), ch) { Some(incb_linker_count) } else { None diff --git a/src/tables.rs b/src/tables.rs index efa2a41..645642b 100644 --- a/src/tables.rs +++ b/src/tables.rs @@ -361,130 +361,6 @@ pub mod derived_property { super::util::bsearch_range_table(c, Alphabetic_table) } - const InCB_Extend_table: &[(char, char)] = &[ - ('\u{300}', '\u{36f}'), ('\u{483}', '\u{489}'), ('\u{591}', '\u{5bd}'), ('\u{5bf}', - '\u{5bf}'), ('\u{5c1}', '\u{5c2}'), ('\u{5c4}', '\u{5c5}'), ('\u{5c7}', '\u{5c7}'), - ('\u{610}', '\u{61a}'), ('\u{64b}', '\u{65f}'), ('\u{670}', '\u{670}'), ('\u{6d6}', - '\u{6dc}'), ('\u{6df}', '\u{6e4}'), ('\u{6e7}', '\u{6e8}'), ('\u{6ea}', '\u{6ed}'), - ('\u{711}', '\u{711}'), ('\u{730}', '\u{74a}'), ('\u{7a6}', '\u{7b0}'), ('\u{7eb}', - '\u{7f3}'), ('\u{7fd}', '\u{7fd}'), ('\u{816}', '\u{819}'), ('\u{81b}', '\u{823}'), - ('\u{825}', '\u{827}'), ('\u{829}', '\u{82d}'), ('\u{859}', '\u{85b}'), ('\u{897}', - '\u{89f}'), ('\u{8ca}', '\u{8e1}'), ('\u{8e3}', '\u{902}'), ('\u{93a}', '\u{93a}'), - ('\u{93c}', '\u{93c}'), ('\u{941}', '\u{948}'), ('\u{951}', '\u{957}'), ('\u{962}', - '\u{963}'), ('\u{981}', '\u{981}'), ('\u{9bc}', '\u{9bc}'), ('\u{9be}', '\u{9be}'), - ('\u{9c1}', '\u{9c4}'), ('\u{9d7}', '\u{9d7}'), ('\u{9e2}', '\u{9e3}'), ('\u{9fe}', - '\u{9fe}'), ('\u{a01}', '\u{a02}'), ('\u{a3c}', '\u{a3c}'), ('\u{a41}', '\u{a42}'), - ('\u{a47}', '\u{a48}'), ('\u{a4b}', '\u{a4d}'), ('\u{a51}', '\u{a51}'), ('\u{a70}', - '\u{a71}'), ('\u{a75}', '\u{a75}'), ('\u{a81}', '\u{a82}'), ('\u{abc}', '\u{abc}'), - ('\u{ac1}', '\u{ac5}'), ('\u{ac7}', '\u{ac8}'), ('\u{ae2}', '\u{ae3}'), ('\u{afa}', - '\u{aff}'), ('\u{b01}', '\u{b01}'), ('\u{b3c}', '\u{b3c}'), ('\u{b3e}', '\u{b3f}'), - ('\u{b41}', '\u{b44}'), ('\u{b55}', '\u{b57}'), ('\u{b62}', '\u{b63}'), ('\u{b82}', - '\u{b82}'), ('\u{bbe}', '\u{bbe}'), ('\u{bc0}', '\u{bc0}'), ('\u{bcd}', '\u{bcd}'), - ('\u{bd7}', '\u{bd7}'), ('\u{c00}', '\u{c00}'), ('\u{c04}', '\u{c04}'), ('\u{c3c}', - '\u{c3c}'), ('\u{c3e}', '\u{c40}'), ('\u{c46}', '\u{c48}'), ('\u{c4a}', '\u{c4c}'), - ('\u{c55}', '\u{c56}'), ('\u{c62}', '\u{c63}'), ('\u{c81}', '\u{c81}'), ('\u{cbc}', - '\u{cbc}'), ('\u{cbf}', '\u{cc0}'), ('\u{cc2}', '\u{cc2}'), ('\u{cc6}', '\u{cc8}'), - ('\u{cca}', '\u{ccd}'), ('\u{cd5}', '\u{cd6}'), ('\u{ce2}', '\u{ce3}'), ('\u{d00}', - '\u{d01}'), ('\u{d3b}', '\u{d3c}'), ('\u{d3e}', '\u{d3e}'), ('\u{d41}', '\u{d44}'), - ('\u{d57}', '\u{d57}'), ('\u{d62}', '\u{d63}'), ('\u{d81}', '\u{d81}'), ('\u{dca}', - '\u{dca}'), ('\u{dcf}', '\u{dcf}'), ('\u{dd2}', '\u{dd4}'), ('\u{dd6}', '\u{dd6}'), - ('\u{ddf}', '\u{ddf}'), ('\u{e31}', '\u{e31}'), ('\u{e34}', '\u{e3a}'), ('\u{e47}', - '\u{e4e}'), ('\u{eb1}', '\u{eb1}'), ('\u{eb4}', '\u{ebc}'), ('\u{ec8}', '\u{ece}'), - ('\u{f18}', '\u{f19}'), ('\u{f35}', '\u{f35}'), ('\u{f37}', '\u{f37}'), ('\u{f39}', - '\u{f39}'), ('\u{f71}', '\u{f7e}'), ('\u{f80}', '\u{f84}'), ('\u{f86}', '\u{f87}'), - ('\u{f8d}', '\u{f97}'), ('\u{f99}', '\u{fbc}'), ('\u{fc6}', '\u{fc6}'), ('\u{102d}', - '\u{1030}'), ('\u{1032}', '\u{1037}'), ('\u{103a}', '\u{103a}'), ('\u{103d}', '\u{103e}'), - ('\u{1058}', '\u{1059}'), ('\u{105e}', '\u{1060}'), ('\u{1071}', '\u{1074}'), ('\u{1082}', - '\u{1082}'), ('\u{1085}', '\u{1086}'), ('\u{108d}', '\u{108d}'), ('\u{109d}', '\u{109d}'), - ('\u{135d}', '\u{135f}'), ('\u{1712}', '\u{1715}'), ('\u{1732}', '\u{1734}'), ('\u{1752}', - '\u{1753}'), ('\u{1772}', '\u{1773}'), ('\u{17b4}', '\u{17b5}'), ('\u{17b7}', '\u{17bd}'), - ('\u{17c6}', '\u{17c6}'), ('\u{17c9}', '\u{17d1}'), ('\u{17d3}', '\u{17d3}'), ('\u{17dd}', - '\u{17dd}'), ('\u{180b}', '\u{180d}'), ('\u{180f}', '\u{180f}'), ('\u{1885}', '\u{1886}'), - ('\u{18a9}', '\u{18a9}'), ('\u{1920}', '\u{1922}'), ('\u{1927}', '\u{1928}'), ('\u{1932}', - '\u{1932}'), ('\u{1939}', '\u{193b}'), ('\u{1a17}', '\u{1a18}'), ('\u{1a1b}', '\u{1a1b}'), - ('\u{1a56}', '\u{1a56}'), ('\u{1a58}', '\u{1a5e}'), ('\u{1a62}', '\u{1a62}'), ('\u{1a65}', - '\u{1a6c}'), ('\u{1a73}', '\u{1a7c}'), ('\u{1a7f}', '\u{1a7f}'), ('\u{1ab0}', '\u{1add}'), - ('\u{1ae0}', '\u{1aeb}'), ('\u{1b00}', '\u{1b03}'), ('\u{1b34}', '\u{1b3d}'), ('\u{1b42}', - '\u{1b43}'), ('\u{1b6b}', '\u{1b73}'), ('\u{1b80}', '\u{1b81}'), ('\u{1ba2}', '\u{1ba5}'), - ('\u{1ba8}', '\u{1baa}'), ('\u{1bac}', '\u{1bad}'), ('\u{1be6}', '\u{1be6}'), ('\u{1be8}', - '\u{1be9}'), ('\u{1bed}', '\u{1bed}'), ('\u{1bef}', '\u{1bf3}'), ('\u{1c2c}', '\u{1c33}'), - ('\u{1c36}', '\u{1c37}'), ('\u{1cd0}', '\u{1cd2}'), ('\u{1cd4}', '\u{1ce0}'), ('\u{1ce2}', - '\u{1ce8}'), ('\u{1ced}', '\u{1ced}'), ('\u{1cf4}', '\u{1cf4}'), ('\u{1cf8}', '\u{1cf9}'), - ('\u{1dc0}', '\u{1dff}'), ('\u{200d}', '\u{200d}'), ('\u{20d0}', '\u{20f0}'), ('\u{2cef}', - '\u{2cf1}'), ('\u{2d7f}', '\u{2d7f}'), ('\u{2de0}', '\u{2dff}'), ('\u{302a}', '\u{302f}'), - ('\u{3099}', '\u{309a}'), ('\u{a66f}', '\u{a672}'), ('\u{a674}', '\u{a67d}'), ('\u{a69e}', - '\u{a69f}'), ('\u{a6f0}', '\u{a6f1}'), ('\u{a802}', '\u{a802}'), ('\u{a806}', '\u{a806}'), - ('\u{a80b}', '\u{a80b}'), ('\u{a825}', '\u{a826}'), ('\u{a82c}', '\u{a82c}'), ('\u{a8c4}', - '\u{a8c5}'), ('\u{a8e0}', '\u{a8f1}'), ('\u{a8ff}', '\u{a8ff}'), ('\u{a926}', '\u{a92d}'), - ('\u{a947}', '\u{a951}'), ('\u{a953}', '\u{a953}'), ('\u{a980}', '\u{a982}'), ('\u{a9b3}', - '\u{a9b3}'), ('\u{a9b6}', '\u{a9b9}'), ('\u{a9bc}', '\u{a9bd}'), ('\u{a9e5}', '\u{a9e5}'), - ('\u{aa29}', '\u{aa2e}'), ('\u{aa31}', '\u{aa32}'), ('\u{aa35}', '\u{aa36}'), ('\u{aa43}', - '\u{aa43}'), ('\u{aa4c}', '\u{aa4c}'), ('\u{aa7c}', '\u{aa7c}'), ('\u{aab0}', '\u{aab0}'), - ('\u{aab2}', '\u{aab4}'), ('\u{aab7}', '\u{aab8}'), ('\u{aabe}', '\u{aabf}'), ('\u{aac1}', - '\u{aac1}'), ('\u{aaec}', '\u{aaed}'), ('\u{abe5}', '\u{abe5}'), ('\u{abe8}', '\u{abe8}'), - ('\u{abed}', '\u{abed}'), ('\u{fb1e}', '\u{fb1e}'), ('\u{fe00}', '\u{fe0f}'), ('\u{fe20}', - '\u{fe2f}'), ('\u{ff9e}', '\u{ff9f}'), ('\u{101fd}', '\u{101fd}'), ('\u{102e0}', - '\u{102e0}'), ('\u{10376}', '\u{1037a}'), ('\u{10a01}', '\u{10a03}'), ('\u{10a05}', - '\u{10a06}'), ('\u{10a0c}', '\u{10a0f}'), ('\u{10a38}', '\u{10a3a}'), ('\u{10ae5}', - '\u{10ae6}'), ('\u{10d24}', '\u{10d27}'), ('\u{10d69}', '\u{10d6d}'), ('\u{10eab}', - '\u{10eac}'), ('\u{10efa}', '\u{10eff}'), ('\u{10f46}', '\u{10f50}'), ('\u{10f82}', - '\u{10f85}'), ('\u{11001}', '\u{11001}'), ('\u{11038}', '\u{11046}'), ('\u{11070}', - '\u{11070}'), ('\u{11073}', '\u{11074}'), ('\u{1107f}', '\u{11081}'), ('\u{110b3}', - '\u{110b6}'), ('\u{110b9}', '\u{110ba}'), ('\u{110c2}', '\u{110c2}'), ('\u{11100}', - '\u{11102}'), ('\u{11127}', '\u{1112b}'), ('\u{1112d}', '\u{11132}'), ('\u{11134}', - '\u{11134}'), ('\u{11173}', '\u{11173}'), ('\u{11180}', '\u{11181}'), ('\u{111b6}', - '\u{111be}'), ('\u{111c0}', '\u{111c0}'), ('\u{111c9}', '\u{111cc}'), ('\u{111cf}', - '\u{111cf}'), ('\u{1122f}', '\u{11231}'), ('\u{11234}', '\u{11237}'), ('\u{1123e}', - '\u{1123e}'), ('\u{11241}', '\u{11241}'), ('\u{112df}', '\u{112df}'), ('\u{112e3}', - '\u{112ea}'), ('\u{11300}', '\u{11301}'), ('\u{1133b}', '\u{1133c}'), ('\u{1133e}', - '\u{1133e}'), ('\u{11340}', '\u{11340}'), ('\u{1134d}', '\u{1134d}'), ('\u{11357}', - '\u{11357}'), ('\u{11366}', '\u{1136c}'), ('\u{11370}', '\u{11374}'), ('\u{113b8}', - '\u{113b8}'), ('\u{113bb}', '\u{113c0}'), ('\u{113c2}', '\u{113c2}'), ('\u{113c5}', - '\u{113c5}'), ('\u{113c7}', '\u{113c9}'), ('\u{113ce}', '\u{113cf}'), ('\u{113d2}', - '\u{113d2}'), ('\u{113e1}', '\u{113e2}'), ('\u{11438}', '\u{1143f}'), ('\u{11442}', - '\u{11444}'), ('\u{11446}', '\u{11446}'), ('\u{1145e}', '\u{1145e}'), ('\u{114b0}', - '\u{114b0}'), ('\u{114b3}', '\u{114b8}'), ('\u{114ba}', '\u{114ba}'), ('\u{114bd}', - '\u{114bd}'), ('\u{114bf}', '\u{114c0}'), ('\u{114c2}', '\u{114c3}'), ('\u{115af}', - '\u{115af}'), ('\u{115b2}', '\u{115b5}'), ('\u{115bc}', '\u{115bd}'), ('\u{115bf}', - '\u{115c0}'), ('\u{115dc}', '\u{115dd}'), ('\u{11633}', '\u{1163a}'), ('\u{1163d}', - '\u{1163d}'), ('\u{1163f}', '\u{11640}'), ('\u{116ab}', '\u{116ab}'), ('\u{116ad}', - '\u{116ad}'), ('\u{116b0}', '\u{116b7}'), ('\u{1171d}', '\u{1171d}'), ('\u{1171f}', - '\u{1171f}'), ('\u{11722}', '\u{11725}'), ('\u{11727}', '\u{1172b}'), ('\u{1182f}', - '\u{11837}'), ('\u{11839}', '\u{1183a}'), ('\u{11930}', '\u{11930}'), ('\u{1193b}', - '\u{1193d}'), ('\u{11943}', '\u{11943}'), ('\u{119d4}', '\u{119d7}'), ('\u{119da}', - '\u{119db}'), ('\u{119e0}', '\u{119e0}'), ('\u{11a01}', '\u{11a0a}'), ('\u{11a33}', - '\u{11a38}'), ('\u{11a3b}', '\u{11a3e}'), ('\u{11a51}', '\u{11a56}'), ('\u{11a59}', - '\u{11a5b}'), ('\u{11a8a}', '\u{11a96}'), ('\u{11a98}', '\u{11a98}'), ('\u{11b60}', - '\u{11b60}'), ('\u{11b62}', '\u{11b64}'), ('\u{11b66}', '\u{11b66}'), ('\u{11c30}', - '\u{11c36}'), ('\u{11c38}', '\u{11c3d}'), ('\u{11c3f}', '\u{11c3f}'), ('\u{11c92}', - '\u{11ca7}'), ('\u{11caa}', '\u{11cb0}'), ('\u{11cb2}', '\u{11cb3}'), ('\u{11cb5}', - '\u{11cb6}'), ('\u{11d31}', '\u{11d36}'), ('\u{11d3a}', '\u{11d3a}'), ('\u{11d3c}', - '\u{11d3d}'), ('\u{11d3f}', '\u{11d45}'), ('\u{11d47}', '\u{11d47}'), ('\u{11d90}', - '\u{11d91}'), ('\u{11d95}', '\u{11d95}'), ('\u{11d97}', '\u{11d97}'), ('\u{11ef3}', - '\u{11ef4}'), ('\u{11f00}', '\u{11f01}'), ('\u{11f36}', '\u{11f3a}'), ('\u{11f40}', - '\u{11f41}'), ('\u{11f5a}', '\u{11f5a}'), ('\u{13440}', '\u{13440}'), ('\u{13447}', - '\u{13455}'), ('\u{1611e}', '\u{16129}'), ('\u{1612d}', '\u{1612f}'), ('\u{16af0}', - '\u{16af4}'), ('\u{16b30}', '\u{16b36}'), ('\u{16f4f}', '\u{16f4f}'), ('\u{16f8f}', - '\u{16f92}'), ('\u{16fe4}', '\u{16fe4}'), ('\u{16ff0}', '\u{16ff1}'), ('\u{1bc9d}', - '\u{1bc9e}'), ('\u{1cf00}', '\u{1cf2d}'), ('\u{1cf30}', '\u{1cf46}'), ('\u{1d165}', - '\u{1d169}'), ('\u{1d16d}', '\u{1d172}'), ('\u{1d17b}', '\u{1d182}'), ('\u{1d185}', - '\u{1d18b}'), ('\u{1d1aa}', '\u{1d1ad}'), ('\u{1d242}', '\u{1d244}'), ('\u{1da00}', - '\u{1da36}'), ('\u{1da3b}', '\u{1da6c}'), ('\u{1da75}', '\u{1da75}'), ('\u{1da84}', - '\u{1da84}'), ('\u{1da9b}', '\u{1da9f}'), ('\u{1daa1}', '\u{1daaf}'), ('\u{1e000}', - '\u{1e006}'), ('\u{1e008}', '\u{1e018}'), ('\u{1e01b}', '\u{1e021}'), ('\u{1e023}', - '\u{1e024}'), ('\u{1e026}', '\u{1e02a}'), ('\u{1e08f}', '\u{1e08f}'), ('\u{1e130}', - '\u{1e136}'), ('\u{1e2ae}', '\u{1e2ae}'), ('\u{1e2ec}', '\u{1e2ef}'), ('\u{1e4ec}', - '\u{1e4ef}'), ('\u{1e5ee}', '\u{1e5ef}'), ('\u{1e6e3}', '\u{1e6e3}'), ('\u{1e6e6}', - '\u{1e6e6}'), ('\u{1e6ee}', '\u{1e6ef}'), ('\u{1e6f5}', '\u{1e6f5}'), ('\u{1e8d0}', - '\u{1e8d6}'), ('\u{1e944}', '\u{1e94a}'), ('\u{1f3fb}', '\u{1f3ff}'), ('\u{e0020}', - '\u{e007f}'), ('\u{e0100}', '\u{e01ef}') - ]; - - #[inline] - pub fn InCB_Extend(c: char) -> bool { - super::util::bsearch_range_table(c, InCB_Extend_table) - } - } pub fn is_incb_linker(c: char) -> bool {