[PATCH] libstdc++: Add Unicode-aware width estimation for std::format

Jonathan Wakely jwakely@redhat.com
Fri Jan 5 15:33:37 GMT 2024


On Fri, 5 Jan 2024 at 14:42, Jonathan Wakely wrote:
>
> Any comments on this approach?

One thing I expect to be unpopular is that the new Python script
doesn't generate a complete header file, just three snippets of code
that need to be pasted into the right places in <bits/unicode.h>. That
means that updating the generated tables to a new version of the
Unicode data isn't as simple as just downloading the new data files
and building a make target.

That could be addressed by adding "// BEGIN 1", "// END 1", etc.
markers into <bits/unicode.h> and using cat, sed, etc. to generate a
new <bits/unicode.h> from the snippets printed by the Pythoin script.
Or we could make it generate three separate header files and then
include those from <bits/unicode.h>. I think I'd prefer not to add
three more headers that need to be opened every time something
includes <bits/unicode.h> though.

We could also move the tables and lookup functions into libstdc++.so
(or into libstdc++exp.a for now), but that would mean they can't be
constexpr functions. They aren't needed during constant evaluation for
std::format, but it seems generally useful to be able to make them
work at compile-time.

>
> I have some ideas for implementing the full grapheme cluster break
> rules, but I think I'd like to push this for now, and fix the unusual
> edge cases later.
>
> The table of grapheme cluster properties is quite large, it might be
> possible to optimize that better. I think libc++ uses a table that only
> contains entries for the code points that don't have value "Other",
> which should reduce the size of the table (since we don't need to record
> when a range of "Other" code points starts). That could be done later as
> well, because the table is just a local variable that doesn't escape the
> function where it's used. We should probably also ensure the arrays are in
> static memory so we don't keep initializing them. ISTR some problem
> doing that for the tables in <charconv>.
>
> -- >8 --
>
> This implements the requirements in the following proposals, which
> dictate how std::format deals with non-ASCII strings:
> https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1868r1.html
> https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2572r1.html
> https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2675r1.pdf
>
> There are two parts to this. The width estimation for strings must only
> count the width of the first character in an extended grapheme cluster.
> That requires implementing the algorithm for detecting cluster breaks,
> which requires a lookup table of the grapheme cluster break properties
> of every code point. Additionally, some characters have a field width of
> 2, which requires a lookup table of field widths for every code point.
> The tables added in this commit do not contain entries for every code
> point from 0 to 0x10FFFF as that would be very inefficient and use too
> much memory. Instead the tables only contain the code points that form
> an "edge" for a property, omitting all the code points that have the
> same property as the preceding one. We can use a binary search to find
> the closest code point in the table that is not greater than the one
> we're looking for.
>
> The tables are generated by a new Python script added to the
> contrib/unicode directory, and a new data file downloaded from the
> Unicode Consortium website.
>
> The rules for extended grapheme cluster breaking are only implemented
> for an older revision of Unicode TR29. The newer rules require encoding
> some additional properties into the lookup tables, and it's no longer
> possible to decide whether to break by only comparing two adjacent
> characters. It will be necessary to preserve some additional state from
> previous characters to implement the new rules correctly. This could be
> done by defining a grapheme-cluster-view that has a state machine in its
> iterators, similar to the _Utf_view added in this commit.
>
> libstdc++-v3/ChangeLog:
>
>         * include/Makefile.am: Add new header
>         * include/Makefile.in: Regenerate.
>         * include/bits/unicode.h: New file.
>         * include/std/format: Include <bits/unicode.h>.
>         (__literal_encoding_is_utf8): Move to <bits/unicode.h>.
>         (_Spec::_M_fill): Change type to char32_t.
>         (_Spec::_M_parse_fill_and_align): Read a Unicode scalar value
>         instead of a single character.
>         (__write_padded): Change __fill_char parameter to char32_t and
>         encode it into the output.
>         (__formatter_str::format): Use new __unicode::__field_width and
>         __unicode::__truncate functions.
>         * include/std/ostream: Adjust namespace qualification for
>         __literal_encoding_is_utf8.
>         * include/std/print: Likewise.
>         * src/c++23/print.cc: Add [[unlikely]] attribute to error path.
>         * testsuite/ext/unicode/view.cc: New test.
>         * testsuite/std/format/functions/format.cc: Add missing examples
>         from the standard demonstrating alignment with non-ASCII
>         characters. Add examples checking correct handling of extended
>         grapheme clusters.
>
> contrib/ChangeLog:
>
>         * unicode/GraphemeBreakProperty.txt: New file.
>         * unicode/gen_std_format_width.py: New file.
> ---
>  contrib/unicode/GraphemeBreakProperty.txt     | 1475 +++++++++++++++++
>  contrib/unicode/gen_std_format_width.py       |  139 ++
>  libstdc++-v3/include/Makefile.am              |    1 +
>  libstdc++-v3/include/Makefile.in              |    1 +
>  libstdc++-v3/include/bits/unicode.h           | 1212 ++++++++++++++
>  libstdc++-v3/include/std/format               |  116 +-
>  libstdc++-v3/include/std/ostream              |    2 +-
>  libstdc++-v3/include/std/print                |    2 +-
>  libstdc++-v3/src/c++23/print.cc               |    2 +-
>  libstdc++-v3/testsuite/ext/unicode/view.cc    |  102 ++
>  .../testsuite/std/format/functions/format.cc  |   71 +
>  11 files changed, 3063 insertions(+), 60 deletions(-)
>  create mode 100644 contrib/unicode/GraphemeBreakProperty.txt
>  create mode 100755 contrib/unicode/gen_std_format_width.py
>  create mode 100644 libstdc++-v3/include/bits/unicode.h
>  create mode 100644 libstdc++-v3/testsuite/ext/unicode/view.cc
>
> diff --git a/contrib/unicode/GraphemeBreakProperty.txt b/contrib/unicode/GraphemeBreakProperty.txt
> new file mode 100644
> index 00000000000..12453cbdb54
> --- /dev/null
> +++ b/contrib/unicode/GraphemeBreakProperty.txt
> @@ -0,0 +1,1475 @@
> +# GraphemeBreakProperty-15.1.0.txt
> +# Date: 2023-01-05, 20:34:41 GMT
> +# © 2023 Unicode®, Inc.
> +# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
> +# For terms of use, see https://www.unicode.org/terms_of_use.html
> +#
> +# Unicode Character Database
> +#   For documentation, see https://www.unicode.org/reports/tr44/
> +
> +# ================================================
> +
> +# Property:    Grapheme_Cluster_Break
> +
> +#  All code points not explicitly listed for Grapheme_Cluster_Break
> +#  have the value Other (XX).
> +
> +# @missing: 0000..10FFFF; Other
> +
> +# ================================================
> +
> +0600..0605    ; Prepend # Cf   [6] ARABIC NUMBER SIGN..ARABIC NUMBER MARK ABOVE
> +06DD          ; Prepend # Cf       ARABIC END OF AYAH
> +070F          ; Prepend # Cf       SYRIAC ABBREVIATION MARK
> +0890..0891    ; Prepend # Cf   [2] ARABIC POUND MARK ABOVE..ARABIC PIASTRE MARK ABOVE
> +08E2          ; Prepend # Cf       ARABIC DISPUTED END OF AYAH
> +0D4E          ; Prepend # Lo       MALAYALAM LETTER DOT REPH
> +110BD         ; Prepend # Cf       KAITHI NUMBER SIGN
> +110CD         ; Prepend # Cf       KAITHI NUMBER SIGN ABOVE
> +111C2..111C3  ; Prepend # Lo   [2] SHARADA SIGN JIHVAMULIYA..SHARADA SIGN UPADHMANIYA
> +1193F         ; Prepend # Lo       DIVES AKURU PREFIXED NASAL SIGN
> +11941         ; Prepend # Lo       DIVES AKURU INITIAL RA
> +11A3A         ; Prepend # Lo       ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA
> +11A84..11A89  ; Prepend # Lo   [6] SOYOMBO SIGN JIHVAMULIYA..SOYOMBO CLUSTER-INITIAL LETTER SA
> +11D46         ; Prepend # Lo       MASARAM GONDI REPHA
> +11F02         ; Prepend # Lo       KAWI SIGN REPHA
> +
> +# Total code points: 27
> +
> +# ================================================
> +
> +000D          ; CR # Cc       <control-000D>
> +
> +# Total code points: 1
> +
> +# ================================================
> +
> +000A          ; LF # Cc       <control-000A>
> +
> +# Total code points: 1
> +
> +# ================================================
> +
> +0000..0009    ; Control # Cc  [10] <control-0000>..<control-0009>
> +000B..000C    ; Control # Cc   [2] <control-000B>..<control-000C>
> +000E..001F    ; Control # Cc  [18] <control-000E>..<control-001F>
> +007F..009F    ; Control # Cc  [33] <control-007F>..<control-009F>
> +00AD          ; Control # Cf       SOFT HYPHEN
> +061C          ; Control # Cf       ARABIC LETTER MARK
> +180E          ; Control # Cf       MONGOLIAN VOWEL SEPARATOR
> +200B          ; Control # Cf       ZERO WIDTH SPACE
> +200E..200F    ; Control # Cf   [2] LEFT-TO-RIGHT MARK..RIGHT-TO-LEFT MARK
> +2028          ; Control # Zl       LINE SEPARATOR
> +2029          ; Control # Zp       PARAGRAPH SEPARATOR
> +202A..202E    ; Control # Cf   [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE
> +2060..2064    ; Control # Cf   [5] WORD JOINER..INVISIBLE PLUS
> +2065          ; Control # Cn       <reserved-2065>
> +2066..206F    ; Control # Cf  [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES
> +FEFF          ; Control # Cf       ZERO WIDTH NO-BREAK SPACE
> +FFF0..FFF8    ; Control # Cn   [9] <reserved-FFF0>..<reserved-FFF8>
> +FFF9..FFFB    ; Control # Cf   [3] INTERLINEAR ANNOTATION ANCHOR..INTERLINEAR ANNOTATION TERMINATOR
> +13430..1343F  ; Control # Cf  [16] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH END WALLED ENCLOSURE
> +1BCA0..1BCA3  ; Control # Cf   [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP
> +1D173..1D17A  ; Control # Cf   [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE
> +E0000         ; Control # Cn       <reserved-E0000>
> +E0001         ; Control # Cf       LANGUAGE TAG
> +E0002..E001F  ; Control # Cn  [30] <reserved-E0002>..<reserved-E001F>
> +E0080..E00FF  ; Control # Cn [128] <reserved-E0080>..<reserved-E00FF>
> +E01F0..E0FFF  ; Control # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
> +
> +# Total code points: 3893
> +
> +# ================================================
> +
> +0300..036F    ; Extend # Mn [112] COMBINING GRAVE ACCENT..COMBINING LATIN SMALL LETTER X
> +0483..0487    ; Extend # Mn   [5] COMBINING CYRILLIC TITLO..COMBINING CYRILLIC POKRYTIE
> +0488..0489    ; Extend # Me   [2] COMBINING CYRILLIC HUNDRED THOUSANDS SIGN..COMBINING CYRILLIC MILLIONS SIGN
> +0591..05BD    ; Extend # Mn  [45] HEBREW ACCENT ETNAHTA..HEBREW POINT METEG
> +05BF          ; Extend # Mn       HEBREW POINT RAFE
> +05C1..05C2    ; Extend # Mn   [2] HEBREW POINT SHIN DOT..HEBREW POINT SIN DOT
> +05C4..05C5    ; Extend # Mn   [2] HEBREW MARK UPPER DOT..HEBREW MARK LOWER DOT
> +05C7          ; Extend # Mn       HEBREW POINT QAMATS QATAN
> +0610..061A    ; Extend # Mn  [11] ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL KASRA
> +064B..065F    ; Extend # Mn  [21] ARABIC FATHATAN..ARABIC WAVY HAMZA BELOW
> +0670          ; Extend # Mn       ARABIC LETTER SUPERSCRIPT ALEF
> +06D6..06DC    ; Extend # Mn   [7] ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA..ARABIC SMALL HIGH SEEN
> +06DF..06E4    ; Extend # Mn   [6] ARABIC SMALL HIGH ROUNDED ZERO..ARABIC SMALL HIGH MADDA
> +06E7..06E8    ; Extend # Mn   [2] ARABIC SMALL HIGH YEH..ARABIC SMALL HIGH NOON
> +06EA..06ED    ; Extend # Mn   [4] ARABIC EMPTY CENTRE LOW STOP..ARABIC SMALL LOW MEEM
> +0711          ; Extend # Mn       SYRIAC LETTER SUPERSCRIPT ALAPH
> +0730..074A    ; Extend # Mn  [27] SYRIAC PTHAHA ABOVE..SYRIAC BARREKH
> +07A6..07B0    ; Extend # Mn  [11] THAANA ABAFILI..THAANA SUKUN
> +07EB..07F3    ; Extend # Mn   [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE
> +07FD          ; Extend # Mn       NKO DANTAYALAN
> +0816..0819    ; Extend # Mn   [4] SAMARITAN MARK IN..SAMARITAN MARK DAGESH
> +081B..0823    ; Extend # Mn   [9] SAMARITAN MARK EPENTHETIC YUT..SAMARITAN VOWEL SIGN A
> +0825..0827    ; Extend # Mn   [3] SAMARITAN VOWEL SIGN SHORT A..SAMARITAN VOWEL SIGN U
> +0829..082D    ; Extend # Mn   [5] SAMARITAN VOWEL SIGN LONG I..SAMARITAN MARK NEQUDAA
> +0859..085B    ; Extend # Mn   [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK
> +0898..089F    ; Extend # Mn   [8] ARABIC SMALL HIGH WORD AL-JUZ..ARABIC HALF MADDA OVER MADDA
> +08CA..08E1    ; Extend # Mn  [24] ARABIC SMALL HIGH FARSI YEH..ARABIC SMALL HIGH SIGN SAFHA
> +08E3..0902    ; Extend # Mn  [32] ARABIC TURNED DAMMA BELOW..DEVANAGARI SIGN ANUSVARA
> +093A          ; Extend # Mn       DEVANAGARI VOWEL SIGN OE
> +093C          ; Extend # Mn       DEVANAGARI SIGN NUKTA
> +0941..0948    ; Extend # Mn   [8] DEVANAGARI VOWEL SIGN U..DEVANAGARI VOWEL SIGN AI
> +094D          ; Extend # Mn       DEVANAGARI SIGN VIRAMA
> +0951..0957    ; Extend # Mn   [7] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI VOWEL SIGN UUE
> +0962..0963    ; Extend # Mn   [2] DEVANAGARI VOWEL SIGN VOCALIC L..DEVANAGARI VOWEL SIGN VOCALIC LL
> +0981          ; Extend # Mn       BENGALI SIGN CANDRABINDU
> +09BC          ; Extend # Mn       BENGALI SIGN NUKTA
> +09BE          ; Extend # Mc       BENGALI VOWEL SIGN AA
> +09C1..09C4    ; Extend # Mn   [4] BENGALI VOWEL SIGN U..BENGALI VOWEL SIGN VOCALIC RR
> +09CD          ; Extend # Mn       BENGALI SIGN VIRAMA
> +09D7          ; Extend # Mc       BENGALI AU LENGTH MARK
> +09E2..09E3    ; Extend # Mn   [2] BENGALI VOWEL SIGN VOCALIC L..BENGALI VOWEL SIGN VOCALIC LL
> +09FE          ; Extend # Mn       BENGALI SANDHI MARK
> +0A01..0A02    ; Extend # Mn   [2] GURMUKHI SIGN ADAK BINDI..GURMUKHI SIGN BINDI
> +0A3C          ; Extend # Mn       GURMUKHI SIGN NUKTA
> +0A41..0A42    ; Extend # Mn   [2] GURMUKHI VOWEL SIGN U..GURMUKHI VOWEL SIGN UU
> +0A47..0A48    ; Extend # Mn   [2] GURMUKHI VOWEL SIGN EE..GURMUKHI VOWEL SIGN AI
> +0A4B..0A4D    ; Extend # Mn   [3] GURMUKHI VOWEL SIGN OO..GURMUKHI SIGN VIRAMA
> +0A51          ; Extend # Mn       GURMUKHI SIGN UDAAT
> +0A70..0A71    ; Extend # Mn   [2] GURMUKHI TIPPI..GURMUKHI ADDAK
> +0A75          ; Extend # Mn       GURMUKHI SIGN YAKASH
> +0A81..0A82    ; Extend # Mn   [2] GUJARATI SIGN CANDRABINDU..GUJARATI SIGN ANUSVARA
> +0ABC          ; Extend # Mn       GUJARATI SIGN NUKTA
> +0AC1..0AC5    ; Extend # Mn   [5] GUJARATI VOWEL SIGN U..GUJARATI VOWEL SIGN CANDRA E
> +0AC7..0AC8    ; Extend # Mn   [2] GUJARATI VOWEL SIGN E..GUJARATI VOWEL SIGN AI
> +0ACD          ; Extend # Mn       GUJARATI SIGN VIRAMA
> +0AE2..0AE3    ; Extend # Mn   [2] GUJARATI VOWEL SIGN VOCALIC L..GUJARATI VOWEL SIGN VOCALIC LL
> +0AFA..0AFF    ; Extend # Mn   [6] GUJARATI SIGN SUKUN..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE
> +0B01          ; Extend # Mn       ORIYA SIGN CANDRABINDU
> +0B3C          ; Extend # Mn       ORIYA SIGN NUKTA
> +0B3E          ; Extend # Mc       ORIYA VOWEL SIGN AA
> +0B3F          ; Extend # Mn       ORIYA VOWEL SIGN I
> +0B41..0B44    ; Extend # Mn   [4] ORIYA VOWEL SIGN U..ORIYA VOWEL SIGN VOCALIC RR
> +0B4D          ; Extend # Mn       ORIYA SIGN VIRAMA
> +0B55..0B56    ; Extend # Mn   [2] ORIYA SIGN OVERLINE..ORIYA AI LENGTH MARK
> +0B57          ; Extend # Mc       ORIYA AU LENGTH MARK
> +0B62..0B63    ; Extend # Mn   [2] ORIYA VOWEL SIGN VOCALIC L..ORIYA VOWEL SIGN VOCALIC LL
> +0B82          ; Extend # Mn       TAMIL SIGN ANUSVARA
> +0BBE          ; Extend # Mc       TAMIL VOWEL SIGN AA
> +0BC0          ; Extend # Mn       TAMIL VOWEL SIGN II
> +0BCD          ; Extend # Mn       TAMIL SIGN VIRAMA
> +0BD7          ; Extend # Mc       TAMIL AU LENGTH MARK
> +0C00          ; Extend # Mn       TELUGU SIGN COMBINING CANDRABINDU ABOVE
> +0C04          ; Extend # Mn       TELUGU SIGN COMBINING ANUSVARA ABOVE
> +0C3C          ; Extend # Mn       TELUGU SIGN NUKTA
> +0C3E..0C40    ; Extend # Mn   [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN II
> +0C46..0C48    ; Extend # Mn   [3] TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI
> +0C4A..0C4D    ; Extend # Mn   [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA
> +0C55..0C56    ; Extend # Mn   [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK
> +0C62..0C63    ; Extend # Mn   [2] TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL
> +0C81          ; Extend # Mn       KANNADA SIGN CANDRABINDU
> +0CBC          ; Extend # Mn       KANNADA SIGN NUKTA
> +0CBF          ; Extend # Mn       KANNADA VOWEL SIGN I
> +0CC2          ; Extend # Mc       KANNADA VOWEL SIGN UU
> +0CC6          ; Extend # Mn       KANNADA VOWEL SIGN E
> +0CCC..0CCD    ; Extend # Mn   [2] KANNADA VOWEL SIGN AU..KANNADA SIGN VIRAMA
> +0CD5..0CD6    ; Extend # Mc   [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK
> +0CE2..0CE3    ; Extend # Mn   [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL
> +0D00..0D01    ; Extend # Mn   [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU
> +0D3B..0D3C    ; Extend # Mn   [2] MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA
> +0D3E          ; Extend # Mc       MALAYALAM VOWEL SIGN AA
> +0D41..0D44    ; Extend # Mn   [4] MALAYALAM VOWEL SIGN U..MALAYALAM VOWEL SIGN VOCALIC RR
> +0D4D          ; Extend # Mn       MALAYALAM SIGN VIRAMA
> +0D57          ; Extend # Mc       MALAYALAM AU LENGTH MARK
> +0D62..0D63    ; Extend # Mn   [2] MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL
> +0D81          ; Extend # Mn       SINHALA SIGN CANDRABINDU
> +0DCA          ; Extend # Mn       SINHALA SIGN AL-LAKUNA
> +0DCF          ; Extend # Mc       SINHALA VOWEL SIGN AELA-PILLA
> +0DD2..0DD4    ; Extend # Mn   [3] SINHALA VOWEL SIGN KETTI IS-PILLA..SINHALA VOWEL SIGN KETTI PAA-PILLA
> +0DD6          ; Extend # Mn       SINHALA VOWEL SIGN DIGA PAA-PILLA
> +0DDF          ; Extend # Mc       SINHALA VOWEL SIGN GAYANUKITTA
> +0E31          ; Extend # Mn       THAI CHARACTER MAI HAN-AKAT
> +0E34..0E3A    ; Extend # Mn   [7] THAI CHARACTER SARA I..THAI CHARACTER PHINTHU
> +0E47..0E4E    ; Extend # Mn   [8] THAI CHARACTER MAITAIKHU..THAI CHARACTER YAMAKKAN
> +0EB1          ; Extend # Mn       LAO VOWEL SIGN MAI KAN
> +0EB4..0EBC    ; Extend # Mn   [9] LAO VOWEL SIGN I..LAO SEMIVOWEL SIGN LO
> +0EC8..0ECE    ; Extend # Mn   [7] LAO TONE MAI EK..LAO YAMAKKAN
> +0F18..0F19    ; Extend # Mn   [2] TIBETAN ASTROLOGICAL SIGN -KHYUD PA..TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS
> +0F35          ; Extend # Mn       TIBETAN MARK NGAS BZUNG NYI ZLA
> +0F37          ; Extend # Mn       TIBETAN MARK NGAS BZUNG SGOR RTAGS
> +0F39          ; Extend # Mn       TIBETAN MARK TSA -PHRU
> +0F71..0F7E    ; Extend # Mn  [14] TIBETAN VOWEL SIGN AA..TIBETAN SIGN RJES SU NGA RO
> +0F80..0F84    ; Extend # Mn   [5] TIBETAN VOWEL SIGN REVERSED I..TIBETAN MARK HALANTA
> +0F86..0F87    ; Extend # Mn   [2] TIBETAN SIGN LCI RTAGS..TIBETAN SIGN YANG RTAGS
> +0F8D..0F97    ; Extend # Mn  [11] TIBETAN SUBJOINED SIGN LCE TSA CAN..TIBETAN SUBJOINED LETTER JA
> +0F99..0FBC    ; Extend # Mn  [36] TIBETAN SUBJOINED LETTER NYA..TIBETAN SUBJOINED LETTER FIXED-FORM RA
> +0FC6          ; Extend # Mn       TIBETAN SYMBOL PADMA GDAN
> +102D..1030    ; Extend # Mn   [4] MYANMAR VOWEL SIGN I..MYANMAR VOWEL SIGN UU
> +1032..1037    ; Extend # Mn   [6] MYANMAR VOWEL SIGN AI..MYANMAR SIGN DOT BELOW
> +1039..103A    ; Extend # Mn   [2] MYANMAR SIGN VIRAMA..MYANMAR SIGN ASAT
> +103D..103E    ; Extend # Mn   [2] MYANMAR CONSONANT SIGN MEDIAL WA..MYANMAR CONSONANT SIGN MEDIAL HA
> +1058..1059    ; Extend # Mn   [2] MYANMAR VOWEL SIGN VOCALIC L..MYANMAR VOWEL SIGN VOCALIC LL
> +105E..1060    ; Extend # Mn   [3] MYANMAR CONSONANT SIGN MON MEDIAL NA..MYANMAR CONSONANT SIGN MON MEDIAL LA
> +1071..1074    ; Extend # Mn   [4] MYANMAR VOWEL SIGN GEBA KAREN I..MYANMAR VOWEL SIGN KAYAH EE
> +1082          ; Extend # Mn       MYANMAR CONSONANT SIGN SHAN MEDIAL WA
> +1085..1086    ; Extend # Mn   [2] MYANMAR VOWEL SIGN SHAN E ABOVE..MYANMAR VOWEL SIGN SHAN FINAL Y
> +108D          ; Extend # Mn       MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE
> +109D          ; Extend # Mn       MYANMAR VOWEL SIGN AITON AI
> +135D..135F    ; Extend # Mn   [3] ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING GEMINATION MARK
> +1712..1714    ; Extend # Mn   [3] TAGALOG VOWEL SIGN I..TAGALOG SIGN VIRAMA
> +1732..1733    ; Extend # Mn   [2] HANUNOO VOWEL SIGN I..HANUNOO VOWEL SIGN U
> +1752..1753    ; Extend # Mn   [2] BUHID VOWEL SIGN I..BUHID VOWEL SIGN U
> +1772..1773    ; Extend # Mn   [2] TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U
> +17B4..17B5    ; Extend # Mn   [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
> +17B7..17BD    ; Extend # Mn   [7] KHMER VOWEL SIGN I..KHMER VOWEL SIGN UA
> +17C6          ; Extend # Mn       KHMER SIGN NIKAHIT
> +17C9..17D3    ; Extend # Mn  [11] KHMER SIGN MUUSIKATOAN..KHMER SIGN BATHAMASAT
> +17DD          ; Extend # Mn       KHMER SIGN ATTHACAN
> +180B..180D    ; Extend # Mn   [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
> +180F          ; Extend # Mn       MONGOLIAN FREE VARIATION SELECTOR FOUR
> +1885..1886    ; Extend # Mn   [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA
> +18A9          ; Extend # Mn       MONGOLIAN LETTER ALI GALI DAGALGA
> +1920..1922    ; Extend # Mn   [3] LIMBU VOWEL SIGN A..LIMBU VOWEL SIGN U
> +1927..1928    ; Extend # Mn   [2] LIMBU VOWEL SIGN E..LIMBU VOWEL SIGN O
> +1932          ; Extend # Mn       LIMBU SMALL LETTER ANUSVARA
> +1939..193B    ; Extend # Mn   [3] LIMBU SIGN MUKPHRENG..LIMBU SIGN SA-I
> +1A17..1A18    ; Extend # Mn   [2] BUGINESE VOWEL SIGN I..BUGINESE VOWEL SIGN U
> +1A1B          ; Extend # Mn       BUGINESE VOWEL SIGN AE
> +1A56          ; Extend # Mn       TAI THAM CONSONANT SIGN MEDIAL LA
> +1A58..1A5E    ; Extend # Mn   [7] TAI THAM SIGN MAI KANG LAI..TAI THAM CONSONANT SIGN SA
> +1A60          ; Extend # Mn       TAI THAM SIGN SAKOT
> +1A62          ; Extend # Mn       TAI THAM VOWEL SIGN MAI SAT
> +1A65..1A6C    ; Extend # Mn   [8] TAI THAM VOWEL SIGN I..TAI THAM VOWEL SIGN OA BELOW
> +1A73..1A7C    ; Extend # Mn  [10] TAI THAM VOWEL SIGN OA ABOVE..TAI THAM SIGN KHUEN-LUE KARAN
> +1A7F          ; Extend # Mn       TAI THAM COMBINING CRYPTOGRAMMIC DOT
> +1AB0..1ABD    ; Extend # Mn  [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW
> +1ABE          ; Extend # Me       COMBINING PARENTHESES OVERLAY
> +1ABF..1ACE    ; Extend # Mn  [16] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER INSULAR T
> +1B00..1B03    ; Extend # Mn   [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG
> +1B34          ; Extend # Mn       BALINESE SIGN REREKAN
> +1B35          ; Extend # Mc       BALINESE VOWEL SIGN TEDUNG
> +1B36..1B3A    ; Extend # Mn   [5] BALINESE VOWEL SIGN ULU..BALINESE VOWEL SIGN RA REPA
> +1B3C          ; Extend # Mn       BALINESE VOWEL SIGN LA LENGA
> +1B42          ; Extend # Mn       BALINESE VOWEL SIGN PEPET
> +1B6B..1B73    ; Extend # Mn   [9] BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG
> +1B80..1B81    ; Extend # Mn   [2] SUNDANESE SIGN PANYECEK..SUNDANESE SIGN PANGLAYAR
> +1BA2..1BA5    ; Extend # Mn   [4] SUNDANESE CONSONANT SIGN PANYAKRA..SUNDANESE VOWEL SIGN PANYUKU
> +1BA8..1BA9    ; Extend # Mn   [2] SUNDANESE VOWEL SIGN PAMEPET..SUNDANESE VOWEL SIGN PANEULEUNG
> +1BAB..1BAD    ; Extend # Mn   [3] SUNDANESE SIGN VIRAMA..SUNDANESE CONSONANT SIGN PASANGAN WA
> +1BE6          ; Extend # Mn       BATAK SIGN TOMPI
> +1BE8..1BE9    ; Extend # Mn   [2] BATAK VOWEL SIGN PAKPAK E..BATAK VOWEL SIGN EE
> +1BED          ; Extend # Mn       BATAK VOWEL SIGN KARO O
> +1BEF..1BF1    ; Extend # Mn   [3] BATAK VOWEL SIGN U FOR SIMALUNGUN SA..BATAK CONSONANT SIGN H
> +1C2C..1C33    ; Extend # Mn   [8] LEPCHA VOWEL SIGN E..LEPCHA CONSONANT SIGN T
> +1C36..1C37    ; Extend # Mn   [2] LEPCHA SIGN RAN..LEPCHA SIGN NUKTA
> +1CD0..1CD2    ; Extend # Mn   [3] VEDIC TONE KARSHANA..VEDIC TONE PRENKHA
> +1CD4..1CE0    ; Extend # Mn  [13] VEDIC SIGN YAJURVEDIC MIDLINE SVARITA..VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA
> +1CE2..1CE8    ; Extend # Mn   [7] VEDIC SIGN VISARGA SVARITA..VEDIC SIGN VISARGA ANUDATTA WITH TAIL
> +1CED          ; Extend # Mn       VEDIC SIGN TIRYAK
> +1CF4          ; Extend # Mn       VEDIC TONE CANDRA ABOVE
> +1CF8..1CF9    ; Extend # Mn   [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE
> +1DC0..1DFF    ; Extend # Mn  [64] COMBINING DOTTED GRAVE ACCENT..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW
> +200C          ; Extend # Cf       ZERO WIDTH NON-JOINER
> +20D0..20DC    ; Extend # Mn  [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE
> +20DD..20E0    ; Extend # Me   [4] COMBINING ENCLOSING CIRCLE..COMBINING ENCLOSING CIRCLE BACKSLASH
> +20E1          ; Extend # Mn       COMBINING LEFT RIGHT ARROW ABOVE
> +20E2..20E4    ; Extend # Me   [3] COMBINING ENCLOSING SCREEN..COMBINING ENCLOSING UPWARD POINTING TRIANGLE
> +20E5..20F0    ; Extend # Mn  [12] COMBINING REVERSE SOLIDUS OVERLAY..COMBINING ASTERISK ABOVE
> +2CEF..2CF1    ; Extend # Mn   [3] COPTIC COMBINING NI ABOVE..COPTIC COMBINING SPIRITUS LENIS
> +2D7F          ; Extend # Mn       TIFINAGH CONSONANT JOINER
> +2DE0..2DFF    ; Extend # Mn  [32] COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS
> +302A..302D    ; Extend # Mn   [4] IDEOGRAPHIC LEVEL TONE MARK..IDEOGRAPHIC ENTERING TONE MARK
> +302E..302F    ; Extend # Mc   [2] HANGUL SINGLE DOT TONE MARK..HANGUL DOUBLE DOT TONE MARK
> +3099..309A    ; Extend # Mn   [2] COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK..COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
> +A66F          ; Extend # Mn       COMBINING CYRILLIC VZMET
> +A670..A672    ; Extend # Me   [3] COMBINING CYRILLIC TEN MILLIONS SIGN..COMBINING CYRILLIC THOUSAND MILLIONS SIGN
> +A674..A67D    ; Extend # Mn  [10] COMBINING CYRILLIC LETTER UKRAINIAN IE..COMBINING CYRILLIC PAYEROK
> +A69E..A69F    ; Extend # Mn   [2] COMBINING CYRILLIC LETTER EF..COMBINING CYRILLIC LETTER IOTIFIED E
> +A6F0..A6F1    ; Extend # Mn   [2] BAMUM COMBINING MARK KOQNDON..BAMUM COMBINING MARK TUKWENTIS
> +A802          ; Extend # Mn       SYLOTI NAGRI SIGN DVISVARA
> +A806          ; Extend # Mn       SYLOTI NAGRI SIGN HASANTA
> +A80B          ; Extend # Mn       SYLOTI NAGRI SIGN ANUSVARA
> +A825..A826    ; Extend # Mn   [2] SYLOTI NAGRI VOWEL SIGN U..SYLOTI NAGRI VOWEL SIGN E
> +A82C          ; Extend # Mn       SYLOTI NAGRI SIGN ALTERNATE HASANTA
> +A8C4..A8C5    ; Extend # Mn   [2] SAURASHTRA SIGN VIRAMA..SAURASHTRA SIGN CANDRABINDU
> +A8E0..A8F1    ; Extend # Mn  [18] COMBINING DEVANAGARI DIGIT ZERO..COMBINING DEVANAGARI SIGN AVAGRAHA
> +A8FF          ; Extend # Mn       DEVANAGARI VOWEL SIGN AY
> +A926..A92D    ; Extend # Mn   [8] KAYAH LI VOWEL UE..KAYAH LI TONE CALYA PLOPHU
> +A947..A951    ; Extend # Mn  [11] REJANG VOWEL SIGN I..REJANG CONSONANT SIGN R
> +A980..A982    ; Extend # Mn   [3] JAVANESE SIGN PANYANGGA..JAVANESE SIGN LAYAR
> +A9B3          ; Extend # Mn       JAVANESE SIGN CECAK TELU
> +A9B6..A9B9    ; Extend # Mn   [4] JAVANESE VOWEL SIGN WULU..JAVANESE VOWEL SIGN SUKU MENDUT
> +A9BC..A9BD    ; Extend # Mn   [2] JAVANESE VOWEL SIGN PEPET..JAVANESE CONSONANT SIGN KERET
> +A9E5          ; Extend # Mn       MYANMAR SIGN SHAN SAW
> +AA29..AA2E    ; Extend # Mn   [6] CHAM VOWEL SIGN AA..CHAM VOWEL SIGN OE
> +AA31..AA32    ; Extend # Mn   [2] CHAM VOWEL SIGN AU..CHAM VOWEL SIGN UE
> +AA35..AA36    ; Extend # Mn   [2] CHAM CONSONANT SIGN LA..CHAM CONSONANT SIGN WA
> +AA43          ; Extend # Mn       CHAM CONSONANT SIGN FINAL NG
> +AA4C          ; Extend # Mn       CHAM CONSONANT SIGN FINAL M
> +AA7C          ; Extend # Mn       MYANMAR SIGN TAI LAING TONE-2
> +AAB0          ; Extend # Mn       TAI VIET MAI KANG
> +AAB2..AAB4    ; Extend # Mn   [3] TAI VIET VOWEL I..TAI VIET VOWEL U
> +AAB7..AAB8    ; Extend # Mn   [2] TAI VIET MAI KHIT..TAI VIET VOWEL IA
> +AABE..AABF    ; Extend # Mn   [2] TAI VIET VOWEL AM..TAI VIET TONE MAI EK
> +AAC1          ; Extend # Mn       TAI VIET TONE MAI THO
> +AAEC..AAED    ; Extend # Mn   [2] MEETEI MAYEK VOWEL SIGN UU..MEETEI MAYEK VOWEL SIGN AAI
> +AAF6          ; Extend # Mn       MEETEI MAYEK VIRAMA
> +ABE5          ; Extend # Mn       MEETEI MAYEK VOWEL SIGN ANAP
> +ABE8          ; Extend # Mn       MEETEI MAYEK VOWEL SIGN UNAP
> +ABED          ; Extend # Mn       MEETEI MAYEK APUN IYEK
> +FB1E          ; Extend # Mn       HEBREW POINT JUDEO-SPANISH VARIKA
> +FE00..FE0F    ; Extend # Mn  [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16
> +FE20..FE2F    ; Extend # Mn  [16] COMBINING LIGATURE LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF
> +FF9E..FF9F    ; Extend # Lm   [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
> +101FD         ; Extend # Mn       PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE
> +102E0         ; Extend # Mn       COPTIC EPACT THOUSANDS MARK
> +10376..1037A  ; Extend # Mn   [5] COMBINING OLD PERMIC LETTER AN..COMBINING OLD PERMIC LETTER SII
> +10A01..10A03  ; Extend # Mn   [3] KHAROSHTHI VOWEL SIGN I..KHAROSHTHI VOWEL SIGN VOCALIC R
> +10A05..10A06  ; Extend # Mn   [2] KHAROSHTHI VOWEL SIGN E..KHAROSHTHI VOWEL SIGN O
> +10A0C..10A0F  ; Extend # Mn   [4] KHAROSHTHI VOWEL LENGTH MARK..KHAROSHTHI SIGN VISARGA
> +10A38..10A3A  ; Extend # Mn   [3] KHAROSHTHI SIGN BAR ABOVE..KHAROSHTHI SIGN DOT BELOW
> +10A3F         ; Extend # Mn       KHAROSHTHI VIRAMA
> +10AE5..10AE6  ; Extend # Mn   [2] MANICHAEAN ABBREVIATION MARK ABOVE..MANICHAEAN ABBREVIATION MARK BELOW
> +10D24..10D27  ; Extend # Mn   [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI
> +10EAB..10EAC  ; Extend # Mn   [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK
> +10EFD..10EFF  ; Extend # Mn   [3] ARABIC SMALL LOW WORD SAKTA..ARABIC SMALL LOW WORD MADDA
> +10F46..10F50  ; Extend # Mn  [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW
> +10F82..10F85  ; Extend # Mn   [4] OLD UYGHUR COMBINING DOT ABOVE..OLD UYGHUR COMBINING TWO DOTS BELOW
> +11001         ; Extend # Mn       BRAHMI SIGN ANUSVARA
> +11038..11046  ; Extend # Mn  [15] BRAHMI VOWEL SIGN AA..BRAHMI VIRAMA
> +11070         ; Extend # Mn       BRAHMI SIGN OLD TAMIL VIRAMA
> +11073..11074  ; Extend # Mn   [2] BRAHMI VOWEL SIGN OLD TAMIL SHORT E..BRAHMI VOWEL SIGN OLD TAMIL SHORT O
> +1107F..11081  ; Extend # Mn   [3] BRAHMI NUMBER JOINER..KAITHI SIGN ANUSVARA
> +110B3..110B6  ; Extend # Mn   [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI
> +110B9..110BA  ; Extend # Mn   [2] KAITHI SIGN VIRAMA..KAITHI SIGN NUKTA
> +110C2         ; Extend # Mn       KAITHI VOWEL SIGN VOCALIC R
> +11100..11102  ; Extend # Mn   [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA
> +11127..1112B  ; Extend # Mn   [5] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN UU
> +1112D..11134  ; Extend # Mn   [8] CHAKMA VOWEL SIGN AI..CHAKMA MAAYYAA
> +11173         ; Extend # Mn       MAHAJANI SIGN NUKTA
> +11180..11181  ; Extend # Mn   [2] SHARADA SIGN CANDRABINDU..SHARADA SIGN ANUSVARA
> +111B6..111BE  ; Extend # Mn   [9] SHARADA VOWEL SIGN U..SHARADA VOWEL SIGN O
> +111C9..111CC  ; Extend # Mn   [4] SHARADA SANDHI MARK..SHARADA EXTRA SHORT VOWEL MARK
> +111CF         ; Extend # Mn       SHARADA SIGN INVERTED CANDRABINDU
> +1122F..11231  ; Extend # Mn   [3] KHOJKI VOWEL SIGN U..KHOJKI VOWEL SIGN AI
> +11234         ; Extend # Mn       KHOJKI SIGN ANUSVARA
> +11236..11237  ; Extend # Mn   [2] KHOJKI SIGN NUKTA..KHOJKI SIGN SHADDA
> +1123E         ; Extend # Mn       KHOJKI SIGN SUKUN
> +11241         ; Extend # Mn       KHOJKI VOWEL SIGN VOCALIC R
> +112DF         ; Extend # Mn       KHUDAWADI SIGN ANUSVARA
> +112E3..112EA  ; Extend # Mn   [8] KHUDAWADI VOWEL SIGN U..KHUDAWADI SIGN VIRAMA
> +11300..11301  ; Extend # Mn   [2] GRANTHA SIGN COMBINING ANUSVARA ABOVE..GRANTHA SIGN CANDRABINDU
> +1133B..1133C  ; Extend # Mn   [2] COMBINING BINDU BELOW..GRANTHA SIGN NUKTA
> +1133E         ; Extend # Mc       GRANTHA VOWEL SIGN AA
> +11340         ; Extend # Mn       GRANTHA VOWEL SIGN II
> +11357         ; Extend # Mc       GRANTHA AU LENGTH MARK
> +11366..1136C  ; Extend # Mn   [7] COMBINING GRANTHA DIGIT ZERO..COMBINING GRANTHA DIGIT SIX
> +11370..11374  ; Extend # Mn   [5] COMBINING GRANTHA LETTER A..COMBINING GRANTHA LETTER PA
> +11438..1143F  ; Extend # Mn   [8] NEWA VOWEL SIGN U..NEWA VOWEL SIGN AI
> +11442..11444  ; Extend # Mn   [3] NEWA SIGN VIRAMA..NEWA SIGN ANUSVARA
> +11446         ; Extend # Mn       NEWA SIGN NUKTA
> +1145E         ; Extend # Mn       NEWA SANDHI MARK
> +114B0         ; Extend # Mc       TIRHUTA VOWEL SIGN AA
> +114B3..114B8  ; Extend # Mn   [6] TIRHUTA VOWEL SIGN U..TIRHUTA VOWEL SIGN VOCALIC LL
> +114BA         ; Extend # Mn       TIRHUTA VOWEL SIGN SHORT E
> +114BD         ; Extend # Mc       TIRHUTA VOWEL SIGN SHORT O
> +114BF..114C0  ; Extend # Mn   [2] TIRHUTA SIGN CANDRABINDU..TIRHUTA SIGN ANUSVARA
> +114C2..114C3  ; Extend # Mn   [2] TIRHUTA SIGN VIRAMA..TIRHUTA SIGN NUKTA
> +115AF         ; Extend # Mc       SIDDHAM VOWEL SIGN AA
> +115B2..115B5  ; Extend # Mn   [4] SIDDHAM VOWEL SIGN U..SIDDHAM VOWEL SIGN VOCALIC RR
> +115BC..115BD  ; Extend # Mn   [2] SIDDHAM SIGN CANDRABINDU..SIDDHAM SIGN ANUSVARA
> +115BF..115C0  ; Extend # Mn   [2] SIDDHAM SIGN VIRAMA..SIDDHAM SIGN NUKTA
> +115DC..115DD  ; Extend # Mn   [2] SIDDHAM VOWEL SIGN ALTERNATE U..SIDDHAM VOWEL SIGN ALTERNATE UU
> +11633..1163A  ; Extend # Mn   [8] MODI VOWEL SIGN U..MODI VOWEL SIGN AI
> +1163D         ; Extend # Mn       MODI SIGN ANUSVARA
> +1163F..11640  ; Extend # Mn   [2] MODI SIGN VIRAMA..MODI SIGN ARDHACANDRA
> +116AB         ; Extend # Mn       TAKRI SIGN ANUSVARA
> +116AD         ; Extend # Mn       TAKRI VOWEL SIGN AA
> +116B0..116B5  ; Extend # Mn   [6] TAKRI VOWEL SIGN U..TAKRI VOWEL SIGN AU
> +116B7         ; Extend # Mn       TAKRI SIGN NUKTA
> +1171D..1171F  ; Extend # Mn   [3] AHOM CONSONANT SIGN MEDIAL LA..AHOM CONSONANT SIGN MEDIAL LIGATING RA
> +11722..11725  ; Extend # Mn   [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU
> +11727..1172B  ; Extend # Mn   [5] AHOM VOWEL SIGN AW..AHOM SIGN KILLER
> +1182F..11837  ; Extend # Mn   [9] DOGRA VOWEL SIGN U..DOGRA SIGN ANUSVARA
> +11839..1183A  ; Extend # Mn   [2] DOGRA SIGN VIRAMA..DOGRA SIGN NUKTA
> +11930         ; Extend # Mc       DIVES AKURU VOWEL SIGN AA
> +1193B..1193C  ; Extend # Mn   [2] DIVES AKURU SIGN ANUSVARA..DIVES AKURU SIGN CANDRABINDU
> +1193E         ; Extend # Mn       DIVES AKURU VIRAMA
> +11943         ; Extend # Mn       DIVES AKURU SIGN NUKTA
> +119D4..119D7  ; Extend # Mn   [4] NANDINAGARI VOWEL SIGN U..NANDINAGARI VOWEL SIGN VOCALIC RR
> +119DA..119DB  ; Extend # Mn   [2] NANDINAGARI VOWEL SIGN E..NANDINAGARI VOWEL SIGN AI
> +119E0         ; Extend # Mn       NANDINAGARI SIGN VIRAMA
> +11A01..11A0A  ; Extend # Mn  [10] ZANABAZAR SQUARE VOWEL SIGN I..ZANABAZAR SQUARE VOWEL LENGTH MARK
> +11A33..11A38  ; Extend # Mn   [6] ZANABAZAR SQUARE FINAL CONSONANT MARK..ZANABAZAR SQUARE SIGN ANUSVARA
> +11A3B..11A3E  ; Extend # Mn   [4] ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA..ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA
> +11A47         ; Extend # Mn       ZANABAZAR SQUARE SUBJOINER
> +11A51..11A56  ; Extend # Mn   [6] SOYOMBO VOWEL SIGN I..SOYOMBO VOWEL SIGN OE
> +11A59..11A5B  ; Extend # Mn   [3] SOYOMBO VOWEL SIGN VOCALIC R..SOYOMBO VOWEL LENGTH MARK
> +11A8A..11A96  ; Extend # Mn  [13] SOYOMBO FINAL CONSONANT SIGN G..SOYOMBO SIGN ANUSVARA
> +11A98..11A99  ; Extend # Mn   [2] SOYOMBO GEMINATION MARK..SOYOMBO SUBJOINER
> +11C30..11C36  ; Extend # Mn   [7] BHAIKSUKI VOWEL SIGN I..BHAIKSUKI VOWEL SIGN VOCALIC L
> +11C38..11C3D  ; Extend # Mn   [6] BHAIKSUKI VOWEL SIGN E..BHAIKSUKI SIGN ANUSVARA
> +11C3F         ; Extend # Mn       BHAIKSUKI SIGN VIRAMA
> +11C92..11CA7  ; Extend # Mn  [22] MARCHEN SUBJOINED LETTER KA..MARCHEN SUBJOINED LETTER ZA
> +11CAA..11CB0  ; Extend # Mn   [7] MARCHEN SUBJOINED LETTER RA..MARCHEN VOWEL SIGN AA
> +11CB2..11CB3  ; Extend # Mn   [2] MARCHEN VOWEL SIGN U..MARCHEN VOWEL SIGN E
> +11CB5..11CB6  ; Extend # Mn   [2] MARCHEN SIGN ANUSVARA..MARCHEN SIGN CANDRABINDU
> +11D31..11D36  ; Extend # Mn   [6] MASARAM GONDI VOWEL SIGN AA..MASARAM GONDI VOWEL SIGN VOCALIC R
> +11D3A         ; Extend # Mn       MASARAM GONDI VOWEL SIGN E
> +11D3C..11D3D  ; Extend # Mn   [2] MASARAM GONDI VOWEL SIGN AI..MASARAM GONDI VOWEL SIGN O
> +11D3F..11D45  ; Extend # Mn   [7] MASARAM GONDI VOWEL SIGN AU..MASARAM GONDI VIRAMA
> +11D47         ; Extend # Mn       MASARAM GONDI RA-KARA
> +11D90..11D91  ; Extend # Mn   [2] GUNJALA GONDI VOWEL SIGN EE..GUNJALA GONDI VOWEL SIGN AI
> +11D95         ; Extend # Mn       GUNJALA GONDI SIGN ANUSVARA
> +11D97         ; Extend # Mn       GUNJALA GONDI VIRAMA
> +11EF3..11EF4  ; Extend # Mn   [2] MAKASAR VOWEL SIGN I..MAKASAR VOWEL SIGN U
> +11F00..11F01  ; Extend # Mn   [2] KAWI SIGN CANDRABINDU..KAWI SIGN ANUSVARA
> +11F36..11F3A  ; Extend # Mn   [5] KAWI VOWEL SIGN I..KAWI VOWEL SIGN VOCALIC R
> +11F40         ; Extend # Mn       KAWI VOWEL SIGN EU
> +11F42         ; Extend # Mn       KAWI CONJOINER
> +13440         ; Extend # Mn       EGYPTIAN HIEROGLYPH MIRROR HORIZONTALLY
> +13447..13455  ; Extend # Mn  [15] EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP START..EGYPTIAN HIEROGLYPH MODIFIER DAMAGED
> +16AF0..16AF4  ; Extend # Mn   [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE
> +16B30..16B36  ; Extend # Mn   [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM
> +16F4F         ; Extend # Mn       MIAO SIGN CONSONANT MODIFIER BAR
> +16F8F..16F92  ; Extend # Mn   [4] MIAO TONE RIGHT..MIAO TONE BELOW
> +16FE4         ; Extend # Mn       KHITAN SMALL SCRIPT FILLER
> +1BC9D..1BC9E  ; Extend # Mn   [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK
> +1CF00..1CF2D  ; Extend # Mn  [46] ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT..ZNAMENNY COMBINING MARK KRYZH ON LEFT
> +1CF30..1CF46  ; Extend # Mn  [23] ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO..ZNAMENNY PRIZNAK MODIFIER ROG
> +1D165         ; Extend # Mc       MUSICAL SYMBOL COMBINING STEM
> +1D167..1D169  ; Extend # Mn   [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3
> +1D16E..1D172  ; Extend # Mc   [5] MUSICAL SYMBOL COMBINING FLAG-1..MUSICAL SYMBOL COMBINING FLAG-5
> +1D17B..1D182  ; Extend # Mn   [8] MUSICAL SYMBOL COMBINING ACCENT..MUSICAL SYMBOL COMBINING LOURE
> +1D185..1D18B  ; Extend # Mn   [7] MUSICAL SYMBOL COMBINING DOIT..MUSICAL SYMBOL COMBINING TRIPLE TONGUE
> +1D1AA..1D1AD  ; Extend # Mn   [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO
> +1D242..1D244  ; Extend # Mn   [3] COMBINING GREEK MUSICAL TRISEME..COMBINING GREEK MUSICAL PENTASEME
> +1DA00..1DA36  ; Extend # Mn  [55] SIGNWRITING HEAD RIM..SIGNWRITING AIR SUCKING IN
> +1DA3B..1DA6C  ; Extend # Mn  [50] SIGNWRITING MOUTH CLOSED NEUTRAL..SIGNWRITING EXCITEMENT
> +1DA75         ; Extend # Mn       SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS
> +1DA84         ; Extend # Mn       SIGNWRITING LOCATION HEAD NECK
> +1DA9B..1DA9F  ; Extend # Mn   [5] SIGNWRITING FILL MODIFIER-2..SIGNWRITING FILL MODIFIER-6
> +1DAA1..1DAAF  ; Extend # Mn  [15] SIGNWRITING ROTATION MODIFIER-2..SIGNWRITING ROTATION MODIFIER-16
> +1E000..1E006  ; Extend # Mn   [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE
> +1E008..1E018  ; Extend # Mn  [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU
> +1E01B..1E021  ; Extend # Mn   [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI
> +1E023..1E024  ; Extend # Mn   [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS
> +1E026..1E02A  ; Extend # Mn   [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA
> +1E08F         ; Extend # Mn       COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
> +1E130..1E136  ; Extend # Mn   [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D
> +1E2AE         ; Extend # Mn       TOTO SIGN RISING TONE
> +1E2EC..1E2EF  ; Extend # Mn   [4] WANCHO TONE TUP..WANCHO TONE KOINI
> +1E4EC..1E4EF  ; Extend # Mn   [4] NAG MUNDARI SIGN MUHOR..NAG MUNDARI SIGN SUTUH
> +1E8D0..1E8D6  ; Extend # Mn   [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS
> +1E944..1E94A  ; Extend # Mn   [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA
> +1F3FB..1F3FF  ; Extend # Sk   [5] EMOJI MODIFIER FITZPATRICK TYPE-1-2..EMOJI MODIFIER FITZPATRICK TYPE-6
> +E0020..E007F  ; Extend # Cf  [96] TAG SPACE..CANCEL TAG
> +E0100..E01EF  ; Extend # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
> +
> +# Total code points: 2130
> +
> +# ================================================
> +
> +1F1E6..1F1FF  ; Regional_Indicator # So  [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z
> +
> +# Total code points: 26
> +
> +# ================================================
> +
> +0903          ; SpacingMark # Mc       DEVANAGARI SIGN VISARGA
> +093B          ; SpacingMark # Mc       DEVANAGARI VOWEL SIGN OOE
> +093E..0940    ; SpacingMark # Mc   [3] DEVANAGARI VOWEL SIGN AA..DEVANAGARI VOWEL SIGN II
> +0949..094C    ; SpacingMark # Mc   [4] DEVANAGARI VOWEL SIGN CANDRA O..DEVANAGARI VOWEL SIGN AU
> +094E..094F    ; SpacingMark # Mc   [2] DEVANAGARI VOWEL SIGN PRISHTHAMATRA E..DEVANAGARI VOWEL SIGN AW
> +0982..0983    ; SpacingMark # Mc   [2] BENGALI SIGN ANUSVARA..BENGALI SIGN VISARGA
> +09BF..09C0    ; SpacingMark # Mc   [2] BENGALI VOWEL SIGN I..BENGALI VOWEL SIGN II
> +09C7..09C8    ; SpacingMark # Mc   [2] BENGALI VOWEL SIGN E..BENGALI VOWEL SIGN AI
> +09CB..09CC    ; SpacingMark # Mc   [2] BENGALI VOWEL SIGN O..BENGALI VOWEL SIGN AU
> +0A03          ; SpacingMark # Mc       GURMUKHI SIGN VISARGA
> +0A3E..0A40    ; SpacingMark # Mc   [3] GURMUKHI VOWEL SIGN AA..GURMUKHI VOWEL SIGN II
> +0A83          ; SpacingMark # Mc       GUJARATI SIGN VISARGA
> +0ABE..0AC0    ; SpacingMark # Mc   [3] GUJARATI VOWEL SIGN AA..GUJARATI VOWEL SIGN II
> +0AC9          ; SpacingMark # Mc       GUJARATI VOWEL SIGN CANDRA O
> +0ACB..0ACC    ; SpacingMark # Mc   [2] GUJARATI VOWEL SIGN O..GUJARATI VOWEL SIGN AU
> +0B02..0B03    ; SpacingMark # Mc   [2] ORIYA SIGN ANUSVARA..ORIYA SIGN VISARGA
> +0B40          ; SpacingMark # Mc       ORIYA VOWEL SIGN II
> +0B47..0B48    ; SpacingMark # Mc   [2] ORIYA VOWEL SIGN E..ORIYA VOWEL SIGN AI
> +0B4B..0B4C    ; SpacingMark # Mc   [2] ORIYA VOWEL SIGN O..ORIYA VOWEL SIGN AU
> +0BBF          ; SpacingMark # Mc       TAMIL VOWEL SIGN I
> +0BC1..0BC2    ; SpacingMark # Mc   [2] TAMIL VOWEL SIGN U..TAMIL VOWEL SIGN UU
> +0BC6..0BC8    ; SpacingMark # Mc   [3] TAMIL VOWEL SIGN E..TAMIL VOWEL SIGN AI
> +0BCA..0BCC    ; SpacingMark # Mc   [3] TAMIL VOWEL SIGN O..TAMIL VOWEL SIGN AU
> +0C01..0C03    ; SpacingMark # Mc   [3] TELUGU SIGN CANDRABINDU..TELUGU SIGN VISARGA
> +0C41..0C44    ; SpacingMark # Mc   [4] TELUGU VOWEL SIGN U..TELUGU VOWEL SIGN VOCALIC RR
> +0C82..0C83    ; SpacingMark # Mc   [2] KANNADA SIGN ANUSVARA..KANNADA SIGN VISARGA
> +0CBE          ; SpacingMark # Mc       KANNADA VOWEL SIGN AA
> +0CC0..0CC1    ; SpacingMark # Mc   [2] KANNADA VOWEL SIGN II..KANNADA VOWEL SIGN U
> +0CC3..0CC4    ; SpacingMark # Mc   [2] KANNADA VOWEL SIGN VOCALIC R..KANNADA VOWEL SIGN VOCALIC RR
> +0CC7..0CC8    ; SpacingMark # Mc   [2] KANNADA VOWEL SIGN EE..KANNADA VOWEL SIGN AI
> +0CCA..0CCB    ; SpacingMark # Mc   [2] KANNADA VOWEL SIGN O..KANNADA VOWEL SIGN OO
> +0CF3          ; SpacingMark # Mc       KANNADA SIGN COMBINING ANUSVARA ABOVE RIGHT
> +0D02..0D03    ; SpacingMark # Mc   [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA
> +0D3F..0D40    ; SpacingMark # Mc   [2] MALAYALAM VOWEL SIGN I..MALAYALAM VOWEL SIGN II
> +0D46..0D48    ; SpacingMark # Mc   [3] MALAYALAM VOWEL SIGN E..MALAYALAM VOWEL SIGN AI
> +0D4A..0D4C    ; SpacingMark # Mc   [3] MALAYALAM VOWEL SIGN O..MALAYALAM VOWEL SIGN AU
> +0D82..0D83    ; SpacingMark # Mc   [2] SINHALA SIGN ANUSVARAYA..SINHALA SIGN VISARGAYA
> +0DD0..0DD1    ; SpacingMark # Mc   [2] SINHALA VOWEL SIGN KETTI AEDA-PILLA..SINHALA VOWEL SIGN DIGA AEDA-PILLA
> +0DD8..0DDE    ; SpacingMark # Mc   [7] SINHALA VOWEL SIGN GAETTA-PILLA..SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA
> +0DF2..0DF3    ; SpacingMark # Mc   [2] SINHALA VOWEL SIGN DIGA GAETTA-PILLA..SINHALA VOWEL SIGN DIGA GAYANUKITTA
> +0E33          ; SpacingMark # Lo       THAI CHARACTER SARA AM
> +0EB3          ; SpacingMark # Lo       LAO VOWEL SIGN AM
> +0F3E..0F3F    ; SpacingMark # Mc   [2] TIBETAN SIGN YAR TSHES..TIBETAN SIGN MAR TSHES
> +0F7F          ; SpacingMark # Mc       TIBETAN SIGN RNAM BCAD
> +1031          ; SpacingMark # Mc       MYANMAR VOWEL SIGN E
> +103B..103C    ; SpacingMark # Mc   [2] MYANMAR CONSONANT SIGN MEDIAL YA..MYANMAR CONSONANT SIGN MEDIAL RA
> +1056..1057    ; SpacingMark # Mc   [2] MYANMAR VOWEL SIGN VOCALIC R..MYANMAR VOWEL SIGN VOCALIC RR
> +1084          ; SpacingMark # Mc       MYANMAR VOWEL SIGN SHAN E
> +1715          ; SpacingMark # Mc       TAGALOG SIGN PAMUDPOD
> +1734          ; SpacingMark # Mc       HANUNOO SIGN PAMUDPOD
> +17B6          ; SpacingMark # Mc       KHMER VOWEL SIGN AA
> +17BE..17C5    ; SpacingMark # Mc   [8] KHMER VOWEL SIGN OE..KHMER VOWEL SIGN AU
> +17C7..17C8    ; SpacingMark # Mc   [2] KHMER SIGN REAHMUK..KHMER SIGN YUUKALEAPINTU
> +1923..1926    ; SpacingMark # Mc   [4] LIMBU VOWEL SIGN EE..LIMBU VOWEL SIGN AU
> +1929..192B    ; SpacingMark # Mc   [3] LIMBU SUBJOINED LETTER YA..LIMBU SUBJOINED LETTER WA
> +1930..1931    ; SpacingMark # Mc   [2] LIMBU SMALL LETTER KA..LIMBU SMALL LETTER NGA
> +1933..1938    ; SpacingMark # Mc   [6] LIMBU SMALL LETTER TA..LIMBU SMALL LETTER LA
> +1A19..1A1A    ; SpacingMark # Mc   [2] BUGINESE VOWEL SIGN E..BUGINESE VOWEL SIGN O
> +1A55          ; SpacingMark # Mc       TAI THAM CONSONANT SIGN MEDIAL RA
> +1A57          ; SpacingMark # Mc       TAI THAM CONSONANT SIGN LA TANG LAI
> +1A6D..1A72    ; SpacingMark # Mc   [6] TAI THAM VOWEL SIGN OY..TAI THAM VOWEL SIGN THAM AI
> +1B04          ; SpacingMark # Mc       BALINESE SIGN BISAH
> +1B3B          ; SpacingMark # Mc       BALINESE VOWEL SIGN RA REPA TEDUNG
> +1B3D..1B41    ; SpacingMark # Mc   [5] BALINESE VOWEL SIGN LA LENGA TEDUNG..BALINESE VOWEL SIGN TALING REPA TEDUNG
> +1B43..1B44    ; SpacingMark # Mc   [2] BALINESE VOWEL SIGN PEPET TEDUNG..BALINESE ADEG ADEG
> +1B82          ; SpacingMark # Mc       SUNDANESE SIGN PANGWISAD
> +1BA1          ; SpacingMark # Mc       SUNDANESE CONSONANT SIGN PAMINGKAL
> +1BA6..1BA7    ; SpacingMark # Mc   [2] SUNDANESE VOWEL SIGN PANAELAENG..SUNDANESE VOWEL SIGN PANOLONG
> +1BAA          ; SpacingMark # Mc       SUNDANESE SIGN PAMAAEH
> +1BE7          ; SpacingMark # Mc       BATAK VOWEL SIGN E
> +1BEA..1BEC    ; SpacingMark # Mc   [3] BATAK VOWEL SIGN I..BATAK VOWEL SIGN O
> +1BEE          ; SpacingMark # Mc       BATAK VOWEL SIGN U
> +1BF2..1BF3    ; SpacingMark # Mc   [2] BATAK PANGOLAT..BATAK PANONGONAN
> +1C24..1C2B    ; SpacingMark # Mc   [8] LEPCHA SUBJOINED LETTER YA..LEPCHA VOWEL SIGN UU
> +1C34..1C35    ; SpacingMark # Mc   [2] LEPCHA CONSONANT SIGN NYIN-DO..LEPCHA CONSONANT SIGN KANG
> +1CE1          ; SpacingMark # Mc       VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA
> +1CF7          ; SpacingMark # Mc       VEDIC SIGN ATIKRAMA
> +A823..A824    ; SpacingMark # Mc   [2] SYLOTI NAGRI VOWEL SIGN A..SYLOTI NAGRI VOWEL SIGN I
> +A827          ; SpacingMark # Mc       SYLOTI NAGRI VOWEL SIGN OO
> +A880..A881    ; SpacingMark # Mc   [2] SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN VISARGA
> +A8B4..A8C3    ; SpacingMark # Mc  [16] SAURASHTRA CONSONANT SIGN HAARU..SAURASHTRA VOWEL SIGN AU
> +A952..A953    ; SpacingMark # Mc   [2] REJANG CONSONANT SIGN H..REJANG VIRAMA
> +A983          ; SpacingMark # Mc       JAVANESE SIGN WIGNYAN
> +A9B4..A9B5    ; SpacingMark # Mc   [2] JAVANESE VOWEL SIGN TARUNG..JAVANESE VOWEL SIGN TOLONG
> +A9BA..A9BB    ; SpacingMark # Mc   [2] JAVANESE VOWEL SIGN TALING..JAVANESE VOWEL SIGN DIRGA MURE
> +A9BE..A9C0    ; SpacingMark # Mc   [3] JAVANESE CONSONANT SIGN PENGKAL..JAVANESE PANGKON
> +AA2F..AA30    ; SpacingMark # Mc   [2] CHAM VOWEL SIGN O..CHAM VOWEL SIGN AI
> +AA33..AA34    ; SpacingMark # Mc   [2] CHAM CONSONANT SIGN YA..CHAM CONSONANT SIGN RA
> +AA4D          ; SpacingMark # Mc       CHAM CONSONANT SIGN FINAL H
> +AAEB          ; SpacingMark # Mc       MEETEI MAYEK VOWEL SIGN II
> +AAEE..AAEF    ; SpacingMark # Mc   [2] MEETEI MAYEK VOWEL SIGN AU..MEETEI MAYEK VOWEL SIGN AAU
> +AAF5          ; SpacingMark # Mc       MEETEI MAYEK VOWEL SIGN VISARGA
> +ABE3..ABE4    ; SpacingMark # Mc   [2] MEETEI MAYEK VOWEL SIGN ONAP..MEETEI MAYEK VOWEL SIGN INAP
> +ABE6..ABE7    ; SpacingMark # Mc   [2] MEETEI MAYEK VOWEL SIGN YENAP..MEETEI MAYEK VOWEL SIGN SOUNAP
> +ABE9..ABEA    ; SpacingMark # Mc   [2] MEETEI MAYEK VOWEL SIGN CHEINAP..MEETEI MAYEK VOWEL SIGN NUNG
> +ABEC          ; SpacingMark # Mc       MEETEI MAYEK LUM IYEK
> +11000         ; SpacingMark # Mc       BRAHMI SIGN CANDRABINDU
> +11002         ; SpacingMark # Mc       BRAHMI SIGN VISARGA
> +11082         ; SpacingMark # Mc       KAITHI SIGN VISARGA
> +110B0..110B2  ; SpacingMark # Mc   [3] KAITHI VOWEL SIGN AA..KAITHI VOWEL SIGN II
> +110B7..110B8  ; SpacingMark # Mc   [2] KAITHI VOWEL SIGN O..KAITHI VOWEL SIGN AU
> +1112C         ; SpacingMark # Mc       CHAKMA VOWEL SIGN E
> +11145..11146  ; SpacingMark # Mc   [2] CHAKMA VOWEL SIGN AA..CHAKMA VOWEL SIGN EI
> +11182         ; SpacingMark # Mc       SHARADA SIGN VISARGA
> +111B3..111B5  ; SpacingMark # Mc   [3] SHARADA VOWEL SIGN AA..SHARADA VOWEL SIGN II
> +111BF..111C0  ; SpacingMark # Mc   [2] SHARADA VOWEL SIGN AU..SHARADA SIGN VIRAMA
> +111CE         ; SpacingMark # Mc       SHARADA VOWEL SIGN PRISHTHAMATRA E
> +1122C..1122E  ; SpacingMark # Mc   [3] KHOJKI VOWEL SIGN AA..KHOJKI VOWEL SIGN II
> +11232..11233  ; SpacingMark # Mc   [2] KHOJKI VOWEL SIGN O..KHOJKI VOWEL SIGN AU
> +11235         ; SpacingMark # Mc       KHOJKI SIGN VIRAMA
> +112E0..112E2  ; SpacingMark # Mc   [3] KHUDAWADI VOWEL SIGN AA..KHUDAWADI VOWEL SIGN II
> +11302..11303  ; SpacingMark # Mc   [2] GRANTHA SIGN ANUSVARA..GRANTHA SIGN VISARGA
> +1133F         ; SpacingMark # Mc       GRANTHA VOWEL SIGN I
> +11341..11344  ; SpacingMark # Mc   [4] GRANTHA VOWEL SIGN U..GRANTHA VOWEL SIGN VOCALIC RR
> +11347..11348  ; SpacingMark # Mc   [2] GRANTHA VOWEL SIGN EE..GRANTHA VOWEL SIGN AI
> +1134B..1134D  ; SpacingMark # Mc   [3] GRANTHA VOWEL SIGN OO..GRANTHA SIGN VIRAMA
> +11362..11363  ; SpacingMark # Mc   [2] GRANTHA VOWEL SIGN VOCALIC L..GRANTHA VOWEL SIGN VOCALIC LL
> +11435..11437  ; SpacingMark # Mc   [3] NEWA VOWEL SIGN AA..NEWA VOWEL SIGN II
> +11440..11441  ; SpacingMark # Mc   [2] NEWA VOWEL SIGN O..NEWA VOWEL SIGN AU
> +11445         ; SpacingMark # Mc       NEWA SIGN VISARGA
> +114B1..114B2  ; SpacingMark # Mc   [2] TIRHUTA VOWEL SIGN I..TIRHUTA VOWEL SIGN II
> +114B9         ; SpacingMark # Mc       TIRHUTA VOWEL SIGN E
> +114BB..114BC  ; SpacingMark # Mc   [2] TIRHUTA VOWEL SIGN AI..TIRHUTA VOWEL SIGN O
> +114BE         ; SpacingMark # Mc       TIRHUTA VOWEL SIGN AU
> +114C1         ; SpacingMark # Mc       TIRHUTA SIGN VISARGA
> +115B0..115B1  ; SpacingMark # Mc   [2] SIDDHAM VOWEL SIGN I..SIDDHAM VOWEL SIGN II
> +115B8..115BB  ; SpacingMark # Mc   [4] SIDDHAM VOWEL SIGN E..SIDDHAM VOWEL SIGN AU
> +115BE         ; SpacingMark # Mc       SIDDHAM SIGN VISARGA
> +11630..11632  ; SpacingMark # Mc   [3] MODI VOWEL SIGN AA..MODI VOWEL SIGN II
> +1163B..1163C  ; SpacingMark # Mc   [2] MODI VOWEL SIGN O..MODI VOWEL SIGN AU
> +1163E         ; SpacingMark # Mc       MODI SIGN VISARGA
> +116AC         ; SpacingMark # Mc       TAKRI SIGN VISARGA
> +116AE..116AF  ; SpacingMark # Mc   [2] TAKRI VOWEL SIGN I..TAKRI VOWEL SIGN II
> +116B6         ; SpacingMark # Mc       TAKRI SIGN VIRAMA
> +11726         ; SpacingMark # Mc       AHOM VOWEL SIGN E
> +1182C..1182E  ; SpacingMark # Mc   [3] DOGRA VOWEL SIGN AA..DOGRA VOWEL SIGN II
> +11838         ; SpacingMark # Mc       DOGRA SIGN VISARGA
> +11931..11935  ; SpacingMark # Mc   [5] DIVES AKURU VOWEL SIGN I..DIVES AKURU VOWEL SIGN E
> +11937..11938  ; SpacingMark # Mc   [2] DIVES AKURU VOWEL SIGN AI..DIVES AKURU VOWEL SIGN O
> +1193D         ; SpacingMark # Mc       DIVES AKURU SIGN HALANTA
> +11940         ; SpacingMark # Mc       DIVES AKURU MEDIAL YA
> +11942         ; SpacingMark # Mc       DIVES AKURU MEDIAL RA
> +119D1..119D3  ; SpacingMark # Mc   [3] NANDINAGARI VOWEL SIGN AA..NANDINAGARI VOWEL SIGN II
> +119DC..119DF  ; SpacingMark # Mc   [4] NANDINAGARI VOWEL SIGN O..NANDINAGARI SIGN VISARGA
> +119E4         ; SpacingMark # Mc       NANDINAGARI VOWEL SIGN PRISHTHAMATRA E
> +11A39         ; SpacingMark # Mc       ZANABAZAR SQUARE SIGN VISARGA
> +11A57..11A58  ; SpacingMark # Mc   [2] SOYOMBO VOWEL SIGN AI..SOYOMBO VOWEL SIGN AU
> +11A97         ; SpacingMark # Mc       SOYOMBO SIGN VISARGA
> +11C2F         ; SpacingMark # Mc       BHAIKSUKI VOWEL SIGN AA
> +11C3E         ; SpacingMark # Mc       BHAIKSUKI SIGN VISARGA
> +11CA9         ; SpacingMark # Mc       MARCHEN SUBJOINED LETTER YA
> +11CB1         ; SpacingMark # Mc       MARCHEN VOWEL SIGN I
> +11CB4         ; SpacingMark # Mc       MARCHEN VOWEL SIGN O
> +11D8A..11D8E  ; SpacingMark # Mc   [5] GUNJALA GONDI VOWEL SIGN AA..GUNJALA GONDI VOWEL SIGN UU
> +11D93..11D94  ; SpacingMark # Mc   [2] GUNJALA GONDI VOWEL SIGN OO..GUNJALA GONDI VOWEL SIGN AU
> +11D96         ; SpacingMark # Mc       GUNJALA GONDI SIGN VISARGA
> +11EF5..11EF6  ; SpacingMark # Mc   [2] MAKASAR VOWEL SIGN E..MAKASAR VOWEL SIGN O
> +11F03         ; SpacingMark # Mc       KAWI SIGN VISARGA
> +11F34..11F35  ; SpacingMark # Mc   [2] KAWI VOWEL SIGN AA..KAWI VOWEL SIGN ALTERNATE AA
> +11F3E..11F3F  ; SpacingMark # Mc   [2] KAWI VOWEL SIGN E..KAWI VOWEL SIGN AI
> +11F41         ; SpacingMark # Mc       KAWI SIGN KILLER
> +16F51..16F87  ; SpacingMark # Mc  [55] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN UI
> +16FF0..16FF1  ; SpacingMark # Mc   [2] VIETNAMESE ALTERNATE READING MARK CA..VIETNAMESE ALTERNATE READING MARK NHAY
> +1D166         ; SpacingMark # Mc       MUSICAL SYMBOL COMBINING SPRECHGESANG STEM
> +1D16D         ; SpacingMark # Mc       MUSICAL SYMBOL COMBINING AUGMENTATION DOT
> +
> +# Total code points: 395
> +
> +# ================================================
> +
> +1100..115F    ; L # Lo  [96] HANGUL CHOSEONG KIYEOK..HANGUL CHOSEONG FILLER
> +A960..A97C    ; L # Lo  [29] HANGUL CHOSEONG TIKEUT-MIEUM..HANGUL CHOSEONG SSANGYEORINHIEUH
> +
> +# Total code points: 125
> +
> +# ================================================
> +
> +1160..11A7    ; V # Lo  [72] HANGUL JUNGSEONG FILLER..HANGUL JUNGSEONG O-YAE
> +D7B0..D7C6    ; V # Lo  [23] HANGUL JUNGSEONG O-YEO..HANGUL JUNGSEONG ARAEA-E
> +
> +# Total code points: 95
> +
> +# ================================================
> +
> +11A8..11FF    ; T # Lo  [88] HANGUL JONGSEONG KIYEOK..HANGUL JONGSEONG SSANGNIEUN
> +D7CB..D7FB    ; T # Lo  [49] HANGUL JONGSEONG NIEUN-RIEUL..HANGUL JONGSEONG PHIEUPH-THIEUTH
> +
> +# Total code points: 137
> +
> +# ================================================
> +
> +AC00          ; LV # Lo       HANGUL SYLLABLE GA
> +AC1C          ; LV # Lo       HANGUL SYLLABLE GAE
> +AC38          ; LV # Lo       HANGUL SYLLABLE GYA
> +AC54          ; LV # Lo       HANGUL SYLLABLE GYAE
> +AC70          ; LV # Lo       HANGUL SYLLABLE GEO
> +AC8C          ; LV # Lo       HANGUL SYLLABLE GE
> +ACA8          ; LV # Lo       HANGUL SYLLABLE GYEO
> +ACC4          ; LV # Lo       HANGUL SYLLABLE GYE
> +ACE0          ; LV # Lo       HANGUL SYLLABLE GO
> +ACFC          ; LV # Lo       HANGUL SYLLABLE GWA
> +AD18          ; LV # Lo       HANGUL SYLLABLE GWAE
> +AD34          ; LV # Lo       HANGUL SYLLABLE GOE
> +AD50          ; LV # Lo       HANGUL SYLLABLE GYO
> +AD6C          ; LV # Lo       HANGUL SYLLABLE GU
> +AD88          ; LV # Lo       HANGUL SYLLABLE GWEO
> +ADA4          ; LV # Lo       HANGUL SYLLABLE GWE
> +ADC0          ; LV # Lo       HANGUL SYLLABLE GWI
> +ADDC          ; LV # Lo       HANGUL SYLLABLE GYU
> +ADF8          ; LV # Lo       HANGUL SYLLABLE GEU
> +AE14          ; LV # Lo       HANGUL SYLLABLE GYI
> +AE30          ; LV # Lo       HANGUL SYLLABLE GI
> +AE4C          ; LV # Lo       HANGUL SYLLABLE GGA
> +AE68          ; LV # Lo       HANGUL SYLLABLE GGAE
> +AE84          ; LV # Lo       HANGUL SYLLABLE GGYA
> +AEA0          ; LV # Lo       HANGUL SYLLABLE GGYAE
> +AEBC          ; LV # Lo       HANGUL SYLLABLE GGEO
> +AED8          ; LV # Lo       HANGUL SYLLABLE GGE
> +AEF4          ; LV # Lo       HANGUL SYLLABLE GGYEO
> +AF10          ; LV # Lo       HANGUL SYLLABLE GGYE
> +AF2C          ; LV # Lo       HANGUL SYLLABLE GGO
> +AF48          ; LV # Lo       HANGUL SYLLABLE GGWA
> +AF64          ; LV # Lo       HANGUL SYLLABLE GGWAE
> +AF80          ; LV # Lo       HANGUL SYLLABLE GGOE
> +AF9C          ; LV # Lo       HANGUL SYLLABLE GGYO
> +AFB8          ; LV # Lo       HANGUL SYLLABLE GGU
> +AFD4          ; LV # Lo       HANGUL SYLLABLE GGWEO
> +AFF0          ; LV # Lo       HANGUL SYLLABLE GGWE
> +B00C          ; LV # Lo       HANGUL SYLLABLE GGWI
> +B028          ; LV # Lo       HANGUL SYLLABLE GGYU
> +B044          ; LV # Lo       HANGUL SYLLABLE GGEU
> +B060          ; LV # Lo       HANGUL SYLLABLE GGYI
> +B07C          ; LV # Lo       HANGUL SYLLABLE GGI
> +B098          ; LV # Lo       HANGUL SYLLABLE NA
> +B0B4          ; LV # Lo       HANGUL SYLLABLE NAE
> +B0D0          ; LV # Lo       HANGUL SYLLABLE NYA
> +B0EC          ; LV # Lo       HANGUL SYLLABLE NYAE
> +B108          ; LV # Lo       HANGUL SYLLABLE NEO
> +B124          ; LV # Lo       HANGUL SYLLABLE NE
> +B140          ; LV # Lo       HANGUL SYLLABLE NYEO
> +B15C          ; LV # Lo       HANGUL SYLLABLE NYE
> +B178          ; LV # Lo       HANGUL SYLLABLE NO
> +B194          ; LV # Lo       HANGUL SYLLABLE NWA
> +B1B0          ; LV # Lo       HANGUL SYLLABLE NWAE
> +B1CC          ; LV # Lo       HANGUL SYLLABLE NOE
> +B1E8          ; LV # Lo       HANGUL SYLLABLE NYO
> +B204          ; LV # Lo       HANGUL SYLLABLE NU
> +B220          ; LV # Lo       HANGUL SYLLABLE NWEO
> +B23C          ; LV # Lo       HANGUL SYLLABLE NWE
> +B258          ; LV # Lo       HANGUL SYLLABLE NWI
> +B274          ; LV # Lo       HANGUL SYLLABLE NYU
> +B290          ; LV # Lo       HANGUL SYLLABLE NEU
> +B2AC          ; LV # Lo       HANGUL SYLLABLE NYI
> +B2C8          ; LV # Lo       HANGUL SYLLABLE NI
> +B2E4          ; LV # Lo       HANGUL SYLLABLE DA
> +B300          ; LV # Lo       HANGUL SYLLABLE DAE
> +B31C          ; LV # Lo       HANGUL SYLLABLE DYA
> +B338          ; LV # Lo       HANGUL SYLLABLE DYAE
> +B354          ; LV # Lo       HANGUL SYLLABLE DEO
> +B370          ; LV # Lo       HANGUL SYLLABLE DE
> +B38C          ; LV # Lo       HANGUL SYLLABLE DYEO
> +B3A8          ; LV # Lo       HANGUL SYLLABLE DYE
> +B3C4          ; LV # Lo       HANGUL SYLLABLE DO
> +B3E0          ; LV # Lo       HANGUL SYLLABLE DWA
> +B3FC          ; LV # Lo       HANGUL SYLLABLE DWAE
> +B418          ; LV # Lo       HANGUL SYLLABLE DOE
> +B434          ; LV # Lo       HANGUL SYLLABLE DYO
> +B450          ; LV # Lo       HANGUL SYLLABLE DU
> +B46C          ; LV # Lo       HANGUL SYLLABLE DWEO
> +B488          ; LV # Lo       HANGUL SYLLABLE DWE
> +B4A4          ; LV # Lo       HANGUL SYLLABLE DWI
> +B4C0          ; LV # Lo       HANGUL SYLLABLE DYU
> +B4DC          ; LV # Lo       HANGUL SYLLABLE DEU
> +B4F8          ; LV # Lo       HANGUL SYLLABLE DYI
> +B514          ; LV # Lo       HANGUL SYLLABLE DI
> +B530          ; LV # Lo       HANGUL SYLLABLE DDA
> +B54C          ; LV # Lo       HANGUL SYLLABLE DDAE
> +B568          ; LV # Lo       HANGUL SYLLABLE DDYA
> +B584          ; LV # Lo       HANGUL SYLLABLE DDYAE
> +B5A0          ; LV # Lo       HANGUL SYLLABLE DDEO
> +B5BC          ; LV # Lo       HANGUL SYLLABLE DDE
> +B5D8          ; LV # Lo       HANGUL SYLLABLE DDYEO
> +B5F4          ; LV # Lo       HANGUL SYLLABLE DDYE
> +B610          ; LV # Lo       HANGUL SYLLABLE DDO
> +B62C          ; LV # Lo       HANGUL SYLLABLE DDWA
> +B648          ; LV # Lo       HANGUL SYLLABLE DDWAE
> +B664          ; LV # Lo       HANGUL SYLLABLE DDOE
> +B680          ; LV # Lo       HANGUL SYLLABLE DDYO
> +B69C          ; LV # Lo       HANGUL SYLLABLE DDU
> +B6B8          ; LV # Lo       HANGUL SYLLABLE DDWEO
> +B6D4          ; LV # Lo       HANGUL SYLLABLE DDWE
> +B6F0          ; LV # Lo       HANGUL SYLLABLE DDWI
> +B70C          ; LV # Lo       HANGUL SYLLABLE DDYU
> +B728          ; LV # Lo       HANGUL SYLLABLE DDEU
> +B744          ; LV # Lo       HANGUL SYLLABLE DDYI
> +B760          ; LV # Lo       HANGUL SYLLABLE DDI
> +B77C          ; LV # Lo       HANGUL SYLLABLE RA
> +B798          ; LV # Lo       HANGUL SYLLABLE RAE
> +B7B4          ; LV # Lo       HANGUL SYLLABLE RYA
> +B7D0          ; LV # Lo       HANGUL SYLLABLE RYAE
> +B7EC          ; LV # Lo       HANGUL SYLLABLE REO
> +B808          ; LV # Lo       HANGUL SYLLABLE RE
> +B824          ; LV # Lo       HANGUL SYLLABLE RYEO
> +B840          ; LV # Lo       HANGUL SYLLABLE RYE
> +B85C          ; LV # Lo       HANGUL SYLLABLE RO
> +B878          ; LV # Lo       HANGUL SYLLABLE RWA
> +B894          ; LV # Lo       HANGUL SYLLABLE RWAE
> +B8B0          ; LV # Lo       HANGUL SYLLABLE ROE
> +B8CC          ; LV # Lo       HANGUL SYLLABLE RYO
> +B8E8          ; LV # Lo       HANGUL SYLLABLE RU
> +B904          ; LV # Lo       HANGUL SYLLABLE RWEO
> +B920          ; LV # Lo       HANGUL SYLLABLE RWE
> +B93C          ; LV # Lo       HANGUL SYLLABLE RWI
> +B958          ; LV # Lo       HANGUL SYLLABLE RYU
> +B974          ; LV # Lo       HANGUL SYLLABLE REU
> +B990          ; LV # Lo       HANGUL SYLLABLE RYI
> +B9AC          ; LV # Lo       HANGUL SYLLABLE RI
> +B9C8          ; LV # Lo       HANGUL SYLLABLE MA
> +B9E4          ; LV # Lo       HANGUL SYLLABLE MAE
> +BA00          ; LV # Lo       HANGUL SYLLABLE MYA
> +BA1C          ; LV # Lo       HANGUL SYLLABLE MYAE
> +BA38          ; LV # Lo       HANGUL SYLLABLE MEO
> +BA54          ; LV # Lo       HANGUL SYLLABLE ME
> +BA70          ; LV # Lo       HANGUL SYLLABLE MYEO
> +BA8C          ; LV # Lo       HANGUL SYLLABLE MYE
> +BAA8          ; LV # Lo       HANGUL SYLLABLE MO
> +BAC4          ; LV # Lo       HANGUL SYLLABLE MWA
> +BAE0          ; LV # Lo       HANGUL SYLLABLE MWAE
> +BAFC          ; LV # Lo       HANGUL SYLLABLE MOE
> +BB18          ; LV # Lo       HANGUL SYLLABLE MYO
> +BB34          ; LV # Lo       HANGUL SYLLABLE MU
> +BB50          ; LV # Lo       HANGUL SYLLABLE MWEO
> +BB6C          ; LV # Lo       HANGUL SYLLABLE MWE
> +BB88          ; LV # Lo       HANGUL SYLLABLE MWI
> +BBA4          ; LV # Lo       HANGUL SYLLABLE MYU
> +BBC0          ; LV # Lo       HANGUL SYLLABLE MEU
> +BBDC          ; LV # Lo       HANGUL SYLLABLE MYI
> +BBF8          ; LV # Lo       HANGUL SYLLABLE MI
> +BC14          ; LV # Lo       HANGUL SYLLABLE BA
> +BC30          ; LV # Lo       HANGUL SYLLABLE BAE
> +BC4C          ; LV # Lo       HANGUL SYLLABLE BYA
> +BC68          ; LV # Lo       HANGUL SYLLABLE BYAE
> +BC84          ; LV # Lo       HANGUL SYLLABLE BEO
> +BCA0          ; LV # Lo       HANGUL SYLLABLE BE
> +BCBC          ; LV # Lo       HANGUL SYLLABLE BYEO
> +BCD8          ; LV # Lo       HANGUL SYLLABLE BYE
> +BCF4          ; LV # Lo       HANGUL SYLLABLE BO
> +BD10          ; LV # Lo       HANGUL SYLLABLE BWA
> +BD2C          ; LV # Lo       HANGUL SYLLABLE BWAE
> +BD48          ; LV # Lo       HANGUL SYLLABLE BOE
> +BD64          ; LV # Lo       HANGUL SYLLABLE BYO
> +BD80          ; LV # Lo       HANGUL SYLLABLE BU
> +BD9C          ; LV # Lo       HANGUL SYLLABLE BWEO
> +BDB8          ; LV # Lo       HANGUL SYLLABLE BWE
> +BDD4          ; LV # Lo       HANGUL SYLLABLE BWI
> +BDF0          ; LV # Lo       HANGUL SYLLABLE BYU
> +BE0C          ; LV # Lo       HANGUL SYLLABLE BEU
> +BE28          ; LV # Lo       HANGUL SYLLABLE BYI
> +BE44          ; LV # Lo       HANGUL SYLLABLE BI
> +BE60          ; LV # Lo       HANGUL SYLLABLE BBA
> +BE7C          ; LV # Lo       HANGUL SYLLABLE BBAE
> +BE98          ; LV # Lo       HANGUL SYLLABLE BBYA
> +BEB4          ; LV # Lo       HANGUL SYLLABLE BBYAE
> +BED0          ; LV # Lo       HANGUL SYLLABLE BBEO
> +BEEC          ; LV # Lo       HANGUL SYLLABLE BBE
> +BF08          ; LV # Lo       HANGUL SYLLABLE BBYEO
> +BF24          ; LV # Lo       HANGUL SYLLABLE BBYE
> +BF40          ; LV # Lo       HANGUL SYLLABLE BBO
> +BF5C          ; LV # Lo       HANGUL SYLLABLE BBWA
> +BF78          ; LV # Lo       HANGUL SYLLABLE BBWAE
> +BF94          ; LV # Lo       HANGUL SYLLABLE BBOE
> +BFB0          ; LV # Lo       HANGUL SYLLABLE BBYO
> +BFCC          ; LV # Lo       HANGUL SYLLABLE BBU
> +BFE8          ; LV # Lo       HANGUL SYLLABLE BBWEO
> +C004          ; LV # Lo       HANGUL SYLLABLE BBWE
> +C020          ; LV # Lo       HANGUL SYLLABLE BBWI
> +C03C          ; LV # Lo       HANGUL SYLLABLE BBYU
> +C058          ; LV # Lo       HANGUL SYLLABLE BBEU
> +C074          ; LV # Lo       HANGUL SYLLABLE BBYI
> +C090          ; LV # Lo       HANGUL SYLLABLE BBI
> +C0AC          ; LV # Lo       HANGUL SYLLABLE SA
> +C0C8          ; LV # Lo       HANGUL SYLLABLE SAE
> +C0E4          ; LV # Lo       HANGUL SYLLABLE SYA
> +C100          ; LV # Lo       HANGUL SYLLABLE SYAE
> +C11C          ; LV # Lo       HANGUL SYLLABLE SEO
> +C138          ; LV # Lo       HANGUL SYLLABLE SE
> +C154          ; LV # Lo       HANGUL SYLLABLE SYEO
> +C170          ; LV # Lo       HANGUL SYLLABLE SYE
> +C18C          ; LV # Lo       HANGUL SYLLABLE SO
> +C1A8          ; LV # Lo       HANGUL SYLLABLE SWA
> +C1C4          ; LV # Lo       HANGUL SYLLABLE SWAE
> +C1E0          ; LV # Lo       HANGUL SYLLABLE SOE
> +C1FC          ; LV # Lo       HANGUL SYLLABLE SYO
> +C218          ; LV # Lo       HANGUL SYLLABLE SU
> +C234          ; LV # Lo       HANGUL SYLLABLE SWEO
> +C250          ; LV # Lo       HANGUL SYLLABLE SWE
> +C26C          ; LV # Lo       HANGUL SYLLABLE SWI
> +C288          ; LV # Lo       HANGUL SYLLABLE SYU
> +C2A4          ; LV # Lo       HANGUL SYLLABLE SEU
> +C2C0          ; LV # Lo       HANGUL SYLLABLE SYI
> +C2DC          ; LV # Lo       HANGUL SYLLABLE SI
> +C2F8          ; LV # Lo       HANGUL SYLLABLE SSA
> +C314          ; LV # Lo       HANGUL SYLLABLE SSAE
> +C330          ; LV # Lo       HANGUL SYLLABLE SSYA
> +C34C          ; LV # Lo       HANGUL SYLLABLE SSYAE
> +C368          ; LV # Lo       HANGUL SYLLABLE SSEO
> +C384          ; LV # Lo       HANGUL SYLLABLE SSE
> +C3A0          ; LV # Lo       HANGUL SYLLABLE SSYEO
> +C3BC          ; LV # Lo       HANGUL SYLLABLE SSYE
> +C3D8          ; LV # Lo       HANGUL SYLLABLE SSO
> +C3F4          ; LV # Lo       HANGUL SYLLABLE SSWA
> +C410          ; LV # Lo       HANGUL SYLLABLE SSWAE
> +C42C          ; LV # Lo       HANGUL SYLLABLE SSOE
> +C448          ; LV # Lo       HANGUL SYLLABLE SSYO
> +C464          ; LV # Lo       HANGUL SYLLABLE SSU
> +C480          ; LV # Lo       HANGUL SYLLABLE SSWEO
> +C49C          ; LV # Lo       HANGUL SYLLABLE SSWE
> +C4B8          ; LV # Lo       HANGUL SYLLABLE SSWI
> +C4D4          ; LV # Lo       HANGUL SYLLABLE SSYU
> +C4F0          ; LV # Lo       HANGUL SYLLABLE SSEU
> +C50C          ; LV # Lo       HANGUL SYLLABLE SSYI
> +C528          ; LV # Lo       HANGUL SYLLABLE SSI
> +C544          ; LV # Lo       HANGUL SYLLABLE A
> +C560          ; LV # Lo       HANGUL SYLLABLE AE
> +C57C          ; LV # Lo       HANGUL SYLLABLE YA
> +C598          ; LV # Lo       HANGUL SYLLABLE YAE
> +C5B4          ; LV # Lo       HANGUL SYLLABLE EO
> +C5D0          ; LV # Lo       HANGUL SYLLABLE E
> +C5EC          ; LV # Lo       HANGUL SYLLABLE YEO
> +C608          ; LV # Lo       HANGUL SYLLABLE YE
> +C624          ; LV # Lo       HANGUL SYLLABLE O
> +C640          ; LV # Lo       HANGUL SYLLABLE WA
> +C65C          ; LV # Lo       HANGUL SYLLABLE WAE
> +C678          ; LV # Lo       HANGUL SYLLABLE OE
> +C694          ; LV # Lo       HANGUL SYLLABLE YO
> +C6B0          ; LV # Lo       HANGUL SYLLABLE U
> +C6CC          ; LV # Lo       HANGUL SYLLABLE WEO
> +C6E8          ; LV # Lo       HANGUL SYLLABLE WE
> +C704          ; LV # Lo       HANGUL SYLLABLE WI
> +C720          ; LV # Lo       HANGUL SYLLABLE YU
> +C73C          ; LV # Lo       HANGUL SYLLABLE EU
> +C758          ; LV # Lo       HANGUL SYLLABLE YI
> +C774          ; LV # Lo       HANGUL SYLLABLE I
> +C790          ; LV # Lo       HANGUL SYLLABLE JA
> +C7AC          ; LV # Lo       HANGUL SYLLABLE JAE
> +C7C8          ; LV # Lo       HANGUL SYLLABLE JYA
> +C7E4          ; LV # Lo       HANGUL SYLLABLE JYAE
> +C800          ; LV # Lo       HANGUL SYLLABLE JEO
> +C81C          ; LV # Lo       HANGUL SYLLABLE JE
> +C838          ; LV # Lo       HANGUL SYLLABLE JYEO
> +C854          ; LV # Lo       HANGUL SYLLABLE JYE
> +C870          ; LV # Lo       HANGUL SYLLABLE JO
> +C88C          ; LV # Lo       HANGUL SYLLABLE JWA
> +C8A8          ; LV # Lo       HANGUL SYLLABLE JWAE
> +C8C4          ; LV # Lo       HANGUL SYLLABLE JOE
> +C8E0          ; LV # Lo       HANGUL SYLLABLE JYO
> +C8FC          ; LV # Lo       HANGUL SYLLABLE JU
> +C918          ; LV # Lo       HANGUL SYLLABLE JWEO
> +C934          ; LV # Lo       HANGUL SYLLABLE JWE
> +C950          ; LV # Lo       HANGUL SYLLABLE JWI
> +C96C          ; LV # Lo       HANGUL SYLLABLE JYU
> +C988          ; LV # Lo       HANGUL SYLLABLE JEU
> +C9A4          ; LV # Lo       HANGUL SYLLABLE JYI
> +C9C0          ; LV # Lo       HANGUL SYLLABLE JI
> +C9DC          ; LV # Lo       HANGUL SYLLABLE JJA
> +C9F8          ; LV # Lo       HANGUL SYLLABLE JJAE
> +CA14          ; LV # Lo       HANGUL SYLLABLE JJYA
> +CA30          ; LV # Lo       HANGUL SYLLABLE JJYAE
> +CA4C          ; LV # Lo       HANGUL SYLLABLE JJEO
> +CA68          ; LV # Lo       HANGUL SYLLABLE JJE
> +CA84          ; LV # Lo       HANGUL SYLLABLE JJYEO
> +CAA0          ; LV # Lo       HANGUL SYLLABLE JJYE
> +CABC          ; LV # Lo       HANGUL SYLLABLE JJO
> +CAD8          ; LV # Lo       HANGUL SYLLABLE JJWA
> +CAF4          ; LV # Lo       HANGUL SYLLABLE JJWAE
> +CB10          ; LV # Lo       HANGUL SYLLABLE JJOE
> +CB2C          ; LV # Lo       HANGUL SYLLABLE JJYO
> +CB48          ; LV # Lo       HANGUL SYLLABLE JJU
> +CB64          ; LV # Lo       HANGUL SYLLABLE JJWEO
> +CB80          ; LV # Lo       HANGUL SYLLABLE JJWE
> +CB9C          ; LV # Lo       HANGUL SYLLABLE JJWI
> +CBB8          ; LV # Lo       HANGUL SYLLABLE JJYU
> +CBD4          ; LV # Lo       HANGUL SYLLABLE JJEU
> +CBF0          ; LV # Lo       HANGUL SYLLABLE JJYI
> +CC0C          ; LV # Lo       HANGUL SYLLABLE JJI
> +CC28          ; LV # Lo       HANGUL SYLLABLE CA
> +CC44          ; LV # Lo       HANGUL SYLLABLE CAE
> +CC60          ; LV # Lo       HANGUL SYLLABLE CYA
> +CC7C          ; LV # Lo       HANGUL SYLLABLE CYAE
> +CC98          ; LV # Lo       HANGUL SYLLABLE CEO
> +CCB4          ; LV # Lo       HANGUL SYLLABLE CE
> +CCD0          ; LV # Lo       HANGUL SYLLABLE CYEO
> +CCEC          ; LV # Lo       HANGUL SYLLABLE CYE
> +CD08          ; LV # Lo       HANGUL SYLLABLE CO
> +CD24          ; LV # Lo       HANGUL SYLLABLE CWA
> +CD40          ; LV # Lo       HANGUL SYLLABLE CWAE
> +CD5C          ; LV # Lo       HANGUL SYLLABLE COE
> +CD78          ; LV # Lo       HANGUL SYLLABLE CYO
> +CD94          ; LV # Lo       HANGUL SYLLABLE CU
> +CDB0          ; LV # Lo       HANGUL SYLLABLE CWEO
> +CDCC          ; LV # Lo       HANGUL SYLLABLE CWE
> +CDE8          ; LV # Lo       HANGUL SYLLABLE CWI
> +CE04          ; LV # Lo       HANGUL SYLLABLE CYU
> +CE20          ; LV # Lo       HANGUL SYLLABLE CEU
> +CE3C          ; LV # Lo       HANGUL SYLLABLE CYI
> +CE58          ; LV # Lo       HANGUL SYLLABLE CI
> +CE74          ; LV # Lo       HANGUL SYLLABLE KA
> +CE90          ; LV # Lo       HANGUL SYLLABLE KAE
> +CEAC          ; LV # Lo       HANGUL SYLLABLE KYA
> +CEC8          ; LV # Lo       HANGUL SYLLABLE KYAE
> +CEE4          ; LV # Lo       HANGUL SYLLABLE KEO
> +CF00          ; LV # Lo       HANGUL SYLLABLE KE
> +CF1C          ; LV # Lo       HANGUL SYLLABLE KYEO
> +CF38          ; LV # Lo       HANGUL SYLLABLE KYE
> +CF54          ; LV # Lo       HANGUL SYLLABLE KO
> +CF70          ; LV # Lo       HANGUL SYLLABLE KWA
> +CF8C          ; LV # Lo       HANGUL SYLLABLE KWAE
> +CFA8          ; LV # Lo       HANGUL SYLLABLE KOE
> +CFC4          ; LV # Lo       HANGUL SYLLABLE KYO
> +CFE0          ; LV # Lo       HANGUL SYLLABLE KU
> +CFFC          ; LV # Lo       HANGUL SYLLABLE KWEO
> +D018          ; LV # Lo       HANGUL SYLLABLE KWE
> +D034          ; LV # Lo       HANGUL SYLLABLE KWI
> +D050          ; LV # Lo       HANGUL SYLLABLE KYU
> +D06C          ; LV # Lo       HANGUL SYLLABLE KEU
> +D088          ; LV # Lo       HANGUL SYLLABLE KYI
> +D0A4          ; LV # Lo       HANGUL SYLLABLE KI
> +D0C0          ; LV # Lo       HANGUL SYLLABLE TA
> +D0DC          ; LV # Lo       HANGUL SYLLABLE TAE
> +D0F8          ; LV # Lo       HANGUL SYLLABLE TYA
> +D114          ; LV # Lo       HANGUL SYLLABLE TYAE
> +D130          ; LV # Lo       HANGUL SYLLABLE TEO
> +D14C          ; LV # Lo       HANGUL SYLLABLE TE
> +D168          ; LV # Lo       HANGUL SYLLABLE TYEO
> +D184          ; LV # Lo       HANGUL SYLLABLE TYE
> +D1A0          ; LV # Lo       HANGUL SYLLABLE TO
> +D1BC          ; LV # Lo       HANGUL SYLLABLE TWA
> +D1D8          ; LV # Lo       HANGUL SYLLABLE TWAE
> +D1F4          ; LV # Lo       HANGUL SYLLABLE TOE
> +D210          ; LV # Lo       HANGUL SYLLABLE TYO
> +D22C          ; LV # Lo       HANGUL SYLLABLE TU
> +D248          ; LV # Lo       HANGUL SYLLABLE TWEO
> +D264          ; LV # Lo       HANGUL SYLLABLE TWE
> +D280          ; LV # Lo       HANGUL SYLLABLE TWI
> +D29C          ; LV # Lo       HANGUL SYLLABLE TYU
> +D2B8          ; LV # Lo       HANGUL SYLLABLE TEU
> +D2D4          ; LV # Lo       HANGUL SYLLABLE TYI
> +D2F0          ; LV # Lo       HANGUL SYLLABLE TI
> +D30C          ; LV # Lo       HANGUL SYLLABLE PA
> +D328          ; LV # Lo       HANGUL SYLLABLE PAE
> +D344          ; LV # Lo       HANGUL SYLLABLE PYA
> +D360          ; LV # Lo       HANGUL SYLLABLE PYAE
> +D37C          ; LV # Lo       HANGUL SYLLABLE PEO
> +D398          ; LV # Lo       HANGUL SYLLABLE PE
> +D3B4          ; LV # Lo       HANGUL SYLLABLE PYEO
> +D3D0          ; LV # Lo       HANGUL SYLLABLE PYE
> +D3EC          ; LV # Lo       HANGUL SYLLABLE PO
> +D408          ; LV # Lo       HANGUL SYLLABLE PWA
> +D424          ; LV # Lo       HANGUL SYLLABLE PWAE
> +D440          ; LV # Lo       HANGUL SYLLABLE POE
> +D45C          ; LV # Lo       HANGUL SYLLABLE PYO
> +D478          ; LV # Lo       HANGUL SYLLABLE PU
> +D494          ; LV # Lo       HANGUL SYLLABLE PWEO
> +D4B0          ; LV # Lo       HANGUL SYLLABLE PWE
> +D4CC          ; LV # Lo       HANGUL SYLLABLE PWI
> +D4E8          ; LV # Lo       HANGUL SYLLABLE PYU
> +D504          ; LV # Lo       HANGUL SYLLABLE PEU
> +D520          ; LV # Lo       HANGUL SYLLABLE PYI
> +D53C          ; LV # Lo       HANGUL SYLLABLE PI
> +D558          ; LV # Lo       HANGUL SYLLABLE HA
> +D574          ; LV # Lo       HANGUL SYLLABLE HAE
> +D590          ; LV # Lo       HANGUL SYLLABLE HYA
> +D5AC          ; LV # Lo       HANGUL SYLLABLE HYAE
> +D5C8          ; LV # Lo       HANGUL SYLLABLE HEO
> +D5E4          ; LV # Lo       HANGUL SYLLABLE HE
> +D600          ; LV # Lo       HANGUL SYLLABLE HYEO
> +D61C          ; LV # Lo       HANGUL SYLLABLE HYE
> +D638          ; LV # Lo       HANGUL SYLLABLE HO
> +D654          ; LV # Lo       HANGUL SYLLABLE HWA
> +D670          ; LV # Lo       HANGUL SYLLABLE HWAE
> +D68C          ; LV # Lo       HANGUL SYLLABLE HOE
> +D6A8          ; LV # Lo       HANGUL SYLLABLE HYO
> +D6C4          ; LV # Lo       HANGUL SYLLABLE HU
> +D6E0          ; LV # Lo       HANGUL SYLLABLE HWEO
> +D6FC          ; LV # Lo       HANGUL SYLLABLE HWE
> +D718          ; LV # Lo       HANGUL SYLLABLE HWI
> +D734          ; LV # Lo       HANGUL SYLLABLE HYU
> +D750          ; LV # Lo       HANGUL SYLLABLE HEU
> +D76C          ; LV # Lo       HANGUL SYLLABLE HYI
> +D788          ; LV # Lo       HANGUL SYLLABLE HI
> +
> +# Total code points: 399
> +
> +# ================================================
> +
> +AC01..AC1B    ; LVT # Lo  [27] HANGUL SYLLABLE GAG..HANGUL SYLLABLE GAH
> +AC1D..AC37    ; LVT # Lo  [27] HANGUL SYLLABLE GAEG..HANGUL SYLLABLE GAEH
> +AC39..AC53    ; LVT # Lo  [27] HANGUL SYLLABLE GYAG..HANGUL SYLLABLE GYAH
> +AC55..AC6F    ; LVT # Lo  [27] HANGUL SYLLABLE GYAEG..HANGUL SYLLABLE GYAEH
> +AC71..AC8B    ; LVT # Lo  [27] HANGUL SYLLABLE GEOG..HANGUL SYLLABLE GEOH
> +AC8D..ACA7    ; LVT # Lo  [27] HANGUL SYLLABLE GEG..HANGUL SYLLABLE GEH
> +ACA9..ACC3    ; LVT # Lo  [27] HANGUL SYLLABLE GYEOG..HANGUL SYLLABLE GYEOH
> +ACC5..ACDF    ; LVT # Lo  [27] HANGUL SYLLABLE GYEG..HANGUL SYLLABLE GYEH
> +ACE1..ACFB    ; LVT # Lo  [27] HANGUL SYLLABLE GOG..HANGUL SYLLABLE GOH
> +ACFD..AD17    ; LVT # Lo  [27] HANGUL SYLLABLE GWAG..HANGUL SYLLABLE GWAH
> +AD19..AD33    ; LVT # Lo  [27] HANGUL SYLLABLE GWAEG..HANGUL SYLLABLE GWAEH
> +AD35..AD4F    ; LVT # Lo  [27] HANGUL SYLLABLE GOEG..HANGUL SYLLABLE GOEH
> +AD51..AD6B    ; LVT # Lo  [27] HANGUL SYLLABLE GYOG..HANGUL SYLLABLE GYOH
> +AD6D..AD87    ; LVT # Lo  [27] HANGUL SYLLABLE GUG..HANGUL SYLLABLE GUH
> +AD89..ADA3    ; LVT # Lo  [27] HANGUL SYLLABLE GWEOG..HANGUL SYLLABLE GWEOH
> +ADA5..ADBF    ; LVT # Lo  [27] HANGUL SYLLABLE GWEG..HANGUL SYLLABLE GWEH
> +ADC1..ADDB    ; LVT # Lo  [27] HANGUL SYLLABLE GWIG..HANGUL SYLLABLE GWIH
> +ADDD..ADF7    ; LVT # Lo  [27] HANGUL SYLLABLE GYUG..HANGUL SYLLABLE GYUH
> +ADF9..AE13    ; LVT # Lo  [27] HANGUL SYLLABLE GEUG..HANGUL SYLLABLE GEUH
> +AE15..AE2F    ; LVT # Lo  [27] HANGUL SYLLABLE GYIG..HANGUL SYLLABLE GYIH
> +AE31..AE4B    ; LVT # Lo  [27] HANGUL SYLLABLE GIG..HANGUL SYLLABLE GIH
> +AE4D..AE67    ; LVT # Lo  [27] HANGUL SYLLABLE GGAG..HANGUL SYLLABLE GGAH
> +AE69..AE83    ; LVT # Lo  [27] HANGUL SYLLABLE GGAEG..HANGUL SYLLABLE GGAEH
> +AE85..AE9F    ; LVT # Lo  [27] HANGUL SYLLABLE GGYAG..HANGUL SYLLABLE GGYAH
> +AEA1..AEBB    ; LVT # Lo  [27] HANGUL SYLLABLE GGYAEG..HANGUL SYLLABLE GGYAEH
> +AEBD..AED7    ; LVT # Lo  [27] HANGUL SYLLABLE GGEOG..HANGUL SYLLABLE GGEOH
> +AED9..AEF3    ; LVT # Lo  [27] HANGUL SYLLABLE GGEG..HANGUL SYLLABLE GGEH
> +AEF5..AF0F    ; LVT # Lo  [27] HANGUL SYLLABLE GGYEOG..HANGUL SYLLABLE GGYEOH
> +AF11..AF2B    ; LVT # Lo  [27] HANGUL SYLLABLE GGYEG..HANGUL SYLLABLE GGYEH
> +AF2D..AF47    ; LVT # Lo  [27] HANGUL SYLLABLE GGOG..HANGUL SYLLABLE GGOH
> +AF49..AF63    ; LVT # Lo  [27] HANGUL SYLLABLE GGWAG..HANGUL SYLLABLE GGWAH
> +AF65..AF7F    ; LVT # Lo  [27] HANGUL SYLLABLE GGWAEG..HANGUL SYLLABLE GGWAEH
> +AF81..AF9B    ; LVT # Lo  [27] HANGUL SYLLABLE GGOEG..HANGUL SYLLABLE GGOEH
> +AF9D..AFB7    ; LVT # Lo  [27] HANGUL SYLLABLE GGYOG..HANGUL SYLLABLE GGYOH
> +AFB9..AFD3    ; LVT # Lo  [27] HANGUL SYLLABLE GGUG..HANGUL SYLLABLE GGUH
> +AFD5..AFEF    ; LVT # Lo  [27] HANGUL SYLLABLE GGWEOG..HANGUL SYLLABLE GGWEOH
> +AFF1..B00B    ; LVT # Lo  [27] HANGUL SYLLABLE GGWEG..HANGUL SYLLABLE GGWEH
> +B00D..B027    ; LVT # Lo  [27] HANGUL SYLLABLE GGWIG..HANGUL SYLLABLE GGWIH
> +B029..B043    ; LVT # Lo  [27] HANGUL SYLLABLE GGYUG..HANGUL SYLLABLE GGYUH
> +B045..B05F    ; LVT # Lo  [27] HANGUL SYLLABLE GGEUG..HANGUL SYLLABLE GGEUH
> +B061..B07B    ; LVT # Lo  [27] HANGUL SYLLABLE GGYIG..HANGUL SYLLABLE GGYIH
> +B07D..B097    ; LVT # Lo  [27] HANGUL SYLLABLE GGIG..HANGUL SYLLABLE GGIH
> +B099..B0B3    ; LVT # Lo  [27] HANGUL SYLLABLE NAG..HANGUL SYLLABLE NAH
> +B0B5..B0CF    ; LVT # Lo  [27] HANGUL SYLLABLE NAEG..HANGUL SYLLABLE NAEH
> +B0D1..B0EB    ; LVT # Lo  [27] HANGUL SYLLABLE NYAG..HANGUL SYLLABLE NYAH
> +B0ED..B107    ; LVT # Lo  [27] HANGUL SYLLABLE NYAEG..HANGUL SYLLABLE NYAEH
> +B109..B123    ; LVT # Lo  [27] HANGUL SYLLABLE NEOG..HANGUL SYLLABLE NEOH
> +B125..B13F    ; LVT # Lo  [27] HANGUL SYLLABLE NEG..HANGUL SYLLABLE NEH
> +B141..B15B    ; LVT # Lo  [27] HANGUL SYLLABLE NYEOG..HANGUL SYLLABLE NYEOH
> +B15D..B177    ; LVT # Lo  [27] HANGUL SYLLABLE NYEG..HANGUL SYLLABLE NYEH
> +B179..B193    ; LVT # Lo  [27] HANGUL SYLLABLE NOG..HANGUL SYLLABLE NOH
> +B195..B1AF    ; LVT # Lo  [27] HANGUL SYLLABLE NWAG..HANGUL SYLLABLE NWAH
> +B1B1..B1CB    ; LVT # Lo  [27] HANGUL SYLLABLE NWAEG..HANGUL SYLLABLE NWAEH
> +B1CD..B1E7    ; LVT # Lo  [27] HANGUL SYLLABLE NOEG..HANGUL SYLLABLE NOEH
> +B1E9..B203    ; LVT # Lo  [27] HANGUL SYLLABLE NYOG..HANGUL SYLLABLE NYOH
> +B205..B21F    ; LVT # Lo  [27] HANGUL SYLLABLE NUG..HANGUL SYLLABLE NUH
> +B221..B23B    ; LVT # Lo  [27] HANGUL SYLLABLE NWEOG..HANGUL SYLLABLE NWEOH
> +B23D..B257    ; LVT # Lo  [27] HANGUL SYLLABLE NWEG..HANGUL SYLLABLE NWEH
> +B259..B273    ; LVT # Lo  [27] HANGUL SYLLABLE NWIG..HANGUL SYLLABLE NWIH
> +B275..B28F    ; LVT # Lo  [27] HANGUL SYLLABLE NYUG..HANGUL SYLLABLE NYUH
> +B291..B2AB    ; LVT # Lo  [27] HANGUL SYLLABLE NEUG..HANGUL SYLLABLE NEUH
> +B2AD..B2C7    ; LVT # Lo  [27] HANGUL SYLLABLE NYIG..HANGUL SYLLABLE NYIH
> +B2C9..B2E3    ; LVT # Lo  [27] HANGUL SYLLABLE NIG..HANGUL SYLLABLE NIH
> +B2E5..B2FF    ; LVT # Lo  [27] HANGUL SYLLABLE DAG..HANGUL SYLLABLE DAH
> +B301..B31B    ; LVT # Lo  [27] HANGUL SYLLABLE DAEG..HANGUL SYLLABLE DAEH
> +B31D..B337    ; LVT # Lo  [27] HANGUL SYLLABLE DYAG..HANGUL SYLLABLE DYAH
> +B339..B353    ; LVT # Lo  [27] HANGUL SYLLABLE DYAEG..HANGUL SYLLABLE DYAEH
> +B355..B36F    ; LVT # Lo  [27] HANGUL SYLLABLE DEOG..HANGUL SYLLABLE DEOH
> +B371..B38B    ; LVT # Lo  [27] HANGUL SYLLABLE DEG..HANGUL SYLLABLE DEH
> +B38D..B3A7    ; LVT # Lo  [27] HANGUL SYLLABLE DYEOG..HANGUL SYLLABLE DYEOH
> +B3A9..B3C3    ; LVT # Lo  [27] HANGUL SYLLABLE DYEG..HANGUL SYLLABLE DYEH
> +B3C5..B3DF    ; LVT # Lo  [27] HANGUL SYLLABLE DOG..HANGUL SYLLABLE DOH
> +B3E1..B3FB    ; LVT # Lo  [27] HANGUL SYLLABLE DWAG..HANGUL SYLLABLE DWAH
> +B3FD..B417    ; LVT # Lo  [27] HANGUL SYLLABLE DWAEG..HANGUL SYLLABLE DWAEH
> +B419..B433    ; LVT # Lo  [27] HANGUL SYLLABLE DOEG..HANGUL SYLLABLE DOEH
> +B435..B44F    ; LVT # Lo  [27] HANGUL SYLLABLE DYOG..HANGUL SYLLABLE DYOH
> +B451..B46B    ; LVT # Lo  [27] HANGUL SYLLABLE DUG..HANGUL SYLLABLE DUH
> +B46D..B487    ; LVT # Lo  [27] HANGUL SYLLABLE DWEOG..HANGUL SYLLABLE DWEOH
> +B489..B4A3    ; LVT # Lo  [27] HANGUL SYLLABLE DWEG..HANGUL SYLLABLE DWEH
> +B4A5..B4BF    ; LVT # Lo  [27] HANGUL SYLLABLE DWIG..HANGUL SYLLABLE DWIH
> +B4C1..B4DB    ; LVT # Lo  [27] HANGUL SYLLABLE DYUG..HANGUL SYLLABLE DYUH
> +B4DD..B4F7    ; LVT # Lo  [27] HANGUL SYLLABLE DEUG..HANGUL SYLLABLE DEUH
> +B4F9..B513    ; LVT # Lo  [27] HANGUL SYLLABLE DYIG..HANGUL SYLLABLE DYIH
> +B515..B52F    ; LVT # Lo  [27] HANGUL SYLLABLE DIG..HANGUL SYLLABLE DIH
> +B531..B54B    ; LVT # Lo  [27] HANGUL SYLLABLE DDAG..HANGUL SYLLABLE DDAH
> +B54D..B567    ; LVT # Lo  [27] HANGUL SYLLABLE DDAEG..HANGUL SYLLABLE DDAEH
> +B569..B583    ; LVT # Lo  [27] HANGUL SYLLABLE DDYAG..HANGUL SYLLABLE DDYAH
> +B585..B59F    ; LVT # Lo  [27] HANGUL SYLLABLE DDYAEG..HANGUL SYLLABLE DDYAEH
> +B5A1..B5BB    ; LVT # Lo  [27] HANGUL SYLLABLE DDEOG..HANGUL SYLLABLE DDEOH
> +B5BD..B5D7    ; LVT # Lo  [27] HANGUL SYLLABLE DDEG..HANGUL SYLLABLE DDEH
> +B5D9..B5F3    ; LVT # Lo  [27] HANGUL SYLLABLE DDYEOG..HANGUL SYLLABLE DDYEOH
> +B5F5..B60F    ; LVT # Lo  [27] HANGUL SYLLABLE DDYEG..HANGUL SYLLABLE DDYEH
> +B611..B62B    ; LVT # Lo  [27] HANGUL SYLLABLE DDOG..HANGUL SYLLABLE DDOH
> +B62D..B647    ; LVT # Lo  [27] HANGUL SYLLABLE DDWAG..HANGUL SYLLABLE DDWAH
> +B649..B663    ; LVT # Lo  [27] HANGUL SYLLABLE DDWAEG..HANGUL SYLLABLE DDWAEH
> +B665..B67F    ; LVT # Lo  [27] HANGUL SYLLABLE DDOEG..HANGUL SYLLABLE DDOEH
> +B681..B69B    ; LVT # Lo  [27] HANGUL SYLLABLE DDYOG..HANGUL SYLLABLE DDYOH
> +B69D..B6B7    ; LVT # Lo  [27] HANGUL SYLLABLE DDUG..HANGUL SYLLABLE DDUH
> +B6B9..B6D3    ; LVT # Lo  [27] HANGUL SYLLABLE DDWEOG..HANGUL SYLLABLE DDWEOH
> +B6D5..B6EF    ; LVT # Lo  [27] HANGUL SYLLABLE DDWEG..HANGUL SYLLABLE DDWEH
> +B6F1..B70B    ; LVT # Lo  [27] HANGUL SYLLABLE DDWIG..HANGUL SYLLABLE DDWIH
> +B70D..B727    ; LVT # Lo  [27] HANGUL SYLLABLE DDYUG..HANGUL SYLLABLE DDYUH
> +B729..B743    ; LVT # Lo  [27] HANGUL SYLLABLE DDEUG..HANGUL SYLLABLE DDEUH
> +B745..B75F    ; LVT # Lo  [27] HANGUL SYLLABLE DDYIG..HANGUL SYLLABLE DDYIH
> +B761..B77B    ; LVT # Lo  [27] HANGUL SYLLABLE DDIG..HANGUL SYLLABLE DDIH
> +B77D..B797    ; LVT # Lo  [27] HANGUL SYLLABLE RAG..HANGUL SYLLABLE RAH
> +B799..B7B3    ; LVT # Lo  [27] HANGUL SYLLABLE RAEG..HANGUL SYLLABLE RAEH
> +B7B5..B7CF    ; LVT # Lo  [27] HANGUL SYLLABLE RYAG..HANGUL SYLLABLE RYAH
> +B7D1..B7EB    ; LVT # Lo  [27] HANGUL SYLLABLE RYAEG..HANGUL SYLLABLE RYAEH
> +B7ED..B807    ; LVT # Lo  [27] HANGUL SYLLABLE REOG..HANGUL SYLLABLE REOH
> +B809..B823    ; LVT # Lo  [27] HANGUL SYLLABLE REG..HANGUL SYLLABLE REH
> +B825..B83F    ; LVT # Lo  [27] HANGUL SYLLABLE RYEOG..HANGUL SYLLABLE RYEOH
> +B841..B85B    ; LVT # Lo  [27] HANGUL SYLLABLE RYEG..HANGUL SYLLABLE RYEH
> +B85D..B877    ; LVT # Lo  [27] HANGUL SYLLABLE ROG..HANGUL SYLLABLE ROH
> +B879..B893    ; LVT # Lo  [27] HANGUL SYLLABLE RWAG..HANGUL SYLLABLE RWAH
> +B895..B8AF    ; LVT # Lo  [27] HANGUL SYLLABLE RWAEG..HANGUL SYLLABLE RWAEH
> +B8B1..B8CB    ; LVT # Lo  [27] HANGUL SYLLABLE ROEG..HANGUL SYLLABLE ROEH
> +B8CD..B8E7    ; LVT # Lo  [27] HANGUL SYLLABLE RYOG..HANGUL SYLLABLE RYOH
> +B8E9..B903    ; LVT # Lo  [27] HANGUL SYLLABLE RUG..HANGUL SYLLABLE RUH
> +B905..B91F    ; LVT # Lo  [27] HANGUL SYLLABLE RWEOG..HANGUL SYLLABLE RWEOH
> +B921..B93B    ; LVT # Lo  [27] HANGUL SYLLABLE RWEG..HANGUL SYLLABLE RWEH
> +B93D..B957    ; LVT # Lo  [27] HANGUL SYLLABLE RWIG..HANGUL SYLLABLE RWIH
> +B959..B973    ; LVT # Lo  [27] HANGUL SYLLABLE RYUG..HANGUL SYLLABLE RYUH
> +B975..B98F    ; LVT # Lo  [27] HANGUL SYLLABLE REUG..HANGUL SYLLABLE REUH
> +B991..B9AB    ; LVT # Lo  [27] HANGUL SYLLABLE RYIG..HANGUL SYLLABLE RYIH
> +B9AD..B9C7    ; LVT # Lo  [27] HANGUL SYLLABLE RIG..HANGUL SYLLABLE RIH
> +B9C9..B9E3    ; LVT # Lo  [27] HANGUL SYLLABLE MAG..HANGUL SYLLABLE MAH
> +B9E5..B9FF    ; LVT # Lo  [27] HANGUL SYLLABLE MAEG..HANGUL SYLLABLE MAEH
> +BA01..BA1B    ; LVT # Lo  [27] HANGUL SYLLABLE MYAG..HANGUL SYLLABLE MYAH
> +BA1D..BA37    ; LVT # Lo  [27] HANGUL SYLLABLE MYAEG..HANGUL SYLLABLE MYAEH
> +BA39..BA53    ; LVT # Lo  [27] HANGUL SYLLABLE MEOG..HANGUL SYLLABLE MEOH
> +BA55..BA6F    ; LVT # Lo  [27] HANGUL SYLLABLE MEG..HANGUL SYLLABLE MEH
> +BA71..BA8B    ; LVT # Lo  [27] HANGUL SYLLABLE MYEOG..HANGUL SYLLABLE MYEOH
> +BA8D..BAA7    ; LVT # Lo  [27] HANGUL SYLLABLE MYEG..HANGUL SYLLABLE MYEH
> +BAA9..BAC3    ; LVT # Lo  [27] HANGUL SYLLABLE MOG..HANGUL SYLLABLE MOH
> +BAC5..BADF    ; LVT # Lo  [27] HANGUL SYLLABLE MWAG..HANGUL SYLLABLE MWAH
> +BAE1..BAFB    ; LVT # Lo  [27] HANGUL SYLLABLE MWAEG..HANGUL SYLLABLE MWAEH
> +BAFD..BB17    ; LVT # Lo  [27] HANGUL SYLLABLE MOEG..HANGUL SYLLABLE MOEH
> +BB19..BB33    ; LVT # Lo  [27] HANGUL SYLLABLE MYOG..HANGUL SYLLABLE MYOH
> +BB35..BB4F    ; LVT # Lo  [27] HANGUL SYLLABLE MUG..HANGUL SYLLABLE MUH
> +BB51..BB6B    ; LVT # Lo  [27] HANGUL SYLLABLE MWEOG..HANGUL SYLLABLE MWEOH
> +BB6D..BB87    ; LVT # Lo  [27] HANGUL SYLLABLE MWEG..HANGUL SYLLABLE MWEH
> +BB89..BBA3    ; LVT # Lo  [27] HANGUL SYLLABLE MWIG..HANGUL SYLLABLE MWIH
> +BBA5..BBBF    ; LVT # Lo  [27] HANGUL SYLLABLE MYUG..HANGUL SYLLABLE MYUH
> +BBC1..BBDB    ; LVT # Lo  [27] HANGUL SYLLABLE MEUG..HANGUL SYLLABLE MEUH
> +BBDD..BBF7    ; LVT # Lo  [27] HANGUL SYLLABLE MYIG..HANGUL SYLLABLE MYIH
> +BBF9..BC13    ; LVT # Lo  [27] HANGUL SYLLABLE MIG..HANGUL SYLLABLE MIH
> +BC15..BC2F    ; LVT # Lo  [27] HANGUL SYLLABLE BAG..HANGUL SYLLABLE BAH
> +BC31..BC4B    ; LVT # Lo  [27] HANGUL SYLLABLE BAEG..HANGUL SYLLABLE BAEH
> +BC4D..BC67    ; LVT # Lo  [27] HANGUL SYLLABLE BYAG..HANGUL SYLLABLE BYAH
> +BC69..BC83    ; LVT # Lo  [27] HANGUL SYLLABLE BYAEG..HANGUL SYLLABLE BYAEH
> +BC85..BC9F    ; LVT # Lo  [27] HANGUL SYLLABLE BEOG..HANGUL SYLLABLE BEOH
> +BCA1..BCBB    ; LVT # Lo  [27] HANGUL SYLLABLE BEG..HANGUL SYLLABLE BEH
> +BCBD..BCD7    ; LVT # Lo  [27] HANGUL SYLLABLE BYEOG..HANGUL SYLLABLE BYEOH
> +BCD9..BCF3    ; LVT # Lo  [27] HANGUL SYLLABLE BYEG..HANGUL SYLLABLE BYEH
> +BCF5..BD0F    ; LVT # Lo  [27] HANGUL SYLLABLE BOG..HANGUL SYLLABLE BOH
> +BD11..BD2B    ; LVT # Lo  [27] HANGUL SYLLABLE BWAG..HANGUL SYLLABLE BWAH
> +BD2D..BD47    ; LVT # Lo  [27] HANGUL SYLLABLE BWAEG..HANGUL SYLLABLE BWAEH
> +BD49..BD63    ; LVT # Lo  [27] HANGUL SYLLABLE BOEG..HANGUL SYLLABLE BOEH
> +BD65..BD7F    ; LVT # Lo  [27] HANGUL SYLLABLE BYOG..HANGUL SYLLABLE BYOH
> +BD81..BD9B    ; LVT # Lo  [27] HANGUL SYLLABLE BUG..HANGUL SYLLABLE BUH
> +BD9D..BDB7    ; LVT # Lo  [27] HANGUL SYLLABLE BWEOG..HANGUL SYLLABLE BWEOH
> +BDB9..BDD3    ; LVT # Lo  [27] HANGUL SYLLABLE BWEG..HANGUL SYLLABLE BWEH
> +BDD5..BDEF    ; LVT # Lo  [27] HANGUL SYLLABLE BWIG..HANGUL SYLLABLE BWIH
> +BDF1..BE0B    ; LVT # Lo  [27] HANGUL SYLLABLE BYUG..HANGUL SYLLABLE BYUH
> +BE0D..BE27    ; LVT # Lo  [27] HANGUL SYLLABLE BEUG..HANGUL SYLLABLE BEUH
> +BE29..BE43    ; LVT # Lo  [27] HANGUL SYLLABLE BYIG..HANGUL SYLLABLE BYIH
> +BE45..BE5F    ; LVT # Lo  [27] HANGUL SYLLABLE BIG..HANGUL SYLLABLE BIH
> +BE61..BE7B    ; LVT # Lo  [27] HANGUL SYLLABLE BBAG..HANGUL SYLLABLE BBAH
> +BE7D..BE97    ; LVT # Lo  [27] HANGUL SYLLABLE BBAEG..HANGUL SYLLABLE BBAEH
> +BE99..BEB3    ; LVT # Lo  [27] HANGUL SYLLABLE BBYAG..HANGUL SYLLABLE BBYAH
> +BEB5..BECF    ; LVT # Lo  [27] HANGUL SYLLABLE BBYAEG..HANGUL SYLLABLE BBYAEH
> +BED1..BEEB    ; LVT # Lo  [27] HANGUL SYLLABLE BBEOG..HANGUL SYLLABLE BBEOH
> +BEED..BF07    ; LVT # Lo  [27] HANGUL SYLLABLE BBEG..HANGUL SYLLABLE BBEH
> +BF09..BF23    ; LVT # Lo  [27] HANGUL SYLLABLE BBYEOG..HANGUL SYLLABLE BBYEOH
> +BF25..BF3F    ; LVT # Lo  [27] HANGUL SYLLABLE BBYEG..HANGUL SYLLABLE BBYEH
> +BF41..BF5B    ; LVT # Lo  [27] HANGUL SYLLABLE BBOG..HANGUL SYLLABLE BBOH
> +BF5D..BF77    ; LVT # Lo  [27] HANGUL SYLLABLE BBWAG..HANGUL SYLLABLE BBWAH
> +BF79..BF93    ; LVT # Lo  [27] HANGUL SYLLABLE BBWAEG..HANGUL SYLLABLE BBWAEH
> +BF95..BFAF    ; LVT # Lo  [27] HANGUL SYLLABLE BBOEG..HANGUL SYLLABLE BBOEH
> +BFB1..BFCB    ; LVT # Lo  [27] HANGUL SYLLABLE BBYOG..HANGUL SYLLABLE BBYOH
> +BFCD..BFE7    ; LVT # Lo  [27] HANGUL SYLLABLE BBUG..HANGUL SYLLABLE BBUH
> +BFE9..C003    ; LVT # Lo  [27] HANGUL SYLLABLE BBWEOG..HANGUL SYLLABLE BBWEOH
> +C005..C01F    ; LVT # Lo  [27] HANGUL SYLLABLE BBWEG..HANGUL SYLLABLE BBWEH
> +C021..C03B    ; LVT # Lo  [27] HANGUL SYLLABLE BBWIG..HANGUL SYLLABLE BBWIH
> +C03D..C057    ; LVT # Lo  [27] HANGUL SYLLABLE BBYUG..HANGUL SYLLABLE BBYUH
> +C059..C073    ; LVT # Lo  [27] HANGUL SYLLABLE BBEUG..HANGUL SYLLABLE BBEUH
> +C075..C08F    ; LVT # Lo  [27] HANGUL SYLLABLE BBYIG..HANGUL SYLLABLE BBYIH
> +C091..C0AB    ; LVT # Lo  [27] HANGUL SYLLABLE BBIG..HANGUL SYLLABLE BBIH
> +C0AD..C0C7    ; LVT # Lo  [27] HANGUL SYLLABLE SAG..HANGUL SYLLABLE SAH
> +C0C9..C0E3    ; LVT # Lo  [27] HANGUL SYLLABLE SAEG..HANGUL SYLLABLE SAEH
> +C0E5..C0FF    ; LVT # Lo  [27] HANGUL SYLLABLE SYAG..HANGUL SYLLABLE SYAH
> +C101..C11B    ; LVT # Lo  [27] HANGUL SYLLABLE SYAEG..HANGUL SYLLABLE SYAEH
> +C11D..C137    ; LVT # Lo  [27] HANGUL SYLLABLE SEOG..HANGUL SYLLABLE SEOH
> +C139..C153    ; LVT # Lo  [27] HANGUL SYLLABLE SEG..HANGUL SYLLABLE SEH
> +C155..C16F    ; LVT # Lo  [27] HANGUL SYLLABLE SYEOG..HANGUL SYLLABLE SYEOH
> +C171..C18B    ; LVT # Lo  [27] HANGUL SYLLABLE SYEG..HANGUL SYLLABLE SYEH
> +C18D..C1A7    ; LVT # Lo  [27] HANGUL SYLLABLE SOG..HANGUL SYLLABLE SOH
> +C1A9..C1C3    ; LVT # Lo  [27] HANGUL SYLLABLE SWAG..HANGUL SYLLABLE SWAH
> +C1C5..C1DF    ; LVT # Lo  [27] HANGUL SYLLABLE SWAEG..HANGUL SYLLABLE SWAEH
> +C1E1..C1FB    ; LVT # Lo  [27] HANGUL SYLLABLE SOEG..HANGUL SYLLABLE SOEH
> +C1FD..C217    ; LVT # Lo  [27] HANGUL SYLLABLE SYOG..HANGUL SYLLABLE SYOH
> +C219..C233    ; LVT # Lo  [27] HANGUL SYLLABLE SUG..HANGUL SYLLABLE SUH
> +C235..C24F    ; LVT # Lo  [27] HANGUL SYLLABLE SWEOG..HANGUL SYLLABLE SWEOH
> +C251..C26B    ; LVT # Lo  [27] HANGUL SYLLABLE SWEG..HANGUL SYLLABLE SWEH
> +C26D..C287    ; LVT # Lo  [27] HANGUL SYLLABLE SWIG..HANGUL SYLLABLE SWIH
> +C289..C2A3    ; LVT # Lo  [27] HANGUL SYLLABLE SYUG..HANGUL SYLLABLE SYUH
> +C2A5..C2BF    ; LVT # Lo  [27] HANGUL SYLLABLE SEUG..HANGUL SYLLABLE SEUH
> +C2C1..C2DB    ; LVT # Lo  [27] HANGUL SYLLABLE SYIG..HANGUL SYLLABLE SYIH
> +C2DD..C2F7    ; LVT # Lo  [27] HANGUL SYLLABLE SIG..HANGUL SYLLABLE SIH
> +C2F9..C313    ; LVT # Lo  [27] HANGUL SYLLABLE SSAG..HANGUL SYLLABLE SSAH
> +C315..C32F    ; LVT # Lo  [27] HANGUL SYLLABLE SSAEG..HANGUL SYLLABLE SSAEH
> +C331..C34B    ; LVT # Lo  [27] HANGUL SYLLABLE SSYAG..HANGUL SYLLABLE SSYAH
> +C34D..C367    ; LVT # Lo  [27] HANGUL SYLLABLE SSYAEG..HANGUL SYLLABLE SSYAEH
> +C369..C383    ; LVT # Lo  [27] HANGUL SYLLABLE SSEOG..HANGUL SYLLABLE SSEOH
> +C385..C39F    ; LVT # Lo  [27] HANGUL SYLLABLE SSEG..HANGUL SYLLABLE SSEH
> +C3A1..C3BB    ; LVT # Lo  [27] HANGUL SYLLABLE SSYEOG..HANGUL SYLLABLE SSYEOH
> +C3BD..C3D7    ; LVT # Lo  [27] HANGUL SYLLABLE SSYEG..HANGUL SYLLABLE SSYEH
> +C3D9..C3F3    ; LVT # Lo  [27] HANGUL SYLLABLE SSOG..HANGUL SYLLABLE SSOH
> +C3F5..C40F    ; LVT # Lo  [27] HANGUL SYLLABLE SSWAG..HANGUL SYLLABLE SSWAH
> +C411..C42B    ; LVT # Lo  [27] HANGUL SYLLABLE SSWAEG..HANGUL SYLLABLE SSWAEH
> +C42D..C447    ; LVT # Lo  [27] HANGUL SYLLABLE SSOEG..HANGUL SYLLABLE SSOEH
> +C449..C463    ; LVT # Lo  [27] HANGUL SYLLABLE SSYOG..HANGUL SYLLABLE SSYOH
> +C465..C47F    ; LVT # Lo  [27] HANGUL SYLLABLE SSUG..HANGUL SYLLABLE SSUH
> +C481..C49B    ; LVT # Lo  [27] HANGUL SYLLABLE SSWEOG..HANGUL SYLLABLE SSWEOH
> +C49D..C4B7    ; LVT # Lo  [27] HANGUL SYLLABLE SSWEG..HANGUL SYLLABLE SSWEH
> +C4B9..C4D3    ; LVT # Lo  [27] HANGUL SYLLABLE SSWIG..HANGUL SYLLABLE SSWIH
> +C4D5..C4EF    ; LVT # Lo  [27] HANGUL SYLLABLE SSYUG..HANGUL SYLLABLE SSYUH
> +C4F1..C50B    ; LVT # Lo  [27] HANGUL SYLLABLE SSEUG..HANGUL SYLLABLE SSEUH
> +C50D..C527    ; LVT # Lo  [27] HANGUL SYLLABLE SSYIG..HANGUL SYLLABLE SSYIH
> +C529..C543    ; LVT # Lo  [27] HANGUL SYLLABLE SSIG..HANGUL SYLLABLE SSIH
> +C545..C55F    ; LVT # Lo  [27] HANGUL SYLLABLE AG..HANGUL SYLLABLE AH
> +C561..C57B    ; LVT # Lo  [27] HANGUL SYLLABLE AEG..HANGUL SYLLABLE AEH
> +C57D..C597    ; LVT # Lo  [27] HANGUL SYLLABLE YAG..HANGUL SYLLABLE YAH
> +C599..C5B3    ; LVT # Lo  [27] HANGUL SYLLABLE YAEG..HANGUL SYLLABLE YAEH
> +C5B5..C5CF    ; LVT # Lo  [27] HANGUL SYLLABLE EOG..HANGUL SYLLABLE EOH
> +C5D1..C5EB    ; LVT # Lo  [27] HANGUL SYLLABLE EG..HANGUL SYLLABLE EH
> +C5ED..C607    ; LVT # Lo  [27] HANGUL SYLLABLE YEOG..HANGUL SYLLABLE YEOH
> +C609..C623    ; LVT # Lo  [27] HANGUL SYLLABLE YEG..HANGUL SYLLABLE YEH
> +C625..C63F    ; LVT # Lo  [27] HANGUL SYLLABLE OG..HANGUL SYLLABLE OH
> +C641..C65B    ; LVT # Lo  [27] HANGUL SYLLABLE WAG..HANGUL SYLLABLE WAH
> +C65D..C677    ; LVT # Lo  [27] HANGUL SYLLABLE WAEG..HANGUL SYLLABLE WAEH
> +C679..C693    ; LVT # Lo  [27] HANGUL SYLLABLE OEG..HANGUL SYLLABLE OEH
> +C695..C6AF    ; LVT # Lo  [27] HANGUL SYLLABLE YOG..HANGUL SYLLABLE YOH
> +C6B1..C6CB    ; LVT # Lo  [27] HANGUL SYLLABLE UG..HANGUL SYLLABLE UH
> +C6CD..C6E7    ; LVT # Lo  [27] HANGUL SYLLABLE WEOG..HANGUL SYLLABLE WEOH
> +C6E9..C703    ; LVT # Lo  [27] HANGUL SYLLABLE WEG..HANGUL SYLLABLE WEH
> +C705..C71F    ; LVT # Lo  [27] HANGUL SYLLABLE WIG..HANGUL SYLLABLE WIH
> +C721..C73B    ; LVT # Lo  [27] HANGUL SYLLABLE YUG..HANGUL SYLLABLE YUH
> +C73D..C757    ; LVT # Lo  [27] HANGUL SYLLABLE EUG..HANGUL SYLLABLE EUH
> +C759..C773    ; LVT # Lo  [27] HANGUL SYLLABLE YIG..HANGUL SYLLABLE YIH
> +C775..C78F    ; LVT # Lo  [27] HANGUL SYLLABLE IG..HANGUL SYLLABLE IH
> +C791..C7AB    ; LVT # Lo  [27] HANGUL SYLLABLE JAG..HANGUL SYLLABLE JAH
> +C7AD..C7C7    ; LVT # Lo  [27] HANGUL SYLLABLE JAEG..HANGUL SYLLABLE JAEH
> +C7C9..C7E3    ; LVT # Lo  [27] HANGUL SYLLABLE JYAG..HANGUL SYLLABLE JYAH
> +C7E5..C7FF    ; LVT # Lo  [27] HANGUL SYLLABLE JYAEG..HANGUL SYLLABLE JYAEH
> +C801..C81B    ; LVT # Lo  [27] HANGUL SYLLABLE JEOG..HANGUL SYLLABLE JEOH
> +C81D..C837    ; LVT # Lo  [27] HANGUL SYLLABLE JEG..HANGUL SYLLABLE JEH
> +C839..C853    ; LVT # Lo  [27] HANGUL SYLLABLE JYEOG..HANGUL SYLLABLE JYEOH
> +C855..C86F    ; LVT # Lo  [27] HANGUL SYLLABLE JYEG..HANGUL SYLLABLE JYEH
> +C871..C88B    ; LVT # Lo  [27] HANGUL SYLLABLE JOG..HANGUL SYLLABLE JOH
> +C88D..C8A7    ; LVT # Lo  [27] HANGUL SYLLABLE JWAG..HANGUL SYLLABLE JWAH
> +C8A9..C8C3    ; LVT # Lo  [27] HANGUL SYLLABLE JWAEG..HANGUL SYLLABLE JWAEH
> +C8C5..C8DF    ; LVT # Lo  [27] HANGUL SYLLABLE JOEG..HANGUL SYLLABLE JOEH
> +C8E1..C8FB    ; LVT # Lo  [27] HANGUL SYLLABLE JYOG..HANGUL SYLLABLE JYOH
> +C8FD..C917    ; LVT # Lo  [27] HANGUL SYLLABLE JUG..HANGUL SYLLABLE JUH
> +C919..C933    ; LVT # Lo  [27] HANGUL SYLLABLE JWEOG..HANGUL SYLLABLE JWEOH
> +C935..C94F    ; LVT # Lo  [27] HANGUL SYLLABLE JWEG..HANGUL SYLLABLE JWEH
> +C951..C96B    ; LVT # Lo  [27] HANGUL SYLLABLE JWIG..HANGUL SYLLABLE JWIH
> +C96D..C987    ; LVT # Lo  [27] HANGUL SYLLABLE JYUG..HANGUL SYLLABLE JYUH
> +C989..C9A3    ; LVT # Lo  [27] HANGUL SYLLABLE JEUG..HANGUL SYLLABLE JEUH
> +C9A5..C9BF    ; LVT # Lo  [27] HANGUL SYLLABLE JYIG..HANGUL SYLLABLE JYIH
> +C9C1..C9DB    ; LVT # Lo  [27] HANGUL SYLLABLE JIG..HANGUL SYLLABLE JIH
> +C9DD..C9F7    ; LVT # Lo  [27] HANGUL SYLLABLE JJAG..HANGUL SYLLABLE JJAH
> +C9F9..CA13    ; LVT # Lo  [27] HANGUL SYLLABLE JJAEG..HANGUL SYLLABLE JJAEH
> +CA15..CA2F    ; LVT # Lo  [27] HANGUL SYLLABLE JJYAG..HANGUL SYLLABLE JJYAH
> +CA31..CA4B    ; LVT # Lo  [27] HANGUL SYLLABLE JJYAEG..HANGUL SYLLABLE JJYAEH
> +CA4D..CA67    ; LVT # Lo  [27] HANGUL SYLLABLE JJEOG..HANGUL SYLLABLE JJEOH
> +CA69..CA83    ; LVT # Lo  [27] HANGUL SYLLABLE JJEG..HANGUL SYLLABLE JJEH
> +CA85..CA9F    ; LVT # Lo  [27] HANGUL SYLLABLE JJYEOG..HANGUL SYLLABLE JJYEOH
> +CAA1..CABB    ; LVT # Lo  [27] HANGUL SYLLABLE JJYEG..HANGUL SYLLABLE JJYEH
> +CABD..CAD7    ; LVT # Lo  [27] HANGUL SYLLABLE JJOG..HANGUL SYLLABLE JJOH
> +CAD9..CAF3    ; LVT # Lo  [27] HANGUL SYLLABLE JJWAG..HANGUL SYLLABLE JJWAH
> +CAF5..CB0F    ; LVT # Lo  [27] HANGUL SYLLABLE JJWAEG..HANGUL SYLLABLE JJWAEH
> +CB11..CB2B    ; LVT # Lo  [27] HANGUL SYLLABLE JJOEG..HANGUL SYLLABLE JJOEH
> +CB2D..CB47    ; LVT # Lo  [27] HANGUL SYLLABLE JJYOG..HANGUL SYLLABLE JJYOH
> +CB49..CB63    ; LVT # Lo  [27] HANGUL SYLLABLE JJUG..HANGUL SYLLABLE JJUH
> +CB65..CB7F    ; LVT # Lo  [27] HANGUL SYLLABLE JJWEOG..HANGUL SYLLABLE JJWEOH
> +CB81..CB9B    ; LVT # Lo  [27] HANGUL SYLLABLE JJWEG..HANGUL SYLLABLE JJWEH
> +CB9D..CBB7    ; LVT # Lo  [27] HANGUL SYLLABLE JJWIG..HANGUL SYLLABLE JJWIH
> +CBB9..CBD3    ; LVT # Lo  [27] HANGUL SYLLABLE JJYUG..HANGUL SYLLABLE JJYUH
> +CBD5..CBEF    ; LVT # Lo  [27] HANGUL SYLLABLE JJEUG..HANGUL SYLLABLE JJEUH
> +CBF1..CC0B    ; LVT # Lo  [27] HANGUL SYLLABLE JJYIG..HANGUL SYLLABLE JJYIH
> +CC0D..CC27    ; LVT # Lo  [27] HANGUL SYLLABLE JJIG..HANGUL SYLLABLE JJIH
> +CC29..CC43    ; LVT # Lo  [27] HANGUL SYLLABLE CAG..HANGUL SYLLABLE CAH
> +CC45..CC5F    ; LVT # Lo  [27] HANGUL SYLLABLE CAEG..HANGUL SYLLABLE CAEH
> +CC61..CC7B    ; LVT # Lo  [27] HANGUL SYLLABLE CYAG..HANGUL SYLLABLE CYAH
> +CC7D..CC97    ; LVT # Lo  [27] HANGUL SYLLABLE CYAEG..HANGUL SYLLABLE CYAEH
> +CC99..CCB3    ; LVT # Lo  [27] HANGUL SYLLABLE CEOG..HANGUL SYLLABLE CEOH
> +CCB5..CCCF    ; LVT # Lo  [27] HANGUL SYLLABLE CEG..HANGUL SYLLABLE CEH
> +CCD1..CCEB    ; LVT # Lo  [27] HANGUL SYLLABLE CYEOG..HANGUL SYLLABLE CYEOH
> +CCED..CD07    ; LVT # Lo  [27] HANGUL SYLLABLE CYEG..HANGUL SYLLABLE CYEH
> +CD09..CD23    ; LVT # Lo  [27] HANGUL SYLLABLE COG..HANGUL SYLLABLE COH
> +CD25..CD3F    ; LVT # Lo  [27] HANGUL SYLLABLE CWAG..HANGUL SYLLABLE CWAH
> +CD41..CD5B    ; LVT # Lo  [27] HANGUL SYLLABLE CWAEG..HANGUL SYLLABLE CWAEH
> +CD5D..CD77    ; LVT # Lo  [27] HANGUL SYLLABLE COEG..HANGUL SYLLABLE COEH
> +CD79..CD93    ; LVT # Lo  [27] HANGUL SYLLABLE CYOG..HANGUL SYLLABLE CYOH
> +CD95..CDAF    ; LVT # Lo  [27] HANGUL SYLLABLE CUG..HANGUL SYLLABLE CUH
> +CDB1..CDCB    ; LVT # Lo  [27] HANGUL SYLLABLE CWEOG..HANGUL SYLLABLE CWEOH
> +CDCD..CDE7    ; LVT # Lo  [27] HANGUL SYLLABLE CWEG..HANGUL SYLLABLE CWEH
> +CDE9..CE03    ; LVT # Lo  [27] HANGUL SYLLABLE CWIG..HANGUL SYLLABLE CWIH
> +CE05..CE1F    ; LVT # Lo  [27] HANGUL SYLLABLE CYUG..HANGUL SYLLABLE CYUH
> +CE21..CE3B    ; LVT # Lo  [27] HANGUL SYLLABLE CEUG..HANGUL SYLLABLE CEUH
> +CE3D..CE57    ; LVT # Lo  [27] HANGUL SYLLABLE CYIG..HANGUL SYLLABLE CYIH
> +CE59..CE73    ; LVT # Lo  [27] HANGUL SYLLABLE CIG..HANGUL SYLLABLE CIH
> +CE75..CE8F    ; LVT # Lo  [27] HANGUL SYLLABLE KAG..HANGUL SYLLABLE KAH
> +CE91..CEAB    ; LVT # Lo  [27] HANGUL SYLLABLE KAEG..HANGUL SYLLABLE KAEH
> +CEAD..CEC7    ; LVT # Lo  [27] HANGUL SYLLABLE KYAG..HANGUL SYLLABLE KYAH
> +CEC9..CEE3    ; LVT # Lo  [27] HANGUL SYLLABLE KYAEG..HANGUL SYLLABLE KYAEH
> +CEE5..CEFF    ; LVT # Lo  [27] HANGUL SYLLABLE KEOG..HANGUL SYLLABLE KEOH
> +CF01..CF1B    ; LVT # Lo  [27] HANGUL SYLLABLE KEG..HANGUL SYLLABLE KEH
> +CF1D..CF37    ; LVT # Lo  [27] HANGUL SYLLABLE KYEOG..HANGUL SYLLABLE KYEOH
> +CF39..CF53    ; LVT # Lo  [27] HANGUL SYLLABLE KYEG..HANGUL SYLLABLE KYEH
> +CF55..CF6F    ; LVT # Lo  [27] HANGUL SYLLABLE KOG..HANGUL SYLLABLE KOH
> +CF71..CF8B    ; LVT # Lo  [27] HANGUL SYLLABLE KWAG..HANGUL SYLLABLE KWAH
> +CF8D..CFA7    ; LVT # Lo  [27] HANGUL SYLLABLE KWAEG..HANGUL SYLLABLE KWAEH
> +CFA9..CFC3    ; LVT # Lo  [27] HANGUL SYLLABLE KOEG..HANGUL SYLLABLE KOEH
> +CFC5..CFDF    ; LVT # Lo  [27] HANGUL SYLLABLE KYOG..HANGUL SYLLABLE KYOH
> +CFE1..CFFB    ; LVT # Lo  [27] HANGUL SYLLABLE KUG..HANGUL SYLLABLE KUH
> +CFFD..D017    ; LVT # Lo  [27] HANGUL SYLLABLE KWEOG..HANGUL SYLLABLE KWEOH
> +D019..D033    ; LVT # Lo  [27] HANGUL SYLLABLE KWEG..HANGUL SYLLABLE KWEH
> +D035..D04F    ; LVT # Lo  [27] HANGUL SYLLABLE KWIG..HANGUL SYLLABLE KWIH
> +D051..D06B    ; LVT # Lo  [27] HANGUL SYLLABLE KYUG..HANGUL SYLLABLE KYUH
> +D06D..D087    ; LVT # Lo  [27] HANGUL SYLLABLE KEUG..HANGUL SYLLABLE KEUH
> +D089..D0A3    ; LVT # Lo  [27] HANGUL SYLLABLE KYIG..HANGUL SYLLABLE KYIH
> +D0A5..D0BF    ; LVT # Lo  [27] HANGUL SYLLABLE KIG..HANGUL SYLLABLE KIH
> +D0C1..D0DB    ; LVT # Lo  [27] HANGUL SYLLABLE TAG..HANGUL SYLLABLE TAH
> +D0DD..D0F7    ; LVT # Lo  [27] HANGUL SYLLABLE TAEG..HANGUL SYLLABLE TAEH
> +D0F9..D113    ; LVT # Lo  [27] HANGUL SYLLABLE TYAG..HANGUL SYLLABLE TYAH
> +D115..D12F    ; LVT # Lo  [27] HANGUL SYLLABLE TYAEG..HANGUL SYLLABLE TYAEH
> +D131..D14B    ; LVT # Lo  [27] HANGUL SYLLABLE TEOG..HANGUL SYLLABLE TEOH
> +D14D..D167    ; LVT # Lo  [27] HANGUL SYLLABLE TEG..HANGUL SYLLABLE TEH
> +D169..D183    ; LVT # Lo  [27] HANGUL SYLLABLE TYEOG..HANGUL SYLLABLE TYEOH
> +D185..D19F    ; LVT # Lo  [27] HANGUL SYLLABLE TYEG..HANGUL SYLLABLE TYEH
> +D1A1..D1BB    ; LVT # Lo  [27] HANGUL SYLLABLE TOG..HANGUL SYLLABLE TOH
> +D1BD..D1D7    ; LVT # Lo  [27] HANGUL SYLLABLE TWAG..HANGUL SYLLABLE TWAH
> +D1D9..D1F3    ; LVT # Lo  [27] HANGUL SYLLABLE TWAEG..HANGUL SYLLABLE TWAEH
> +D1F5..D20F    ; LVT # Lo  [27] HANGUL SYLLABLE TOEG..HANGUL SYLLABLE TOEH
> +D211..D22B    ; LVT # Lo  [27] HANGUL SYLLABLE TYOG..HANGUL SYLLABLE TYOH
> +D22D..D247    ; LVT # Lo  [27] HANGUL SYLLABLE TUG..HANGUL SYLLABLE TUH
> +D249..D263    ; LVT # Lo  [27] HANGUL SYLLABLE TWEOG..HANGUL SYLLABLE TWEOH
> +D265..D27F    ; LVT # Lo  [27] HANGUL SYLLABLE TWEG..HANGUL SYLLABLE TWEH
> +D281..D29B    ; LVT # Lo  [27] HANGUL SYLLABLE TWIG..HANGUL SYLLABLE TWIH
> +D29D..D2B7    ; LVT # Lo  [27] HANGUL SYLLABLE TYUG..HANGUL SYLLABLE TYUH
> +D2B9..D2D3    ; LVT # Lo  [27] HANGUL SYLLABLE TEUG..HANGUL SYLLABLE TEUH
> +D2D5..D2EF    ; LVT # Lo  [27] HANGUL SYLLABLE TYIG..HANGUL SYLLABLE TYIH
> +D2F1..D30B    ; LVT # Lo  [27] HANGUL SYLLABLE TIG..HANGUL SYLLABLE TIH
> +D30D..D327    ; LVT # Lo  [27] HANGUL SYLLABLE PAG..HANGUL SYLLABLE PAH
> +D329..D343    ; LVT # Lo  [27] HANGUL SYLLABLE PAEG..HANGUL SYLLABLE PAEH
> +D345..D35F    ; LVT # Lo  [27] HANGUL SYLLABLE PYAG..HANGUL SYLLABLE PYAH
> +D361..D37B    ; LVT # Lo  [27] HANGUL SYLLABLE PYAEG..HANGUL SYLLABLE PYAEH
> +D37D..D397    ; LVT # Lo  [27] HANGUL SYLLABLE PEOG..HANGUL SYLLABLE PEOH
> +D399..D3B3    ; LVT # Lo  [27] HANGUL SYLLABLE PEG..HANGUL SYLLABLE PEH
> +D3B5..D3CF    ; LVT # Lo  [27] HANGUL SYLLABLE PYEOG..HANGUL SYLLABLE PYEOH
> +D3D1..D3EB    ; LVT # Lo  [27] HANGUL SYLLABLE PYEG..HANGUL SYLLABLE PYEH
> +D3ED..D407    ; LVT # Lo  [27] HANGUL SYLLABLE POG..HANGUL SYLLABLE POH
> +D409..D423    ; LVT # Lo  [27] HANGUL SYLLABLE PWAG..HANGUL SYLLABLE PWAH
> +D425..D43F    ; LVT # Lo  [27] HANGUL SYLLABLE PWAEG..HANGUL SYLLABLE PWAEH
> +D441..D45B    ; LVT # Lo  [27] HANGUL SYLLABLE POEG..HANGUL SYLLABLE POEH
> +D45D..D477    ; LVT # Lo  [27] HANGUL SYLLABLE PYOG..HANGUL SYLLABLE PYOH
> +D479..D493    ; LVT # Lo  [27] HANGUL SYLLABLE PUG..HANGUL SYLLABLE PUH
> +D495..D4AF    ; LVT # Lo  [27] HANGUL SYLLABLE PWEOG..HANGUL SYLLABLE PWEOH
> +D4B1..D4CB    ; LVT # Lo  [27] HANGUL SYLLABLE PWEG..HANGUL SYLLABLE PWEH
> +D4CD..D4E7    ; LVT # Lo  [27] HANGUL SYLLABLE PWIG..HANGUL SYLLABLE PWIH
> +D4E9..D503    ; LVT # Lo  [27] HANGUL SYLLABLE PYUG..HANGUL SYLLABLE PYUH
> +D505..D51F    ; LVT # Lo  [27] HANGUL SYLLABLE PEUG..HANGUL SYLLABLE PEUH
> +D521..D53B    ; LVT # Lo  [27] HANGUL SYLLABLE PYIG..HANGUL SYLLABLE PYIH
> +D53D..D557    ; LVT # Lo  [27] HANGUL SYLLABLE PIG..HANGUL SYLLABLE PIH
> +D559..D573    ; LVT # Lo  [27] HANGUL SYLLABLE HAG..HANGUL SYLLABLE HAH
> +D575..D58F    ; LVT # Lo  [27] HANGUL SYLLABLE HAEG..HANGUL SYLLABLE HAEH
> +D591..D5AB    ; LVT # Lo  [27] HANGUL SYLLABLE HYAG..HANGUL SYLLABLE HYAH
> +D5AD..D5C7    ; LVT # Lo  [27] HANGUL SYLLABLE HYAEG..HANGUL SYLLABLE HYAEH
> +D5C9..D5E3    ; LVT # Lo  [27] HANGUL SYLLABLE HEOG..HANGUL SYLLABLE HEOH
> +D5E5..D5FF    ; LVT # Lo  [27] HANGUL SYLLABLE HEG..HANGUL SYLLABLE HEH
> +D601..D61B    ; LVT # Lo  [27] HANGUL SYLLABLE HYEOG..HANGUL SYLLABLE HYEOH
> +D61D..D637    ; LVT # Lo  [27] HANGUL SYLLABLE HYEG..HANGUL SYLLABLE HYEH
> +D639..D653    ; LVT # Lo  [27] HANGUL SYLLABLE HOG..HANGUL SYLLABLE HOH
> +D655..D66F    ; LVT # Lo  [27] HANGUL SYLLABLE HWAG..HANGUL SYLLABLE HWAH
> +D671..D68B    ; LVT # Lo  [27] HANGUL SYLLABLE HWAEG..HANGUL SYLLABLE HWAEH
> +D68D..D6A7    ; LVT # Lo  [27] HANGUL SYLLABLE HOEG..HANGUL SYLLABLE HOEH
> +D6A9..D6C3    ; LVT # Lo  [27] HANGUL SYLLABLE HYOG..HANGUL SYLLABLE HYOH
> +D6C5..D6DF    ; LVT # Lo  [27] HANGUL SYLLABLE HUG..HANGUL SYLLABLE HUH
> +D6E1..D6FB    ; LVT # Lo  [27] HANGUL SYLLABLE HWEOG..HANGUL SYLLABLE HWEOH
> +D6FD..D717    ; LVT # Lo  [27] HANGUL SYLLABLE HWEG..HANGUL SYLLABLE HWEH
> +D719..D733    ; LVT # Lo  [27] HANGUL SYLLABLE HWIG..HANGUL SYLLABLE HWIH
> +D735..D74F    ; LVT # Lo  [27] HANGUL SYLLABLE HYUG..HANGUL SYLLABLE HYUH
> +D751..D76B    ; LVT # Lo  [27] HANGUL SYLLABLE HEUG..HANGUL SYLLABLE HEUH
> +D76D..D787    ; LVT # Lo  [27] HANGUL SYLLABLE HYIG..HANGUL SYLLABLE HYIH
> +D789..D7A3    ; LVT # Lo  [27] HANGUL SYLLABLE HIG..HANGUL SYLLABLE HIH
> +
> +# Total code points: 10773
> +
> +# ================================================
> +
> +200D          ; ZWJ # Cf       ZERO WIDTH JOINER
> +
> +# Total code points: 1
> +
> +# EOF
> diff --git a/contrib/unicode/gen_std_format_width.py b/contrib/unicode/gen_std_format_width.py
> new file mode 100755
> index 00000000000..b2f0c49598e
> --- /dev/null
> +++ b/contrib/unicode/gen_std_format_width.py
> @@ -0,0 +1,139 @@
> +#!/usr/bin/env python3
> +#
> +# Script to generate tables for libstdc++ std::format width estimation.
> +#
> +# This file is part of GCC.
> +#
> +# GCC is free software; you can redistribute it and/or modify it under
> +# the terms of the GNU General Public License as published by the Free
> +# Software Foundation; either version 3, or (at your option) any later
> +# version.
> +#
> +# GCC is distributed in the hope that it will be useful, but WITHOUT ANY
> +# WARRANTY; without even the implied warranty of MERCHANTABILITY or
> +# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> +# for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with GCC; see the file COPYING3.  If not see
> +# <http://www.gnu.org/licenses/>.
> +
> +import sys
> +import re
> +import math
> +
> +# By default treat every code point as having width 1.
> +widths = [1] * (1 + 0x10FFFF)
> +
> +# Process a code point value or range of code point values with given width.
> +def process_code_points(s, width):
> +    # Example arguments:
> +    # 1100..115F
> +    # 232A
> +
> +    r = s.split("..")
> +    if len(r) == 1:
> +        c = int(r[0], base=16)
> +        widths[c] = width
> +    elif len(r) == 2:
> +        begin = int(r[0], base=16)
> +        end = int(r[1], base=16) + 1
> +        widths[begin:end] = [width] * (end - begin)
> +    else:
> +        raise ValueError
> +
> +for line in open("EastAsianWidth.txt", "r"):
> +    line = line.split("#")[0]
> +    if len(line) and re.match(r'^[\dA-Fa-f][^;]+;\s*[WF]\s*$', line):
> +        process_code_points(line.split(";")[0], 2)
> +
> +# The C++ standard gives width 2 to the following ranges:
> +# U+4DC0 – U+4DFF (Yijing Hexagram Symbols)
> +process_code_points("4DC0..4DFF", 2)
> +# U+1F300 – U+1F5FF (Miscellaneous Symbols and Pictographs)
> +process_code_points("1F300..1F5FF", 2)
> +# U+1F900 – U+1F9FF (Supplemental Symbols and Pictographs)
> +process_code_points("1F900..1F9FF", 2)
> +
> +# Condense the list to contiguous ranges.
> +prev_width = 1
> +edges = []
> +for i, width in enumerate(widths):
> +    if width == 0:
> +        width = 1
> +    if width != prev_width:
> +        edges.append(i)
> +        prev_width = width
> +
> +# Output the table for __format_width in libstdc++-v3/include/bits/unicode.h
> +print("    // Table generated by contrib/unicode/gen_std_format_width.py,")
> +print("    // from EastAsianWidth.txt from the Unicode standard.");
> +print("    constexpr char32_t __width_edges[] = {", end="")
> +for i, e in enumerate(edges):
> +    if i % 8:
> +        print(" ", end="")
> +    else:
> +        print("\n      ", end="")
> +    print("{:#x},".format(e), end="")
> +print("\n    };\n")
> +
> +properties = ["Other"] * (1 + 0x10FFFF)
> +
> +def process_grapheme_property(code_points, prop):
> +    # Example arguments:
> +    # "0600..0605", "Prepend"
> +    # "00AD", "Control"
> +
> +    prop = prop.strip()
> +    r = code_points.split("..")
> +    if len(r) == 1:
> +        c = int(r[0], base=16)
> +        properties[c] = prop
> +    elif len(r) == 2:
> +        begin = int(r[0], base=16)
> +        end = int(r[1], base=16) + 1
> +        properties[begin:end] = [prop] * (end - begin)
> +    else:
> +        raise ValueError
> +
> +for line in open("GraphemeBreakProperty.txt", "r"):
> +    line = line.split("#")[0]
> +    if len(line) and re.match(r'^[\dA-Fa-f][^;]+;', line):
> +        process_grapheme_property(*line.split(";"))
> +
> +# Condense the list to contiguous ranges.
> +prev_prop = "Other"
> +edges = []
> +for i, prop in enumerate(properties):
> +    if prop != prev_prop:
> +        edges.append((i, prop))
> +        prev_prop = prop
> +props = {p:i+1 for i,p in enumerate(sorted(set([x[1] for x in edges])))}
> +shift_bits = int(math.ceil(math.log2(len(props))))
> +
> +for i, e in enumerate(edges):
> +    if i > 120:
> +        break
> +    print("{}".format(e))
> +print("{}".format(edges[-1]))
> +
> +# Output the table for __grapheme_break in libstdc++-v3/include/bits/unicode.h
> +print("  enum class _Gcb_property {")
> +for p in props.items():
> +    print("    _Gcb_{} = {},".format(p[0],p[1]))
> +print("  };")
> +print()
> +print("    // Values generated by contrib/unicode/gen_std_format_width.py,")
> +print("    // from GraphemeBreakProperty.txt from the Unicode standard.");
> +print("    // Entries are (code_point << shift_bits) + property.")
> +print("    constexpr int __shift_bits = {:#x};".format(shift_bits))
> +print("    constexpr uint32_t __gcb_edges[] = {", end="")
> +for i, e in enumerate(edges):
> +    if i % 5:
> +        print(" ", end="")
> +    else:
> +        print("\n      ", end="")
> +    c, p = e
> +    x = (c << shift_bits) + props[p]
> +    print("{0:#x},".format(x), end="")
> +print("\n    };\n")
> diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
> index d44a399b9f6..1f29f337240 100644
> --- a/libstdc++-v3/include/Makefile.am
> +++ b/libstdc++-v3/include/Makefile.am
> @@ -161,6 +161,7 @@ bits_freestanding = \
>         ${bits_srcdir}/stl_uninitialized.h \
>         ${bits_srcdir}/version.h \
>         ${bits_srcdir}/string_view.tcc \
> +       ${bits_srcdir}/unicode.h \
>         ${bits_srcdir}/uniform_int_dist.h \
>         ${bits_srcdir}/unique_ptr.h \
>         ${bits_srcdir}/uses_allocator.h \
> diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
> index 4fa4a259fef..1824f875613 100644
> --- a/libstdc++-v3/include/Makefile.in
> +++ b/libstdc++-v3/include/Makefile.in
> @@ -516,6 +516,7 @@ bits_freestanding = \
>         ${bits_srcdir}/stl_uninitialized.h \
>         ${bits_srcdir}/version.h \
>         ${bits_srcdir}/string_view.tcc \
> +       ${bits_srcdir}/unicode.h \
>         ${bits_srcdir}/uniform_int_dist.h \
>         ${bits_srcdir}/unique_ptr.h \
>         ${bits_srcdir}/uses_allocator.h \
> diff --git a/libstdc++-v3/include/bits/unicode.h b/libstdc++-v3/include/bits/unicode.h
> new file mode 100644
> index 00000000000..202f285b907
> --- /dev/null
> +++ b/libstdc++-v3/include/bits/unicode.h
> @@ -0,0 +1,1212 @@
> +// Unicode utilities -*- C++ -*-
> +
> +// Copyright The GNU Toolchain Authors.
> +//
> +// This file is part of the GNU ISO C++ Library.  This library is free
> +// software; you can redistribute it and/or modify it under the
> +// terms of the GNU General Public License as published by the
> +// Free Software Foundation; either version 3, or (at your option)
> +// any later version.
> +
> +// This library is distributed in the hope that it will be useful,
> +// but WITHOUT ANY WARRANTY; without even the implied warranty of
> +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +// GNU General Public License for more details.
> +
> +// Under Section 7 of GPL version 3, you are granted additional
> +// permissions described in the GCC Runtime Library Exception, version
> +// 3.1, as published by the Free Software Foundation.
> +
> +// You should have received a copy of the GNU General Public License and
> +// a copy of the GCC Runtime Library Exception along with this program;
> +// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
> +// <http://www.gnu.org/licenses/>.
> +
> +/** @file include/bits/unicode.h
> + *  This is an internal header file, included by other library headers.
> + *  Do not attempt to use it directly. @headername{format}
> + */
> +
> +#ifndef _GLIBCXX_UNICODE_H
> +#define _GLIBCXX_UNICODE_H 1
> +
> +#if __cplusplus >= 202002L
> +#include <array>
> +#include <bit>
> +#include <cstdint>
> +#include <bits/stl_algo.h>
> +#include <bits/stl_iterator.h>
> +#include <bits/ranges_base.h>
> +
> +namespace std _GLIBCXX_VISIBILITY(default)
> +{
> +_GLIBCXX_BEGIN_NAMESPACE_VERSION
> +namespace __unicode
> +{
> +  // A Unicode code point that is not a high or low surrogate.
> +  constexpr bool
> +  __is_scalar_value(char32_t __c)
> +  {
> +    if (__c < 0xD800) [[likely]]
> +      return true;
> +    return 0xDFFF < __c && __c <= 0x10FFFF;
> +  }
> +
> +  // A code point that can be encoded in a single code unit of type _CharT.
> +  template<typename _CharT>
> +    constexpr bool
> +    __is_single_code_unit(char32_t __c)
> +    {
> +      if constexpr (__gnu_cxx::__int_traits<_CharT>::__max <= 0xFF)
> +       return __c < 0x7F; // ASCII character
> +      else
> +       return __c < __gnu_cxx::__int_traits<_CharT>::__max
> +                      && __is_scalar_value(__c);
> +    }
> +
> +  // Based on https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2728r6.html#add-the-transcoding-iterator-template
> +
> +  struct _Repl
> +  {
> +    constexpr char32_t
> +    operator()() const noexcept
> +    { return 0xFFFD; }
> +  };
> +
> +  struct _Null_sentinel_t
> +  {
> +    template<input_iterator _It>
> +      requires default_initializable<iter_value_t<_It>>
> +       && equality_comparable_with<iter_reference_t<_It>, iter_value_t<_It>>
> +      friend constexpr auto
> +      operator==(_It __it, _Null_sentinel_t)
> +      { return *__it == iter_value_t<_It>{}; }
> +  };
> +
> +  inline constexpr _Null_sentinel_t __null_sentinel;
> +
> +  template<typename _FromFmt, typename _ToFmt,
> +          input_iterator _Iter, sentinel_for<_Iter> _Sent = _Iter,
> +          typename _ErrorHandler = _Repl>
> +    requires convertible_to<iter_value_t<_Iter>, _FromFmt>
> +    class _Utf_iterator
> +    {
> +      static_assert(forward_iterator<_Iter> || noexcept(_ErrorHandler()()));
> +
> +    public:
> +      using value_type = _ToFmt;
> +      using difference_type = iter_difference_t<_Iter>;
> +      using reference = value_type;
> +      using iterator_concept
> +       = std::__detail::__clamp_iter_cat<__iter_category_t<_Iter>,
> +                                         bidirectional_iterator_tag>;
> +
> +      constexpr _Utf_iterator() = default;
> +
> +      constexpr
> +      _Utf_iterator(_Iter __first, _Iter __it, _Sent __last)
> +      requires bidirectional_iterator<_Iter>
> +      : _M_first_and_curr{__first, __it}, _M_last(__last)
> +      {
> +       if (_M_curr() != _M_last)
> +         _M_read();
> +       else
> +         _M_buf = {};
> +      }
> +
> +      constexpr
> +      _Utf_iterator(_Iter __it, _Sent __last)
> +      requires (!bidirectional_iterator<_Iter>)
> +      : _M_first_and_curr{__it}, _M_last(__last)
> +      {
> +       if (_M_curr() != _M_last)
> +         _M_read();
> +       else
> +         _M_buf = {};
> +      }
> +
> +      template<class _Iter2, class _Sent2>
> +       requires convertible_to<_Iter2, _Iter> && convertible_to<_Sent2, _Sent>
> +       constexpr
> +       _Utf_iterator(const _Utf_iterator<_FromFmt, _ToFmt, _Iter2, _Sent2,
> +                                         _ErrorHandler>& __other)
> +       : _M_buf(__other._M_buf), _M_first_and_curr(__other._M_first_and_curr),
> +         _M_buf_index(__other._M_buf_index), _M_buf_last(__other._M_buf_last),
> +         _M_last(__other._M_last)
> +       { }
> +
> +      [[nodiscard]]
> +      constexpr _Iter
> +      begin() const requires bidirectional_iterator<_Iter>
> +      { return _M_first(); }
> +
> +      [[nodiscard]]
> +      constexpr _Sent
> +      end() const { return _M_last; }
> +
> +      [[nodiscard]]
> +      constexpr _Iter
> +      base() const requires forward_iterator<_Iter>
> +      { return _M_curr(); }
> +
> +      [[nodiscard]]
> +      constexpr value_type
> +      operator*() const { return _M_buf[_M_buf_index]; }
> +
> +      constexpr _Utf_iterator&
> +      operator++()
> +      {
> +       if (_M_buf_index + 1 == _M_buf_last && _M_curr() != _M_last)
> +         {
> +           if constexpr (forward_iterator<_Iter>)
> +             advance(_M_curr(), _M_to_increment);
> +           if (_M_curr() == _M_last)
> +             _M_buf_index = 0;
> +           else
> +             _M_read();
> +         }
> +       else if (_M_buf_index + 1 <= _M_buf_last)
> +         ++_M_buf_index;
> +       return *this;
> +      }
> +
> +      constexpr _Utf_iterator
> +      operator++(int)
> +      {
> +       auto __tmp = *this;
> +       ++*this;
> +       return __tmp;
> +      }
> +
> +      constexpr _Utf_iterator&
> +      operator--() requires bidirectional_iterator<_Iter>
> +      {
> +       if (!_M_buf_index && _M_curr() != _M_first())
> +         _M_read_reverse();
> +       else if (_M_buf_index)
> +         --_M_buf_index;
> +       return *this;
> +      }
> +
> +      constexpr _Utf_iterator
> +      operator--(int)
> +      {
> +       auto __tmp = *this;
> +       --*this;
> +       return __tmp;
> +      }
> +
> +      [[nodiscard]]
> +      friend constexpr bool
> +      operator==(_Utf_iterator __lhs, _Utf_iterator __rhs)
> +      requires forward_iterator<_Iter> || requires (_Iter __i) { __i != __i; }
> +      {
> +       if constexpr (forward_iterator<_Iter>)
> +         return __lhs._M_curr() == __rhs._M_curr()
> +                  && __lhs._M_buf_index == __rhs._M_buf_index;
> +       else if (__lhs._M_curr() != __rhs._M_curr())
> +         return false;
> +       else if (__lhs._M_buf_index == __rhs._M_buf_index
> +                  && __lhs._M_buf_last == __rhs._M_buf_last)
> +         return true;
> +       else
> +         return __lhs._M_buf_index == __lhs._M_buf_last
> +                  && __rhs._M_buf_index == __rhs._M_buf_last;
> +      }
> +
> +      [[nodiscard]]
> +      friend constexpr bool
> +      operator==(_Utf_iterator __lhs, _Sent __rhs)
> +      {
> +       if constexpr (forward_iterator<_Iter>)
> +         return __lhs._M_curr() == __rhs;
> +       else
> +         return __lhs._M_curr() == __rhs
> +                  && __lhs._M_buf_index == __lhs._M_buf_last;
> +      }
> +
> +    private:
> +      constexpr void
> +      _M_read()
> +      {
> +       if constexpr (sizeof(_FromFmt) == sizeof(uint8_t))
> +         _M_read_utf8();
> +       else if constexpr (sizeof(_FromFmt) == sizeof(uint16_t))
> +         _M_read_utf16();
> +       else
> +         {
> +           static_assert(sizeof(_FromFmt) == sizeof(uint32_t));
> +           _M_read_utf32();
> +         }
> +      }
> +
> +      constexpr void
> +      _M_read_reverse(); // TODO
> +
> +      template<typename>
> +       struct _Guard
> +       {
> +         _Guard(void*, _Iter&) { }
> +       };
> +
> +      template<typename _It> requires forward_iterator<_It>
> +       struct _Guard<_It>
> +       {
> +         constexpr ~_Guard() { _M_this->_M_curr() = std::move(_M_orig); }
> +         _Utf_iterator* _M_this;
> +         _It _M_orig;
> +       };
> +
> +      constexpr void
> +      _M_read_utf8()
> +      {
> +       _Guard<_Iter> __g{this, _M_curr()};
> +       char32_t __c{};
> +       uint8_t __u = *_M_curr()++;
> +       const uint8_t __lo_bound = 0x80, __hi_bound = 0xBF;
> +       uint8_t __to_incr = 1;
> +
> +       if (__u <= 0x7F) [[likely]]      // 0x00 to 0x7F
> +         __c = __u;
> +       else if (__u < 0xC2) [[unlikely]]
> +         __c = _S_error();
> +       else if (_M_curr() == _M_last) [[unlikely]]
> +         __c = _S_error();
> +       else if (__u <= 0xDF) // 0xC2 to 0xDF
> +         {
> +           __c = __u & 0x1F;
> +           __u = *_M_curr();
> +
> +           if (__u < __lo_bound || __u > __hi_bound) [[unlikely]]
> +             __c = _S_error();
> +           else
> +             {
> +               __c = (__c << 6) | (__u & 0x3F);
> +               ++_M_curr();
> +               ++__to_incr;
> +             }
> +         }
> +       else if (__u <= 0xEF) // 0xE0 to 0xEF
> +         {
> +           const uint8_t __lo_bound_2 = __u == 0xE0 ? 0xA0 : __lo_bound;
> +           const uint8_t __hi_bound_2 = __u == 0xED ? 0x9F : __hi_bound;
> +
> +           __c = __u & 0x0F;
> +           __u = *_M_curr();
> +
> +           if (__u < __lo_bound_2 || __u > __hi_bound_2) [[unlikely]]
> +             __c = _S_error();
> +           else if (++_M_curr() == _M_last) [[unlikely]]
> +             __c = _S_error();
> +           else
> +             {
> +               ++__to_incr;
> +               __c = (__c << 6) | (__u & 0x3F);
> +               __u = *_M_curr();
> +
> +               if (__u < __lo_bound || __u > __hi_bound) [[unlikely]]
> +                 __c = _S_error();
> +               else
> +                 {
> +                   __c = (__c << 6) | (__u & 0x3F);
> +                   ++_M_curr();
> +                   ++__to_incr;
> +                 }
> +             }
> +         }
> +       else if (__u <= 0xF4) // 0xF0 to 0xF4
> +         {
> +           const uint8_t __lo_bound_2 = __u == 0xF0 ? 0x90 : __lo_bound;
> +           const uint8_t __hi_bound_2 = __u == 0xF4 ? 0x8F : __hi_bound;
> +
> +           __c = __u & 0x07;
> +           __u = *_M_curr();
> +
> +           if (__u < __lo_bound_2 || __u > __hi_bound_2) [[unlikely]]
> +             __c = _S_error();
> +           else if (++_M_curr() == _M_last) [[unlikely]]
> +             __c = _S_error();
> +           else
> +             {
> +               ++__to_incr;
> +               __c = (__c << 6) | (__u & 0x3F);
> +               __u = *_M_curr();
> +
> +               if (__u < __lo_bound || __u > __hi_bound) [[unlikely]]
> +                 __c = _S_error();
> +               else if (++_M_curr() == _M_last) [[unlikely]]
> +                 __c = _S_error();
> +               else
> +                 {
> +                   ++__to_incr;
> +                   __c = (__c << 6) | (__u & 0x3F);
> +                   __u = *_M_curr();
> +
> +                   if (__u < __lo_bound || __u > __hi_bound) [[unlikely]]
> +                     __c = _S_error();
> +                   else
> +                     {
> +                       __c = (__c << 6) | (__u & 0x3F);
> +                       ++_M_curr();
> +                       ++__to_incr;
> +                     }
> +                 }
> +             }
> +         }
> +       else [[unlikely]]
> +         __c = _S_error();
> +
> +       _M_update(__c, __to_incr);
> +      }
> +
> +      constexpr void
> +      _M_read_utf16()
> +      {
> +       _Guard<_Iter> __g{this, _M_curr()};
> +       char32_t __c{};
> +       uint16_t __u = *_M_curr()++;
> +       uint8_t __to_incr = 1;
> +
> +       if (__u < 0xD800 || __u > 0xDFFF) [[likely]]
> +         __c = __u;
> +       else if (__u < 0xDC00 && _M_curr() != _M_last)
> +         {
> +           uint16_t __u2 = *_M_curr();
> +           if (__u2 < 0xDC00 || __u2 > 0xDFFF) [[unlikely]]
> +             __c = _S_error();
> +           else
> +             {
> +               ++_M_curr();
> +               __to_incr = 2;
> +               uint32_t __x = (__u & 0x3F) << 10 | __u2 & 0x3FF;
> +               uint32_t __w = (__u >> 6) & 0x1F;
> +               __c = (__w + 1) << 16 | __x;
> +             }
> +         }
> +       else
> +         __c = _S_error();
> +
> +       _M_update(__c, __to_incr);
> +      }
> +
> +      constexpr void
> +      _M_read_utf32()
> +      {
> +       _Guard<_Iter> __g{this, _M_curr()};
> +       char32_t __c = *_M_curr()++;
> +       if (!__is_scalar_value(__c)) [[unlikely]]
> +         __c = _S_error();
> +       _M_update(__c, 1);
> +      }
> +
> +      // Encode the code point __c as one or more code units in _M_buf.
> +      constexpr void
> +      _M_update(char32_t __c, uint8_t __to_incr)
> +      {
> +       _M_to_increment = __to_incr;
> +       _M_buf_index = 0;
> +       if constexpr (sizeof(_ToFmt) == sizeof(uint32_t))
> +         {
> +           _M_buf[0] = __c;
> +           _M_buf_last = 1;
> +         }
> +       else if constexpr (sizeof(_ToFmt) == sizeof(uint16_t))
> +         {
> +           if (__is_single_code_unit<_ToFmt>(__c))
> +             {
> +               _M_buf[0] = __c;
> +               _M_buf[1] = 0;
> +               _M_buf_last = 1;
> +             }
> +           else
> +             {
> +               // From http://www.unicode.org/faq/utf_bom.html#utf16-4
> +               const char32_t __lead_offset = 0xD800 - (0x10000 >> 10);
> +               char16_t __lead = __lead_offset + (__c >> 10);
> +               char16_t __trail = 0xDC00 + (__c & 0x3FF);
> +               _M_buf[0] = __lead;
> +               _M_buf[1] = __trail;
> +               _M_buf_last = 2;
> +             }
> +         }
> +       else
> +         {
> +           static_assert(sizeof(_ToFmt) == 1);
> +           int __bits = std::bit_width((uint32_t)__c);
> +           if (__bits <= 7) [[likely]]
> +             {
> +               _M_buf[0] = __c;
> +               _M_buf[1] = _M_buf[2] = _M_buf[3] = 0;
> +               _M_buf_last = 1;
> +             }
> +           else if (__bits <= 11)
> +             {
> +               _M_buf[0] = 0xC0 | (__c >> 6);
> +               _M_buf[1] = 0x80 | (__c & 0x3F);
> +               _M_buf[2] = _M_buf[3] = 0;
> +               _M_buf_last = 2;
> +             }
> +           else if (__bits <= 16)
> +             {
> +               _M_buf[0] = 0xE0 | (__c >> 12);
> +               _M_buf[1] = 0x80 | ((__c >> 6) & 0x3F);
> +               _M_buf[2] = 0x80 | (__c & 0x3F);
> +               _M_buf[3] = 0;
> +               _M_buf_last = 3;
> +             }
> +           else
> +             {
> +               _M_buf[0] = 0xF0 | ((__c >> 18) & 0x07);
> +               _M_buf[1] = 0x80 | ((__c >> 12) & 0x3F);
> +               _M_buf[2] = 0x80 | ((__c >> 6) & 0x3F);
> +               _M_buf[3] = 0x80 | (__c & 0x3F);
> +               _M_buf_last = 4;
> +             }
> +         }
> +      }
> +
> +      constexpr char32_t
> +      _S_error()
> +      {
> +       char32_t __c = _ErrorHandler()();
> +       __glibcxx_assert(__is_scalar_value(__c));
> +       return __c;
> +      }
> +
> +      constexpr _Iter
> +      _M_first() const requires bidirectional_iterator<_Iter>
> +      { return _M_first_and_curr._M_first; }
> +
> +      constexpr _Iter&
> +      _M_curr() { return _M_first_and_curr._M_curr; }
> +
> +      constexpr _Iter
> +      _M_curr() const { return _M_first_and_curr._M_curr; }
> +
> +      array<value_type, 4 / sizeof(_ToFmt)> _M_buf;
> +
> +      template<typename _It>
> +       struct _First_and_curr
> +       {
> +         _First_and_curr() = default;
> +
> +         constexpr
> +         _First_and_curr(_It __curr) : _M_curr(__curr) { }
> +
> +         template<convertible_to<_It> _It2>
> +           constexpr
> +           _First_and_curr(const _First_and_curr<_It2>& __other)
> +           : _M_curr(__other._M_curr) { }
> +
> +         _It _M_curr;
> +       };
> +
> +      template<typename _It> requires bidirectional_iterator<_It>
> +       struct _First_and_curr<_It>
> +       {
> +         _First_and_curr() = default;
> +
> +         constexpr
> +         _First_and_curr(_It __first, _It __curr)
> +         : _M_first(__first), _M_curr(__curr) { }
> +
> +         template<convertible_to<_It> _It2>
> +           constexpr
> +           _First_and_curr(const _First_and_curr<_It2>& __other)
> +           : _M_first(__other._M_first), _M_curr(__other._M_curr) { }
> +
> +         _It _M_first;
> +         _It _M_curr;
> +       };
> +
> +      _First_and_curr<_Iter> _M_first_and_curr;
> +
> +      uint8_t _M_buf_index = 0;
> +      uint8_t _M_buf_last = 0;
> +      uint8_t _M_to_increment = 0;
> +
> +      [[no_unique_address]] _Sent _M_last;
> +
> +      template<typename _FromFmt2, typename _ToFmt2,
> +              input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
> +              typename _ErrHandler>
> +       requires convertible_to<iter_value_t<_Iter2>, _FromFmt2>
> +       friend class _Utf_iterator;
> +    };
> +
> +  template<typename _ToFormat, ranges::input_range _Range>
> +    class _Utf_view
> +    : public ranges::view_interface<_Utf_view<_ToFormat, _Range>>
> +    {
> +      using _Iterator = _Utf_iterator<ranges::range_value_t<_Range>,
> +                                     _ToFormat, ranges::iterator_t<_Range>,
> +                                     ranges::sentinel_t<_Range>>;
> +
> +      template<typename _Iter, typename _Sent>
> +       constexpr auto
> +       _M_begin(_Iter __first, _Sent __last)
> +       {
> +         if constexpr (bidirectional_iterator<_Iter>)
> +           return _Iterator(__first, __first, __last);
> +         else
> +           return _Iterator(__first, __last);
> +       }
> +
> +      template<typename _Iter, typename _Sent>
> +       constexpr auto
> +       _M_end(_Iter __first, _Sent __last)
> +       {
> +         if constexpr (!is_same_v<_Iter, _Sent>)
> +           return __last;
> +         else if constexpr (bidirectional_iterator<_Iter>)
> +           return _Iterator(__first, __last, __last);
> +         else
> +           return _Iterator(__last, __last);
> +       }
> +
> +      _Range _M_base;
> +
> +    public:
> +      constexpr explicit
> +      _Utf_view(_Range&& __r) : _M_base(std::forward<_Range>(__r)) { }
> +
> +      constexpr auto begin()
> +      { return _M_begin(ranges::begin(_M_base), ranges::end(_M_base)); }
> +
> +      constexpr auto end()
> +      { return _M_end(ranges::begin(_M_base), ranges::end(_M_base)); }
> +
> +      constexpr bool empty() const { return ranges::empty(_M_base); }
> +    };
> +
> +  template<typename _View>
> +    using _Utf8_view = _Utf_view<char8_t, _View>;
> +  template<typename _View>
> +    using _Utf16_view = _Utf_view<char16_t, _View>;
> +  template<typename _View>
> +    using _Utf32_view = _Utf_view<char32_t, _View>;
> +
> +  // The field width of a code point.
> +  constexpr int
> +  __field_width(char32_t __c) noexcept
> +  {
> +    // Table generated by contrib/unicode/gen_std_format_width.py,
> +    // from EastAsianWidth.txt from the Unicode standard.
> +    constexpr char32_t __width_edges[] = {
> +      0x1100, 0x1160, 0x231a, 0x231c, 0x2329, 0x232b, 0x23e9, 0x23ed,
> +      0x23f0, 0x23f1, 0x23f3, 0x23f4, 0x25fd, 0x25ff, 0x2614, 0x2616,
> +      0x2648, 0x2654, 0x267f, 0x2680, 0x2693, 0x2694, 0x26a1, 0x26a2,
> +      0x26aa, 0x26ac, 0x26bd, 0x26bf, 0x26c4, 0x26c6, 0x26ce, 0x26cf,
> +      0x26d4, 0x26d5, 0x26ea, 0x26eb, 0x26f2, 0x26f4, 0x26f5, 0x26f6,
> +      0x26fa, 0x26fb, 0x26fd, 0x26fe, 0x2705, 0x2706, 0x270a, 0x270c,
> +      0x2728, 0x2729, 0x274c, 0x274d, 0x274e, 0x274f, 0x2753, 0x2756,
> +      0x2757, 0x2758, 0x2795, 0x2798, 0x27b0, 0x27b1, 0x27bf, 0x27c0,
> +      0x2b1b, 0x2b1d, 0x2b50, 0x2b51, 0x2b55, 0x2b56, 0x2e80, 0x2e9a,
> +      0x2e9b, 0x2ef4, 0x2f00, 0x2fd6, 0x2ff0, 0x303f, 0x3041, 0x3097,
> +      0x3099, 0x3100, 0x3105, 0x3130, 0x3131, 0x318f, 0x3190, 0x31e4,
> +      0x31ef, 0x321f, 0x3220, 0x3248, 0x3250, 0xa48d, 0xa490, 0xa4c7,
> +      0xa960, 0xa97d, 0xac00, 0xd7a4, 0xf900, 0xfb00, 0xfe10, 0xfe1a,
> +      0xfe30, 0xfe53, 0xfe54, 0xfe67, 0xfe68, 0xfe6c, 0xff01, 0xff61,
> +      0xffe0, 0xffe7, 0x16fe0, 0x16fe5, 0x16ff0, 0x16ff2, 0x17000, 0x187f8,
> +      0x18800, 0x18cd6, 0x18d00, 0x18d09, 0x1aff0, 0x1aff4, 0x1aff5, 0x1affc,
> +      0x1affd, 0x1afff, 0x1b000, 0x1b123, 0x1b132, 0x1b133, 0x1b150, 0x1b153,
> +      0x1b155, 0x1b156, 0x1b164, 0x1b168, 0x1b170, 0x1b2fc, 0x1f004, 0x1f005,
> +      0x1f0cf, 0x1f0d0, 0x1f18e, 0x1f18f, 0x1f191, 0x1f19b, 0x1f200, 0x1f203,
> +      0x1f210, 0x1f23c, 0x1f240, 0x1f249, 0x1f250, 0x1f252, 0x1f260, 0x1f266,
> +      0x1f300, 0x1f650, 0x1f680, 0x1f6c6, 0x1f6cc, 0x1f6cd, 0x1f6d0, 0x1f6d3,
> +      0x1f6d5, 0x1f6d8, 0x1f6dc, 0x1f6e0, 0x1f6eb, 0x1f6ed, 0x1f6f4, 0x1f6fd,
> +      0x1f7e0, 0x1f7ec, 0x1f7f0, 0x1f7f1, 0x1f900, 0x1fa00, 0x1fa70, 0x1fa7d,
> +      0x1fa80, 0x1fa89, 0x1fa90, 0x1fabe, 0x1fabf, 0x1fac6, 0x1face, 0x1fadc,
> +      0x1fae0, 0x1fae9, 0x1faf0, 0x1faf9, 0x20000, 0x2fffe, 0x30000, 0x3fffe,
> +    };
> +
> +    if (__c < __width_edges[0]) [[likely]]
> +      return 1;
> +
> +    auto* __p = std::upper_bound(__width_edges, std::end(__width_edges), __c);
> +    return (__p - __width_edges) % 2 + 1;
> +  }
> +
> +  enum class _Gcb_property {
> +    _Gcb_CR = 1,
> +    _Gcb_Control = 2,
> +    _Gcb_Extend = 3,
> +    _Gcb_L = 4,
> +    _Gcb_LF = 5,
> +    _Gcb_LV = 6,
> +    _Gcb_LVT = 7,
> +    _Gcb_Other = 8,
> +    _Gcb_Prepend = 9,
> +    _Gcb_Regional_Indicator = 10,
> +    _Gcb_SpacingMark = 11,
> +    _Gcb_T = 12,
> +    _Gcb_V = 13,
> +    _Gcb_ZWJ = 14,
> +  };
> +
> +  constexpr _Gcb_property
> +  __grapheme_cluster_break_property(char32_t __c) noexcept
> +  {
> +    // Values generated by contrib/unicode/gen_std_format_width.py,
> +    // from GraphemeBreakProperty.txt from the Unicode standard.
> +    // Entries are (code_point << shift_bits) + property.
> +    constexpr int __shift_bits = 0x4;
> +    constexpr uint32_t __gcb_edges[] = {
> +      0x2, 0xa5, 0xb2, 0xd1, 0xe2,
> +      0x208, 0x7f2, 0xa08, 0xad2, 0xae8,
> +      0x3003, 0x3708, 0x4833, 0x48a8, 0x5913,
> +      0x5be8, 0x5bf3, 0x5c08, 0x5c13, 0x5c38,
> +      0x5c43, 0x5c68, 0x5c73, 0x5c88, 0x6009,
> +      0x6068, 0x6103, 0x61b8, 0x61c2, 0x61d8,
> +      0x64b3, 0x6608, 0x6703, 0x6718, 0x6d63,
> +      0x6dd9, 0x6de8, 0x6df3, 0x6e58, 0x6e73,
> +      0x6e98, 0x6ea3, 0x6ee8, 0x70f9, 0x7108,
> +      0x7113, 0x7128, 0x7303, 0x74b8, 0x7a63,
> +      0x7b18, 0x7eb3, 0x7f48, 0x7fd3, 0x7fe8,
> +      0x8163, 0x81a8, 0x81b3, 0x8248, 0x8253,
> +      0x8288, 0x8293, 0x82e8, 0x8593, 0x85c8,
> +      0x8909, 0x8928, 0x8983, 0x8a08, 0x8ca3,
> +      0x8e29, 0x8e33, 0x903b, 0x9048, 0x93a3,
> +      0x93bb, 0x93c3, 0x93d8, 0x93eb, 0x9413,
> +      0x949b, 0x94d3, 0x94eb, 0x9508, 0x9513,
> +      0x9588, 0x9623, 0x9648, 0x9813, 0x982b,
> +      0x9848, 0x9bc3, 0x9bd8, 0x9be3, 0x9bfb,
> +      0x9c13, 0x9c58, 0x9c7b, 0x9c98, 0x9cbb,
> +      0x9cd3, 0x9ce8, 0x9d73, 0x9d88, 0x9e23,
> +      0x9e48, 0x9fe3, 0x9ff8, 0xa013, 0xa03b,
> +      0xa048, 0xa3c3, 0xa3d8, 0xa3eb, 0xa413,
> +      0xa438, 0xa473, 0xa498, 0xa4b3, 0xa4e8,
> +      0xa513, 0xa528, 0xa703, 0xa728, 0xa753,
> +      0xa768, 0xa813, 0xa83b, 0xa848, 0xabc3,
> +      0xabd8, 0xabeb, 0xac13, 0xac68, 0xac73,
> +      0xac9b, 0xaca8, 0xacbb, 0xacd3, 0xace8,
> +      0xae23, 0xae48, 0xafa3, 0xb008, 0xb013,
> +      0xb02b, 0xb048, 0xb3c3, 0xb3d8, 0xb3e3,
> +      0xb40b, 0xb413, 0xb458, 0xb47b, 0xb498,
> +      0xb4bb, 0xb4d3, 0xb4e8, 0xb553, 0xb588,
> +      0xb623, 0xb648, 0xb823, 0xb838, 0xbbe3,
> +      0xbbfb, 0xbc03, 0xbc1b, 0xbc38, 0xbc6b,
> +      0xbc98, 0xbcab, 0xbcd3, 0xbce8, 0xbd73,
> +      0xbd88, 0xc003, 0xc01b, 0xc043, 0xc058,
> +      0xc3c3, 0xc3d8, 0xc3e3, 0xc41b, 0xc458,
> +      0xc463, 0xc498, 0xc4a3, 0xc4e8, 0xc553,
> +      0xc578, 0xc623, 0xc648, 0xc813, 0xc82b,
> +      0xc848, 0xcbc3, 0xcbd8, 0xcbeb, 0xcbf3,
> +      0xcc0b, 0xcc23, 0xcc3b, 0xcc58, 0xcc63,
> +      0xcc7b, 0xcc98, 0xccab, 0xccc3, 0xcce8,
> +      0xcd53, 0xcd78, 0xce23, 0xce48, 0xcf3b,
> +      0xcf48, 0xd003, 0xd02b, 0xd048, 0xd3b3,
> +      0xd3d8, 0xd3e3, 0xd3fb, 0xd413, 0xd458,
> +      0xd46b, 0xd498, 0xd4ab, 0xd4d3, 0xd4e9,
> +      0xd4f8, 0xd573, 0xd588, 0xd623, 0xd648,
> +      0xd813, 0xd82b, 0xd848, 0xdca3, 0xdcb8,
> +      0xdcf3, 0xdd0b, 0xdd23, 0xdd58, 0xdd63,
> +      0xdd78, 0xdd8b, 0xddf3, 0xde08, 0xdf2b,
> +      0xdf48, 0xe313, 0xe328, 0xe33b, 0xe343,
> +      0xe3b8, 0xe473, 0xe4f8, 0xeb13, 0xeb28,
> +      0xeb3b, 0xeb43, 0xebd8, 0xec83, 0xecf8,
> +      0xf183, 0xf1a8, 0xf353, 0xf368, 0xf373,
> +      0xf388, 0xf393, 0xf3a8, 0xf3eb, 0xf408,
> +      0xf713, 0xf7fb, 0xf803, 0xf858, 0xf863,
> +      0xf888, 0xf8d3, 0xf988, 0xf993, 0xfbd8,
> +      0xfc63, 0xfc78, 0x102d3, 0x1031b, 0x10323,
> +      0x10388, 0x10393, 0x103bb, 0x103d3, 0x103f8,
> +      0x1056b, 0x10583, 0x105a8, 0x105e3, 0x10618,
> +      0x10713, 0x10758, 0x10823, 0x10838, 0x1084b,
> +      0x10853, 0x10878, 0x108d3, 0x108e8, 0x109d3,
> +      0x109e8, 0x11004, 0x1160d, 0x11a8c, 0x12008,
> +      0x135d3, 0x13608, 0x17123, 0x1715b, 0x17168,
> +      0x17323, 0x1734b, 0x17358, 0x17523, 0x17548,
> +      0x17723, 0x17748, 0x17b43, 0x17b6b, 0x17b73,
> +      0x17beb, 0x17c63, 0x17c7b, 0x17c93, 0x17d48,
> +      0x17dd3, 0x17de8, 0x180b3, 0x180e2, 0x180f3,
> +      0x18108, 0x18853, 0x18878, 0x18a93, 0x18aa8,
> +      0x19203, 0x1923b, 0x19273, 0x1929b, 0x192c8,
> +      0x1930b, 0x19323, 0x1933b, 0x19393, 0x193c8,
> +      0x1a173, 0x1a19b, 0x1a1b3, 0x1a1c8, 0x1a55b,
> +      0x1a563, 0x1a57b, 0x1a583, 0x1a5f8, 0x1a603,
> +      0x1a618, 0x1a623, 0x1a638, 0x1a653, 0x1a6db,
> +      0x1a733, 0x1a7d8, 0x1a7f3, 0x1a808, 0x1ab03,
> +      0x1acf8, 0x1b003, 0x1b04b, 0x1b058, 0x1b343,
> +      0x1b3bb, 0x1b3c3, 0x1b3db, 0x1b423, 0x1b43b,
> +      0x1b458, 0x1b6b3, 0x1b748, 0x1b803, 0x1b82b,
> +      0x1b838, 0x1ba1b, 0x1ba23, 0x1ba6b, 0x1ba83,
> +      0x1baab, 0x1bab3, 0x1bae8, 0x1be63, 0x1be7b,
> +      0x1be83, 0x1beab, 0x1bed3, 0x1beeb, 0x1bef3,
> +      0x1bf2b, 0x1bf48, 0x1c24b, 0x1c2c3, 0x1c34b,
> +      0x1c363, 0x1c388, 0x1cd03, 0x1cd38, 0x1cd43,
> +      0x1ce1b, 0x1ce23, 0x1ce98, 0x1ced3, 0x1cee8,
> +      0x1cf43, 0x1cf58, 0x1cf7b, 0x1cf83, 0x1cfa8,
> +      0x1dc03, 0x1e008, 0x200b2, 0x200c3, 0x200de,
> +      0x200e2, 0x20108, 0x20282, 0x202f8, 0x20602,
> +      0x20708, 0x20d03, 0x20f18, 0x2cef3, 0x2cf28,
> +      0x2d7f3, 0x2d808, 0x2de03, 0x2e008, 0x302a3,
> +      0x30308, 0x30993, 0x309b8, 0xa66f3, 0xa6738,
> +      0xa6743, 0xa67e8, 0xa69e3, 0xa6a08, 0xa6f03,
> +      0xa6f28, 0xa8023, 0xa8038, 0xa8063, 0xa8078,
> +      0xa80b3, 0xa80c8, 0xa823b, 0xa8253, 0xa827b,
> +      0xa8288, 0xa82c3, 0xa82d8, 0xa880b, 0xa8828,
> +      0xa8b4b, 0xa8c43, 0xa8c68, 0xa8e03, 0xa8f28,
> +      0xa8ff3, 0xa9008, 0xa9263, 0xa92e8, 0xa9473,
> +      0xa952b, 0xa9548, 0xa9604, 0xa97d8, 0xa9803,
> +      0xa983b, 0xa9848, 0xa9b33, 0xa9b4b, 0xa9b63,
> +      0xa9bab, 0xa9bc3, 0xa9beb, 0xa9c18, 0xa9e53,
> +      0xa9e68, 0xaa293, 0xaa2fb, 0xaa313, 0xaa33b,
> +      0xaa353, 0xaa378, 0xaa433, 0xaa448, 0xaa4c3,
> +      0xaa4db, 0xaa4e8, 0xaa7c3, 0xaa7d8, 0xaab03,
> +      0xaab18, 0xaab23, 0xaab58, 0xaab73, 0xaab98,
> +      0xaabe3, 0xaac08, 0xaac13, 0xaac28, 0xaaebb,
> +      0xaaec3, 0xaaeeb, 0xaaf08, 0xaaf5b, 0xaaf63,
> +      0xaaf78, 0xabe3b, 0xabe53, 0xabe6b, 0xabe83,
> +      0xabe9b, 0xabeb8, 0xabecb, 0xabed3, 0xabee8,
> +      0xac006, 0xac017, 0xac1c6, 0xac1d7, 0xac386,
> +      0xac397, 0xac546, 0xac557, 0xac706, 0xac717,
> +      0xac8c6, 0xac8d7, 0xaca86, 0xaca97, 0xacc46,
> +      0xacc57, 0xace06, 0xace17, 0xacfc6, 0xacfd7,
> +      0xad186, 0xad197, 0xad346, 0xad357, 0xad506,
> +      0xad517, 0xad6c6, 0xad6d7, 0xad886, 0xad897,
> +      0xada46, 0xada57, 0xadc06, 0xadc17, 0xaddc6,
> +      0xaddd7, 0xadf86, 0xadf97, 0xae146, 0xae157,
> +      0xae306, 0xae317, 0xae4c6, 0xae4d7, 0xae686,
> +      0xae697, 0xae846, 0xae857, 0xaea06, 0xaea17,
> +      0xaebc6, 0xaebd7, 0xaed86, 0xaed97, 0xaef46,
> +      0xaef57, 0xaf106, 0xaf117, 0xaf2c6, 0xaf2d7,
> +      0xaf486, 0xaf497, 0xaf646, 0xaf657, 0xaf806,
> +      0xaf817, 0xaf9c6, 0xaf9d7, 0xafb86, 0xafb97,
> +      0xafd46, 0xafd57, 0xaff06, 0xaff17, 0xb00c6,
> +      0xb00d7, 0xb0286, 0xb0297, 0xb0446, 0xb0457,
> +      0xb0606, 0xb0617, 0xb07c6, 0xb07d7, 0xb0986,
> +      0xb0997, 0xb0b46, 0xb0b57, 0xb0d06, 0xb0d17,
> +      0xb0ec6, 0xb0ed7, 0xb1086, 0xb1097, 0xb1246,
> +      0xb1257, 0xb1406, 0xb1417, 0xb15c6, 0xb15d7,
> +      0xb1786, 0xb1797, 0xb1946, 0xb1957, 0xb1b06,
> +      0xb1b17, 0xb1cc6, 0xb1cd7, 0xb1e86, 0xb1e97,
> +      0xb2046, 0xb2057, 0xb2206, 0xb2217, 0xb23c6,
> +      0xb23d7, 0xb2586, 0xb2597, 0xb2746, 0xb2757,
> +      0xb2906, 0xb2917, 0xb2ac6, 0xb2ad7, 0xb2c86,
> +      0xb2c97, 0xb2e46, 0xb2e57, 0xb3006, 0xb3017,
> +      0xb31c6, 0xb31d7, 0xb3386, 0xb3397, 0xb3546,
> +      0xb3557, 0xb3706, 0xb3717, 0xb38c6, 0xb38d7,
> +      0xb3a86, 0xb3a97, 0xb3c46, 0xb3c57, 0xb3e06,
> +      0xb3e17, 0xb3fc6, 0xb3fd7, 0xb4186, 0xb4197,
> +      0xb4346, 0xb4357, 0xb4506, 0xb4517, 0xb46c6,
> +      0xb46d7, 0xb4886, 0xb4897, 0xb4a46, 0xb4a57,
> +      0xb4c06, 0xb4c17, 0xb4dc6, 0xb4dd7, 0xb4f86,
> +      0xb4f97, 0xb5146, 0xb5157, 0xb5306, 0xb5317,
> +      0xb54c6, 0xb54d7, 0xb5686, 0xb5697, 0xb5846,
> +      0xb5857, 0xb5a06, 0xb5a17, 0xb5bc6, 0xb5bd7,
> +      0xb5d86, 0xb5d97, 0xb5f46, 0xb5f57, 0xb6106,
> +      0xb6117, 0xb62c6, 0xb62d7, 0xb6486, 0xb6497,
> +      0xb6646, 0xb6657, 0xb6806, 0xb6817, 0xb69c6,
> +      0xb69d7, 0xb6b86, 0xb6b97, 0xb6d46, 0xb6d57,
> +      0xb6f06, 0xb6f17, 0xb70c6, 0xb70d7, 0xb7286,
> +      0xb7297, 0xb7446, 0xb7457, 0xb7606, 0xb7617,
> +      0xb77c6, 0xb77d7, 0xb7986, 0xb7997, 0xb7b46,
> +      0xb7b57, 0xb7d06, 0xb7d17, 0xb7ec6, 0xb7ed7,
> +      0xb8086, 0xb8097, 0xb8246, 0xb8257, 0xb8406,
> +      0xb8417, 0xb85c6, 0xb85d7, 0xb8786, 0xb8797,
> +      0xb8946, 0xb8957, 0xb8b06, 0xb8b17, 0xb8cc6,
> +      0xb8cd7, 0xb8e86, 0xb8e97, 0xb9046, 0xb9057,
> +      0xb9206, 0xb9217, 0xb93c6, 0xb93d7, 0xb9586,
> +      0xb9597, 0xb9746, 0xb9757, 0xb9906, 0xb9917,
> +      0xb9ac6, 0xb9ad7, 0xb9c86, 0xb9c97, 0xb9e46,
> +      0xb9e57, 0xba006, 0xba017, 0xba1c6, 0xba1d7,
> +      0xba386, 0xba397, 0xba546, 0xba557, 0xba706,
> +      0xba717, 0xba8c6, 0xba8d7, 0xbaa86, 0xbaa97,
> +      0xbac46, 0xbac57, 0xbae06, 0xbae17, 0xbafc6,
> +      0xbafd7, 0xbb186, 0xbb197, 0xbb346, 0xbb357,
> +      0xbb506, 0xbb517, 0xbb6c6, 0xbb6d7, 0xbb886,
> +      0xbb897, 0xbba46, 0xbba57, 0xbbc06, 0xbbc17,
> +      0xbbdc6, 0xbbdd7, 0xbbf86, 0xbbf97, 0xbc146,
> +      0xbc157, 0xbc306, 0xbc317, 0xbc4c6, 0xbc4d7,
> +      0xbc686, 0xbc697, 0xbc846, 0xbc857, 0xbca06,
> +      0xbca17, 0xbcbc6, 0xbcbd7, 0xbcd86, 0xbcd97,
> +      0xbcf46, 0xbcf57, 0xbd106, 0xbd117, 0xbd2c6,
> +      0xbd2d7, 0xbd486, 0xbd497, 0xbd646, 0xbd657,
> +      0xbd806, 0xbd817, 0xbd9c6, 0xbd9d7, 0xbdb86,
> +      0xbdb97, 0xbdd46, 0xbdd57, 0xbdf06, 0xbdf17,
> +      0xbe0c6, 0xbe0d7, 0xbe286, 0xbe297, 0xbe446,
> +      0xbe457, 0xbe606, 0xbe617, 0xbe7c6, 0xbe7d7,
> +      0xbe986, 0xbe997, 0xbeb46, 0xbeb57, 0xbed06,
> +      0xbed17, 0xbeec6, 0xbeed7, 0xbf086, 0xbf097,
> +      0xbf246, 0xbf257, 0xbf406, 0xbf417, 0xbf5c6,
> +      0xbf5d7, 0xbf786, 0xbf797, 0xbf946, 0xbf957,
> +      0xbfb06, 0xbfb17, 0xbfcc6, 0xbfcd7, 0xbfe86,
> +      0xbfe97, 0xc0046, 0xc0057, 0xc0206, 0xc0217,
> +      0xc03c6, 0xc03d7, 0xc0586, 0xc0597, 0xc0746,
> +      0xc0757, 0xc0906, 0xc0917, 0xc0ac6, 0xc0ad7,
> +      0xc0c86, 0xc0c97, 0xc0e46, 0xc0e57, 0xc1006,
> +      0xc1017, 0xc11c6, 0xc11d7, 0xc1386, 0xc1397,
> +      0xc1546, 0xc1557, 0xc1706, 0xc1717, 0xc18c6,
> +      0xc18d7, 0xc1a86, 0xc1a97, 0xc1c46, 0xc1c57,
> +      0xc1e06, 0xc1e17, 0xc1fc6, 0xc1fd7, 0xc2186,
> +      0xc2197, 0xc2346, 0xc2357, 0xc2506, 0xc2517,
> +      0xc26c6, 0xc26d7, 0xc2886, 0xc2897, 0xc2a46,
> +      0xc2a57, 0xc2c06, 0xc2c17, 0xc2dc6, 0xc2dd7,
> +      0xc2f86, 0xc2f97, 0xc3146, 0xc3157, 0xc3306,
> +      0xc3317, 0xc34c6, 0xc34d7, 0xc3686, 0xc3697,
> +      0xc3846, 0xc3857, 0xc3a06, 0xc3a17, 0xc3bc6,
> +      0xc3bd7, 0xc3d86, 0xc3d97, 0xc3f46, 0xc3f57,
> +      0xc4106, 0xc4117, 0xc42c6, 0xc42d7, 0xc4486,
> +      0xc4497, 0xc4646, 0xc4657, 0xc4806, 0xc4817,
> +      0xc49c6, 0xc49d7, 0xc4b86, 0xc4b97, 0xc4d46,
> +      0xc4d57, 0xc4f06, 0xc4f17, 0xc50c6, 0xc50d7,
> +      0xc5286, 0xc5297, 0xc5446, 0xc5457, 0xc5606,
> +      0xc5617, 0xc57c6, 0xc57d7, 0xc5986, 0xc5997,
> +      0xc5b46, 0xc5b57, 0xc5d06, 0xc5d17, 0xc5ec6,
> +      0xc5ed7, 0xc6086, 0xc6097, 0xc6246, 0xc6257,
> +      0xc6406, 0xc6417, 0xc65c6, 0xc65d7, 0xc6786,
> +      0xc6797, 0xc6946, 0xc6957, 0xc6b06, 0xc6b17,
> +      0xc6cc6, 0xc6cd7, 0xc6e86, 0xc6e97, 0xc7046,
> +      0xc7057, 0xc7206, 0xc7217, 0xc73c6, 0xc73d7,
> +      0xc7586, 0xc7597, 0xc7746, 0xc7757, 0xc7906,
> +      0xc7917, 0xc7ac6, 0xc7ad7, 0xc7c86, 0xc7c97,
> +      0xc7e46, 0xc7e57, 0xc8006, 0xc8017, 0xc81c6,
> +      0xc81d7, 0xc8386, 0xc8397, 0xc8546, 0xc8557,
> +      0xc8706, 0xc8717, 0xc88c6, 0xc88d7, 0xc8a86,
> +      0xc8a97, 0xc8c46, 0xc8c57, 0xc8e06, 0xc8e17,
> +      0xc8fc6, 0xc8fd7, 0xc9186, 0xc9197, 0xc9346,
> +      0xc9357, 0xc9506, 0xc9517, 0xc96c6, 0xc96d7,
> +      0xc9886, 0xc9897, 0xc9a46, 0xc9a57, 0xc9c06,
> +      0xc9c17, 0xc9dc6, 0xc9dd7, 0xc9f86, 0xc9f97,
> +      0xca146, 0xca157, 0xca306, 0xca317, 0xca4c6,
> +      0xca4d7, 0xca686, 0xca697, 0xca846, 0xca857,
> +      0xcaa06, 0xcaa17, 0xcabc6, 0xcabd7, 0xcad86,
> +      0xcad97, 0xcaf46, 0xcaf57, 0xcb106, 0xcb117,
> +      0xcb2c6, 0xcb2d7, 0xcb486, 0xcb497, 0xcb646,
> +      0xcb657, 0xcb806, 0xcb817, 0xcb9c6, 0xcb9d7,
> +      0xcbb86, 0xcbb97, 0xcbd46, 0xcbd57, 0xcbf06,
> +      0xcbf17, 0xcc0c6, 0xcc0d7, 0xcc286, 0xcc297,
> +      0xcc446, 0xcc457, 0xcc606, 0xcc617, 0xcc7c6,
> +      0xcc7d7, 0xcc986, 0xcc997, 0xccb46, 0xccb57,
> +      0xccd06, 0xccd17, 0xccec6, 0xcced7, 0xcd086,
> +      0xcd097, 0xcd246, 0xcd257, 0xcd406, 0xcd417,
> +      0xcd5c6, 0xcd5d7, 0xcd786, 0xcd797, 0xcd946,
> +      0xcd957, 0xcdb06, 0xcdb17, 0xcdcc6, 0xcdcd7,
> +      0xcde86, 0xcde97, 0xce046, 0xce057, 0xce206,
> +      0xce217, 0xce3c6, 0xce3d7, 0xce586, 0xce597,
> +      0xce746, 0xce757, 0xce906, 0xce917, 0xceac6,
> +      0xcead7, 0xcec86, 0xcec97, 0xcee46, 0xcee57,
> +      0xcf006, 0xcf017, 0xcf1c6, 0xcf1d7, 0xcf386,
> +      0xcf397, 0xcf546, 0xcf557, 0xcf706, 0xcf717,
> +      0xcf8c6, 0xcf8d7, 0xcfa86, 0xcfa97, 0xcfc46,
> +      0xcfc57, 0xcfe06, 0xcfe17, 0xcffc6, 0xcffd7,
> +      0xd0186, 0xd0197, 0xd0346, 0xd0357, 0xd0506,
> +      0xd0517, 0xd06c6, 0xd06d7, 0xd0886, 0xd0897,
> +      0xd0a46, 0xd0a57, 0xd0c06, 0xd0c17, 0xd0dc6,
> +      0xd0dd7, 0xd0f86, 0xd0f97, 0xd1146, 0xd1157,
> +      0xd1306, 0xd1317, 0xd14c6, 0xd14d7, 0xd1686,
> +      0xd1697, 0xd1846, 0xd1857, 0xd1a06, 0xd1a17,
> +      0xd1bc6, 0xd1bd7, 0xd1d86, 0xd1d97, 0xd1f46,
> +      0xd1f57, 0xd2106, 0xd2117, 0xd22c6, 0xd22d7,
> +      0xd2486, 0xd2497, 0xd2646, 0xd2657, 0xd2806,
> +      0xd2817, 0xd29c6, 0xd29d7, 0xd2b86, 0xd2b97,
> +      0xd2d46, 0xd2d57, 0xd2f06, 0xd2f17, 0xd30c6,
> +      0xd30d7, 0xd3286, 0xd3297, 0xd3446, 0xd3457,
> +      0xd3606, 0xd3617, 0xd37c6, 0xd37d7, 0xd3986,
> +      0xd3997, 0xd3b46, 0xd3b57, 0xd3d06, 0xd3d17,
> +      0xd3ec6, 0xd3ed7, 0xd4086, 0xd4097, 0xd4246,
> +      0xd4257, 0xd4406, 0xd4417, 0xd45c6, 0xd45d7,
> +      0xd4786, 0xd4797, 0xd4946, 0xd4957, 0xd4b06,
> +      0xd4b17, 0xd4cc6, 0xd4cd7, 0xd4e86, 0xd4e97,
> +      0xd5046, 0xd5057, 0xd5206, 0xd5217, 0xd53c6,
> +      0xd53d7, 0xd5586, 0xd5597, 0xd5746, 0xd5757,
> +      0xd5906, 0xd5917, 0xd5ac6, 0xd5ad7, 0xd5c86,
> +      0xd5c97, 0xd5e46, 0xd5e57, 0xd6006, 0xd6017,
> +      0xd61c6, 0xd61d7, 0xd6386, 0xd6397, 0xd6546,
> +      0xd6557, 0xd6706, 0xd6717, 0xd68c6, 0xd68d7,
> +      0xd6a86, 0xd6a97, 0xd6c46, 0xd6c57, 0xd6e06,
> +      0xd6e17, 0xd6fc6, 0xd6fd7, 0xd7186, 0xd7197,
> +      0xd7346, 0xd7357, 0xd7506, 0xd7517, 0xd76c6,
> +      0xd76d7, 0xd7886, 0xd7897, 0xd7a48, 0xd7b0d,
> +      0xd7c78, 0xd7cbc, 0xd7fc8, 0xfb1e3, 0xfb1f8,
> +      0xfe003, 0xfe108, 0xfe203, 0xfe308, 0xfeff2,
> +      0xff008, 0xff9e3, 0xffa08, 0xfff02, 0xfffc8,
> +      0x101fd3, 0x101fe8, 0x102e03, 0x102e18, 0x103763,
> +      0x1037b8, 0x10a013, 0x10a048, 0x10a053, 0x10a078,
> +      0x10a0c3, 0x10a108, 0x10a383, 0x10a3b8, 0x10a3f3,
> +      0x10a408, 0x10ae53, 0x10ae78, 0x10d243, 0x10d288,
> +      0x10eab3, 0x10ead8, 0x10efd3, 0x10f008, 0x10f463,
> +      0x10f518, 0x10f823, 0x10f868, 0x11000b, 0x110013,
> +      0x11002b, 0x110038, 0x110383, 0x110478, 0x110703,
> +      0x110718, 0x110733, 0x110758, 0x1107f3, 0x11082b,
> +      0x110838, 0x110b0b, 0x110b33, 0x110b7b, 0x110b93,
> +      0x110bb8, 0x110bd9, 0x110be8, 0x110c23, 0x110c38,
> +      0x110cd9, 0x110ce8, 0x111003, 0x111038, 0x111273,
> +      0x1112cb, 0x1112d3, 0x111358, 0x11145b, 0x111478,
> +      0x111733, 0x111748, 0x111803, 0x11182b, 0x111838,
> +      0x111b3b, 0x111b63, 0x111bfb, 0x111c18, 0x111c29,
> +      0x111c48, 0x111c93, 0x111cd8, 0x111ceb, 0x111cf3,
> +      0x111d08, 0x1122cb, 0x1122f3, 0x11232b, 0x112343,
> +      0x11235b, 0x112363, 0x112388, 0x1123e3, 0x1123f8,
> +      0x112413, 0x112428, 0x112df3, 0x112e0b, 0x112e33,
> +      0x112eb8, 0x113003, 0x11302b, 0x113048, 0x1133b3,
> +      0x1133d8, 0x1133e3, 0x1133fb, 0x113403, 0x11341b,
> +      0x113458, 0x11347b, 0x113498, 0x1134bb, 0x1134e8,
> +      0x113573, 0x113588, 0x11362b, 0x113648, 0x113663,
> +      0x1136d8, 0x113703, 0x113758, 0x11435b, 0x114383,
> +      0x11440b, 0x114423, 0x11445b, 0x114463, 0x114478,
> +      0x1145e3, 0x1145f8, 0x114b03, 0x114b1b, 0x114b33,
> +      0x114b9b, 0x114ba3, 0x114bbb, 0x114bd3, 0x114beb,
> +      0x114bf3, 0x114c1b, 0x114c23, 0x114c48, 0x115af3,
> +      0x115b0b, 0x115b23, 0x115b68, 0x115b8b, 0x115bc3,
> +      0x115beb, 0x115bf3, 0x115c18, 0x115dc3, 0x115de8,
> +      0x11630b, 0x116333, 0x1163bb, 0x1163d3, 0x1163eb,
> +      0x1163f3, 0x116418, 0x116ab3, 0x116acb, 0x116ad3,
> +      0x116aeb, 0x116b03, 0x116b6b, 0x116b73, 0x116b88,
> +      0x1171d3, 0x117208, 0x117223, 0x11726b, 0x117273,
> +      0x1172c8, 0x1182cb, 0x1182f3, 0x11838b, 0x118393,
> +      0x1183b8, 0x119303, 0x11931b, 0x119368, 0x11937b,
> +      0x119398, 0x1193b3, 0x1193db, 0x1193e3, 0x1193f9,
> +      0x11940b, 0x119419, 0x11942b, 0x119433, 0x119448,
> +      0x119d1b, 0x119d43, 0x119d88, 0x119da3, 0x119dcb,
> +      0x119e03, 0x119e18, 0x119e4b, 0x119e58, 0x11a013,
> +      0x11a0b8, 0x11a333, 0x11a39b, 0x11a3a9, 0x11a3b3,
> +      0x11a3f8, 0x11a473, 0x11a488, 0x11a513, 0x11a57b,
> +      0x11a593, 0x11a5c8, 0x11a849, 0x11a8a3, 0x11a97b,
> +      0x11a983, 0x11a9a8, 0x11c2fb, 0x11c303, 0x11c378,
> +      0x11c383, 0x11c3eb, 0x11c3f3, 0x11c408, 0x11c923,
> +      0x11ca88, 0x11ca9b, 0x11caa3, 0x11cb1b, 0x11cb23,
> +      0x11cb4b, 0x11cb53, 0x11cb78, 0x11d313, 0x11d378,
> +      0x11d3a3, 0x11d3b8, 0x11d3c3, 0x11d3e8, 0x11d3f3,
> +      0x11d469, 0x11d473, 0x11d488, 0x11d8ab, 0x11d8f8,
> +      0x11d903, 0x11d928, 0x11d93b, 0x11d953, 0x11d96b,
> +      0x11d973, 0x11d988, 0x11ef33, 0x11ef5b, 0x11ef78,
> +      0x11f003, 0x11f029, 0x11f03b, 0x11f048, 0x11f34b,
> +      0x11f363, 0x11f3b8, 0x11f3eb, 0x11f403, 0x11f41b,
> +      0x11f423, 0x11f438, 0x134302, 0x134403, 0x134418,
> +      0x134473, 0x134568, 0x16af03, 0x16af58, 0x16b303,
> +      0x16b378, 0x16f4f3, 0x16f508, 0x16f51b, 0x16f888,
> +      0x16f8f3, 0x16f938, 0x16fe43, 0x16fe58, 0x16ff0b,
> +      0x16ff28, 0x1bc9d3, 0x1bc9f8, 0x1bca02, 0x1bca48,
> +      0x1cf003, 0x1cf2e8, 0x1cf303, 0x1cf478, 0x1d1653,
> +      0x1d166b, 0x1d1673, 0x1d16a8, 0x1d16db, 0x1d16e3,
> +      0x1d1732, 0x1d17b3, 0x1d1838, 0x1d1853, 0x1d18c8,
> +      0x1d1aa3, 0x1d1ae8, 0x1d2423, 0x1d2458, 0x1da003,
> +      0x1da378, 0x1da3b3, 0x1da6d8, 0x1da753, 0x1da768,
> +      0x1da843, 0x1da858, 0x1da9b3, 0x1daa08, 0x1daa13,
> +      0x1dab08, 0x1e0003, 0x1e0078, 0x1e0083, 0x1e0198,
> +      0x1e01b3, 0x1e0228, 0x1e0233, 0x1e0258, 0x1e0263,
> +      0x1e02b8, 0x1e08f3, 0x1e0908, 0x1e1303, 0x1e1378,
> +      0x1e2ae3, 0x1e2af8, 0x1e2ec3, 0x1e2f08, 0x1e4ec3,
> +      0x1e4f08, 0x1e8d03, 0x1e8d78, 0x1e9443, 0x1e94b8,
> +      0x1f1e6a, 0x1f2008, 0x1f3fb3, 0x1f4008, 0xe00002,
> +      0xe00203, 0xe00802, 0xe01003, 0xe01f02, 0xe10008,
> +    };
> +
> +    constexpr uint32_t __mask = (1 << __shift_bits) - 1;
> +    auto* __end = std::end(__gcb_edges);
> +    auto* __p = std::lower_bound(__gcb_edges, __end, __c << __shift_bits);
> +    return _Gcb_property(__p[-1] & __mask);
> +  }
> +
> +  // Implement the Grapheme Cluster Boundary Rules from Unicode Annex #29
> +  // http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundary_Rules
> +  // This implements an outdated version of the rules from TR29 revision 27.
> +  constexpr bool
> +  __is_grapheme_cluster_break(_Gcb_property __p1, _Gcb_property __p2)
> +  {
> +    using enum _Gcb_property;
> +
> +    if (__p1 == _Gcb_Control || __p1 == _Gcb_LF)
> +      return true; // Break after Control or LF.
> +
> +    if (__p1 == _Gcb_CR)
> +      return __p2 != _Gcb_LF; // Do not break between a CR and LF.
> +
> +    if (__p2 == _Gcb_Control || __p2 == _Gcb_CR || __p2 == _Gcb_LF)
> +      return true; // Break before Control, CR or LF.
> +
> +    if (__p1 == _Gcb_L)
> +      switch (__p2)
> +      {
> +       case _Gcb_L:
> +       case _Gcb_V:
> +       case _Gcb_LV:
> +       case _Gcb_LVT:
> +         return false; // Do not break Hangul syllable sequences.
> +       default:
> +         return true;
> +      }
> +
> +    if (__p1 == _Gcb_LV || __p1 == _Gcb_V)
> +      switch (__p2)
> +      {
> +       case _Gcb_V:
> +       case _Gcb_T:
> +         return false; // Do not break Hangul syllable sequences.
> +       default:
> +         return true;
> +      }
> +
> +    if (__p1 == _Gcb_LVT || __p1 == _Gcb_T)
> +      return __p2 != _Gcb_T; // Do not break Hangul syllable sequences.
> +
> +    if (__p1 == _Gcb_Regional_Indicator && __p2 == _Gcb_Regional_Indicator)
> +      return false; // Do not break between regional indicator symbols.
> +
> +    if (__p2 == _Gcb_Extend || __p2 == _Gcb_ZWJ)
> +      return false; // Do not break before extending characters or ZWJ.
> +
> +    // The following two rules only apply to extended grapheme clusters,
> +    // which is what the C++ standard uses (not legacy grapheme clusters).
> +    if (__p2 == _Gcb_SpacingMark)
> +      return false; // Do not break before SpacingMarks,
> +    if (__p1 == _Gcb_Prepend)
> +      return false; // or after Prepend characters.
> +
> +    // TODO:
> +    // Do not break within certain combinations with
> +    // Indic_Conjunct_Break (InCB)=Linker.
> +
> +    // TODO:
> +    // Do not break within emoji modifier sequences or emoji zwj sequences.
> +
> +    // TODO:
> +    // Do not break within emoji flag sequences. That is, do not break
> +    // between regional indicator (RI) symbols if there is an odd number
> +    // of RI characters before the break point.
> +
> +    return true; // Otherwise, break everywhere.
> +  }
> +
> +  // Return the field width of a string.
> +  template<typename _CharT>
> +    constexpr size_t
> +    __field_width(basic_string_view<_CharT> __s)
> +    {
> +      if (__s.empty()) [[unlikely]]
> +       return 0;
> +
> +      _Utf32_view __us(__s);
> +      auto __it = __us.begin();
> +      const auto __end = __us.end();
> +      char32_t __c = *__it;
> +      auto __prop = __grapheme_cluster_break_property(__c);
> +      size_t __n = __field_width(__c);
> +      while (++__it != __end)
> +       {
> +         const auto __prev = __prop;
> +         __c = *__it;
> +         __prop = __grapheme_cluster_break_property(__c);
> +         if (__is_grapheme_cluster_break(__prev, __prop))
> +           __n += __field_width(__c);
> +       }
> +      return __n;
> +    }
> +
> +  // Truncate a string to at most `__max` field width units, and return the
> +  // resulting field width.
> +  template<typename _CharT>
> +    constexpr size_t
> +    __truncate(basic_string_view<_CharT>& __s, size_t __max)
> +    {
> +      if (__s.empty()) [[unlikely]]
> +       return 0;
> +
> +      _Utf32_view __us(__s);
> +      auto __it = __us.begin();
> +      const auto __end = __us.end();
> +      char32_t __c = *__it;
> +      auto __prop = __grapheme_cluster_break_property(__c);
> +      size_t __n = __field_width(__c);
> +      if (__n > __max)
> +       {
> +         __s = {};
> +         return 0;
> +       }
> +      while (++__it != __end)
> +       {
> +         const auto __prev = __prop;
> +         __c = *__it;
> +         __prop = __grapheme_cluster_break_property(__c);
> +         if (__is_grapheme_cluster_break(__prev, __prop))
> +           {
> +             size_t __n2 = __n + __field_width(__c);
> +             if (__n2 > __max)
> +               {
> +                 __s = basic_string_view<_CharT>(__s.begin(), __it.base());
> +                 return __n;
> +               }
> +             __n = __n2;
> +           }
> +       }
> +      return __n;
> +    }
> +
> +    template<typename _CharT>
> +    consteval bool
> +    __literal_encoding_is_unicode()
> +    {
> +      if constexpr (is_same_v<_CharT, char8_t>)
> +       return true;
> +      else if constexpr (is_same_v<_CharT, char16_t>)
> +       return true;
> +      else if constexpr (is_same_v<_CharT, char32_t>)
> +         return true;
> +
> +      const char* __enc = "";
> +
> +#ifdef __GNUC_EXECUTION_CHARSET_NAME
> +      auto __remove_iso10646_prefix = [](const char* __s) {
> +       // GNU iconv allows "ISO-10646/" prefix (case-insensitive).
> +       if (__s[0] == 'I' || __s[0] == 'i')
> +         if (__s[1] == 'S' || __s[1] == 's')
> +           if (__s[2] == 'O' || __s[2] == 'o')
> +             if (string_view(__s + 3).starts_with("-10646/"))
> +               return __s + 10;
> +       return __s;
> +      };
> +
> +      if constexpr (is_same_v<_CharT, char>)
> +       __enc = __remove_iso10646_prefix(__GNUC_EXECUTION_CHARSET_NAME);
> +# if defined _GLIBCXX_USE_WCHAR_T && defined __GNUC_WIDE_EXECUTION_CHARSET_NAME
> +      else
> +       __enc = __remove_iso10646_prefix(__GNUC_WIDE_EXECUTION_CHARSET_NAME);
> +# endif
> +
> +      if ((__enc[0] == 'U' || __enc[0] == 'u')
> +           && (__enc[1] == 'T' || __enc[1] == 't')
> +           && (__enc[2] == 'F' || __enc[2] == 'f'))
> +       {
> +         __enc += 3;
> +         if (__enc[0] == '-')
> +           ++__enc;
> +         if (__enc[0] == '8')
> +           return __enc[1] == '\0' || string_view(__enc + 1) == "//";
> +         else if constexpr (!is_same_v<_CharT, char>)
> +           {
> +             string_view __s(__enc);
> +             if (__s.ends_with("//"))
> +               __s.remove_suffix(2);
> +             return __s == "16" || __s == "32";
> +           }
> +       }
> +#elif defined __clang_literal_encoding__
> +      if constexpr (is_same_v<_CharT, char>)
> +       __enc = __clang_literal_encoding__;
> +# if defined _GLIBCXX_USE_WCHAR_T && defined __clang_wide_literal_encoding__
> +      else
> +       __enc = __clang_wide_literal_encoding__;
> +# endif
> +      // Clang accepts "-fexec-charset=utf-8" but the macro is still uppercase.
> +      string_view __s(__enc);
> +      if (__s == "UTF-8")
> +       return true;
> +      else if constexpr (!is_same_v<_CharT, char>)
> +       return __s == "UTF-16" || __s == "UTF-32";
> +#endif
> +
> +      return false;
> +    }
> +
> +  consteval bool
> +  __literal_encoding_is_utf8()
> +  { return __literal_encoding_is_unicode<char>(); }
> +
> +} // namespace __unicode
> +
> +_GLIBCXX_END_NAMESPACE_VERSION
> +} // namespace std
> +#endif // C++20
> +#endif // _GLIBCXX_UNICODE_H
> diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
> index 1110ba4ab16..0633fdf5dd1 100644
> --- a/libstdc++-v3/include/std/format
> +++ b/libstdc++-v3/include/std/format
> @@ -50,9 +50,11 @@
>  #include <string>
>  #include <variant>            // monostate (TODO: move to bits/utility.h?)
>  #include <bits/ranges_base.h>  // input_range, range_reference_t
> +#include <bits/ranges_util.h>  // subrange
>  #include <bits/ranges_algobase.h> // ranges::copy
>  #include <bits/stl_iterator.h> // back_insert_iterator
>  #include <bits/stl_pair.h>     // __is_pair
> +#include <bits/unicode.h>      // __is_scalar_value, _Utf_view, etc.
>  #include <bits/utility.h>      // tuple_size_v
>  #include <ext/numeric_traits.h> // __int_traits
>
> @@ -346,44 +348,6 @@ namespace __format
>      _WP_from_arg // Use a formatting argument for width/prec.
>    };
>
> -  consteval bool
> -  __literal_encoding_is_utf8()
> -  {
> -#ifdef __GNUC_EXECUTION_CHARSET_NAME
> -    const char* __enc = __GNUC_EXECUTION_CHARSET_NAME;
> -    // GNU iconv allows "ISO-10646/" prefix (case-insensitive).
> -    if (__enc[0] == 'I' || __enc[0] == 'i')
> -      {
> -       if ((__enc[1] == 'S' || __enc[1] == 's')
> -             && (__enc[2] == 'O' || __enc[2] == 'o'))
> -         {
> -           __enc += 3;
> -           if (string_view(__enc).starts_with("-10646/"))
> -             __enc += 7;
> -           else
> -             return false;
> -         }
> -       else
> -         return false;
> -      }
> -
> -    if ((__enc[0] == 'U' || __enc[0] == 'u')
> -         && (__enc[1] == 'T' || __enc[1] == 't')
> -         && (__enc[2] == 'F' || __enc[2] == 'f'))
> -      {
> -       __enc += 3;
> -       if (__enc[0] == '-')
> -         ++__enc;
> -       if (__enc[0] == '8')
> -         return __enc[1] == '\0' || string_view(__enc + 1) == "//";
> -      }
> -#elif defined __clang_literal_encoding__
> -    // Clang accepts "-fexec-charset=utf-8" but the macro is still uppercase.
> -    return string_view(__clang_literal_encoding__) == "UTF-8";
> -#endif
> -    return false;
> -  }
> -
>    template<typename _Context>
>      size_t
>      __int_from_arg(const basic_format_arg<_Context>& __arg);
> @@ -407,7 +371,7 @@ namespace __format
>        _Pres_type _M_type : 4;
>        unsigned short _M_width;
>        unsigned short _M_prec;
> -      _CharT _M_fill = ' ';
> +      char32_t _M_fill = ' ';
>
>        using iterator = typename basic_string_view<_CharT>::iterator;
>
> @@ -429,17 +393,32 @@ namespace __format
>        {
>         if (*__first != '{')
>           {
> -           // TODO: accept any UCS scalar value as fill character.
> -           // If narrow source encoding is UTF-8 then accept multibyte char.
> -           if (__last - __first >= 2)
> +           using namespace __unicode;
> +           if constexpr (__literal_encoding_is_unicode<_CharT>())
>               {
> -               if (_Align __align = _S_align(__first[1]))
> +               // Accept any UCS scalar value as fill character.
> +               _Utf32_view __uv(ranges::subrange(__first, __last));
> +               if (!__uv.empty())
>                   {
> -                   _M_fill = *__first;
> -                   _M_align = __align;
> -                   return __first + 2;
> +                   auto __beg = __uv.begin();
> +                   char32_t __c = *__beg++;
> +                   if (__is_scalar_value(__c))
> +                     if (auto __next = __beg.base(); __next != __last)
> +                       if (_Align __align = _S_align(*__next))
> +                         {
> +                           _M_fill = __c;
> +                           _M_align = __align;
> +                           return ++__next;
> +                         }
>                   }
>               }
> +           else if (__last - __first >= 2)
> +             if (_Align __align = _S_align(__first[1]))
> +               {
> +                 _M_fill = *__first;
> +                 _M_align = __align;
> +                 return __first + 2;
> +               }
>
>             if (_Align __align = _S_align(__first[0]))
>               {
> @@ -646,7 +625,7 @@ namespace __format
>    template<typename _Out, typename _CharT>
>      _Out
>      __write_padded(_Out __out, basic_string_view<_CharT> __str,
> -                  _Align __align, size_t __nfill, _CharT __fill_char)
> +                  _Align __align, size_t __nfill, char32_t __fill_char)
>      {
>        const size_t __buflen = 0x20;
>        _CharT __padding_chars[__buflen];
> @@ -684,12 +663,30 @@ namespace __format
>           __r = __nfill;
>           __max = __r;
>         }
> +
> +      using namespace __unicode;
> +      if constexpr (__literal_encoding_is_unicode<_CharT>())
> +       if (!__is_single_code_unit<_CharT>(__fill_char)) [[unlikely]]
> +         {
> +           // Encode fill char as multiple code units of type _CharT.
> +           const char32_t __arr[1]{ __fill_char };
> +           _Utf_view<_CharT, const char32_t(&)[1]> __v(__arr);
> +           basic_string<_CharT> __padstr(__v.begin(), __v.end());
> +           __padding = __padstr;
> +           while (__l-- > 0)
> +             __out = __format::__write(std::move(__out), __padding);
> +           __out = __format::__write(std::move(__out), __str);
> +           while (__r-- > 0)
> +             __out = __format::__write(std::move(__out), __padding);
> +           return __out;
> +         }
> +
>        if (__max < __buflen)
>         __padding.remove_suffix(__buflen - __max);
>        else
>         __max = __buflen;
> -      char_traits<_CharT>::assign(__padding_chars, __max, __fill_char);
>
> +      char_traits<_CharT>::assign(__padding_chars, __max, __fill_char);
>        __pad(__l, __out);
>        __out = __format::__write(std::move(__out), __str);
>        __pad(__r, __out);
> @@ -870,16 +867,21 @@ namespace __format
>                 && _M_spec._M_prec_kind == _WP_none)
>             return __format::__write(__fc.out(), __s);
>
> -         size_t __estimated_width = __s.size(); // TODO: Unicode-aware estim.
> -
> -         if (_M_spec._M_prec_kind != _WP_none)
> +         size_t __estimated_width;
> +         if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>())
>             {
> -             size_t __prec = _M_spec._M_get_precision(__fc);
> -             if (__estimated_width > __prec)
> +             if (_M_spec._M_prec_kind != _WP_none)
>                 {
> -                 __s = __s.substr(0, __prec); // TODO: do not split code points
> -                 __estimated_width = __prec;
> +                 size_t __prec = _M_spec._M_get_precision(__fc);
> +                 __estimated_width = __unicode::__truncate(__s, __prec);
>                 }
> +             else
> +               __estimated_width = __unicode::__field_width(__s);
> +           }
> +         else
> +           {
> +             __s = __s.substr(0, _M_spec._M_get_precision(__fc));
> +             __estimated_width = __s.size();
>             }
>
>           return __format::__write_padded_as_spec(__s, __estimated_width,
> @@ -1221,7 +1223,7 @@ namespace __format
>           if (__width <= __str.size())
>             return __format::__write(__fc.out(), __str);
>
> -         _CharT __fill_char = _M_spec._M_fill;
> +         char32_t __fill_char = _M_spec._M_fill;
>           _Align __align = _M_spec._M_align;
>
>           size_t __nfill = __width - __str.size();
> @@ -1686,7 +1688,7 @@ namespace __format
>           if (__width <= __str.size())
>             return __format::__write(__fc.out(), __str);
>
> -         _CharT __fill_char = _M_spec._M_fill;
> +         char32_t __fill_char = _M_spec._M_fill;
>           _Align __align = _M_spec._M_align;
>
>           size_t __nfill = __width - __str.size();
> diff --git a/libstdc++-v3/include/std/ostream b/libstdc++-v3/include/std/ostream
> index a4ef92c04b2..4dff0cf645d 100644
> --- a/libstdc++-v3/include/std/ostream
> +++ b/libstdc++-v3/include/std/ostream
> @@ -982,7 +982,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      print(ostream& __os, format_string<_Args...> __fmt, _Args&&... __args)
>      {
>        auto __fmtargs = std::make_format_args(std::forward<_Args>(__args)...);
> -      if constexpr (__format::__literal_encoding_is_utf8())
> +      if constexpr (__unicode::__literal_encoding_is_utf8())
>         std::vprint_unicode(__os, __fmt.get(), __fmtargs);
>        else
>         std::vprint_nonunicode(__os, __fmt.get(), __fmtargs);
> diff --git a/libstdc++-v3/include/std/print b/libstdc++-v3/include/std/print
> index bb029610d70..f44256c5dca 100644
> --- a/libstdc++-v3/include/std/print
> +++ b/libstdc++-v3/include/std/print
> @@ -104,7 +104,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      print(FILE* __stream, format_string<_Args...> __fmt, _Args&&... __args)
>      {
>        auto __fmtargs = std::make_format_args(std::forward<_Args>(__args)...);
> -      if constexpr (__format::__literal_encoding_is_utf8())
> +      if constexpr (__unicode::__literal_encoding_is_utf8())
>         std::vprint_unicode(__stream, __fmt.get(), __fmtargs);
>        else
>         std::vprint_nonunicode(__stream, __fmt.get(), __fmtargs);
> diff --git a/libstdc++-v3/src/c++23/print.cc b/libstdc++-v3/src/c++23/print.cc
> index be9762bbfdc..aceca6f9139 100644
> --- a/libstdc++-v3/src/c++23/print.cc
> +++ b/libstdc++-v3/src/c++23/print.cc
> @@ -162,7 +162,7 @@ namespace
>                     }
>                   continue;
>                 }
> -             else if (byte < 0xC2)
> +             else if (byte < 0xC2) [[unlikely]]
>                 {
>                   if constexpr (transcode)
>                     out.push_back(0xFFFD);
> diff --git a/libstdc++-v3/testsuite/ext/unicode/view.cc b/libstdc++-v3/testsuite/ext/unicode/view.cc
> new file mode 100644
> index 00000000000..eaab5c79edc
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/ext/unicode/view.cc
> @@ -0,0 +1,102 @@
> +// { dg-do run { target c++20 } }
> +#include <format>
> +#include <string_view>
> +#include <ranges>
> +#include <testsuite_hooks.h>
> +
> +namespace uc = std::__unicode;
> +using namespace std::string_view_literals;
> +
> +constexpr void
> +test_utf8_to_utf8()
> +{
> +  const std::u8string_view s8 = u8"£🇬🇧 €🇪🇺 æбçδé ♠♥♦♣ 🤡";
> +  uc::_Utf8_view v(s8);
> +  VERIFY( std::ranges::distance(v) == s8.size() );
> +  VERIFY( std::ranges::equal(v,  s8) );
> +}
> +
> +constexpr void
> +test_utf8_to_utf16()
> +{
> +  const std::u8string_view s8  = u8"£🇬🇧 €🇪🇺 æбçδé ♠♥♦♣ 🤡";
> +  const std::u16string_view s16 = u"£🇬🇧 €🇪🇺 æбçδé ♠♥♦♣ 🤡";
> +  uc::_Utf16_view v(s8);
> +  VERIFY( std::ranges::distance(v) == s16.size() );
> +  VERIFY( std::ranges::equal(v,  s16) );
> +}
> +
> +constexpr void
> +test_utf8_to_utf32()
> +{
> +  const auto s8 = u8"£🇬🇧 €🇪🇺 æбçδé ♠♥♦♣ 🤡"sv;
> +  const auto s32 = U"£🇬🇧 €🇪🇺 æбçδé ♠♥♦♣ 🤡"sv;
> +  uc::_Utf32_view v(s8);
> +  VERIFY( std::ranges::distance(v) == s32.size() );
> +  VERIFY( std::ranges::equal(v,  s32) );
> +}
> +
> +constexpr void
> +test_illformed_utf8()
> +{
> +  uc::_Utf32_view v("\xa3 10.99 \xee \xdd"sv);
> +  VERIFY( std::ranges::equal(v, U"\uFFFD 10.99 \uFFFD \uFFFD"sv) );
> +
> +  uc::_Utf16_view v2(" \xf8\x80\x80\x80 "sv);
> +  VERIFY( std::ranges::distance(v2) == 6 );
> +  VERIFY( std::ranges::equal(v2, U" \uFFFD\uFFFD\uFFFD\uFFFD "sv) );
> +
> +  // Examples of U+FFFD substitution from Unicode standard.
> +  uc::_Utf8_view v3("\xc0\xaf\xe0\x80\xbf\xf0\x81\x82\x41"sv); // Table 3-8
> +  VERIFY( std::ranges::equal(v3, u8"\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\x41"sv) );
> +  uc::_Utf8_view v4("\xed\xa0\x80\xed\xbf\xbf\xed\xaf\x41"sv); // Table 3-9
> +  VERIFY( std::ranges::equal(v4, u8"\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\x41"sv) );
> +  uc::_Utf8_view v5("\xf4\x91\x92\x93\xff\x41\x80\xbf\x42"sv); // Table 3-10
> +  VERIFY( std::ranges::equal(v5, u8"\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\x41\uFFFD\uFFFD\x42"sv) );
> +  uc::_Utf8_view v6("\xe1\x80\xe2\xf0\x91\x92\xf1\xbf\x41"sv); // Table 3-11
> +  VERIFY( std::ranges::equal(v6, u8"\uFFFD\uFFFD\uFFFD\uFFFD\x41"sv) );
> +}
> +
> +constexpr void
> +test_illformed_utf16()
> +{
> +  std::u16string_view s = u"\N{CLOWN FACE}";
> +  std::u16string_view r = u"\uFFFD";
> +  VERIFY( std::ranges::equal(uc::_Utf16_view(s.substr(0, 1)), r) );
> +  VERIFY( std::ranges::equal(uc::_Utf16_view(s.substr(1, 1)), r) );
> +  std::array s2{ s[0], s[0] };
> +  VERIFY( std::ranges::equal(uc::_Utf16_view(s2), u"\uFFFD\uFFFD"sv) );
> +  std::array s3{ s[0], s[0], s[1] };
> +  VERIFY( std::ranges::equal(uc::_Utf16_view(s3), u"\uFFFD\N{CLOWN FACE}"sv) );
> +  std::array s4{ s[1], s[0] };
> +  VERIFY( std::ranges::equal(uc::_Utf16_view(s4), u"\uFFFD\uFFFD"sv) );
> +  std::array s5{ s[1], s[0], s[1] };
> +  VERIFY( std::ranges::equal(uc::_Utf16_view(s5), u"\uFFFD\N{CLOWN FACE}"sv) );
> +}
> +
> +constexpr void
> +test_illformed_utf32()
> +{
> +  std::u32string_view s = U"\x110000";
> +  VERIFY( std::ranges::equal(uc::_Utf32_view(s), U"\uFFFD"sv) );
> +  s = U"\xFFFFFF";
> +  VERIFY( std::ranges::equal(uc::_Utf32_view(s), U"\uFFFD"sv) );
> +  s = U"\xFFFFFFF0";
> +  VERIFY( std::ranges::equal(uc::_Utf32_view(s), U"\uFFFD"sv) );
> +}
> +
> +int main()
> +{
> +  auto run_tests = []{
> +    test_utf8_to_utf8();
> +    test_utf8_to_utf16();
> +    test_utf8_to_utf32();
> +    test_illformed_utf8();
> +    test_illformed_utf16();
> +    test_illformed_utf32();
> +    return true;
> +  };
> +
> +  VERIFY( run_tests() );
> +  static_assert( run_tests() );
> +}
> diff --git a/libstdc++-v3/testsuite/std/format/functions/format.cc b/libstdc++-v3/testsuite/std/format/functions/format.cc
> index b3b4f0647bc..a7b9afbccb0 100644
> --- a/libstdc++-v3/testsuite/std/format/functions/format.cc
> +++ b/libstdc++-v3/testsuite/std/format/functions/format.cc
> @@ -1,3 +1,4 @@
> +// { dg-options "-fexec-charset=UTF-8" }
>  // { dg-do run { target c++20 } }
>  // { dg-add-options no_pch }
>
> @@ -85,6 +86,18 @@ test_std_examples()
>      VERIFY(s5 == "   120");
>      string s6 = format("{:6}", true);
>      VERIFY(s6 == "true  ");
> +    string s7 = format("{:*<6.3}", "123456");
> +    VERIFY( s7 == "123***" );
> +    string s8 = format("{:02}", 1234);
> +    VERIFY( s8 == "1234" );
> +    string s9 = format("{:*<}", "12");
> +    VERIFY( s9 == "12" );
> +    string sA = format("{:*<6}", "12345678");
> +    VERIFY( sA == "12345678" );
> +    string sB = format("{:🤡^6}", "x");
> +    VERIFY( sB == "🤡🤡x🤡🤡🤡" );
> +    string sC = format("{:*^6}", "🤡🤡🤡");
> +    VERIFY( sC == "🤡🤡🤡" );
>    }
>
>    // sign
> @@ -439,6 +452,63 @@ test_bool()
>    VERIFY( s == "0 0x1 0X0" );
>  }
>
> +void
> +test_unicode()
> +{
> +  // Similar to sC example in test_std_examples, but not from the standard.
> +  // Verify that the character "🤡" has estimated field width 2,
> +  // rather than estimated field width equal to strlen("🤡"), which would be 4.
> +  std::string sC = std::format("{:*<3}", "🤡");
> +  VERIFY( sC == "🤡*" );
> +
> +  // Verify that "£" has estimated field width 1, not strlen("£") == 2.
> +  std::string sL = std::format("{:*<3}", "£");
> +  VERIFY( sL == "£**" );
> +
> +  // Verify that precision is measured in field width units (column positions)
> +  // not bytes. The result should contain complete Unicode characters, not be
> +  // truncated in the middle of a multibyte UTF-8 sequence. The string "£" has
> +  // field width 1 despite being 2 bytes, and the string "🤡" has field width 2
> +  // and so cannot be formatted into a replacement field using .1 precision.
> +  std::string sP = std::format("{:1.1} {:*<1.1}", "£", "🤡");
> +  VERIFY( sP == "£ *" );
> +  sP = std::format("{:*<2.1} {:*<2.1}", "£", "🤡");
> +  VERIFY( sP == "£* **" );
> +
> +  // Verify field width handling for extended grapheme clusters,
> +  // and that a cluster gets output as a single item, not truncated.
> +  std::string sG = std::format("{:*>2.1}", "\u006f\u0302\u0323!");
> +  VERIFY( sG == "*\u006f\u0302\u0323" );
> +
> +  // Examples from P1868R2
> +  // https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1868r2.html
> +  const char* inputs[][2] = {
> +    {"\x41",         "    \u0041"},
> +    {"\xC3\x81",     "    \u00c1"},
> +    {"\x41\xCC\x81", "    \u0041\u0301"},
> +    {"\xc4\xb2", "    \u0132"},
> +    {"\xce\x94", "    \u0394"},
> +    {"\xd0\xa9", "    \u0429"},
> +    {"\xd7\x90", "    \u05D0"},
> +    {"\xd8\xb4", "    \u0634"},
> +    {"\xe3\x80\x89", "   \u3009"},
> +    {"\xe7\x95\x8c", "   \u754C"},
> +    {"\xf0\x9f\xa6\x84", "   \U0001F984"},
> +    {"\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa9\xe2\x80\x8d"
> +     "\xf0\x9f\x91\xa7\xe2\x80\x8d\xf0\x9f\x91\xa6",
> +     // FIXME: Revision 33 of Unicode Standard Annex #29 says that this
> +     // emoji sequence should be a single grapheme cluster.
> +     // "   \U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466" }
> +     // Libstdc++ currently doesn't support that, giving this result:
> +     "\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466" }
> +  };
> +  for (auto& input : inputs)
> +  {
> +    std::string sA = std::format("{:>5}", input[0]);
> +    VERIFY( sA == input[1] );
> +  }
> +}
> +
>  int main()
>  {
>    test_no_args();
> @@ -453,4 +523,5 @@ int main()
>    test_p1652r1();
>    test_pointer();
>    test_bool();
> +  test_unicode();
>  }
> --
> 2.43.0
>



More information about the Libstdc++ mailing list