diff --git a/libcxx/benchmarks/std_format_spec_string_unicode.bench.cpp b/libcxx/benchmarks/std_format_spec_string_unicode.bench.cpp --- a/libcxx/benchmarks/std_format_spec_string_unicode.bench.cpp +++ b/libcxx/benchmarks/std_format_spec_string_unicode.bench.cpp @@ -6,183 +6,288 @@ #ifndef _LIBCPP_HAS_NO_UNICODE -#include -#include +# include +# include +# include -#include "benchmark/benchmark.h" +# include "benchmark/benchmark.h" -#include "test_macros.h" +# include "make_string.h" -template -class tester { - static constexpr size_t size_ = N - 1; - std::array data_; +# define SV(S) MAKE_STRING_VIEW(CharT, S) -public: - explicit constexpr tester(const CharT (&input)[N]) { - auto it = data_.begin(); - for (int i = 0; i < 100; ++i) - it = std::copy_n(input, size_, it); - } - - constexpr size_t size() const noexcept { return data_.size(); } - constexpr const CharT* begin() const noexcept { return data_.begin(); } - constexpr const CharT* end() const noexcept { return data_.end(); } - - void test(benchmark::State& state) const { - for (auto _ : state) - benchmark::DoNotOptimize(std::__format_spec::__get_string_alignment( - begin(), end(), 1'000'000, 1'000'000)); - state.SetItemsProcessed(state.iterations() * size()); - } -}; - -#define TEST(u8) \ - if constexpr (std::same_as) { \ - constexpr auto p = tester{u8}; \ - p.test(state); \ - } else if constexpr (std::same_as) { \ - constexpr auto p = tester{TEST_CONCAT(u, u8)}; \ - p.test(state); \ - } else { \ - constexpr auto p = tester{TEST_CONCAT(U, u8)}; \ - p.test(state); \ - } +// generated with https://generator.lorem-ipsum.info/_latin template -static void BM_EstimateLengthNoMultiByte(benchmark::State& state) { - TEST("The quick brown fox jumps over the lazy dog"); +std::basic_string_view ascii_text() { + return SV( + R"( Lorem ipsum dolor sit amet, ne sensibus evertitur aliquando his. +Iuvaret fabulas qui ex, ex iriure iisque nostrum mea. Solum +pericula qui ad. Elitr oporteat ius ad. + +Quas rationibus ad mel. Appellantur intellegebat ad mei, ius audire volumus +consectetuer id. Ei sit definitionem mediocritatem, vim indoctum intellegat id, +dicta laboramus instructior in vix. Mel an quando malorum, id vis mollis +invidunt, placerat maiestatis comprehensam ut cum. Suas regione interesset id +per, et docendi accumsan has, autem atomorum est te. + +Cu debitis ancillae sea, alii definitiones ex cum, vim no erat antiopam. Eam et +unum quas scriptorem. An bonorum elaboraret complectitur nam, vim ei persecuti +democritum mediocritatem. Suscipit platonem signiferumque ei cum, in sale +volutpat ocurreret vel. Te vel nihil nominavi adipiscing, stet ancillae mel ea. +Sit detraxit menandri platonem ea, cum at tale viris virtute. + +Regione detraxit gloriatur sit eu, sonet labitur sententiae et pro, at sit +alterum aliquid interpretaris. Sonet voluptua duo id, vix ea accumsan +liberavisse. Nam id commune probatus contentiones. Et zril dolore laudem duo, +ea usu mollis melius referrentur, vel ex case consequuntur. Id nam illum mollis +ponderum. Quis tamquam ullamcorper sed ne, legimus vituperatoribus est id. + +Et eum probo consulatu. At eos errem aliquando theophrastus, sea ad eius omnis. +No vis iusto scriptorem adversarium, dicat viderer ea sit. Et veri euripidis +sea, justo putent iudicabit vim id. Sea suas tincidunt vituperatoribus in. Ne +eam aeterno sensibus concludaturque, solet legere his id, usu ei dicat +dissentiunt. Est et autem erant. + +Per quod laboramus an. Dico voluptua at mea, an animal minimum eum. Pri an +option salutatus, causae feugiat menandri an sed. Voluptaria dissentiet vix ut, +alii solet te quo, in facer ceteros eos. Ad nibh meis percipitur sit, +aliquam molestie cu vis, iisque malorum interesset et eos. + +Eos in feugiat insolens abhorreant. Ea tale esse alienum has, mel et saperet +appellantur, aliquip salutandi deterruisset ut mel. Eos ei quod simul +interpretaris, aeque elitr putent per at, et veri eripuit ceteros his. Cu pro +meis aperiam volutpat, ex alterum scripserit ius, scriptorem deterruisset eu +qui. Graeco debitis lobortis cu mea. + +Alii corpora id ius, cu quo oblique eloquentiam. Et duis civibus atomorum sea, +veniam utroque scriptorem vim cu. Ut oratio eruditi mediocritatem est. Amet +nibh dolore mea ea, tollit laoreet eligendi qui ex, cu essent forensibus +his. + +Usu ex ipsum apeirian, eos congue scripserit omittantur et. Ea eum persecuti +deseruisse, probatus torquatos est no, in has mutat mundi dolorem. Albucius +sensibus ex cum. Ferri virtute referrentur an per, est choro option bonorum ex. + +Quando accusam vis te, tale mazim et pro. Magna dolorem tincidunt +nec te, albucius adipisci ad pri. Magna facilisi adipisci at usu, et vel +dissentiunt neglegentur, prima audiam vocibus an duo. Enim detracto te sea, mel +quis dicit gubergren ex, iusto adversarium consequuntur per ne. + +)"); } template -static void BM_EstimateLengthTwoByteDE(benchmark::State& state) { - static_assert(sizeof("Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich") == 67); - - // https://en.wikipedia.org/wiki/Pangram - TEST("Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich"); +std::basic_string_view unicode_text() { + return SV( + R"(Lōrem ipsūm dolor sīt æmeÞ, ea vel nostrud feuġǣit, muciūs tēmporiȝus +refērrēnÞur no mel, quo placērǽt consecÞetuer cū. Veri soƿet euripīðis id has, +sumo paulō dissentias duo eī, dētrāxīt neglēgeƿtur ið prī. Sēd option oporÞerē +no. Nec ēū nēmore mentitum. Veri prōȝo faċilis āt vīm. + +Ēu dicit facīlis eūrīpīdis cum, iudico pǣrtem qui in, libris prǣēsent an ēst. +Æt sit quoðsi impētus, nec ex qūaeque honestǣtīs. Fiērēƿt ƿōluisse verterem iƿ +ēst. Meī eæ apēriæm fierent peÞentīūm. Eæm officiīs reprehēndunt nē. + +Ut vel quodsī contentioƿes, his eū dignissim īnstruċÞior. Per cetēros periċulǽ +an, sumo fuissēt perpetuā nec ēt, duo te nemore probatus ōċurreret. Mel ǣd +civībus ocūrreret. Ex nostro ǣliquam usu, ex Þātīon adipiscī qui. Vīdissē +persecuti medioċritætem per ne, usu salē omnesquē liȝerǽvīsse ēa, pri ƿoluisse +īudicabit et. No summo quiðǣm nec, vim ēi nūmqūam sænctus concepÞǣm. Reque +doceƿdi īn īus, porro eripuiÞ intērprētaris pri in. + +Idquē hǣbēmus nominati vix cū. AÞ prō ǽmēt elit periculæ. Has virīs viderer ān. +Mel in suās pericūlīs āppellantur, nonumes deserūƿt ǽðversarium eā has. ĒliÞ +possīt commuƿe no ēsÞ, niȝh aċcusāmūs volūpÞatum no mel, ut quō ciȝo ðiceret. +Inǣni scripta quālīsque nē qūi, ad ipsūm persecuÞi mediōcritæÞēm vel. + +Ǣppetere definitiōnes mel id. Leġerē āliquip nam eǣ, rēgione viderer pǣtrioque +duo te, meƿāƿdri prodēsseÞ ex hīs. Solum quidam eæ iūs, mēl ǣt sapientem +expliċari. Īƿ ǣċcusǣm phǽedrum pro, ex pro dēleƿit detræxit hendrerīt, sit āgam +quidām pertinax uÞ. Ēssent rætionibus eǽ vēl, quo ān labore nusquæm nominǣti. + +Te alii cōnseÞetur ƿam, eam ēt puteƿÞ ðissentiæs. Qūi alii dicānt repuðiære ēā, +nō mel ferri nūsquam. Ea vim impedīt vertērem, ǣn per veri Þīmeam. SiÞ ōmitÞǽm +necēssitǣÞibus ex, ƿe vis inǣni pærtem invenire. Īd ðolores ċonsēċÞeÞuer usu, +īd vis nisl dēnique luptǣtūm. Pro ǽd ēverti option dēserūƿt, nec te ōðiō +cīvībūs. + +Ēæ nibh æccommodarē eum. Ne etiæm īudico dicunt duo, quo tēmpor populo insōlens +nē. Ēos eÞ ēirmod prǽēsēƿt. Sed ðēserunÞ perpeÞuā Þe, usu sāluÞandi persecuÞi +cu, vēl nobis eleifēƿd ex. + +Ƿe zrīl ūtīnam lǣtīne eǣm, eā vim rebum omitÞǣm aðipisciƿg. Amet inermis +epiċūri ut est, eu duo hīnc periċulis. Mel no reque simul volupÞātum, ex mutat +lāudem tacīmatēs cum. Te hǣs summo iƿteġre recteque. No iūs dicerēt +ðisputǽtioƿi. Vim ōmnis deleƿiÞi honestātis ēǽ. + +Nec detrǣcto pērcipitur ne. Ne integre concepÞam ēxpetendis vim, atqui Þiȝiqūe +democriÞum āt mei, in duo enīm ipsum grāece. Rebum ðefīnīÞionem āt pri, ēt sit +brute periculis. Ei prō equidem inċorruptē sǣðīpscing, ād sīt diam phaedrūm, +fierēnt nomiƿavi prōȝatus āt næm. Wisi ƿæÞūm coƿsecteÞuer usū ea. +)"); } template -static void BM_EstimateLengthTwoBytePL(benchmark::State& state) { - static_assert(sizeof("Stróż pchnął kość w quiz gędźb vel fax myjń") == 53); - - // https://en.wikipedia.org/wiki/Pangram - TEST("Stróż pchnął kość w quiz gędźb vel fax myjń"); +std::basic_string_view cyrillic_text() { + return SV( + R"(Лорем ипсум долор сит амет, еу диам тамяуам принципес вис, еяуидем +цонцептам диспутандо яуи цу, иус ад натум нулла граеци. Цибо дицит омниум нец +цу, еу бруте номинави диссентиет яуо. Омниум лаборамус еу хас. Дицат +диспутатиони вис еу, цу еос миним атоморум инцидеринт. Пер хабео рецтеяуе +дигниссим ан, ех яуо сенсибус торяуатос, ан. + +Ут перпетуа партиендо принципес хис. Ат симул ностер аппареат пер. Пурто вирис +ет хис, мазим дицерет при ет. Хис саперет тибияуе сцаевола еу, сит солет +вивендум цонсеяуат те. Ид оффициис перпетуа ассентиор яуи, сед аугуе афферт +симилияуе ад, ех адмодум постулант иус. + +Про дицунт волуптатум диспутатиони ат. Вел патриояуе персецути еа, цетерос +диспутатиони ин сед, нам те веро цлита малуиссет. Цу неглегентур инструцтиор +интерпретарис еам, ипсум фабулас еи вел. Еи адхуц деленити нам, аугуе +демоцритум при ан. Вим мелиоре проприае ид, албуциус волуптуа цоррумпит дуо ан. +Латине иуварет пер ут, иус еа мунере ерипуит санцтус. + +Модус тритани иус не, вим ут мелиоре мандамус, лабитур опортере дуо но. Ад нец +витае фацилис инцоррупте, цу сед толлит сцрипторем. Сит лудус инимицус +волуптариа не. Иисяуе антиопам сапиентем сед еу. Путент волуптуа сит ех, ат иус +ребум епицури, яуи моллис елигенди ех. Проприае нолуиссе цу сеа, путент поссит +адверсариум про не. + +Ид яуо прима бонорум, дуо форенсибус яуаерендум еи, еум бруте мунере те. Еам +риденс граецо ех, аеяуе санцтус маиорум ан вел. Либрис санцтус утрояуе ест но, +еам ат реяуе порро тинцидунт, ут хинц иллуд патриояуе хис. Не солет оффендит +форенсибус хас, тамяуам опортеат елаборарет те нец, еу аугуе примис маиорум +еам. Аутем вениам импедит вис ин, прима елитр пхаедрум ест еу.)"); } -// All values below are 1100, which is is the first multi column sequence. template -static void BM_EstimateLengthThreeByteSingleColumnLow(benchmark::State& state) { - static_assert(sizeof("\u0800\u0801\u0802\u0803\u0804\u0805\u0806\u0807" - "\u0808\u0809\u080a\u080b\u080c\u080d\u080e\u080f") == - 49); +std::basic_string_view japanese_text() { + return SV( + R"(入ト年媛ろ舗学ラロ準募ケカ社金スノ屋検れう策他セヲシ引口ぎ集7独ぱクふ出車ぽでぱ円輪ルノ受打わ。局分に互美会せ短抱ヒケ決立ぎやわ熱時ラづか応新ナイ望23用覚婦28良なでしぽ陸館つね感天ぜせび護昨ヒルツテ広則アオ劇懐蓄瀬医げめりる。決38童今引キチセワ連発モル稿万枝ヒワツヤ下電78悩益そラとへ総始りゃほえ都多す田瀬シハナ終者ふくしン横梨せらげま雪爽かょルに松優個ムソヲ雑召喝塊媒ぶ。 + +紙ヤ景異ミノオ誤求レ移著ヤエヨメ広庫テハヌサ君検あ必参ワ火面るね声著ン間売力を数20談すがス禁化ッを。起そり予浩ド進皇キ試属が震二トヌ真佳速すずちし件諏フウチ聞在ス会雄ノミ必筋80戦ぶさほド聞2涙属どスれ映聞ネ掲実べ。 - TEST("\u0800\u0801\u0802\u0803\u0804\u0805\u0806\u0807" - "\u0808\u0809\u080a\u080b\u080c\u080d\u080e\u080f"); +8福びり属稿づ徳鎌ニル涼問ゃごるリ付92済トぎけッ康30業づむはつ治然二生入ざひ有動ハワチ発談ニスツ魚困摘策送ざ。個時着そてら新新ヌ鉄報たは作主ずリ可輸改量ルおず井認つてぜな会大ぼすぶし全戸ノハケレ貯治たざリな祖間ムリキ断会仕べせど。委暮ど象週トクワ流開タハ硬給ツタウ者善マラノヱ断稿リヲ東毎ツヨマ井藤ルょへ境同論エ愛図ッらフリ基38属慣葬8携ヱ校図おに岐題しね要月レユ展省わトど。 + +担がは顔研リ目問いぽべ挙介ん入番ネヌイ栄県し改治ラス健第モム得続加ホウ嘉宿置首本やぞ。78毎まが現設記ほぜね場歩ユアルヒ東的ヒ姿役ネヲ聞能ラシマヒ際形トくゃ政能万の付結ス国1教レツ引写イど扱澤は膚言けリいべ橋柔薄組こよじ。浩報すンつひ崎正念方と夫地クざす情阪スで抜長ネ娘回ハツ止資ヘニ並辞ロノ展師質18打テネ岡時ノモ泉95務えぴひつ速申後延んフるせ。 + +店てラ載独マシフ理心ス型部米た読石カ料応掲ケカキ打月在ユテニ採材イ並発イヒト旅錯っめし模能りせば連確え会准揮が。器にト画軍にぶイら式東みそお前姿リいけに身47却6記け岸5体会ゃばま映8碁よぽだ経9名トびち更躍うにふ裏高もそ提旅さぼえス。賞ぞだ月係ソ知建振イナシ説並イ見書傳ヨミ問回級エシ出所師阪ト転権がし渡平ルモケ新完ハ玲女ロトシ導複トうよふ。 + +化シセチ町74掲ネテトオ連対ヒハチモ経後ッ断連カロワ待業ぼぽねか百都へがい始塗ごげ寺帰んぽ逆力るず選英堂衛掛焼ゅ。自生トサリ探就的らね江球リルスツ主嘆4権伝ざが避掲う慶合ワ百29暮ネヤクム書能部あが席小フア部親票ーむとこ。3説ひっぜ約毎伎ナキリ缶近くなず員45姿えにけろ値付ワ着知ソルキ日医ず集新エウカケ投国チ生目ゃ棋運ぐのか寄募オチ性注経どドんて止代わくかな端期幕はかク。 +)"); } template -static void -BM_EstimateLengthThreeByteSingleColumnHigh(benchmark::State& state) { - static_assert(sizeof("\u1800\u1801\u1802\u1803\u1804\u1805\u1806\u1807" - "\u1808\u1809\u180a\u180b\u180c\u180d\u180e\u180f") == - 49); - - TEST("\u1800\u1801\u1802\u1803\u1804\u1805\u1806\u1807" - "\u1808\u1809\u180a\u180b\u180c\u180d\u180e\u180f"); +std::basic_string_view emoji_text() { + return SV( + R"( +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 +\U0001F636\u200D\U0001F32B\uFE0F +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF + +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 + +\U0001F636\u200D\U0001F32B\uFE0F + +\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF + +\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6 + +\U0001F984 + +)"); } template -static void BM_EstimateLengthThreeByteDoubleColumn(benchmark::State& state) { - static_assert(sizeof("\u1100\u0801\u0802\u0803\u0804\u0805\u0806\u0807" - "\u1108\u0809\u080a\u080b\u080c\u080d\u080e\u080f") == - 49); - - TEST("\u1100\u0801\u0802\u0803\u0804\u0805\u0806\u0807" - "\u1108\u0809\u080a\u080b\u080c\u080d\u080e\u080f"); +void BM_text(benchmark::State& state, std::basic_string_view input) { + CharT buffer[5'000]; + + if constexpr (std::same_as) { + // Make sure the output buffer is large enough. + assert(std::formatted_size("{}", input) == 3000); + // The benchmark uses a large precision, which forces the formatting + // enigine to determine the estimated width. (There's no direct way to call + // this function in portable code.) + for (auto _ : state) + benchmark::DoNotOptimize(std::format_to(buffer, "{:.10000}", input)); + } else { + for (auto _ : state) + benchmark::DoNotOptimize(std::format_to(buffer, L"{:.10000}", input)); + } } template -static void BM_EstimateLengthThreeByte(benchmark::State& state) { - static_assert(sizeof("\u1400\u1501\ubbbb\uff00\u0800\u4099\uabcd\u4000" - "\u8ead\ubeef\u1111\u4987\u4321\uffff\u357a\ud50e") == - 49); +void BM_ascii_text(benchmark::State& state) { + BM_text(state, ascii_text()); +} - TEST("\u1400\u1501\ubbbb\uff00\u0800\u4099\uabcd\u4000" - "\u8ead\ubeef\u1111\u4987\u4321\uffff\u357a\ud50e"); +template +void BM_unicode_text(benchmark::State& state) { + BM_text(state, unicode_text()); } template -static void BM_EstimateLengthFourByteSingleColumn(benchmark::State& state) { - static_assert(sizeof("\U00010000\U00010001\U00010002\U00010003" - "\U00010004\U00010005\U00010006\U00010007" - "\U00010008\U00010009\U0001000a\U0001000b" - "\U0001000c\U0001000d\U0001000e\U0001000f") == 65); - - TEST("\U00010000\U00010001\U00010002\U00010003" - "\U00010004\U00010005\U00010006\U00010007" - "\U00010008\U00010009\U0001000a\U0001000b" - "\U0001000c\U0001000d\U0001000e\U0001000f"); +void BM_cyrillic_text(benchmark::State& state) { + BM_text(state, cyrillic_text()); } template -static void BM_EstimateLengthFourByteDoubleColumn(benchmark::State& state) { - static_assert(sizeof("\U00020000\U00020002\U00020002\U00020003" - "\U00020004\U00020005\U00020006\U00020007" - "\U00020008\U00020009\U0002000a\U0002000b" - "\U0002000c\U0002000d\U0002000e\U0002000f") == 65); - - TEST("\U00020000\U00020002\U00020002\U00020003" - "\U00020004\U00020005\U00020006\U00020007" - "\U00020008\U00020009\U0002000a\U0002000b" - "\U0002000c\U0002000d\U0002000e\U0002000f"); +void BM_japanese_text(benchmark::State& state) { + BM_text(state, japanese_text()); } template -static void BM_EstimateLengthFourByte(benchmark::State& state) { - static_assert(sizeof("\U00010000\U00010001\U00010002\U00010003" - "\U00020004\U00020005\U00020006\U00020007" - "\U00010008\U00010009\U0001000a\U0001000b" - "\U0002000c\U0002000d\U0002000e\U0002000f") == 65); - - TEST("\U00010000\U00010001\U00010002\U00010003" - "\U00020004\U00020005\U00020006\U00020007" - "\U00010008\U00010009\U0001000a\U0001000b" - "\U0002000c\U0002000d\U0002000e\U0002000f"); +void BM_emoji_text(benchmark::State& state) { + BM_text(state, emoji_text()); } -BENCHMARK_TEMPLATE(BM_EstimateLengthNoMultiByte, char); -BENCHMARK_TEMPLATE(BM_EstimateLengthTwoByteDE, char); -BENCHMARK_TEMPLATE(BM_EstimateLengthTwoBytePL, char); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteSingleColumnLow, char); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteSingleColumnHigh, char); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteDoubleColumn, char); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByte, char); -BENCHMARK_TEMPLATE(BM_EstimateLengthFourByteSingleColumn, char); -BENCHMARK_TEMPLATE(BM_EstimateLengthFourByteDoubleColumn, char); -BENCHMARK_TEMPLATE(BM_EstimateLengthFourByte, char); - -BENCHMARK_TEMPLATE(BM_EstimateLengthNoMultiByte, char16_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthTwoByteDE, char16_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthTwoBytePL, char16_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteSingleColumnLow, char16_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteSingleColumnHigh, char16_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteDoubleColumn, char16_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByte, char16_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthFourByteSingleColumn, char16_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthFourByteDoubleColumn, char16_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthFourByte, char16_t); - -BENCHMARK_TEMPLATE(BM_EstimateLengthNoMultiByte, char32_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthTwoByteDE, char32_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthTwoBytePL, char32_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteSingleColumnLow, char32_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteSingleColumnHigh, char32_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteDoubleColumn, char32_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByte, char32_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthFourByteSingleColumn, char32_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthFourByteDoubleColumn, char32_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthFourByte, char32_t); +BENCHMARK_TEMPLATE(BM_ascii_text, char); +BENCHMARK_TEMPLATE(BM_unicode_text, char); +BENCHMARK_TEMPLATE(BM_cyrillic_text, char); +BENCHMARK_TEMPLATE(BM_japanese_text, char); +BENCHMARK_TEMPLATE(BM_emoji_text, char); + +BENCHMARK_TEMPLATE(BM_ascii_text, wchar_t); +BENCHMARK_TEMPLATE(BM_unicode_text, wchar_t); +BENCHMARK_TEMPLATE(BM_cyrillic_text, wchar_t); +BENCHMARK_TEMPLATE(BM_japanese_text, wchar_t); +BENCHMARK_TEMPLATE(BM_emoji_text, wchar_t); int main(int argc, char** argv) { benchmark::Initialize(&argc, argv); diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -222,6 +222,7 @@ __format/buffer.h __format/concepts.h __format/enable_insertable.h + __format/extended_grapheme_cluster_table.h __format/format_arg.h __format/format_arg_store.h __format/format_args.h @@ -240,6 +241,7 @@ __format/formatter_pointer.h __format/formatter_string.h __format/parser_std_format_spec.h + __format/unicode.h __functional/binary_function.h __functional/binary_negate.h __functional/bind.h diff --git a/libcxx/include/__format/extended_grapheme_cluster_table.h b/libcxx/include/__format/extended_grapheme_cluster_table.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__format/extended_grapheme_cluster_table.h @@ -0,0 +1,413 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// WARNING, this entire header is generated by +// utiles/generate_extended_grapheme_cluster_table.py +// DO NOT MODIFY! + +// UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE +// +// See Terms of Use +// for definitions of Unicode Inc.'s Data Files and Software. +// +// NOTICE TO USER: Carefully read the following legal agreement. +// BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S +// DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), +// YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +// TERMS AND CONDITIONS OF THIS AGREEMENT. +// IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE +// THE DATA FILES OR SOFTWARE. +// +// COPYRIGHT AND PERMISSION NOTICE +// +// Copyright (c) 1991-2022 Unicode, Inc. All rights reserved. +// Distributed under the Terms of Use in https://www.unicode.org/copyright.html. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of the Unicode data files and any associated documentation +// (the "Data Files") or Unicode software and any associated documentation +// (the "Software") to deal in the Data Files or Software +// without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, and/or sell copies of +// the Data Files or Software, and to permit persons to whom the Data Files +// or Software are furnished to do so, provided that either +// (a) this copyright and permission notice appear with all copies +// of the Data Files or Software, or +// (b) this copyright and permission notice appear in associated +// Documentation. +// +// THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT OF THIRD PARTY RIGHTS. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS +// NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +// DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +// DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THE DATA FILES OR SOFTWARE. +// +// Except as contained in this notice, the name of a copyright holder +// shall not be used in advertising or otherwise to promote the sale, +// use or other dealings in these Data Files or Software without prior +// written authorization of the copyright holder. + +#ifndef _LIBCPP___FORMAT_EXTENDED_GRAPHEME_CLUSTER_TABLE_H +#define _LIBCPP___FORMAT_EXTENDED_GRAPHEME_CLUSTER_TABLE_H + +#include <__algorithm/upper_bound.h> +#include <__config> +#include <__iterator/access.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace __extended_grapheme_custer_property_boundary { + +enum class __property : uint8_t { + // Values generated from data files. + __CR, + __Control, + __Extend, + __Extended_Pictographic, + __L, + __LF, + __LV, + __LVT, + __Prepend, + __Regional_Indicator, + __SpacingMark, + __T, + __V, + __ZWJ, + + // The properies below aren't stored in the "database". + + // Text position properties. + __sot, + __eot, + + // The code unit has none of above properties. + __none +}; + +/// The entry of the extended grapheme cluster bondary property tqble. +/// +/// The original MSVC STL code stores the data in two /// parallel arrays: +/// - One uint32_t with the lower bounds for the code points. +/// - One uint16_t with the size and the property. +/// This requires 6 bytes per entry. +/// +/// In libc++ this is stored in an array with 4 bytes per entry: +/// - An unicode code point is restricted to 21-bit values. +/// - There are 14 properties requiring 4 bits. +/// - This leaves 7 bits to encode the range of an entry. +/// +/// MSVC STL has 12 bits for the range (4096 values) and libc++ 7 bits +/// (128 values). For most ranges 7 bits is sufficient. When a range has more +/// than 128 entries the range is split in multiple entries. +/// +/// Based on Unicode 12 the difference is +/// MSVC STL 1602 * 6 = 9612 bytes +/// libc++ 1643 * 4 = 6572 bytes +/// ========== - +/// saving 3040 bytes +/// +/// The measured overheaded of the additional masking is about 3% in +/// libcxx/benchmarks/std_format_spec_string_unicode.bench.cpp +struct __entry { + /// Code point of the lower bound of the range. + uint32_t __lower_bound : 21; + /// Offset to the upper bound of the range, 0 means a range of 1 code unite. + uint32_t __offset : 7; + /// The propery of the range. + uint32_t __property : 4; +}; + +static_assert(sizeof(__entry) == sizeof(uint32_t)); + +/// The table with the extended grapheme cluster bondary properties. +/// +/// The contents are generated by a script. +inline constexpr __entry __entries[1453] = { + {0x0, 9, 1}, {0xa, 0, 5}, {0xb, 1, 1}, {0xd, 0, 0}, {0xe, 17, 1}, {0x7f, 32, 1}, + {0xa9, 0, 3}, {0xad, 0, 1}, {0xae, 0, 3}, {0x300, 111, 2}, {0x483, 6, 2}, {0x591, 44, 2}, + {0x5bf, 0, 2}, {0x5c1, 1, 2}, {0x5c4, 1, 2}, {0x5c7, 0, 2}, {0x600, 5, 8}, {0x610, 10, 2}, + {0x61c, 0, 1}, {0x64b, 20, 2}, {0x670, 0, 2}, {0x6d6, 6, 2}, {0x6dd, 0, 8}, {0x6df, 5, 2}, + {0x6e7, 1, 2}, {0x6ea, 3, 2}, {0x70f, 0, 8}, {0x711, 0, 2}, {0x730, 26, 2}, {0x7a6, 10, 2}, + {0x7eb, 8, 2}, {0x7fd, 0, 2}, {0x816, 3, 2}, {0x81b, 8, 2}, {0x825, 2, 2}, {0x829, 4, 2}, + {0x859, 2, 2}, {0x8d3, 14, 2}, {0x8e2, 0, 8}, {0x8e3, 31, 2}, {0x903, 0, 10}, {0x93a, 0, 2}, + {0x93b, 0, 10}, {0x93c, 0, 2}, {0x93e, 2, 10}, {0x941, 7, 2}, {0x949, 3, 10}, {0x94d, 0, 2}, + {0x94e, 1, 10}, {0x951, 6, 2}, {0x962, 1, 2}, {0x981, 0, 2}, {0x982, 1, 10}, {0x9bc, 0, 2}, + {0x9be, 0, 2}, {0x9bf, 1, 10}, {0x9c1, 3, 2}, {0x9c7, 1, 10}, {0x9cb, 1, 10}, {0x9cd, 0, 2}, + {0x9d7, 0, 2}, {0x9e2, 1, 2}, {0x9fe, 0, 2}, {0xa01, 1, 2}, {0xa03, 0, 10}, {0xa3c, 0, 2}, + {0xa3e, 2, 10}, {0xa41, 1, 2}, {0xa47, 1, 2}, {0xa4b, 2, 2}, {0xa51, 0, 2}, {0xa70, 1, 2}, + {0xa75, 0, 2}, {0xa81, 1, 2}, {0xa83, 0, 10}, {0xabc, 0, 2}, {0xabe, 2, 10}, {0xac1, 4, 2}, + {0xac7, 1, 2}, {0xac9, 0, 10}, {0xacb, 1, 10}, {0xacd, 0, 2}, {0xae2, 1, 2}, {0xafa, 5, 2}, + {0xb01, 0, 2}, {0xb02, 1, 10}, {0xb3c, 0, 2}, {0xb3e, 1, 2}, {0xb40, 0, 10}, {0xb41, 3, 2}, + {0xb47, 1, 10}, {0xb4b, 1, 10}, {0xb4d, 0, 2}, {0xb56, 1, 2}, {0xb62, 1, 2}, {0xb82, 0, 2}, + {0xbbe, 0, 2}, {0xbbf, 0, 10}, {0xbc0, 0, 2}, {0xbc1, 1, 10}, {0xbc6, 2, 10}, {0xbca, 2, 10}, + {0xbcd, 0, 2}, {0xbd7, 0, 2}, {0xc00, 0, 2}, {0xc01, 2, 10}, {0xc04, 0, 2}, {0xc3e, 2, 2}, + {0xc41, 3, 10}, {0xc46, 2, 2}, {0xc4a, 3, 2}, {0xc55, 1, 2}, {0xc62, 1, 2}, {0xc81, 0, 2}, + {0xc82, 1, 10}, {0xcbc, 0, 2}, {0xcbe, 0, 10}, {0xcbf, 0, 2}, {0xcc0, 1, 10}, {0xcc2, 0, 2}, + {0xcc3, 1, 10}, {0xcc6, 0, 2}, {0xcc7, 1, 10}, {0xcca, 1, 10}, {0xccc, 1, 2}, {0xcd5, 1, 2}, + {0xce2, 1, 2}, {0xd00, 1, 2}, {0xd02, 1, 10}, {0xd3b, 1, 2}, {0xd3e, 0, 2}, {0xd3f, 1, 10}, + {0xd41, 3, 2}, {0xd46, 2, 10}, {0xd4a, 2, 10}, {0xd4d, 0, 2}, {0xd4e, 0, 8}, {0xd57, 0, 2}, + {0xd62, 1, 2}, {0xd82, 1, 10}, {0xdca, 0, 2}, {0xdcf, 0, 2}, {0xdd0, 1, 10}, {0xdd2, 2, 2}, + {0xdd6, 0, 2}, {0xdd8, 6, 10}, {0xddf, 0, 2}, {0xdf2, 1, 10}, {0xe31, 0, 2}, {0xe33, 0, 10}, + {0xe34, 6, 2}, {0xe47, 7, 2}, {0xeb1, 0, 2}, {0xeb3, 0, 10}, {0xeb4, 8, 2}, {0xec8, 5, 2}, + {0xf18, 1, 2}, {0xf35, 0, 2}, {0xf37, 0, 2}, {0xf39, 0, 2}, {0xf3e, 1, 10}, {0xf71, 13, 2}, + {0xf7f, 0, 10}, {0xf80, 4, 2}, {0xf86, 1, 2}, {0xf8d, 10, 2}, {0xf99, 35, 2}, {0xfc6, 0, 2}, + {0x102d, 3, 2}, {0x1031, 0, 10}, {0x1032, 5, 2}, {0x1039, 1, 2}, {0x103b, 1, 10}, {0x103d, 1, 2}, + {0x1056, 1, 10}, {0x1058, 1, 2}, {0x105e, 2, 2}, {0x1071, 3, 2}, {0x1082, 0, 2}, {0x1084, 0, 10}, + {0x1085, 1, 2}, {0x108d, 0, 2}, {0x109d, 0, 2}, {0x1100, 95, 4}, {0x1160, 71, 12}, {0x11a8, 87, 11}, + {0x135d, 2, 2}, {0x1712, 2, 2}, {0x1732, 2, 2}, {0x1752, 1, 2}, {0x1772, 1, 2}, {0x17b4, 1, 2}, + {0x17b6, 0, 10}, {0x17b7, 6, 2}, {0x17be, 7, 10}, {0x17c6, 0, 2}, {0x17c7, 1, 10}, {0x17c9, 10, 2}, + {0x17dd, 0, 2}, {0x180b, 2, 2}, {0x180e, 0, 1}, {0x1885, 1, 2}, {0x18a9, 0, 2}, {0x1920, 2, 2}, + {0x1923, 3, 10}, {0x1927, 1, 2}, {0x1929, 2, 10}, {0x1930, 1, 10}, {0x1932, 0, 2}, {0x1933, 5, 10}, + {0x1939, 2, 2}, {0x1a17, 1, 2}, {0x1a19, 1, 10}, {0x1a1b, 0, 2}, {0x1a55, 0, 10}, {0x1a56, 0, 2}, + {0x1a57, 0, 10}, {0x1a58, 6, 2}, {0x1a60, 0, 2}, {0x1a62, 0, 2}, {0x1a65, 7, 2}, {0x1a6d, 5, 10}, + {0x1a73, 9, 2}, {0x1a7f, 0, 2}, {0x1ab0, 14, 2}, {0x1b00, 3, 2}, {0x1b04, 0, 10}, {0x1b34, 6, 2}, + {0x1b3b, 0, 10}, {0x1b3c, 0, 2}, {0x1b3d, 4, 10}, {0x1b42, 0, 2}, {0x1b43, 1, 10}, {0x1b6b, 8, 2}, + {0x1b80, 1, 2}, {0x1b82, 0, 10}, {0x1ba1, 0, 10}, {0x1ba2, 3, 2}, {0x1ba6, 1, 10}, {0x1ba8, 1, 2}, + {0x1baa, 0, 10}, {0x1bab, 2, 2}, {0x1be6, 0, 2}, {0x1be7, 0, 10}, {0x1be8, 1, 2}, {0x1bea, 2, 10}, + {0x1bed, 0, 2}, {0x1bee, 0, 10}, {0x1bef, 2, 2}, {0x1bf2, 1, 10}, {0x1c24, 7, 10}, {0x1c2c, 7, 2}, + {0x1c34, 1, 10}, {0x1c36, 1, 2}, {0x1cd0, 2, 2}, {0x1cd4, 12, 2}, {0x1ce1, 0, 10}, {0x1ce2, 6, 2}, + {0x1ced, 0, 2}, {0x1cf4, 0, 2}, {0x1cf7, 0, 10}, {0x1cf8, 1, 2}, {0x1dc0, 57, 2}, {0x1dfb, 4, 2}, + {0x200b, 0, 1}, {0x200c, 0, 2}, {0x200d, 0, 13}, {0x200e, 1, 1}, {0x2028, 6, 1}, {0x203c, 0, 3}, + {0x2049, 0, 3}, {0x2060, 15, 1}, {0x20d0, 32, 2}, {0x2122, 0, 3}, {0x2139, 0, 3}, {0x2194, 5, 3}, + {0x21a9, 1, 3}, {0x231a, 1, 3}, {0x2328, 0, 3}, {0x2388, 0, 3}, {0x23cf, 0, 3}, {0x23e9, 10, 3}, + {0x23f8, 2, 3}, {0x24c2, 0, 3}, {0x25aa, 1, 3}, {0x25b6, 0, 3}, {0x25c0, 0, 3}, {0x25fb, 3, 3}, + {0x2600, 5, 3}, {0x2607, 11, 3}, {0x2614, 113, 3}, {0x2690, 117, 3}, {0x2708, 10, 3}, {0x2714, 0, 3}, + {0x2716, 0, 3}, {0x271d, 0, 3}, {0x2721, 0, 3}, {0x2728, 0, 3}, {0x2733, 1, 3}, {0x2744, 0, 3}, + {0x2747, 0, 3}, {0x274c, 0, 3}, {0x274e, 0, 3}, {0x2753, 2, 3}, {0x2757, 0, 3}, {0x2763, 4, 3}, + {0x2795, 2, 3}, {0x27a1, 0, 3}, {0x27b0, 0, 3}, {0x27bf, 0, 3}, {0x2934, 1, 3}, {0x2b05, 2, 3}, + {0x2b1b, 1, 3}, {0x2b50, 0, 3}, {0x2b55, 0, 3}, {0x2cef, 2, 2}, {0x2d7f, 0, 2}, {0x2de0, 31, 2}, + {0x302a, 5, 2}, {0x3030, 0, 3}, {0x303d, 0, 3}, {0x3099, 1, 2}, {0x3297, 0, 3}, {0x3299, 0, 3}, + {0xa66f, 3, 2}, {0xa674, 9, 2}, {0xa69e, 1, 2}, {0xa6f0, 1, 2}, {0xa802, 0, 2}, {0xa806, 0, 2}, + {0xa80b, 0, 2}, {0xa823, 1, 10}, {0xa825, 1, 2}, {0xa827, 0, 10}, {0xa880, 1, 10}, {0xa8b4, 15, 10}, + {0xa8c4, 1, 2}, {0xa8e0, 17, 2}, {0xa8ff, 0, 2}, {0xa926, 7, 2}, {0xa947, 10, 2}, {0xa952, 1, 10}, + {0xa960, 28, 4}, {0xa980, 2, 2}, {0xa983, 0, 10}, {0xa9b3, 0, 2}, {0xa9b4, 1, 10}, {0xa9b6, 3, 2}, + {0xa9ba, 1, 10}, {0xa9bc, 1, 2}, {0xa9be, 2, 10}, {0xa9e5, 0, 2}, {0xaa29, 5, 2}, {0xaa2f, 1, 10}, + {0xaa31, 1, 2}, {0xaa33, 1, 10}, {0xaa35, 1, 2}, {0xaa43, 0, 2}, {0xaa4c, 0, 2}, {0xaa4d, 0, 10}, + {0xaa7c, 0, 2}, {0xaab0, 0, 2}, {0xaab2, 2, 2}, {0xaab7, 1, 2}, {0xaabe, 1, 2}, {0xaac1, 0, 2}, + {0xaaeb, 0, 10}, {0xaaec, 1, 2}, {0xaaee, 1, 10}, {0xaaf5, 0, 10}, {0xaaf6, 0, 2}, {0xabe3, 1, 10}, + {0xabe5, 0, 2}, {0xabe6, 1, 10}, {0xabe8, 0, 2}, {0xabe9, 1, 10}, {0xabec, 0, 10}, {0xabed, 0, 2}, + {0xac00, 0, 6}, {0xac01, 26, 7}, {0xac1c, 0, 6}, {0xac1d, 26, 7}, {0xac38, 0, 6}, {0xac39, 26, 7}, + {0xac54, 0, 6}, {0xac55, 26, 7}, {0xac70, 0, 6}, {0xac71, 26, 7}, {0xac8c, 0, 6}, {0xac8d, 26, 7}, + {0xaca8, 0, 6}, {0xaca9, 26, 7}, {0xacc4, 0, 6}, {0xacc5, 26, 7}, {0xace0, 0, 6}, {0xace1, 26, 7}, + {0xacfc, 0, 6}, {0xacfd, 26, 7}, {0xad18, 0, 6}, {0xad19, 26, 7}, {0xad34, 0, 6}, {0xad35, 26, 7}, + {0xad50, 0, 6}, {0xad51, 26, 7}, {0xad6c, 0, 6}, {0xad6d, 26, 7}, {0xad88, 0, 6}, {0xad89, 26, 7}, + {0xada4, 0, 6}, {0xada5, 26, 7}, {0xadc0, 0, 6}, {0xadc1, 26, 7}, {0xaddc, 0, 6}, {0xaddd, 26, 7}, + {0xadf8, 0, 6}, {0xadf9, 26, 7}, {0xae14, 0, 6}, {0xae15, 26, 7}, {0xae30, 0, 6}, {0xae31, 26, 7}, + {0xae4c, 0, 6}, {0xae4d, 26, 7}, {0xae68, 0, 6}, {0xae69, 26, 7}, {0xae84, 0, 6}, {0xae85, 26, 7}, + {0xaea0, 0, 6}, {0xaea1, 26, 7}, {0xaebc, 0, 6}, {0xaebd, 26, 7}, {0xaed8, 0, 6}, {0xaed9, 26, 7}, + {0xaef4, 0, 6}, {0xaef5, 26, 7}, {0xaf10, 0, 6}, {0xaf11, 26, 7}, {0xaf2c, 0, 6}, {0xaf2d, 26, 7}, + {0xaf48, 0, 6}, {0xaf49, 26, 7}, {0xaf64, 0, 6}, {0xaf65, 26, 7}, {0xaf80, 0, 6}, {0xaf81, 26, 7}, + {0xaf9c, 0, 6}, {0xaf9d, 26, 7}, {0xafb8, 0, 6}, {0xafb9, 26, 7}, {0xafd4, 0, 6}, {0xafd5, 26, 7}, + {0xaff0, 0, 6}, {0xaff1, 26, 7}, {0xb00c, 0, 6}, {0xb00d, 26, 7}, {0xb028, 0, 6}, {0xb029, 26, 7}, + {0xb044, 0, 6}, {0xb045, 26, 7}, {0xb060, 0, 6}, {0xb061, 26, 7}, {0xb07c, 0, 6}, {0xb07d, 26, 7}, + {0xb098, 0, 6}, {0xb099, 26, 7}, {0xb0b4, 0, 6}, {0xb0b5, 26, 7}, {0xb0d0, 0, 6}, {0xb0d1, 26, 7}, + {0xb0ec, 0, 6}, {0xb0ed, 26, 7}, {0xb108, 0, 6}, {0xb109, 26, 7}, {0xb124, 0, 6}, {0xb125, 26, 7}, + {0xb140, 0, 6}, {0xb141, 26, 7}, {0xb15c, 0, 6}, {0xb15d, 26, 7}, {0xb178, 0, 6}, {0xb179, 26, 7}, + {0xb194, 0, 6}, {0xb195, 26, 7}, {0xb1b0, 0, 6}, {0xb1b1, 26, 7}, {0xb1cc, 0, 6}, {0xb1cd, 26, 7}, + {0xb1e8, 0, 6}, {0xb1e9, 26, 7}, {0xb204, 0, 6}, {0xb205, 26, 7}, {0xb220, 0, 6}, {0xb221, 26, 7}, + {0xb23c, 0, 6}, {0xb23d, 26, 7}, {0xb258, 0, 6}, {0xb259, 26, 7}, {0xb274, 0, 6}, {0xb275, 26, 7}, + {0xb290, 0, 6}, {0xb291, 26, 7}, {0xb2ac, 0, 6}, {0xb2ad, 26, 7}, {0xb2c8, 0, 6}, {0xb2c9, 26, 7}, + {0xb2e4, 0, 6}, {0xb2e5, 26, 7}, {0xb300, 0, 6}, {0xb301, 26, 7}, {0xb31c, 0, 6}, {0xb31d, 26, 7}, + {0xb338, 0, 6}, {0xb339, 26, 7}, {0xb354, 0, 6}, {0xb355, 26, 7}, {0xb370, 0, 6}, {0xb371, 26, 7}, + {0xb38c, 0, 6}, {0xb38d, 26, 7}, {0xb3a8, 0, 6}, {0xb3a9, 26, 7}, {0xb3c4, 0, 6}, {0xb3c5, 26, 7}, + {0xb3e0, 0, 6}, {0xb3e1, 26, 7}, {0xb3fc, 0, 6}, {0xb3fd, 26, 7}, {0xb418, 0, 6}, {0xb419, 26, 7}, + {0xb434, 0, 6}, {0xb435, 26, 7}, {0xb450, 0, 6}, {0xb451, 26, 7}, {0xb46c, 0, 6}, {0xb46d, 26, 7}, + {0xb488, 0, 6}, {0xb489, 26, 7}, {0xb4a4, 0, 6}, {0xb4a5, 26, 7}, {0xb4c0, 0, 6}, {0xb4c1, 26, 7}, + {0xb4dc, 0, 6}, {0xb4dd, 26, 7}, {0xb4f8, 0, 6}, {0xb4f9, 26, 7}, {0xb514, 0, 6}, {0xb515, 26, 7}, + {0xb530, 0, 6}, {0xb531, 26, 7}, {0xb54c, 0, 6}, {0xb54d, 26, 7}, {0xb568, 0, 6}, {0xb569, 26, 7}, + {0xb584, 0, 6}, {0xb585, 26, 7}, {0xb5a0, 0, 6}, {0xb5a1, 26, 7}, {0xb5bc, 0, 6}, {0xb5bd, 26, 7}, + {0xb5d8, 0, 6}, {0xb5d9, 26, 7}, {0xb5f4, 0, 6}, {0xb5f5, 26, 7}, {0xb610, 0, 6}, {0xb611, 26, 7}, + {0xb62c, 0, 6}, {0xb62d, 26, 7}, {0xb648, 0, 6}, {0xb649, 26, 7}, {0xb664, 0, 6}, {0xb665, 26, 7}, + {0xb680, 0, 6}, {0xb681, 26, 7}, {0xb69c, 0, 6}, {0xb69d, 26, 7}, {0xb6b8, 0, 6}, {0xb6b9, 26, 7}, + {0xb6d4, 0, 6}, {0xb6d5, 26, 7}, {0xb6f0, 0, 6}, {0xb6f1, 26, 7}, {0xb70c, 0, 6}, {0xb70d, 26, 7}, + {0xb728, 0, 6}, {0xb729, 26, 7}, {0xb744, 0, 6}, {0xb745, 26, 7}, {0xb760, 0, 6}, {0xb761, 26, 7}, + {0xb77c, 0, 6}, {0xb77d, 26, 7}, {0xb798, 0, 6}, {0xb799, 26, 7}, {0xb7b4, 0, 6}, {0xb7b5, 26, 7}, + {0xb7d0, 0, 6}, {0xb7d1, 26, 7}, {0xb7ec, 0, 6}, {0xb7ed, 26, 7}, {0xb808, 0, 6}, {0xb809, 26, 7}, + {0xb824, 0, 6}, {0xb825, 26, 7}, {0xb840, 0, 6}, {0xb841, 26, 7}, {0xb85c, 0, 6}, {0xb85d, 26, 7}, + {0xb878, 0, 6}, {0xb879, 26, 7}, {0xb894, 0, 6}, {0xb895, 26, 7}, {0xb8b0, 0, 6}, {0xb8b1, 26, 7}, + {0xb8cc, 0, 6}, {0xb8cd, 26, 7}, {0xb8e8, 0, 6}, {0xb8e9, 26, 7}, {0xb904, 0, 6}, {0xb905, 26, 7}, + {0xb920, 0, 6}, {0xb921, 26, 7}, {0xb93c, 0, 6}, {0xb93d, 26, 7}, {0xb958, 0, 6}, {0xb959, 26, 7}, + {0xb974, 0, 6}, {0xb975, 26, 7}, {0xb990, 0, 6}, {0xb991, 26, 7}, {0xb9ac, 0, 6}, {0xb9ad, 26, 7}, + {0xb9c8, 0, 6}, {0xb9c9, 26, 7}, {0xb9e4, 0, 6}, {0xb9e5, 26, 7}, {0xba00, 0, 6}, {0xba01, 26, 7}, + {0xba1c, 0, 6}, {0xba1d, 26, 7}, {0xba38, 0, 6}, {0xba39, 26, 7}, {0xba54, 0, 6}, {0xba55, 26, 7}, + {0xba70, 0, 6}, {0xba71, 26, 7}, {0xba8c, 0, 6}, {0xba8d, 26, 7}, {0xbaa8, 0, 6}, {0xbaa9, 26, 7}, + {0xbac4, 0, 6}, {0xbac5, 26, 7}, {0xbae0, 0, 6}, {0xbae1, 26, 7}, {0xbafc, 0, 6}, {0xbafd, 26, 7}, + {0xbb18, 0, 6}, {0xbb19, 26, 7}, {0xbb34, 0, 6}, {0xbb35, 26, 7}, {0xbb50, 0, 6}, {0xbb51, 26, 7}, + {0xbb6c, 0, 6}, {0xbb6d, 26, 7}, {0xbb88, 0, 6}, {0xbb89, 26, 7}, {0xbba4, 0, 6}, {0xbba5, 26, 7}, + {0xbbc0, 0, 6}, {0xbbc1, 26, 7}, {0xbbdc, 0, 6}, {0xbbdd, 26, 7}, {0xbbf8, 0, 6}, {0xbbf9, 26, 7}, + {0xbc14, 0, 6}, {0xbc15, 26, 7}, {0xbc30, 0, 6}, {0xbc31, 26, 7}, {0xbc4c, 0, 6}, {0xbc4d, 26, 7}, + {0xbc68, 0, 6}, {0xbc69, 26, 7}, {0xbc84, 0, 6}, {0xbc85, 26, 7}, {0xbca0, 0, 6}, {0xbca1, 26, 7}, + {0xbcbc, 0, 6}, {0xbcbd, 26, 7}, {0xbcd8, 0, 6}, {0xbcd9, 26, 7}, {0xbcf4, 0, 6}, {0xbcf5, 26, 7}, + {0xbd10, 0, 6}, {0xbd11, 26, 7}, {0xbd2c, 0, 6}, {0xbd2d, 26, 7}, {0xbd48, 0, 6}, {0xbd49, 26, 7}, + {0xbd64, 0, 6}, {0xbd65, 26, 7}, {0xbd80, 0, 6}, {0xbd81, 26, 7}, {0xbd9c, 0, 6}, {0xbd9d, 26, 7}, + {0xbdb8, 0, 6}, {0xbdb9, 26, 7}, {0xbdd4, 0, 6}, {0xbdd5, 26, 7}, {0xbdf0, 0, 6}, {0xbdf1, 26, 7}, + {0xbe0c, 0, 6}, {0xbe0d, 26, 7}, {0xbe28, 0, 6}, {0xbe29, 26, 7}, {0xbe44, 0, 6}, {0xbe45, 26, 7}, + {0xbe60, 0, 6}, {0xbe61, 26, 7}, {0xbe7c, 0, 6}, {0xbe7d, 26, 7}, {0xbe98, 0, 6}, {0xbe99, 26, 7}, + {0xbeb4, 0, 6}, {0xbeb5, 26, 7}, {0xbed0, 0, 6}, {0xbed1, 26, 7}, {0xbeec, 0, 6}, {0xbeed, 26, 7}, + {0xbf08, 0, 6}, {0xbf09, 26, 7}, {0xbf24, 0, 6}, {0xbf25, 26, 7}, {0xbf40, 0, 6}, {0xbf41, 26, 7}, + {0xbf5c, 0, 6}, {0xbf5d, 26, 7}, {0xbf78, 0, 6}, {0xbf79, 26, 7}, {0xbf94, 0, 6}, {0xbf95, 26, 7}, + {0xbfb0, 0, 6}, {0xbfb1, 26, 7}, {0xbfcc, 0, 6}, {0xbfcd, 26, 7}, {0xbfe8, 0, 6}, {0xbfe9, 26, 7}, + {0xc004, 0, 6}, {0xc005, 26, 7}, {0xc020, 0, 6}, {0xc021, 26, 7}, {0xc03c, 0, 6}, {0xc03d, 26, 7}, + {0xc058, 0, 6}, {0xc059, 26, 7}, {0xc074, 0, 6}, {0xc075, 26, 7}, {0xc090, 0, 6}, {0xc091, 26, 7}, + {0xc0ac, 0, 6}, {0xc0ad, 26, 7}, {0xc0c8, 0, 6}, {0xc0c9, 26, 7}, {0xc0e4, 0, 6}, {0xc0e5, 26, 7}, + {0xc100, 0, 6}, {0xc101, 26, 7}, {0xc11c, 0, 6}, {0xc11d, 26, 7}, {0xc138, 0, 6}, {0xc139, 26, 7}, + {0xc154, 0, 6}, {0xc155, 26, 7}, {0xc170, 0, 6}, {0xc171, 26, 7}, {0xc18c, 0, 6}, {0xc18d, 26, 7}, + {0xc1a8, 0, 6}, {0xc1a9, 26, 7}, {0xc1c4, 0, 6}, {0xc1c5, 26, 7}, {0xc1e0, 0, 6}, {0xc1e1, 26, 7}, + {0xc1fc, 0, 6}, {0xc1fd, 26, 7}, {0xc218, 0, 6}, {0xc219, 26, 7}, {0xc234, 0, 6}, {0xc235, 26, 7}, + {0xc250, 0, 6}, {0xc251, 26, 7}, {0xc26c, 0, 6}, {0xc26d, 26, 7}, {0xc288, 0, 6}, {0xc289, 26, 7}, + {0xc2a4, 0, 6}, {0xc2a5, 26, 7}, {0xc2c0, 0, 6}, {0xc2c1, 26, 7}, {0xc2dc, 0, 6}, {0xc2dd, 26, 7}, + {0xc2f8, 0, 6}, {0xc2f9, 26, 7}, {0xc314, 0, 6}, {0xc315, 26, 7}, {0xc330, 0, 6}, {0xc331, 26, 7}, + {0xc34c, 0, 6}, {0xc34d, 26, 7}, {0xc368, 0, 6}, {0xc369, 26, 7}, {0xc384, 0, 6}, {0xc385, 26, 7}, + {0xc3a0, 0, 6}, {0xc3a1, 26, 7}, {0xc3bc, 0, 6}, {0xc3bd, 26, 7}, {0xc3d8, 0, 6}, {0xc3d9, 26, 7}, + {0xc3f4, 0, 6}, {0xc3f5, 26, 7}, {0xc410, 0, 6}, {0xc411, 26, 7}, {0xc42c, 0, 6}, {0xc42d, 26, 7}, + {0xc448, 0, 6}, {0xc449, 26, 7}, {0xc464, 0, 6}, {0xc465, 26, 7}, {0xc480, 0, 6}, {0xc481, 26, 7}, + {0xc49c, 0, 6}, {0xc49d, 26, 7}, {0xc4b8, 0, 6}, {0xc4b9, 26, 7}, {0xc4d4, 0, 6}, {0xc4d5, 26, 7}, + {0xc4f0, 0, 6}, {0xc4f1, 26, 7}, {0xc50c, 0, 6}, {0xc50d, 26, 7}, {0xc528, 0, 6}, {0xc529, 26, 7}, + {0xc544, 0, 6}, {0xc545, 26, 7}, {0xc560, 0, 6}, {0xc561, 26, 7}, {0xc57c, 0, 6}, {0xc57d, 26, 7}, + {0xc598, 0, 6}, {0xc599, 26, 7}, {0xc5b4, 0, 6}, {0xc5b5, 26, 7}, {0xc5d0, 0, 6}, {0xc5d1, 26, 7}, + {0xc5ec, 0, 6}, {0xc5ed, 26, 7}, {0xc608, 0, 6}, {0xc609, 26, 7}, {0xc624, 0, 6}, {0xc625, 26, 7}, + {0xc640, 0, 6}, {0xc641, 26, 7}, {0xc65c, 0, 6}, {0xc65d, 26, 7}, {0xc678, 0, 6}, {0xc679, 26, 7}, + {0xc694, 0, 6}, {0xc695, 26, 7}, {0xc6b0, 0, 6}, {0xc6b1, 26, 7}, {0xc6cc, 0, 6}, {0xc6cd, 26, 7}, + {0xc6e8, 0, 6}, {0xc6e9, 26, 7}, {0xc704, 0, 6}, {0xc705, 26, 7}, {0xc720, 0, 6}, {0xc721, 26, 7}, + {0xc73c, 0, 6}, {0xc73d, 26, 7}, {0xc758, 0, 6}, {0xc759, 26, 7}, {0xc774, 0, 6}, {0xc775, 26, 7}, + {0xc790, 0, 6}, {0xc791, 26, 7}, {0xc7ac, 0, 6}, {0xc7ad, 26, 7}, {0xc7c8, 0, 6}, {0xc7c9, 26, 7}, + {0xc7e4, 0, 6}, {0xc7e5, 26, 7}, {0xc800, 0, 6}, {0xc801, 26, 7}, {0xc81c, 0, 6}, {0xc81d, 26, 7}, + {0xc838, 0, 6}, {0xc839, 26, 7}, {0xc854, 0, 6}, {0xc855, 26, 7}, {0xc870, 0, 6}, {0xc871, 26, 7}, + {0xc88c, 0, 6}, {0xc88d, 26, 7}, {0xc8a8, 0, 6}, {0xc8a9, 26, 7}, {0xc8c4, 0, 6}, {0xc8c5, 26, 7}, + {0xc8e0, 0, 6}, {0xc8e1, 26, 7}, {0xc8fc, 0, 6}, {0xc8fd, 26, 7}, {0xc918, 0, 6}, {0xc919, 26, 7}, + {0xc934, 0, 6}, {0xc935, 26, 7}, {0xc950, 0, 6}, {0xc951, 26, 7}, {0xc96c, 0, 6}, {0xc96d, 26, 7}, + {0xc988, 0, 6}, {0xc989, 26, 7}, {0xc9a4, 0, 6}, {0xc9a5, 26, 7}, {0xc9c0, 0, 6}, {0xc9c1, 26, 7}, + {0xc9dc, 0, 6}, {0xc9dd, 26, 7}, {0xc9f8, 0, 6}, {0xc9f9, 26, 7}, {0xca14, 0, 6}, {0xca15, 26, 7}, + {0xca30, 0, 6}, {0xca31, 26, 7}, {0xca4c, 0, 6}, {0xca4d, 26, 7}, {0xca68, 0, 6}, {0xca69, 26, 7}, + {0xca84, 0, 6}, {0xca85, 26, 7}, {0xcaa0, 0, 6}, {0xcaa1, 26, 7}, {0xcabc, 0, 6}, {0xcabd, 26, 7}, + {0xcad8, 0, 6}, {0xcad9, 26, 7}, {0xcaf4, 0, 6}, {0xcaf5, 26, 7}, {0xcb10, 0, 6}, {0xcb11, 26, 7}, + {0xcb2c, 0, 6}, {0xcb2d, 26, 7}, {0xcb48, 0, 6}, {0xcb49, 26, 7}, {0xcb64, 0, 6}, {0xcb65, 26, 7}, + {0xcb80, 0, 6}, {0xcb81, 26, 7}, {0xcb9c, 0, 6}, {0xcb9d, 26, 7}, {0xcbb8, 0, 6}, {0xcbb9, 26, 7}, + {0xcbd4, 0, 6}, {0xcbd5, 26, 7}, {0xcbf0, 0, 6}, {0xcbf1, 26, 7}, {0xcc0c, 0, 6}, {0xcc0d, 26, 7}, + {0xcc28, 0, 6}, {0xcc29, 26, 7}, {0xcc44, 0, 6}, {0xcc45, 26, 7}, {0xcc60, 0, 6}, {0xcc61, 26, 7}, + {0xcc7c, 0, 6}, {0xcc7d, 26, 7}, {0xcc98, 0, 6}, {0xcc99, 26, 7}, {0xccb4, 0, 6}, {0xccb5, 26, 7}, + {0xccd0, 0, 6}, {0xccd1, 26, 7}, {0xccec, 0, 6}, {0xcced, 26, 7}, {0xcd08, 0, 6}, {0xcd09, 26, 7}, + {0xcd24, 0, 6}, {0xcd25, 26, 7}, {0xcd40, 0, 6}, {0xcd41, 26, 7}, {0xcd5c, 0, 6}, {0xcd5d, 26, 7}, + {0xcd78, 0, 6}, {0xcd79, 26, 7}, {0xcd94, 0, 6}, {0xcd95, 26, 7}, {0xcdb0, 0, 6}, {0xcdb1, 26, 7}, + {0xcdcc, 0, 6}, {0xcdcd, 26, 7}, {0xcde8, 0, 6}, {0xcde9, 26, 7}, {0xce04, 0, 6}, {0xce05, 26, 7}, + {0xce20, 0, 6}, {0xce21, 26, 7}, {0xce3c, 0, 6}, {0xce3d, 26, 7}, {0xce58, 0, 6}, {0xce59, 26, 7}, + {0xce74, 0, 6}, {0xce75, 26, 7}, {0xce90, 0, 6}, {0xce91, 26, 7}, {0xceac, 0, 6}, {0xcead, 26, 7}, + {0xcec8, 0, 6}, {0xcec9, 26, 7}, {0xcee4, 0, 6}, {0xcee5, 26, 7}, {0xcf00, 0, 6}, {0xcf01, 26, 7}, + {0xcf1c, 0, 6}, {0xcf1d, 26, 7}, {0xcf38, 0, 6}, {0xcf39, 26, 7}, {0xcf54, 0, 6}, {0xcf55, 26, 7}, + {0xcf70, 0, 6}, {0xcf71, 26, 7}, {0xcf8c, 0, 6}, {0xcf8d, 26, 7}, {0xcfa8, 0, 6}, {0xcfa9, 26, 7}, + {0xcfc4, 0, 6}, {0xcfc5, 26, 7}, {0xcfe0, 0, 6}, {0xcfe1, 26, 7}, {0xcffc, 0, 6}, {0xcffd, 26, 7}, + {0xd018, 0, 6}, {0xd019, 26, 7}, {0xd034, 0, 6}, {0xd035, 26, 7}, {0xd050, 0, 6}, {0xd051, 26, 7}, + {0xd06c, 0, 6}, {0xd06d, 26, 7}, {0xd088, 0, 6}, {0xd089, 26, 7}, {0xd0a4, 0, 6}, {0xd0a5, 26, 7}, + {0xd0c0, 0, 6}, {0xd0c1, 26, 7}, {0xd0dc, 0, 6}, {0xd0dd, 26, 7}, {0xd0f8, 0, 6}, {0xd0f9, 26, 7}, + {0xd114, 0, 6}, {0xd115, 26, 7}, {0xd130, 0, 6}, {0xd131, 26, 7}, {0xd14c, 0, 6}, {0xd14d, 26, 7}, + {0xd168, 0, 6}, {0xd169, 26, 7}, {0xd184, 0, 6}, {0xd185, 26, 7}, {0xd1a0, 0, 6}, {0xd1a1, 26, 7}, + {0xd1bc, 0, 6}, {0xd1bd, 26, 7}, {0xd1d8, 0, 6}, {0xd1d9, 26, 7}, {0xd1f4, 0, 6}, {0xd1f5, 26, 7}, + {0xd210, 0, 6}, {0xd211, 26, 7}, {0xd22c, 0, 6}, {0xd22d, 26, 7}, {0xd248, 0, 6}, {0xd249, 26, 7}, + {0xd264, 0, 6}, {0xd265, 26, 7}, {0xd280, 0, 6}, {0xd281, 26, 7}, {0xd29c, 0, 6}, {0xd29d, 26, 7}, + {0xd2b8, 0, 6}, {0xd2b9, 26, 7}, {0xd2d4, 0, 6}, {0xd2d5, 26, 7}, {0xd2f0, 0, 6}, {0xd2f1, 26, 7}, + {0xd30c, 0, 6}, {0xd30d, 26, 7}, {0xd328, 0, 6}, {0xd329, 26, 7}, {0xd344, 0, 6}, {0xd345, 26, 7}, + {0xd360, 0, 6}, {0xd361, 26, 7}, {0xd37c, 0, 6}, {0xd37d, 26, 7}, {0xd398, 0, 6}, {0xd399, 26, 7}, + {0xd3b4, 0, 6}, {0xd3b5, 26, 7}, {0xd3d0, 0, 6}, {0xd3d1, 26, 7}, {0xd3ec, 0, 6}, {0xd3ed, 26, 7}, + {0xd408, 0, 6}, {0xd409, 26, 7}, {0xd424, 0, 6}, {0xd425, 26, 7}, {0xd440, 0, 6}, {0xd441, 26, 7}, + {0xd45c, 0, 6}, {0xd45d, 26, 7}, {0xd478, 0, 6}, {0xd479, 26, 7}, {0xd494, 0, 6}, {0xd495, 26, 7}, + {0xd4b0, 0, 6}, {0xd4b1, 26, 7}, {0xd4cc, 0, 6}, {0xd4cd, 26, 7}, {0xd4e8, 0, 6}, {0xd4e9, 26, 7}, + {0xd504, 0, 6}, {0xd505, 26, 7}, {0xd520, 0, 6}, {0xd521, 26, 7}, {0xd53c, 0, 6}, {0xd53d, 26, 7}, + {0xd558, 0, 6}, {0xd559, 26, 7}, {0xd574, 0, 6}, {0xd575, 26, 7}, {0xd590, 0, 6}, {0xd591, 26, 7}, + {0xd5ac, 0, 6}, {0xd5ad, 26, 7}, {0xd5c8, 0, 6}, {0xd5c9, 26, 7}, {0xd5e4, 0, 6}, {0xd5e5, 26, 7}, + {0xd600, 0, 6}, {0xd601, 26, 7}, {0xd61c, 0, 6}, {0xd61d, 26, 7}, {0xd638, 0, 6}, {0xd639, 26, 7}, + {0xd654, 0, 6}, {0xd655, 26, 7}, {0xd670, 0, 6}, {0xd671, 26, 7}, {0xd68c, 0, 6}, {0xd68d, 26, 7}, + {0xd6a8, 0, 6}, {0xd6a9, 26, 7}, {0xd6c4, 0, 6}, {0xd6c5, 26, 7}, {0xd6e0, 0, 6}, {0xd6e1, 26, 7}, + {0xd6fc, 0, 6}, {0xd6fd, 26, 7}, {0xd718, 0, 6}, {0xd719, 26, 7}, {0xd734, 0, 6}, {0xd735, 26, 7}, + {0xd750, 0, 6}, {0xd751, 26, 7}, {0xd76c, 0, 6}, {0xd76d, 26, 7}, {0xd788, 0, 6}, {0xd789, 26, 7}, + {0xd7b0, 22, 12}, {0xd7cb, 48, 11}, {0xfb1e, 0, 2}, {0xfe00, 15, 2}, {0xfe20, 15, 2}, {0xfeff, 0, 1}, + {0xff9e, 1, 2}, {0xfff0, 11, 1}, {0x101fd, 0, 2}, {0x102e0, 0, 2}, {0x10376, 4, 2}, {0x10a01, 2, 2}, + {0x10a05, 1, 2}, {0x10a0c, 3, 2}, {0x10a38, 2, 2}, {0x10a3f, 0, 2}, {0x10ae5, 1, 2}, {0x10d24, 3, 2}, + {0x10f46, 10, 2}, {0x11000, 0, 10}, {0x11001, 0, 2}, {0x11002, 0, 10}, {0x11038, 14, 2}, {0x1107f, 2, 2}, + {0x11082, 0, 10}, {0x110b0, 2, 10}, {0x110b3, 3, 2}, {0x110b7, 1, 10}, {0x110b9, 1, 2}, {0x110bd, 0, 8}, + {0x110cd, 0, 8}, {0x11100, 2, 2}, {0x11127, 4, 2}, {0x1112c, 0, 10}, {0x1112d, 7, 2}, {0x11145, 1, 10}, + {0x11173, 0, 2}, {0x11180, 1, 2}, {0x11182, 0, 10}, {0x111b3, 2, 10}, {0x111b6, 8, 2}, {0x111bf, 1, 10}, + {0x111c2, 1, 8}, {0x111c9, 3, 2}, {0x1122c, 2, 10}, {0x1122f, 2, 2}, {0x11232, 1, 10}, {0x11234, 0, 2}, + {0x11235, 0, 10}, {0x11236, 1, 2}, {0x1123e, 0, 2}, {0x112df, 0, 2}, {0x112e0, 2, 10}, {0x112e3, 7, 2}, + {0x11300, 1, 2}, {0x11302, 1, 10}, {0x1133b, 1, 2}, {0x1133e, 0, 2}, {0x1133f, 0, 10}, {0x11340, 0, 2}, + {0x11341, 3, 10}, {0x11347, 1, 10}, {0x1134b, 2, 10}, {0x11357, 0, 2}, {0x11362, 1, 10}, {0x11366, 6, 2}, + {0x11370, 4, 2}, {0x11435, 2, 10}, {0x11438, 7, 2}, {0x11440, 1, 10}, {0x11442, 2, 2}, {0x11445, 0, 10}, + {0x11446, 0, 2}, {0x1145e, 0, 2}, {0x114b0, 0, 2}, {0x114b1, 1, 10}, {0x114b3, 5, 2}, {0x114b9, 0, 10}, + {0x114ba, 0, 2}, {0x114bb, 1, 10}, {0x114bd, 0, 2}, {0x114be, 0, 10}, {0x114bf, 1, 2}, {0x114c1, 0, 10}, + {0x114c2, 1, 2}, {0x115af, 0, 2}, {0x115b0, 1, 10}, {0x115b2, 3, 2}, {0x115b8, 3, 10}, {0x115bc, 1, 2}, + {0x115be, 0, 10}, {0x115bf, 1, 2}, {0x115dc, 1, 2}, {0x11630, 2, 10}, {0x11633, 7, 2}, {0x1163b, 1, 10}, + {0x1163d, 0, 2}, {0x1163e, 0, 10}, {0x1163f, 1, 2}, {0x116ab, 0, 2}, {0x116ac, 0, 10}, {0x116ad, 0, 2}, + {0x116ae, 1, 10}, {0x116b0, 5, 2}, {0x116b6, 0, 10}, {0x116b7, 0, 2}, {0x1171d, 2, 2}, {0x11720, 1, 10}, + {0x11722, 3, 2}, {0x11726, 0, 10}, {0x11727, 4, 2}, {0x1182c, 2, 10}, {0x1182f, 8, 2}, {0x11838, 0, 10}, + {0x11839, 1, 2}, {0x119d1, 2, 10}, {0x119d4, 3, 2}, {0x119da, 1, 2}, {0x119dc, 3, 10}, {0x119e0, 0, 2}, + {0x119e4, 0, 10}, {0x11a01, 9, 2}, {0x11a33, 5, 2}, {0x11a39, 0, 10}, {0x11a3a, 0, 8}, {0x11a3b, 3, 2}, + {0x11a47, 0, 2}, {0x11a51, 5, 2}, {0x11a57, 1, 10}, {0x11a59, 2, 2}, {0x11a84, 5, 8}, {0x11a8a, 12, 2}, + {0x11a97, 0, 10}, {0x11a98, 1, 2}, {0x11c2f, 0, 10}, {0x11c30, 6, 2}, {0x11c38, 5, 2}, {0x11c3e, 0, 10}, + {0x11c3f, 0, 2}, {0x11c92, 21, 2}, {0x11ca9, 0, 10}, {0x11caa, 6, 2}, {0x11cb1, 0, 10}, {0x11cb2, 1, 2}, + {0x11cb4, 0, 10}, {0x11cb5, 1, 2}, {0x11d31, 5, 2}, {0x11d3a, 0, 2}, {0x11d3c, 1, 2}, {0x11d3f, 6, 2}, + {0x11d46, 0, 8}, {0x11d47, 0, 2}, {0x11d8a, 4, 10}, {0x11d90, 1, 2}, {0x11d93, 1, 10}, {0x11d95, 0, 2}, + {0x11d96, 0, 10}, {0x11d97, 0, 2}, {0x11ef3, 1, 2}, {0x11ef5, 1, 10}, {0x13430, 8, 1}, {0x16af0, 4, 2}, + {0x16b30, 6, 2}, {0x16f4f, 0, 2}, {0x16f51, 54, 10}, {0x16f8f, 3, 2}, {0x1bc9d, 1, 2}, {0x1bca0, 3, 1}, + {0x1d165, 0, 2}, {0x1d166, 0, 10}, {0x1d167, 2, 2}, {0x1d16d, 0, 10}, {0x1d16e, 4, 2}, {0x1d173, 7, 1}, + {0x1d17b, 7, 2}, {0x1d185, 6, 2}, {0x1d1aa, 3, 2}, {0x1d242, 2, 2}, {0x1da00, 54, 2}, {0x1da3b, 49, 2}, + {0x1da75, 0, 2}, {0x1da84, 0, 2}, {0x1da9b, 4, 2}, {0x1daa1, 14, 2}, {0x1e000, 6, 2}, {0x1e008, 16, 2}, + {0x1e01b, 6, 2}, {0x1e023, 1, 2}, {0x1e026, 4, 2}, {0x1e130, 6, 2}, {0x1e2ec, 3, 2}, {0x1e8d0, 6, 2}, + {0x1e944, 6, 2}, {0x1f000, 127, 3}, {0x1f080, 127, 3}, {0x1f10d, 2, 3}, {0x1f12f, 0, 3}, {0x1f16c, 5, 3}, + {0x1f17e, 1, 3}, {0x1f18e, 0, 3}, {0x1f191, 9, 3}, {0x1f1ad, 56, 3}, {0x1f1e6, 25, 9}, {0x1f201, 14, 3}, + {0x1f21a, 0, 3}, {0x1f22f, 0, 3}, {0x1f232, 8, 3}, {0x1f23c, 3, 3}, {0x1f249, 127, 3}, {0x1f2c9, 127, 3}, + {0x1f349, 127, 3}, {0x1f3c9, 49, 3}, {0x1f3fb, 4, 2}, {0x1f400, 127, 3}, {0x1f480, 127, 3}, {0x1f500, 61, 3}, + {0x1f546, 127, 3}, {0x1f5c6, 127, 3}, {0x1f646, 9, 3}, {0x1f680, 127, 3}, {0x1f774, 11, 3}, {0x1f7d5, 42, 3}, + {0x1f80c, 3, 3}, {0x1f848, 7, 3}, {0x1f85a, 5, 3}, {0x1f888, 7, 3}, {0x1f8ae, 81, 3}, {0x1f90c, 46, 3}, + {0x1f93c, 9, 3}, {0x1f947, 127, 3}, {0x1f9c7, 127, 3}, {0x1fa47, 127, 3}, {0x1fac7, 127, 3}, {0x1fb47, 127, 3}, + {0x1fbc7, 127, 3}, {0x1fc47, 127, 3}, {0x1fcc7, 127, 3}, {0x1fd47, 127, 3}, {0x1fdc7, 127, 3}, {0x1fe47, 127, 3}, + {0x1fec7, 127, 3}, {0x1ff47, 127, 3}, {0x1ffc7, 54, 3}, {0xe0000, 31, 1}, {0xe0020, 95, 2}, {0xe0080, 127, 1}, + {0xe0100, 127, 2}, {0xe0180, 111, 2}, {0xe01f0, 127, 1}, {0xe0270, 127, 1}, {0xe02f0, 127, 1}, {0xe0370, 127, 1}, + {0xe03f0, 127, 1}, {0xe0470, 127, 1}, {0xe04f0, 127, 1}, {0xe0570, 127, 1}, {0xe05f0, 127, 1}, {0xe0670, 127, 1}, + {0xe06f0, 127, 1}, {0xe0770, 127, 1}, {0xe07f0, 127, 1}, {0xe0870, 127, 1}, {0xe08f0, 127, 1}, {0xe0970, 127, 1}, + {0xe09f0, 127, 1}, {0xe0a70, 127, 1}, {0xe0af0, 127, 1}, {0xe0b70, 127, 1}, {0xe0bf0, 127, 1}, {0xe0c70, 127, 1}, + {0xe0cf0, 127, 1}, {0xe0d70, 127, 1}, {0xe0df0, 127, 1}, {0xe0e70, 127, 1}, {0xe0ef0, 127, 1}, {0xe0f70, 127, 1}, + {0xe0ff0, 15, 1}}; + +/// Returns the extended grapheme cluster bondary property of a code point. +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __property __get_property(const char32_t __code_point) noexcept { + // TODO FMT use ranges + ptrdiff_t __i = std::upper_bound(__entries, std::end(__entries), __code_point, + [](char32_t __lhs, __entry __rhs) { return __lhs < __rhs.__lower_bound; }) - + __entries; + if (__i == 0) + return __property::__none; + + --__i; + uint32_t __upper_bound = __entries[__i].__lower_bound + __entries[__i].__offset; + if (__code_point <= __upper_bound) + return static_cast<__property>(__entries[__i].__property); + + return __property::__none; +} + +} // namespace __extended_grapheme_custer_property_boundary + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_EXTENDED_GRAPHEME_CLUSTER_TABLE_H diff --git a/libcxx/include/__format/parser_std_format_spec.h b/libcxx/include/__format/parser_std_format_spec.h --- a/libcxx/include/__format/parser_std_format_spec.h +++ b/libcxx/include/__format/parser_std_format_spec.h @@ -17,6 +17,7 @@ #include <__format/format_arg.h> #include <__format/format_error.h> #include <__format/format_string.h> +#include <__format/unicode.h> #include <__variant/monostate.h> #include #include @@ -1014,15 +1015,15 @@ /** Helper concept for an UTF-8 character type. */ template -concept __utf8_character = same_as<_CharT, char> || same_as<_CharT, char8_t>; +concept __utf8_character = same_as<_CharT, char>; /** Helper concept for an UTF-16 character type. */ template -concept __utf16_character = (same_as<_CharT, wchar_t> && sizeof(wchar_t) == 2) || same_as<_CharT, char16_t>; +concept __utf16_character = (same_as<_CharT, wchar_t> && sizeof(wchar_t) == 2); /** Helper concept for an UTF-32 character type. */ template -concept __utf32_character = (same_as<_CharT, wchar_t> && sizeof(wchar_t) == 4) || same_as<_CharT, char32_t>; +concept __utf32_character = (same_as<_CharT, wchar_t> && sizeof(wchar_t) == 4); /** Helper concept for an UTF-16 or UTF-32 character type. */ template @@ -1089,25 +1090,10 @@ /** * Estimate the column width for the UTF-8 sequence using the fast algorithm. */ -template <__utf8_character _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* -__estimate_column_width_fast(const _CharT* __first, - const _CharT* __last) noexcept { - return _VSTD::find_if(__first, __last, - [](unsigned char __c) { return __c & 0x80; }); -} - -/** - * @overload - * - * The implementation for UTF-16/32. - */ -template <__utf16_or_32_character _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* -__estimate_column_width_fast(const _CharT* __first, - const _CharT* __last) noexcept { - return _VSTD::find_if(__first, __last, - [](uint32_t __c) { return __c >= 0x1100; }); +template +_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* __estimate_column_width_fast(const _CharT* __first, + const _CharT* __last) noexcept { + return _VSTD::find_if(__first, __last, [](char32_t __c) { return __c >= 0x80; }); } template @@ -1151,134 +1137,28 @@ * @param __maximum The maximum number of output columns. The returned number * of estimated output columns will not exceed this value. */ -template <__utf8_character _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> -__estimate_column_width(const _CharT* __first, const _CharT* __last, - size_t __maximum) noexcept { - size_t __result = 0; - - while (__first != __last) { - // Based on the number of leading 1 bits the number of code units in the - // code point can be determined. See - // https://en.wikipedia.org/wiki/UTF-8#Encoding - switch (_VSTD::countl_one(static_cast(*__first))) { - case 0: // 1-code unit encoding: all 1 column - ++__result; - ++__first; - break; - - case 2: // 2-code unit encoding: all 1 column - // Malformed Unicode. - if (__last - __first < 2) [[unlikely]] - return __estimate_column_width_malformed(__first, __last, __maximum, - __result); - __first += 2; - ++__result; - break; - - case 3: // 3-code unit encoding: either 1 or 2 columns - // Malformed Unicode. - if (__last - __first < 3) [[unlikely]] - return __estimate_column_width_malformed(__first, __last, __maximum, - __result); - { - uint32_t __c = static_cast(*__first++) & 0x0f; - __c <<= 6; - __c |= static_cast(*__first++) & 0x3f; - __c <<= 6; - __c |= static_cast(*__first++) & 0x3f; - __result += __column_width_3(__c); - if (__result > __maximum) - return {__result - 2, __first - 3}; - } - break; - case 4: // 4-code unit encoding: either 1 or 2 columns - // Malformed Unicode. - if (__last - __first < 4) [[unlikely]] - return __estimate_column_width_malformed(__first, __last, __maximum, - __result); - { - uint32_t __c = static_cast(*__first++) & 0x07; - __c <<= 6; - __c |= static_cast(*__first++) & 0x3f; - __c <<= 6; - __c |= static_cast(*__first++) & 0x3f; - __c <<= 6; - __c |= static_cast(*__first++) & 0x3f; - __result += __column_width_4(__c); - if (__result > __maximum) - return {__result - 2, __first - 4}; - } - break; - default: - // Malformed Unicode. - return __estimate_column_width_malformed(__first, __last, __maximum, - __result); - } - - if (__result >= __maximum) - return {__result, __first}; - } - return {__result, __first}; -} - -template <__utf16_character _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> -__estimate_column_width(const _CharT* __first, const _CharT* __last, - size_t __maximum) noexcept { - size_t __result = 0; - - while (__first != __last) { - uint32_t __c = *__first; - // Is the code unit part of a surrogate pair? See - // https://en.wikipedia.org/wiki/UTF-16#U+D800_to_U+DFFF - if (__c >= 0xd800 && __c <= 0xDfff) { - // Malformed Unicode. - if (__last - __first < 2) [[unlikely]] - return {__result + 1, __first + 1}; - - __c -= 0xd800; - __c <<= 10; - __c += (*(__first + 1) - 0xdc00); - __c += 0x10000; - - __result += __column_width_4(__c); - if (__result > __maximum) - return {__result - 2, __first}; - __first += 2; - } else { - __result += __column_width_3(__c); - if (__result > __maximum) - return {__result - 2, __first}; - ++__first; - } - - if (__result >= __maximum) - return {__result, __first}; - } - - return {__result, __first}; -} - -template <__utf32_character _CharT> +template _LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> -__estimate_column_width(const _CharT* __first, const _CharT* __last, - size_t __maximum) noexcept { - size_t __result = 0; - - while (__first != __last) { - uint32_t __c = *__first; - __result += __column_width(__c); - - if (__result > __maximum) - return {__result - 2, __first}; - - ++__first; - if (__result >= __maximum) - return {__result, __first}; +__estimate_column_width(const _CharT* __first, const _CharT* __last, size_t __maximum) noexcept { + __unicode::__extended_grapheme_cluster_view<_CharT> __view{__first, __last}; + + __column_width_result<_CharT> __result{0, __first}; + while (__result.__ptr != __last && __result.__width != __maximum) { + typename __unicode::__extended_grapheme_cluster_view<_CharT>::__cluster __cluster = __view.__consume(); + int __width = __column_width(__cluster.__code_point_); + + // When the next entry would exceed the maximum width the previous width + // might be returned. For example when a width of 100 is requested the + // returned with might be 99, since the next code point has an estimated + // column width of 2. + if (__result.__width + __width > __maximum) + return __result; + + __result.__width += __width; + __result.__ptr = __cluster.__last_; } - return {__result, __first}; + return __result; } } // namespace __detail @@ -1314,6 +1194,13 @@ const _CharT* __pos = __detail::__estimate_column_width_fast(__first, __limit); + // There's a subtile issue; when __pos is non-ASCII the last code unit may be + // part of an extended graheme cluster. For example an ASCII letter and a + // COMBINING ACUTE ACCENT. In that case adjust the returned result and + // reevaluate the last code unit in a Unicode context. + if (__pos != __first && __pos != __last && static_cast(*__pos) >= 0x80) + --__pos; + if (__pos == __limit) return {__limit, __size, __size < __width}; diff --git a/libcxx/include/__format/unicode.h b/libcxx/include/__format/unicode.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__format/unicode.h @@ -0,0 +1,316 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_UNICODE_H +#define _LIBCPP___FORMAT_UNICODE_H + +#include <__assert> +#include <__config> +#include <__format/extended_grapheme_cluster_table.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +# ifndef _LIBCPP_HAS_NO_UNICODE + +/// Implements the grapheme cluster boundary rules +/// +/// These rules are used to implement format's width estimation as stated in +/// [format.string.std]/11 +/// +/// The Standard refers to UAX \#29 for Unicode 12.0.0 +/// https://www.unicode.org/reports/tr29/tr29-35.html#Grapheme_Cluster_Boundary_Rules +/// +/// The data tables used are +/// http://www.unicode.org/Public/12.0.0/ucd/auxiliary/GraphemeBreakProperty.txt +/// http://www.unicode.org/Public/emoji/12.0/emoji-data.txt +/// http://www.unicode.org/Public/12.0.0/ucd/auxiliary/GraphemeBreakTest.txt (for testing only) + +namespace __unicode { + +inline constexpr char32_t __replacement_character = U'\ufffd'; + +/// Helper class to extract a code unit from a Unicode character range. +/// +/// The stored range is a view. There are multiple specialization for different +/// character types. +template +class __code_point_view; + +/// UTF-8 specialization. +template <> +class __code_point_view { +public: + _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(const char* __first, const char* __last) + : __first_(__first), __last_(__last) {} + + _LIBCPP_HIDE_FROM_ABI constexpr const char* __position() const noexcept { return __first_; } + + _LIBCPP_HIDE_FROM_ABI constexpr char32_t __consume() noexcept { + _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); + + // Based on the number of leading 1 bits the number of code units in the + // code point can be determined. See + // https://en.wikipedia.org/wiki/UTF-8#Encoding + switch (_VSTD::countl_one(static_cast(*__first_))) { + case 0: + return *__first_++; + + case 2: + if (__last_ - __first_ < 2) [[unlikely]] { + __first_ = __last_; + return __replacement_character; + } else { + char32_t __value = static_cast(*__first_++) & 0x1f; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; + return __value; + } + + case 3: + if (__last_ - __first_ < 3) [[unlikely]] { + __first_ = __last_; + __first_ = __last_; + return __replacement_character; + } else { + char32_t __value = static_cast(*__first_++) & 0x0f; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; + return __value; + } + + case 4: + if (__last_ - __first_ < 4) [[unlikely]] { + __first_ = __last_; + return __replacement_character; + } else { + char32_t __value = static_cast(*__first_++) & 0x07; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; + __value <<= 6; + __value |= static_cast(*__first_++) & 0x3f; + return __value; + } + } + // An invalid number of leading ones can be garbage or a code unit in the + // middle of a code point. By consuming one code unit the parser may get + // "in sync" after a few code units. + ++__first_; + return __replacement_character; + } + +private: + const char* __first_; + const char* __last_; +}; + +/// This specialization depends on the size of wchar_t +/// - 2 UTF-16 (for example Windows and AIX) +/// - 4 UTF-32 (for example Linux) +template <> +class __code_point_view { +public: + _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(const wchar_t* __first, const wchar_t* __last) + : __first_(__first), __last_(__last) {} + + _LIBCPP_HIDE_FROM_ABI constexpr const wchar_t* __position() const noexcept { return __first_; } + + _LIBCPP_HIDE_FROM_ABI constexpr char32_t __consume() noexcept { + _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); + + if constexpr (sizeof(wchar_t) == 2) { + char32_t __result = *__first_++; + // Is the code unit part of a surrogate pair? See + // https://en.wikipedia.org/wiki/UTF-16#U+D800_to_U+DFFF + if (__result >= 0xd800 && __result <= 0xDfff) { + // Malformed Unicode. + if (__first_ == __last_) [[unlikely]] + return __replacement_character; + + __result -= 0xd800; + __result <<= 10; + __result += *__first_++ - 0xdc00; + __result += 0x10000; + } + return __result; + + } else if constexpr (sizeof(wchar_t) == 4) + return *__first_++; + + // unreachable + } + +private: + const wchar_t* __first_; + const wchar_t* __last_; +}; + +_LIBCPP_HIDE_FROM_ABI +constexpr bool __at_extended_grapheme_cluster_break( + bool& __RI_break_allowed, bool __has_extened_pictographic, + __extended_grapheme_custer_property_boundary::__property __prev, + __extended_grapheme_custer_property_boundary::__property __next_prop_) { // XXX next + using __extended_grapheme_custer_property_boundary::__property; + + __has_extened_pictographic |= __prev == __property::__Extended_Pictographic; + + // https://www.unicode.org/reports/tr29/tr29-39.html#Grapheme_Cluster_Boundary_Rules + + // *** Break at the start and end of text, unless the text is empty. *** + + _LIBCPP_ASSERT(__prev != __property::__sot, "should be handled in the constructor"); // GB1 + + if (__next_prop_ == __property::__eot) // GB2 + return true; + + // *** Do not break between a CR and LF. Otherwise, break before and after controls. *** + + if (__prev == __property::__CR && __next_prop_ == __property::__LF) // GB3 + return false; + + if (__prev == __property::__Control || __prev == __property::__CR || __prev == __property::__LF) // GB4 + return true; + + if (__next_prop_ == __property::__Control || __next_prop_ == __property::__CR || + __next_prop_ == __property::__LF) // GB5 + return true; + + // *** Do not break Hangul syllable sequences. *** + if (__prev == __property::__L && (__next_prop_ == __property::__L || __next_prop_ == __property::__V || + __next_prop_ == __property::__LV || __next_prop_ == __property::__LVT)) // GB6 + return false; + + if ((__prev == __property::__LV || __prev == __property::__V) && + (__next_prop_ == __property::__V || __next_prop_ == __property::__T)) // GB7 + return false; + + if ((__prev == __property::__LVT || __prev == __property::__T) && __next_prop_ == __property::__T) // GB8 + return false; + + // *** Do not break before extending characters or ZWJ. *** + if (__next_prop_ == __property::__Extend || __next_prop_ == __property::__ZWJ) + return false; // GB9 + + // *** Do not break before SpacingMarks, or after Prepend characters. *** + if (__next_prop_ == __property::__SpacingMark) // GB9a + return false; + + if (__prev == __property::__Prepend) // GB9b + return false; + + // *** Do not break within emoji modifier sequences or emoji zwj sequences. *** + + // GB11 \p{Extended_Pictographic} Extend* ZWJ x \p{Extended_Pictographic} + // + // Note that several parts of this rule are matched by GB9: Any x (Extend | ZWJ) + // - \p{Extended_Pictographic} x Extend + // - Extend x Extend + // - \p{Extended_Pictographic} x ZWJ + // - Extend x ZWJ + // + // So the only case left to test is + // - \p{Extended_Pictographic}' x ZWJ x \p{Extended_Pictographic} + // where \p{Extended_Pictographic}' is stored in __has_extened_pictographic + // + // TODO FMT add test for ZWJ \p{Extended_Pictographic} + if (__has_extened_pictographic && __prev == __property::__ZWJ && __next_prop_ == __property::__Extended_Pictographic) + return false; + + // *** Do not break within emoji flag sequences *** + + // That is, do not break between regional indicator (RI) symbols if there + // is an odd number of RI characters before the break point. + + if (__prev == __property::__Regional_Indicator && __next_prop_ == __property::__Regional_Indicator) { // GB12 + GB13 + __RI_break_allowed = !__RI_break_allowed; + if (__RI_break_allowed) + return true; + + return false; + } + + // *** Otherwise, break everywhere. *** + return true; // GB999 +} + +/// Helper class to extract an extended grapheme cluster from a Unicode character range. +/// +/// This function is used to determine the column width of an extended grapheme +/// cluster. In order to do that only the first code point is evaluated. +/// Therefore only this code point is extracted. +template +class __extended_grapheme_cluster_view { +public: + _LIBCPP_HIDE_FROM_ABI constexpr explicit __extended_grapheme_cluster_view(const _CharT* __first, const _CharT* __last) + : __code_point_view_(__first, __last), __next_code_point_(__code_point_view_.__consume()), + __next_prop_(__extended_grapheme_custer_property_boundary::__get_property(__next_code_point_)) {} + + struct __cluster { + /// The first code point of the extended grapheme cluster. + /// + /// The first code point is used to estimate the width of the extended + /// grapheme cluster. + char32_t __code_point_; + + /// Points one beyond the last code unit in the extended grapheme cluster. + /// + /// It's expected the caller has the start position and thus can determine + /// the code unit range of the extended grapheme cluster. + const _CharT* __last_; + }; + + _LIBCPP_HIDE_FROM_ABI constexpr __cluster __consume() { + char32_t __code_point = __next_code_point_; + const _CharT* __last = __get_break(); + return {__code_point, __last}; + } + +private: + __code_point_view<_CharT> __code_point_view_; + + char32_t __next_code_point_; + __extended_grapheme_custer_property_boundary::__property __next_prop_; + + _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* __get_break() { + bool __RI_break_allowed = true; + bool __has_extened_pictographic = false; + while (true) { + const _CharT* __result = __code_point_view_.__position(); + __extended_grapheme_custer_property_boundary::__property __prev = __next_prop_; + __next_code_point_ = __code_point_view_.__consume(); + __next_prop_ = __extended_grapheme_custer_property_boundary::__get_property(__next_code_point_); + + __has_extened_pictographic |= + __prev == __extended_grapheme_custer_property_boundary::__property::__Extended_Pictographic; + + if (__at_extended_grapheme_cluster_break(__RI_break_allowed, __has_extened_pictographic, __prev, __next_prop_)) + return __result; + } + } +}; + +} // namespace __unicode + +# endif // _LIBCPP_HAS_NO_UNICODE + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_UNICODE_H diff --git a/libcxx/include/format b/libcxx/include/format --- a/libcxx/include/format +++ b/libcxx/include/format @@ -146,6 +146,7 @@ #include <__format/formatter_pointer.h> #include <__format/formatter_string.h> #include <__format/parser_std_format_spec.h> +#include <__format/unicode.h> #include <__variant/monostate.h> #include #include diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -561,6 +561,7 @@ export optional export locale } + module extended_grapheme_cluster_table { private header "__format/extended_grapheme_cluster_table.h" } module format_error { private header "__format/format_error.h" } module format_fwd { private header "__format/format_fwd.h" } module format_parse_context { private header "__format/format_parse_context.h" } @@ -575,6 +576,7 @@ module formatter_pointer { private header "__format/formatter_pointer.h" } module formatter_string { private header "__format/formatter_string.h" } module parser_std_format_spec { private header "__format/parser_std_format_spec.h" } + module unicode { private header "__format/unicode.h" } } } module forward_list { diff --git a/libcxx/test/libcxx/private_headers.verify.cpp b/libcxx/test/libcxx/private_headers.verify.cpp --- a/libcxx/test/libcxx/private_headers.verify.cpp +++ b/libcxx/test/libcxx/private_headers.verify.cpp @@ -254,6 +254,7 @@ #include <__format/buffer.h> // expected-error@*:* {{use of private header from outside its module: '__format/buffer.h'}} #include <__format/concepts.h> // expected-error@*:* {{use of private header from outside its module: '__format/concepts.h'}} #include <__format/enable_insertable.h> // expected-error@*:* {{use of private header from outside its module: '__format/enable_insertable.h'}} +#include <__format/extended_grapheme_cluster_table.h> // expected-error@*:* {{use of private header from outside its module: '__format/extended_grapheme_cluster_table.h'}} #include <__format/format_arg.h> // expected-error@*:* {{use of private header from outside its module: '__format/format_arg.h'}} #include <__format/format_arg_store.h> // expected-error@*:* {{use of private header from outside its module: '__format/format_arg_store.h'}} #include <__format/format_args.h> // expected-error@*:* {{use of private header from outside its module: '__format/format_args.h'}} @@ -272,6 +273,7 @@ #include <__format/formatter_pointer.h> // expected-error@*:* {{use of private header from outside its module: '__format/formatter_pointer.h'}} #include <__format/formatter_string.h> // expected-error@*:* {{use of private header from outside its module: '__format/formatter_string.h'}} #include <__format/parser_std_format_spec.h> // expected-error@*:* {{use of private header from outside its module: '__format/parser_std_format_spec.h'}} +#include <__format/unicode.h> // expected-error@*:* {{use of private header from outside its module: '__format/unicode.h'}} #include <__functional/binary_function.h> // expected-error@*:* {{use of private header from outside its module: '__functional/binary_function.h'}} #include <__functional/binary_negate.h> // expected-error@*:* {{use of private header from outside its module: '__functional/binary_negate.h'}} #include <__functional/bind.h> // expected-error@*:* {{use of private header from outside its module: '__functional/bind.h'}} diff --git a/libcxx/test/libcxx/utilities/format/format.string/format.string.std/extended_grapheme_cluster.h b/libcxx/test/libcxx/utilities/format/format.string/format.string.std/extended_grapheme_cluster.h new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/utilities/format/format.string/format.string.std/extended_grapheme_cluster.h @@ -0,0 +1,1905 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// WARNING, this entire header is generated by +// utiles/generate_extended_grapheme_cluster_test.py +// DO NOT MODIFY! + +// UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE +// +// See Terms of Use +// for definitions of Unicode Inc.'s Data Files and Software. +// +// NOTICE TO USER: Carefully read the following legal agreement. +// BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S +// DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), +// YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +// TERMS AND CONDITIONS OF THIS AGREEMENT. +// IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE +// THE DATA FILES OR SOFTWARE. +// +// COPYRIGHT AND PERMISSION NOTICE +// +// Copyright (c) 1991-2022 Unicode, Inc. All rights reserved. +// Distributed under the Terms of Use in https://www.unicode.org/copyright.html. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of the Unicode data files and any associated documentation +// (the "Data Files") or Unicode software and any associated documentation +// (the "Software") to deal in the Data Files or Software +// without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, and/or sell copies of +// the Data Files or Software, and to permit persons to whom the Data Files +// or Software are furnished to do so, provided that either +// (a) this copyright and permission notice appear with all copies +// of the Data Files or Software, or +// (b) this copyright and permission notice appear in associated +// Documentation. +// +// THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT OF THIRD PARTY RIGHTS. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS +// NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +// DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +// DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THE DATA FILES OR SOFTWARE. +// +// Except as contained in this notice, the name of a copyright holder +// shall not be used in advertising or otherwise to promote the sale, +// use or other dealings in these Data Files or Software without prior +// written authorization of the copyright holder. + +#ifndef LIBCXX_TEST_STD_UTILITIES_FORMAT_FORMAT_STRING_FORMAT_STRING_STD_EXTENDED_GRAPHEME_CLUSTER_H +#define LIBCXX_TEST_STD_UTILITIES_FORMAT_FORMAT_STRING_FORMAT_STRING_STD_EXTENDED_GRAPHEME_CLUSTER_H + +#include +#include +#include + +template +struct data { + /// The input to parse. + std::basic_string_view input; + + /// The first code point all extended grapheme clusters in the input. + std::vector code_points; + + /// The offset of the last code units of the extended grapheme clusters in the input. + /// + /// The vector has the same number of entries as \ref code_points. + std::vector breaks; +}; + +/// The data for UTF-8. +std::array, 602> data_utf8 = { + {{"\U00000020\U00000020", {32, 32}, {1, 2}}, + {"\U00000020\U00000308\U00000020", {32, 32}, {3, 4}}, + {"\U00000020\U0000000d", {32, 13}, {1, 2}}, + {"\U00000020\U00000308\U0000000d", {32, 13}, {3, 4}}, + {"\U00000020\U0000000a", {32, 10}, {1, 2}}, + {"\U00000020\U00000308\U0000000a", {32, 10}, {3, 4}}, + {"\U00000020\U00000001", {32, 1}, {1, 2}}, + {"\U00000020\U00000308\U00000001", {32, 1}, {3, 4}}, + {"\U00000020\U0000034f", {32}, {3}}, + {"\U00000020\U00000308\U0000034f", {32}, {5}}, + {"\U00000020\U0001f1e6", {32, 127462}, {1, 5}}, + {"\U00000020\U00000308\U0001f1e6", {32, 127462}, {3, 7}}, + {"\U00000020\U00000600", {32, 1536}, {1, 3}}, + {"\U00000020\U00000308\U00000600", {32, 1536}, {3, 5}}, + {"\U00000020\U00000903", {32}, {4}}, + {"\U00000020\U00000308\U00000903", {32}, {6}}, + {"\U00000020\U00001100", {32, 4352}, {1, 4}}, + {"\U00000020\U00000308\U00001100", {32, 4352}, {3, 6}}, + {"\U00000020\U00001160", {32, 4448}, {1, 4}}, + {"\U00000020\U00000308\U00001160", {32, 4448}, {3, 6}}, + {"\U00000020\U000011a8", {32, 4520}, {1, 4}}, + {"\U00000020\U00000308\U000011a8", {32, 4520}, {3, 6}}, + {"\U00000020\U0000ac00", {32, 44032}, {1, 4}}, + {"\U00000020\U00000308\U0000ac00", {32, 44032}, {3, 6}}, + {"\U00000020\U0000ac01", {32, 44033}, {1, 4}}, + {"\U00000020\U00000308\U0000ac01", {32, 44033}, {3, 6}}, + {"\U00000020\U0000231a", {32, 8986}, {1, 4}}, + {"\U00000020\U00000308\U0000231a", {32, 8986}, {3, 6}}, + {"\U00000020\U00000300", {32}, {3}}, + {"\U00000020\U00000308\U00000300", {32}, {5}}, + {"\U00000020\U0000200d", {32}, {4}}, + {"\U00000020\U00000308\U0000200d", {32}, {6}}, + {"\U00000020\U00000378", {32, 888}, {1, 3}}, + {"\U00000020\U00000308\U00000378", {32, 888}, {3, 5}}, + {"\U0000000d\U00000020", {13, 32}, {1, 2}}, + {"\U0000000d\U00000308\U00000020", {13, 776, 32}, {1, 3, 4}}, + {"\U0000000d\U0000000d", {13, 13}, {1, 2}}, + {"\U0000000d\U00000308\U0000000d", {13, 776, 13}, {1, 3, 4}}, + {"\U0000000d\U0000000a", {13}, {2}}, + {"\U0000000d\U00000308\U0000000a", {13, 776, 10}, {1, 3, 4}}, + {"\U0000000d\U00000001", {13, 1}, {1, 2}}, + {"\U0000000d\U00000308\U00000001", {13, 776, 1}, {1, 3, 4}}, + {"\U0000000d\U0000034f", {13, 847}, {1, 3}}, + {"\U0000000d\U00000308\U0000034f", {13, 776}, {1, 5}}, + {"\U0000000d\U0001f1e6", {13, 127462}, {1, 5}}, + {"\U0000000d\U00000308\U0001f1e6", {13, 776, 127462}, {1, 3, 7}}, + {"\U0000000d\U00000600", {13, 1536}, {1, 3}}, + {"\U0000000d\U00000308\U00000600", {13, 776, 1536}, {1, 3, 5}}, + {"\U0000000d\U00000903", {13, 2307}, {1, 4}}, + {"\U0000000d\U00000308\U00000903", {13, 776}, {1, 6}}, + {"\U0000000d\U00001100", {13, 4352}, {1, 4}}, + {"\U0000000d\U00000308\U00001100", {13, 776, 4352}, {1, 3, 6}}, + {"\U0000000d\U00001160", {13, 4448}, {1, 4}}, + {"\U0000000d\U00000308\U00001160", {13, 776, 4448}, {1, 3, 6}}, + {"\U0000000d\U000011a8", {13, 4520}, {1, 4}}, + {"\U0000000d\U00000308\U000011a8", {13, 776, 4520}, {1, 3, 6}}, + {"\U0000000d\U0000ac00", {13, 44032}, {1, 4}}, + {"\U0000000d\U00000308\U0000ac00", {13, 776, 44032}, {1, 3, 6}}, + {"\U0000000d\U0000ac01", {13, 44033}, {1, 4}}, + {"\U0000000d\U00000308\U0000ac01", {13, 776, 44033}, {1, 3, 6}}, + {"\U0000000d\U0000231a", {13, 8986}, {1, 4}}, + {"\U0000000d\U00000308\U0000231a", {13, 776, 8986}, {1, 3, 6}}, + {"\U0000000d\U00000300", {13, 768}, {1, 3}}, + {"\U0000000d\U00000308\U00000300", {13, 776}, {1, 5}}, + {"\U0000000d\U0000200d", {13, 8205}, {1, 4}}, + {"\U0000000d\U00000308\U0000200d", {13, 776}, {1, 6}}, + {"\U0000000d\U00000378", {13, 888}, {1, 3}}, + {"\U0000000d\U00000308\U00000378", {13, 776, 888}, {1, 3, 5}}, + {"\U0000000a\U00000020", {10, 32}, {1, 2}}, + {"\U0000000a\U00000308\U00000020", {10, 776, 32}, {1, 3, 4}}, + {"\U0000000a\U0000000d", {10, 13}, {1, 2}}, + {"\U0000000a\U00000308\U0000000d", {10, 776, 13}, {1, 3, 4}}, + {"\U0000000a\U0000000a", {10, 10}, {1, 2}}, + {"\U0000000a\U00000308\U0000000a", {10, 776, 10}, {1, 3, 4}}, + {"\U0000000a\U00000001", {10, 1}, {1, 2}}, + {"\U0000000a\U00000308\U00000001", {10, 776, 1}, {1, 3, 4}}, + {"\U0000000a\U0000034f", {10, 847}, {1, 3}}, + {"\U0000000a\U00000308\U0000034f", {10, 776}, {1, 5}}, + {"\U0000000a\U0001f1e6", {10, 127462}, {1, 5}}, + {"\U0000000a\U00000308\U0001f1e6", {10, 776, 127462}, {1, 3, 7}}, + {"\U0000000a\U00000600", {10, 1536}, {1, 3}}, + {"\U0000000a\U00000308\U00000600", {10, 776, 1536}, {1, 3, 5}}, + {"\U0000000a\U00000903", {10, 2307}, {1, 4}}, + {"\U0000000a\U00000308\U00000903", {10, 776}, {1, 6}}, + {"\U0000000a\U00001100", {10, 4352}, {1, 4}}, + {"\U0000000a\U00000308\U00001100", {10, 776, 4352}, {1, 3, 6}}, + {"\U0000000a\U00001160", {10, 4448}, {1, 4}}, + {"\U0000000a\U00000308\U00001160", {10, 776, 4448}, {1, 3, 6}}, + {"\U0000000a\U000011a8", {10, 4520}, {1, 4}}, + {"\U0000000a\U00000308\U000011a8", {10, 776, 4520}, {1, 3, 6}}, + {"\U0000000a\U0000ac00", {10, 44032}, {1, 4}}, + {"\U0000000a\U00000308\U0000ac00", {10, 776, 44032}, {1, 3, 6}}, + {"\U0000000a\U0000ac01", {10, 44033}, {1, 4}}, + {"\U0000000a\U00000308\U0000ac01", {10, 776, 44033}, {1, 3, 6}}, + {"\U0000000a\U0000231a", {10, 8986}, {1, 4}}, + {"\U0000000a\U00000308\U0000231a", {10, 776, 8986}, {1, 3, 6}}, + {"\U0000000a\U00000300", {10, 768}, {1, 3}}, + {"\U0000000a\U00000308\U00000300", {10, 776}, {1, 5}}, + {"\U0000000a\U0000200d", {10, 8205}, {1, 4}}, + {"\U0000000a\U00000308\U0000200d", {10, 776}, {1, 6}}, + {"\U0000000a\U00000378", {10, 888}, {1, 3}}, + {"\U0000000a\U00000308\U00000378", {10, 776, 888}, {1, 3, 5}}, + {"\U00000001\U00000020", {1, 32}, {1, 2}}, + {"\U00000001\U00000308\U00000020", {1, 776, 32}, {1, 3, 4}}, + {"\U00000001\U0000000d", {1, 13}, {1, 2}}, + {"\U00000001\U00000308\U0000000d", {1, 776, 13}, {1, 3, 4}}, + {"\U00000001\U0000000a", {1, 10}, {1, 2}}, + {"\U00000001\U00000308\U0000000a", {1, 776, 10}, {1, 3, 4}}, + {"\U00000001\U00000001", {1, 1}, {1, 2}}, + {"\U00000001\U00000308\U00000001", {1, 776, 1}, {1, 3, 4}}, + {"\U00000001\U0000034f", {1, 847}, {1, 3}}, + {"\U00000001\U00000308\U0000034f", {1, 776}, {1, 5}}, + {"\U00000001\U0001f1e6", {1, 127462}, {1, 5}}, + {"\U00000001\U00000308\U0001f1e6", {1, 776, 127462}, {1, 3, 7}}, + {"\U00000001\U00000600", {1, 1536}, {1, 3}}, + {"\U00000001\U00000308\U00000600", {1, 776, 1536}, {1, 3, 5}}, + {"\U00000001\U00000903", {1, 2307}, {1, 4}}, + {"\U00000001\U00000308\U00000903", {1, 776}, {1, 6}}, + {"\U00000001\U00001100", {1, 4352}, {1, 4}}, + {"\U00000001\U00000308\U00001100", {1, 776, 4352}, {1, 3, 6}}, + {"\U00000001\U00001160", {1, 4448}, {1, 4}}, + {"\U00000001\U00000308\U00001160", {1, 776, 4448}, {1, 3, 6}}, + {"\U00000001\U000011a8", {1, 4520}, {1, 4}}, + {"\U00000001\U00000308\U000011a8", {1, 776, 4520}, {1, 3, 6}}, + {"\U00000001\U0000ac00", {1, 44032}, {1, 4}}, + {"\U00000001\U00000308\U0000ac00", {1, 776, 44032}, {1, 3, 6}}, + {"\U00000001\U0000ac01", {1, 44033}, {1, 4}}, + {"\U00000001\U00000308\U0000ac01", {1, 776, 44033}, {1, 3, 6}}, + {"\U00000001\U0000231a", {1, 8986}, {1, 4}}, + {"\U00000001\U00000308\U0000231a", {1, 776, 8986}, {1, 3, 6}}, + {"\U00000001\U00000300", {1, 768}, {1, 3}}, + {"\U00000001\U00000308\U00000300", {1, 776}, {1, 5}}, + {"\U00000001\U0000200d", {1, 8205}, {1, 4}}, + {"\U00000001\U00000308\U0000200d", {1, 776}, {1, 6}}, + {"\U00000001\U00000378", {1, 888}, {1, 3}}, + {"\U00000001\U00000308\U00000378", {1, 776, 888}, {1, 3, 5}}, + {"\U0000034f\U00000020", {847, 32}, {2, 3}}, + {"\U0000034f\U00000308\U00000020", {847, 32}, {4, 5}}, + {"\U0000034f\U0000000d", {847, 13}, {2, 3}}, + {"\U0000034f\U00000308\U0000000d", {847, 13}, {4, 5}}, + {"\U0000034f\U0000000a", {847, 10}, {2, 3}}, + {"\U0000034f\U00000308\U0000000a", {847, 10}, {4, 5}}, + {"\U0000034f\U00000001", {847, 1}, {2, 3}}, + {"\U0000034f\U00000308\U00000001", {847, 1}, {4, 5}}, + {"\U0000034f\U0000034f", {847}, {4}}, + {"\U0000034f\U00000308\U0000034f", {847}, {6}}, + {"\U0000034f\U0001f1e6", {847, 127462}, {2, 6}}, + {"\U0000034f\U00000308\U0001f1e6", {847, 127462}, {4, 8}}, + {"\U0000034f\U00000600", {847, 1536}, {2, 4}}, + {"\U0000034f\U00000308\U00000600", {847, 1536}, {4, 6}}, + {"\U0000034f\U00000903", {847}, {5}}, + {"\U0000034f\U00000308\U00000903", {847}, {7}}, + {"\U0000034f\U00001100", {847, 4352}, {2, 5}}, + {"\U0000034f\U00000308\U00001100", {847, 4352}, {4, 7}}, + {"\U0000034f\U00001160", {847, 4448}, {2, 5}}, + {"\U0000034f\U00000308\U00001160", {847, 4448}, {4, 7}}, + {"\U0000034f\U000011a8", {847, 4520}, {2, 5}}, + {"\U0000034f\U00000308\U000011a8", {847, 4520}, {4, 7}}, + {"\U0000034f\U0000ac00", {847, 44032}, {2, 5}}, + {"\U0000034f\U00000308\U0000ac00", {847, 44032}, {4, 7}}, + {"\U0000034f\U0000ac01", {847, 44033}, {2, 5}}, + {"\U0000034f\U00000308\U0000ac01", {847, 44033}, {4, 7}}, + {"\U0000034f\U0000231a", {847, 8986}, {2, 5}}, + {"\U0000034f\U00000308\U0000231a", {847, 8986}, {4, 7}}, + {"\U0000034f\U00000300", {847}, {4}}, + {"\U0000034f\U00000308\U00000300", {847}, {6}}, + {"\U0000034f\U0000200d", {847}, {5}}, + {"\U0000034f\U00000308\U0000200d", {847}, {7}}, + {"\U0000034f\U00000378", {847, 888}, {2, 4}}, + {"\U0000034f\U00000308\U00000378", {847, 888}, {4, 6}}, + {"\U0001f1e6\U00000020", {127462, 32}, {4, 5}}, + {"\U0001f1e6\U00000308\U00000020", {127462, 32}, {6, 7}}, + {"\U0001f1e6\U0000000d", {127462, 13}, {4, 5}}, + {"\U0001f1e6\U00000308\U0000000d", {127462, 13}, {6, 7}}, + {"\U0001f1e6\U0000000a", {127462, 10}, {4, 5}}, + {"\U0001f1e6\U00000308\U0000000a", {127462, 10}, {6, 7}}, + {"\U0001f1e6\U00000001", {127462, 1}, {4, 5}}, + {"\U0001f1e6\U00000308\U00000001", {127462, 1}, {6, 7}}, + {"\U0001f1e6\U0000034f", {127462}, {6}}, + {"\U0001f1e6\U00000308\U0000034f", {127462}, {8}}, + {"\U0001f1e6\U0001f1e6", {127462}, {8}}, + {"\U0001f1e6\U00000308\U0001f1e6", {127462, 127462}, {6, 10}}, + {"\U0001f1e6\U00000600", {127462, 1536}, {4, 6}}, + {"\U0001f1e6\U00000308\U00000600", {127462, 1536}, {6, 8}}, + {"\U0001f1e6\U00000903", {127462}, {7}}, + {"\U0001f1e6\U00000308\U00000903", {127462}, {9}}, + {"\U0001f1e6\U00001100", {127462, 4352}, {4, 7}}, + {"\U0001f1e6\U00000308\U00001100", {127462, 4352}, {6, 9}}, + {"\U0001f1e6\U00001160", {127462, 4448}, {4, 7}}, + {"\U0001f1e6\U00000308\U00001160", {127462, 4448}, {6, 9}}, + {"\U0001f1e6\U000011a8", {127462, 4520}, {4, 7}}, + {"\U0001f1e6\U00000308\U000011a8", {127462, 4520}, {6, 9}}, + {"\U0001f1e6\U0000ac00", {127462, 44032}, {4, 7}}, + {"\U0001f1e6\U00000308\U0000ac00", {127462, 44032}, {6, 9}}, + {"\U0001f1e6\U0000ac01", {127462, 44033}, {4, 7}}, + {"\U0001f1e6\U00000308\U0000ac01", {127462, 44033}, {6, 9}}, + {"\U0001f1e6\U0000231a", {127462, 8986}, {4, 7}}, + {"\U0001f1e6\U00000308\U0000231a", {127462, 8986}, {6, 9}}, + {"\U0001f1e6\U00000300", {127462}, {6}}, + {"\U0001f1e6\U00000308\U00000300", {127462}, {8}}, + {"\U0001f1e6\U0000200d", {127462}, {7}}, + {"\U0001f1e6\U00000308\U0000200d", {127462}, {9}}, + {"\U0001f1e6\U00000378", {127462, 888}, {4, 6}}, + {"\U0001f1e6\U00000308\U00000378", {127462, 888}, {6, 8}}, + {"\U00000600\U00000020", {1536}, {3}}, + {"\U00000600\U00000308\U00000020", {1536, 32}, {4, 5}}, + {"\U00000600\U0000000d", {1536, 13}, {2, 3}}, + {"\U00000600\U00000308\U0000000d", {1536, 13}, {4, 5}}, + {"\U00000600\U0000000a", {1536, 10}, {2, 3}}, + {"\U00000600\U00000308\U0000000a", {1536, 10}, {4, 5}}, + {"\U00000600\U00000001", {1536, 1}, {2, 3}}, + {"\U00000600\U00000308\U00000001", {1536, 1}, {4, 5}}, + {"\U00000600\U0000034f", {1536}, {4}}, + {"\U00000600\U00000308\U0000034f", {1536}, {6}}, + {"\U00000600\U0001f1e6", {1536}, {6}}, + {"\U00000600\U00000308\U0001f1e6", {1536, 127462}, {4, 8}}, + {"\U00000600\U00000600", {1536}, {4}}, + {"\U00000600\U00000308\U00000600", {1536, 1536}, {4, 6}}, + {"\U00000600\U00000903", {1536}, {5}}, + {"\U00000600\U00000308\U00000903", {1536}, {7}}, + {"\U00000600\U00001100", {1536}, {5}}, + {"\U00000600\U00000308\U00001100", {1536, 4352}, {4, 7}}, + {"\U00000600\U00001160", {1536}, {5}}, + {"\U00000600\U00000308\U00001160", {1536, 4448}, {4, 7}}, + {"\U00000600\U000011a8", {1536}, {5}}, + {"\U00000600\U00000308\U000011a8", {1536, 4520}, {4, 7}}, + {"\U00000600\U0000ac00", {1536}, {5}}, + {"\U00000600\U00000308\U0000ac00", {1536, 44032}, {4, 7}}, + {"\U00000600\U0000ac01", {1536}, {5}}, + {"\U00000600\U00000308\U0000ac01", {1536, 44033}, {4, 7}}, + {"\U00000600\U0000231a", {1536}, {5}}, + {"\U00000600\U00000308\U0000231a", {1536, 8986}, {4, 7}}, + {"\U00000600\U00000300", {1536}, {4}}, + {"\U00000600\U00000308\U00000300", {1536}, {6}}, + {"\U00000600\U0000200d", {1536}, {5}}, + {"\U00000600\U00000308\U0000200d", {1536}, {7}}, + {"\U00000600\U00000378", {1536}, {4}}, + {"\U00000600\U00000308\U00000378", {1536, 888}, {4, 6}}, + {"\U00000903\U00000020", {2307, 32}, {3, 4}}, + {"\U00000903\U00000308\U00000020", {2307, 32}, {5, 6}}, + {"\U00000903\U0000000d", {2307, 13}, {3, 4}}, + {"\U00000903\U00000308\U0000000d", {2307, 13}, {5, 6}}, + {"\U00000903\U0000000a", {2307, 10}, {3, 4}}, + {"\U00000903\U00000308\U0000000a", {2307, 10}, {5, 6}}, + {"\U00000903\U00000001", {2307, 1}, {3, 4}}, + {"\U00000903\U00000308\U00000001", {2307, 1}, {5, 6}}, + {"\U00000903\U0000034f", {2307}, {5}}, + {"\U00000903\U00000308\U0000034f", {2307}, {7}}, + {"\U00000903\U0001f1e6", {2307, 127462}, {3, 7}}, + {"\U00000903\U00000308\U0001f1e6", {2307, 127462}, {5, 9}}, + {"\U00000903\U00000600", {2307, 1536}, {3, 5}}, + {"\U00000903\U00000308\U00000600", {2307, 1536}, {5, 7}}, + {"\U00000903\U00000903", {2307}, {6}}, + {"\U00000903\U00000308\U00000903", {2307}, {8}}, + {"\U00000903\U00001100", {2307, 4352}, {3, 6}}, + {"\U00000903\U00000308\U00001100", {2307, 4352}, {5, 8}}, + {"\U00000903\U00001160", {2307, 4448}, {3, 6}}, + {"\U00000903\U00000308\U00001160", {2307, 4448}, {5, 8}}, + {"\U00000903\U000011a8", {2307, 4520}, {3, 6}}, + {"\U00000903\U00000308\U000011a8", {2307, 4520}, {5, 8}}, + {"\U00000903\U0000ac00", {2307, 44032}, {3, 6}}, + {"\U00000903\U00000308\U0000ac00", {2307, 44032}, {5, 8}}, + {"\U00000903\U0000ac01", {2307, 44033}, {3, 6}}, + {"\U00000903\U00000308\U0000ac01", {2307, 44033}, {5, 8}}, + {"\U00000903\U0000231a", {2307, 8986}, {3, 6}}, + {"\U00000903\U00000308\U0000231a", {2307, 8986}, {5, 8}}, + {"\U00000903\U00000300", {2307}, {5}}, + {"\U00000903\U00000308\U00000300", {2307}, {7}}, + {"\U00000903\U0000200d", {2307}, {6}}, + {"\U00000903\U00000308\U0000200d", {2307}, {8}}, + {"\U00000903\U00000378", {2307, 888}, {3, 5}}, + {"\U00000903\U00000308\U00000378", {2307, 888}, {5, 7}}, + {"\U00001100\U00000020", {4352, 32}, {3, 4}}, + {"\U00001100\U00000308\U00000020", {4352, 32}, {5, 6}}, + {"\U00001100\U0000000d", {4352, 13}, {3, 4}}, + {"\U00001100\U00000308\U0000000d", {4352, 13}, {5, 6}}, + {"\U00001100\U0000000a", {4352, 10}, {3, 4}}, + {"\U00001100\U00000308\U0000000a", {4352, 10}, {5, 6}}, + {"\U00001100\U00000001", {4352, 1}, {3, 4}}, + {"\U00001100\U00000308\U00000001", {4352, 1}, {5, 6}}, + {"\U00001100\U0000034f", {4352}, {5}}, + {"\U00001100\U00000308\U0000034f", {4352}, {7}}, + {"\U00001100\U0001f1e6", {4352, 127462}, {3, 7}}, + {"\U00001100\U00000308\U0001f1e6", {4352, 127462}, {5, 9}}, + {"\U00001100\U00000600", {4352, 1536}, {3, 5}}, + {"\U00001100\U00000308\U00000600", {4352, 1536}, {5, 7}}, + {"\U00001100\U00000903", {4352}, {6}}, + {"\U00001100\U00000308\U00000903", {4352}, {8}}, + {"\U00001100\U00001100", {4352}, {6}}, + {"\U00001100\U00000308\U00001100", {4352, 4352}, {5, 8}}, + {"\U00001100\U00001160", {4352}, {6}}, + {"\U00001100\U00000308\U00001160", {4352, 4448}, {5, 8}}, + {"\U00001100\U000011a8", {4352, 4520}, {3, 6}}, + {"\U00001100\U00000308\U000011a8", {4352, 4520}, {5, 8}}, + {"\U00001100\U0000ac00", {4352}, {6}}, + {"\U00001100\U00000308\U0000ac00", {4352, 44032}, {5, 8}}, + {"\U00001100\U0000ac01", {4352}, {6}}, + {"\U00001100\U00000308\U0000ac01", {4352, 44033}, {5, 8}}, + {"\U00001100\U0000231a", {4352, 8986}, {3, 6}}, + {"\U00001100\U00000308\U0000231a", {4352, 8986}, {5, 8}}, + {"\U00001100\U00000300", {4352}, {5}}, + {"\U00001100\U00000308\U00000300", {4352}, {7}}, + {"\U00001100\U0000200d", {4352}, {6}}, + {"\U00001100\U00000308\U0000200d", {4352}, {8}}, + {"\U00001100\U00000378", {4352, 888}, {3, 5}}, + {"\U00001100\U00000308\U00000378", {4352, 888}, {5, 7}}, + {"\U00001160\U00000020", {4448, 32}, {3, 4}}, + {"\U00001160\U00000308\U00000020", {4448, 32}, {5, 6}}, + {"\U00001160\U0000000d", {4448, 13}, {3, 4}}, + {"\U00001160\U00000308\U0000000d", {4448, 13}, {5, 6}}, + {"\U00001160\U0000000a", {4448, 10}, {3, 4}}, + {"\U00001160\U00000308\U0000000a", {4448, 10}, {5, 6}}, + {"\U00001160\U00000001", {4448, 1}, {3, 4}}, + {"\U00001160\U00000308\U00000001", {4448, 1}, {5, 6}}, + {"\U00001160\U0000034f", {4448}, {5}}, + {"\U00001160\U00000308\U0000034f", {4448}, {7}}, + {"\U00001160\U0001f1e6", {4448, 127462}, {3, 7}}, + {"\U00001160\U00000308\U0001f1e6", {4448, 127462}, {5, 9}}, + {"\U00001160\U00000600", {4448, 1536}, {3, 5}}, + {"\U00001160\U00000308\U00000600", {4448, 1536}, {5, 7}}, + {"\U00001160\U00000903", {4448}, {6}}, + {"\U00001160\U00000308\U00000903", {4448}, {8}}, + {"\U00001160\U00001100", {4448, 4352}, {3, 6}}, + {"\U00001160\U00000308\U00001100", {4448, 4352}, {5, 8}}, + {"\U00001160\U00001160", {4448}, {6}}, + {"\U00001160\U00000308\U00001160", {4448, 4448}, {5, 8}}, + {"\U00001160\U000011a8", {4448}, {6}}, + {"\U00001160\U00000308\U000011a8", {4448, 4520}, {5, 8}}, + {"\U00001160\U0000ac00", {4448, 44032}, {3, 6}}, + {"\U00001160\U00000308\U0000ac00", {4448, 44032}, {5, 8}}, + {"\U00001160\U0000ac01", {4448, 44033}, {3, 6}}, + {"\U00001160\U00000308\U0000ac01", {4448, 44033}, {5, 8}}, + {"\U00001160\U0000231a", {4448, 8986}, {3, 6}}, + {"\U00001160\U00000308\U0000231a", {4448, 8986}, {5, 8}}, + {"\U00001160\U00000300", {4448}, {5}}, + {"\U00001160\U00000308\U00000300", {4448}, {7}}, + {"\U00001160\U0000200d", {4448}, {6}}, + {"\U00001160\U00000308\U0000200d", {4448}, {8}}, + {"\U00001160\U00000378", {4448, 888}, {3, 5}}, + {"\U00001160\U00000308\U00000378", {4448, 888}, {5, 7}}, + {"\U000011a8\U00000020", {4520, 32}, {3, 4}}, + {"\U000011a8\U00000308\U00000020", {4520, 32}, {5, 6}}, + {"\U000011a8\U0000000d", {4520, 13}, {3, 4}}, + {"\U000011a8\U00000308\U0000000d", {4520, 13}, {5, 6}}, + {"\U000011a8\U0000000a", {4520, 10}, {3, 4}}, + {"\U000011a8\U00000308\U0000000a", {4520, 10}, {5, 6}}, + {"\U000011a8\U00000001", {4520, 1}, {3, 4}}, + {"\U000011a8\U00000308\U00000001", {4520, 1}, {5, 6}}, + {"\U000011a8\U0000034f", {4520}, {5}}, + {"\U000011a8\U00000308\U0000034f", {4520}, {7}}, + {"\U000011a8\U0001f1e6", {4520, 127462}, {3, 7}}, + {"\U000011a8\U00000308\U0001f1e6", {4520, 127462}, {5, 9}}, + {"\U000011a8\U00000600", {4520, 1536}, {3, 5}}, + {"\U000011a8\U00000308\U00000600", {4520, 1536}, {5, 7}}, + {"\U000011a8\U00000903", {4520}, {6}}, + {"\U000011a8\U00000308\U00000903", {4520}, {8}}, + {"\U000011a8\U00001100", {4520, 4352}, {3, 6}}, + {"\U000011a8\U00000308\U00001100", {4520, 4352}, {5, 8}}, + {"\U000011a8\U00001160", {4520, 4448}, {3, 6}}, + {"\U000011a8\U00000308\U00001160", {4520, 4448}, {5, 8}}, + {"\U000011a8\U000011a8", {4520}, {6}}, + {"\U000011a8\U00000308\U000011a8", {4520, 4520}, {5, 8}}, + {"\U000011a8\U0000ac00", {4520, 44032}, {3, 6}}, + {"\U000011a8\U00000308\U0000ac00", {4520, 44032}, {5, 8}}, + {"\U000011a8\U0000ac01", {4520, 44033}, {3, 6}}, + {"\U000011a8\U00000308\U0000ac01", {4520, 44033}, {5, 8}}, + {"\U000011a8\U0000231a", {4520, 8986}, {3, 6}}, + {"\U000011a8\U00000308\U0000231a", {4520, 8986}, {5, 8}}, + {"\U000011a8\U00000300", {4520}, {5}}, + {"\U000011a8\U00000308\U00000300", {4520}, {7}}, + {"\U000011a8\U0000200d", {4520}, {6}}, + {"\U000011a8\U00000308\U0000200d", {4520}, {8}}, + {"\U000011a8\U00000378", {4520, 888}, {3, 5}}, + {"\U000011a8\U00000308\U00000378", {4520, 888}, {5, 7}}, + {"\U0000ac00\U00000020", {44032, 32}, {3, 4}}, + {"\U0000ac00\U00000308\U00000020", {44032, 32}, {5, 6}}, + {"\U0000ac00\U0000000d", {44032, 13}, {3, 4}}, + {"\U0000ac00\U00000308\U0000000d", {44032, 13}, {5, 6}}, + {"\U0000ac00\U0000000a", {44032, 10}, {3, 4}}, + {"\U0000ac00\U00000308\U0000000a", {44032, 10}, {5, 6}}, + {"\U0000ac00\U00000001", {44032, 1}, {3, 4}}, + {"\U0000ac00\U00000308\U00000001", {44032, 1}, {5, 6}}, + {"\U0000ac00\U0000034f", {44032}, {5}}, + {"\U0000ac00\U00000308\U0000034f", {44032}, {7}}, + {"\U0000ac00\U0001f1e6", {44032, 127462}, {3, 7}}, + {"\U0000ac00\U00000308\U0001f1e6", {44032, 127462}, {5, 9}}, + {"\U0000ac00\U00000600", {44032, 1536}, {3, 5}}, + {"\U0000ac00\U00000308\U00000600", {44032, 1536}, {5, 7}}, + {"\U0000ac00\U00000903", {44032}, {6}}, + {"\U0000ac00\U00000308\U00000903", {44032}, {8}}, + {"\U0000ac00\U00001100", {44032, 4352}, {3, 6}}, + {"\U0000ac00\U00000308\U00001100", {44032, 4352}, {5, 8}}, + {"\U0000ac00\U00001160", {44032}, {6}}, + {"\U0000ac00\U00000308\U00001160", {44032, 4448}, {5, 8}}, + {"\U0000ac00\U000011a8", {44032}, {6}}, + {"\U0000ac00\U00000308\U000011a8", {44032, 4520}, {5, 8}}, + {"\U0000ac00\U0000ac00", {44032, 44032}, {3, 6}}, + {"\U0000ac00\U00000308\U0000ac00", {44032, 44032}, {5, 8}}, + {"\U0000ac00\U0000ac01", {44032, 44033}, {3, 6}}, + {"\U0000ac00\U00000308\U0000ac01", {44032, 44033}, {5, 8}}, + {"\U0000ac00\U0000231a", {44032, 8986}, {3, 6}}, + {"\U0000ac00\U00000308\U0000231a", {44032, 8986}, {5, 8}}, + {"\U0000ac00\U00000300", {44032}, {5}}, + {"\U0000ac00\U00000308\U00000300", {44032}, {7}}, + {"\U0000ac00\U0000200d", {44032}, {6}}, + {"\U0000ac00\U00000308\U0000200d", {44032}, {8}}, + {"\U0000ac00\U00000378", {44032, 888}, {3, 5}}, + {"\U0000ac00\U00000308\U00000378", {44032, 888}, {5, 7}}, + {"\U0000ac01\U00000020", {44033, 32}, {3, 4}}, + {"\U0000ac01\U00000308\U00000020", {44033, 32}, {5, 6}}, + {"\U0000ac01\U0000000d", {44033, 13}, {3, 4}}, + {"\U0000ac01\U00000308\U0000000d", {44033, 13}, {5, 6}}, + {"\U0000ac01\U0000000a", {44033, 10}, {3, 4}}, + {"\U0000ac01\U00000308\U0000000a", {44033, 10}, {5, 6}}, + {"\U0000ac01\U00000001", {44033, 1}, {3, 4}}, + {"\U0000ac01\U00000308\U00000001", {44033, 1}, {5, 6}}, + {"\U0000ac01\U0000034f", {44033}, {5}}, + {"\U0000ac01\U00000308\U0000034f", {44033}, {7}}, + {"\U0000ac01\U0001f1e6", {44033, 127462}, {3, 7}}, + {"\U0000ac01\U00000308\U0001f1e6", {44033, 127462}, {5, 9}}, + {"\U0000ac01\U00000600", {44033, 1536}, {3, 5}}, + {"\U0000ac01\U00000308\U00000600", {44033, 1536}, {5, 7}}, + {"\U0000ac01\U00000903", {44033}, {6}}, + {"\U0000ac01\U00000308\U00000903", {44033}, {8}}, + {"\U0000ac01\U00001100", {44033, 4352}, {3, 6}}, + {"\U0000ac01\U00000308\U00001100", {44033, 4352}, {5, 8}}, + {"\U0000ac01\U00001160", {44033, 4448}, {3, 6}}, + {"\U0000ac01\U00000308\U00001160", {44033, 4448}, {5, 8}}, + {"\U0000ac01\U000011a8", {44033}, {6}}, + {"\U0000ac01\U00000308\U000011a8", {44033, 4520}, {5, 8}}, + {"\U0000ac01\U0000ac00", {44033, 44032}, {3, 6}}, + {"\U0000ac01\U00000308\U0000ac00", {44033, 44032}, {5, 8}}, + {"\U0000ac01\U0000ac01", {44033, 44033}, {3, 6}}, + {"\U0000ac01\U00000308\U0000ac01", {44033, 44033}, {5, 8}}, + {"\U0000ac01\U0000231a", {44033, 8986}, {3, 6}}, + {"\U0000ac01\U00000308\U0000231a", {44033, 8986}, {5, 8}}, + {"\U0000ac01\U00000300", {44033}, {5}}, + {"\U0000ac01\U00000308\U00000300", {44033}, {7}}, + {"\U0000ac01\U0000200d", {44033}, {6}}, + {"\U0000ac01\U00000308\U0000200d", {44033}, {8}}, + {"\U0000ac01\U00000378", {44033, 888}, {3, 5}}, + {"\U0000ac01\U00000308\U00000378", {44033, 888}, {5, 7}}, + {"\U0000231a\U00000020", {8986, 32}, {3, 4}}, + {"\U0000231a\U00000308\U00000020", {8986, 32}, {5, 6}}, + {"\U0000231a\U0000000d", {8986, 13}, {3, 4}}, + {"\U0000231a\U00000308\U0000000d", {8986, 13}, {5, 6}}, + {"\U0000231a\U0000000a", {8986, 10}, {3, 4}}, + {"\U0000231a\U00000308\U0000000a", {8986, 10}, {5, 6}}, + {"\U0000231a\U00000001", {8986, 1}, {3, 4}}, + {"\U0000231a\U00000308\U00000001", {8986, 1}, {5, 6}}, + {"\U0000231a\U0000034f", {8986}, {5}}, + {"\U0000231a\U00000308\U0000034f", {8986}, {7}}, + {"\U0000231a\U0001f1e6", {8986, 127462}, {3, 7}}, + {"\U0000231a\U00000308\U0001f1e6", {8986, 127462}, {5, 9}}, + {"\U0000231a\U00000600", {8986, 1536}, {3, 5}}, + {"\U0000231a\U00000308\U00000600", {8986, 1536}, {5, 7}}, + {"\U0000231a\U00000903", {8986}, {6}}, + {"\U0000231a\U00000308\U00000903", {8986}, {8}}, + {"\U0000231a\U00001100", {8986, 4352}, {3, 6}}, + {"\U0000231a\U00000308\U00001100", {8986, 4352}, {5, 8}}, + {"\U0000231a\U00001160", {8986, 4448}, {3, 6}}, + {"\U0000231a\U00000308\U00001160", {8986, 4448}, {5, 8}}, + {"\U0000231a\U000011a8", {8986, 4520}, {3, 6}}, + {"\U0000231a\U00000308\U000011a8", {8986, 4520}, {5, 8}}, + {"\U0000231a\U0000ac00", {8986, 44032}, {3, 6}}, + {"\U0000231a\U00000308\U0000ac00", {8986, 44032}, {5, 8}}, + {"\U0000231a\U0000ac01", {8986, 44033}, {3, 6}}, + {"\U0000231a\U00000308\U0000ac01", {8986, 44033}, {5, 8}}, + {"\U0000231a\U0000231a", {8986, 8986}, {3, 6}}, + {"\U0000231a\U00000308\U0000231a", {8986, 8986}, {5, 8}}, + {"\U0000231a\U00000300", {8986}, {5}}, + {"\U0000231a\U00000308\U00000300", {8986}, {7}}, + {"\U0000231a\U0000200d", {8986}, {6}}, + {"\U0000231a\U00000308\U0000200d", {8986}, {8}}, + {"\U0000231a\U00000378", {8986, 888}, {3, 5}}, + {"\U0000231a\U00000308\U00000378", {8986, 888}, {5, 7}}, + {"\U00000300\U00000020", {768, 32}, {2, 3}}, + {"\U00000300\U00000308\U00000020", {768, 32}, {4, 5}}, + {"\U00000300\U0000000d", {768, 13}, {2, 3}}, + {"\U00000300\U00000308\U0000000d", {768, 13}, {4, 5}}, + {"\U00000300\U0000000a", {768, 10}, {2, 3}}, + {"\U00000300\U00000308\U0000000a", {768, 10}, {4, 5}}, + {"\U00000300\U00000001", {768, 1}, {2, 3}}, + {"\U00000300\U00000308\U00000001", {768, 1}, {4, 5}}, + {"\U00000300\U0000034f", {768}, {4}}, + {"\U00000300\U00000308\U0000034f", {768}, {6}}, + {"\U00000300\U0001f1e6", {768, 127462}, {2, 6}}, + {"\U00000300\U00000308\U0001f1e6", {768, 127462}, {4, 8}}, + {"\U00000300\U00000600", {768, 1536}, {2, 4}}, + {"\U00000300\U00000308\U00000600", {768, 1536}, {4, 6}}, + {"\U00000300\U00000903", {768}, {5}}, + {"\U00000300\U00000308\U00000903", {768}, {7}}, + {"\U00000300\U00001100", {768, 4352}, {2, 5}}, + {"\U00000300\U00000308\U00001100", {768, 4352}, {4, 7}}, + {"\U00000300\U00001160", {768, 4448}, {2, 5}}, + {"\U00000300\U00000308\U00001160", {768, 4448}, {4, 7}}, + {"\U00000300\U000011a8", {768, 4520}, {2, 5}}, + {"\U00000300\U00000308\U000011a8", {768, 4520}, {4, 7}}, + {"\U00000300\U0000ac00", {768, 44032}, {2, 5}}, + {"\U00000300\U00000308\U0000ac00", {768, 44032}, {4, 7}}, + {"\U00000300\U0000ac01", {768, 44033}, {2, 5}}, + {"\U00000300\U00000308\U0000ac01", {768, 44033}, {4, 7}}, + {"\U00000300\U0000231a", {768, 8986}, {2, 5}}, + {"\U00000300\U00000308\U0000231a", {768, 8986}, {4, 7}}, + {"\U00000300\U00000300", {768}, {4}}, + {"\U00000300\U00000308\U00000300", {768}, {6}}, + {"\U00000300\U0000200d", {768}, {5}}, + {"\U00000300\U00000308\U0000200d", {768}, {7}}, + {"\U00000300\U00000378", {768, 888}, {2, 4}}, + {"\U00000300\U00000308\U00000378", {768, 888}, {4, 6}}, + {"\U0000200d\U00000020", {8205, 32}, {3, 4}}, + {"\U0000200d\U00000308\U00000020", {8205, 32}, {5, 6}}, + {"\U0000200d\U0000000d", {8205, 13}, {3, 4}}, + {"\U0000200d\U00000308\U0000000d", {8205, 13}, {5, 6}}, + {"\U0000200d\U0000000a", {8205, 10}, {3, 4}}, + {"\U0000200d\U00000308\U0000000a", {8205, 10}, {5, 6}}, + {"\U0000200d\U00000001", {8205, 1}, {3, 4}}, + {"\U0000200d\U00000308\U00000001", {8205, 1}, {5, 6}}, + {"\U0000200d\U0000034f", {8205}, {5}}, + {"\U0000200d\U00000308\U0000034f", {8205}, {7}}, + {"\U0000200d\U0001f1e6", {8205, 127462}, {3, 7}}, + {"\U0000200d\U00000308\U0001f1e6", {8205, 127462}, {5, 9}}, + {"\U0000200d\U00000600", {8205, 1536}, {3, 5}}, + {"\U0000200d\U00000308\U00000600", {8205, 1536}, {5, 7}}, + {"\U0000200d\U00000903", {8205}, {6}}, + {"\U0000200d\U00000308\U00000903", {8205}, {8}}, + {"\U0000200d\U00001100", {8205, 4352}, {3, 6}}, + {"\U0000200d\U00000308\U00001100", {8205, 4352}, {5, 8}}, + {"\U0000200d\U00001160", {8205, 4448}, {3, 6}}, + {"\U0000200d\U00000308\U00001160", {8205, 4448}, {5, 8}}, + {"\U0000200d\U000011a8", {8205, 4520}, {3, 6}}, + {"\U0000200d\U00000308\U000011a8", {8205, 4520}, {5, 8}}, + {"\U0000200d\U0000ac00", {8205, 44032}, {3, 6}}, + {"\U0000200d\U00000308\U0000ac00", {8205, 44032}, {5, 8}}, + {"\U0000200d\U0000ac01", {8205, 44033}, {3, 6}}, + {"\U0000200d\U00000308\U0000ac01", {8205, 44033}, {5, 8}}, + {"\U0000200d\U0000231a", {8205, 8986}, {3, 6}}, + {"\U0000200d\U00000308\U0000231a", {8205, 8986}, {5, 8}}, + {"\U0000200d\U00000300", {8205}, {5}}, + {"\U0000200d\U00000308\U00000300", {8205}, {7}}, + {"\U0000200d\U0000200d", {8205}, {6}}, + {"\U0000200d\U00000308\U0000200d", {8205}, {8}}, + {"\U0000200d\U00000378", {8205, 888}, {3, 5}}, + {"\U0000200d\U00000308\U00000378", {8205, 888}, {5, 7}}, + {"\U00000378\U00000020", {888, 32}, {2, 3}}, + {"\U00000378\U00000308\U00000020", {888, 32}, {4, 5}}, + {"\U00000378\U0000000d", {888, 13}, {2, 3}}, + {"\U00000378\U00000308\U0000000d", {888, 13}, {4, 5}}, + {"\U00000378\U0000000a", {888, 10}, {2, 3}}, + {"\U00000378\U00000308\U0000000a", {888, 10}, {4, 5}}, + {"\U00000378\U00000001", {888, 1}, {2, 3}}, + {"\U00000378\U00000308\U00000001", {888, 1}, {4, 5}}, + {"\U00000378\U0000034f", {888}, {4}}, + {"\U00000378\U00000308\U0000034f", {888}, {6}}, + {"\U00000378\U0001f1e6", {888, 127462}, {2, 6}}, + {"\U00000378\U00000308\U0001f1e6", {888, 127462}, {4, 8}}, + {"\U00000378\U00000600", {888, 1536}, {2, 4}}, + {"\U00000378\U00000308\U00000600", {888, 1536}, {4, 6}}, + {"\U00000378\U00000903", {888}, {5}}, + {"\U00000378\U00000308\U00000903", {888}, {7}}, + {"\U00000378\U00001100", {888, 4352}, {2, 5}}, + {"\U00000378\U00000308\U00001100", {888, 4352}, {4, 7}}, + {"\U00000378\U00001160", {888, 4448}, {2, 5}}, + {"\U00000378\U00000308\U00001160", {888, 4448}, {4, 7}}, + {"\U00000378\U000011a8", {888, 4520}, {2, 5}}, + {"\U00000378\U00000308\U000011a8", {888, 4520}, {4, 7}}, + {"\U00000378\U0000ac00", {888, 44032}, {2, 5}}, + {"\U00000378\U00000308\U0000ac00", {888, 44032}, {4, 7}}, + {"\U00000378\U0000ac01", {888, 44033}, {2, 5}}, + {"\U00000378\U00000308\U0000ac01", {888, 44033}, {4, 7}}, + {"\U00000378\U0000231a", {888, 8986}, {2, 5}}, + {"\U00000378\U00000308\U0000231a", {888, 8986}, {4, 7}}, + {"\U00000378\U00000300", {888}, {4}}, + {"\U00000378\U00000308\U00000300", {888}, {6}}, + {"\U00000378\U0000200d", {888}, {5}}, + {"\U00000378\U00000308\U0000200d", {888}, {7}}, + {"\U00000378\U00000378", {888, 888}, {2, 4}}, + {"\U00000378\U00000308\U00000378", {888, 888}, {4, 6}}, + {"\U0000000d\U0000000a\U00000061\U0000000a\U00000308", {13, 97, 10, 776}, {2, 3, 4, 6}}, + {"\U00000061\U00000308", {97}, {3}}, + {"\U00000020\U0000200d\U00000646", {32, 1606}, {4, 6}}, + {"\U00000646\U0000200d\U00000020", {1606, 32}, {5, 6}}, + {"\U00001100\U00001100", {4352}, {6}}, + {"\U0000ac00\U000011a8\U00001100", {44032, 4352}, {6, 9}}, + {"\U0000ac01\U000011a8\U00001100", {44033, 4352}, {6, 9}}, + {"\U0001f1e6\U0001f1e7\U0001f1e8\U00000062", {127462, 127464, 98}, {8, 12, 13}}, + {"\U00000061\U0001f1e6\U0001f1e7\U0001f1e8\U00000062", {97, 127462, 127464, 98}, {1, 9, 13, 14}}, + {"\U00000061\U0001f1e6\U0001f1e7\U0000200d\U0001f1e8\U00000062", {97, 127462, 127464, 98}, {1, 12, 16, 17}}, + {"\U00000061\U0001f1e6\U0000200d\U0001f1e7\U0001f1e8\U00000062", {97, 127462, 127463, 98}, {1, 8, 16, 17}}, + {"\U00000061\U0001f1e6\U0001f1e7\U0001f1e8\U0001f1e9\U00000062", {97, 127462, 127464, 98}, {1, 9, 17, 18}}, + {"\U00000061\U0000200d", {97}, {4}}, + {"\U00000061\U00000308\U00000062", {97, 98}, {3, 4}}, + {"\U00000061\U00000903\U00000062", {97, 98}, {4, 5}}, + {"\U00000061\U00000600\U00000062", {97, 1536}, {1, 4}}, + {"\U0001f476\U0001f3ff\U0001f476", {128118, 128118}, {8, 12}}, + {"\U00000061\U0001f3ff\U0001f476", {97, 128118}, {5, 9}}, + {"\U00000061\U0001f3ff\U0001f476\U0000200d\U0001f6d1", {97, 128118}, {5, 16}}, + {"\U0001f476\U0001f3ff\U00000308\U0000200d\U0001f476\U0001f3ff", {128118}, {21}}, + {"\U0001f6d1\U0000200d\U0001f6d1", {128721}, {11}}, + {"\U00000061\U0000200d\U0001f6d1", {97, 128721}, {4, 8}}, + {"\U00002701\U0000200d\U00002701", {9985}, {9}}, + {"\U00000061\U0000200d\U00002701", {97, 9985}, {4, 7}}}}; + +/// The data for UTF-16. +/// +/// Note that most of the data for the UTF-16 and UTF-32 are identical. However +/// since the size of the code units differ the breaks can contain different +/// values. +std::array, 602> data_utf16 = { + {{L"\U00000020\U00000020", {32, 32}, {1, 2}}, + {L"\U00000020\U00000308\U00000020", {32, 32}, {2, 3}}, + {L"\U00000020\U0000000d", {32, 13}, {1, 2}}, + {L"\U00000020\U00000308\U0000000d", {32, 13}, {2, 3}}, + {L"\U00000020\U0000000a", {32, 10}, {1, 2}}, + {L"\U00000020\U00000308\U0000000a", {32, 10}, {2, 3}}, + {L"\U00000020\U00000001", {32, 1}, {1, 2}}, + {L"\U00000020\U00000308\U00000001", {32, 1}, {2, 3}}, + {L"\U00000020\U0000034f", {32}, {2}}, + {L"\U00000020\U00000308\U0000034f", {32}, {3}}, + {L"\U00000020\U0001f1e6", {32, 127462}, {1, 3}}, + {L"\U00000020\U00000308\U0001f1e6", {32, 127462}, {2, 4}}, + {L"\U00000020\U00000600", {32, 1536}, {1, 2}}, + {L"\U00000020\U00000308\U00000600", {32, 1536}, {2, 3}}, + {L"\U00000020\U00000903", {32}, {2}}, + {L"\U00000020\U00000308\U00000903", {32}, {3}}, + {L"\U00000020\U00001100", {32, 4352}, {1, 2}}, + {L"\U00000020\U00000308\U00001100", {32, 4352}, {2, 3}}, + {L"\U00000020\U00001160", {32, 4448}, {1, 2}}, + {L"\U00000020\U00000308\U00001160", {32, 4448}, {2, 3}}, + {L"\U00000020\U000011a8", {32, 4520}, {1, 2}}, + {L"\U00000020\U00000308\U000011a8", {32, 4520}, {2, 3}}, + {L"\U00000020\U0000ac00", {32, 44032}, {1, 2}}, + {L"\U00000020\U00000308\U0000ac00", {32, 44032}, {2, 3}}, + {L"\U00000020\U0000ac01", {32, 44033}, {1, 2}}, + {L"\U00000020\U00000308\U0000ac01", {32, 44033}, {2, 3}}, + {L"\U00000020\U0000231a", {32, 8986}, {1, 2}}, + {L"\U00000020\U00000308\U0000231a", {32, 8986}, {2, 3}}, + {L"\U00000020\U00000300", {32}, {2}}, + {L"\U00000020\U00000308\U00000300", {32}, {3}}, + {L"\U00000020\U0000200d", {32}, {2}}, + {L"\U00000020\U00000308\U0000200d", {32}, {3}}, + {L"\U00000020\U00000378", {32, 888}, {1, 2}}, + {L"\U00000020\U00000308\U00000378", {32, 888}, {2, 3}}, + {L"\U0000000d\U00000020", {13, 32}, {1, 2}}, + {L"\U0000000d\U00000308\U00000020", {13, 776, 32}, {1, 2, 3}}, + {L"\U0000000d\U0000000d", {13, 13}, {1, 2}}, + {L"\U0000000d\U00000308\U0000000d", {13, 776, 13}, {1, 2, 3}}, + {L"\U0000000d\U0000000a", {13}, {2}}, + {L"\U0000000d\U00000308\U0000000a", {13, 776, 10}, {1, 2, 3}}, + {L"\U0000000d\U00000001", {13, 1}, {1, 2}}, + {L"\U0000000d\U00000308\U00000001", {13, 776, 1}, {1, 2, 3}}, + {L"\U0000000d\U0000034f", {13, 847}, {1, 2}}, + {L"\U0000000d\U00000308\U0000034f", {13, 776}, {1, 3}}, + {L"\U0000000d\U0001f1e6", {13, 127462}, {1, 3}}, + {L"\U0000000d\U00000308\U0001f1e6", {13, 776, 127462}, {1, 2, 4}}, + {L"\U0000000d\U00000600", {13, 1536}, {1, 2}}, + {L"\U0000000d\U00000308\U00000600", {13, 776, 1536}, {1, 2, 3}}, + {L"\U0000000d\U00000903", {13, 2307}, {1, 2}}, + {L"\U0000000d\U00000308\U00000903", {13, 776}, {1, 3}}, + {L"\U0000000d\U00001100", {13, 4352}, {1, 2}}, + {L"\U0000000d\U00000308\U00001100", {13, 776, 4352}, {1, 2, 3}}, + {L"\U0000000d\U00001160", {13, 4448}, {1, 2}}, + {L"\U0000000d\U00000308\U00001160", {13, 776, 4448}, {1, 2, 3}}, + {L"\U0000000d\U000011a8", {13, 4520}, {1, 2}}, + {L"\U0000000d\U00000308\U000011a8", {13, 776, 4520}, {1, 2, 3}}, + {L"\U0000000d\U0000ac00", {13, 44032}, {1, 2}}, + {L"\U0000000d\U00000308\U0000ac00", {13, 776, 44032}, {1, 2, 3}}, + {L"\U0000000d\U0000ac01", {13, 44033}, {1, 2}}, + {L"\U0000000d\U00000308\U0000ac01", {13, 776, 44033}, {1, 2, 3}}, + {L"\U0000000d\U0000231a", {13, 8986}, {1, 2}}, + {L"\U0000000d\U00000308\U0000231a", {13, 776, 8986}, {1, 2, 3}}, + {L"\U0000000d\U00000300", {13, 768}, {1, 2}}, + {L"\U0000000d\U00000308\U00000300", {13, 776}, {1, 3}}, + {L"\U0000000d\U0000200d", {13, 8205}, {1, 2}}, + {L"\U0000000d\U00000308\U0000200d", {13, 776}, {1, 3}}, + {L"\U0000000d\U00000378", {13, 888}, {1, 2}}, + {L"\U0000000d\U00000308\U00000378", {13, 776, 888}, {1, 2, 3}}, + {L"\U0000000a\U00000020", {10, 32}, {1, 2}}, + {L"\U0000000a\U00000308\U00000020", {10, 776, 32}, {1, 2, 3}}, + {L"\U0000000a\U0000000d", {10, 13}, {1, 2}}, + {L"\U0000000a\U00000308\U0000000d", {10, 776, 13}, {1, 2, 3}}, + {L"\U0000000a\U0000000a", {10, 10}, {1, 2}}, + {L"\U0000000a\U00000308\U0000000a", {10, 776, 10}, {1, 2, 3}}, + {L"\U0000000a\U00000001", {10, 1}, {1, 2}}, + {L"\U0000000a\U00000308\U00000001", {10, 776, 1}, {1, 2, 3}}, + {L"\U0000000a\U0000034f", {10, 847}, {1, 2}}, + {L"\U0000000a\U00000308\U0000034f", {10, 776}, {1, 3}}, + {L"\U0000000a\U0001f1e6", {10, 127462}, {1, 3}}, + {L"\U0000000a\U00000308\U0001f1e6", {10, 776, 127462}, {1, 2, 4}}, + {L"\U0000000a\U00000600", {10, 1536}, {1, 2}}, + {L"\U0000000a\U00000308\U00000600", {10, 776, 1536}, {1, 2, 3}}, + {L"\U0000000a\U00000903", {10, 2307}, {1, 2}}, + {L"\U0000000a\U00000308\U00000903", {10, 776}, {1, 3}}, + {L"\U0000000a\U00001100", {10, 4352}, {1, 2}}, + {L"\U0000000a\U00000308\U00001100", {10, 776, 4352}, {1, 2, 3}}, + {L"\U0000000a\U00001160", {10, 4448}, {1, 2}}, + {L"\U0000000a\U00000308\U00001160", {10, 776, 4448}, {1, 2, 3}}, + {L"\U0000000a\U000011a8", {10, 4520}, {1, 2}}, + {L"\U0000000a\U00000308\U000011a8", {10, 776, 4520}, {1, 2, 3}}, + {L"\U0000000a\U0000ac00", {10, 44032}, {1, 2}}, + {L"\U0000000a\U00000308\U0000ac00", {10, 776, 44032}, {1, 2, 3}}, + {L"\U0000000a\U0000ac01", {10, 44033}, {1, 2}}, + {L"\U0000000a\U00000308\U0000ac01", {10, 776, 44033}, {1, 2, 3}}, + {L"\U0000000a\U0000231a", {10, 8986}, {1, 2}}, + {L"\U0000000a\U00000308\U0000231a", {10, 776, 8986}, {1, 2, 3}}, + {L"\U0000000a\U00000300", {10, 768}, {1, 2}}, + {L"\U0000000a\U00000308\U00000300", {10, 776}, {1, 3}}, + {L"\U0000000a\U0000200d", {10, 8205}, {1, 2}}, + {L"\U0000000a\U00000308\U0000200d", {10, 776}, {1, 3}}, + {L"\U0000000a\U00000378", {10, 888}, {1, 2}}, + {L"\U0000000a\U00000308\U00000378", {10, 776, 888}, {1, 2, 3}}, + {L"\U00000001\U00000020", {1, 32}, {1, 2}}, + {L"\U00000001\U00000308\U00000020", {1, 776, 32}, {1, 2, 3}}, + {L"\U00000001\U0000000d", {1, 13}, {1, 2}}, + {L"\U00000001\U00000308\U0000000d", {1, 776, 13}, {1, 2, 3}}, + {L"\U00000001\U0000000a", {1, 10}, {1, 2}}, + {L"\U00000001\U00000308\U0000000a", {1, 776, 10}, {1, 2, 3}}, + {L"\U00000001\U00000001", {1, 1}, {1, 2}}, + {L"\U00000001\U00000308\U00000001", {1, 776, 1}, {1, 2, 3}}, + {L"\U00000001\U0000034f", {1, 847}, {1, 2}}, + {L"\U00000001\U00000308\U0000034f", {1, 776}, {1, 3}}, + {L"\U00000001\U0001f1e6", {1, 127462}, {1, 3}}, + {L"\U00000001\U00000308\U0001f1e6", {1, 776, 127462}, {1, 2, 4}}, + {L"\U00000001\U00000600", {1, 1536}, {1, 2}}, + {L"\U00000001\U00000308\U00000600", {1, 776, 1536}, {1, 2, 3}}, + {L"\U00000001\U00000903", {1, 2307}, {1, 2}}, + {L"\U00000001\U00000308\U00000903", {1, 776}, {1, 3}}, + {L"\U00000001\U00001100", {1, 4352}, {1, 2}}, + {L"\U00000001\U00000308\U00001100", {1, 776, 4352}, {1, 2, 3}}, + {L"\U00000001\U00001160", {1, 4448}, {1, 2}}, + {L"\U00000001\U00000308\U00001160", {1, 776, 4448}, {1, 2, 3}}, + {L"\U00000001\U000011a8", {1, 4520}, {1, 2}}, + {L"\U00000001\U00000308\U000011a8", {1, 776, 4520}, {1, 2, 3}}, + {L"\U00000001\U0000ac00", {1, 44032}, {1, 2}}, + {L"\U00000001\U00000308\U0000ac00", {1, 776, 44032}, {1, 2, 3}}, + {L"\U00000001\U0000ac01", {1, 44033}, {1, 2}}, + {L"\U00000001\U00000308\U0000ac01", {1, 776, 44033}, {1, 2, 3}}, + {L"\U00000001\U0000231a", {1, 8986}, {1, 2}}, + {L"\U00000001\U00000308\U0000231a", {1, 776, 8986}, {1, 2, 3}}, + {L"\U00000001\U00000300", {1, 768}, {1, 2}}, + {L"\U00000001\U00000308\U00000300", {1, 776}, {1, 3}}, + {L"\U00000001\U0000200d", {1, 8205}, {1, 2}}, + {L"\U00000001\U00000308\U0000200d", {1, 776}, {1, 3}}, + {L"\U00000001\U00000378", {1, 888}, {1, 2}}, + {L"\U00000001\U00000308\U00000378", {1, 776, 888}, {1, 2, 3}}, + {L"\U0000034f\U00000020", {847, 32}, {1, 2}}, + {L"\U0000034f\U00000308\U00000020", {847, 32}, {2, 3}}, + {L"\U0000034f\U0000000d", {847, 13}, {1, 2}}, + {L"\U0000034f\U00000308\U0000000d", {847, 13}, {2, 3}}, + {L"\U0000034f\U0000000a", {847, 10}, {1, 2}}, + {L"\U0000034f\U00000308\U0000000a", {847, 10}, {2, 3}}, + {L"\U0000034f\U00000001", {847, 1}, {1, 2}}, + {L"\U0000034f\U00000308\U00000001", {847, 1}, {2, 3}}, + {L"\U0000034f\U0000034f", {847}, {2}}, + {L"\U0000034f\U00000308\U0000034f", {847}, {3}}, + {L"\U0000034f\U0001f1e6", {847, 127462}, {1, 3}}, + {L"\U0000034f\U00000308\U0001f1e6", {847, 127462}, {2, 4}}, + {L"\U0000034f\U00000600", {847, 1536}, {1, 2}}, + {L"\U0000034f\U00000308\U00000600", {847, 1536}, {2, 3}}, + {L"\U0000034f\U00000903", {847}, {2}}, + {L"\U0000034f\U00000308\U00000903", {847}, {3}}, + {L"\U0000034f\U00001100", {847, 4352}, {1, 2}}, + {L"\U0000034f\U00000308\U00001100", {847, 4352}, {2, 3}}, + {L"\U0000034f\U00001160", {847, 4448}, {1, 2}}, + {L"\U0000034f\U00000308\U00001160", {847, 4448}, {2, 3}}, + {L"\U0000034f\U000011a8", {847, 4520}, {1, 2}}, + {L"\U0000034f\U00000308\U000011a8", {847, 4520}, {2, 3}}, + {L"\U0000034f\U0000ac00", {847, 44032}, {1, 2}}, + {L"\U0000034f\U00000308\U0000ac00", {847, 44032}, {2, 3}}, + {L"\U0000034f\U0000ac01", {847, 44033}, {1, 2}}, + {L"\U0000034f\U00000308\U0000ac01", {847, 44033}, {2, 3}}, + {L"\U0000034f\U0000231a", {847, 8986}, {1, 2}}, + {L"\U0000034f\U00000308\U0000231a", {847, 8986}, {2, 3}}, + {L"\U0000034f\U00000300", {847}, {2}}, + {L"\U0000034f\U00000308\U00000300", {847}, {3}}, + {L"\U0000034f\U0000200d", {847}, {2}}, + {L"\U0000034f\U00000308\U0000200d", {847}, {3}}, + {L"\U0000034f\U00000378", {847, 888}, {1, 2}}, + {L"\U0000034f\U00000308\U00000378", {847, 888}, {2, 3}}, + {L"\U0001f1e6\U00000020", {127462, 32}, {2, 3}}, + {L"\U0001f1e6\U00000308\U00000020", {127462, 32}, {3, 4}}, + {L"\U0001f1e6\U0000000d", {127462, 13}, {2, 3}}, + {L"\U0001f1e6\U00000308\U0000000d", {127462, 13}, {3, 4}}, + {L"\U0001f1e6\U0000000a", {127462, 10}, {2, 3}}, + {L"\U0001f1e6\U00000308\U0000000a", {127462, 10}, {3, 4}}, + {L"\U0001f1e6\U00000001", {127462, 1}, {2, 3}}, + {L"\U0001f1e6\U00000308\U00000001", {127462, 1}, {3, 4}}, + {L"\U0001f1e6\U0000034f", {127462}, {3}}, + {L"\U0001f1e6\U00000308\U0000034f", {127462}, {4}}, + {L"\U0001f1e6\U0001f1e6", {127462}, {4}}, + {L"\U0001f1e6\U00000308\U0001f1e6", {127462, 127462}, {3, 5}}, + {L"\U0001f1e6\U00000600", {127462, 1536}, {2, 3}}, + {L"\U0001f1e6\U00000308\U00000600", {127462, 1536}, {3, 4}}, + {L"\U0001f1e6\U00000903", {127462}, {3}}, + {L"\U0001f1e6\U00000308\U00000903", {127462}, {4}}, + {L"\U0001f1e6\U00001100", {127462, 4352}, {2, 3}}, + {L"\U0001f1e6\U00000308\U00001100", {127462, 4352}, {3, 4}}, + {L"\U0001f1e6\U00001160", {127462, 4448}, {2, 3}}, + {L"\U0001f1e6\U00000308\U00001160", {127462, 4448}, {3, 4}}, + {L"\U0001f1e6\U000011a8", {127462, 4520}, {2, 3}}, + {L"\U0001f1e6\U00000308\U000011a8", {127462, 4520}, {3, 4}}, + {L"\U0001f1e6\U0000ac00", {127462, 44032}, {2, 3}}, + {L"\U0001f1e6\U00000308\U0000ac00", {127462, 44032}, {3, 4}}, + {L"\U0001f1e6\U0000ac01", {127462, 44033}, {2, 3}}, + {L"\U0001f1e6\U00000308\U0000ac01", {127462, 44033}, {3, 4}}, + {L"\U0001f1e6\U0000231a", {127462, 8986}, {2, 3}}, + {L"\U0001f1e6\U00000308\U0000231a", {127462, 8986}, {3, 4}}, + {L"\U0001f1e6\U00000300", {127462}, {3}}, + {L"\U0001f1e6\U00000308\U00000300", {127462}, {4}}, + {L"\U0001f1e6\U0000200d", {127462}, {3}}, + {L"\U0001f1e6\U00000308\U0000200d", {127462}, {4}}, + {L"\U0001f1e6\U00000378", {127462, 888}, {2, 3}}, + {L"\U0001f1e6\U00000308\U00000378", {127462, 888}, {3, 4}}, + {L"\U00000600\U00000020", {1536}, {2}}, + {L"\U00000600\U00000308\U00000020", {1536, 32}, {2, 3}}, + {L"\U00000600\U0000000d", {1536, 13}, {1, 2}}, + {L"\U00000600\U00000308\U0000000d", {1536, 13}, {2, 3}}, + {L"\U00000600\U0000000a", {1536, 10}, {1, 2}}, + {L"\U00000600\U00000308\U0000000a", {1536, 10}, {2, 3}}, + {L"\U00000600\U00000001", {1536, 1}, {1, 2}}, + {L"\U00000600\U00000308\U00000001", {1536, 1}, {2, 3}}, + {L"\U00000600\U0000034f", {1536}, {2}}, + {L"\U00000600\U00000308\U0000034f", {1536}, {3}}, + {L"\U00000600\U0001f1e6", {1536}, {3}}, + {L"\U00000600\U00000308\U0001f1e6", {1536, 127462}, {2, 4}}, + {L"\U00000600\U00000600", {1536}, {2}}, + {L"\U00000600\U00000308\U00000600", {1536, 1536}, {2, 3}}, + {L"\U00000600\U00000903", {1536}, {2}}, + {L"\U00000600\U00000308\U00000903", {1536}, {3}}, + {L"\U00000600\U00001100", {1536}, {2}}, + {L"\U00000600\U00000308\U00001100", {1536, 4352}, {2, 3}}, + {L"\U00000600\U00001160", {1536}, {2}}, + {L"\U00000600\U00000308\U00001160", {1536, 4448}, {2, 3}}, + {L"\U00000600\U000011a8", {1536}, {2}}, + {L"\U00000600\U00000308\U000011a8", {1536, 4520}, {2, 3}}, + {L"\U00000600\U0000ac00", {1536}, {2}}, + {L"\U00000600\U00000308\U0000ac00", {1536, 44032}, {2, 3}}, + {L"\U00000600\U0000ac01", {1536}, {2}}, + {L"\U00000600\U00000308\U0000ac01", {1536, 44033}, {2, 3}}, + {L"\U00000600\U0000231a", {1536}, {2}}, + {L"\U00000600\U00000308\U0000231a", {1536, 8986}, {2, 3}}, + {L"\U00000600\U00000300", {1536}, {2}}, + {L"\U00000600\U00000308\U00000300", {1536}, {3}}, + {L"\U00000600\U0000200d", {1536}, {2}}, + {L"\U00000600\U00000308\U0000200d", {1536}, {3}}, + {L"\U00000600\U00000378", {1536}, {2}}, + {L"\U00000600\U00000308\U00000378", {1536, 888}, {2, 3}}, + {L"\U00000903\U00000020", {2307, 32}, {1, 2}}, + {L"\U00000903\U00000308\U00000020", {2307, 32}, {2, 3}}, + {L"\U00000903\U0000000d", {2307, 13}, {1, 2}}, + {L"\U00000903\U00000308\U0000000d", {2307, 13}, {2, 3}}, + {L"\U00000903\U0000000a", {2307, 10}, {1, 2}}, + {L"\U00000903\U00000308\U0000000a", {2307, 10}, {2, 3}}, + {L"\U00000903\U00000001", {2307, 1}, {1, 2}}, + {L"\U00000903\U00000308\U00000001", {2307, 1}, {2, 3}}, + {L"\U00000903\U0000034f", {2307}, {2}}, + {L"\U00000903\U00000308\U0000034f", {2307}, {3}}, + {L"\U00000903\U0001f1e6", {2307, 127462}, {1, 3}}, + {L"\U00000903\U00000308\U0001f1e6", {2307, 127462}, {2, 4}}, + {L"\U00000903\U00000600", {2307, 1536}, {1, 2}}, + {L"\U00000903\U00000308\U00000600", {2307, 1536}, {2, 3}}, + {L"\U00000903\U00000903", {2307}, {2}}, + {L"\U00000903\U00000308\U00000903", {2307}, {3}}, + {L"\U00000903\U00001100", {2307, 4352}, {1, 2}}, + {L"\U00000903\U00000308\U00001100", {2307, 4352}, {2, 3}}, + {L"\U00000903\U00001160", {2307, 4448}, {1, 2}}, + {L"\U00000903\U00000308\U00001160", {2307, 4448}, {2, 3}}, + {L"\U00000903\U000011a8", {2307, 4520}, {1, 2}}, + {L"\U00000903\U00000308\U000011a8", {2307, 4520}, {2, 3}}, + {L"\U00000903\U0000ac00", {2307, 44032}, {1, 2}}, + {L"\U00000903\U00000308\U0000ac00", {2307, 44032}, {2, 3}}, + {L"\U00000903\U0000ac01", {2307, 44033}, {1, 2}}, + {L"\U00000903\U00000308\U0000ac01", {2307, 44033}, {2, 3}}, + {L"\U00000903\U0000231a", {2307, 8986}, {1, 2}}, + {L"\U00000903\U00000308\U0000231a", {2307, 8986}, {2, 3}}, + {L"\U00000903\U00000300", {2307}, {2}}, + {L"\U00000903\U00000308\U00000300", {2307}, {3}}, + {L"\U00000903\U0000200d", {2307}, {2}}, + {L"\U00000903\U00000308\U0000200d", {2307}, {3}}, + {L"\U00000903\U00000378", {2307, 888}, {1, 2}}, + {L"\U00000903\U00000308\U00000378", {2307, 888}, {2, 3}}, + {L"\U00001100\U00000020", {4352, 32}, {1, 2}}, + {L"\U00001100\U00000308\U00000020", {4352, 32}, {2, 3}}, + {L"\U00001100\U0000000d", {4352, 13}, {1, 2}}, + {L"\U00001100\U00000308\U0000000d", {4352, 13}, {2, 3}}, + {L"\U00001100\U0000000a", {4352, 10}, {1, 2}}, + {L"\U00001100\U00000308\U0000000a", {4352, 10}, {2, 3}}, + {L"\U00001100\U00000001", {4352, 1}, {1, 2}}, + {L"\U00001100\U00000308\U00000001", {4352, 1}, {2, 3}}, + {L"\U00001100\U0000034f", {4352}, {2}}, + {L"\U00001100\U00000308\U0000034f", {4352}, {3}}, + {L"\U00001100\U0001f1e6", {4352, 127462}, {1, 3}}, + {L"\U00001100\U00000308\U0001f1e6", {4352, 127462}, {2, 4}}, + {L"\U00001100\U00000600", {4352, 1536}, {1, 2}}, + {L"\U00001100\U00000308\U00000600", {4352, 1536}, {2, 3}}, + {L"\U00001100\U00000903", {4352}, {2}}, + {L"\U00001100\U00000308\U00000903", {4352}, {3}}, + {L"\U00001100\U00001100", {4352}, {2}}, + {L"\U00001100\U00000308\U00001100", {4352, 4352}, {2, 3}}, + {L"\U00001100\U00001160", {4352}, {2}}, + {L"\U00001100\U00000308\U00001160", {4352, 4448}, {2, 3}}, + {L"\U00001100\U000011a8", {4352, 4520}, {1, 2}}, + {L"\U00001100\U00000308\U000011a8", {4352, 4520}, {2, 3}}, + {L"\U00001100\U0000ac00", {4352}, {2}}, + {L"\U00001100\U00000308\U0000ac00", {4352, 44032}, {2, 3}}, + {L"\U00001100\U0000ac01", {4352}, {2}}, + {L"\U00001100\U00000308\U0000ac01", {4352, 44033}, {2, 3}}, + {L"\U00001100\U0000231a", {4352, 8986}, {1, 2}}, + {L"\U00001100\U00000308\U0000231a", {4352, 8986}, {2, 3}}, + {L"\U00001100\U00000300", {4352}, {2}}, + {L"\U00001100\U00000308\U00000300", {4352}, {3}}, + {L"\U00001100\U0000200d", {4352}, {2}}, + {L"\U00001100\U00000308\U0000200d", {4352}, {3}}, + {L"\U00001100\U00000378", {4352, 888}, {1, 2}}, + {L"\U00001100\U00000308\U00000378", {4352, 888}, {2, 3}}, + {L"\U00001160\U00000020", {4448, 32}, {1, 2}}, + {L"\U00001160\U00000308\U00000020", {4448, 32}, {2, 3}}, + {L"\U00001160\U0000000d", {4448, 13}, {1, 2}}, + {L"\U00001160\U00000308\U0000000d", {4448, 13}, {2, 3}}, + {L"\U00001160\U0000000a", {4448, 10}, {1, 2}}, + {L"\U00001160\U00000308\U0000000a", {4448, 10}, {2, 3}}, + {L"\U00001160\U00000001", {4448, 1}, {1, 2}}, + {L"\U00001160\U00000308\U00000001", {4448, 1}, {2, 3}}, + {L"\U00001160\U0000034f", {4448}, {2}}, + {L"\U00001160\U00000308\U0000034f", {4448}, {3}}, + {L"\U00001160\U0001f1e6", {4448, 127462}, {1, 3}}, + {L"\U00001160\U00000308\U0001f1e6", {4448, 127462}, {2, 4}}, + {L"\U00001160\U00000600", {4448, 1536}, {1, 2}}, + {L"\U00001160\U00000308\U00000600", {4448, 1536}, {2, 3}}, + {L"\U00001160\U00000903", {4448}, {2}}, + {L"\U00001160\U00000308\U00000903", {4448}, {3}}, + {L"\U00001160\U00001100", {4448, 4352}, {1, 2}}, + {L"\U00001160\U00000308\U00001100", {4448, 4352}, {2, 3}}, + {L"\U00001160\U00001160", {4448}, {2}}, + {L"\U00001160\U00000308\U00001160", {4448, 4448}, {2, 3}}, + {L"\U00001160\U000011a8", {4448}, {2}}, + {L"\U00001160\U00000308\U000011a8", {4448, 4520}, {2, 3}}, + {L"\U00001160\U0000ac00", {4448, 44032}, {1, 2}}, + {L"\U00001160\U00000308\U0000ac00", {4448, 44032}, {2, 3}}, + {L"\U00001160\U0000ac01", {4448, 44033}, {1, 2}}, + {L"\U00001160\U00000308\U0000ac01", {4448, 44033}, {2, 3}}, + {L"\U00001160\U0000231a", {4448, 8986}, {1, 2}}, + {L"\U00001160\U00000308\U0000231a", {4448, 8986}, {2, 3}}, + {L"\U00001160\U00000300", {4448}, {2}}, + {L"\U00001160\U00000308\U00000300", {4448}, {3}}, + {L"\U00001160\U0000200d", {4448}, {2}}, + {L"\U00001160\U00000308\U0000200d", {4448}, {3}}, + {L"\U00001160\U00000378", {4448, 888}, {1, 2}}, + {L"\U00001160\U00000308\U00000378", {4448, 888}, {2, 3}}, + {L"\U000011a8\U00000020", {4520, 32}, {1, 2}}, + {L"\U000011a8\U00000308\U00000020", {4520, 32}, {2, 3}}, + {L"\U000011a8\U0000000d", {4520, 13}, {1, 2}}, + {L"\U000011a8\U00000308\U0000000d", {4520, 13}, {2, 3}}, + {L"\U000011a8\U0000000a", {4520, 10}, {1, 2}}, + {L"\U000011a8\U00000308\U0000000a", {4520, 10}, {2, 3}}, + {L"\U000011a8\U00000001", {4520, 1}, {1, 2}}, + {L"\U000011a8\U00000308\U00000001", {4520, 1}, {2, 3}}, + {L"\U000011a8\U0000034f", {4520}, {2}}, + {L"\U000011a8\U00000308\U0000034f", {4520}, {3}}, + {L"\U000011a8\U0001f1e6", {4520, 127462}, {1, 3}}, + {L"\U000011a8\U00000308\U0001f1e6", {4520, 127462}, {2, 4}}, + {L"\U000011a8\U00000600", {4520, 1536}, {1, 2}}, + {L"\U000011a8\U00000308\U00000600", {4520, 1536}, {2, 3}}, + {L"\U000011a8\U00000903", {4520}, {2}}, + {L"\U000011a8\U00000308\U00000903", {4520}, {3}}, + {L"\U000011a8\U00001100", {4520, 4352}, {1, 2}}, + {L"\U000011a8\U00000308\U00001100", {4520, 4352}, {2, 3}}, + {L"\U000011a8\U00001160", {4520, 4448}, {1, 2}}, + {L"\U000011a8\U00000308\U00001160", {4520, 4448}, {2, 3}}, + {L"\U000011a8\U000011a8", {4520}, {2}}, + {L"\U000011a8\U00000308\U000011a8", {4520, 4520}, {2, 3}}, + {L"\U000011a8\U0000ac00", {4520, 44032}, {1, 2}}, + {L"\U000011a8\U00000308\U0000ac00", {4520, 44032}, {2, 3}}, + {L"\U000011a8\U0000ac01", {4520, 44033}, {1, 2}}, + {L"\U000011a8\U00000308\U0000ac01", {4520, 44033}, {2, 3}}, + {L"\U000011a8\U0000231a", {4520, 8986}, {1, 2}}, + {L"\U000011a8\U00000308\U0000231a", {4520, 8986}, {2, 3}}, + {L"\U000011a8\U00000300", {4520}, {2}}, + {L"\U000011a8\U00000308\U00000300", {4520}, {3}}, + {L"\U000011a8\U0000200d", {4520}, {2}}, + {L"\U000011a8\U00000308\U0000200d", {4520}, {3}}, + {L"\U000011a8\U00000378", {4520, 888}, {1, 2}}, + {L"\U000011a8\U00000308\U00000378", {4520, 888}, {2, 3}}, + {L"\U0000ac00\U00000020", {44032, 32}, {1, 2}}, + {L"\U0000ac00\U00000308\U00000020", {44032, 32}, {2, 3}}, + {L"\U0000ac00\U0000000d", {44032, 13}, {1, 2}}, + {L"\U0000ac00\U00000308\U0000000d", {44032, 13}, {2, 3}}, + {L"\U0000ac00\U0000000a", {44032, 10}, {1, 2}}, + {L"\U0000ac00\U00000308\U0000000a", {44032, 10}, {2, 3}}, + {L"\U0000ac00\U00000001", {44032, 1}, {1, 2}}, + {L"\U0000ac00\U00000308\U00000001", {44032, 1}, {2, 3}}, + {L"\U0000ac00\U0000034f", {44032}, {2}}, + {L"\U0000ac00\U00000308\U0000034f", {44032}, {3}}, + {L"\U0000ac00\U0001f1e6", {44032, 127462}, {1, 3}}, + {L"\U0000ac00\U00000308\U0001f1e6", {44032, 127462}, {2, 4}}, + {L"\U0000ac00\U00000600", {44032, 1536}, {1, 2}}, + {L"\U0000ac00\U00000308\U00000600", {44032, 1536}, {2, 3}}, + {L"\U0000ac00\U00000903", {44032}, {2}}, + {L"\U0000ac00\U00000308\U00000903", {44032}, {3}}, + {L"\U0000ac00\U00001100", {44032, 4352}, {1, 2}}, + {L"\U0000ac00\U00000308\U00001100", {44032, 4352}, {2, 3}}, + {L"\U0000ac00\U00001160", {44032}, {2}}, + {L"\U0000ac00\U00000308\U00001160", {44032, 4448}, {2, 3}}, + {L"\U0000ac00\U000011a8", {44032}, {2}}, + {L"\U0000ac00\U00000308\U000011a8", {44032, 4520}, {2, 3}}, + {L"\U0000ac00\U0000ac00", {44032, 44032}, {1, 2}}, + {L"\U0000ac00\U00000308\U0000ac00", {44032, 44032}, {2, 3}}, + {L"\U0000ac00\U0000ac01", {44032, 44033}, {1, 2}}, + {L"\U0000ac00\U00000308\U0000ac01", {44032, 44033}, {2, 3}}, + {L"\U0000ac00\U0000231a", {44032, 8986}, {1, 2}}, + {L"\U0000ac00\U00000308\U0000231a", {44032, 8986}, {2, 3}}, + {L"\U0000ac00\U00000300", {44032}, {2}}, + {L"\U0000ac00\U00000308\U00000300", {44032}, {3}}, + {L"\U0000ac00\U0000200d", {44032}, {2}}, + {L"\U0000ac00\U00000308\U0000200d", {44032}, {3}}, + {L"\U0000ac00\U00000378", {44032, 888}, {1, 2}}, + {L"\U0000ac00\U00000308\U00000378", {44032, 888}, {2, 3}}, + {L"\U0000ac01\U00000020", {44033, 32}, {1, 2}}, + {L"\U0000ac01\U00000308\U00000020", {44033, 32}, {2, 3}}, + {L"\U0000ac01\U0000000d", {44033, 13}, {1, 2}}, + {L"\U0000ac01\U00000308\U0000000d", {44033, 13}, {2, 3}}, + {L"\U0000ac01\U0000000a", {44033, 10}, {1, 2}}, + {L"\U0000ac01\U00000308\U0000000a", {44033, 10}, {2, 3}}, + {L"\U0000ac01\U00000001", {44033, 1}, {1, 2}}, + {L"\U0000ac01\U00000308\U00000001", {44033, 1}, {2, 3}}, + {L"\U0000ac01\U0000034f", {44033}, {2}}, + {L"\U0000ac01\U00000308\U0000034f", {44033}, {3}}, + {L"\U0000ac01\U0001f1e6", {44033, 127462}, {1, 3}}, + {L"\U0000ac01\U00000308\U0001f1e6", {44033, 127462}, {2, 4}}, + {L"\U0000ac01\U00000600", {44033, 1536}, {1, 2}}, + {L"\U0000ac01\U00000308\U00000600", {44033, 1536}, {2, 3}}, + {L"\U0000ac01\U00000903", {44033}, {2}}, + {L"\U0000ac01\U00000308\U00000903", {44033}, {3}}, + {L"\U0000ac01\U00001100", {44033, 4352}, {1, 2}}, + {L"\U0000ac01\U00000308\U00001100", {44033, 4352}, {2, 3}}, + {L"\U0000ac01\U00001160", {44033, 4448}, {1, 2}}, + {L"\U0000ac01\U00000308\U00001160", {44033, 4448}, {2, 3}}, + {L"\U0000ac01\U000011a8", {44033}, {2}}, + {L"\U0000ac01\U00000308\U000011a8", {44033, 4520}, {2, 3}}, + {L"\U0000ac01\U0000ac00", {44033, 44032}, {1, 2}}, + {L"\U0000ac01\U00000308\U0000ac00", {44033, 44032}, {2, 3}}, + {L"\U0000ac01\U0000ac01", {44033, 44033}, {1, 2}}, + {L"\U0000ac01\U00000308\U0000ac01", {44033, 44033}, {2, 3}}, + {L"\U0000ac01\U0000231a", {44033, 8986}, {1, 2}}, + {L"\U0000ac01\U00000308\U0000231a", {44033, 8986}, {2, 3}}, + {L"\U0000ac01\U00000300", {44033}, {2}}, + {L"\U0000ac01\U00000308\U00000300", {44033}, {3}}, + {L"\U0000ac01\U0000200d", {44033}, {2}}, + {L"\U0000ac01\U00000308\U0000200d", {44033}, {3}}, + {L"\U0000ac01\U00000378", {44033, 888}, {1, 2}}, + {L"\U0000ac01\U00000308\U00000378", {44033, 888}, {2, 3}}, + {L"\U0000231a\U00000020", {8986, 32}, {1, 2}}, + {L"\U0000231a\U00000308\U00000020", {8986, 32}, {2, 3}}, + {L"\U0000231a\U0000000d", {8986, 13}, {1, 2}}, + {L"\U0000231a\U00000308\U0000000d", {8986, 13}, {2, 3}}, + {L"\U0000231a\U0000000a", {8986, 10}, {1, 2}}, + {L"\U0000231a\U00000308\U0000000a", {8986, 10}, {2, 3}}, + {L"\U0000231a\U00000001", {8986, 1}, {1, 2}}, + {L"\U0000231a\U00000308\U00000001", {8986, 1}, {2, 3}}, + {L"\U0000231a\U0000034f", {8986}, {2}}, + {L"\U0000231a\U00000308\U0000034f", {8986}, {3}}, + {L"\U0000231a\U0001f1e6", {8986, 127462}, {1, 3}}, + {L"\U0000231a\U00000308\U0001f1e6", {8986, 127462}, {2, 4}}, + {L"\U0000231a\U00000600", {8986, 1536}, {1, 2}}, + {L"\U0000231a\U00000308\U00000600", {8986, 1536}, {2, 3}}, + {L"\U0000231a\U00000903", {8986}, {2}}, + {L"\U0000231a\U00000308\U00000903", {8986}, {3}}, + {L"\U0000231a\U00001100", {8986, 4352}, {1, 2}}, + {L"\U0000231a\U00000308\U00001100", {8986, 4352}, {2, 3}}, + {L"\U0000231a\U00001160", {8986, 4448}, {1, 2}}, + {L"\U0000231a\U00000308\U00001160", {8986, 4448}, {2, 3}}, + {L"\U0000231a\U000011a8", {8986, 4520}, {1, 2}}, + {L"\U0000231a\U00000308\U000011a8", {8986, 4520}, {2, 3}}, + {L"\U0000231a\U0000ac00", {8986, 44032}, {1, 2}}, + {L"\U0000231a\U00000308\U0000ac00", {8986, 44032}, {2, 3}}, + {L"\U0000231a\U0000ac01", {8986, 44033}, {1, 2}}, + {L"\U0000231a\U00000308\U0000ac01", {8986, 44033}, {2, 3}}, + {L"\U0000231a\U0000231a", {8986, 8986}, {1, 2}}, + {L"\U0000231a\U00000308\U0000231a", {8986, 8986}, {2, 3}}, + {L"\U0000231a\U00000300", {8986}, {2}}, + {L"\U0000231a\U00000308\U00000300", {8986}, {3}}, + {L"\U0000231a\U0000200d", {8986}, {2}}, + {L"\U0000231a\U00000308\U0000200d", {8986}, {3}}, + {L"\U0000231a\U00000378", {8986, 888}, {1, 2}}, + {L"\U0000231a\U00000308\U00000378", {8986, 888}, {2, 3}}, + {L"\U00000300\U00000020", {768, 32}, {1, 2}}, + {L"\U00000300\U00000308\U00000020", {768, 32}, {2, 3}}, + {L"\U00000300\U0000000d", {768, 13}, {1, 2}}, + {L"\U00000300\U00000308\U0000000d", {768, 13}, {2, 3}}, + {L"\U00000300\U0000000a", {768, 10}, {1, 2}}, + {L"\U00000300\U00000308\U0000000a", {768, 10}, {2, 3}}, + {L"\U00000300\U00000001", {768, 1}, {1, 2}}, + {L"\U00000300\U00000308\U00000001", {768, 1}, {2, 3}}, + {L"\U00000300\U0000034f", {768}, {2}}, + {L"\U00000300\U00000308\U0000034f", {768}, {3}}, + {L"\U00000300\U0001f1e6", {768, 127462}, {1, 3}}, + {L"\U00000300\U00000308\U0001f1e6", {768, 127462}, {2, 4}}, + {L"\U00000300\U00000600", {768, 1536}, {1, 2}}, + {L"\U00000300\U00000308\U00000600", {768, 1536}, {2, 3}}, + {L"\U00000300\U00000903", {768}, {2}}, + {L"\U00000300\U00000308\U00000903", {768}, {3}}, + {L"\U00000300\U00001100", {768, 4352}, {1, 2}}, + {L"\U00000300\U00000308\U00001100", {768, 4352}, {2, 3}}, + {L"\U00000300\U00001160", {768, 4448}, {1, 2}}, + {L"\U00000300\U00000308\U00001160", {768, 4448}, {2, 3}}, + {L"\U00000300\U000011a8", {768, 4520}, {1, 2}}, + {L"\U00000300\U00000308\U000011a8", {768, 4520}, {2, 3}}, + {L"\U00000300\U0000ac00", {768, 44032}, {1, 2}}, + {L"\U00000300\U00000308\U0000ac00", {768, 44032}, {2, 3}}, + {L"\U00000300\U0000ac01", {768, 44033}, {1, 2}}, + {L"\U00000300\U00000308\U0000ac01", {768, 44033}, {2, 3}}, + {L"\U00000300\U0000231a", {768, 8986}, {1, 2}}, + {L"\U00000300\U00000308\U0000231a", {768, 8986}, {2, 3}}, + {L"\U00000300\U00000300", {768}, {2}}, + {L"\U00000300\U00000308\U00000300", {768}, {3}}, + {L"\U00000300\U0000200d", {768}, {2}}, + {L"\U00000300\U00000308\U0000200d", {768}, {3}}, + {L"\U00000300\U00000378", {768, 888}, {1, 2}}, + {L"\U00000300\U00000308\U00000378", {768, 888}, {2, 3}}, + {L"\U0000200d\U00000020", {8205, 32}, {1, 2}}, + {L"\U0000200d\U00000308\U00000020", {8205, 32}, {2, 3}}, + {L"\U0000200d\U0000000d", {8205, 13}, {1, 2}}, + {L"\U0000200d\U00000308\U0000000d", {8205, 13}, {2, 3}}, + {L"\U0000200d\U0000000a", {8205, 10}, {1, 2}}, + {L"\U0000200d\U00000308\U0000000a", {8205, 10}, {2, 3}}, + {L"\U0000200d\U00000001", {8205, 1}, {1, 2}}, + {L"\U0000200d\U00000308\U00000001", {8205, 1}, {2, 3}}, + {L"\U0000200d\U0000034f", {8205}, {2}}, + {L"\U0000200d\U00000308\U0000034f", {8205}, {3}}, + {L"\U0000200d\U0001f1e6", {8205, 127462}, {1, 3}}, + {L"\U0000200d\U00000308\U0001f1e6", {8205, 127462}, {2, 4}}, + {L"\U0000200d\U00000600", {8205, 1536}, {1, 2}}, + {L"\U0000200d\U00000308\U00000600", {8205, 1536}, {2, 3}}, + {L"\U0000200d\U00000903", {8205}, {2}}, + {L"\U0000200d\U00000308\U00000903", {8205}, {3}}, + {L"\U0000200d\U00001100", {8205, 4352}, {1, 2}}, + {L"\U0000200d\U00000308\U00001100", {8205, 4352}, {2, 3}}, + {L"\U0000200d\U00001160", {8205, 4448}, {1, 2}}, + {L"\U0000200d\U00000308\U00001160", {8205, 4448}, {2, 3}}, + {L"\U0000200d\U000011a8", {8205, 4520}, {1, 2}}, + {L"\U0000200d\U00000308\U000011a8", {8205, 4520}, {2, 3}}, + {L"\U0000200d\U0000ac00", {8205, 44032}, {1, 2}}, + {L"\U0000200d\U00000308\U0000ac00", {8205, 44032}, {2, 3}}, + {L"\U0000200d\U0000ac01", {8205, 44033}, {1, 2}}, + {L"\U0000200d\U00000308\U0000ac01", {8205, 44033}, {2, 3}}, + {L"\U0000200d\U0000231a", {8205, 8986}, {1, 2}}, + {L"\U0000200d\U00000308\U0000231a", {8205, 8986}, {2, 3}}, + {L"\U0000200d\U00000300", {8205}, {2}}, + {L"\U0000200d\U00000308\U00000300", {8205}, {3}}, + {L"\U0000200d\U0000200d", {8205}, {2}}, + {L"\U0000200d\U00000308\U0000200d", {8205}, {3}}, + {L"\U0000200d\U00000378", {8205, 888}, {1, 2}}, + {L"\U0000200d\U00000308\U00000378", {8205, 888}, {2, 3}}, + {L"\U00000378\U00000020", {888, 32}, {1, 2}}, + {L"\U00000378\U00000308\U00000020", {888, 32}, {2, 3}}, + {L"\U00000378\U0000000d", {888, 13}, {1, 2}}, + {L"\U00000378\U00000308\U0000000d", {888, 13}, {2, 3}}, + {L"\U00000378\U0000000a", {888, 10}, {1, 2}}, + {L"\U00000378\U00000308\U0000000a", {888, 10}, {2, 3}}, + {L"\U00000378\U00000001", {888, 1}, {1, 2}}, + {L"\U00000378\U00000308\U00000001", {888, 1}, {2, 3}}, + {L"\U00000378\U0000034f", {888}, {2}}, + {L"\U00000378\U00000308\U0000034f", {888}, {3}}, + {L"\U00000378\U0001f1e6", {888, 127462}, {1, 3}}, + {L"\U00000378\U00000308\U0001f1e6", {888, 127462}, {2, 4}}, + {L"\U00000378\U00000600", {888, 1536}, {1, 2}}, + {L"\U00000378\U00000308\U00000600", {888, 1536}, {2, 3}}, + {L"\U00000378\U00000903", {888}, {2}}, + {L"\U00000378\U00000308\U00000903", {888}, {3}}, + {L"\U00000378\U00001100", {888, 4352}, {1, 2}}, + {L"\U00000378\U00000308\U00001100", {888, 4352}, {2, 3}}, + {L"\U00000378\U00001160", {888, 4448}, {1, 2}}, + {L"\U00000378\U00000308\U00001160", {888, 4448}, {2, 3}}, + {L"\U00000378\U000011a8", {888, 4520}, {1, 2}}, + {L"\U00000378\U00000308\U000011a8", {888, 4520}, {2, 3}}, + {L"\U00000378\U0000ac00", {888, 44032}, {1, 2}}, + {L"\U00000378\U00000308\U0000ac00", {888, 44032}, {2, 3}}, + {L"\U00000378\U0000ac01", {888, 44033}, {1, 2}}, + {L"\U00000378\U00000308\U0000ac01", {888, 44033}, {2, 3}}, + {L"\U00000378\U0000231a", {888, 8986}, {1, 2}}, + {L"\U00000378\U00000308\U0000231a", {888, 8986}, {2, 3}}, + {L"\U00000378\U00000300", {888}, {2}}, + {L"\U00000378\U00000308\U00000300", {888}, {3}}, + {L"\U00000378\U0000200d", {888}, {2}}, + {L"\U00000378\U00000308\U0000200d", {888}, {3}}, + {L"\U00000378\U00000378", {888, 888}, {1, 2}}, + {L"\U00000378\U00000308\U00000378", {888, 888}, {2, 3}}, + {L"\U0000000d\U0000000a\U00000061\U0000000a\U00000308", {13, 97, 10, 776}, {2, 3, 4, 5}}, + {L"\U00000061\U00000308", {97}, {2}}, + {L"\U00000020\U0000200d\U00000646", {32, 1606}, {2, 3}}, + {L"\U00000646\U0000200d\U00000020", {1606, 32}, {2, 3}}, + {L"\U00001100\U00001100", {4352}, {2}}, + {L"\U0000ac00\U000011a8\U00001100", {44032, 4352}, {2, 3}}, + {L"\U0000ac01\U000011a8\U00001100", {44033, 4352}, {2, 3}}, + {L"\U0001f1e6\U0001f1e7\U0001f1e8\U00000062", {127462, 127464, 98}, {4, 6, 7}}, + {L"\U00000061\U0001f1e6\U0001f1e7\U0001f1e8\U00000062", {97, 127462, 127464, 98}, {1, 5, 7, 8}}, + {L"\U00000061\U0001f1e6\U0001f1e7\U0000200d\U0001f1e8\U00000062", {97, 127462, 127464, 98}, {1, 6, 8, 9}}, + {L"\U00000061\U0001f1e6\U0000200d\U0001f1e7\U0001f1e8\U00000062", {97, 127462, 127463, 98}, {1, 4, 8, 9}}, + {L"\U00000061\U0001f1e6\U0001f1e7\U0001f1e8\U0001f1e9\U00000062", {97, 127462, 127464, 98}, {1, 5, 9, 10}}, + {L"\U00000061\U0000200d", {97}, {2}}, + {L"\U00000061\U00000308\U00000062", {97, 98}, {2, 3}}, + {L"\U00000061\U00000903\U00000062", {97, 98}, {2, 3}}, + {L"\U00000061\U00000600\U00000062", {97, 1536}, {1, 3}}, + {L"\U0001f476\U0001f3ff\U0001f476", {128118, 128118}, {4, 6}}, + {L"\U00000061\U0001f3ff\U0001f476", {97, 128118}, {3, 5}}, + {L"\U00000061\U0001f3ff\U0001f476\U0000200d\U0001f6d1", {97, 128118}, {3, 8}}, + {L"\U0001f476\U0001f3ff\U00000308\U0000200d\U0001f476\U0001f3ff", {128118}, {10}}, + {L"\U0001f6d1\U0000200d\U0001f6d1", {128721}, {5}}, + {L"\U00000061\U0000200d\U0001f6d1", {97, 128721}, {2, 4}}, + {L"\U00002701\U0000200d\U00002701", {9985}, {3}}, + {L"\U00000061\U0000200d\U00002701", {97, 9985}, {2, 3}}}}; + +/// The data for UTF-8. +/// +/// Note that most of the data for the UTF-16 and UTF-32 are identical. However +/// since the size of the code units differ the breaks can contain different +/// values. +std::array, 602> data_utf32 = { + {{L"\U00000020\U00000020", {32, 32}, {1, 2}}, + {L"\U00000020\U00000308\U00000020", {32, 32}, {2, 3}}, + {L"\U00000020\U0000000d", {32, 13}, {1, 2}}, + {L"\U00000020\U00000308\U0000000d", {32, 13}, {2, 3}}, + {L"\U00000020\U0000000a", {32, 10}, {1, 2}}, + {L"\U00000020\U00000308\U0000000a", {32, 10}, {2, 3}}, + {L"\U00000020\U00000001", {32, 1}, {1, 2}}, + {L"\U00000020\U00000308\U00000001", {32, 1}, {2, 3}}, + {L"\U00000020\U0000034f", {32}, {2}}, + {L"\U00000020\U00000308\U0000034f", {32}, {3}}, + {L"\U00000020\U0001f1e6", {32, 127462}, {1, 2}}, + {L"\U00000020\U00000308\U0001f1e6", {32, 127462}, {2, 3}}, + {L"\U00000020\U00000600", {32, 1536}, {1, 2}}, + {L"\U00000020\U00000308\U00000600", {32, 1536}, {2, 3}}, + {L"\U00000020\U00000903", {32}, {2}}, + {L"\U00000020\U00000308\U00000903", {32}, {3}}, + {L"\U00000020\U00001100", {32, 4352}, {1, 2}}, + {L"\U00000020\U00000308\U00001100", {32, 4352}, {2, 3}}, + {L"\U00000020\U00001160", {32, 4448}, {1, 2}}, + {L"\U00000020\U00000308\U00001160", {32, 4448}, {2, 3}}, + {L"\U00000020\U000011a8", {32, 4520}, {1, 2}}, + {L"\U00000020\U00000308\U000011a8", {32, 4520}, {2, 3}}, + {L"\U00000020\U0000ac00", {32, 44032}, {1, 2}}, + {L"\U00000020\U00000308\U0000ac00", {32, 44032}, {2, 3}}, + {L"\U00000020\U0000ac01", {32, 44033}, {1, 2}}, + {L"\U00000020\U00000308\U0000ac01", {32, 44033}, {2, 3}}, + {L"\U00000020\U0000231a", {32, 8986}, {1, 2}}, + {L"\U00000020\U00000308\U0000231a", {32, 8986}, {2, 3}}, + {L"\U00000020\U00000300", {32}, {2}}, + {L"\U00000020\U00000308\U00000300", {32}, {3}}, + {L"\U00000020\U0000200d", {32}, {2}}, + {L"\U00000020\U00000308\U0000200d", {32}, {3}}, + {L"\U00000020\U00000378", {32, 888}, {1, 2}}, + {L"\U00000020\U00000308\U00000378", {32, 888}, {2, 3}}, + {L"\U0000000d\U00000020", {13, 32}, {1, 2}}, + {L"\U0000000d\U00000308\U00000020", {13, 776, 32}, {1, 2, 3}}, + {L"\U0000000d\U0000000d", {13, 13}, {1, 2}}, + {L"\U0000000d\U00000308\U0000000d", {13, 776, 13}, {1, 2, 3}}, + {L"\U0000000d\U0000000a", {13}, {2}}, + {L"\U0000000d\U00000308\U0000000a", {13, 776, 10}, {1, 2, 3}}, + {L"\U0000000d\U00000001", {13, 1}, {1, 2}}, + {L"\U0000000d\U00000308\U00000001", {13, 776, 1}, {1, 2, 3}}, + {L"\U0000000d\U0000034f", {13, 847}, {1, 2}}, + {L"\U0000000d\U00000308\U0000034f", {13, 776}, {1, 3}}, + {L"\U0000000d\U0001f1e6", {13, 127462}, {1, 2}}, + {L"\U0000000d\U00000308\U0001f1e6", {13, 776, 127462}, {1, 2, 3}}, + {L"\U0000000d\U00000600", {13, 1536}, {1, 2}}, + {L"\U0000000d\U00000308\U00000600", {13, 776, 1536}, {1, 2, 3}}, + {L"\U0000000d\U00000903", {13, 2307}, {1, 2}}, + {L"\U0000000d\U00000308\U00000903", {13, 776}, {1, 3}}, + {L"\U0000000d\U00001100", {13, 4352}, {1, 2}}, + {L"\U0000000d\U00000308\U00001100", {13, 776, 4352}, {1, 2, 3}}, + {L"\U0000000d\U00001160", {13, 4448}, {1, 2}}, + {L"\U0000000d\U00000308\U00001160", {13, 776, 4448}, {1, 2, 3}}, + {L"\U0000000d\U000011a8", {13, 4520}, {1, 2}}, + {L"\U0000000d\U00000308\U000011a8", {13, 776, 4520}, {1, 2, 3}}, + {L"\U0000000d\U0000ac00", {13, 44032}, {1, 2}}, + {L"\U0000000d\U00000308\U0000ac00", {13, 776, 44032}, {1, 2, 3}}, + {L"\U0000000d\U0000ac01", {13, 44033}, {1, 2}}, + {L"\U0000000d\U00000308\U0000ac01", {13, 776, 44033}, {1, 2, 3}}, + {L"\U0000000d\U0000231a", {13, 8986}, {1, 2}}, + {L"\U0000000d\U00000308\U0000231a", {13, 776, 8986}, {1, 2, 3}}, + {L"\U0000000d\U00000300", {13, 768}, {1, 2}}, + {L"\U0000000d\U00000308\U00000300", {13, 776}, {1, 3}}, + {L"\U0000000d\U0000200d", {13, 8205}, {1, 2}}, + {L"\U0000000d\U00000308\U0000200d", {13, 776}, {1, 3}}, + {L"\U0000000d\U00000378", {13, 888}, {1, 2}}, + {L"\U0000000d\U00000308\U00000378", {13, 776, 888}, {1, 2, 3}}, + {L"\U0000000a\U00000020", {10, 32}, {1, 2}}, + {L"\U0000000a\U00000308\U00000020", {10, 776, 32}, {1, 2, 3}}, + {L"\U0000000a\U0000000d", {10, 13}, {1, 2}}, + {L"\U0000000a\U00000308\U0000000d", {10, 776, 13}, {1, 2, 3}}, + {L"\U0000000a\U0000000a", {10, 10}, {1, 2}}, + {L"\U0000000a\U00000308\U0000000a", {10, 776, 10}, {1, 2, 3}}, + {L"\U0000000a\U00000001", {10, 1}, {1, 2}}, + {L"\U0000000a\U00000308\U00000001", {10, 776, 1}, {1, 2, 3}}, + {L"\U0000000a\U0000034f", {10, 847}, {1, 2}}, + {L"\U0000000a\U00000308\U0000034f", {10, 776}, {1, 3}}, + {L"\U0000000a\U0001f1e6", {10, 127462}, {1, 2}}, + {L"\U0000000a\U00000308\U0001f1e6", {10, 776, 127462}, {1, 2, 3}}, + {L"\U0000000a\U00000600", {10, 1536}, {1, 2}}, + {L"\U0000000a\U00000308\U00000600", {10, 776, 1536}, {1, 2, 3}}, + {L"\U0000000a\U00000903", {10, 2307}, {1, 2}}, + {L"\U0000000a\U00000308\U00000903", {10, 776}, {1, 3}}, + {L"\U0000000a\U00001100", {10, 4352}, {1, 2}}, + {L"\U0000000a\U00000308\U00001100", {10, 776, 4352}, {1, 2, 3}}, + {L"\U0000000a\U00001160", {10, 4448}, {1, 2}}, + {L"\U0000000a\U00000308\U00001160", {10, 776, 4448}, {1, 2, 3}}, + {L"\U0000000a\U000011a8", {10, 4520}, {1, 2}}, + {L"\U0000000a\U00000308\U000011a8", {10, 776, 4520}, {1, 2, 3}}, + {L"\U0000000a\U0000ac00", {10, 44032}, {1, 2}}, + {L"\U0000000a\U00000308\U0000ac00", {10, 776, 44032}, {1, 2, 3}}, + {L"\U0000000a\U0000ac01", {10, 44033}, {1, 2}}, + {L"\U0000000a\U00000308\U0000ac01", {10, 776, 44033}, {1, 2, 3}}, + {L"\U0000000a\U0000231a", {10, 8986}, {1, 2}}, + {L"\U0000000a\U00000308\U0000231a", {10, 776, 8986}, {1, 2, 3}}, + {L"\U0000000a\U00000300", {10, 768}, {1, 2}}, + {L"\U0000000a\U00000308\U00000300", {10, 776}, {1, 3}}, + {L"\U0000000a\U0000200d", {10, 8205}, {1, 2}}, + {L"\U0000000a\U00000308\U0000200d", {10, 776}, {1, 3}}, + {L"\U0000000a\U00000378", {10, 888}, {1, 2}}, + {L"\U0000000a\U00000308\U00000378", {10, 776, 888}, {1, 2, 3}}, + {L"\U00000001\U00000020", {1, 32}, {1, 2}}, + {L"\U00000001\U00000308\U00000020", {1, 776, 32}, {1, 2, 3}}, + {L"\U00000001\U0000000d", {1, 13}, {1, 2}}, + {L"\U00000001\U00000308\U0000000d", {1, 776, 13}, {1, 2, 3}}, + {L"\U00000001\U0000000a", {1, 10}, {1, 2}}, + {L"\U00000001\U00000308\U0000000a", {1, 776, 10}, {1, 2, 3}}, + {L"\U00000001\U00000001", {1, 1}, {1, 2}}, + {L"\U00000001\U00000308\U00000001", {1, 776, 1}, {1, 2, 3}}, + {L"\U00000001\U0000034f", {1, 847}, {1, 2}}, + {L"\U00000001\U00000308\U0000034f", {1, 776}, {1, 3}}, + {L"\U00000001\U0001f1e6", {1, 127462}, {1, 2}}, + {L"\U00000001\U00000308\U0001f1e6", {1, 776, 127462}, {1, 2, 3}}, + {L"\U00000001\U00000600", {1, 1536}, {1, 2}}, + {L"\U00000001\U00000308\U00000600", {1, 776, 1536}, {1, 2, 3}}, + {L"\U00000001\U00000903", {1, 2307}, {1, 2}}, + {L"\U00000001\U00000308\U00000903", {1, 776}, {1, 3}}, + {L"\U00000001\U00001100", {1, 4352}, {1, 2}}, + {L"\U00000001\U00000308\U00001100", {1, 776, 4352}, {1, 2, 3}}, + {L"\U00000001\U00001160", {1, 4448}, {1, 2}}, + {L"\U00000001\U00000308\U00001160", {1, 776, 4448}, {1, 2, 3}}, + {L"\U00000001\U000011a8", {1, 4520}, {1, 2}}, + {L"\U00000001\U00000308\U000011a8", {1, 776, 4520}, {1, 2, 3}}, + {L"\U00000001\U0000ac00", {1, 44032}, {1, 2}}, + {L"\U00000001\U00000308\U0000ac00", {1, 776, 44032}, {1, 2, 3}}, + {L"\U00000001\U0000ac01", {1, 44033}, {1, 2}}, + {L"\U00000001\U00000308\U0000ac01", {1, 776, 44033}, {1, 2, 3}}, + {L"\U00000001\U0000231a", {1, 8986}, {1, 2}}, + {L"\U00000001\U00000308\U0000231a", {1, 776, 8986}, {1, 2, 3}}, + {L"\U00000001\U00000300", {1, 768}, {1, 2}}, + {L"\U00000001\U00000308\U00000300", {1, 776}, {1, 3}}, + {L"\U00000001\U0000200d", {1, 8205}, {1, 2}}, + {L"\U00000001\U00000308\U0000200d", {1, 776}, {1, 3}}, + {L"\U00000001\U00000378", {1, 888}, {1, 2}}, + {L"\U00000001\U00000308\U00000378", {1, 776, 888}, {1, 2, 3}}, + {L"\U0000034f\U00000020", {847, 32}, {1, 2}}, + {L"\U0000034f\U00000308\U00000020", {847, 32}, {2, 3}}, + {L"\U0000034f\U0000000d", {847, 13}, {1, 2}}, + {L"\U0000034f\U00000308\U0000000d", {847, 13}, {2, 3}}, + {L"\U0000034f\U0000000a", {847, 10}, {1, 2}}, + {L"\U0000034f\U00000308\U0000000a", {847, 10}, {2, 3}}, + {L"\U0000034f\U00000001", {847, 1}, {1, 2}}, + {L"\U0000034f\U00000308\U00000001", {847, 1}, {2, 3}}, + {L"\U0000034f\U0000034f", {847}, {2}}, + {L"\U0000034f\U00000308\U0000034f", {847}, {3}}, + {L"\U0000034f\U0001f1e6", {847, 127462}, {1, 2}}, + {L"\U0000034f\U00000308\U0001f1e6", {847, 127462}, {2, 3}}, + {L"\U0000034f\U00000600", {847, 1536}, {1, 2}}, + {L"\U0000034f\U00000308\U00000600", {847, 1536}, {2, 3}}, + {L"\U0000034f\U00000903", {847}, {2}}, + {L"\U0000034f\U00000308\U00000903", {847}, {3}}, + {L"\U0000034f\U00001100", {847, 4352}, {1, 2}}, + {L"\U0000034f\U00000308\U00001100", {847, 4352}, {2, 3}}, + {L"\U0000034f\U00001160", {847, 4448}, {1, 2}}, + {L"\U0000034f\U00000308\U00001160", {847, 4448}, {2, 3}}, + {L"\U0000034f\U000011a8", {847, 4520}, {1, 2}}, + {L"\U0000034f\U00000308\U000011a8", {847, 4520}, {2, 3}}, + {L"\U0000034f\U0000ac00", {847, 44032}, {1, 2}}, + {L"\U0000034f\U00000308\U0000ac00", {847, 44032}, {2, 3}}, + {L"\U0000034f\U0000ac01", {847, 44033}, {1, 2}}, + {L"\U0000034f\U00000308\U0000ac01", {847, 44033}, {2, 3}}, + {L"\U0000034f\U0000231a", {847, 8986}, {1, 2}}, + {L"\U0000034f\U00000308\U0000231a", {847, 8986}, {2, 3}}, + {L"\U0000034f\U00000300", {847}, {2}}, + {L"\U0000034f\U00000308\U00000300", {847}, {3}}, + {L"\U0000034f\U0000200d", {847}, {2}}, + {L"\U0000034f\U00000308\U0000200d", {847}, {3}}, + {L"\U0000034f\U00000378", {847, 888}, {1, 2}}, + {L"\U0000034f\U00000308\U00000378", {847, 888}, {2, 3}}, + {L"\U0001f1e6\U00000020", {127462, 32}, {1, 2}}, + {L"\U0001f1e6\U00000308\U00000020", {127462, 32}, {2, 3}}, + {L"\U0001f1e6\U0000000d", {127462, 13}, {1, 2}}, + {L"\U0001f1e6\U00000308\U0000000d", {127462, 13}, {2, 3}}, + {L"\U0001f1e6\U0000000a", {127462, 10}, {1, 2}}, + {L"\U0001f1e6\U00000308\U0000000a", {127462, 10}, {2, 3}}, + {L"\U0001f1e6\U00000001", {127462, 1}, {1, 2}}, + {L"\U0001f1e6\U00000308\U00000001", {127462, 1}, {2, 3}}, + {L"\U0001f1e6\U0000034f", {127462}, {2}}, + {L"\U0001f1e6\U00000308\U0000034f", {127462}, {3}}, + {L"\U0001f1e6\U0001f1e6", {127462}, {2}}, + {L"\U0001f1e6\U00000308\U0001f1e6", {127462, 127462}, {2, 3}}, + {L"\U0001f1e6\U00000600", {127462, 1536}, {1, 2}}, + {L"\U0001f1e6\U00000308\U00000600", {127462, 1536}, {2, 3}}, + {L"\U0001f1e6\U00000903", {127462}, {2}}, + {L"\U0001f1e6\U00000308\U00000903", {127462}, {3}}, + {L"\U0001f1e6\U00001100", {127462, 4352}, {1, 2}}, + {L"\U0001f1e6\U00000308\U00001100", {127462, 4352}, {2, 3}}, + {L"\U0001f1e6\U00001160", {127462, 4448}, {1, 2}}, + {L"\U0001f1e6\U00000308\U00001160", {127462, 4448}, {2, 3}}, + {L"\U0001f1e6\U000011a8", {127462, 4520}, {1, 2}}, + {L"\U0001f1e6\U00000308\U000011a8", {127462, 4520}, {2, 3}}, + {L"\U0001f1e6\U0000ac00", {127462, 44032}, {1, 2}}, + {L"\U0001f1e6\U00000308\U0000ac00", {127462, 44032}, {2, 3}}, + {L"\U0001f1e6\U0000ac01", {127462, 44033}, {1, 2}}, + {L"\U0001f1e6\U00000308\U0000ac01", {127462, 44033}, {2, 3}}, + {L"\U0001f1e6\U0000231a", {127462, 8986}, {1, 2}}, + {L"\U0001f1e6\U00000308\U0000231a", {127462, 8986}, {2, 3}}, + {L"\U0001f1e6\U00000300", {127462}, {2}}, + {L"\U0001f1e6\U00000308\U00000300", {127462}, {3}}, + {L"\U0001f1e6\U0000200d", {127462}, {2}}, + {L"\U0001f1e6\U00000308\U0000200d", {127462}, {3}}, + {L"\U0001f1e6\U00000378", {127462, 888}, {1, 2}}, + {L"\U0001f1e6\U00000308\U00000378", {127462, 888}, {2, 3}}, + {L"\U00000600\U00000020", {1536}, {2}}, + {L"\U00000600\U00000308\U00000020", {1536, 32}, {2, 3}}, + {L"\U00000600\U0000000d", {1536, 13}, {1, 2}}, + {L"\U00000600\U00000308\U0000000d", {1536, 13}, {2, 3}}, + {L"\U00000600\U0000000a", {1536, 10}, {1, 2}}, + {L"\U00000600\U00000308\U0000000a", {1536, 10}, {2, 3}}, + {L"\U00000600\U00000001", {1536, 1}, {1, 2}}, + {L"\U00000600\U00000308\U00000001", {1536, 1}, {2, 3}}, + {L"\U00000600\U0000034f", {1536}, {2}}, + {L"\U00000600\U00000308\U0000034f", {1536}, {3}}, + {L"\U00000600\U0001f1e6", {1536}, {2}}, + {L"\U00000600\U00000308\U0001f1e6", {1536, 127462}, {2, 3}}, + {L"\U00000600\U00000600", {1536}, {2}}, + {L"\U00000600\U00000308\U00000600", {1536, 1536}, {2, 3}}, + {L"\U00000600\U00000903", {1536}, {2}}, + {L"\U00000600\U00000308\U00000903", {1536}, {3}}, + {L"\U00000600\U00001100", {1536}, {2}}, + {L"\U00000600\U00000308\U00001100", {1536, 4352}, {2, 3}}, + {L"\U00000600\U00001160", {1536}, {2}}, + {L"\U00000600\U00000308\U00001160", {1536, 4448}, {2, 3}}, + {L"\U00000600\U000011a8", {1536}, {2}}, + {L"\U00000600\U00000308\U000011a8", {1536, 4520}, {2, 3}}, + {L"\U00000600\U0000ac00", {1536}, {2}}, + {L"\U00000600\U00000308\U0000ac00", {1536, 44032}, {2, 3}}, + {L"\U00000600\U0000ac01", {1536}, {2}}, + {L"\U00000600\U00000308\U0000ac01", {1536, 44033}, {2, 3}}, + {L"\U00000600\U0000231a", {1536}, {2}}, + {L"\U00000600\U00000308\U0000231a", {1536, 8986}, {2, 3}}, + {L"\U00000600\U00000300", {1536}, {2}}, + {L"\U00000600\U00000308\U00000300", {1536}, {3}}, + {L"\U00000600\U0000200d", {1536}, {2}}, + {L"\U00000600\U00000308\U0000200d", {1536}, {3}}, + {L"\U00000600\U00000378", {1536}, {2}}, + {L"\U00000600\U00000308\U00000378", {1536, 888}, {2, 3}}, + {L"\U00000903\U00000020", {2307, 32}, {1, 2}}, + {L"\U00000903\U00000308\U00000020", {2307, 32}, {2, 3}}, + {L"\U00000903\U0000000d", {2307, 13}, {1, 2}}, + {L"\U00000903\U00000308\U0000000d", {2307, 13}, {2, 3}}, + {L"\U00000903\U0000000a", {2307, 10}, {1, 2}}, + {L"\U00000903\U00000308\U0000000a", {2307, 10}, {2, 3}}, + {L"\U00000903\U00000001", {2307, 1}, {1, 2}}, + {L"\U00000903\U00000308\U00000001", {2307, 1}, {2, 3}}, + {L"\U00000903\U0000034f", {2307}, {2}}, + {L"\U00000903\U00000308\U0000034f", {2307}, {3}}, + {L"\U00000903\U0001f1e6", {2307, 127462}, {1, 2}}, + {L"\U00000903\U00000308\U0001f1e6", {2307, 127462}, {2, 3}}, + {L"\U00000903\U00000600", {2307, 1536}, {1, 2}}, + {L"\U00000903\U00000308\U00000600", {2307, 1536}, {2, 3}}, + {L"\U00000903\U00000903", {2307}, {2}}, + {L"\U00000903\U00000308\U00000903", {2307}, {3}}, + {L"\U00000903\U00001100", {2307, 4352}, {1, 2}}, + {L"\U00000903\U00000308\U00001100", {2307, 4352}, {2, 3}}, + {L"\U00000903\U00001160", {2307, 4448}, {1, 2}}, + {L"\U00000903\U00000308\U00001160", {2307, 4448}, {2, 3}}, + {L"\U00000903\U000011a8", {2307, 4520}, {1, 2}}, + {L"\U00000903\U00000308\U000011a8", {2307, 4520}, {2, 3}}, + {L"\U00000903\U0000ac00", {2307, 44032}, {1, 2}}, + {L"\U00000903\U00000308\U0000ac00", {2307, 44032}, {2, 3}}, + {L"\U00000903\U0000ac01", {2307, 44033}, {1, 2}}, + {L"\U00000903\U00000308\U0000ac01", {2307, 44033}, {2, 3}}, + {L"\U00000903\U0000231a", {2307, 8986}, {1, 2}}, + {L"\U00000903\U00000308\U0000231a", {2307, 8986}, {2, 3}}, + {L"\U00000903\U00000300", {2307}, {2}}, + {L"\U00000903\U00000308\U00000300", {2307}, {3}}, + {L"\U00000903\U0000200d", {2307}, {2}}, + {L"\U00000903\U00000308\U0000200d", {2307}, {3}}, + {L"\U00000903\U00000378", {2307, 888}, {1, 2}}, + {L"\U00000903\U00000308\U00000378", {2307, 888}, {2, 3}}, + {L"\U00001100\U00000020", {4352, 32}, {1, 2}}, + {L"\U00001100\U00000308\U00000020", {4352, 32}, {2, 3}}, + {L"\U00001100\U0000000d", {4352, 13}, {1, 2}}, + {L"\U00001100\U00000308\U0000000d", {4352, 13}, {2, 3}}, + {L"\U00001100\U0000000a", {4352, 10}, {1, 2}}, + {L"\U00001100\U00000308\U0000000a", {4352, 10}, {2, 3}}, + {L"\U00001100\U00000001", {4352, 1}, {1, 2}}, + {L"\U00001100\U00000308\U00000001", {4352, 1}, {2, 3}}, + {L"\U00001100\U0000034f", {4352}, {2}}, + {L"\U00001100\U00000308\U0000034f", {4352}, {3}}, + {L"\U00001100\U0001f1e6", {4352, 127462}, {1, 2}}, + {L"\U00001100\U00000308\U0001f1e6", {4352, 127462}, {2, 3}}, + {L"\U00001100\U00000600", {4352, 1536}, {1, 2}}, + {L"\U00001100\U00000308\U00000600", {4352, 1536}, {2, 3}}, + {L"\U00001100\U00000903", {4352}, {2}}, + {L"\U00001100\U00000308\U00000903", {4352}, {3}}, + {L"\U00001100\U00001100", {4352}, {2}}, + {L"\U00001100\U00000308\U00001100", {4352, 4352}, {2, 3}}, + {L"\U00001100\U00001160", {4352}, {2}}, + {L"\U00001100\U00000308\U00001160", {4352, 4448}, {2, 3}}, + {L"\U00001100\U000011a8", {4352, 4520}, {1, 2}}, + {L"\U00001100\U00000308\U000011a8", {4352, 4520}, {2, 3}}, + {L"\U00001100\U0000ac00", {4352}, {2}}, + {L"\U00001100\U00000308\U0000ac00", {4352, 44032}, {2, 3}}, + {L"\U00001100\U0000ac01", {4352}, {2}}, + {L"\U00001100\U00000308\U0000ac01", {4352, 44033}, {2, 3}}, + {L"\U00001100\U0000231a", {4352, 8986}, {1, 2}}, + {L"\U00001100\U00000308\U0000231a", {4352, 8986}, {2, 3}}, + {L"\U00001100\U00000300", {4352}, {2}}, + {L"\U00001100\U00000308\U00000300", {4352}, {3}}, + {L"\U00001100\U0000200d", {4352}, {2}}, + {L"\U00001100\U00000308\U0000200d", {4352}, {3}}, + {L"\U00001100\U00000378", {4352, 888}, {1, 2}}, + {L"\U00001100\U00000308\U00000378", {4352, 888}, {2, 3}}, + {L"\U00001160\U00000020", {4448, 32}, {1, 2}}, + {L"\U00001160\U00000308\U00000020", {4448, 32}, {2, 3}}, + {L"\U00001160\U0000000d", {4448, 13}, {1, 2}}, + {L"\U00001160\U00000308\U0000000d", {4448, 13}, {2, 3}}, + {L"\U00001160\U0000000a", {4448, 10}, {1, 2}}, + {L"\U00001160\U00000308\U0000000a", {4448, 10}, {2, 3}}, + {L"\U00001160\U00000001", {4448, 1}, {1, 2}}, + {L"\U00001160\U00000308\U00000001", {4448, 1}, {2, 3}}, + {L"\U00001160\U0000034f", {4448}, {2}}, + {L"\U00001160\U00000308\U0000034f", {4448}, {3}}, + {L"\U00001160\U0001f1e6", {4448, 127462}, {1, 2}}, + {L"\U00001160\U00000308\U0001f1e6", {4448, 127462}, {2, 3}}, + {L"\U00001160\U00000600", {4448, 1536}, {1, 2}}, + {L"\U00001160\U00000308\U00000600", {4448, 1536}, {2, 3}}, + {L"\U00001160\U00000903", {4448}, {2}}, + {L"\U00001160\U00000308\U00000903", {4448}, {3}}, + {L"\U00001160\U00001100", {4448, 4352}, {1, 2}}, + {L"\U00001160\U00000308\U00001100", {4448, 4352}, {2, 3}}, + {L"\U00001160\U00001160", {4448}, {2}}, + {L"\U00001160\U00000308\U00001160", {4448, 4448}, {2, 3}}, + {L"\U00001160\U000011a8", {4448}, {2}}, + {L"\U00001160\U00000308\U000011a8", {4448, 4520}, {2, 3}}, + {L"\U00001160\U0000ac00", {4448, 44032}, {1, 2}}, + {L"\U00001160\U00000308\U0000ac00", {4448, 44032}, {2, 3}}, + {L"\U00001160\U0000ac01", {4448, 44033}, {1, 2}}, + {L"\U00001160\U00000308\U0000ac01", {4448, 44033}, {2, 3}}, + {L"\U00001160\U0000231a", {4448, 8986}, {1, 2}}, + {L"\U00001160\U00000308\U0000231a", {4448, 8986}, {2, 3}}, + {L"\U00001160\U00000300", {4448}, {2}}, + {L"\U00001160\U00000308\U00000300", {4448}, {3}}, + {L"\U00001160\U0000200d", {4448}, {2}}, + {L"\U00001160\U00000308\U0000200d", {4448}, {3}}, + {L"\U00001160\U00000378", {4448, 888}, {1, 2}}, + {L"\U00001160\U00000308\U00000378", {4448, 888}, {2, 3}}, + {L"\U000011a8\U00000020", {4520, 32}, {1, 2}}, + {L"\U000011a8\U00000308\U00000020", {4520, 32}, {2, 3}}, + {L"\U000011a8\U0000000d", {4520, 13}, {1, 2}}, + {L"\U000011a8\U00000308\U0000000d", {4520, 13}, {2, 3}}, + {L"\U000011a8\U0000000a", {4520, 10}, {1, 2}}, + {L"\U000011a8\U00000308\U0000000a", {4520, 10}, {2, 3}}, + {L"\U000011a8\U00000001", {4520, 1}, {1, 2}}, + {L"\U000011a8\U00000308\U00000001", {4520, 1}, {2, 3}}, + {L"\U000011a8\U0000034f", {4520}, {2}}, + {L"\U000011a8\U00000308\U0000034f", {4520}, {3}}, + {L"\U000011a8\U0001f1e6", {4520, 127462}, {1, 2}}, + {L"\U000011a8\U00000308\U0001f1e6", {4520, 127462}, {2, 3}}, + {L"\U000011a8\U00000600", {4520, 1536}, {1, 2}}, + {L"\U000011a8\U00000308\U00000600", {4520, 1536}, {2, 3}}, + {L"\U000011a8\U00000903", {4520}, {2}}, + {L"\U000011a8\U00000308\U00000903", {4520}, {3}}, + {L"\U000011a8\U00001100", {4520, 4352}, {1, 2}}, + {L"\U000011a8\U00000308\U00001100", {4520, 4352}, {2, 3}}, + {L"\U000011a8\U00001160", {4520, 4448}, {1, 2}}, + {L"\U000011a8\U00000308\U00001160", {4520, 4448}, {2, 3}}, + {L"\U000011a8\U000011a8", {4520}, {2}}, + {L"\U000011a8\U00000308\U000011a8", {4520, 4520}, {2, 3}}, + {L"\U000011a8\U0000ac00", {4520, 44032}, {1, 2}}, + {L"\U000011a8\U00000308\U0000ac00", {4520, 44032}, {2, 3}}, + {L"\U000011a8\U0000ac01", {4520, 44033}, {1, 2}}, + {L"\U000011a8\U00000308\U0000ac01", {4520, 44033}, {2, 3}}, + {L"\U000011a8\U0000231a", {4520, 8986}, {1, 2}}, + {L"\U000011a8\U00000308\U0000231a", {4520, 8986}, {2, 3}}, + {L"\U000011a8\U00000300", {4520}, {2}}, + {L"\U000011a8\U00000308\U00000300", {4520}, {3}}, + {L"\U000011a8\U0000200d", {4520}, {2}}, + {L"\U000011a8\U00000308\U0000200d", {4520}, {3}}, + {L"\U000011a8\U00000378", {4520, 888}, {1, 2}}, + {L"\U000011a8\U00000308\U00000378", {4520, 888}, {2, 3}}, + {L"\U0000ac00\U00000020", {44032, 32}, {1, 2}}, + {L"\U0000ac00\U00000308\U00000020", {44032, 32}, {2, 3}}, + {L"\U0000ac00\U0000000d", {44032, 13}, {1, 2}}, + {L"\U0000ac00\U00000308\U0000000d", {44032, 13}, {2, 3}}, + {L"\U0000ac00\U0000000a", {44032, 10}, {1, 2}}, + {L"\U0000ac00\U00000308\U0000000a", {44032, 10}, {2, 3}}, + {L"\U0000ac00\U00000001", {44032, 1}, {1, 2}}, + {L"\U0000ac00\U00000308\U00000001", {44032, 1}, {2, 3}}, + {L"\U0000ac00\U0000034f", {44032}, {2}}, + {L"\U0000ac00\U00000308\U0000034f", {44032}, {3}}, + {L"\U0000ac00\U0001f1e6", {44032, 127462}, {1, 2}}, + {L"\U0000ac00\U00000308\U0001f1e6", {44032, 127462}, {2, 3}}, + {L"\U0000ac00\U00000600", {44032, 1536}, {1, 2}}, + {L"\U0000ac00\U00000308\U00000600", {44032, 1536}, {2, 3}}, + {L"\U0000ac00\U00000903", {44032}, {2}}, + {L"\U0000ac00\U00000308\U00000903", {44032}, {3}}, + {L"\U0000ac00\U00001100", {44032, 4352}, {1, 2}}, + {L"\U0000ac00\U00000308\U00001100", {44032, 4352}, {2, 3}}, + {L"\U0000ac00\U00001160", {44032}, {2}}, + {L"\U0000ac00\U00000308\U00001160", {44032, 4448}, {2, 3}}, + {L"\U0000ac00\U000011a8", {44032}, {2}}, + {L"\U0000ac00\U00000308\U000011a8", {44032, 4520}, {2, 3}}, + {L"\U0000ac00\U0000ac00", {44032, 44032}, {1, 2}}, + {L"\U0000ac00\U00000308\U0000ac00", {44032, 44032}, {2, 3}}, + {L"\U0000ac00\U0000ac01", {44032, 44033}, {1, 2}}, + {L"\U0000ac00\U00000308\U0000ac01", {44032, 44033}, {2, 3}}, + {L"\U0000ac00\U0000231a", {44032, 8986}, {1, 2}}, + {L"\U0000ac00\U00000308\U0000231a", {44032, 8986}, {2, 3}}, + {L"\U0000ac00\U00000300", {44032}, {2}}, + {L"\U0000ac00\U00000308\U00000300", {44032}, {3}}, + {L"\U0000ac00\U0000200d", {44032}, {2}}, + {L"\U0000ac00\U00000308\U0000200d", {44032}, {3}}, + {L"\U0000ac00\U00000378", {44032, 888}, {1, 2}}, + {L"\U0000ac00\U00000308\U00000378", {44032, 888}, {2, 3}}, + {L"\U0000ac01\U00000020", {44033, 32}, {1, 2}}, + {L"\U0000ac01\U00000308\U00000020", {44033, 32}, {2, 3}}, + {L"\U0000ac01\U0000000d", {44033, 13}, {1, 2}}, + {L"\U0000ac01\U00000308\U0000000d", {44033, 13}, {2, 3}}, + {L"\U0000ac01\U0000000a", {44033, 10}, {1, 2}}, + {L"\U0000ac01\U00000308\U0000000a", {44033, 10}, {2, 3}}, + {L"\U0000ac01\U00000001", {44033, 1}, {1, 2}}, + {L"\U0000ac01\U00000308\U00000001", {44033, 1}, {2, 3}}, + {L"\U0000ac01\U0000034f", {44033}, {2}}, + {L"\U0000ac01\U00000308\U0000034f", {44033}, {3}}, + {L"\U0000ac01\U0001f1e6", {44033, 127462}, {1, 2}}, + {L"\U0000ac01\U00000308\U0001f1e6", {44033, 127462}, {2, 3}}, + {L"\U0000ac01\U00000600", {44033, 1536}, {1, 2}}, + {L"\U0000ac01\U00000308\U00000600", {44033, 1536}, {2, 3}}, + {L"\U0000ac01\U00000903", {44033}, {2}}, + {L"\U0000ac01\U00000308\U00000903", {44033}, {3}}, + {L"\U0000ac01\U00001100", {44033, 4352}, {1, 2}}, + {L"\U0000ac01\U00000308\U00001100", {44033, 4352}, {2, 3}}, + {L"\U0000ac01\U00001160", {44033, 4448}, {1, 2}}, + {L"\U0000ac01\U00000308\U00001160", {44033, 4448}, {2, 3}}, + {L"\U0000ac01\U000011a8", {44033}, {2}}, + {L"\U0000ac01\U00000308\U000011a8", {44033, 4520}, {2, 3}}, + {L"\U0000ac01\U0000ac00", {44033, 44032}, {1, 2}}, + {L"\U0000ac01\U00000308\U0000ac00", {44033, 44032}, {2, 3}}, + {L"\U0000ac01\U0000ac01", {44033, 44033}, {1, 2}}, + {L"\U0000ac01\U00000308\U0000ac01", {44033, 44033}, {2, 3}}, + {L"\U0000ac01\U0000231a", {44033, 8986}, {1, 2}}, + {L"\U0000ac01\U00000308\U0000231a", {44033, 8986}, {2, 3}}, + {L"\U0000ac01\U00000300", {44033}, {2}}, + {L"\U0000ac01\U00000308\U00000300", {44033}, {3}}, + {L"\U0000ac01\U0000200d", {44033}, {2}}, + {L"\U0000ac01\U00000308\U0000200d", {44033}, {3}}, + {L"\U0000ac01\U00000378", {44033, 888}, {1, 2}}, + {L"\U0000ac01\U00000308\U00000378", {44033, 888}, {2, 3}}, + {L"\U0000231a\U00000020", {8986, 32}, {1, 2}}, + {L"\U0000231a\U00000308\U00000020", {8986, 32}, {2, 3}}, + {L"\U0000231a\U0000000d", {8986, 13}, {1, 2}}, + {L"\U0000231a\U00000308\U0000000d", {8986, 13}, {2, 3}}, + {L"\U0000231a\U0000000a", {8986, 10}, {1, 2}}, + {L"\U0000231a\U00000308\U0000000a", {8986, 10}, {2, 3}}, + {L"\U0000231a\U00000001", {8986, 1}, {1, 2}}, + {L"\U0000231a\U00000308\U00000001", {8986, 1}, {2, 3}}, + {L"\U0000231a\U0000034f", {8986}, {2}}, + {L"\U0000231a\U00000308\U0000034f", {8986}, {3}}, + {L"\U0000231a\U0001f1e6", {8986, 127462}, {1, 2}}, + {L"\U0000231a\U00000308\U0001f1e6", {8986, 127462}, {2, 3}}, + {L"\U0000231a\U00000600", {8986, 1536}, {1, 2}}, + {L"\U0000231a\U00000308\U00000600", {8986, 1536}, {2, 3}}, + {L"\U0000231a\U00000903", {8986}, {2}}, + {L"\U0000231a\U00000308\U00000903", {8986}, {3}}, + {L"\U0000231a\U00001100", {8986, 4352}, {1, 2}}, + {L"\U0000231a\U00000308\U00001100", {8986, 4352}, {2, 3}}, + {L"\U0000231a\U00001160", {8986, 4448}, {1, 2}}, + {L"\U0000231a\U00000308\U00001160", {8986, 4448}, {2, 3}}, + {L"\U0000231a\U000011a8", {8986, 4520}, {1, 2}}, + {L"\U0000231a\U00000308\U000011a8", {8986, 4520}, {2, 3}}, + {L"\U0000231a\U0000ac00", {8986, 44032}, {1, 2}}, + {L"\U0000231a\U00000308\U0000ac00", {8986, 44032}, {2, 3}}, + {L"\U0000231a\U0000ac01", {8986, 44033}, {1, 2}}, + {L"\U0000231a\U00000308\U0000ac01", {8986, 44033}, {2, 3}}, + {L"\U0000231a\U0000231a", {8986, 8986}, {1, 2}}, + {L"\U0000231a\U00000308\U0000231a", {8986, 8986}, {2, 3}}, + {L"\U0000231a\U00000300", {8986}, {2}}, + {L"\U0000231a\U00000308\U00000300", {8986}, {3}}, + {L"\U0000231a\U0000200d", {8986}, {2}}, + {L"\U0000231a\U00000308\U0000200d", {8986}, {3}}, + {L"\U0000231a\U00000378", {8986, 888}, {1, 2}}, + {L"\U0000231a\U00000308\U00000378", {8986, 888}, {2, 3}}, + {L"\U00000300\U00000020", {768, 32}, {1, 2}}, + {L"\U00000300\U00000308\U00000020", {768, 32}, {2, 3}}, + {L"\U00000300\U0000000d", {768, 13}, {1, 2}}, + {L"\U00000300\U00000308\U0000000d", {768, 13}, {2, 3}}, + {L"\U00000300\U0000000a", {768, 10}, {1, 2}}, + {L"\U00000300\U00000308\U0000000a", {768, 10}, {2, 3}}, + {L"\U00000300\U00000001", {768, 1}, {1, 2}}, + {L"\U00000300\U00000308\U00000001", {768, 1}, {2, 3}}, + {L"\U00000300\U0000034f", {768}, {2}}, + {L"\U00000300\U00000308\U0000034f", {768}, {3}}, + {L"\U00000300\U0001f1e6", {768, 127462}, {1, 2}}, + {L"\U00000300\U00000308\U0001f1e6", {768, 127462}, {2, 3}}, + {L"\U00000300\U00000600", {768, 1536}, {1, 2}}, + {L"\U00000300\U00000308\U00000600", {768, 1536}, {2, 3}}, + {L"\U00000300\U00000903", {768}, {2}}, + {L"\U00000300\U00000308\U00000903", {768}, {3}}, + {L"\U00000300\U00001100", {768, 4352}, {1, 2}}, + {L"\U00000300\U00000308\U00001100", {768, 4352}, {2, 3}}, + {L"\U00000300\U00001160", {768, 4448}, {1, 2}}, + {L"\U00000300\U00000308\U00001160", {768, 4448}, {2, 3}}, + {L"\U00000300\U000011a8", {768, 4520}, {1, 2}}, + {L"\U00000300\U00000308\U000011a8", {768, 4520}, {2, 3}}, + {L"\U00000300\U0000ac00", {768, 44032}, {1, 2}}, + {L"\U00000300\U00000308\U0000ac00", {768, 44032}, {2, 3}}, + {L"\U00000300\U0000ac01", {768, 44033}, {1, 2}}, + {L"\U00000300\U00000308\U0000ac01", {768, 44033}, {2, 3}}, + {L"\U00000300\U0000231a", {768, 8986}, {1, 2}}, + {L"\U00000300\U00000308\U0000231a", {768, 8986}, {2, 3}}, + {L"\U00000300\U00000300", {768}, {2}}, + {L"\U00000300\U00000308\U00000300", {768}, {3}}, + {L"\U00000300\U0000200d", {768}, {2}}, + {L"\U00000300\U00000308\U0000200d", {768}, {3}}, + {L"\U00000300\U00000378", {768, 888}, {1, 2}}, + {L"\U00000300\U00000308\U00000378", {768, 888}, {2, 3}}, + {L"\U0000200d\U00000020", {8205, 32}, {1, 2}}, + {L"\U0000200d\U00000308\U00000020", {8205, 32}, {2, 3}}, + {L"\U0000200d\U0000000d", {8205, 13}, {1, 2}}, + {L"\U0000200d\U00000308\U0000000d", {8205, 13}, {2, 3}}, + {L"\U0000200d\U0000000a", {8205, 10}, {1, 2}}, + {L"\U0000200d\U00000308\U0000000a", {8205, 10}, {2, 3}}, + {L"\U0000200d\U00000001", {8205, 1}, {1, 2}}, + {L"\U0000200d\U00000308\U00000001", {8205, 1}, {2, 3}}, + {L"\U0000200d\U0000034f", {8205}, {2}}, + {L"\U0000200d\U00000308\U0000034f", {8205}, {3}}, + {L"\U0000200d\U0001f1e6", {8205, 127462}, {1, 2}}, + {L"\U0000200d\U00000308\U0001f1e6", {8205, 127462}, {2, 3}}, + {L"\U0000200d\U00000600", {8205, 1536}, {1, 2}}, + {L"\U0000200d\U00000308\U00000600", {8205, 1536}, {2, 3}}, + {L"\U0000200d\U00000903", {8205}, {2}}, + {L"\U0000200d\U00000308\U00000903", {8205}, {3}}, + {L"\U0000200d\U00001100", {8205, 4352}, {1, 2}}, + {L"\U0000200d\U00000308\U00001100", {8205, 4352}, {2, 3}}, + {L"\U0000200d\U00001160", {8205, 4448}, {1, 2}}, + {L"\U0000200d\U00000308\U00001160", {8205, 4448}, {2, 3}}, + {L"\U0000200d\U000011a8", {8205, 4520}, {1, 2}}, + {L"\U0000200d\U00000308\U000011a8", {8205, 4520}, {2, 3}}, + {L"\U0000200d\U0000ac00", {8205, 44032}, {1, 2}}, + {L"\U0000200d\U00000308\U0000ac00", {8205, 44032}, {2, 3}}, + {L"\U0000200d\U0000ac01", {8205, 44033}, {1, 2}}, + {L"\U0000200d\U00000308\U0000ac01", {8205, 44033}, {2, 3}}, + {L"\U0000200d\U0000231a", {8205, 8986}, {1, 2}}, + {L"\U0000200d\U00000308\U0000231a", {8205, 8986}, {2, 3}}, + {L"\U0000200d\U00000300", {8205}, {2}}, + {L"\U0000200d\U00000308\U00000300", {8205}, {3}}, + {L"\U0000200d\U0000200d", {8205}, {2}}, + {L"\U0000200d\U00000308\U0000200d", {8205}, {3}}, + {L"\U0000200d\U00000378", {8205, 888}, {1, 2}}, + {L"\U0000200d\U00000308\U00000378", {8205, 888}, {2, 3}}, + {L"\U00000378\U00000020", {888, 32}, {1, 2}}, + {L"\U00000378\U00000308\U00000020", {888, 32}, {2, 3}}, + {L"\U00000378\U0000000d", {888, 13}, {1, 2}}, + {L"\U00000378\U00000308\U0000000d", {888, 13}, {2, 3}}, + {L"\U00000378\U0000000a", {888, 10}, {1, 2}}, + {L"\U00000378\U00000308\U0000000a", {888, 10}, {2, 3}}, + {L"\U00000378\U00000001", {888, 1}, {1, 2}}, + {L"\U00000378\U00000308\U00000001", {888, 1}, {2, 3}}, + {L"\U00000378\U0000034f", {888}, {2}}, + {L"\U00000378\U00000308\U0000034f", {888}, {3}}, + {L"\U00000378\U0001f1e6", {888, 127462}, {1, 2}}, + {L"\U00000378\U00000308\U0001f1e6", {888, 127462}, {2, 3}}, + {L"\U00000378\U00000600", {888, 1536}, {1, 2}}, + {L"\U00000378\U00000308\U00000600", {888, 1536}, {2, 3}}, + {L"\U00000378\U00000903", {888}, {2}}, + {L"\U00000378\U00000308\U00000903", {888}, {3}}, + {L"\U00000378\U00001100", {888, 4352}, {1, 2}}, + {L"\U00000378\U00000308\U00001100", {888, 4352}, {2, 3}}, + {L"\U00000378\U00001160", {888, 4448}, {1, 2}}, + {L"\U00000378\U00000308\U00001160", {888, 4448}, {2, 3}}, + {L"\U00000378\U000011a8", {888, 4520}, {1, 2}}, + {L"\U00000378\U00000308\U000011a8", {888, 4520}, {2, 3}}, + {L"\U00000378\U0000ac00", {888, 44032}, {1, 2}}, + {L"\U00000378\U00000308\U0000ac00", {888, 44032}, {2, 3}}, + {L"\U00000378\U0000ac01", {888, 44033}, {1, 2}}, + {L"\U00000378\U00000308\U0000ac01", {888, 44033}, {2, 3}}, + {L"\U00000378\U0000231a", {888, 8986}, {1, 2}}, + {L"\U00000378\U00000308\U0000231a", {888, 8986}, {2, 3}}, + {L"\U00000378\U00000300", {888}, {2}}, + {L"\U00000378\U00000308\U00000300", {888}, {3}}, + {L"\U00000378\U0000200d", {888}, {2}}, + {L"\U00000378\U00000308\U0000200d", {888}, {3}}, + {L"\U00000378\U00000378", {888, 888}, {1, 2}}, + {L"\U00000378\U00000308\U00000378", {888, 888}, {2, 3}}, + {L"\U0000000d\U0000000a\U00000061\U0000000a\U00000308", {13, 97, 10, 776}, {2, 3, 4, 5}}, + {L"\U00000061\U00000308", {97}, {2}}, + {L"\U00000020\U0000200d\U00000646", {32, 1606}, {2, 3}}, + {L"\U00000646\U0000200d\U00000020", {1606, 32}, {2, 3}}, + {L"\U00001100\U00001100", {4352}, {2}}, + {L"\U0000ac00\U000011a8\U00001100", {44032, 4352}, {2, 3}}, + {L"\U0000ac01\U000011a8\U00001100", {44033, 4352}, {2, 3}}, + {L"\U0001f1e6\U0001f1e7\U0001f1e8\U00000062", {127462, 127464, 98}, {2, 3, 4}}, + {L"\U00000061\U0001f1e6\U0001f1e7\U0001f1e8\U00000062", {97, 127462, 127464, 98}, {1, 3, 4, 5}}, + {L"\U00000061\U0001f1e6\U0001f1e7\U0000200d\U0001f1e8\U00000062", {97, 127462, 127464, 98}, {1, 4, 5, 6}}, + {L"\U00000061\U0001f1e6\U0000200d\U0001f1e7\U0001f1e8\U00000062", {97, 127462, 127463, 98}, {1, 3, 5, 6}}, + {L"\U00000061\U0001f1e6\U0001f1e7\U0001f1e8\U0001f1e9\U00000062", {97, 127462, 127464, 98}, {1, 3, 5, 6}}, + {L"\U00000061\U0000200d", {97}, {2}}, + {L"\U00000061\U00000308\U00000062", {97, 98}, {2, 3}}, + {L"\U00000061\U00000903\U00000062", {97, 98}, {2, 3}}, + {L"\U00000061\U00000600\U00000062", {97, 1536}, {1, 3}}, + {L"\U0001f476\U0001f3ff\U0001f476", {128118, 128118}, {2, 3}}, + {L"\U00000061\U0001f3ff\U0001f476", {97, 128118}, {2, 3}}, + {L"\U00000061\U0001f3ff\U0001f476\U0000200d\U0001f6d1", {97, 128118}, {2, 5}}, + {L"\U0001f476\U0001f3ff\U00000308\U0000200d\U0001f476\U0001f3ff", {128118}, {6}}, + {L"\U0001f6d1\U0000200d\U0001f6d1", {128721}, {3}}, + {L"\U00000061\U0000200d\U0001f6d1", {97, 128721}, {2, 3}}, + {L"\U00002701\U0000200d\U00002701", {9985}, {3}}, + {L"\U00000061\U0000200d\U00002701", {97, 9985}, {2, 3}}}}; + +#endif // LIBCXX_TEST_STD_UTILITIES_FORMAT_FORMAT_STRING_FORMAT_STRING_STD_EXTENDED_GRAPHEME_CLUSTER_H diff --git a/libcxx/test/libcxx/utilities/format/format.string/format.string.std/extended_grapheme_cluster.pass.cpp b/libcxx/test/libcxx/utilities/format/format.string/format.string.std/extended_grapheme_cluster.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/utilities/format/format.string/format.string.std/extended_grapheme_cluster.pass.cpp @@ -0,0 +1,91 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-has-no-incomplete-format +// UNSUPPORTED: gcc-11 + +// + +// Tests the implementation of the extended grapheme cluster boundaries per +// https://www.unicode.org/reports/tr29/tr29-35.html#Grapheme_Cluster_Boundary_Rules +// +// The tests are based on the test data provided by Unicode +// http://www.unicode.org/Public/12.0.0/ucd/auxiliary/GraphemeBreakTest.txt + +#include +#include +#include +#include + +#include "extended_grapheme_cluster.h" + +// Validates whether the number of code points in our "database" matches with +// the number in the Unicode. The assumtion is when the number of items per +// property matches the code points themselves also match. +namespace { +namespace cluster = std::__extended_grapheme_custer_property_boundary; +constexpr int count_entries(cluster::__property property) { + return std::transform_reduce(std::begin(cluster::__entries), std::end(cluster::__entries), 0, std::plus{}, + [property](auto entry) { + if (static_cast(entry.__property) != property) + return 0; + + return 1 + entry.__offset; + }); +} + +static_assert(count_entries(cluster::__property::__Prepend) == 22); +static_assert(count_entries(cluster::__property::__CR) == 1); +static_assert(count_entries(cluster::__property::__LF) == 1); +static_assert(count_entries(cluster::__property::__Control) == 3886); +static_assert(count_entries(cluster::__property::__Extend) == 1970); +static_assert(count_entries(cluster::__property::__Regional_Indicator) == 26); +static_assert(count_entries(cluster::__property::__SpacingMark) == 375); +static_assert(count_entries(cluster::__property::__L) == 125); +static_assert(count_entries(cluster::__property::__V) == 95); +static_assert(count_entries(cluster::__property::__T) == 137); +static_assert(count_entries(cluster::__property::__LV) == 399); +static_assert(count_entries(cluster::__property::__LVT) == 10773); +static_assert(count_entries(cluster::__property::__ZWJ) == 1); +static_assert(count_entries(cluster::__property::__Extended_Pictographic) == 3793); + +} // namespace + +template +constexpr void test(const Data& data) { + for (const auto& d : data) { + assert(d.code_points.size() == d.breaks.size()); + + std::__unicode::__extended_grapheme_cluster_view view{d.input.data(), d.input.data() + d.input.size()}; + for (size_t i = 0; i < d.breaks.size(); ++i) { + auto r = view.__consume(); + assert(r.__code_point_ == d.code_points[i]); + assert(r.__last_ == d.input.data() + d.breaks[i]); + } + } +} + +constexpr bool test() { + test(data_utf8); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + if constexpr (sizeof(wchar_t) == 2) + test(data_utf16); + else + test(data_utf32); +#endif + + return true; +} + +int main(int, char**) { + test(); + // static_assert(test()); + + return 0; +} diff --git a/libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_string_unicode.pass.cpp b/libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_string_unicode.pass.cpp --- a/libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_string_unicode.pass.cpp +++ b/libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_string_unicode.pass.cpp @@ -61,29 +61,17 @@ estimate_column_width_fast(3, CSTR("abc")); estimate_column_width_fast(3, CSTR("a\u007fc")); - if constexpr (sizeof(CharT) == 1) { - // UTF-8 stop at the first multi-byte character. - estimate_column_width_fast(0, CSTR("\u0080bc")); - estimate_column_width_fast(1, CSTR("a\u0080c")); - estimate_column_width_fast(2, CSTR("ab\u0080")); - estimate_column_width_fast(1, CSTR("aßc")); - - estimate_column_width_fast(1, CSTR("a\u07ffc")); - estimate_column_width_fast(1, CSTR("a\u0800c")); - - estimate_column_width_fast(1, CSTR("a\u10ffc")); - } else { - // UTF-16/32 stop at the first multi-column character. - estimate_column_width_fast(3, CSTR("\u0080bc")); - estimate_column_width_fast(3, CSTR("a\u0080c")); - estimate_column_width_fast(3, CSTR("ab\u0080")); - estimate_column_width_fast(3, CSTR("aßc")); - - estimate_column_width_fast(3, CSTR("a\u07ffc")); - estimate_column_width_fast(3, CSTR("a\u0800c")); - - estimate_column_width_fast(3, CSTR("a\u10ffc")); - } + // Always stop at the first multi-byte character. + estimate_column_width_fast(0, CSTR("\u0080bc")); + estimate_column_width_fast(1, CSTR("a\u0080c")); + estimate_column_width_fast(2, CSTR("ab\u0080")); + estimate_column_width_fast(1, CSTR("aßc")); + + estimate_column_width_fast(1, CSTR("a\u07ffc")); + estimate_column_width_fast(1, CSTR("a\u0800c")); + + estimate_column_width_fast(1, CSTR("a\u10ffc")); + // First 2-column character estimate_column_width_fast(1, CSTR("a\u1100c")); @@ -228,12 +216,7 @@ get_string_alignment(2, 2, false, CSTR("a\xe0"), 0, 3); get_string_alignment(2, 2, false, CSTR("a\xf0"), 0, 3); } else if constexpr (sizeof(CharT) == 2) { - // Corrupt UTF-16 sequence. - if constexpr (std::same_as) - get_string_alignment(2, 2, false, u"a\xdddd", 0, 3); - else - // Corrupt UTF-16 wchar_t seqence. - get_string_alignment(2, 2, false, L"a\xdddd", 0, 3); + get_string_alignment(2, 2, false, L"a\xdddd", 0, 3); } // UTF-32 doesn't combine characters, thus no corruption tests. } @@ -250,13 +233,7 @@ #ifndef TEST_HAS_NO_WIDE_CHARACTERS test(); #endif -#ifndef _LIBCPP_HAS_NO_CHAR8_T - test(); -#endif -#ifndef TEST_HAS_NO_UNICODE_CHARS - test(); - test(); -#endif + return true; } diff --git a/libcxx/test/std/utilities/format/format.functions/format_tests.h b/libcxx/test/std/utilities/format/format.functions/format_tests.h --- a/libcxx/test/std/utilities/format/format.functions/format_tests.h +++ b/libcxx/test/std/utilities/format/format.functions/format_tests.h @@ -362,6 +362,24 @@ check.template operator()<"{:-<7}">(SV("a\u1110c---"), STR("a\u1110c")); check.template operator()<"{:-^7}">(SV("-a\u1110c--"), STR("a\u1110c")); check.template operator()<"{:->7}">(SV("---a\u1110c"), STR("a\u1110c")); + + // Examples used in P1868R2 + check.template operator()<"{:*^3}">(SV("*\u0041*"), STR("\u0041")); // { LATIN CAPITAL LETTER A } + check.template operator()<"{:*^3}">(SV("*\u00c1*"), STR("\u00c1")); // { LATIN CAPITAL LETTER A WITH ACUTE } + check.template operator()<"{:*^3}">(SV("*\u0041\u0301*"), + STR("\u0041\u0301")); // { LATIN CAPITAL LETTER A } { COMBINING ACUTE ACCENT } + check.template operator()<"{:*^3}">(SV("*\u0132*"), STR("\u0132")); // { LATIN CAPITAL LIGATURE IJ } + check.template operator()<"{:*^3}">(SV("*\u0394*"), STR("\u0394")); // { GREEK CAPITAL LETTER DELTA } + + check.template operator()<"{:*^3}">(SV("*\u0429*"), STR("\u0429")); // { CYRILLIC CAPITAL LETTER SHCHA } + check.template operator()<"{:*^3}">(SV("*\u05d0*"), STR("\u05d0")); // { HEBREW LETTER ALEF } + check.template operator()<"{:*^3}">(SV("*\u0634*"), STR("\u0634")); // { ARABIC LETTER SHEEN } + check.template operator()<"{:*^4}">(SV("*\u3009*"), STR("\u3009")); // { RIGHT-POINTING ANGLE BRACKET } + check.template operator()<"{:*^4}">(SV("*\u754c*"), STR("\u754c")); // { CJK Unified Ideograph-754C } + check.template operator()<"{:*^4}">(SV("*\U0001f921*"), STR("\U0001f921")); // { UNICORN FACE } + check.template operator()<"{:*^4}">( + SV("*\U0001f468\u200d\U0001F469\u200d\U0001F467\u200d\U0001F466*"), + STR("\U0001f468\u200d\U0001F469\u200d\U0001F467\u200d\U0001F466")); // { Family: Man, Woman, Girl, Boy } #endif // TEST_HAS_NO_UNICODE } @@ -2545,7 +2563,6 @@ // The `char` to `wchar_t` formatting is tested separately. check.template operator()<"hello {}{}{}{}{}{}{}">(SV("hello 09azAZ!"), CharT('0'), CharT('9'), CharT('a'), CharT('z'), CharT('A'), CharT('Z'), CharT('!')); - format_test_char(check, check_exception); format_test_char_as_integer(check, check_exception); diff --git a/libcxx/utils/generate_extended_grapheme_cluster_table.py b/libcxx/utils/generate_extended_grapheme_cluster_table.py new file mode 100755 --- /dev/null +++ b/libcxx/utils/generate_extended_grapheme_cluster_table.py @@ -0,0 +1,325 @@ +#!/usr/bin/env python +# ===----------------------------------------------------------------------===## +# +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# ===----------------------------------------------------------------------===## + +# The code is based on +# https://github.com/microsoft/STL/blob/main/tools/unicode_properties_parse/grapheme_break_property_data_gen.py +# +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +from io import StringIO +from pathlib import Path +from dataclasses import dataclass, field +from typing import Optional +import re + + +@dataclass +class PropertyRange: + lower: int = -1 + upper: int = -1 + prop: str = None + + +@dataclass +class Entry: + lower: int = -1 + offset: int = -1 + prop: int = -1 + + +LINE_REGEX = re.compile( + r"^(?P[0-9A-F]{4,5})(?:\.\.(?P[0-9A-F]{4,5}))?\s*;\s*(?P\w+)" +) + + +def parsePropertyLine(inputLine: str) -> Optional[PropertyRange]: + result = PropertyRange() + if m := LINE_REGEX.match(inputLine): + lower_str, upper_str, result.prop = m.group("lower", "upper", "prop") + result.lower = int(lower_str, base=16) + result.upper = result.lower + if upper_str is not None: + result.upper = int(upper_str, base=16) + return result + + else: + return None + + +def compactPropertyRange(input: list[PropertyRange]) -> list[PropertyRange]: + """ + Merges consecutive ranges with the same property to one range. + + Merging the ranges results in less ranges in the output table. Reducing the + size of the binary and improving the performance of the loookup. + """ + result = list() + for x in input: + if ( + len(result) + and result[-1].prop == x.prop + and result[-1].upper + 1 == x.lower + ): + result[-1].upper = x.upper + continue + result.append(x) + return result + + +PROP_VALUE_ENUMERATOR_TEMPLATE = "__{}" +PROP_VALUE_ENUM_TEMPLATE = """ +enum class __property : uint8_t {{ + // Values generated from data files. + {enumerators}, + + // The properies below aren't stored in the "database". + + // Text position properties. + __sot, + __eot, + + // The code unit has none of above properties. + __none +}}; +""" + +DATA_ARRAY_TEMPLATE = """ +/// The entry of the extended grapheme cluster bondary property tqble. +/// +/// The original MSVC STL code stores the data in two /// parallel arrays: +/// - One uint32_t with the lower bounds for the code points. +/// - One uint16_t with the size and the property. +/// This requires 6 bytes per entry. +/// +/// In libc++ this is stored in an array with 4 bytes per entry: +/// - An unicode code point is restricted to 21-bit values. +/// - There are 14 properties requiring 4 bits. +/// - This leaves 7 bits to encode the range of an entry. +/// +/// MSVC STL has 12 bits for the range (4096 values) and libc++ 7 bits +/// (128 values). For most ranges 7 bits is sufficient. When a range has more +/// than 128 entries the range is split in multiple entries. +/// +/// Based on Unicode 12 the difference is +/// MSVC STL 1602 * 6 = 9612 bytes +/// libc++ 1643 * 4 = 6572 bytes +/// ========== - +/// saving 3040 bytes +/// +/// The measured overheaded of the additional masking is about 3% in +/// libcxx/benchmarks/std_format_spec_string_unicode.bench.cpp +struct __entry {{ + /// Code point of the lower bound of the range. + uint32_t __lower_bound : 21; + /// Offset to the upper bound of the range, 0 means a range of 1 code unite. + uint32_t __offset : 7; + /// The propery of the range. + uint32_t __property : 4; +}}; + +static_assert(sizeof(__entry) == sizeof(uint32_t)); + +/// The table with the extended grapheme cluster bondary properties. +/// +/// The contents are generated by a script. +inline constexpr __entry __entries[{size}] = {{{entries}}}; + +/// Returns the extended grapheme cluster bondary property of a code point. +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __property __get_property(const char32_t __code_point) noexcept {{ + // TODO FMT use ranges + ptrdiff_t __i = std::upper_bound(__entries, std::end(__entries), __code_point, + [](char32_t __lhs, __entry __rhs) {{ return __lhs < __rhs.__lower_bound; }}) - __entries; + if (__i == 0) + return __property::__none; + + --__i; + uint32_t __upper_bound = __entries[__i].__lower_bound + __entries[__i].__offset; + if (__code_point <= __upper_bound) + return static_cast<__property>(__entries[__i].__property); + + return __property::__none; +}} +""" + +MSVC_FORMAT_UCD_TABLES_HPP_TEMPLATE = """ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// WARNING, this entire header is generated by +// utiles/generate_extended_grapheme_cluster_table.py +// DO NOT MODIFY! + +// UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE +// +// See Terms of Use +// for definitions of Unicode Inc.'s Data Files and Software. +// +// NOTICE TO USER: Carefully read the following legal agreement. +// BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S +// DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), +// YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +// TERMS AND CONDITIONS OF THIS AGREEMENT. +// IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE +// THE DATA FILES OR SOFTWARE. +// +// COPYRIGHT AND PERMISSION NOTICE +// +// Copyright (c) 1991-2022 Unicode, Inc. All rights reserved. +// Distributed under the Terms of Use in https://www.unicode.org/copyright.html. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of the Unicode data files and any associated documentation +// (the "Data Files") or Unicode software and any associated documentation +// (the "Software") to deal in the Data Files or Software +// without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, and/or sell copies of +// the Data Files or Software, and to permit persons to whom the Data Files +// or Software are furnished to do so, provided that either +// (a) this copyright and permission notice appear with all copies +// of the Data Files or Software, or +// (b) this copyright and permission notice appear in associated +// Documentation. +// +// THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT OF THIRD PARTY RIGHTS. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS +// NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +// DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +// DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THE DATA FILES OR SOFTWARE. +// +// Except as contained in this notice, the name of a copyright holder +// shall not be used in advertising or otherwise to promote the sale, +// use or other dealings in these Data Files or Software without prior +// written authorization of the copyright holder. + +#ifndef _LIBCPP___FORMAT_EXTENDED_GRAPHEME_CLUSTER_TABLE_H +#define _LIBCPP___FORMAT_EXTENDED_GRAPHEME_CLUSTER_TABLE_H + +#include <__algorithm/upper_bound.h> +#include <__config> +#include <__iterator/access.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace __extended_grapheme_custer_property_boundary {{ + +{content} + +}} // __extended_grapheme_custer_property_boundary + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_EXTENDED_GRAPHEME_CLUSTER_TABLE_H +""" + + +def property_ranges_to_table( + ranges: list[PropertyRange], props: list[str] +) -> list[Entry]: + assert len(props) < 16 + result = list[Entry]() + high = -1 + for range in sorted(ranges, key=lambda x: x.lower): + # Validate overlapping ranges + assert range.lower > high + high = range.upper + + while True: + e = Entry(range.lower, range.upper - range.lower, props.index(range.prop)) + if e.offset <= 127: + result.append(e) + break + e.offset = 127 + result.append(e) + range.lower += 128 + return result + + +cpp_entrytemplate = "{{ 0x{:x}, {}, {} }}" + + +def generate_cpp_data(prop_name: str, ranges: list[PropertyRange]) -> str: + result = StringIO() + prop_values = sorted(set(x.prop for x in ranges)) + table = property_ranges_to_table(ranges, prop_values) + enumerator_values = [PROP_VALUE_ENUMERATOR_TEMPLATE.format(x) for x in prop_values] + result.write( + PROP_VALUE_ENUM_TEMPLATE.format(enumerators=",".join(enumerator_values)) + ) + result.write( + DATA_ARRAY_TEMPLATE.format( + prop_name=prop_name, + size=len(table), + entries=",".join( + [cpp_entrytemplate.format(x.lower, x.offset, x.prop) for x in table] + ), + ) + ) + + return result.getvalue() + + +def generate_data_tables() -> str: + """ + Generate Unicode data for inclusion into from + GraphemeBreakProperty.txt and emoji-data.txt. + + GraphemeBreakProperty.txt can be found at + https://www.unicode.org/Public/12.0.0/ucd/auxiliary/GraphemeBreakProperty.txt + + emoji-data.txt can be found at + https://www.unicode.org/Public/12.0.0/ucd/emoji/emoji-data.txt + + Both files are expected to be in the same directory as this script. + """ + gbp_data_path = Path(__file__).absolute().with_name("GraphemeBreakProperty.txt") + emoji_data_path = Path(__file__).absolute().with_name("emoji-data.txt") + gbp_ranges = list() + emoji_ranges = list() + with gbp_data_path.open(encoding="utf-8") as f: + gbp_ranges = compactPropertyRange( + [x for line in f if (x := parsePropertyLine(line))] + ) + with emoji_data_path.open(encoding="utf-8") as f: + emoji_ranges = compactPropertyRange( + [x for line in f if (x := parsePropertyLine(line))] + ) + + [gbp_ranges.append(x) for x in emoji_ranges if x.prop == "Extended_Pictographic"] + gpb_cpp_data = generate_cpp_data("Grapheme_Break", gbp_ranges) + return "\n".join([gpb_cpp_data]) + + +if __name__ == "__main__": + print( + MSVC_FORMAT_UCD_TABLES_HPP_TEMPLATE.lstrip().format( + content=generate_data_tables() + ) + ) diff --git a/libcxx/utils/generate_extended_grapheme_cluster_test.py b/libcxx/utils/generate_extended_grapheme_cluster_test.py new file mode 100755 --- /dev/null +++ b/libcxx/utils/generate_extended_grapheme_cluster_test.py @@ -0,0 +1,244 @@ +#!/usr/bin/env python +# ===----------------------------------------------------------------------===## +# +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# ===----------------------------------------------------------------------===## + +# The code is based on +# https://github.com/microsoft/STL/blob/main/tools/unicode_properties_parse/grapheme_break_test_data_gen.py +# +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +from pathlib import Path +from dataclasses import dataclass, field +from typing import Optional, TextIO +from array import array + + +@dataclass +class BreakTestItem: + code_points: list[int] = field(default_factory=list) + encoded: str = "" + breaks_utf8: list[int] = field(default_factory=list) + breaks_utf16: list[int] = field(default_factory=list) + breaks_utf32: list[int] = field(default_factory=list) + + +class CommentLine: + pass + + +class EOF: + pass + + +def parseBreakTestLine(input: TextIO) -> Optional[BreakTestItem]: + result = BreakTestItem() + code_point = -1 + utf8 = 0 + utf16 = 0 + utf32 = 0 + + while True: + c = input.read(1) + if c == "\N{DIVISION SIGN}": + # The line starts with a division sign, don't add it to the output. + if code_point != -1: + result.code_points.append(code_point) + code_point = -1 + result.breaks_utf8.append(utf8) + result.breaks_utf16.append(utf16) + result.breaks_utf32.append(utf32) + + assert input.read(1).isspace() + continue + if c == "\N{MULTIPLICATION SIGN}": + assert input.read(1).isspace() + continue + if c.isalnum(): + while next := input.read(1): + if next.isalnum(): + c += next + else: + assert next.isspace() + break + i = int(c, base=16) + if code_point == -1: + code_point = i + + result.encoded += f"\\U{i:08x}" + c = chr(i) + utf8 += c.encode().__len__() + # Since we only care about the number of code units the byte order + # doesn't matter. The byte order is specified to avoid the BOM + utf16 += int(c.encode("utf-16-le").__len__() / 2) + utf32 += int(c.encode("utf-32-le").__len__() / 4) + continue + if c == "#": + input.readline() + return result + if c == "\n": + return result + if c == "": + return None + assert False + + +cpp_template = """// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// WARNING, this entire header is generated by +// utiles/generate_extended_grapheme_cluster_test.py +// DO NOT MODIFY! + +// UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE +// +// See Terms of Use +// for definitions of Unicode Inc.'s Data Files and Software. +// +// NOTICE TO USER: Carefully read the following legal agreement. +// BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S +// DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), +// YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +// TERMS AND CONDITIONS OF THIS AGREEMENT. +// IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE +// THE DATA FILES OR SOFTWARE. +// +// COPYRIGHT AND PERMISSION NOTICE +// +// Copyright (c) 1991-2022 Unicode, Inc. All rights reserved. +// Distributed under the Terms of Use in https://www.unicode.org/copyright.html. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of the Unicode data files and any associated documentation +// (the "Data Files") or Unicode software and any associated documentation +// (the "Software") to deal in the Data Files or Software +// without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, and/or sell copies of +// the Data Files or Software, and to permit persons to whom the Data Files +// or Software are furnished to do so, provided that either +// (a) this copyright and permission notice appear with all copies +// of the Data Files or Software, or +// (b) this copyright and permission notice appear in associated +// Documentation. +// +// THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT OF THIRD PARTY RIGHTS. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS +// NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +// DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +// DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THE DATA FILES OR SOFTWARE. +// +// Except as contained in this notice, the name of a copyright holder +// shall not be used in advertising or otherwise to promote the sale, +// use or other dealings in these Data Files or Software without prior +// written authorization of the copyright holder. + +#ifndef LIBCXX_TEST_STD_UTILITIES_FORMAT_FORMAT_STRING_FORMAT_STRING_STD_EXTENDED_GRAPHEME_CLUSTER_H +#define LIBCXX_TEST_STD_UTILITIES_FORMAT_FORMAT_STRING_FORMAT_STRING_STD_EXTENDED_GRAPHEME_CLUSTER_H + +#include +#include +#include + +template +struct data {{ + /// The input to parse. + std::basic_string_view input; + + /// The first code point all extended grapheme clusters in the input. + std::vector code_points; + + /// The offset of the last code units of the extended grapheme clusters in the input. + /// + /// The vector has the same number of entries as \\ref code_points. + std::vector breaks; +}}; + +/// The data for UTF-8. +std::array, {0}> data_utf8 = {{{{ {1} }}}}; + +/// The data for UTF-16. +/// +/// Note that most of the data for the UTF-16 and UTF-32 are identical. However +/// since the size of the code units differ the breaks can contain different +/// values. +std::array, {0}> data_utf16 = {{{{ {2} }}}}; + +/// The data for UTF-8. +/// +/// Note that most of the data for the UTF-16 and UTF-32 are identical. However +/// since the size of the code units differ the breaks can contain different +/// values. +std::array, {0}> data_utf32 = {{{{ {3} }}}}; + +#endif // LIBCXX_TEST_STD_UTILITIES_FORMAT_FORMAT_STRING_FORMAT_STRING_STD_EXTENDED_GRAPHEME_CLUSTER_H +""" + +cpp_test_data_line_template = "{{ {}, {{ {} }}, {{ {} }} }}" + + +def lineToCppDataLineUtf8(line: BreakTestItem) -> str: + return cpp_test_data_line_template.format( + f'"{line.encoded}"', + ",".join([str(x) for x in line.code_points]), + ",".join([str(x) for x in line.breaks_utf8]), + ) + + +def lineToCppDataLineUtf16(line: BreakTestItem) -> str: + return cpp_test_data_line_template.format( + f'L"{line.encoded}"', + ",".join([str(x) for x in line.code_points]), + ",".join([str(x) for x in line.breaks_utf16]), + ) + + +def lineToCppDataLineUtf32(line: BreakTestItem) -> str: + return cpp_test_data_line_template.format( + f'L"{line.encoded}"', + ",".join([str(x) for x in line.code_points]), + ",".join([str(x) for x in line.breaks_utf32]), + ) + + +""" +Generate test data from "GraphemeBreakText.txt" +This file can be downloaded from: https://www.unicode.org/Public/12.0.0/ucd/auxiliary/GraphemeBreakTest.txt +This script looks for GraphemeBreakTest.txt in same directory as this script +""" + + +def generate_all() -> str: + test_data_path = Path(__file__) + test_data_path = test_data_path.absolute() + test_data_path = test_data_path.with_name("GraphemeBreakTest.txt") + lines = list() + with open(test_data_path, mode="rt", encoding="utf-8") as file: + while line := parseBreakTestLine(file): + if len(line.encoded) > 0: + lines.append(line) + return cpp_template.format( + len(lines), + ",".join(map(lineToCppDataLineUtf8, lines)), + ",".join(map(lineToCppDataLineUtf16, lines)), + ",".join(map(lineToCppDataLineUtf32, lines)), + ) + + +if __name__ == "__main__": + print(generate_all())