├── .gitignore ├── LICENSE.txt ├── Makefile ├── README.md ├── data-6.3.0 ├── CompositionExclusions.txt ├── NormalizationTest.txt ├── UnicodeData.txt ├── allkeys.txt └── fetch-collation-data.sh ├── miniutf.cpp ├── miniutf.hpp ├── miniutf_collation.cpp ├── miniutf_collation.hpp ├── miniutfdata.h ├── miniutfdata_collation.h ├── preprocess.py └── test.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | test 2 | test.dSYM 3 | data-*/CollationTest* 4 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Dropbox, Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TEST_SRCS = miniutf.cpp miniutf_collation.cpp test.cpp 2 | DATA_HDRS = miniutfdata.h miniutfdata_collation.h 3 | 4 | .PHONY: clean check 5 | 6 | check: test 7 | ./test 8 | 9 | test: Makefile $(TEST_SRCS) $(DATA_HDRS) 10 | clang++ -g -Wall -Wextra -std=c++11 -stdlib=libc++ -pedantic $(TEST_SRCS) -o $@ 11 | 12 | miniutfdata.h: preprocess.py 13 | python preprocess.py > miniutfdata.h 14 | 15 | miniutfdata_collation.h: preprocess.py 16 | python preprocess.py --collation > miniutfdata_collation.h 17 | 18 | .PHONY: clean 19 | clean: 20 | rm -rf test test test.dSYM $(DATA_HDRS) 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | miniutf 2 | ======= 3 | 4 | miniutf is a C++ implementation of several basic Unicode manipulation functions. 5 | 6 | Features 7 | -------- 8 | 9 | ### UTF-8, UTF-16, UTF-32 (UCS-4) 10 | 11 | miniutf can convert between UTF-8 (`std::string`), UTF-16 (`std::u16string`), and 12 | UTF-32 / UCS-4 (`std::u32string`). The C++11 standard library provides UTF-8 and -16 encoders 13 | and decoders (`codecvt_utf8` / `codecvt_utf16`), but as of late 2013, libstdc++ doesn't 14 | implement them. Miniutf's conversion functions also provide validity checking and can insert 15 | replacement characters if invalid input is found. 16 | 17 | ### NFC, NFD 18 | 19 | miniutf implements conversion to NFC and NFD as defined in Unicode TR15. It does not implement 20 | NFKC or NFKD. 21 | 22 | ### Collation 23 | 24 | miniutf implements collation as defined by the Default Unicode Collation Element Table, 25 | level 1 (Unicode TR10). This requires a large data table, which adds to binary size, so it's 26 | in a separate source and header file. The collation function can be used for case- and 27 | accent-insensitive searching and sorting. 28 | 29 | ### Lowercase 30 | 31 | Unicode defines a one-to-one lowercase translation for each codepoint. (This is needed for 32 | Dropbox's internal use, but should be avoided otherwise. One-to-one lowercasing does not 33 | always match the lowercase rules of a given language, e.g. German eszett, Turkish dotless i.) 34 | 35 | System Requirements 36 | ------------------- 37 | 38 | miniutf requires a recent C++11 compiler and standard library, such as Clang 3.3+ or GCC 4.8+. 39 | 40 | License 41 | ------- 42 | 43 | MIT (see LICENSE.txt) 44 | -------------------------------------------------------------------------------- /data-6.3.0/CompositionExclusions.txt: -------------------------------------------------------------------------------- 1 | # CompositionExclusions-6.3.0.txt 2 | # Date: 2012-12-11, 11:23:00 GMT [KW, LI] 3 | # 4 | # This file lists the characters for the Composition Exclusion Table 5 | # defined in UAX #15, Unicode Normalization Forms. 6 | # 7 | # This file is a normative contributory data file in the 8 | # Unicode Character Database. 9 | # 10 | # Copyright (c) 1991-2012 Unicode, Inc. 11 | # For terms of use, see http://www.unicode.org/terms_of_use.html 12 | # 13 | # For more information, see 14 | # http://www.unicode.org/unicode/reports/tr15/#Primary_Exclusion_List_Table 15 | # 16 | # For a full derivation of composition exclusions, see the derived property 17 | # Full_Composition_Exclusion in DerivedNormalizationProps.txt 18 | # 19 | 20 | # ================================================ 21 | # (1) Script Specifics 22 | # 23 | # This list of characters cannot be derived from the UnicodeData.txt file. 24 | # ================================================ 25 | 26 | 0958 # DEVANAGARI LETTER QA 27 | 0959 # DEVANAGARI LETTER KHHA 28 | 095A # DEVANAGARI LETTER GHHA 29 | 095B # DEVANAGARI LETTER ZA 30 | 095C # DEVANAGARI LETTER DDDHA 31 | 095D # DEVANAGARI LETTER RHA 32 | 095E # DEVANAGARI LETTER FA 33 | 095F # DEVANAGARI LETTER YYA 34 | 09DC # BENGALI LETTER RRA 35 | 09DD # BENGALI LETTER RHA 36 | 09DF # BENGALI LETTER YYA 37 | 0A33 # GURMUKHI LETTER LLA 38 | 0A36 # GURMUKHI LETTER SHA 39 | 0A59 # GURMUKHI LETTER KHHA 40 | 0A5A # GURMUKHI LETTER GHHA 41 | 0A5B # GURMUKHI LETTER ZA 42 | 0A5E # GURMUKHI LETTER FA 43 | 0B5C # ORIYA LETTER RRA 44 | 0B5D # ORIYA LETTER RHA 45 | 0F43 # TIBETAN LETTER GHA 46 | 0F4D # TIBETAN LETTER DDHA 47 | 0F52 # TIBETAN LETTER DHA 48 | 0F57 # TIBETAN LETTER BHA 49 | 0F5C # TIBETAN LETTER DZHA 50 | 0F69 # TIBETAN LETTER KSSA 51 | 0F76 # TIBETAN VOWEL SIGN VOCALIC R 52 | 0F78 # TIBETAN VOWEL SIGN VOCALIC L 53 | 0F93 # TIBETAN SUBJOINED LETTER GHA 54 | 0F9D # TIBETAN SUBJOINED LETTER DDHA 55 | 0FA2 # TIBETAN SUBJOINED LETTER DHA 56 | 0FA7 # TIBETAN SUBJOINED LETTER BHA 57 | 0FAC # TIBETAN SUBJOINED LETTER DZHA 58 | 0FB9 # TIBETAN SUBJOINED LETTER KSSA 59 | FB1D # HEBREW LETTER YOD WITH HIRIQ 60 | FB1F # HEBREW LIGATURE YIDDISH YOD YOD PATAH 61 | FB2A # HEBREW LETTER SHIN WITH SHIN DOT 62 | FB2B # HEBREW LETTER SHIN WITH SIN DOT 63 | FB2C # HEBREW LETTER SHIN WITH DAGESH AND SHIN DOT 64 | FB2D # HEBREW LETTER SHIN WITH DAGESH AND SIN DOT 65 | FB2E # HEBREW LETTER ALEF WITH PATAH 66 | FB2F # HEBREW LETTER ALEF WITH QAMATS 67 | FB30 # HEBREW LETTER ALEF WITH MAPIQ 68 | FB31 # HEBREW LETTER BET WITH DAGESH 69 | FB32 # HEBREW LETTER GIMEL WITH DAGESH 70 | FB33 # HEBREW LETTER DALET WITH DAGESH 71 | FB34 # HEBREW LETTER HE WITH MAPIQ 72 | FB35 # HEBREW LETTER VAV WITH DAGESH 73 | FB36 # HEBREW LETTER ZAYIN WITH DAGESH 74 | FB38 # HEBREW LETTER TET WITH DAGESH 75 | FB39 # HEBREW LETTER YOD WITH DAGESH 76 | FB3A # HEBREW LETTER FINAL KAF WITH DAGESH 77 | FB3B # HEBREW LETTER KAF WITH DAGESH 78 | FB3C # HEBREW LETTER LAMED WITH DAGESH 79 | FB3E # HEBREW LETTER MEM WITH DAGESH 80 | FB40 # HEBREW LETTER NUN WITH DAGESH 81 | FB41 # HEBREW LETTER SAMEKH WITH DAGESH 82 | FB43 # HEBREW LETTER FINAL PE WITH DAGESH 83 | FB44 # HEBREW LETTER PE WITH DAGESH 84 | FB46 # HEBREW LETTER TSADI WITH DAGESH 85 | FB47 # HEBREW LETTER QOF WITH DAGESH 86 | FB48 # HEBREW LETTER RESH WITH DAGESH 87 | FB49 # HEBREW LETTER SHIN WITH DAGESH 88 | FB4A # HEBREW LETTER TAV WITH DAGESH 89 | FB4B # HEBREW LETTER VAV WITH HOLAM 90 | FB4C # HEBREW LETTER BET WITH RAFE 91 | FB4D # HEBREW LETTER KAF WITH RAFE 92 | FB4E # HEBREW LETTER PE WITH RAFE 93 | 94 | # Total code points: 67 95 | 96 | # ================================================ 97 | # (2) Post Composition Version precomposed characters 98 | # 99 | # These characters cannot be derived solely from the UnicodeData.txt file 100 | # in this version of Unicode. 101 | # 102 | # Note that characters added to the standard after the 103 | # Composition Version and which have canonical decomposition mappings 104 | # are not automatically added to this list of Post Composition 105 | # Version precomposed characters. 106 | # ================================================ 107 | 108 | 2ADC # FORKING 109 | 1D15E # MUSICAL SYMBOL HALF NOTE 110 | 1D15F # MUSICAL SYMBOL QUARTER NOTE 111 | 1D160 # MUSICAL SYMBOL EIGHTH NOTE 112 | 1D161 # MUSICAL SYMBOL SIXTEENTH NOTE 113 | 1D162 # MUSICAL SYMBOL THIRTY-SECOND NOTE 114 | 1D163 # MUSICAL SYMBOL SIXTY-FOURTH NOTE 115 | 1D164 # MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE 116 | 1D1BB # MUSICAL SYMBOL MINIMA 117 | 1D1BC # MUSICAL SYMBOL MINIMA BLACK 118 | 1D1BD # MUSICAL SYMBOL SEMIMINIMA WHITE 119 | 1D1BE # MUSICAL SYMBOL SEMIMINIMA BLACK 120 | 1D1BF # MUSICAL SYMBOL FUSA WHITE 121 | 1D1C0 # MUSICAL SYMBOL FUSA BLACK 122 | 123 | # Total code points: 14 124 | 125 | # ================================================ 126 | # (3) Singleton Decompositions 127 | # 128 | # These characters can be derived from the UnicodeData.txt file 129 | # by including all canonically decomposable characters whose 130 | # canonical decomposition consists of a single character. 131 | # 132 | # These characters are simply quoted here for reference. 133 | # See also Full_Composition_Exclusion in DerivedNormalizationProps.txt 134 | # ================================================ 135 | 136 | # 0340..0341 [2] COMBINING GRAVE TONE MARK..COMBINING ACUTE TONE MARK 137 | # 0343 COMBINING GREEK KORONIS 138 | # 0374 GREEK NUMERAL SIGN 139 | # 037E GREEK QUESTION MARK 140 | # 0387 GREEK ANO TELEIA 141 | # 1F71 GREEK SMALL LETTER ALPHA WITH OXIA 142 | # 1F73 GREEK SMALL LETTER EPSILON WITH OXIA 143 | # 1F75 GREEK SMALL LETTER ETA WITH OXIA 144 | # 1F77 GREEK SMALL LETTER IOTA WITH OXIA 145 | # 1F79 GREEK SMALL LETTER OMICRON WITH OXIA 146 | # 1F7B GREEK SMALL LETTER UPSILON WITH OXIA 147 | # 1F7D GREEK SMALL LETTER OMEGA WITH OXIA 148 | # 1FBB GREEK CAPITAL LETTER ALPHA WITH OXIA 149 | # 1FBE GREEK PROSGEGRAMMENI 150 | # 1FC9 GREEK CAPITAL LETTER EPSILON WITH OXIA 151 | # 1FCB GREEK CAPITAL LETTER ETA WITH OXIA 152 | # 1FD3 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA 153 | # 1FDB GREEK CAPITAL LETTER IOTA WITH OXIA 154 | # 1FE3 GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA 155 | # 1FEB GREEK CAPITAL LETTER UPSILON WITH OXIA 156 | # 1FEE..1FEF [2] GREEK DIALYTIKA AND OXIA..GREEK VARIA 157 | # 1FF9 GREEK CAPITAL LETTER OMICRON WITH OXIA 158 | # 1FFB GREEK CAPITAL LETTER OMEGA WITH OXIA 159 | # 1FFD GREEK OXIA 160 | # 2000..2001 [2] EN QUAD..EM QUAD 161 | # 2126 OHM SIGN 162 | # 212A..212B [2] KELVIN SIGN..ANGSTROM SIGN 163 | # 2329 LEFT-POINTING ANGLE BRACKET 164 | # 232A RIGHT-POINTING ANGLE BRACKET 165 | # F900..FA0D [270] CJK COMPATIBILITY IDEOGRAPH-F900..CJK COMPATIBILITY IDEOGRAPH-FA0D 166 | # FA10 CJK COMPATIBILITY IDEOGRAPH-FA10 167 | # FA12 CJK COMPATIBILITY IDEOGRAPH-FA12 168 | # FA15..FA1E [10] CJK COMPATIBILITY IDEOGRAPH-FA15..CJK COMPATIBILITY IDEOGRAPH-FA1E 169 | # FA20 CJK COMPATIBILITY IDEOGRAPH-FA20 170 | # FA22 CJK COMPATIBILITY IDEOGRAPH-FA22 171 | # FA25..FA26 [2] CJK COMPATIBILITY IDEOGRAPH-FA25..CJK COMPATIBILITY IDEOGRAPH-FA26 172 | # FA2A..FA6D [68] CJK COMPATIBILITY IDEOGRAPH-FA2A..CJK COMPATIBILITY IDEOGRAPH-FA6D 173 | # FA70..FAD9 [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILITY IDEOGRAPH-FAD9 174 | # 2F800..2FA1D [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D 175 | 176 | # Total code points: 1035 177 | 178 | # ================================================ 179 | # (4) Non-Starter Decompositions 180 | # 181 | # These characters can be derived from the UnicodeData.txt file 182 | # by including each expanding canonical decomposition 183 | # (i.e., those which canonically decompose to a sequence 184 | # of characters instead of a single character), such that: 185 | # 186 | # A. The character is not a Starter. 187 | # 188 | # OR (inclusive) 189 | # 190 | # B. The character's canonical decomposition begins 191 | # with a character that is not a Starter. 192 | # 193 | # Note that a "Starter" is any character with a zero combining class. 194 | # 195 | # These characters are simply quoted here for reference. 196 | # See also Full_Composition_Exclusion in DerivedNormalizationProps.txt 197 | # ================================================ 198 | 199 | # 0344 COMBINING GREEK DIALYTIKA TONOS 200 | # 0F73 TIBETAN VOWEL SIGN II 201 | # 0F75 TIBETAN VOWEL SIGN UU 202 | # 0F81 TIBETAN VOWEL SIGN REVERSED II 203 | 204 | # Total code points: 4 205 | 206 | # EOF 207 | -------------------------------------------------------------------------------- /data-6.3.0/fetch-collation-data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | curl http://www.unicode.org/Public/UCA/6.3.0/CollationTest.zip > CollationTest.zip 3 | unzip CollationTest.zip 4 | -------------------------------------------------------------------------------- /miniutf.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013 Dropbox, Inc. 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #include "miniutf.hpp" 23 | 24 | #include 25 | 26 | namespace miniutf { 27 | 28 | #include "miniutfdata.h" 29 | 30 | /* * * * * * * * * * 31 | * Encoding 32 | * * * * * * * * * */ 33 | 34 | void utf8_encode(char32_t pt, std::string & out) { 35 | if (pt < 0x80) { 36 | out += static_cast(pt); 37 | } else if (pt < 0x800) { 38 | out += { static_cast((pt >> 6) | 0xC0), 39 | static_cast((pt & 0x3F) | 0x80) }; 40 | } else if (pt < 0x10000) { 41 | out += { static_cast((pt >> 12) | 0xE0), 42 | static_cast(((pt >> 6) & 0x3F) | 0x80), 43 | static_cast((pt & 0x3F) | 0x80) }; 44 | } else if (pt < 0x110000) { 45 | out += { static_cast((pt >> 18) | 0xF0), 46 | static_cast(((pt >> 12) & 0x3F) | 0x80), 47 | static_cast(((pt >> 6) & 0x3F) | 0x80), 48 | static_cast((pt & 0x3F) | 0x80) }; 49 | } else { 50 | out += { static_cast(0xEF), 51 | static_cast(0xBF), 52 | static_cast(0xBD) }; // U+FFFD 53 | } 54 | } 55 | 56 | void utf16_encode(char32_t pt, std::u16string & out) { 57 | if (pt < 0x10000) { 58 | out += static_cast(pt); 59 | } else if (pt < 0x110000) { 60 | out += { static_cast(((pt - 0x10000) >> 10) + 0xD800), 61 | static_cast((pt & 0x3FF) + 0xDC00) }; 62 | } else { 63 | out += 0xFFFD; 64 | } 65 | } 66 | 67 | /* * * * * * * * * * 68 | * Decoding logic 69 | * * * * * * * * * */ 70 | 71 | struct offset_pt { 72 | int offset; 73 | char32_t pt; 74 | }; 75 | 76 | static constexpr const offset_pt invalid_pt = { -1, 0 }; 77 | 78 | /* 79 | * Decode a codepoint starting at str[i], and return the number of code units (bytes, for 80 | * UTF-8) consumed and the result. If no valid codepoint is at str[i], return invalid_pt. 81 | */ 82 | static offset_pt utf8_decode_check(const std::string & str, std::string::size_type i) { 83 | uint32_t b0, b1, b2, b3; 84 | 85 | b0 = static_cast(str[i]); 86 | 87 | if (b0 < 0x80) { 88 | // 1-byte character 89 | return { 1, b0 }; 90 | } else if (b0 < 0xC0) { 91 | // Unexpected continuation byte 92 | return invalid_pt; 93 | } else if (b0 < 0xE0) { 94 | // 2-byte character 95 | if (((b1 = str[i+1]) & 0xC0) != 0x80) 96 | return invalid_pt; 97 | 98 | char32_t pt = (b0 & 0x1F) << 6 | (b1 & 0x3F); 99 | if (pt < 0x80) 100 | return invalid_pt; 101 | 102 | return { 2, pt }; 103 | } else if (b0 < 0xF0) { 104 | // 3-byte character 105 | if (((b1 = str[i+1]) & 0xC0) != 0x80) 106 | return invalid_pt; 107 | if (((b2 = str[i+2]) & 0xC0) != 0x80) 108 | return invalid_pt; 109 | 110 | char32_t pt = (b0 & 0x0F) << 12 | (b1 & 0x3F) << 6 | (b2 & 0x3F); 111 | if (pt < 0x800) 112 | return invalid_pt; 113 | 114 | return { 3, pt }; 115 | } else if (b0 < 0xF8) { 116 | // 4-byte character 117 | if (((b1 = str[i+1]) & 0xC0) != 0x80) 118 | return invalid_pt; 119 | if (((b2 = str[i+2]) & 0xC0) != 0x80) 120 | return invalid_pt; 121 | if (((b3 = str[i+3]) & 0xC0) != 0x80) 122 | return invalid_pt; 123 | 124 | char32_t pt = (b0 & 0x0F) << 18 | (b1 & 0x3F) << 12 125 | | (b2 & 0x3F) << 6 | (b3 & 0x3F); 126 | if (pt < 0x10000 || pt >= 0x110000) 127 | return invalid_pt; 128 | 129 | return { 4, pt }; 130 | } else { 131 | // Codepoint out of range 132 | return invalid_pt; 133 | } 134 | } 135 | 136 | // UTF-16 decode helpers. 137 | static inline bool is_high_surrogate(char16_t c) { return (c >= 0xD800) && (c < 0xDC00); } 138 | static inline bool is_low_surrogate(char16_t c) { return (c >= 0xDC00) && (c < 0xE000); } 139 | 140 | /* 141 | * Like utf8_decode_check, but for UTF-16. 142 | */ 143 | static offset_pt utf16_decode_check(const std::u16string & str, std::u16string::size_type i) { 144 | if (is_high_surrogate(str[i]) && is_low_surrogate(str[i+1])) { 145 | // High surrogate followed by low surrogate 146 | char32_t pt = (((str[i] - 0xD800) << 10) | (str[i+1] - 0xDC00)) + 0x10000; 147 | return { 2, pt }; 148 | } else if (is_high_surrogate(str[i]) || is_low_surrogate(str[i])) { 149 | // High surrogate *not* followed by low surrogate, or unpaired low surrogate 150 | return invalid_pt; 151 | } else { 152 | return { 1, str[i] }; 153 | } 154 | } 155 | 156 | /* 157 | * UTF-32 is very easy to check. 158 | */ 159 | static offset_pt utf32_decode_check(const std::u32string & str, std::u32string::size_type i) { 160 | if (str[i] < 0x110000) { 161 | return { 1, str[i] }; 162 | } else { 163 | return invalid_pt; 164 | } 165 | } 166 | 167 | /* * * * * * * * * * 168 | * Decoding wrappers 169 | * * * * * * * * * */ 170 | 171 | char32_t utf8_decode(const std::string & str, std::string::size_type & i, 172 | bool * replacement_flag) { 173 | offset_pt res = utf8_decode_check(str, i); 174 | if (res.offset < 0) { 175 | if (replacement_flag) 176 | *replacement_flag = true; 177 | i += 1; 178 | return 0xFFFD; 179 | } else { 180 | i += res.offset; 181 | return res.pt; 182 | } 183 | } 184 | 185 | char32_t utf16_decode(const std::u16string & str, std::u16string::size_type & i, 186 | bool * replacement_flag) { 187 | offset_pt res = utf16_decode_check(str, i); 188 | if (res.offset < 0) { 189 | if (replacement_flag) 190 | *replacement_flag = true; 191 | i += 1; 192 | return 0xFFFD; 193 | } else { 194 | i += res.offset; 195 | return res.pt; 196 | } 197 | } 198 | 199 | /* * * * * * * * * * 200 | * Checking 201 | * * * * * * * * * */ 202 | 203 | template 204 | bool check_helper(const Tfunc & func, const Tstring & str) { 205 | for (typename Tstring::size_type i = 0; i < str.length(); ) { 206 | offset_pt res = func(str, i); 207 | if (res.offset < 0) 208 | return false; 209 | i += res.offset; 210 | } 211 | return true; 212 | } 213 | 214 | bool utf8_check (const std::string & str) { return check_helper(utf8_decode_check, str); } 215 | bool utf16_check(const std::u16string & str) { return check_helper(utf16_decode_check, str); } 216 | bool utf32_check(const std::u32string & str) { return check_helper(utf32_decode_check, str); } 217 | 218 | /* * * * * * * * * * 219 | * Conversion 220 | * * * * * * * * * */ 221 | 222 | std::u32string to_utf32(const std::string & str) { 223 | std::u32string out; 224 | out.reserve(str.length()); // likely overallocate 225 | for (std::string::size_type i = 0; i < str.length(); ) 226 | out += utf8_decode(str, i); 227 | return out; 228 | } 229 | 230 | std::u16string to_utf16(const std::string & str) { 231 | std::u16string out; 232 | out.reserve(str.length()); // likely overallocate 233 | for (std::string::size_type i = 0; i < str.length(); ) 234 | utf16_encode(utf8_decode(str, i), out); 235 | return out; 236 | } 237 | 238 | std::string to_utf8(const std::u16string & str) { 239 | std::string out; 240 | out.reserve(str.length() * 3 / 2); // estimate 241 | for (std::u16string::size_type i = 0; i < str.length(); ) 242 | utf8_encode(utf16_decode(str, i), out); 243 | return out; 244 | } 245 | 246 | std::string to_utf8(const std::u32string & str) { 247 | std::string out; 248 | out.reserve(str.length() * 3 / 2); // estimate 249 | for (char32_t pt : str) 250 | utf8_encode(pt, out); 251 | return out; 252 | } 253 | 254 | /* * * * * * * * * * 255 | * Lowercase 256 | * * * * * * * * * */ 257 | 258 | std::string lowercase(const std::string & str) { 259 | std::string out; 260 | out.reserve(str.size()); 261 | for (size_t i = 0; i < str.length(); ) { 262 | int32_t pt = utf8_decode(str, i); 263 | utf8_encode(pt + lowercase_offset(pt), out); 264 | } 265 | return out; 266 | } 267 | 268 | /* * * * * * * * * * 269 | * Composition 270 | * * * * * * * * * */ 271 | 272 | /* 273 | * Write the canonical decomposition of pt to out. 274 | */ 275 | static void unicode_decompose(char32_t pt, std::u32string & out) { 276 | // Special-case: Hangul decomposition 277 | if (pt >= 0xAC00 && pt < 0xD7A4) { 278 | out += 0x1100 + (pt - 0xAC00) / 588; 279 | out += 0x1161 + ((pt - 0xAC00) % 588) / 28; 280 | if ((pt - 0xAC00) % 28) 281 | out += 0x11A7 + (pt - 0xAC00) % 28; 282 | return; 283 | } 284 | 285 | // Otherwise, look up in the decomposition table 286 | int32_t decomp_start_idx = decomp_idx(pt); 287 | if (!decomp_start_idx) { 288 | out += pt; 289 | return; 290 | } 291 | 292 | size_t length = (decomp_start_idx >> 14) + 1; 293 | decomp_start_idx &= (1 << 14) - 1; 294 | 295 | for (size_t i = 0; i < length; i++) { 296 | out += xref[decomp_seq[decomp_start_idx + i]]; 297 | } 298 | } 299 | 300 | /* 301 | * If there is a Primary Composite equivalent to , return it. Otherwise return 0. 302 | */ 303 | static uint32_t unicode_compose(uint32_t L, uint32_t C) { 304 | int comp_seq_idx; 305 | 306 | /* Algorithmic Hangul composition */ 307 | if (L >= 0x1100 && L < 0x1113 && C >= 0x1161 && C < 0x1176) 308 | return ((L - 0x1100) * 21 + C - 0x1161) * 28 + 0xAC00; 309 | 310 | if (L >= 0xAC00 && L < 0xD7A4 && !((L-0xAC00)%28) && C >= 0x11A8 && C < 0x11C3) 311 | return L + C - 0x11A7; 312 | 313 | /* Predefined composition mapping */ 314 | comp_seq_idx = comp_idx(L); 315 | do { 316 | if (xref[comp_seq[comp_seq_idx*2] & ~0x8000] == C) 317 | return xref[comp_seq[comp_seq_idx*2 + 1]]; 318 | } while (!(comp_seq[(comp_seq_idx++) * 2] & 0x8000)); 319 | 320 | return 0; 321 | } 322 | 323 | std::u32string normalize32(const std::string & str, bool compose, bool * replacement_flag) { 324 | if (str.empty()) 325 | return {}; 326 | 327 | // Decode and decompose 328 | std::u32string codepoints; 329 | codepoints.reserve(str.size()); 330 | for (size_t i = 0; i < str.length(); ) { 331 | uint32_t pt = utf8_decode(str, i, replacement_flag); 332 | unicode_decompose(pt, codepoints); 333 | } 334 | 335 | // Canonical Ordering Algorithm: sort all runs of characters with nonzero combining class. 336 | size_t start = 0; 337 | while (start < codepoints.length()) { 338 | if (!ccc(codepoints[start])) { 339 | start++; 340 | continue; 341 | } 342 | 343 | size_t end = start + 1; 344 | while (end < codepoints.length() && ccc(codepoints[end])) { 345 | end++; 346 | } 347 | 348 | if (end - start > 1) { 349 | std::stable_sort(codepoints.begin() + start, codepoints.begin() + end, 350 | [] (char32_t a, char32_t b) { return ccc(a) < ccc(b); }); 351 | } 352 | 353 | start = end + 1; 354 | } 355 | 356 | if (compose) { 357 | size_t i = 1; 358 | int last_class = -1, starter_pos = 0, target_pos = 1; 359 | char32_t starter = codepoints[0]; 360 | 361 | while (i < codepoints.length()) { 362 | char32_t ch = codepoints[i]; 363 | int ch_class = ccc(ch); 364 | 365 | uint32_t composite = unicode_compose(starter, ch); 366 | if (composite && last_class < ch_class) { 367 | codepoints[starter_pos] = composite; 368 | starter = composite; 369 | } else if (ch_class == 0) { 370 | starter_pos = target_pos; 371 | starter = ch; 372 | last_class = -1; 373 | codepoints[target_pos] = ch; 374 | target_pos++; 375 | } else { 376 | last_class = ch_class; 377 | codepoints[target_pos] = ch; 378 | target_pos++; 379 | } 380 | 381 | i++; 382 | } 383 | 384 | codepoints.resize(target_pos); 385 | } 386 | 387 | return codepoints; 388 | } 389 | 390 | std::string normalize8(const std::string & str, bool compose, bool * replacement_flag) { 391 | std::u32string codepoints = normalize32(str, compose, replacement_flag); 392 | return to_utf8(codepoints); 393 | } 394 | 395 | std::string nfc(const std::string & str, bool * replacement_flag) { 396 | return normalize8(str, true, replacement_flag); 397 | } 398 | 399 | std::string nfd(const std::string & str, bool * replacement_flag) { 400 | return normalize8(str, false, replacement_flag); 401 | } 402 | 403 | } // namespace miniutf 404 | -------------------------------------------------------------------------------- /miniutf.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013 Dropbox, Inc. 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | namespace miniutf { 27 | 28 | /* 29 | * Character-at-a-time encoding. Convert pt to UTF-8/16 and append to out. 30 | * 31 | * If pt is invalid (greater than U+10FFFF), U+FFFD will be encoded instead. 32 | */ 33 | void utf8_encode(char32_t pt, std::string & out); 34 | void utf16_encode(char32_t pt, std::u16string & out); 35 | 36 | /* 37 | * Character-at-a-time decoding. Decodes and returns the codepoint starting at str[pos], 38 | * and then advance pos by the appropriate amount. 39 | * 40 | * If an invalid codepoint is found, return U+FFFD, add 1 to pos, and (if replacement_flag is 41 | * non-null) set *replacement_flag to true. 42 | */ 43 | char32_t utf8_decode(const std::string & str, 44 | std::string::size_type & pos, 45 | bool * replacement_flag = nullptr); 46 | char32_t utf16_decode(const std::u16string & str, 47 | std::u16string::size_type & pos, 48 | bool * replacement_flag = nullptr); 49 | 50 | /* 51 | * Return true if str is valid UTF-8, -16, or -32. 52 | * 53 | * - UTF-8 is valid if it contains no misplaced or missing continuation bytes, no overlong 54 | * encodings, and no codepoints above U+10FFFF. 55 | * 56 | * - UTF-16 is valid if it contains no unpaired surrogates. (There's no way to attempt 57 | * to represent codepoints above U+10FFFF in UTF-16.) 58 | * 59 | * - UTF-32 is valid if it contains no codepoints above U+10FFFF. 60 | */ 61 | bool utf8_check(const std::string & str); 62 | bool utf16_check(const std::string & str); 63 | bool utf32_check(const std::string & str); 64 | 65 | /* 66 | * Convert back and forth between UTF-8 and UTF-16 or UTF-32. 67 | * 68 | * These functions replace invalid sections of input with U+FFFD. If this is not desired, 69 | * use utf8_check (above) first to check that the input is valid. 70 | */ 71 | std::u32string to_utf32(const std::string & str); 72 | std::u16string to_utf16(const std::string & str); 73 | std::string to_utf8(const std::u16string & str); 74 | std::string to_utf8(const std::u32string & str); 75 | 76 | /* 77 | * Convert str to lowercase, per the built-in Unicode lowercasing map (codepoint-by-codepoint). 78 | */ 79 | std::string lowercase(const std::string & str); 80 | 81 | /* 82 | * Decompose str. Then, if compose is set, recompose it. 83 | * 84 | * If replacement characters are used during decoding (i.e. str contains invalid UTF-8), and 85 | * replacement_flag is specified, it will be set to true. 86 | */ 87 | std::string normalize8(const std::string & str, 88 | bool compose, 89 | bool * replacement_flag = nullptr); 90 | std::u32string normalize32(const std::string & str, 91 | bool compose, 92 | bool * replacement_flag = nullptr); 93 | 94 | /* 95 | * Convert str to Normalization Form C. Equivalent to normalize8(str, true, replacement_flag). 96 | * 97 | * If replacement characters are used during decoding (i.e. str contains invalid UTF-8), and 98 | * replacement_flag is specified, *replacement_flag will be set to true. 99 | */ 100 | std::string nfc(const std::string & str, bool * replacement_flag = nullptr); 101 | 102 | /* 103 | * Convert str to Normalization Form D. Equivalent to normalize8(in, false, replacement_flag). 104 | * 105 | * If replacement characters are used during decoding (i.e. str contains invalid UTF-8), and 106 | * replacement_flag is specified, *replacement_flag will be set to true. 107 | */ 108 | std::string nfd(const std::string & str, bool * replacement_flag = nullptr); 109 | 110 | } // namespace miniutf 111 | -------------------------------------------------------------------------------- /miniutf_collation.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013 Dropbox, Inc. 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #include "miniutf_collation.hpp" 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | namespace miniutf { 29 | 30 | #include "miniutfdata_collation.h" 31 | 32 | // The highest possible codepoint is 0x10FFFF, so we need 21 bits to represent a codepoint. 33 | #define UNICODE_CODE_SPACE_BITS 21 34 | 35 | /* Return the hash of the given range. 36 | */ 37 | template 38 | static size_t hash_key(IterType begin, IterType end) { 39 | size_t hash = 0; 40 | while (begin != end) { 41 | hash = (hash * DUCET_HASH_MULTIPLIER + *begin) % DUCET_HASH_BUCKETS; 42 | ++begin; 43 | } 44 | return hash; 45 | } 46 | 47 | /* Look up a sequence of codepoints in the DUCET. 48 | * 49 | * This function takes its input as begin/end iterators; 'end' is one-past-the-end, as usual. 50 | * 51 | * The return value is the start and length of a sequence of collation elements, if found. If 52 | * the input is found, the returned pointer will always be non-null, though the length 53 | * may be 0 to indicate an empty mapping. If not found, the returned pointer will be null. 54 | */ 55 | static std::pair find_elements(const char32_t * begin, 56 | const char32_t * end) { 57 | size_t hash = hash_key(begin, end); 58 | 59 | const uint32_t * entry = std::begin(ducet_data) + ducet_bucket_indexes[hash]; 60 | 61 | while (entry < std::end(ducet_data)) { 62 | uint32_t key_len = (entry[0] >> (DUCET_DATA_HIGH_BIT - DUCET_KEY_BITS)) 63 | & ~(~0ULL << DUCET_KEY_BITS); 64 | uint32_t value_len = (entry[0] >> (DUCET_DATA_HIGH_BIT - DUCET_KEY_BITS 65 | - DUCET_VALUE_BITS)) 66 | & ~(~0ULL << DUCET_VALUE_BITS); 67 | uint32_t first_word = entry[0] & ~(~0ULL << UNICODE_CODE_SPACE_BITS); 68 | 69 | // If this entry matches [begin, end), then we're done. 70 | if (key_len == static_cast(end - begin) 71 | && first_word == begin[0] 72 | && std::equal(entry + 1, entry + key_len, begin + 1)) { 73 | return { entry + key_len, value_len }; 74 | } 75 | 76 | // Otherwise, see if we're at the end of this hash bucket 77 | if (entry[0] & (1 << DUCET_DATA_HIGH_BIT)) { 78 | return { nullptr, 0 }; 79 | } 80 | 81 | // Move on to the next bucket. 82 | entry += key_len + value_len; 83 | } 84 | 85 | return { nullptr, 0 }; 86 | } 87 | 88 | // in miniutf.cpp. 89 | int32_t ccc(int32_t codepoint); 90 | 91 | /* 92 | * Finds the DUCET collation elements at position i in a string, adds its length to i, and 93 | * appends the collation elements to the given vector. We only deal with level 1 here. 94 | */ 95 | void get_ducet_level1(std::u32string & str, 96 | size_t & i, 97 | std::vector & elements) { 98 | 99 | assert(i < str.size()); 100 | 101 | std::pair best_key { nullptr, 0 }; 102 | size_t best_length = 0; 103 | 104 | // S2.1: Find the longest initial substring S at each point that has a match in the table. 105 | 106 | for (size_t j = 1; j <= DUCET_LONGEST_KEY && i+j <= str.length(); j++) { 107 | auto itr = find_elements(str.data() + i, str.data() + i + j); 108 | if (itr.first) { 109 | best_key = itr; 110 | best_length = j; 111 | } 112 | } 113 | 114 | // S2.1.1. If there are any non-starters following S, process each non-starter C. 115 | 116 | std::unordered_set blocked_classes; 117 | 118 | if (best_key.first) { 119 | size_t j = best_length; 120 | while (i + j <= str.length()) { 121 | const char32_t C = str[i+j]; 122 | const int32_t ccc_C = ccc(C); 123 | if (ccc_C == 0) { 124 | break; 125 | } 126 | 127 | // S2.1.2 If C is not blocked from S, find if S + C has a match in the table. 128 | // Note: A non-starter in a string is called blocked if there is another 129 | // non-starter of the same canonical combining class or zero between it and the 130 | // last character of canonical combining class 0. 131 | if (!blocked_classes.count(ccc_C)) { 132 | 133 | // TODO(j4cbo): Would be nice to eliminate this copy. 134 | std::u32string SC { str.data() + i, str.data() + i + best_length }; 135 | SC += C; 136 | 137 | auto itr = find_elements(SC.data(), SC.data() + SC.size()); 138 | 139 | // S2.1.3 If there is a match, replace S by S + C, and remove C. 140 | if (itr.first) { 141 | std::copy_backward(str.begin() + i + best_length, str.begin() + i + j, 142 | str.begin() + i + j + 1); 143 | str[i + best_length] = C; 144 | best_key = itr; 145 | best_length++; 146 | break; 147 | } 148 | } 149 | 150 | blocked_classes.emplace(ccc_C); 151 | j++; 152 | } 153 | } 154 | 155 | // S2.2 Fetch the corresponding collation element(s) from the table if there is a match. 156 | // If there is no match, synthesize a weight as described in Section 7.1, 157 | // Derived Collation Elements. 158 | 159 | if (best_key.first) { 160 | elements.insert(elements.end(), best_key.first, best_key.first + best_key.second); 161 | i += best_length; 162 | return; 163 | } 164 | 165 | // http://www.unicode.org/reports/tr10/#Derived_Collation_Elements 166 | char32_t pt = str[i]; 167 | char32_t base = 0xfbc0; 168 | ++i; 169 | 170 | // ftp://ftp.unicode.org/Public/6.3.0/ucd/PropList.txt says the Unified_Ideograph 171 | // characters are: 172 | // 3400..4DB5 [ CJK Unified Ideographs Extension A ] 173 | // 4E00..9FCC [ CJK Unified Ideographs ] 174 | // FA0E..FA0F, FA11, FA13..FA14, FA1F, FA21, FA23..FA24, FA27..FA29 175 | // [ CJK Compatibility Ideographs ] 176 | // 20000..2A6D6 [ CJK Unified Ideographs Extension B ] 177 | // 2A700..2B734 [ CJK Unified Ideographs Extension C ] 178 | // 2B740..2B81D [ CJK Unified Ideographs Extension D ] 179 | // 180 | 181 | if ((0x4e00 <= pt && pt <= 0x9fcc) || (0xfa0e <= pt && pt <= 0xfa0f) || pt == 0xfa11 182 | || pt == 0xfa13 || pt == 0xfa14 || pt == 0xfa1f || pt == 0xfa21 || pt == 0xfa23 183 | || pt == 0xfa24 || pt == 0xfa27 || pt == 0xfa28 || pt == 0xfa29) { 184 | base = 0xfb40; 185 | } else if ((0x3400 <= pt && pt <= 0x4db5) // CJK Unified Ideographs Extension A 186 | || (0x20000 <= pt && pt <= 0x2a6d6) // CJK Unified Ideographs Extension B 187 | || (0x2a700 <= pt && pt <= 0x2b734) // CJK Unified Ideographs Extension C 188 | || (0x2b740 <= pt && pt <= 0x2b81d)) { // CJK Unified Ideographs Extension D 189 | base = 0xfb80; 190 | } 191 | 192 | char32_t aaaa = base + (pt >> 15); 193 | char32_t bbbb = (pt & 0x7fff) | 0x8000; 194 | 195 | elements.push_back(aaaa); 196 | elements.push_back(bbbb); 197 | } 198 | 199 | std::vector match_key(const std::string & in) { 200 | 201 | // S1.1 Use the Unicode canonical algorithm to decompose characters according to the 202 | // canonical mappings. That is, put the string into Normalization Form D (see [UAX15]). 203 | std::u32string codepoints = normalize32(in, false, nullptr); 204 | 205 | std::vector key; 206 | key.reserve(codepoints.size()); 207 | 208 | for (size_t i = 0; i < codepoints.size(); ) { 209 | get_ducet_level1(codepoints,i,key); 210 | } 211 | 212 | return key; 213 | } 214 | 215 | } // namespace miniutf 216 | -------------------------------------------------------------------------------- /miniutf_collation.hpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013 Dropbox, Inc. 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include "miniutf.hpp" 25 | 26 | #include 27 | 28 | namespace miniutf { 29 | 30 | /* match_key(in) 31 | * 32 | * Returns the level 1 sort key (no identical level), for use in user-facing searching. 33 | * 34 | * The key is generated using a truncated version of DUCET: 35 | * http://www.unicode.org/Public/UCA/6.3.0/allkeys.txt 36 | * 37 | */ 38 | std::vector match_key(const std::string & in); 39 | 40 | } 41 | -------------------------------------------------------------------------------- /miniutfdata.h: -------------------------------------------------------------------------------- 1 | static const uint32_t xref[] = { 2 | 0, 59, 60, 61, 62, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 3 | 78, 79, 80, 82, 83, 84, 85, 86, 87, 88, 89, 90, 96, 97, 98, 99, 100, 4 | 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114, 115, 5 | 116, 117, 118, 119, 120, 121, 122, 168, 180, 183, 192, 193, 194, 195, 6 | 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 209, 210, 7 | 211, 212, 213, 214, 216, 217, 218, 219, 220, 221, 224, 225, 226, 227, 8 | 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 241, 242, 9 | 243, 244, 245, 246, 248, 249, 250, 251, 252, 253, 255, 256, 257, 258, 10 | 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 274, 11 | 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 12 | 289, 290, 291, 292, 293, 296, 297, 298, 299, 300, 301, 302, 303, 304, 13 | 308, 309, 310, 311, 313, 314, 315, 316, 317, 318, 323, 324, 325, 326, 14 | 327, 328, 332, 333, 334, 335, 336, 337, 340, 341, 342, 343, 344, 345, 15 | 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 360, 361, 16 | 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 17 | 376, 377, 378, 379, 380, 381, 382, 383, 416, 417, 431, 432, 439, 461, 18 | 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 19 | 476, 478, 479, 480, 481, 482, 483, 486, 487, 488, 489, 490, 491, 492, 20 | 493, 494, 495, 496, 500, 501, 504, 505, 506, 507, 508, 509, 510, 511, 21 | 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 22 | 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 23 | 542, 543, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 24 | 562, 563, 658, 697, 768, 769, 770, 771, 772, 774, 775, 776, 777, 778, 25 | 779, 780, 783, 785, 787, 788, 795, 803, 804, 805, 806, 807, 808, 813, 26 | 814, 816, 817, 824, 832, 833, 834, 835, 836, 837, 884, 894, 901, 902, 27 | 903, 904, 905, 906, 908, 910, 911, 912, 913, 917, 919, 921, 927, 929, 28 | 933, 937, 938, 939, 940, 941, 942, 943, 944, 945, 949, 951, 953, 959, 29 | 961, 965, 969, 970, 971, 972, 973, 974, 978, 979, 980, 1024, 1025, 30 | 1027, 1030, 1031, 1036, 1037, 1038, 1040, 1043, 1045, 1046, 1047, 31 | 1048, 1049, 1050, 1054, 1059, 1063, 1067, 1069, 1072, 1075, 1077, 32 | 1078, 1079, 1080, 1081, 1082, 1086, 1091, 1095, 1099, 1101, 1104, 33 | 1105, 1107, 1110, 1111, 1116, 1117, 1118, 1140, 1141, 1142, 1143, 34 | 1217, 1218, 1232, 1233, 1234, 1235, 1238, 1239, 1240, 1241, 1242, 35 | 1243, 1244, 1245, 1246, 1247, 1250, 1251, 1252, 1253, 1254, 1255, 36 | 1256, 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 1266, 37 | 1267, 1268, 1269, 1272, 1273, 1460, 1463, 1464, 1465, 1468, 1471, 38 | 1473, 1474, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1496, 1497, 39 | 1498, 1499, 1500, 1502, 1504, 1505, 1507, 1508, 1510, 1511, 1512, 40 | 1513, 1514, 1522, 1570, 1571, 1572, 1573, 1574, 1575, 1608, 1610, 41 | 1619, 1620, 1621, 1728, 1729, 1730, 1746, 1747, 1749, 2325, 2326, 42 | 2327, 2332, 2337, 2338, 2344, 2345, 2347, 2351, 2352, 2353, 2355, 43 | 2356, 2364, 2392, 2393, 2394, 2395, 2396, 2397, 2398, 2399, 2465, 44 | 2466, 2479, 2492, 2494, 2503, 2507, 2508, 2519, 2524, 2525, 2527, 45 | 2582, 2583, 2588, 2603, 2610, 2611, 2614, 2616, 2620, 2649, 2650, 46 | 2651, 2654, 2849, 2850, 2876, 2878, 2887, 2888, 2891, 2892, 2902, 47 | 2903, 2908, 2909, 2962, 2964, 3006, 3014, 3015, 3018, 3019, 3020, 48 | 3031, 3142, 3144, 3158, 3263, 3264, 3266, 3270, 3271, 3272, 3274, 49 | 3275, 3285, 3286, 3390, 3398, 3399, 3402, 3403, 3404, 3415, 3530, 50 | 3535, 3545, 3546, 3548, 3549, 3550, 3551, 3904, 3906, 3907, 3916, 51 | 3917, 3921, 3922, 3926, 3927, 3931, 3932, 3945, 3953, 3954, 3955, 52 | 3956, 3957, 3958, 3960, 3968, 3969, 3984, 3986, 3987, 3996, 3997, 53 | 4001, 4002, 4006, 4007, 4011, 4012, 4018, 4019, 4021, 4023, 4025, 54 | 4133, 4134, 4142, 6917, 6918, 6919, 6920, 6921, 6922, 6923, 6924, 55 | 6925, 6926, 6929, 6930, 6965, 6970, 6971, 6972, 6973, 6974, 6975, 56 | 6976, 6977, 6978, 6979, 7680, 7681, 7682, 7683, 7684, 7685, 7686, 57 | 7687, 7688, 7689, 7690, 7691, 7692, 7693, 7694, 7695, 7696, 7697, 58 | 7698, 7699, 7700, 7701, 7702, 7703, 7704, 7705, 7706, 7707, 7708, 59 | 7709, 7710, 7711, 7712, 7713, 7714, 7715, 7716, 7717, 7718, 7719, 60 | 7720, 7721, 7722, 7723, 7724, 7725, 7726, 7727, 7728, 7729, 7730, 61 | 7731, 7732, 7733, 7734, 7735, 7736, 7737, 7738, 7739, 7740, 7741, 62 | 7742, 7743, 7744, 7745, 7746, 7747, 7748, 7749, 7750, 7751, 7752, 63 | 7753, 7754, 7755, 7756, 7757, 7758, 7759, 7760, 7761, 7762, 7763, 64 | 7764, 7765, 7766, 7767, 7768, 7769, 7770, 7771, 7772, 7773, 7774, 65 | 7775, 7776, 7777, 7778, 7779, 7780, 7781, 7782, 7783, 7784, 7785, 66 | 7786, 7787, 7788, 7789, 7790, 7791, 7792, 7793, 7794, 7795, 7796, 67 | 7797, 7798, 7799, 7800, 7801, 7802, 7803, 7804, 7805, 7806, 7807, 68 | 7808, 7809, 7810, 7811, 7812, 7813, 7814, 7815, 7816, 7817, 7818, 69 | 7819, 7820, 7821, 7822, 7823, 7824, 7825, 7826, 7827, 7828, 7829, 70 | 7830, 7831, 7832, 7833, 7835, 7840, 7841, 7842, 7843, 7844, 7845, 71 | 7846, 7847, 7848, 7849, 7850, 7851, 7852, 7853, 7854, 7855, 7856, 72 | 7857, 7858, 7859, 7860, 7861, 7862, 7863, 7864, 7865, 7866, 7867, 73 | 7868, 7869, 7870, 7871, 7872, 7873, 7874, 7875, 7876, 7877, 7878, 74 | 7879, 7880, 7881, 7882, 7883, 7884, 7885, 7886, 7887, 7888, 7889, 75 | 7890, 7891, 7892, 7893, 7894, 7895, 7896, 7897, 7898, 7899, 7900, 76 | 7901, 7902, 7903, 7904, 7905, 7906, 7907, 7908, 7909, 7910, 7911, 77 | 7912, 7913, 7914, 7915, 7916, 7917, 7918, 7919, 7920, 7921, 7922, 78 | 7923, 7924, 7925, 7926, 7927, 7928, 7929, 7936, 7937, 7938, 7939, 79 | 7940, 7941, 7942, 7943, 7944, 7945, 7946, 7947, 7948, 7949, 7950, 80 | 7951, 7952, 7953, 7954, 7955, 7956, 7957, 7960, 7961, 7962, 7963, 81 | 7964, 7965, 7968, 7969, 7970, 7971, 7972, 7973, 7974, 7975, 7976, 82 | 7977, 7978, 7979, 7980, 7981, 7982, 7983, 7984, 7985, 7986, 7987, 83 | 7988, 7989, 7990, 7991, 7992, 7993, 7994, 7995, 7996, 7997, 7998, 84 | 7999, 8000, 8001, 8002, 8003, 8004, 8005, 8008, 8009, 8010, 8011, 85 | 8012, 8013, 8016, 8017, 8018, 8019, 8020, 8021, 8022, 8023, 8025, 86 | 8027, 8029, 8031, 8032, 8033, 8034, 8035, 8036, 8037, 8038, 8039, 87 | 8040, 8041, 8042, 8043, 8044, 8045, 8046, 8047, 8048, 8049, 8050, 88 | 8051, 8052, 8053, 8054, 8055, 8056, 8057, 8058, 8059, 8060, 8061, 89 | 8064, 8065, 8066, 8067, 8068, 8069, 8070, 8071, 8072, 8073, 8074, 90 | 8075, 8076, 8077, 8078, 8079, 8080, 8081, 8082, 8083, 8084, 8085, 91 | 8086, 8087, 8088, 8089, 8090, 8091, 8092, 8093, 8094, 8095, 8096, 92 | 8097, 8098, 8099, 8100, 8101, 8102, 8103, 8104, 8105, 8106, 8107, 93 | 8108, 8109, 8110, 8111, 8112, 8113, 8114, 8115, 8116, 8118, 8119, 94 | 8120, 8121, 8122, 8123, 8124, 8126, 8127, 8129, 8130, 8131, 8132, 95 | 8134, 8135, 8136, 8137, 8138, 8139, 8140, 8141, 8142, 8143, 8144, 96 | 8145, 8146, 8147, 8150, 8151, 8152, 8153, 8154, 8155, 8157, 8158, 97 | 8159, 8160, 8161, 8162, 8163, 8164, 8165, 8166, 8167, 8168, 8169, 98 | 8170, 8171, 8172, 8173, 8174, 8175, 8178, 8179, 8180, 8182, 8183, 99 | 8184, 8185, 8186, 8187, 8188, 8189, 8190, 8192, 8193, 8194, 8195, 100 | 8486, 8490, 8491, 8592, 8594, 8596, 8602, 8603, 8622, 8653, 8654, 101 | 8655, 8656, 8658, 8660, 8707, 8708, 8712, 8713, 8715, 8716, 8739, 102 | 8740, 8741, 8742, 8764, 8769, 8771, 8772, 8773, 8775, 8776, 8777, 103 | 8781, 8800, 8801, 8802, 8804, 8805, 8813, 8814, 8815, 8816, 8817, 104 | 8818, 8819, 8820, 8821, 8822, 8823, 8824, 8825, 8826, 8827, 8828, 105 | 8829, 8832, 8833, 8834, 8835, 8836, 8837, 8838, 8839, 8840, 8841, 106 | 8849, 8850, 8866, 8872, 8873, 8875, 8876, 8877, 8878, 8879, 8882, 107 | 8883, 8884, 8885, 8928, 8929, 8930, 8931, 8938, 8939, 8940, 8941, 108 | 9001, 9002, 10972, 10973, 12296, 12297, 12358, 12363, 12364, 12365, 109 | 12366, 12367, 12368, 12369, 12370, 12371, 12372, 12373, 12374, 12375, 110 | 12376, 12377, 12378, 12379, 12380, 12381, 12382, 12383, 12384, 12385, 111 | 12386, 12388, 12389, 12390, 12391, 12392, 12393, 12399, 12400, 12401, 112 | 12402, 12403, 12404, 12405, 12406, 12407, 12408, 12409, 12410, 12411, 113 | 12412, 12413, 12436, 12441, 12442, 12445, 12446, 12454, 12459, 12460, 114 | 12461, 12462, 12463, 12464, 12465, 12466, 12467, 12468, 12469, 12470, 115 | 12471, 12472, 12473, 12474, 12475, 12476, 12477, 12478, 12479, 12480, 116 | 12481, 12482, 12484, 12485, 12486, 12487, 12488, 12489, 12495, 12496, 117 | 12497, 12498, 12499, 12500, 12501, 12502, 12503, 12504, 12505, 12506, 118 | 12507, 12508, 12509, 12527, 12528, 12529, 12530, 12532, 12535, 12536, 119 | 12537, 12538, 12541, 12542, 13470, 13497, 13499, 13535, 13589, 14062, 120 | 14076, 14209, 14383, 14434, 14460, 14535, 14563, 14620, 14650, 14894, 121 | 14956, 15076, 15112, 15129, 15177, 15261, 15384, 15438, 15667, 15766, 122 | 16044, 16056, 16155, 16380, 16392, 16408, 16441, 16454, 16534, 16611, 123 | 16687, 16898, 16935, 17056, 17153, 17204, 17241, 17365, 17369, 17419, 124 | 17515, 17707, 17757, 17761, 17771, 17879, 17913, 17973, 18110, 18119, 125 | 18837, 18918, 19054, 19062, 19122, 19251, 19406, 19662, 19693, 19704, 126 | 19798, 19981, 20006, 20018, 20024, 20025, 20029, 20033, 20098, 20102, 127 | 20142, 20160, 20172, 20196, 20320, 20352, 20358, 20363, 20398, 20411, 128 | 20415, 20482, 20523, 20602, 20633, 20687, 20698, 20711, 20800, 20805, 129 | 20813, 20820, 20836, 20839, 20840, 20841, 20845, 20855, 20864, 20877, 130 | 20882, 20885, 20887, 20900, 20908, 20917, 20919, 20937, 20940, 20956, 131 | 20958, 20981, 20995, 20999, 21015, 21033, 21050, 21051, 21062, 21106, 132 | 21111, 21129, 21147, 21155, 21171, 21191, 21193, 21202, 21214, 21220, 133 | 21237, 21242, 21253, 21254, 21271, 21311, 21321, 21329, 21338, 21363, 134 | 21365, 21373, 21375, 21443, 21450, 21471, 21477, 21483, 21489, 21510, 135 | 21519, 21533, 21560, 21570, 21576, 21608, 21662, 21666, 21693, 21750, 136 | 21776, 21843, 21845, 21859, 21892, 21895, 21913, 21917, 21931, 21939, 137 | 21952, 21954, 21986, 22022, 22097, 22120, 22132, 22265, 22294, 22295, 138 | 22411, 22478, 22516, 22541, 22577, 22578, 22592, 22618, 22622, 22696, 139 | 22700, 22707, 22744, 22751, 22766, 22770, 22775, 22790, 22810, 22818, 140 | 22852, 22856, 22865, 22868, 22882, 22899, 23000, 23020, 23067, 23079, 141 | 23138, 23142, 23221, 23304, 23336, 23358, 23429, 23491, 23512, 23527, 142 | 23534, 23539, 23551, 23558, 23586, 23615, 23648, 23650, 23652, 23653, 143 | 23662, 23693, 23744, 23833, 23875, 23888, 23915, 23918, 23932, 23986, 144 | 23994, 24033, 24034, 24061, 24104, 24125, 24169, 24180, 24230, 24240, 145 | 24243, 24246, 24265, 24266, 24274, 24275, 24281, 24300, 24318, 24324, 146 | 24354, 24403, 24418, 24425, 24427, 24459, 24474, 24489, 24493, 24525, 147 | 24535, 24565, 24569, 24594, 24604, 24693, 24705, 24724, 24775, 24792, 148 | 24801, 24840, 24900, 24904, 24908, 24910, 24928, 24936, 24954, 24974, 149 | 24976, 24996, 25007, 25010, 25054, 25074, 25078, 25088, 25104, 25115, 150 | 25134, 25140, 25181, 25265, 25289, 25295, 25299, 25300, 25340, 25342, 151 | 25405, 25424, 25448, 25467, 25475, 25504, 25513, 25540, 25541, 25572, 152 | 25628, 25634, 25682, 25705, 25719, 25726, 25754, 25757, 25796, 25935, 153 | 25942, 25964, 25976, 26009, 26053, 26082, 26083, 26131, 26185, 26228, 154 | 26248, 26257, 26268, 26292, 26310, 26356, 26360, 26368, 26391, 26395, 155 | 26401, 26446, 26451, 26454, 26462, 26491, 26501, 26519, 26611, 26618, 156 | 26647, 26655, 26706, 26753, 26757, 26766, 26792, 26900, 26946, 27043, 157 | 27114, 27138, 27155, 27304, 27347, 27355, 27396, 27425, 27476, 27506, 158 | 27511, 27513, 27551, 27566, 27578, 27579, 27726, 27751, 27784, 27839, 159 | 27852, 27853, 27877, 27926, 27931, 27934, 27956, 27966, 27969, 28009, 160 | 28010, 28023, 28024, 28037, 28107, 28122, 28138, 28153, 28186, 28207, 161 | 28270, 28316, 28346, 28359, 28363, 28369, 28379, 28431, 28450, 28451, 162 | 28526, 28614, 28651, 28670, 28699, 28702, 28729, 28746, 28784, 28791, 163 | 28797, 28825, 28845, 28872, 28889, 28997, 29001, 29038, 29084, 29134, 164 | 29136, 29200, 29211, 29224, 29227, 29237, 29264, 29282, 29312, 29333, 165 | 29359, 29376, 29436, 29482, 29557, 29562, 29575, 29579, 29605, 29618, 166 | 29662, 29702, 29705, 29730, 29767, 29788, 29801, 29809, 29829, 29833, 167 | 29848, 29898, 29958, 29988, 30011, 30014, 30041, 30053, 30064, 30178, 168 | 30224, 30237, 30239, 30274, 30313, 30410, 30427, 30439, 30452, 30465, 169 | 30494, 30495, 30528, 30538, 30603, 30631, 30798, 30827, 30860, 30865, 170 | 30922, 30924, 30971, 31018, 31036, 31038, 31048, 31049, 31056, 31062, 171 | 31069, 31070, 31077, 31103, 31117, 31118, 31119, 31150, 31178, 31211, 172 | 31260, 31296, 31306, 31311, 31361, 31409, 31435, 31470, 31520, 31680, 173 | 31686, 31689, 31806, 31840, 31867, 31890, 31934, 31954, 31958, 31971, 174 | 31975, 31976, 32000, 32016, 32034, 32047, 32091, 32099, 32160, 32190, 175 | 32199, 32244, 32258, 32265, 32311, 32321, 32325, 32574, 32626, 32633, 176 | 32634, 32645, 32661, 32666, 32701, 32762, 32769, 32773, 32838, 32864, 177 | 32879, 32880, 32894, 32907, 32941, 32946, 33027, 33086, 33240, 33256, 178 | 33261, 33281, 33284, 33304, 33391, 33401, 33419, 33425, 33437, 33457, 179 | 33459, 33469, 33509, 33510, 33565, 33571, 33590, 33618, 33619, 33635, 180 | 33709, 33725, 33737, 33738, 33740, 33756, 33767, 33775, 33777, 33853, 181 | 33865, 33879, 34030, 34033, 34035, 34044, 34070, 34148, 34253, 34298, 182 | 34310, 34322, 34349, 34367, 34384, 34396, 34407, 34409, 34440, 34473, 183 | 34530, 34574, 34600, 34667, 34681, 34694, 34746, 34785, 34817, 34847, 184 | 34892, 34912, 34915, 35010, 35023, 35031, 35038, 35041, 35064, 35066, 185 | 35088, 35137, 35172, 35206, 35211, 35222, 35488, 35498, 35519, 35531, 186 | 35538, 35542, 35565, 35576, 35582, 35585, 35641, 35672, 35712, 35722, 187 | 35912, 35925, 36011, 36033, 36034, 36040, 36051, 36104, 36123, 36215, 188 | 36284, 36299, 36335, 36336, 36554, 36564, 36646, 36650, 36664, 36667, 189 | 36706, 36766, 36784, 36790, 36899, 36920, 36978, 36988, 37007, 37012, 190 | 37070, 37086, 37105, 37117, 37137, 37147, 37226, 37273, 37300, 37324, 191 | 37327, 37329, 37428, 37432, 37494, 37500, 37591, 37592, 37636, 37706, 192 | 37881, 37909, 38283, 38317, 38327, 38446, 38475, 38477, 38517, 38520, 193 | 38524, 38534, 38563, 38583, 38584, 38595, 38626, 38627, 38646, 38647, 194 | 38691, 38706, 38728, 38742, 38875, 38880, 38911, 38923, 38936, 38953, 195 | 38971, 39006, 39138, 39151, 39164, 39208, 39209, 39335, 39362, 39409, 196 | 39422, 39530, 39698, 39791, 40000, 40023, 40189, 40295, 40372, 40442, 197 | 40478, 40575, 40599, 40607, 40635, 40654, 40697, 40702, 40709, 40719, 198 | 40726, 40763, 40771, 40845, 40846, 40860, 63744, 63745, 63746, 63747, 199 | 63748, 63749, 63750, 63751, 63752, 63753, 63754, 63755, 63756, 63757, 200 | 63758, 63759, 63760, 63761, 63762, 63763, 63764, 63765, 63766, 63767, 201 | 63768, 63769, 63770, 63771, 63772, 63773, 63774, 63775, 63776, 63777, 202 | 63778, 63779, 63780, 63781, 63782, 63783, 63784, 63785, 63786, 63787, 203 | 63788, 63789, 63790, 63791, 63792, 63793, 63794, 63795, 63796, 63797, 204 | 63798, 63799, 63800, 63801, 63802, 63803, 63804, 63805, 63806, 63807, 205 | 63808, 63809, 63810, 63811, 63812, 63813, 63814, 63815, 63816, 63817, 206 | 63818, 63819, 63820, 63821, 63822, 63823, 63824, 63825, 63826, 63827, 207 | 63828, 63829, 63830, 63831, 63832, 63833, 63834, 63835, 63836, 63837, 208 | 63838, 63839, 63840, 63841, 63842, 63843, 63844, 63845, 63846, 63847, 209 | 63848, 63849, 63850, 63851, 63852, 63853, 63854, 63855, 63856, 63857, 210 | 63858, 63859, 63860, 63861, 63862, 63863, 63864, 63865, 63866, 63867, 211 | 63868, 63869, 63870, 63871, 63872, 63873, 63874, 63875, 63876, 63877, 212 | 63878, 63879, 63880, 63881, 63882, 63883, 63884, 63885, 63886, 63887, 213 | 63888, 63889, 63890, 63891, 63892, 63893, 63894, 63895, 63896, 63897, 214 | 63898, 63899, 63900, 63901, 63902, 63903, 63904, 63905, 63906, 63907, 215 | 63908, 63909, 63910, 63911, 63912, 63913, 63914, 63915, 63916, 63917, 216 | 63918, 63919, 63920, 63921, 63922, 63923, 63924, 63925, 63926, 63927, 217 | 63928, 63929, 63930, 63931, 63932, 63933, 63934, 63935, 63936, 63937, 218 | 63938, 63939, 63940, 63941, 63942, 63943, 63944, 63945, 63946, 63947, 219 | 63948, 63949, 63950, 63951, 63952, 63953, 63954, 63955, 63956, 63957, 220 | 63958, 63959, 63960, 63961, 63962, 63963, 63964, 63965, 63966, 63967, 221 | 63968, 63969, 63970, 63971, 63972, 63973, 63974, 63975, 63976, 63977, 222 | 63978, 63979, 63980, 63981, 63982, 63983, 63984, 63985, 63986, 63987, 223 | 63988, 63989, 63990, 63991, 63992, 63993, 63994, 63995, 63996, 63997, 224 | 63998, 63999, 64000, 64001, 64002, 64003, 64004, 64005, 64006, 64007, 225 | 64008, 64009, 64010, 64011, 64012, 64013, 64016, 64018, 64021, 64022, 226 | 64023, 64024, 64025, 64026, 64027, 64028, 64029, 64030, 64032, 64034, 227 | 64037, 64038, 64042, 64043, 64044, 64045, 64046, 64047, 64048, 64049, 228 | 64050, 64051, 64052, 64053, 64054, 64055, 64056, 64057, 64058, 64059, 229 | 64060, 64061, 64062, 64063, 64064, 64065, 64066, 64067, 64068, 64069, 230 | 64070, 64071, 64072, 64073, 64074, 64075, 64076, 64077, 64078, 64079, 231 | 64080, 64081, 64082, 64083, 64084, 64085, 64086, 64087, 64088, 64089, 232 | 64090, 64091, 64092, 64093, 64094, 64095, 64096, 64097, 64098, 64099, 233 | 64100, 64101, 64102, 64103, 64104, 64105, 64106, 64107, 64108, 64109, 234 | 64112, 64113, 64114, 64115, 64116, 64117, 64118, 64119, 64120, 64121, 235 | 64122, 64123, 64124, 64125, 64126, 64127, 64128, 64129, 64130, 64131, 236 | 64132, 64133, 64134, 64135, 64136, 64137, 64138, 64139, 64140, 64141, 237 | 64142, 64143, 64144, 64145, 64146, 64147, 64148, 64149, 64150, 64151, 238 | 64152, 64153, 64154, 64155, 64156, 64157, 64158, 64159, 64160, 64161, 239 | 64162, 64163, 64164, 64165, 64166, 64167, 64168, 64169, 64170, 64171, 240 | 64172, 64173, 64174, 64175, 64176, 64177, 64178, 64179, 64180, 64181, 241 | 64182, 64183, 64184, 64185, 64186, 64187, 64188, 64189, 64190, 64191, 242 | 64192, 64193, 64194, 64195, 64196, 64197, 64198, 64199, 64200, 64201, 243 | 64202, 64203, 64204, 64205, 64206, 64207, 64208, 64209, 64210, 64211, 244 | 64212, 64213, 64214, 64215, 64216, 64217, 64285, 64287, 64298, 64299, 245 | 64300, 64301, 64302, 64303, 64304, 64305, 64306, 64307, 64308, 64309, 246 | 64310, 64312, 64313, 64314, 64315, 64316, 64318, 64320, 64321, 64323, 247 | 64324, 64326, 64327, 64328, 64329, 64330, 64331, 64332, 64333, 64334, 248 | 69785, 69786, 69787, 69788, 69797, 69803, 69818, 69927, 69934, 69935, 249 | 69937, 69938, 119127, 119128, 119134, 119135, 119136, 119137, 119138, 250 | 119139, 119140, 119141, 119150, 119151, 119152, 119153, 119154, 251 | 119225, 119226, 119227, 119228, 119229, 119230, 119231, 119232, 252 | 131362, 132380, 132389, 132427, 132666, 133124, 133342, 133676, 253 | 133987, 136420, 136872, 136938, 137672, 138008, 138507, 138724, 254 | 138726, 139651, 139679, 140081, 141012, 141380, 141386, 142092, 255 | 142321, 143370, 144056, 144223, 144275, 144284, 144323, 144341, 256 | 144493, 145059, 145575, 146061, 146170, 146620, 146718, 147153, 257 | 147294, 147342, 148067, 148206, 148395, 149000, 149301, 149524, 258 | 150582, 150674, 151457, 151480, 151620, 151794, 151795, 151833, 259 | 151859, 152137, 152605, 153126, 153242, 153285, 153980, 154279, 260 | 154539, 154752, 154832, 155526, 156122, 156200, 156231, 156377, 261 | 156478, 156890, 156963, 157096, 157607, 157621, 158524, 158774, 262 | 158933, 159083, 159532, 159665, 159954, 160714, 161383, 161966, 263 | 162150, 162984, 163539, 163631, 165330, 165357, 165678, 166906, 264 | 167287, 168261, 168415, 168474, 168970, 169110, 169398, 170800, 265 | 172238, 172293, 172558, 172689, 172946, 173568, 194560, 194561, 266 | 194562, 194563, 194564, 194565, 194566, 194567, 194568, 194569, 267 | 194570, 194571, 194572, 194573, 194574, 194575, 194576, 194577, 268 | 194578, 194579, 194580, 194581, 194582, 194583, 194584, 194585, 269 | 194586, 194587, 194588, 194589, 194590, 194591, 194592, 194593, 270 | 194594, 194595, 194596, 194597, 194598, 194599, 194600, 194601, 271 | 194602, 194603, 194604, 194605, 194606, 194607, 194608, 194609, 272 | 194610, 194611, 194612, 194613, 194614, 194615, 194616, 194617, 273 | 194618, 194619, 194620, 194621, 194622, 194623, 194624, 194625, 274 | 194626, 194627, 194628, 194629, 194630, 194631, 194632, 194633, 275 | 194634, 194635, 194636, 194637, 194638, 194639, 194640, 194641, 276 | 194642, 194643, 194644, 194645, 194646, 194647, 194648, 194649, 277 | 194650, 194651, 194652, 194653, 194654, 194655, 194656, 194657, 278 | 194658, 194659, 194660, 194661, 194662, 194663, 194664, 194665, 279 | 194666, 194667, 194668, 194669, 194670, 194671, 194672, 194673, 280 | 194674, 194675, 194676, 194677, 194678, 194679, 194680, 194681, 281 | 194682, 194683, 194684, 194685, 194686, 194687, 194688, 194689, 282 | 194690, 194691, 194692, 194693, 194694, 194695, 194696, 194697, 283 | 194698, 194699, 194700, 194701, 194702, 194703, 194704, 194705, 284 | 194706, 194707, 194708, 194709, 194710, 194711, 194712, 194713, 285 | 194714, 194715, 194716, 194717, 194718, 194719, 194720, 194721, 286 | 194722, 194723, 194724, 194725, 194726, 194727, 194728, 194729, 287 | 194730, 194731, 194732, 194733, 194734, 194735, 194736, 194737, 288 | 194738, 194739, 194740, 194741, 194742, 194743, 194744, 194745, 289 | 194746, 194747, 194748, 194749, 194750, 194751, 194752, 194753, 290 | 194754, 194755, 194756, 194757, 194758, 194759, 194760, 194761, 291 | 194762, 194763, 194764, 194765, 194766, 194767, 194768, 194769, 292 | 194770, 194771, 194772, 194773, 194774, 194775, 194776, 194777, 293 | 194778, 194779, 194780, 194781, 194782, 194783, 194784, 194785, 294 | 194786, 194787, 194788, 194789, 194790, 194791, 194792, 194793, 295 | 194794, 194795, 194796, 194797, 194798, 194799, 194800, 194801, 296 | 194802, 194803, 194804, 194805, 194806, 194807, 194808, 194809, 297 | 194810, 194811, 194812, 194813, 194814, 194815, 194816, 194817, 298 | 194818, 194819, 194820, 194821, 194822, 194823, 194824, 194825, 299 | 194826, 194827, 194828, 194829, 194830, 194831, 194832, 194833, 300 | 194834, 194835, 194836, 194837, 194838, 194839, 194840, 194841, 301 | 194842, 194843, 194844, 194845, 194846, 194847, 194848, 194849, 302 | 194850, 194851, 194852, 194853, 194854, 194855, 194856, 194857, 303 | 194858, 194859, 194860, 194861, 194862, 194863, 194864, 194865, 304 | 194866, 194867, 194868, 194869, 194870, 194871, 194872, 194873, 305 | 194874, 194875, 194876, 194877, 194878, 194879, 194880, 194881, 306 | 194882, 194883, 194884, 194885, 194886, 194887, 194888, 194889, 307 | 194890, 194891, 194892, 194893, 194894, 194895, 194896, 194897, 308 | 194898, 194899, 194900, 194901, 194902, 194903, 194904, 194905, 309 | 194906, 194907, 194908, 194909, 194910, 194911, 194912, 194913, 310 | 194914, 194915, 194916, 194917, 194918, 194919, 194920, 194921, 311 | 194922, 194923, 194924, 194925, 194926, 194927, 194928, 194929, 312 | 194930, 194931, 194932, 194933, 194934, 194935, 194936, 194937, 313 | 194938, 194939, 194940, 194941, 194942, 194943, 194944, 194945, 314 | 194946, 194947, 194948, 194949, 194950, 194951, 194952, 194953, 315 | 194954, 194955, 194956, 194957, 194958, 194959, 194960, 194961, 316 | 194962, 194963, 194964, 194965, 194966, 194967, 194968, 194969, 317 | 194970, 194971, 194972, 194973, 194974, 194975, 194976, 194977, 318 | 194978, 194979, 194980, 194981, 194982, 194983, 194984, 194985, 319 | 194986, 194987, 194988, 194989, 194990, 194991, 194992, 194993, 320 | 194994, 194995, 194996, 194997, 194998, 194999, 195000, 195001, 321 | 195002, 195003, 195004, 195005, 195006, 195007, 195008, 195009, 322 | 195010, 195011, 195012, 195013, 195014, 195015, 195016, 195017, 323 | 195018, 195019, 195020, 195021, 195022, 195023, 195024, 195025, 324 | 195026, 195027, 195028, 195029, 195030, 195031, 195032, 195033, 325 | 195034, 195035, 195036, 195037, 195038, 195039, 195040, 195041, 326 | 195042, 195043, 195044, 195045, 195046, 195047, 195048, 195049, 327 | 195050, 195051, 195052, 195053, 195054, 195055, 195056, 195057, 328 | 195058, 195059, 195060, 195061, 195062, 195063, 195064, 195065, 329 | 195066, 195067, 195068, 195069, 195070, 195071, 195072, 195073, 330 | 195074, 195075, 195076, 195077, 195078, 195079, 195080, 195081, 331 | 195082, 195083, 195084, 195085, 195086, 195087, 195088, 195089, 332 | 195090, 195091, 195092, 195093, 195094, 195095, 195096, 195097, 333 | 195098, 195099, 195100, 195101 334 | }; 335 | 336 | static const uint16_t comp_seq[] = { 337 | 33432, 663, 33114, 1208, 33114, 1202, 33114, 1209, 319, 59, 322, 62, 338 | 330, 230, 331, 273, 325, 303, 341, 120, 332, 275, 327, 845, 324, 118, 339 | 338, 688, 321, 61, 336, 843, 326, 63, 320, 60, 323, 116, 33096, 64, 340 | 345, 694, 325, 690, 33104, 692, 330, 128, 320, 122, 340, 66, 325, 126, 341 | 33089, 124, 330, 130, 340, 704, 325, 698, 342, 706, 345, 702, 33104, 342 | 700, 336, 867, 341, 138, 332, 279, 342, 712, 330, 140, 326, 70, 321, 343 | 69, 324, 134, 322, 871, 344, 714, 323, 132, 331, 277, 325, 136, 319, 344 | 67, 340, 305, 320, 68, 33095, 869, 34077, 1308, 321, 142, 330, 252, 345 | 324, 144, 320, 263, 340, 148, 323, 720, 33093, 146, 336, 724, 330, 346 | 301, 326, 726, 340, 728, 321, 150, 325, 722, 33111, 730, 330, 232, 347 | 323, 154, 332, 283, 320, 72, 327, 883, 336, 885, 319, 71, 322, 152, 348 | 331, 281, 324, 156, 321, 73, 325, 160, 326, 74, 344, 732, 33109, 158, 349 | 33089, 161, 336, 738, 320, 736, 345, 740, 330, 254, 33108, 163, 336, 350 | 742, 340, 167, 345, 746, 342, 748, 330, 169, 33088, 165, 34077, 1266, 351 | 320, 171, 330, 175, 319, 265, 325, 756, 340, 173, 336, 758, 322, 75, 352 | 342, 762, 33113, 760, 335, 225, 325, 311, 327, 889, 331, 285, 326, 80, 353 | 323, 177, 321, 78, 341, 256, 319, 76, 320, 77, 330, 234, 336, 887, 354 | 322, 79, 332, 287, 324, 179, 33097, 181, 320, 772, 33093, 774, 34077, 355 | 1270, 345, 782, 325, 776, 330, 187, 340, 185, 331, 289, 336, 778, 320, 356 | 183, 33100, 291, 325, 784, 321, 191, 330, 195, 320, 189, 340, 193, 357 | 339, 297, 33104, 786, 342, 800, 330, 199, 325, 794, 339, 299, 345, 358 | 798, 340, 197, 33104, 796, 323, 203, 320, 83, 337, 802, 344, 804, 329, 359 | 209, 330, 236, 322, 201, 331, 293, 321, 84, 328, 207, 332, 295, 341, 360 | 211, 326, 85, 335, 227, 324, 205, 319, 82, 336, 911, 327, 913, 33110, 361 | 806, 336, 814, 33090, 812, 319, 816, 325, 822, 321, 213, 336, 824, 362 | 326, 820, 33088, 818, 326, 828, 33093, 826, 325, 830, 326, 217, 327, 363 | 929, 336, 927, 319, 925, 321, 215, 323, 315, 320, 86, 33090, 931, 320, 364 | 218, 325, 220, 345, 836, 336, 834, 330, 222, 33089, 832, 34077, 1280, 365 | 34077, 1282, 34077, 1284, 327, 846, 330, 231, 323, 117, 336, 844, 325, 366 | 304, 331, 274, 324, 119, 319, 87, 332, 276, 321, 89, 338, 689, 326, 367 | 91, 341, 121, 320, 88, 322, 90, 33096, 92, 336, 693, 345, 695, 33093, 368 | 691, 325, 127, 340, 94, 321, 125, 320, 123, 33098, 129, 336, 701, 342, 369 | 707, 340, 705, 325, 699, 345, 703, 33098, 131, 336, 868, 323, 133, 370 | 330, 141, 332, 280, 342, 713, 326, 98, 324, 135, 321, 97, 319, 95, 371 | 344, 715, 327, 870, 320, 96, 322, 872, 331, 278, 325, 137, 340, 306, 372 | 33109, 139, 34077, 1290, 321, 143, 325, 147, 330, 253, 324, 145, 340, 373 | 149, 323, 721, 33088, 264, 325, 723, 330, 302, 345, 838, 326, 727, 374 | 321, 151, 340, 729, 336, 725, 33111, 731, 331, 282, 320, 100, 332, 375 | 284, 327, 884, 336, 886, 322, 153, 326, 102, 324, 157, 330, 233, 341, 376 | 159, 319, 99, 344, 733, 323, 155, 33089, 101, 330, 262, 33089, 162, 377 | 345, 741, 330, 255, 320, 737, 340, 164, 33104, 739, 336, 743, 330, 378 | 170, 340, 168, 345, 747, 342, 749, 33088, 166, 336, 755, 325, 753, 379 | 33088, 751, 345, 761, 319, 266, 340, 174, 320, 172, 325, 757, 336, 380 | 759, 342, 763, 330, 176, 33090, 103, 330, 235, 321, 106, 336, 888, 381 | 326, 108, 341, 257, 327, 890, 325, 312, 319, 104, 322, 107, 323, 178, 382 | 331, 286, 320, 105, 329, 182, 324, 180, 332, 288, 33103, 226, 325, 383 | 775, 33088, 773, 1310, 1298, 34077, 1297, 330, 196, 336, 787, 325, 384 | 785, 320, 190, 339, 298, 340, 194, 33089, 192, 326, 839, 336, 797, 385 | 330, 200, 342, 801, 339, 300, 325, 795, 345, 799, 33108, 198, 335, 386 | 228, 329, 210, 320, 111, 337, 803, 319, 110, 331, 294, 326, 113, 342, 387 | 807, 341, 212, 322, 202, 344, 805, 324, 206, 332, 296, 330, 237, 327, 388 | 914, 321, 112, 323, 204, 336, 912, 33096, 208, 322, 813, 33104, 815, 389 | 320, 819, 321, 214, 325, 823, 328, 840, 336, 825, 326, 821, 33087, 390 | 817, 1310, 1304, 34077, 1303, 325, 831, 323, 316, 319, 926, 326, 115, 391 | 336, 928, 321, 216, 328, 841, 320, 114, 327, 930, 33090, 932, 345, 392 | 837, 336, 835, 325, 221, 321, 833, 330, 223, 33088, 219, 1309, 1306, 393 | 34078, 1307, 35430, 2657, 35430, 2659, 34077, 1312, 35430, 2661, 394 | 34077, 1363, 319, 1149, 349, 1109, 33088, 355, 34077, 1315, 34077, 395 | 1317, 34077, 1319, 34077, 1321, 34077, 1323, 34077, 1325, 34077, 1327, 396 | 34077, 1329, 34077, 1331, 34077, 1333, 34077, 1335, 34077, 1337, 327, 397 | 851, 322, 853, 320, 847, 33087, 849, 33091, 246, 33088, 267, 34077, 398 | 1341, 33088, 696, 34077, 1343, 322, 879, 319, 875, 320, 873, 33095, 399 | 877, 1310, 1346, 34077, 1345, 1310, 1349, 34077, 1348, 327, 895, 322, 400 | 897, 319, 893, 33088, 891, 1309, 1351, 34078, 1352, 33091, 307, 1310, 401 | 1355, 34077, 1354, 1309, 1357, 34078, 1358, 319, 244, 330, 242, 320, 402 | 240, 33091, 238, 327, 852, 319, 850, 322, 854, 33088, 848, 33091, 247, 403 | 33088, 268, 323, 251, 33088, 270, 33088, 697, 320, 874, 327, 878, 322, 404 | 880, 33087, 876, 33088, 735, 34077, 1365, 34077, 1366, 34077, 1367, 405 | 319, 894, 320, 892, 322, 898, 33095, 896, 320, 765, 326, 767, 33091, 406 | 310, 33091, 308, 33088, 272, 320, 241, 323, 239, 319, 245, 33098, 243, 407 | 34077, 1369, 320, 857, 319, 859, 322, 863, 33095, 861, 320, 858, 327, 408 | 862, 322, 864, 33087, 860, 319, 708, 33088, 710, 320, 711, 33087, 709, 409 | 33310, 535, 33310, 539, 35431, 2664, 35431, 2665, 33310, 541, 319, 410 | 768, 33088, 770, 320, 771, 33087, 769, 33093, 788, 33093, 789, 33093, 411 | 790, 33093, 791, 33088, 808, 33088, 809, 33094, 810, 33094, 811, 412 | 33093, 842, 33114, 1174, 33114, 1175, 33114, 1176, 322, 907, 336, 909, 413 | 327, 905, 319, 903, 33088, 901, 319, 904, 336, 910, 327, 906, 320, 414 | 902, 33090, 908, 33093, 718, 320, 915, 319, 917, 327, 919, 322, 921, 415 | 33104, 923, 319, 918, 336, 924, 320, 916, 327, 920, 33090, 922, 33098, 416 | 260, 34077, 1264, 559, 558, 33323, 557, 336, 754, 325, 752, 33088, 417 | 750, 33114, 1177, 33114, 1179, 33114, 1178, 34077, 1268, 33091, 258, 418 | 33091, 259, 34077, 1272, 34077, 1274, 33114, 1184, 33114, 1186, 34077, 419 | 1276, 34077, 1278, 33114, 1190, 33114, 1192, 33091, 248, 33091, 249, 420 | 33092, 716, 33092, 717, 33091, 313, 33091, 314, 33114, 1194, 33114, 421 | 1196, 33114, 1198, 34077, 1286, 33114, 1200, 33114, 1207, 34077, 1288, 422 | 33114, 1204, 33114, 1210, 33114, 1211, 34077, 1292, 33114, 1214, 423 | 33114, 1215, 33114, 1218, 33114, 1219, 33114, 1224, 33114, 1225, 424 | 33114, 1248, 33114, 1249, 33114, 1228, 33114, 1229, 33114, 1232, 425 | 33114, 1233, 33114, 1250, 33098, 261, 1310, 1295, 34077, 1294, 33114, 426 | 1240, 33114, 1241, 33114, 1242, 33114, 1243, 332, 292, 330, 188, 345, 427 | 783, 340, 186, 325, 777, 336, 779, 331, 290, 33088, 184, 33114, 1252, 428 | 33114, 1253, 33114, 1254, 33114, 1255, 1309, 1300, 34078, 1301, 326, 429 | 829, 33093, 827, 33445, 666, 33445, 668, 33445, 670, 33445, 672, 430 | 33445, 674, 33445, 676, 33445, 679, 33445, 681, 33445, 684, 33445, 431 | 685, 33445, 687, 585, 583, 584, 581, 33347, 582, 319, 1104, 323, 1103, 432 | 324, 1102, 334, 942, 352, 1106, 320, 356, 33101, 941, 33364, 589, 320, 433 | 358, 319, 1115, 334, 956, 33101, 955, 352, 1119, 334, 970, 320, 359, 434 | 319, 1117, 33101, 969, 319, 1131, 326, 373, 333, 985, 323, 1130, 324, 435 | 1129, 320, 360, 33102, 986, 319, 1157, 334, 1000, 320, 361, 33101, 436 | 999, 33102, 1148, 324, 1144, 326, 374, 320, 362, 319, 1146, 334, 1013, 437 | 33091, 1145, 352, 1161, 334, 1026, 319, 1159, 320, 363, 33101, 1025, 438 | 33120, 1099, 33120, 1112, 320, 375, 334, 934, 323, 1096, 352, 1098, 439 | 349, 1100, 333, 933, 324, 1095, 33087, 1033, 320, 376, 334, 950, 319, 440 | 1035, 33101, 949, 319, 1037, 334, 962, 320, 377, 333, 961, 352, 1111, 441 | 33117, 1113, 333, 977, 323, 1124, 326, 388, 320, 378, 349, 1127, 334, 442 | 978, 324, 1123, 33087, 1039, 319, 1041, 334, 994, 320, 390, 33101, 443 | 993, 333, 1140, 33102, 1141, 319, 1043, 333, 1005, 320, 391, 326, 389, 444 | 324, 1136, 334, 1006, 323, 1137, 33117, 1142, 590, 593, 33364, 595, 445 | 33358, 594, 320, 392, 352, 1153, 349, 1155, 333, 1017, 319, 1045, 446 | 33102, 1018, 320, 364, 319, 1125, 33117, 1128, 320, 379, 319, 1138, 447 | 33117, 1143, 33120, 1154, 326, 395, 33088, 394, 33093, 719, 33094, 448 | 400, 324, 444, 33094, 446, 33088, 398, 319, 396, 324, 448, 33094, 397, 449 | 326, 454, 33092, 442, 33094, 456, 324, 410, 319, 402, 326, 460, 33091, 450 | 458, 33088, 401, 33094, 462, 326, 472, 323, 470, 324, 403, 33097, 474, 451 | 33094, 476, 33094, 478, 33094, 468, 324, 445, 33094, 447, 33088, 432, 452 | 319, 430, 324, 449, 33094, 431, 326, 455, 33092, 443, 33094, 457, 324, 453 | 423, 326, 461, 323, 459, 33087, 436, 33088, 435, 33094, 463, 323, 471, 454 | 329, 475, 324, 437, 33094, 473, 33367, 598, 33094, 477, 33094, 479, 455 | 33094, 469, 33094, 434, 33099, 440, 33099, 441, 33120, 1092, 34077, 456 | 1339, 320, 269, 33091, 250, 33376, 601, 609, 605, 602, 606, 33376, 457 | 604, 33376, 607, 33094, 452, 33094, 453, 33088, 734, 33094, 466, 458 | 33094, 467, 323, 309, 320, 764, 33094, 766, 33088, 271, 610, 613, 459 | 33384, 615, 33378, 614, 34077, 1364, 624, 623, 617, 620, 33386, 621, 460 | 33385, 622, 521, 514, 520, 512, 33287, 511, 33091, 744, 33091, 745, 461 | 33288, 513, 33288, 515, 33091, 780, 33091, 781, 33114, 1188, 33093, 462 | 792, 33093, 793, 324, 865, 33089, 855, 324, 866, 33089, 856, 33089, 463 | 881, 33089, 882, 33288, 524, 33089, 899, 33089, 900, 33288, 526, 464 | 33288, 522, 320, 937, 319, 935, 352, 1047, 33117, 939, 320, 938, 319, 465 | 936, 352, 1048, 33117, 940, 33120, 1049, 33120, 1050, 33120, 1051, 466 | 33120, 1052, 33120, 1053, 33120, 1054, 349, 947, 319, 943, 320, 945, 467 | 33120, 1055, 320, 946, 319, 944, 352, 1056, 33117, 948, 33120, 1057, 468 | 33120, 1058, 33120, 1059, 33120, 1060, 33120, 1061, 33120, 1062, 320, 469 | 953, 33087, 951, 319, 952, 33088, 954, 320, 959, 33087, 957, 319, 958, 470 | 33088, 960, 319, 963, 320, 965, 349, 967, 33120, 1063, 352, 1064, 319, 471 | 964, 320, 966, 33117, 968, 33120, 1065, 33120, 1066, 33120, 1067, 472 | 33120, 1068, 33120, 1069, 33120, 1070, 352, 1071, 320, 973, 319, 971, 473 | 33117, 975, 320, 974, 319, 972, 352, 1072, 33117, 976, 33120, 1073, 474 | 33120, 1074, 33120, 1075, 33120, 1076, 33120, 1077, 33120, 1078, 319, 475 | 979, 320, 981, 33117, 983, 320, 982, 319, 980, 33117, 984, 319, 987, 476 | 320, 989, 33117, 991, 320, 990, 319, 988, 33117, 992, 320, 997, 33087, 477 | 995, 319, 996, 33088, 998, 320, 1003, 33087, 1001, 319, 1002, 33088, 478 | 1004, 319, 1007, 320, 1009, 33117, 1011, 320, 1010, 319, 1008, 33117, 479 | 1012, 320, 1015, 319, 1014, 33117, 1016, 349, 1023, 319, 1019, 352, 480 | 1079, 33088, 1021, 320, 1022, 319, 1020, 352, 1080, 33117, 1024, 481 | 33120, 1081, 33120, 1082, 33120, 1083, 33120, 1084, 33120, 1085, 482 | 33120, 1086, 352, 1087, 320, 1029, 319, 1027, 33117, 1031, 352, 1088, 483 | 319, 1028, 320, 1030, 33117, 1032, 33120, 1089, 33120, 1090, 33120, 484 | 1091, 33114, 1251, 33120, 1093, 33120, 1094, 33120, 1097, 33120, 1110, 485 | 33120, 1152, 33120, 1101, 320, 1121, 319, 1120, 33117, 1122, 33120, 486 | 1114, 33120, 1156, 319, 1133, 320, 1134, 33117, 1135 487 | }; 488 | 489 | static const uint16_t decomp_seq[] = { 490 | 0, 1166, 1167, 2783, 2784, 1989, 2075, 2064, 5, 319, 5, 320, 5, 321, 491 | 5, 322, 5, 326, 5, 328, 7, 340, 9, 319, 9, 320, 9, 321, 9, 326, 13, 492 | 319, 13, 320, 13, 321, 13, 326, 18, 322, 19, 319, 19, 320, 19, 321, 493 | 19, 322, 19, 326, 24, 319, 24, 320, 24, 321, 24, 326, 28, 320, 31, 494 | 319, 31, 320, 31, 321, 31, 322, 31, 326, 31, 328, 33, 340, 35, 319, 495 | 35, 320, 35, 321, 35, 326, 39, 319, 39, 320, 39, 321, 39, 326, 44, 496 | 322, 45, 319, 45, 320, 45, 321, 45, 322, 45, 326, 50, 319, 50, 320, 497 | 50, 321, 50, 326, 54, 320, 54, 326, 5, 323, 31, 323, 5, 324, 31, 324, 498 | 5, 341, 31, 341, 7, 320, 33, 320, 7, 321, 33, 321, 7, 325, 33, 325, 7, 499 | 330, 33, 330, 8, 330, 34, 330, 9, 323, 35, 323, 9, 324, 35, 324, 9, 500 | 325, 35, 325, 9, 341, 35, 341, 9, 330, 35, 330, 11, 321, 37, 321, 11, 501 | 324, 37, 324, 11, 325, 37, 325, 11, 340, 37, 340, 12, 321, 38, 321, 502 | 372, 13, 322, 39, 322, 13, 323, 39, 323, 13, 324, 39, 324, 13, 341, 503 | 39, 341, 13, 325, 14, 321, 40, 321, 15, 340, 41, 340, 16, 320, 42, 504 | 320, 16, 340, 42, 340, 16, 330, 42, 330, 18, 320, 44, 320, 18, 340, 505 | 44, 340, 18, 330, 44, 330, 19, 323, 45, 323, 19, 324, 45, 324, 19, 506 | 329, 45, 329, 21, 320, 47, 320, 21, 340, 47, 340, 21, 330, 47, 330, 507 | 22, 320, 48, 320, 22, 321, 48, 321, 22, 340, 48, 340, 22, 330, 48, 508 | 330, 23, 340, 49, 340, 23, 330, 49, 330, 24, 322, 50, 322, 24, 323, 509 | 50, 323, 24, 324, 50, 324, 24, 328, 50, 328, 24, 329, 50, 329, 24, 510 | 341, 50, 341, 26, 321, 52, 321, 28, 321, 54, 321, 28, 326, 29, 320, 511 | 55, 320, 29, 325, 55, 325, 29, 330, 55, 330, 1171, 346, 1172, 346, 19, 512 | 335, 45, 335, 1173, 346, 24, 335, 50, 335, 2000, 5, 330, 31, 330, 13, 513 | 330, 39, 330, 19, 330, 45, 330, 24, 330, 50, 330, 24, 326, 323, 50, 514 | 326, 323, 24, 326, 320, 50, 326, 320, 24, 326, 330, 50, 326, 330, 24, 515 | 326, 319, 50, 326, 319, 5, 326, 323, 31, 326, 323, 5, 325, 323, 31, 516 | 325, 323, 65, 323, 93, 323, 11, 330, 37, 330, 15, 330, 41, 330, 19, 517 | 341, 45, 341, 19, 341, 323, 45, 341, 323, 229, 330, 317, 330, 40, 330, 518 | 11, 320, 37, 320, 18, 319, 44, 319, 5, 328, 320, 31, 328, 320, 65, 519 | 320, 93, 320, 81, 320, 109, 320, 5, 331, 31, 331, 5, 332, 31, 332, 9, 520 | 331, 35, 331, 9, 332, 35, 332, 13, 331, 39, 331, 13, 332, 39, 332, 19, 521 | 331, 45, 331, 19, 332, 45, 332, 21, 331, 47, 331, 21, 332, 47, 332, 522 | 24, 331, 50, 331, 24, 332, 50, 332, 22, 339, 48, 339, 23, 339, 49, 523 | 339, 12, 330, 38, 330, 1189, 346, 1191, 346, 9, 340, 35, 340, 19, 326, 524 | 323, 45, 326, 323, 19, 322, 323, 45, 322, 323, 19, 325, 45, 325, 19, 525 | 325, 323, 45, 325, 323, 28, 323, 54, 323, 1193, 346, 1195, 346, 1197, 526 | 346, 1199, 346, 3, 346, 1203, 346, 1201, 346, 2, 346, 4, 346, 1205, 527 | 346, 1206, 346, 1212, 346, 1213, 346, 1216, 346, 1217, 346, 1220, 346, 528 | 1221, 346, 1226, 346, 1227, 346, 1230, 346, 1231, 346, 1993, 1236, 529 | 346, 1237, 346, 1238, 346, 1239, 346, 2790, 1222, 346, 1223, 346, 530 | 1234, 346, 1235, 346, 1244, 346, 1245, 346, 1246, 346, 1247, 346, 531 | 1260, 1261, 333, 498, 484, 318, 1, 501, 484, 56, 320, 365, 320, 58, 532 | 366, 320, 367, 320, 368, 320, 369, 320, 371, 320, 372, 320, 383, 326, 533 | 320, 503, 484, 368, 326, 371, 326, 380, 320, 381, 320, 382, 320, 383, 534 | 320, 386, 326, 320, 384, 320, 386, 320, 387, 320, 1418, 393, 320, 393, 535 | 326, 406, 319, 406, 326, 405, 320, 399, 326, 411, 320, 409, 319, 413, 536 | 324, 409, 324, 1982, 422, 324, 419, 319, 419, 326, 418, 320, 433, 326, 537 | 424, 320, 422, 319, 426, 324, 1419, 438, 331, 439, 331, 1990, 407, 538 | 324, 420, 324, 404, 324, 417, 324, 404, 326, 417, 326, 406, 324, 419, 539 | 324, 450, 326, 451, 326, 407, 326, 420, 326, 408, 326, 421, 326, 409, 540 | 323, 422, 323, 409, 326, 422, 326, 412, 326, 425, 326, 464, 326, 465, 541 | 326, 416, 326, 429, 326, 413, 323, 426, 323, 413, 326, 426, 326, 413, 542 | 329, 426, 329, 414, 326, 427, 326, 415, 326, 428, 326, 1977, 516, 519, 543 | 516, 520, 517, 520, 516, 521, 518, 520, 1420, 527, 520, 523, 520, 525, 544 | 520, 1992, 534, 542, 538, 542, 540, 542, 528, 542, 529, 542, 530, 542, 545 | 531, 542, 532, 542, 533, 542, 536, 542, 537, 542, 556, 555, 556, 559, 546 | 551, 554, 552, 554, 553, 554, 567, 571, 570, 571, 2776, 563, 571, 564, 547 | 571, 565, 571, 566, 571, 1180, 346, 1182, 346, 1181, 346, 1259, 346, 548 | 580, 584, 580, 579, 580, 585, 576, 578, 577, 578, 588, 596, 591, 590, 549 | 592, 590, 591, 596, 1183, 346, 1185, 346, 597, 599, 1187, 346, 600, 550 | 608, 603, 608, 603, 609, 603, 602, 603, 602, 608, 611, 610, 612, 610, 551 | 611, 616, 619, 617, 619, 618, 619, 618, 617, 619, 624, 626, 660, 628, 552 | 660, 630, 660, 632, 660, 634, 660, 625, 659, 637, 638, 637, 640, 657, 553 | 644, 658, 644, 637, 644, 647, 660, 649, 660, 651, 660, 653, 660, 655, 554 | 660, 646, 659, 1892, 1895, 1406, 662, 664, 1897, 1263, 1309, 1265, 555 | 1309, 1267, 1309, 1269, 1309, 1271, 1309, 1273, 1309, 1275, 1309, 556 | 1277, 1309, 1279, 1309, 1281, 1309, 1283, 1309, 1285, 1309, 1287, 557 | 1309, 1289, 1309, 1291, 1309, 1293, 1309, 1293, 1310, 1296, 1309, 558 | 1296, 1310, 1299, 1309, 1299, 1310, 1302, 1309, 1302, 1310, 1305, 559 | 1309, 1305, 1310, 1262, 1309, 2753, 2656, 2662, 2658, 2662, 1311, 560 | 1309, 2660, 2662, 1314, 1309, 1316, 1309, 1318, 1309, 1320, 1309, 561 | 1322, 1309, 1324, 1309, 1326, 1309, 1328, 1309, 1330, 1309, 1332, 562 | 1309, 1334, 1309, 1336, 1309, 1338, 1309, 1340, 1309, 1342, 1309, 563 | 1344, 1309, 1344, 1310, 1347, 1309, 1347, 1310, 1350, 1309, 1350, 564 | 1310, 1353, 1309, 1353, 1310, 1356, 1309, 1356, 1310, 1903, 1313, 565 | 1309, 1359, 1309, 1360, 1309, 1361, 1309, 1362, 1309, 1368, 1309, 566 | 1407, 2666, 2663, 2667, 2663, 1906, 2668, 2677, 2669, 2677, 2669, 567 | 2677, 2678, 2669, 2677, 2679, 2669, 2677, 2680, 2669, 2677, 2681, 568 | 2669, 2677, 2682, 1907, 1408, 2756, 2683, 2677, 2684, 2677, 2683, 569 | 2677, 2678, 2684, 2677, 2678, 2683, 2677, 2679, 2684, 2677, 2679, 570 | 1913, 1409, 1917, 1915, 1918, 2758, 1923, 1898, 1410, 1926, 1928, 571 | 1932, 1411, 1899, 2760, 2761, 1412, 2762, 1936, 2763, 1938, 1941, 572 | 1943, 2764, 2754, 2765, 1945, 2766, 1947, 2718, 1413, 1951, 1952, 573 | 1415, 1953, 1588, 2767, 2768, 2719, 2720, 1773, 1777, 1774, 1775, 574 | 1778, 2794, 1957, 1779, 2729, 1772, 1785, 1786, 1958, 1394, 1790, 575 | 1789, 2730, 1783, 2067, 1796, 2731, 2732, 1797, 1802, 1416, 1801, 576 | 1800, 1395, 1803, 1806, 1963, 1805, 1808, 2693, 1811, 2755, 2733, 577 | 1962, 1814, 2735, 1819, 1821, 1822, 1964, 2736, 1824, 1825, 2737, 578 | 2738, 1500, 1831, 1833, 1396, 1834, 1397, 1965, 1840, 1841, 1843, 579 | 1844, 1966, 1847, 1398, 1849, 2739, 1851, 1967, 2740, 1854, 2709, 580 | 1856, 2741, 1969, 2742, 2743, 1399, 1971, 1400, 1864, 2769, 2745, 581 | 2744, 2746, 2747, 1866, 1968, 1867, 1869, 1402, 1870, 1970, 1403, 582 | 1404, 2749, 1872, 1874, 1975, 1877, 1405, 2750, 1885, 2751, 1976, 583 | 2752, 1442, 1440, 1443, 2691, 1450, 1454, 1455, 1457, 1459, 1460, 584 | 1463, 1461, 1370, 2695, 1466, 1467, 1468, 1473, 2692, 1371, 1469, 585 | 1475, 2694, 1478, 1479, 1448, 1480, 1481, 2789, 1487, 1488, 1373, 586 | 1493, 1494, 1495, 1496, 1374, 1501, 1502, 1505, 1507, 1508, 1509, 587 | 1510, 1512, 1513, 1514, 1515, 1517, 1518, 2698, 1804, 1520, 1521, 588 | 2699, 1523, 1524, 1525, 1532, 1528, 1530, 1531, 1533, 1535, 1536, 589 | 1537, 1539, 1540, 1542, 1544, 1545, 1547, 1554, 1549, 1555, 1550, 590 | 1552, 1489, 1570, 1557, 1558, 1559, 1556, 1561, 1560, 1566, 2700, 591 | 1571, 1572, 1573, 1574, 1575, 1580, 2701, 2702, 1583, 1584, 1585, 592 | 1582, 1587, 1375, 1376, 1589, 1591, 2703, 1593, 1594, 1595, 1597, 593 | 2704, 1598, 1599, 1637, 1600, 1377, 1602, 1606, 1608, 1607, 2706, 594 | 1610, 2707, 1613, 1612, 1614, 1617, 1618, 1378, 1619, 1620, 1621, 595 | 1622, 1379, 2708, 1380, 1625, 1626, 1627, 1629, 2799, 1634, 2710, 596 | 1636, 1381, 2717, 2759, 1638, 1640, 1382, 1642, 1645, 1646, 1648, 597 | 1652, 1384, 1383, 1653, 2711, 1654, 1659, 1660, 1661, 1664, 1665, 598 | 1669, 1667, 1668, 1670, 1671, 1672, 1674, 1675, 1678, 1679, 1683, 599 | 1687, 2714, 1686, 1684, 1688, 1690, 1695, 2715, 1697, 1694, 1692, 600 | 1385, 1699, 1701, 1703, 1700, 1386, 1705, 1707, 2716, 1712, 1722, 601 | 1714, 1389, 1717, 1388, 1387, 1476, 1477, 1723, 1718, 1950, 1414, 602 | 1724, 1725, 1726, 1730, 1728, 2721, 1390, 1735, 1732, 1738, 1740, 603 | 2723, 1741, 1737, 1743, 1391, 1744, 1745, 1746, 1749, 2724, 1751, 604 | 1392, 1753, 2725, 1754, 1393, 1755, 1758, 1760, 1761, 2726, 2705, 605 | 2727, 1762, 2728, 1765, 1767, 1763, 1769, 2046, 1721, 2060, 2051, 606 | 1791, 1439, 1522, 2161, 1578, 2087, 1541, 1577, 1860, 1937, 1999, 607 | 2012, 2024, 2074, 1747, 1770, 1810, 1836, 1985, 2082, 2135, 1444, 608 | 1516, 1752, 1818, 1998, 2146, 1611, 1798, 1994, 2028, 1680, 1954, 609 | 2015, 1776, 1828, 2076, 1452, 1482, 1504, 1704, 1750, 1817, 1863, 610 | 1942, 1996, 2001, 2058, 2117, 2139, 2145, 1889, 1924, 1978, 2094, 611 | 2147, 2037, 1569, 1635, 1909, 1948, 1823, 1876, 2050, 2115, 1568, 612 | 1603, 1748, 1781, 1793, 1921, 1930, 2102, 1503, 1949, 1485, 1484, 613 | 1896, 1925, 1984, 2104, 2044, 1681, 2040, 1441, 1649, 1832, 1878, 614 | 1456, 1643, 1437, 1766, 1708, 1920, 1519, 1564, 1865, 1986, 2033, 615 | 2068, 1764, 1685, 1691, 1853, 1446, 1471, 1483, 1739, 1916, 1960, 616 | 2036, 2086, 1506, 1529, 1581, 1633, 1710, 1799, 1879, 2099, 2137, 617 | 2148, 2151, 1498, 1720, 1756, 2066, 1623, 1666, 1673, 1702, 1795, 618 | 1812, 1845, 1894, 1927, 1946, 2062, 1988, 2070, 2095, 1490, 1499, 619 | 1534, 1809, 2019, 1628, 1647, 1689, 1759, 1908, 1830, 1449, 1553, 620 | 1616, 1650, 1835, 1842, 1939, 1944, 2088, 2114, 2118, 2124, 1453, 621 | 1893, 2084, 2110, 1656, 1445, 1462, 1596, 1601, 1709, 1815, 1859, 622 | 1991, 2073, 2159, 1716, 2101, 1497, 1731, 1734, 1787, 1838, 1852, 623 | 1873, 1919, 2127, 1472, 1676, 2105, 1458, 1609, 1782, 2063, 1641, 624 | 1658, 1736, 2107, 1491, 1526, 1605, 1713, 1727, 1742, 1768, 1837, 625 | 1855, 1935, 2020, 2023, 2085, 2112, 1511, 1788, 1527, 1816, 1846, 626 | 1995, 2108, 2141, 2149, 1733, 1780, 1955, 1902, 1904, 1911, 1827, 627 | 1807, 2043, 1447, 1972, 1492, 1624, 1682, 1914, 1592, 1771, 1719, 628 | 2065, 2016, 2103, 2030, 1631, 1464, 1546, 1434, 2773, 1563, 1435, 629 | 1715, 2797, 2798, 1486, 1829, 1861, 1880, 1887, 1888, 2119, 1912, 630 | 1940, 1997, 2774, 2039, 2071, 2079, 2775, 2129, 2130, 2131, 2144, 631 | 2077, 2109, 1543, 1551, 1562, 1565, 1604, 1663, 1711, 1784, 1794, 632 | 1813, 1820, 1839, 1875, 1881, 1883, 1882, 1884, 1886, 1890, 1891, 633 | 1900, 1905, 1929, 1931, 1934, 1956, 1961, 1987, 2026, 2031, 2041, 634 | 2042, 2052, 2053, 2069, 2113, 2122, 2126, 1651, 2734, 1959, 2009, 635 | 1438, 1470, 1451, 1465, 1474, 1538, 1548, 1567, 1576, 1579, 1586, 636 | 1590, 1630, 1632, 1639, 1644, 1655, 1657, 1662, 1677, 1693, 1696, 637 | 1698, 1706, 1729, 1757, 1792, 1871, 1826, 1848, 1850, 1857, 1858, 638 | 1862, 1868, 1901, 1910, 1922, 1933, 1973, 1983, 2010, 2027, 2029, 639 | 2034, 2035, 2038, 2045, 2072, 2083, 2090, 2106, 2120, 2123, 2138, 640 | 2713, 2712, 2722, 1401, 2748, 2757, 2781, 2158, 2160, 2032, 2047, 641 | 2780, 2048, 2049, 2054, 665, 677, 667, 677, 2002, 669, 677, 2055, 671, 642 | 677, 673, 677, 2782, 675, 677, 2696, 496, 480, 510, 481, 2056, 2003, 643 | 2059, 508, 486, 508, 487, 508, 484, 486, 508, 484, 487, 488, 481, 488, 644 | 482, 488, 484, 489, 484, 490, 484, 491, 484, 492, 484, 493, 484, 494, 645 | 484, 495, 484, 496, 484, 497, 484, 678, 677, 499, 484, 680, 677, 500, 646 | 484, 682, 677, 683, 677, 686, 677, 504, 484, 2005, 505, 484, 506, 484, 647 | 507, 484, 509, 484, 493, 483, 489, 485, 498, 485, 504, 485, 2078, 648 | 2080, 2785, 2004, 2081, 2089, 2092, 2093, 2091, 2007, 2096, 2097, 649 | 2786, 2098, 1426, 1974, 2006, 2100, 2787, 1427, 2771, 2111, 1615, 650 | 2116, 2788, 2772, 1428, 1429, 2008, 2121, 2791, 1430, 2792, 2125, 651 | 2793, 2128, 1431, 2011, 2132, 2133, 2134, 2136, 1432, 1979, 1421, 652 | 2061, 2140, 2142, 1433, 2013, 2143, 2795, 2796, 2014, 2150, 1436, 653 | 2152, 1422, 2153, 2154, 2155, 2156, 2157, 2017, 2800, 1980, 2018, 654 | 2777, 2697, 2021, 2022, 1423, 1981, 2025, 1372, 2778, 2057, 2779, 655 | 1424, 2770, 1425, 5, 338, 31, 338, 6, 325, 32, 325, 6, 336, 32, 336, 656 | 6, 345, 32, 345, 7, 340, 320, 33, 340, 320, 8, 325, 34, 325, 8, 336, 657 | 34, 336, 8, 345, 34, 345, 8, 340, 34, 340, 8, 342, 34, 342, 9, 323, 658 | 319, 35, 323, 319, 9, 323, 320, 35, 323, 320, 9, 342, 35, 342, 9, 344, 659 | 35, 344, 9, 340, 324, 35, 340, 324, 10, 325, 36, 325, 11, 323, 37, 660 | 323, 12, 325, 38, 325, 12, 336, 38, 336, 12, 326, 38, 326, 12, 340, 661 | 38, 340, 12, 343, 38, 343, 13, 344, 39, 344, 13, 326, 320, 39, 326, 662 | 320, 15, 320, 41, 320, 15, 336, 41, 336, 15, 345, 41, 345, 16, 336, 663 | 42, 336, 16, 336, 323, 42, 336, 323, 16, 345, 42, 345, 16, 342, 42, 664 | 342, 17, 320, 43, 320, 17, 325, 43, 325, 17, 336, 43, 336, 18, 325, 665 | 44, 325, 18, 336, 44, 336, 18, 345, 44, 345, 18, 342, 44, 342, 19, 666 | 322, 320, 45, 322, 320, 19, 322, 326, 45, 322, 326, 19, 323, 319, 45, 667 | 323, 319, 19, 323, 320, 45, 323, 320, 20, 320, 46, 320, 20, 325, 46, 668 | 325, 21, 325, 47, 325, 21, 336, 47, 336, 21, 336, 323, 47, 336, 323, 669 | 21, 345, 47, 345, 22, 325, 48, 325, 22, 336, 48, 336, 22, 320, 325, 670 | 48, 320, 325, 22, 330, 325, 48, 330, 325, 22, 336, 325, 48, 336, 325, 671 | 23, 325, 49, 325, 23, 336, 49, 336, 23, 345, 49, 345, 23, 342, 49, 672 | 342, 24, 337, 50, 337, 24, 344, 50, 344, 24, 342, 50, 342, 24, 322, 673 | 320, 50, 322, 320, 24, 323, 326, 50, 323, 326, 25, 322, 51, 322, 25, 674 | 336, 51, 336, 26, 319, 52, 319, 26, 320, 52, 320, 26, 326, 52, 326, 675 | 26, 325, 52, 325, 26, 336, 52, 336, 27, 325, 53, 325, 27, 326, 53, 676 | 326, 28, 325, 54, 325, 29, 321, 55, 321, 29, 336, 55, 336, 29, 345, 677 | 55, 345, 38, 345, 49, 326, 52, 328, 54, 328, 224, 325, 1417, 5, 336, 678 | 31, 336, 5, 327, 31, 327, 5, 321, 320, 31, 321, 320, 5, 321, 319, 31, 679 | 321, 319, 5, 321, 327, 31, 321, 327, 5, 321, 322, 31, 321, 322, 5, 680 | 336, 321, 31, 336, 321, 5, 324, 320, 31, 324, 320, 5, 324, 319, 31, 681 | 324, 319, 5, 324, 327, 31, 324, 327, 5, 324, 322, 31, 324, 322, 5, 682 | 336, 324, 31, 336, 324, 9, 336, 35, 336, 9, 327, 35, 327, 9, 322, 35, 683 | 322, 9, 321, 320, 35, 321, 320, 9, 321, 319, 35, 321, 319, 9, 321, 684 | 327, 35, 321, 327, 9, 321, 322, 35, 321, 322, 9, 336, 321, 35, 336, 685 | 321, 13, 327, 39, 327, 13, 336, 39, 336, 19, 336, 45, 336, 19, 327, 686 | 45, 327, 19, 321, 320, 45, 321, 320, 19, 321, 319, 45, 321, 319, 19, 687 | 321, 327, 45, 321, 327, 19, 321, 322, 45, 321, 322, 19, 336, 321, 45, 688 | 336, 321, 19, 335, 320, 45, 335, 320, 19, 335, 319, 45, 335, 319, 19, 689 | 335, 327, 45, 335, 327, 19, 335, 322, 45, 335, 322, 19, 335, 336, 45, 690 | 335, 336, 24, 336, 50, 336, 24, 327, 50, 327, 24, 335, 320, 50, 335, 691 | 320, 24, 335, 319, 50, 335, 319, 24, 335, 327, 50, 335, 327, 24, 335, 692 | 322, 50, 335, 322, 24, 335, 336, 50, 335, 336, 28, 319, 54, 319, 28, 693 | 336, 54, 336, 28, 327, 54, 327, 28, 322, 54, 322, 380, 333, 380, 334, 694 | 380, 333, 319, 380, 334, 319, 380, 333, 320, 380, 334, 320, 380, 333, 695 | 349, 380, 334, 349, 365, 333, 365, 334, 365, 333, 319, 365, 334, 319, 696 | 365, 333, 320, 365, 334, 320, 365, 333, 349, 365, 334, 349, 381, 333, 697 | 381, 334, 381, 333, 319, 381, 334, 319, 381, 333, 320, 381, 334, 320, 698 | 366, 333, 366, 334, 366, 333, 319, 366, 334, 319, 366, 333, 320, 366, 699 | 334, 320, 382, 333, 382, 334, 382, 333, 319, 382, 334, 319, 382, 333, 700 | 320, 382, 334, 320, 382, 333, 349, 382, 334, 349, 367, 333, 367, 334, 701 | 367, 333, 319, 367, 334, 319, 367, 333, 320, 367, 334, 320, 367, 333, 702 | 349, 367, 334, 349, 383, 333, 383, 334, 383, 333, 319, 383, 334, 319, 703 | 383, 333, 320, 383, 334, 320, 383, 333, 349, 383, 334, 349, 368, 333, 704 | 368, 334, 368, 333, 319, 368, 334, 319, 368, 333, 320, 368, 334, 320, 705 | 368, 333, 349, 368, 334, 349, 384, 333, 384, 334, 384, 333, 319, 384, 706 | 334, 319, 384, 333, 320, 384, 334, 320, 369, 333, 369, 334, 369, 333, 707 | 319, 369, 334, 319, 369, 333, 320, 369, 334, 320, 386, 333, 386, 334, 708 | 386, 333, 319, 386, 334, 319, 386, 333, 320, 386, 334, 320, 386, 333, 709 | 349, 386, 334, 349, 371, 334, 371, 334, 319, 371, 334, 320, 371, 334, 710 | 349, 387, 333, 387, 334, 387, 333, 319, 387, 334, 319, 387, 333, 320, 711 | 387, 334, 320, 387, 333, 349, 387, 334, 349, 372, 333, 372, 334, 372, 712 | 333, 319, 372, 334, 319, 372, 333, 320, 372, 334, 320, 372, 333, 349, 713 | 372, 334, 349, 380, 319, 381, 319, 382, 319, 383, 319, 384, 319, 386, 714 | 319, 387, 319, 380, 333, 352, 380, 334, 352, 380, 333, 319, 352, 380, 715 | 334, 319, 352, 380, 333, 320, 352, 380, 334, 320, 352, 380, 333, 349, 716 | 352, 380, 334, 349, 352, 365, 333, 352, 365, 334, 352, 365, 333, 319, 717 | 352, 365, 334, 319, 352, 365, 333, 320, 352, 365, 334, 320, 352, 365, 718 | 333, 349, 352, 365, 334, 349, 352, 382, 333, 352, 382, 334, 352, 382, 719 | 333, 319, 352, 382, 334, 319, 352, 382, 333, 320, 352, 382, 334, 320, 720 | 352, 382, 333, 349, 352, 382, 334, 349, 352, 367, 333, 352, 367, 334, 721 | 352, 367, 333, 319, 352, 367, 334, 319, 352, 367, 333, 320, 352, 367, 722 | 334, 320, 352, 367, 333, 349, 352, 367, 334, 349, 352, 387, 333, 352, 723 | 387, 334, 352, 387, 333, 319, 352, 387, 334, 319, 352, 387, 333, 320, 724 | 352, 387, 334, 320, 352, 387, 333, 349, 352, 387, 334, 349, 352, 372, 725 | 333, 352, 372, 334, 352, 372, 333, 319, 352, 372, 334, 319, 352, 372, 726 | 333, 320, 352, 372, 334, 320, 352, 372, 333, 349, 352, 372, 334, 349, 727 | 352, 380, 324, 380, 323, 380, 319, 352, 380, 352, 380, 320, 352, 502, 728 | 484, 380, 349, 380, 349, 352, 365, 324, 365, 323, 365, 319, 365, 352, 729 | 56, 349, 382, 319, 352, 382, 352, 382, 320, 352, 382, 349, 382, 349, 730 | 352, 366, 319, 367, 319, 367, 352, 1108, 319, 1108, 320, 1108, 349, 731 | 383, 324, 383, 323, 383, 326, 319, 383, 349, 383, 326, 349, 368, 324, 732 | 368, 323, 368, 319, 1163, 319, 1163, 320, 1163, 349, 386, 324, 386, 733 | 323, 386, 326, 319, 385, 333, 385, 334, 386, 349, 386, 326, 349, 371, 734 | 324, 371, 323, 371, 319, 370, 334, 56, 319, 30, 387, 319, 352, 387, 735 | 352, 387, 320, 352, 387, 349, 387, 349, 352, 369, 319, 372, 319, 372, 736 | 352, 57 737 | }; 738 | 739 | static const uint8_t decomp_idx_t1[] = { 740 | 0, 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 0, 0, 7, 8, 9, 10, 11, 0, 12, 0, 0, 741 | 0, 0, 13, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 15, 16, 0, 17, 18, 19, 0, 742 | 0, 0, 20, 21, 22, 0, 23, 0, 24, 0, 25, 0, 26, 0, 0, 0, 0, 0, 27, 28, 743 | 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 744 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 745 | 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, 746 | 0, 0, 0, 41, 0, 42, 43, 44, 45, 46, 47, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 747 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 748 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 749 | 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 750 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 751 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 752 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 753 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 754 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 755 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 756 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 757 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 758 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 759 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 760 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 761 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 762 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 763 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 764 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 765 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 766 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 767 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 768 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 769 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 770 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 771 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 772 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 773 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 774 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 775 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 776 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 777 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 778 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 779 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 780 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 781 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 782 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 783 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 54, 55, 784 | 56, 57, 58, 59, 60, 61, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 785 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 786 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 787 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 788 | 0, 63, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 789 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 790 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 791 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 792 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 793 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 794 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 795 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 796 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 797 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 798 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 799 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 800 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 801 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 802 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 803 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 804 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 805 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 806 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 807 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 808 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 809 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 810 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 811 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 812 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 813 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 814 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 815 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 816 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 817 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 818 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 819 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 820 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 821 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 66, 67, 0, 0, 0, 0, 0, 0, 822 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 823 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 824 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 825 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 826 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 827 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 828 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 829 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 830 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 831 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 832 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 833 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 834 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 835 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 836 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 837 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 838 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 839 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 840 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 841 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 842 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 843 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 844 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 845 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 846 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 847 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 848 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 849 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 850 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 851 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 852 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 853 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 854 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 855 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 856 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 857 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 858 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 859 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 860 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 861 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 862 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 863 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 864 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 865 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 866 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 867 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 868 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 869 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 870 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 871 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 872 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 69, 873 | 70, 71, 72, 73, 74, 75, 76 874 | }; 875 | 876 | static const uint16_t decomp_idx_t2[] = { 877 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 878 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 879 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16392, 16394, 880 | 16396, 16398, 16400, 16402, 0, 16404, 16406, 16408, 16410, 16412, 881 | 16414, 16416, 16418, 16420, 0, 16422, 16424, 16426, 16428, 16430, 882 | 16432, 0, 0, 16434, 16436, 16438, 16440, 16442, 0, 0, 16444, 16446, 883 | 16448, 16450, 16452, 16454, 0, 16456, 16458, 16460, 16462, 16464, 884 | 16466, 16468, 16470, 16472, 0, 16474, 16476, 16478, 16480, 16482, 885 | 16484, 0, 0, 16486, 16488, 16490, 16492, 16494, 0, 16496, 16498, 886 | 16500, 16502, 16504, 16506, 16508, 16510, 16512, 16514, 16516, 16518, 887 | 16520, 16522, 16524, 16526, 16528, 0, 0, 16530, 16532, 16534, 16536, 888 | 16538, 16540, 16542, 16544, 16546, 16548, 16550, 16552, 16554, 16556, 889 | 16558, 16560, 16562, 16564, 16566, 16568, 0, 0, 16571, 16573, 16575, 890 | 16577, 16579, 16581, 16583, 16585, 16587, 0, 0, 0, 16589, 16591, 891 | 16593, 16595, 0, 16597, 16599, 16601, 16603, 16605, 16607, 0, 0, 0, 0, 892 | 16609, 16611, 16613, 16615, 16617, 16619, 0, 0, 0, 16621, 16623, 893 | 16625, 16627, 16629, 16631, 0, 0, 16633, 16635, 16637, 16639, 16641, 894 | 16643, 16645, 16647, 16649, 16651, 16653, 16655, 16657, 16659, 16661, 895 | 16663, 16665, 16667, 0, 0, 16669, 16671, 16673, 16675, 16677, 16679, 896 | 16681, 16683, 16685, 16687, 16689, 16691, 16693, 16695, 16697, 16699, 897 | 16701, 16703, 16705, 16707, 16709, 16711, 16713, 0, 0, 0, 0, 0, 0, 0, 898 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 899 | 0, 0, 0, 16719, 16721, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16725, 900 | 16727, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 901 | 0, 0, 0, 0, 0, 0, 0, 16730, 16732, 16734, 16736, 16738, 16740, 16742, 902 | 16744, 33130, 33133, 33136, 33139, 33142, 33145, 33148, 33151, 0, 903 | 33154, 33157, 33160, 33163, 16782, 16784, 0, 0, 16786, 16788, 16790, 904 | 16792, 16794, 16796, 33182, 33185, 16804, 16806, 16808, 0, 0, 0, 905 | 16810, 16812, 0, 0, 16814, 16816, 33202, 33205, 16824, 16826, 16828, 906 | 16830, 16832, 16834, 16836, 16838, 16840, 16842, 16844, 16846, 16848, 907 | 16850, 16852, 16854, 16856, 16858, 16860, 16862, 16864, 16866, 16868, 908 | 16870, 16872, 16874, 16876, 16878, 16880, 16882, 16884, 16886, 0, 0, 909 | 16888, 16890, 0, 0, 0, 0, 0, 0, 16776, 16779, 16896, 16898, 33284, 910 | 33287, 33290, 33293, 16912, 16914, 33300, 33303, 16922, 16924, 0, 0, 911 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 11, 0, 612, 16753, 0, 0, 0, 0, 0, 0, 912 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 913 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 615, 0, 0, 0, 0, 914 | 0, 0, 0, 0, 0, 616, 0, 0, 0, 0, 0, 0, 17003, 17005, 623, 17008, 17010, 915 | 17012, 0, 17014, 0, 17016, 17018, 33404, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 916 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17025, 17027, 17029, 917 | 17031, 17033, 17035, 33421, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 918 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17020, 17037, 17040, 17042, 17044, 0, 919 | 0, 0, 0, 17047, 17049, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 920 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 921 | 0, 0, 0, 0, 17051, 17053, 0, 17055, 0, 0, 0, 17057, 0, 0, 0, 0, 17059, 922 | 17061, 17063, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17065, 0, 0, 0, 0, 0, 0, 923 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 924 | 0, 0, 17068, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 925 | 0, 0, 0, 17070, 17072, 0, 17074, 0, 0, 0, 17076, 0, 0, 0, 0, 17078, 926 | 17080, 17082, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 927 | 0, 0, 0, 0, 17085, 17087, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17090, 17092, 0, 928 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17094, 17096, 17098, 17100, 0, 0, 929 | 17102, 17104, 0, 0, 17106, 17108, 17110, 17112, 17114, 17116, 0, 0, 930 | 17118, 17120, 17122, 17124, 17126, 17128, 0, 0, 17130, 17132, 17134, 931 | 17136, 17138, 17140, 17142, 17144, 17146, 17148, 17150, 17152, 0, 0, 932 | 17154, 17156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 933 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17159, 934 | 17161, 17163, 17165, 17167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 935 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17170, 0, 17172, 0, 0, 0, 0, 0, 0, 0, 936 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 17174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 937 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 938 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 939 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 940 | 0, 0, 0, 0, 17177, 0, 0, 0, 0, 0, 0, 0, 17179, 0, 0, 17181, 0, 0, 0, 941 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 942 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 17183, 17185, 17187, 17189, 17191, 17193, 943 | 17195, 17197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 944 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 945 | 0, 17199, 17201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17203, 946 | 17205, 0, 17207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 947 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 948 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 949 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17209, 0, 0, 950 | 17211, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 951 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17214, 17216, 17218, 0, 0, 952 | 17220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 953 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17230, 0, 954 | 0, 17232, 17234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17236, 955 | 17238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 956 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 957 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 958 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 959 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17242, 17244, 960 | 17246, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 961 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 962 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17252, 0, 0, 0, 0, 0, 0, 963 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 964 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 965 | 0, 0, 0, 17256, 0, 0, 0, 0, 0, 0, 17258, 17260, 0, 17262, 33648, 0, 0, 966 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 967 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 968 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17267, 17269, 17271, 0, 0, 969 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 970 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 971 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 972 | 0, 0, 0, 0, 0, 0, 17273, 0, 17275, 33661, 17280, 0, 0, 0, 0, 0, 0, 0, 973 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 974 | 0, 0, 0, 0, 0, 0, 17282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17284, 0, 0, 0, 0, 975 | 17286, 0, 0, 0, 0, 17288, 0, 0, 0, 0, 17290, 0, 0, 0, 0, 0, 0, 0, 0, 976 | 0, 0, 0, 0, 17292, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17294, 0, 17296, 17298, 977 | 0, 17300, 0, 0, 0, 0, 0, 0, 0, 0, 17302, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 978 | 0, 0, 0, 0, 0, 0, 0, 17304, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17306, 0, 0, 0, 979 | 0, 17308, 0, 0, 0, 0, 17310, 0, 0, 0, 0, 17312, 0, 0, 0, 0, 0, 0, 0, 980 | 0, 0, 0, 0, 0, 17314, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 981 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 982 | 0, 0, 0, 0, 0, 17319, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 983 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18275, 0, 18277, 0, 984 | 18280, 0, 18283, 0, 18285, 0, 0, 0, 18288, 0, 0, 0, 0, 0, 0, 0, 0, 0, 985 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 986 | 0, 0, 0, 0, 0, 0, 0, 0, 18332, 0, 18336, 0, 0, 18340, 18342, 0, 18344, 987 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 988 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 989 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446, 18448, 18450, 18452, 990 | 18454, 18456, 18458, 18460, 34846, 34849, 18468, 18470, 18472, 18474, 991 | 18476, 18478, 18480, 18482, 18484, 18486, 34872, 34875, 34878, 34881, 992 | 18500, 18502, 18504, 18506, 34892, 34895, 18514, 18516, 18518, 18520, 993 | 18522, 18524, 18526, 18528, 18530, 18532, 18534, 18536, 18538, 18540, 994 | 18542, 18544, 34930, 34933, 18552, 18554, 18556, 18558, 18560, 18562, 995 | 18564, 18566, 34952, 34955, 18574, 18576, 18578, 18580, 18582, 18584, 996 | 18586, 18588, 18590, 18592, 18594, 18596, 18598, 18600, 18602, 18604, 997 | 18606, 18608, 34994, 34997, 35000, 35003, 35006, 35009, 35012, 35015, 998 | 18634, 18636, 18638, 18640, 18642, 18644, 18646, 18648, 35034, 35037, 999 | 18656, 18658, 18660, 18662, 18664, 18666, 35052, 35055, 35058, 35061, 1000 | 35064, 35067, 18686, 18688, 18690, 18692, 18694, 18696, 18698, 18700, 1001 | 18702, 18704, 18706, 18708, 18710, 18712, 35098, 35101, 35104, 35107, 1002 | 18726, 18728, 18730, 18732, 18734, 18736, 18738, 18740, 18742, 18744, 1003 | 18746, 18748, 18750, 18752, 18754, 18756, 18758, 18760, 18762, 18764, 1004 | 18766, 18768, 18770, 18772, 18774, 18776, 18778, 18780, 18782, 18784, 1005 | 0, 18786, 0, 0, 0, 0, 18789, 18791, 18793, 18795, 35181, 35184, 35187, 1006 | 35190, 35193, 35196, 35199, 35202, 35205, 35208, 35211, 35214, 35217, 1007 | 35220, 35223, 35226, 35229, 35232, 35235, 35238, 18857, 18859, 18861, 1008 | 18863, 18865, 18867, 35253, 35256, 35259, 35262, 35265, 35268, 35271, 1009 | 35274, 35277, 35280, 18899, 18901, 18903, 18905, 18907, 18909, 18911, 1010 | 18913, 35299, 35302, 35305, 35308, 35311, 35314, 35317, 35320, 35323, 1011 | 35326, 35329, 35332, 35335, 35338, 35341, 35344, 35347, 35350, 35353, 1012 | 35356, 18975, 18977, 18979, 18981, 35367, 35370, 35373, 35376, 35379, 1013 | 35382, 35385, 35388, 35391, 35394, 19013, 19015, 19017, 19019, 19021, 1014 | 19023, 19025, 19027, 0, 0, 0, 0, 0, 0, 19029, 19031, 35417, 35420, 1015 | 35423, 35426, 35429, 35432, 19051, 19053, 35439, 35442, 35445, 35448, 1016 | 35451, 35454, 19073, 19075, 35461, 35464, 35467, 35470, 0, 0, 19089, 1017 | 19091, 35477, 35480, 35483, 35486, 0, 0, 19105, 19107, 35493, 35496, 1018 | 35499, 35502, 35505, 35508, 19127, 19129, 35515, 35518, 35521, 35524, 1019 | 35527, 35530, 19149, 19151, 35537, 35540, 35543, 35546, 35549, 35552, 1020 | 19171, 19173, 35559, 35562, 35565, 35568, 35571, 35574, 19193, 19195, 1021 | 35581, 35584, 35587, 35590, 0, 0, 19209, 19211, 35597, 35600, 35603, 1022 | 35606, 0, 0, 19225, 19227, 35613, 35616, 35619, 35622, 35625, 35628, 1023 | 0, 19247, 0, 35633, 0, 35636, 0, 35639, 19258, 19260, 35646, 35649, 1024 | 35652, 35655, 35658, 35661, 19280, 19282, 35668, 35671, 35674, 35677, 1025 | 35680, 35683, 19302, 17029, 19304, 17031, 19306, 17033, 19308, 17035, 1026 | 19310, 17040, 19312, 17042, 19314, 17044, 0, 0, 35700, 35703, 52090, 1027 | 52094, 52098, 52102, 52106, 52110, 35730, 35733, 52120, 52124, 52128, 1028 | 52132, 52136, 52140, 35760, 35763, 52150, 52154, 52158, 52162, 52166, 1029 | 52170, 35790, 35793, 52180, 52184, 52188, 52192, 52196, 52200, 35820, 1030 | 35823, 52210, 52214, 52218, 52222, 52226, 52230, 35850, 35853, 52240, 1031 | 52244, 52248, 52252, 52256, 52260, 19496, 19498, 35884, 19503, 35889, 1032 | 0, 19510, 35896, 19515, 19517, 19519, 17005, 19521, 0, 636, 0, 0, 1033 | 19523, 35909, 19528, 35914, 0, 19533, 35919, 19538, 17008, 19540, 1034 | 17010, 19542, 19544, 19546, 19548, 19550, 19552, 35938, 33404, 0, 0, 1035 | 19557, 35943, 19562, 19564, 19566, 17012, 0, 19568, 19570, 19572, 1036 | 19574, 19576, 35962, 33421, 19581, 19583, 19585, 35971, 19590, 19592, 1037 | 19594, 17016, 19596, 19598, 17003, 3216, 0, 0, 35985, 19604, 35990, 0, 1038 | 19609, 35995, 19614, 17014, 19616, 17018, 19618, 3236, 0, 0, 1, 2, 0, 1039 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1040 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1041 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1042 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1043 | 0, 0, 0, 0, 0, 0, 0, 186, 0, 0, 0, 209, 16402, 0, 0, 0, 0, 0, 0, 0, 0, 1044 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1045 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16715, 16717, 0, 0, 0, 0, 1046 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16723, 0, 0, 0, 0, 0, 0, 0, 1047 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1048 | 17222, 17224, 17226, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1049 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1050 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17248, 0, 0, 0, 0, 17250, 0, 0, 1051 | 17254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1052 | 0, 0, 16892, 0, 16894, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1053 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16926, 0, 0, 16928, 0, 0, 16930, 0, 1054 | 16932, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1055 | 0, 16934, 0, 16936, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16938, 16940, 16942, 1056 | 16944, 16946, 0, 0, 16948, 16950, 0, 0, 16952, 16954, 0, 0, 0, 0, 0, 1057 | 0, 16956, 16958, 0, 0, 16960, 16962, 0, 0, 16964, 16966, 0, 0, 0, 0, 1058 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1059 | 0, 0, 0, 0, 0, 0, 0, 16969, 16971, 16973, 16975, 0, 0, 0, 0, 0, 0, 0, 1060 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1061 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16978, 16980, 1062 | 16982, 16984, 0, 0, 0, 0, 0, 0, 16986, 16988, 16990, 16992, 0, 0, 0, 1063 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1064 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1065 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 610, 611, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1066 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1067 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17228, 0, 0, 0, 0, 0, 1068 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1069 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17322, 0, 1070 | 17324, 0, 17326, 0, 17328, 0, 17330, 0, 17332, 0, 17334, 0, 17336, 0, 1071 | 17338, 0, 17340, 0, 17342, 0, 17344, 0, 0, 17346, 0, 17348, 0, 17350, 1072 | 0, 0, 0, 0, 0, 0, 17352, 17354, 0, 17356, 17358, 0, 17360, 17362, 0, 1073 | 17364, 17366, 0, 17368, 17370, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1074 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 17372, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17379, 0, 1075 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17383, 0, 17385, 0, 17387, 0, 1076 | 17389, 0, 17391, 0, 17393, 0, 17395, 0, 17397, 0, 17399, 0, 17401, 0, 1077 | 17403, 0, 17405, 0, 0, 17407, 0, 17409, 0, 17411, 0, 0, 0, 0, 0, 0, 1078 | 17413, 17415, 0, 17417, 17419, 0, 17421, 17423, 0, 17425, 17427, 0, 1079 | 17429, 17431, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1080 | 0, 0, 0, 17434, 0, 0, 17436, 17438, 17440, 17442, 0, 0, 0, 17444, 0, 1081 | 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1505, 1506, 1507, 1082 | 1508, 1509, 1419, 1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517, 1083 | 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, 1084 | 1529, 1530, 1531, 1532, 1533, 1534, 1535, 1388, 1458, 1536, 1537, 1085 | 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1546, 1547, 1548, 1086 | 1549, 1550, 1551, 1552, 1241, 1553, 1554, 1555, 1556, 1557, 1558, 1087 | 1559, 1560, 1561, 1562, 1563, 1564, 1565, 1566, 1567, 1568, 1569, 1088 | 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1089 | 1581, 1582, 1583, 1584, 1516, 1585, 1586, 1357, 1587, 1588, 1214, 1090 | 1293, 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1596, 1597, 1598, 1091 | 1599, 1600, 1487, 1601, 1602, 1603, 1231, 1604, 1605, 1606, 1607, 1092 | 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 1093 | 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627, 1628, 1629, 1094 | 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1095 | 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1600, 1648, 1649, 1650, 1096 | 1651, 1652, 1653, 1654, 1655, 1357, 1656, 1657, 1658, 1659, 1660, 1097 | 1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, 1098 | 1672, 1673, 1674, 1675, 1516, 1676, 1677, 1678, 1679, 1680, 1681, 1099 | 1682, 1683, 1684, 1685, 1148, 1686, 1687, 1688, 1689, 1690, 1691, 1100 | 1692, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 1700, 1701, 1588, 1101 | 1702, 1703, 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1102 | 1713, 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1721, 1722, 1723, 1103 | 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731, 1732, 1733, 1734, 1104 | 1735, 1736, 1737, 1327, 1738, 1739, 1740, 1741, 1742, 1743, 1744, 1105 | 1745, 1746, 1747, 1748, 1749, 1750, 0, 0, 1753, 0, 1755, 0, 0, 1758, 1106 | 1759, 1760, 1761, 1762, 1763, 932, 1764, 1765, 1766, 0, 1767, 0, 1769, 1107 | 0, 0, 1770, 1771, 0, 0, 0, 1773, 1774, 1775, 1776, 1777, 1778, 1255, 1108 | 1260, 1264, 1288, 1289, 1295, 1779, 1323, 1780, 1781, 1782, 1783, 1109 | 1366, 1406, 1784, 1413, 1418, 1442, 1785, 1449, 1468, 1147, 1786, 1110 | 1787, 1788, 1789, 1790, 1791, 1792, 1793, 1794, 1795, 1246, 1796, 1111 | 1797, 1798, 937, 1799, 1800, 1637, 1801, 1802, 1803, 1128, 1804, 1805, 1112 | 1805, 1806, 1807, 1808, 1809, 1810, 1811, 1812, 1813, 1770, 1814, 1113 | 1815, 1816, 1817, 1818, 1819, 0, 0, 1821, 1277, 1822, 1823, 1824, 1114 | 1825, 1287, 1290, 1779, 1826, 1318, 1827, 1753, 1828, 1829, 1830, 1115 | 1831, 1832, 1833, 1834, 1835, 1836, 1837, 1411, 1838, 1413, 1839, 1116 | 1418, 1840, 1841, 1842, 1843, 1844, 1755, 1458, 1459, 1845, 1846, 1117 | 1487, 1148, 1847, 1160, 1787, 1171, 1788, 1848, 1187, 1849, 1759, 1118 | 1204, 1850, 1851, 1852, 1853, 1760, 1854, 1224, 1233, 1855, 1243, 1119 | 1856, 1800, 1857, 1858, 1637, 1859, 1128, 1860, 1861, 1862, 1863, 1120 | 1864, 1808, 1865, 1769, 1866, 1809, 1585, 1867, 1810, 1868, 1812, 7, 1121 | 1869, 1870, 1871, 1872, 1814, 1764, 1873, 1815, 1874, 1816, 1875, 1122 | 1505, 1876, 1877, 1878, 1473, 1879, 1234, 1880, 1881, 1882, 1883, 1123 | 1884, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1124 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1125 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1126 | 18291, 0, 18293, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18298, 18300, 34686, 1127 | 34689, 18308, 18310, 18312, 18314, 18316, 18318, 18320, 18322, 18324, 1128 | 0, 18326, 18328, 18330, 16997, 18334, 0, 18338, 0, 17001, 19508, 0, 1129 | 17023, 18346, 0, 18349, 18351, 18353, 18302, 18355, 18357, 18359, 1130 | 18361, 18363, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1131 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1132 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1133 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17375, 0, 17377, 0, 0, 0, 0, 0, 0, 0, 0, 1134 | 0, 0, 0, 0, 0, 0, 17381, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1135 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1136 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1137 | 0, 0, 0, 0, 0, 17447, 17449, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1138 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1139 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 17452, 17454, 33840, 33843, 33846, 33849, 1140 | 33852, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1141 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1142 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1143 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17474, 17476, 1144 | 33862, 33865, 33868, 33871, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1145 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1146 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1147 | 0, 0, 0, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1148 | 1260, 1261, 1262, 1263, 1264, 1265, 1266, 1267, 1268, 1269, 1270, 1149 | 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, 1150 | 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1151 | 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1299, 1299, 1300, 1301, 1152 | 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311, 1312, 1153 | 1313, 1314, 1315, 1316, 1317, 1317, 1318, 1319, 1320, 1321, 1322, 1154 | 1323, 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, 1333, 1155 | 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343, 1344, 1156 | 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1353, 1354, 1157 | 1355, 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1158 | 1366, 1367, 1368, 1369, 1370, 1371, 1372, 1373, 1374, 1375, 1376, 1159 | 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1160 | 1388, 1389, 1390, 1391, 1391, 1152, 1392, 1392, 1393, 1394, 1395, 1161 | 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1162 | 1407, 1408, 1409, 1410, 1411, 1410, 1412, 1413, 1414, 1415, 1416, 1163 | 1417, 1418, 1419, 1420, 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1164 | 1428, 1429, 1430, 1431, 1432, 1433, 1434, 1435, 1436, 1437, 1438, 1165 | 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, 1447, 1448, 1449, 1166 | 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1167 | 1461, 1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1470, 1471, 1168 | 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479, 1480, 1481, 1482, 1169 | 1483, 1484, 1485, 1486, 1487, 1488, 1489, 1490, 1491, 1492, 1493, 1170 | 1494, 1495, 1496, 1497, 1146, 1147, 1148, 1149, 1150, 1153, 1154, 1171 | 1155, 1156, 1157, 1159, 1160, 1161, 1162, 1163, 1165, 1166, 1167, 1172 | 1168, 1169, 1171, 1172, 1173, 1174, 1175, 1177, 1178, 1179, 1180, 1173 | 1182, 1184, 1185, 1186, 1187, 1188, 1190, 1191, 1192, 1193, 1194, 1174 | 1196, 1197, 1198, 1199, 1200, 1200, 1202, 1203, 1204, 1205, 1207, 1175 | 1208, 1209, 1210, 1211, 1213, 1214, 1215, 1216, 1217, 1219, 1220, 1176 | 1221, 1223, 1224, 1226, 1227, 1228, 1229, 1230, 1232, 1232, 1233, 1177 | 1234, 1235, 1237, 1238, 1239, 1240, 1241, 1243, 1244, 1245, 1246, 1178 | 1247, 1249, 932, 933, 934, 937, 1113, 1119, 990, 1130, 1130, 1049, 1179 | 1062, 1181, 1067, 1087, 1088, 1089, 1106, 1107, 1108, 1109, 1110, 1180 | 1111, 1112, 1114, 1115, 1116, 1117, 1118, 1120, 1121, 1122, 1123, 1181 | 1124, 1125, 1126, 1127, 1128, 1129, 1131, 1132, 1133, 1134, 1135, 1182 | 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145, 1152, 1183 | 1158, 1164, 1170, 1176, 1183, 1189, 1195, 1201, 1206, 1212, 1218, 1184 | 1225, 1231, 1236, 1242, 1248, 1222, 774, 683, 1806, 1996, 2024, 2046, 1185 | 2053, 2060, 2006, 2001, 2404, 5, 705, 792, 829, 584, 1752, 662, 700, 1186 | 1768, 1772, 785, 345, 1548, 1895, 1912, 1964, 1984, 1990, 1997, 1862, 1187 | 2009, 1820, 2018, 2025, 2030, 2034, 2038, 2044, 2047, 2048, 2050, 1188 | 2051, 2052, 2054, 2055, 2056, 2058, 2059, 2061, 1885, 1867, 1868, 1189 | 1886, 1887, 1888, 1889, 1890, 1898, 1903, 1906, 2057, 1911, 1913, 1190 | 2049, 2026, 7, 3, 4, 6, 1981, 1982, 1983, 1985, 1986, 1987, 1988, 1191 | 1989, 1991, 1992, 1993, 1994, 1995, 1998, 1999, 2000, 2002, 2003, 1192 | 2004, 2005, 593, 2007, 2008, 2010, 2011, 2012, 2013, 1874, 1874, 2014, 1193 | 2015, 2016, 2017, 2019, 2020, 2021, 2022, 2023, 1151, 1875, 2027, 1194 | 2028, 2029, 1751, 2031, 2032, 1754, 2033, 1756, 1757, 2035, 2036, 1195 | 2037, 2039, 2040, 2041, 2042, 2043, 2045 1196 | }; 1197 | 1198 | int32_t decomp_idx(int32_t codepoint) { 1199 | if (codepoint >= 195102) return 0; 1200 | return decomp_idx_t2[(decomp_idx_t1[codepoint >> 6] << 6) + (codepoint & 63)]; 1201 | } 1202 | static const uint8_t comp_idx_t1[] = { 1203 | 0, 1, 2, 3, 0, 4, 5, 6, 7, 0, 8, 9, 0, 10, 0, 11, 0, 12, 0, 0, 13, 0, 1204 | 0, 0, 0, 0, 0, 0, 14, 15, 16, 0, 17, 18, 19, 20, 0, 0, 21, 22, 0, 0, 1205 | 0, 0, 0, 0, 0, 0, 0, 23, 24, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1206 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 1207 | 0, 0, 0, 28, 0, 29, 0, 30, 0, 0, 0, 31, 0, 0, 32, 33, 0, 0, 0, 34, 0, 1208 | 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1209 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1210 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1211 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1212 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 37, 38, 0, 0, 0, 1213 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 40, 41, 1214 | 0, 42, 43, 0, 44, 45, 46, 47, 0, 48, 49, 50, 0, 0, 0, 0, 0, 0, 0, 0, 1215 | 0, 0, 0, 0, 51, 0, 52, 0, 53, 54, 55, 56, 57, 58, 0, 0, 0, 0, 0, 0, 0, 1216 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1217 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1218 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1219 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1220 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 60, 61, 62, 63, 64, 0, 0, 0, 0, 0, 0, 1221 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1222 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1223 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1224 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1225 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1226 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1227 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1228 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1229 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1230 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1231 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1232 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1233 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1234 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1235 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1236 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1237 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1238 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1239 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1240 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1241 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1242 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1243 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1244 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1245 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1246 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1247 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1248 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1249 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1250 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1251 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1252 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1253 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1254 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1255 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1256 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1257 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1258 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1259 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1260 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1261 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1262 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1263 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1264 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1265 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1266 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1267 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1268 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1269 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1270 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1271 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1272 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1273 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1274 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1275 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1276 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1277 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1278 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1279 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1280 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1281 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1282 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1283 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1284 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1285 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1286 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1287 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1288 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1289 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1290 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1291 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1292 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1293 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1294 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1295 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1296 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1297 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1298 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 66, 0, 0, 0, 67 1299 | }; 1300 | 1301 | static const uint16_t comp_idx_t2[] = { 1302 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1303 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1304 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 4, 20, 23, 1305 | 28, 34, 502, 52, 59, 66, 81, 82, 87, 517, 94, 103, 119, 0, 122, 130, 1306 | 137, 144, 163, 165, 171, 173, 182, 0, 0, 0, 0, 0, 0, 191, 207, 210, 1307 | 215, 221, 701, 239, 246, 254, 268, 270, 275, 281, 284, 293, 309, 0, 1308 | 571, 313, 320, 328, 347, 349, 585, 358, 368, 0, 0, 0, 0, 0, 0, 0, 0, 1309 | 0, 0, 0, 0, 0, 381, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1310 | 0, 0, 0, 0, 0, 0, 0, 0, 396, 0, 400, 401, 753, 403, 0, 0, 405, 0, 0, 1311 | 0, 0, 762, 0, 0, 0, 0, 413, 765, 419, 0, 768, 0, 0, 0, 424, 0, 0, 0, 1312 | 0, 0, 428, 0, 432, 433, 434, 436, 0, 0, 437, 0, 0, 0, 0, 441, 0, 0, 0, 1313 | 0, 445, 449, 452, 0, 453, 0, 0, 0, 454, 0, 0, 0, 0, 0, 459, 463, 0, 0, 1314 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 467, 469, 0, 0, 0, 0, 0, 0, 0, 0, 1315 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 476, 478, 0, 0, 0, 0, 1316 | 0, 0, 0, 0, 0, 0, 0, 0, 480, 481, 0, 0, 0, 0, 482, 483, 0, 0, 0, 0, 0, 1317 | 0, 484, 485, 486, 487, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1318 | 0, 0, 0, 488, 492, 497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 503, 1319 | 508, 0, 0, 0, 0, 0, 0, 513, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1320 | 0, 0, 0, 0, 524, 525, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1321 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 534, 535, 536, 537, 0, 0, 0, 0, 538, 1322 | 539, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1323 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 564, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1324 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 601, 0, 0, 1325 | 0, 609, 0, 613, 0, 618, 0, 0, 0, 0, 0, 625, 0, 629, 0, 0, 0, 630, 0, 1326 | 0, 0, 636, 0, 0, 641, 0, 642, 0, 0, 643, 0, 0, 0, 651, 0, 655, 0, 661, 1327 | 0, 0, 0, 0, 0, 669, 0, 673, 0, 0, 0, 675, 0, 0, 0, 686, 692, 695, 0, 1328 | 0, 698, 0, 0, 0, 699, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1329 | 0, 0, 0, 702, 0, 0, 0, 0, 0, 0, 0, 0, 0, 703, 0, 0, 705, 0, 706, 709, 1330 | 711, 712, 0, 716, 0, 0, 0, 717, 0, 0, 0, 0, 718, 0, 0, 0, 722, 0, 0, 1331 | 0, 723, 0, 724, 0, 0, 725, 0, 0, 727, 0, 728, 731, 733, 734, 0, 738, 1332 | 0, 0, 0, 739, 0, 0, 0, 0, 740, 0, 0, 0, 745, 0, 0, 0, 746, 0, 747, 0, 1333 | 0, 0, 0, 0, 0, 0, 0, 748, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1334 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 749, 750, 0, 0, 0, 0, 0, 0, 1335 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1336 | 0, 0, 0, 0, 0, 760, 761, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1337 | 763, 764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1338 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 777, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1339 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 782, 0, 783, 1340 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 795, 1341 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 798, 0, 0, 799, 0, 0, 1342 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 471, 0, 0, 0, 0, 0, 0, 1343 | 0, 472, 0, 0, 475, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1344 | 0, 0, 515, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1345 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 598, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1346 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1347 | 0, 0, 0, 0, 0, 0, 0, 0, 608, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1348 | 0, 0, 0, 0, 0, 683, 685, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1349 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 744, 0, 0, 0, 0, 0, 0, 0, 1350 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1351 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1352 | 0, 0, 0, 755, 0, 0, 0, 0, 0, 0, 756, 0, 0, 0, 759, 0, 0, 0, 0, 0, 0, 1353 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 769, 1354 | 771, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1355 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1356 | 0, 0, 0, 0, 773, 0, 0, 776, 0, 0, 0, 0, 0, 0, 0, 0, 587, 0, 588, 0, 1357 | 589, 0, 590, 0, 591, 0, 0, 0, 592, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1358 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1359 | 0, 0, 0, 0, 0, 593, 0, 594, 0, 595, 596, 0, 0, 597, 0, 0, 0, 0, 0, 0, 1360 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1361 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 780, 1362 | 781, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1363 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 784, 785, 0, 0, 0, 0, 0, 0, 787, 1364 | 788, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1365 | 0, 0, 0, 0, 0, 0, 789, 791, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1366 | 0, 0, 0, 0, 0, 0, 0, 0, 793, 794, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1367 | 0, 0, 0, 0, 0, 0, 796, 797, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1368 | 0, 0, 0, 0, 800, 804, 808, 809, 810, 811, 812, 813, 814, 818, 822, 1369 | 823, 824, 825, 826, 827, 828, 830, 0, 0, 0, 0, 0, 0, 832, 834, 0, 0, 1370 | 0, 0, 0, 0, 836, 840, 844, 845, 846, 847, 848, 849, 850, 854, 858, 1371 | 859, 860, 861, 862, 863, 864, 867, 0, 0, 0, 0, 0, 0, 870, 873, 0, 0, 1372 | 0, 0, 0, 0, 876, 878, 0, 0, 0, 0, 0, 0, 880, 882, 0, 0, 0, 0, 0, 0, 1373 | 884, 887, 0, 0, 0, 0, 0, 0, 0, 890, 0, 0, 0, 0, 0, 0, 893, 897, 901, 1374 | 902, 903, 904, 905, 906, 907, 911, 915, 916, 917, 751, 919, 920, 921, 1375 | 0, 0, 0, 922, 0, 0, 0, 0, 0, 0, 0, 923, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1376 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 924, 0, 0, 0, 0, 0, 0, 0, 1377 | 0, 925, 0, 0, 0, 0, 0, 0, 928, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1378 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1379 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 929, 0, 0, 0, 0, 0, 0, 0, 930, 0, 0, 1380 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 489, 0, 490, 0, 491, 0, 1381 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1382 | 0, 0, 0, 520, 0, 521, 0, 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1383 | 0, 528, 0, 0, 0, 0, 529, 0, 0, 786, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1384 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 532, 0, 533, 0, 0, 0, 0, 0, 0, 0, 1385 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 540, 0, 0, 0, 0, 0, 0, 1386 | 541, 0, 542, 0, 0, 544, 0, 0, 0, 0, 545, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1387 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 547, 0, 0, 548, 549, 0, 0, 0, 0, 0, 0, 0, 1388 | 0, 0, 0, 0, 0, 551, 552, 0, 0, 553, 554, 0, 0, 555, 556, 557, 558, 0, 1389 | 0, 0, 0, 559, 560, 0, 0, 561, 562, 0, 0, 0, 0, 0, 0, 0, 0, 0, 563, 1390 | 918, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 567, 0, 0, 0, 0, 0, 1391 | 568, 569, 0, 570, 0, 0, 0, 0, 0, 0, 579, 580, 581, 582, 0, 0, 0, 0, 0, 1392 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 514, 0, 93, 0, 523, 1393 | 0, 121, 0, 526, 0, 527, 0, 530, 0, 531, 0, 188, 0, 189, 0, 190, 0, 1394 | 543, 0, 0, 546, 0, 238, 0, 550, 0, 0, 0, 0, 0, 0, 565, 0, 0, 311, 0, 1395 | 0, 583, 0, 0, 356, 0, 0, 374, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1396 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 378, 0, 0, 1397 | 0, 0, 0, 0, 0, 0, 380, 0, 0, 0, 0, 384, 0, 385, 0, 386, 0, 387, 0, 1398 | 388, 0, 389, 0, 390, 0, 391, 0, 392, 0, 393, 0, 394, 0, 395, 0, 0, 1399 | 752, 0, 402, 0, 404, 0, 0, 0, 0, 0, 0, 409, 0, 0, 411, 0, 0, 417, 0, 1400 | 0, 420, 0, 0, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1401 | 0, 0, 772, 442, 443, 444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 458, 0, 0, 0, 1402 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1403 | 0, 376, 0, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 379, 0, 0, 0, 0, 0, 0, 0, 1404 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1405 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 473, 474 1406 | }; 1407 | 1408 | int32_t comp_idx(int32_t codepoint) { 1409 | if (codepoint >= 69939) return 0; 1410 | return comp_idx_t2[(comp_idx_t1[codepoint >> 5] << 5) + (codepoint & 31)]; 1411 | } 1412 | static const uint8_t ccc_t1[] = { 1413 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 4, 1414 | 5, 6, 7, 0, 8, 9, 10, 0, 11, 12, 13, 0, 14, 15, 16, 15, 17, 15, 17, 1415 | 15, 17, 15, 17, 0, 17, 0, 18, 15, 17, 0, 17, 0, 19, 20, 21, 22, 23, 1416 | 24, 25, 26, 27, 28, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 1417 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 32, 0, 0, 33, 0, 34, 0, 0, 1418 | 0, 35, 36, 0, 0, 37, 38, 39, 40, 41, 0, 0, 42, 0, 0, 0, 43, 0, 0, 0, 1419 | 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1420 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1421 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 46, 0, 47, 0, 0, 0, 0, 0, 0, 0, 1422 | 0, 48, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1423 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1424 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1425 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1426 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1427 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1428 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1429 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1430 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1431 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1432 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1433 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1434 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1435 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1436 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1437 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1438 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1439 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1440 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1441 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1442 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 52, 0, 0, 0, 0, 53, 1443 | 0, 0, 54, 55, 56, 57, 58, 0, 0, 59, 60, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0, 1444 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1445 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1446 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1447 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1448 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1449 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1450 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1451 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1452 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1453 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1454 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1455 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1456 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1457 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1458 | 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 1459 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1460 | 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1461 | 0, 0, 0, 0, 53, 66, 0, 67, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1462 | 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1463 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1464 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1465 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1466 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1467 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1468 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1469 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1470 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1471 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1472 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1473 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1474 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1475 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1476 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1477 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1478 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1479 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1480 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1481 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1482 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1483 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1484 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1485 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1486 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1487 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1488 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1489 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1490 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1491 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1492 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1493 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1494 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 70, 0, 0, 71 1495 | }; 1496 | 1497 | static const uint8_t ccc_t2[] = { 1498 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1499 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1500 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 1501 | 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 1502 | 230, 230, 230, 230, 232, 220, 220, 220, 220, 232, 216, 220, 220, 220, 1503 | 220, 220, 202, 202, 220, 220, 220, 220, 202, 202, 220, 220, 220, 220, 1504 | 220, 220, 220, 220, 220, 220, 220, 1, 1, 1, 1, 1, 220, 220, 220, 220, 1505 | 230, 230, 230, 230, 230, 230, 230, 230, 240, 230, 220, 220, 220, 230, 1506 | 230, 230, 220, 220, 0, 230, 230, 230, 220, 220, 220, 220, 230, 232, 1507 | 220, 220, 230, 233, 234, 234, 233, 234, 234, 233, 230, 230, 230, 230, 1508 | 230, 230, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 1509 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 0, 0, 0, 0, 1510 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1511 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1512 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1513 | 220, 230, 230, 230, 230, 220, 230, 230, 230, 222, 220, 230, 230, 230, 1514 | 230, 230, 230, 220, 220, 220, 220, 220, 220, 230, 230, 220, 230, 230, 1515 | 222, 228, 230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 1516 | 0, 23, 0, 24, 25, 0, 230, 220, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1517 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1518 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1519 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 1520 | 230, 230, 230, 30, 31, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1521 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1522 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 28, 29, 30, 31, 32, 33, 34, 230, 1523 | 230, 220, 220, 230, 230, 230, 230, 230, 220, 230, 230, 220, 0, 0, 0, 1524 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1525 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1526 | 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 230, 230, 230, 1527 | 230, 220, 230, 0, 0, 230, 230, 0, 220, 230, 230, 220, 0, 0, 0, 0, 0, 1528 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1529 | 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1530 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 230, 230, 220, 1531 | 230, 230, 220, 220, 220, 230, 220, 220, 230, 220, 230, 230, 230, 220, 1532 | 230, 220, 230, 220, 230, 220, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1533 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1534 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1535 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1536 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 1537 | 230, 230, 230, 220, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1538 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 1539 | 230, 230, 0, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0, 230, 230, 1540 | 230, 0, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1541 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1542 | 0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1543 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1544 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1545 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 220, 230, 1546 | 230, 220, 230, 230, 230, 220, 220, 220, 27, 28, 29, 230, 230, 230, 1547 | 220, 230, 230, 220, 220, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 1548 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1549 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1550 | 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1551 | 0, 9, 0, 0, 0, 230, 220, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1552 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1553 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 1554 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1555 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1556 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 1557 | 0, 84, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1558 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1559 | 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1560 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1561 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1562 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1563 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1564 | 0, 0, 0, 103, 103, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, 1565 | 107, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1566 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1567 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1568 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1569 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 118, 0, 1570 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 122, 122, 122, 0, 0, 0, 0, 1571 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1572 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1573 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1574 | 0, 0, 0, 220, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1575 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 220, 0, 216, 0, 0, 0, 0, 0, 0, 1576 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1577 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1578 | 0, 0, 0, 129, 130, 0, 132, 0, 0, 0, 0, 0, 130, 130, 130, 130, 0, 0, 1579 | 130, 0, 230, 230, 9, 0, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1580 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1581 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1582 | 0, 0, 0, 0, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1583 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1584 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1585 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1586 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1587 | 0, 0, 7, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1588 | 0, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1589 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1590 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1591 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 0, 0, 0, 0, 0, 0, 1592 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1593 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1594 | 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1595 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1596 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 1597 | 0, 0, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1598 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1599 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1600 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1601 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1602 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1603 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 1604 | 230, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1605 | 0, 0, 0, 0, 0, 0, 0, 230, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1606 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1607 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1608 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1609 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 230, 230, 1610 | 0, 0, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1611 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1612 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1613 | 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1614 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 230, 1615 | 230, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1616 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1617 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 1618 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1619 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1620 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 1621 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1622 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1623 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 1624 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1625 | 230, 230, 230, 0, 1, 220, 220, 220, 220, 220, 230, 230, 220, 220, 220, 1626 | 220, 230, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 220, 0, 0, 0, 0, 0, 0, 1627 | 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 220, 230, 230, 230, 1628 | 230, 230, 230, 230, 220, 230, 230, 234, 214, 220, 202, 230, 230, 230, 1629 | 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 1630 | 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1631 | 0, 0, 0, 0, 0, 0, 233, 220, 230, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1632 | 0, 0, 0, 0, 0, 230, 230, 1, 1, 230, 230, 230, 230, 1, 1, 1, 230, 230, 1633 | 0, 0, 0, 0, 230, 0, 0, 0, 1, 1, 230, 220, 230, 1, 1, 220, 220, 220, 1634 | 220, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1635 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1636 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 1637 | 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1638 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1639 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1640 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1641 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 1642 | 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 1643 | 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 1644 | 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1645 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, 1646 | 228, 232, 222, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1647 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1648 | 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1649 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1650 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1651 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, 1652 | 0, 0, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 1653 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1654 | 0, 0, 0, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1655 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1656 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1657 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 0, 0, 0, 1658 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 1659 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1660 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1661 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1662 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 1663 | 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0, 0, 1664 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1665 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1666 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1667 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1668 | 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1669 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1670 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1671 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1672 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 1673 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1674 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1675 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1676 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1677 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0, 230, 1678 | 230, 220, 0, 0, 230, 230, 0, 0, 0, 0, 0, 230, 230, 0, 230, 0, 0, 0, 0, 1679 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1680 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1681 | 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1682 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1683 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1684 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1685 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 1686 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1687 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1688 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 230, 0, 1689 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1690 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1691 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1692 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 0, 0, 0, 1693 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1694 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1695 | 0, 0, 0, 0, 0, 0, 0, 230, 1, 220, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 1696 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1697 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1698 | 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 1699 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1700 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 1701 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1702 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1703 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 1704 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1705 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 216, 1, 1, 1, 1706 | 0, 0, 0, 226, 216, 216, 216, 216, 216, 0, 0, 0, 0, 0, 0, 0, 0, 220, 1707 | 220, 220, 220, 220, 220, 220, 220, 0, 0, 230, 230, 230, 230, 230, 220, 1708 | 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1709 | 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1710 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230 1711 | }; 1712 | 1713 | int32_t ccc(int32_t codepoint) { 1714 | if (codepoint >= 119365) return 0; 1715 | return ccc_t2[(ccc_t1[codepoint >> 6] << 6) + (codepoint & 63)]; 1716 | } 1717 | static const int32_t lowercase_offset_values[] = { 1718 | 0, 32, 1, -199, -121, 210, 206, 205, 79, 202, 203, 207, 211, 209, 213, 1719 | 214, 218, 217, 219, 2, -97, -56, -130, 10795, -163, 10792, -195, 69, 1720 | 71, 38, 37, 64, 63, 8, -60, -7, 80, 15, 48, 7264, -7615, -8, -74, -9, 1721 | -86, -100, -112, -128, -126, -7517, -8383, -8262, 28, 16, 26, -10743, 1722 | -3814, -10727, -10780, -10749, -10783, -10782, -10815, -35332, -42280, 1723 | -42308, 40 1724 | }; 1725 | 1726 | static const uint8_t lowercase_offset_t1[] = { 1727 | 0, 1, 0, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 9, 10, 11, 12, 13, 14, 15, 16, 1728 | 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1729 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 1730 | 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1731 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1732 | 0, 0, 0, 0, 0, 0, 0, 20, 20, 21, 20, 22, 23, 24, 25, 0, 0, 0, 0, 26, 1733 | 27, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 30, 0, 0, 0, 0, 0, 0, 0, 1734 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 32, 1735 | 20, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1736 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1737 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1738 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1739 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1740 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1741 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1742 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1743 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1744 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1745 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1746 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1747 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1748 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1749 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1750 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1751 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1752 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1753 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1754 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1755 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1756 | 0, 0, 0, 0, 34, 35, 0, 36, 37, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1757 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1758 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1759 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1760 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1761 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1762 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1763 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1764 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1765 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1766 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1767 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1768 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1769 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1770 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1771 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 1772 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40 1773 | }; 1774 | 1775 | static const uint8_t lowercase_offset_t2[] = { 1776 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1777 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1778 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1779 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1780 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1781 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1782 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1783 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1784 | 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1785 | 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1786 | 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 0, 2, 0, 2, 0, 1787 | 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1788 | 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1789 | 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 4, 2, 0, 2, 0, 2, 0, 0, 0, 5, 1790 | 2, 0, 2, 0, 6, 2, 0, 7, 7, 2, 0, 0, 8, 9, 10, 2, 0, 7, 11, 0, 12, 13, 1791 | 2, 0, 0, 0, 12, 14, 0, 15, 2, 0, 2, 0, 2, 0, 16, 2, 0, 16, 0, 0, 2, 0, 1792 | 16, 2, 0, 17, 17, 2, 0, 2, 0, 18, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1793 | 19, 2, 0, 19, 2, 0, 19, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1794 | 0, 2, 0, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 1795 | 19, 2, 0, 2, 0, 20, 21, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1796 | 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1797 | 2, 0, 22, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 1798 | 0, 0, 0, 0, 0, 23, 2, 0, 24, 25, 0, 0, 2, 0, 26, 27, 28, 2, 0, 2, 0, 1799 | 2, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1800 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1801 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1802 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1803 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1804 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 30, 30, 30, 0, 31, 0, 32, 32, 0, 1, 1805 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1806 | 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1807 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 1808 | 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1809 | 2, 0, 0, 0, 0, 0, 34, 0, 0, 2, 0, 35, 2, 0, 0, 22, 22, 22, 36, 36, 36, 1810 | 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 1, 1, 1, 1, 1, 1, 1811 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1812 | 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1813 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1814 | 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1815 | 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1816 | 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1817 | 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1818 | 0, 2, 0, 2, 0, 2, 0, 2, 0, 37, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1819 | 0, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1820 | 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1821 | 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1822 | 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 1823 | 0, 0, 0, 0, 0, 0, 0, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 1824 | 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 1825 | 38, 38, 38, 38, 38, 38, 38, 38, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1826 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1827 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1828 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 39, 39, 39, 39, 1829 | 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 1830 | 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 0, 39, 1831 | 0, 0, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1832 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1833 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1834 | 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1835 | 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1836 | 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1837 | 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1838 | 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1839 | 0, 0, 0, 0, 0, 0, 0, 0, 41, 41, 41, 41, 41, 41, 41, 41, 0, 0, 0, 0, 0, 1840 | 0, 0, 0, 41, 41, 41, 41, 41, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 41, 1841 | 41, 41, 41, 41, 41, 41, 0, 0, 0, 0, 0, 0, 0, 0, 41, 41, 41, 41, 41, 1842 | 41, 41, 41, 0, 0, 0, 0, 0, 0, 0, 0, 41, 41, 41, 41, 41, 41, 0, 0, 0, 1843 | 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 41, 0, 41, 0, 41, 0, 0, 0, 0, 0, 0, 0, 1844 | 0, 41, 41, 41, 41, 41, 41, 41, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1845 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 41, 41, 41, 41, 41, 41, 41, 0, 1846 | 0, 0, 0, 0, 0, 0, 0, 41, 41, 41, 41, 41, 41, 41, 41, 0, 0, 0, 0, 0, 0, 1847 | 0, 0, 41, 41, 41, 41, 41, 41, 41, 41, 0, 0, 0, 0, 0, 0, 0, 0, 41, 41, 1848 | 42, 42, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 44, 44, 44, 43, 0, 0, 1849 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 41, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1850 | 0, 0, 0, 41, 41, 46, 46, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 1851 | 48, 48, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1852 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 1853 | 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1854 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1855 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 53, 53, 53, 53, 53, 53, 53, 1856 | 53, 53, 53, 53, 53, 53, 53, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1857 | 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1858 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1859 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1860 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1861 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1862 | 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 1863 | 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 1864 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1865 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 38, 38, 1866 | 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 1867 | 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 1868 | 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1869 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1870 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 55, 56, 57, 0, 1871 | 0, 2, 0, 2, 0, 2, 0, 58, 59, 60, 61, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1872 | 0, 0, 62, 62, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1873 | 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1874 | 0, 2, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1875 | 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1876 | 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 1877 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 0, 1878 | 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 1879 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1880 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1881 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1882 | 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 2, 0, 2, 0, 2, 0, 2, 1883 | 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1884 | 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1885 | 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 63, 1886 | 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 2, 0, 64, 0, 0, 2, 0, 2, 0, 0, 1887 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 65, 0, 1888 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1889 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1890 | 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1891 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 66, 66, 66, 66, 66, 66, 1892 | 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 1893 | 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66 1894 | }; 1895 | 1896 | int32_t lowercase_offset(int32_t codepoint) { 1897 | int offset_index; 1898 | if (codepoint >= 66600) return 0; 1899 | offset_index = lowercase_offset_t2[(lowercase_offset_t1[codepoint >> 6] << 6) + (codepoint & 63)]; 1900 | return lowercase_offset_values[offset_index]; 1901 | } 1902 | -------------------------------------------------------------------------------- /preprocess.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Copyright (c) 2013 Dropbox, Inc. 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | 23 | from collections import defaultdict, namedtuple 24 | import itertools 25 | import textwrap 26 | import sys 27 | import os 28 | import re 29 | 30 | # Helper for flattening nested lists 31 | flatten = itertools.chain.from_iterable 32 | 33 | CodepointInfo = namedtuple("CodepointInfo", 34 | [ "codepoint", "name", "category", "ccc", "bidi_category", "decomposition", 35 | "decimal_value", "digit_value", "numeric_value", "mirrored", "old_name", "comment", 36 | "uppercase", "lowercase", "titlecase" ]) 37 | 38 | Decomposition = namedtuple("Decomposition", [ "type", "mapping" ]) 39 | 40 | # The highest possible codepoint is 0x10FFFF, so we need 21 bits to represent a codepoint. 41 | UNICODE_CODE_SPACE_BITS = 21 42 | 43 | def from_hex(s): 44 | """Parse a hex string. 45 | """ 46 | return int(s, 16) if s else None 47 | 48 | 49 | def file_lines(*path_components): 50 | """Helper for reading all lines out of a file, ignoring comments. 51 | """ 52 | with open(os.path.join(*path_components)) as f: 53 | for line in f.readlines(): 54 | line = line.strip().split("#", 1)[0] 55 | if line and line[0] != '@': 56 | yield line 57 | 58 | 59 | def parse_data(base_path): 60 | """Parse the Unicode character data and composition exclusion files. 61 | """ 62 | 63 | codepoints = {} 64 | for line in file_lines(base_path, "UnicodeData.txt"): 65 | fields = line.strip().split(";") 66 | 67 | if fields[5]: 68 | decomp_fields = fields[5].split(" ") 69 | if decomp_fields[0].startswith("<"): 70 | decomp = Decomposition(decomp_fields[0], map(from_hex, decomp_fields[1:])) 71 | else: 72 | decomp = Decomposition("canonical", map(from_hex, decomp_fields)) 73 | else: 74 | decomp = Decomposition("none", None) 75 | 76 | info = CodepointInfo( 77 | from_hex(fields[0]), fields[1], fields[2], int(fields[3]), fields[4], decomp, 78 | fields[6], fields[7], fields[8], fields[9], fields[10], fields[11], 79 | from_hex(fields[12]), from_hex(fields[13]), from_hex(fields[14])) 80 | 81 | codepoints[info.codepoint] = info 82 | 83 | exclusions = set(map(from_hex, file_lines(base_path, "CompositionExclusions.txt"))) 84 | 85 | return codepoints, exclusions 86 | 87 | 88 | def parse_collation(base_path): 89 | """Parse the DUCET file allkeys.txt 90 | """ 91 | collation_elements = {} 92 | def parse_element(el_string): 93 | # we treat * variable weight as non-ignorable because this is not actually used for sorting 94 | return map(from_hex, re.split('\.|\*',el_string)) 95 | for line in file_lines(base_path, "allkeys.txt"): 96 | fields = line.strip().split(";"); 97 | if fields[0]: 98 | codepoints = tuple(map(from_hex, fields[0].strip().split())) 99 | fields = re.split('\]\[(?:\.|\*)', fields[1].strip(' []*.')) 100 | collation_elements[codepoints] = map(parse_element, fields) 101 | return collation_elements 102 | 103 | 104 | def recursive_decompose(data, pt): 105 | """Return the full decomposition for codepoint pt. 106 | """ 107 | info = data.get(pt, None) 108 | if info and info.decomposition.type == "canonical": 109 | return flatten(recursive_decompose(data, pt) for pt in info.decomposition.mapping) 110 | else: 111 | return (pt, ) 112 | 113 | 114 | def bytes_needed(data): 115 | """Find an appropriate type to represent all values in data. 116 | """ 117 | if any(d < 0 for d in data): 118 | prefix, nbits = "", max(max(data).bit_length(), (-1 - min(data)).bit_length()) + 1 119 | else: 120 | prefix, nbits = "u", max(data).bit_length() 121 | 122 | return prefix, next(v for v in (1, 2, 4) if v * 8 >= nbits) 123 | 124 | 125 | def try_split(arr, shift): 126 | """Try splitting arr into a 2-level trie with chunks of size 2**shift. 127 | 128 | Return the two levels of the tree as dicts, as well as shift. 129 | """ 130 | table1, table2 = [], [] 131 | size = 2 ** shift 132 | chunks = {} 133 | 134 | for i in range(0, len(arr), size): 135 | this_chunk = tuple(arr[i:i+size]) 136 | if this_chunk not in chunks: 137 | chunks[this_chunk] = len(table2) >> shift 138 | table2.extend(this_chunk) 139 | 140 | table1.append(chunks[this_chunk]) 141 | 142 | return table1, table2, shift 143 | 144 | 145 | def split_array(arr): 146 | """Split arr into a 2-level trie. 147 | """ 148 | return min( 149 | ( try_split(arr, shift) for shift in xrange(len(arr).bit_length()) ), 150 | key = lambda (t1, t2, shift): bytes_needed(t1)[1] * len(t1) 151 | + bytes_needed(t2)[1] * len(t2) 152 | ) 153 | 154 | 155 | def dump_table(name, data): 156 | """Dump data as a C array called 'name'. 157 | """ 158 | prefix, nbytes = bytes_needed(data) 159 | typ = "%sint%s_t" % (prefix, nbytes * 8) 160 | return len(data) * nbytes, "static const %s %s[] = {\n %s\n};\n" % ( 161 | typ, name, "\n ".join(textwrap.wrap(", ".join(map(str, data))))) 162 | 163 | 164 | 165 | def sublist_index(haystack, needle): 166 | n = len(needle) 167 | for i in xrange(len(haystack) - n + 1): 168 | if haystack[i:i+n] == needle: 169 | return i 170 | 171 | def make_translation_map(name, translation_func): 172 | translation_map = [ 0 ] * 0x110000 173 | value_table = [] 174 | value_index_cache = {} 175 | 176 | for codepoint, info in data.iteritems(): 177 | value = translation_func(info) 178 | 179 | if value not in value_index_cache: 180 | value_index_cache[value] = len(value_table) 181 | value_table.append(value) 182 | 183 | translation_map[codepoint] = value_index_cache[value] 184 | 185 | # End the table at the highest non-zero value 186 | translation_map = translation_map[:max(i for i, v in enumerate(translation_map) if v) + 1] 187 | 188 | index1, index2, shift = split_array(translation_map) 189 | 190 | vb, v = dump_table(name + "_values", value_table) 191 | t1b, t1 = dump_table(name + "_t1", index1) 192 | t2b, t2 = dump_table(name + "_t2", index2) 193 | 194 | out = "%s\n%s\n%s\n" % (v, t1, t2) 195 | out += """int32_t %s(int32_t codepoint) { 196 | int offset_index; 197 | if (codepoint >= %d) return 0; 198 | offset_index = %s_t2[(%s_t1[codepoint >> %d] << %d) + (codepoint & %d)]; 199 | return %s_values[offset_index]; 200 | }""" % (name, len(translation_map), name, name, shift, shift, (1 << shift) - 1, name) 201 | 202 | return vb + t1b + t2b, out 203 | 204 | def make_direct_map(name, func): 205 | out_map = [ func(data[codepoint]) if codepoint in data else 0 206 | for codepoint in xrange(0x110000) ] 207 | 208 | # End the table at the highest non-zero value 209 | out_map = out_map[:max(i for i, v in enumerate(out_map) if v) + 1] 210 | 211 | index1, index2, shift = split_array(out_map) 212 | 213 | t1b, t1 = dump_table(name + "_t1", index1) 214 | t2b, t2 = dump_table(name + "_t2", index2) 215 | 216 | out = "%s\n%s\n" % (t1, t2) 217 | out += """int32_t %s(int32_t codepoint) { 218 | if (codepoint >= %d) return 0; 219 | return %s_t2[(%s_t1[codepoint >> %d] << %d) + (codepoint & %d)]; 220 | }""" % (name, len(out_map), name, name, shift, shift, (1 << shift) - 1) 221 | 222 | return t1b + t2b, out 223 | 224 | 225 | def make_collation_element_table(collation_elements): 226 | 227 | # The Default Unicode Collation Element Table (DUCET) is a mapping from sequences of 228 | # codepoints to sequences of collation elements. We only implement "level 1" (see 229 | # Unicode TR10 for more detail), so a collation element is the same as a "weight", 230 | # a 16-bit integer. We use 32-bit integers throughout to represent weights. 231 | # 232 | # This function produces a hash table mapping sequences of codepoints to sequences of 233 | # collation elements. The actual collation algorithm is implmented in 234 | # minutf_collation.cpp; it takes an input string and performs a number of lookups in the 235 | # hash table to produce a sort key. We use a simple hash function, defined below and 236 | # also in C++, to hash sequences of codepoints into buckets. 237 | # 238 | # The DUCET is serialized as a sequence of records, of variable length. Each record is 239 | # simply a key (nonempty sequence of codepoints) followed by a value (sequence of 240 | # weights; values may be empty). These records are variable-length, so the high-order 241 | # bits of the first word of the key contain metadata: 242 | # 243 | # Bit 31 Set if this is the *last* record in its bucket 244 | # Bits 30:29 Length of key 245 | # Bits 28:24 Length of value 246 | # Bits 21:0: First codepoint in key 247 | # 248 | # These records are serialized into an array called "ducet_data". A second array called 249 | # ducet_bucket_indexes maps hash buckets to the index in ducet_data of the first record 250 | # for that bucket. So, the lookup algorithm is: 251 | # 252 | # - Given a sequence of codepoint, hash them to find which bucket any mappings for that 253 | # key would be in. 254 | # - Read ducet_bucket_indexes[bucket] to find where in ducet_data to start reading 255 | # - Process variable-length records starting at ducet_data[ducet_bucket_indexes[bucket]] 256 | # and see if any key matches the input. Stop when a record indicating that it's the last 257 | # is found. 258 | 259 | def get_level_1_elements(elements): 260 | return [el[0] for el in elements if el[0] != 0] 261 | 262 | level1_elements = { key: get_level_1_elements(all_levels) 263 | for key, all_levels 264 | in collation_elements.iteritems() } 265 | 266 | # How many bits do we need to store key and value lengths? 267 | longest_key = max(len(key) for key in level1_elements.iterkeys()) 268 | longest_value = max(len(value) for value in level1_elements.itervalues()) 269 | 270 | KEY_BITS = longest_key.bit_length() 271 | VALUE_BITS = longest_value.bit_length() 272 | BUCKETS = len(level1_elements) 273 | HASH_MULTIPLIER = 1031 274 | DUCET_DATA_HIGH_BIT = 31 275 | 276 | bucket_to_data = defaultdict(list) 277 | 278 | def bucket(seq): 279 | out = 0 280 | for i in seq: 281 | out = (out * HASH_MULTIPLIER + i) % BUCKETS 282 | return out # % BUCKETS 283 | 284 | for key, value in sorted(level1_elements.iteritems()): 285 | header_word = (len(key) << (DUCET_DATA_HIGH_BIT - KEY_BITS)) \ 286 | | (len(value) << (DUCET_DATA_HIGH_BIT - KEY_BITS - VALUE_BITS)) 287 | assert (header_word & ~(~0 << UNICODE_CODE_SPACE_BITS)) == 0 288 | data = [ header_word | key[0] ] + list(key[1:]) + list(value) 289 | bucket_to_data[bucket(key)].append(data) 290 | 291 | # First, figure out what the total length of data_array should be, so we know where 292 | # to point empty buckets. 293 | data_array_len = 0 294 | for b in range(BUCKETS): 295 | if b in bucket_to_data: 296 | for d in bucket_to_data[b]: 297 | data_array_len += len(d) 298 | 299 | bucket_to_offset = [] 300 | 301 | data_array = [] 302 | 303 | collision_count = defaultdict(int) 304 | 305 | for b in range(BUCKETS): 306 | if b in bucket_to_data: 307 | bucket_to_offset.append(len(data_array)) 308 | 309 | collision_count[len(bucket_to_data[b])] += 1 310 | 311 | # Set the high bit of the first word of the last record in this bucket. 312 | bucket_to_data[b][-1][0] |= (1 << DUCET_DATA_HIGH_BIT) 313 | 314 | for d in bucket_to_data[b]: 315 | data_array.extend(d) 316 | 317 | else: 318 | bucket_to_offset.append(data_array_len) 319 | 320 | assert len(data_array) == data_array_len 321 | 322 | header = "// %r\n" % (collision_count, ) 323 | 324 | dd_bytes, dd = dump_table("ducet_data", data_array) 325 | off_bytes, off = dump_table("ducet_bucket_indexes", bucket_to_offset) 326 | footer = "#define DUCET_HASH_BUCKETS %d\n" % (BUCKETS, ) 327 | footer += "#define DUCET_HASH_MULTIPLIER %d\n" % (HASH_MULTIPLIER, ) 328 | footer += "#define DUCET_LONGEST_KEY %d\n" % (longest_key, ) 329 | footer += "#define DUCET_KEY_BITS %d\n" % (KEY_BITS, ) 330 | footer += "#define DUCET_VALUE_BITS %d\n" % (VALUE_BITS, ) 331 | footer += "#define DUCET_DATA_HIGH_BIT %d\n" % (DUCET_DATA_HIGH_BIT, ) 332 | 333 | return dd_bytes + off_bytes, header + dd + off + footer 334 | 335 | 336 | data, exclusions = parse_data("data-6.3.0") 337 | collation_elements = parse_collation("data-6.3.0") 338 | 339 | ccc = { codepoint: info.ccc for (codepoint, info) in data.iteritems() } 340 | 341 | # Recursively calculate decomposition mappings and reorder combining characters 342 | decomposition_map = { 343 | pt: sorted(recursive_decompose(data, pt), key = lambda pt: ccc.get(pt, 0)) 344 | for pt, info in data.iteritems() 345 | if info.decomposition.type == "canonical" 346 | } 347 | 348 | composition_map = { 349 | tuple(info.decomposition.mapping): codepoint 350 | for codepoint, info in data.items() 351 | if codepoint not in exclusions 352 | and info.decomposition.type == "canonical" 353 | and len(info.decomposition.mapping) == 2 354 | and info.ccc == 0 355 | and ccc.get(info.decomposition.mapping[0], 0) == 0 356 | } 357 | 358 | # Make a shorter list of all interesting codepoints 359 | interesting_codepoints = [0] + sorted( 360 | set(flatten([ cp ] + dc for cp, dc in decomposition_map.iteritems())) 361 | | set(flatten((k1, k2, v) for ((k1, k2), v) in composition_map.iteritems())) 362 | ) 363 | interesting_codepoint_map = { pt: idx for idx, pt in enumerate(interesting_codepoints) } 364 | 365 | # Assemble decomposition sequences 366 | decomposition_sequences = [ 0 ] 367 | decomposition_starts = {} 368 | for codepoint, decomposition in decomposition_map.iteritems(): 369 | decomposition = [ interesting_codepoint_map[cp] for cp in decomposition ] 370 | idx = sublist_index(decomposition_sequences, decomposition) 371 | if idx is None: 372 | idx = len(decomposition_sequences) 373 | decomposition_sequences.extend(decomposition) 374 | 375 | assert len(decomposition) in (1, 2, 3, 4) 376 | assert idx < (1 << 14) 377 | 378 | decomposition_starts[codepoint] = idx | ((len(decomposition) - 1) << 14) 379 | 380 | k2map = defaultdict(set) 381 | for (k1, k2), v in composition_map.iteritems(): 382 | k2map[k1].add((k2, v)) 383 | 384 | comp_seqs = [] 385 | comp_map = {} 386 | 387 | for k1, k2vs in k2map.iteritems(): 388 | comp_map[k1] = len(comp_seqs) / 2 389 | last_k2, last_v = k2vs.pop() 390 | for k2, v in k2vs: 391 | comp_seqs.append(interesting_codepoint_map[k2]) 392 | comp_seqs.append(interesting_codepoint_map[v]) 393 | 394 | comp_seqs.append(interesting_codepoint_map[last_k2] | 0x8000) 395 | comp_seqs.append(interesting_codepoint_map[last_v]) 396 | 397 | if len(sys.argv) >= 2 and sys.argv[1] == "--collation": 398 | out = { 399 | "ducet_level1": make_collation_element_table(collation_elements) 400 | } 401 | else: 402 | out = { 403 | "lower_offset": make_translation_map("lowercase_offset", lambda info: info.lowercase - info.codepoint if info.lowercase else 0), 404 | # "upper_offset": make_translation_map("uppercase_offset", lambda info: info.uppercase - info.codepoint if info.uppercase else 0), 405 | "ccc": make_direct_map("ccc", lambda info: info.ccc), 406 | "xref": dump_table("xref", interesting_codepoints), 407 | "decomp_seq": dump_table("decomp_seq", decomposition_sequences), 408 | "decomp_idx": make_direct_map("decomp_idx", lambda info: decomposition_starts.get(info.codepoint, 0)), 409 | "comp_seq": dump_table("comp_seq", comp_seqs), 410 | "comp_idx": make_direct_map("comp_idx", lambda info: comp_map.get(info.codepoint, 0)), 411 | } 412 | 413 | # for k in sorted(out.keys()): 414 | # (nbytes, defs) = out[k] 415 | for k, (nbytes, defs) in out.iteritems(): 416 | print defs 417 | print >>sys.stderr, "%s: %d" % (k, nbytes) 418 | 419 | print >>sys.stderr, "total: %s" % sum(nbytes for nbytes, defs in out.values()) 420 | -------------------------------------------------------------------------------- /test.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013 Dropbox, Inc. 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "miniutf.hpp" 28 | #include "miniutf_collation.hpp" 29 | 30 | using std::string; 31 | using std::istringstream; 32 | using std::printf; 33 | using std::snprintf; 34 | 35 | void dump(const string & str) { 36 | for (size_t i = 0; i < str.length(); ) 37 | printf(i ? "%04X" : " %04X", miniutf::utf8_decode(str, i)); 38 | } 39 | 40 | int check_eq(const char *test, const string & expected, const string & got) { 41 | if (expected == got) 42 | return 1; 43 | 44 | printf("%s: expected \"", test); 45 | dump(expected); 46 | printf("\", got \""); 47 | dump(got); 48 | printf("\"\n"); 49 | return 0; 50 | } 51 | 52 | string decode_hex(const string &in) { 53 | istringstream ss(in); 54 | int ch; 55 | string out; 56 | while (ss >> std::hex >> ch) 57 | miniutf::utf8_encode(ch, out); 58 | return out; 59 | } 60 | 61 | int process_test_line(string &line) { 62 | if (line[0] == '#') 63 | return 0; 64 | 65 | if (line[0] == '@') { 66 | printf("%s\n", line.c_str()); 67 | return 0; 68 | } 69 | 70 | istringstream ss(line); 71 | 72 | string s1, s2, s3, s4, s5; 73 | std::getline(ss, s1, ';'); 74 | std::getline(ss, s2, ';'); 75 | std::getline(ss, s3, ';'); 76 | std::getline(ss, s4, ';'); 77 | std::getline(ss, s5, ';'); 78 | if (!ss) { 79 | printf("Bad line format - expected 5 fields\n"); 80 | return 1; 81 | } 82 | 83 | /* Decode each string as UTF-8 */ 84 | s1 = decode_hex(s1); 85 | s2 = decode_hex(s2); 86 | s3 = decode_hex(s3); 87 | s4 = decode_hex(s4); 88 | s5 = decode_hex(s5); 89 | 90 | if (!check_eq("NFD(c1)", s3, miniutf::nfd(s1))) return 1; 91 | if (!check_eq("NFD(c2)", s3, miniutf::nfd(s2))) return 1; 92 | if (!check_eq("NFD(c3)", s3, miniutf::nfd(s3))) return 1; 93 | if (!check_eq("NFD(c4)", s5, miniutf::nfd(s4))) return 1; 94 | if (!check_eq("NFD(c5)", s5, miniutf::nfd(s5))) return 1; 95 | if (!check_eq("NFC(c1)", s2, miniutf::nfc(s1))) return 1; 96 | if (!check_eq("NFC(c2)", s2, miniutf::nfc(s2))) return 1; 97 | if (!check_eq("NFC(c3)", s2, miniutf::nfc(s3))) return 1; 98 | if (!check_eq("NFC(c4)", s4, miniutf::nfc(s4))) return 1; 99 | if (!check_eq("NFC(c5)", s4, miniutf::nfc(s5))) return 1; 100 | return 0; 101 | } 102 | 103 | string match_key_as_hex(const std::vector & key) { 104 | string out; 105 | for (uint32_t c : key) { 106 | char outc[10]; 107 | snprintf(outc, 10, "%08X ", (unsigned int)c); 108 | out.append(outc); 109 | } 110 | return out.substr(0,out.size()-1); 111 | } 112 | 113 | template string string_as_hex(const T & s) { 114 | string out; 115 | for (size_t i = 0; i < s.size(); i++) { 116 | char outc[10]; 117 | snprintf(outc, 10, "%02X ", (unsigned int)s[i]); 118 | out.append(outc); 119 | } 120 | return out.substr(0,out.size()-1); 121 | } 122 | 123 | bool check_match_key(const string & s1, const string & s2) { 124 | std::vector k1 = miniutf::match_key(s1); 125 | std::vector k2 = miniutf::match_key(s2); 126 | if (k1 != k2) { 127 | printf("match_key(%s,%s) test failed\n", string_as_hex(s1).c_str(), string_as_hex(s2).c_str()); 128 | printf(" got %s, expected %s\n", match_key_as_hex(k1).c_str(), match_key_as_hex(k2).c_str()); 129 | std::u32string codepoints = miniutf::normalize32(s1, false, nullptr); 130 | printf(" codepoints are %s\n", string_as_hex(codepoints).c_str()); 131 | return false; 132 | } 133 | return true; 134 | } 135 | 136 | bool check_collation_order() { 137 | std::ifstream file("data-6.3.0/CollationTest/CollationTest_NON_IGNORABLE.txt"); 138 | 139 | if (!file) { 140 | printf("/!\\ Skipping collation test.\n"); 141 | printf(" The collation test data is large, so it isn't included with miniutf.\n"); 142 | printf(" To fetch it, cd into data-6.3.0/ and run fetch-collation-data.sh\n"); 143 | return true; 144 | } 145 | 146 | std::vector last_match_key {}; 147 | string last_line; 148 | 149 | string line; 150 | int i = 0; 151 | while (std::getline(file, line)) { 152 | auto semicolon = line.find(';'); 153 | if (semicolon == line.npos) { 154 | continue; 155 | } 156 | 157 | string s = decode_hex(line.substr(0, semicolon)); 158 | std::vector key = miniutf::match_key(s); 159 | 160 | if (key < last_match_key) { 161 | printf("Out of sequence, line %d:\n", i); 162 | printf("%s\n", last_line.c_str()); 163 | printf("-> %s\n", match_key_as_hex(last_match_key).c_str()); 164 | printf("%s\n", line.c_str()); 165 | dump(s); 166 | printf(" -> %s\n", match_key_as_hex(key).c_str()); 167 | return false; 168 | } 169 | 170 | last_match_key = key; 171 | last_line = line; 172 | i++; 173 | } 174 | 175 | printf("Collation OK\n"); 176 | return true; 177 | } 178 | 179 | int main(void) { 180 | 181 | string utf8_test = { '\x61', '\x00', '\xF0', '\x9F', '\x92', '\xA9' }; 182 | std::u16string utf16_test = { 0x61, 0, 0xD83D, 0xDCA9 }; 183 | 184 | // We also have some tests of UTF-8 to UTF-16 conversion 185 | string utf8 = miniutf::to_utf8(utf16_test); 186 | if (!check_eq("16-to-8", utf8_test, utf8)) 187 | return 1; 188 | 189 | std::u16string utf16 = miniutf::to_utf16(utf8_test); 190 | if (utf16 != utf16_test) { 191 | printf("utf8-to-utf16 test failed: got "); 192 | for (size_t i = 0; i < utf16.length(); i++) printf("%04x ", (uint16_t)utf16[i]); 193 | printf("\n"); 194 | return 1; 195 | } 196 | 197 | // Test match_key function 198 | if (!check_match_key(u8"Øǣç", 199 | u8"oaec")) { return 1; } 200 | if (!check_match_key(u8"ãäåèéêëüõñ", 201 | u8"aaaeeeeuon")) { return 1; } 202 | 203 | // Hammer on match_key a bit 204 | { 205 | std::mt19937 gen; // note: unseeded - so this is deterministic 206 | std::uniform_int_distribution<> cpt (1, 0x1ffff); 207 | std::uniform_int_distribution<> len (3, 10); 208 | 209 | for (int i = 0; i < 100000; i++) { 210 | std::u32string s; 211 | int n = len(gen); 212 | for (int i = 0; i < n; i++) { 213 | s += cpt(gen); 214 | } 215 | 216 | miniutf::match_key(miniutf::to_utf8(s)); 217 | } 218 | } 219 | 220 | std::ifstream file("data-6.3.0/NormalizationTest.txt"); 221 | 222 | string line; 223 | while (std::getline(file, line)) 224 | if (process_test_line(line)) 225 | return 1; 226 | 227 | if (!check_collation_order()) 228 | return 1; 229 | 230 | printf("OK\n"); 231 | return 0; 232 | } 233 | --------------------------------------------------------------------------------