diff options
author | Jérôme Vouillon <vouillon@pps.jussieu.fr> | 2010-04-12 09:40:14 +0000 |
---|---|---|
committer | Jérôme Vouillon <vouillon@pps.jussieu.fr> | 2010-04-12 09:40:14 +0000 |
commit | 2cc611ab0d92d9f20e5b1952fb44c8b731d0fe03 (patch) | |
tree | 2616f52686388e7dca8a3c636ca878f4145c60ed | |
parent | ac797cbd2b140033d255b0a8f81e151c473d83dc (diff) | |
download | unison-2cc611ab0d92d9f20e5b1952fb44c8b731d0fe03.zip unison-2cc611ab0d92d9f20e5b1952fb44c8b731d0fe03.tar.gz unison-2cc611ab0d92d9f20e5b1952fb44c8b731d0fe03.tar.bz2 |
* Compare filenames up to decomposition in case sensitive mode when
one host is running MacOSX and the unicode preference is set to
true.
* Fixed some non-tail recursive functions
-rw-r--r-- | src/RECENTNEWS | 8 | ||||
-rw-r--r-- | src/case.ml | 36 | ||||
-rw-r--r-- | src/case.mli | 4 | ||||
-rw-r--r-- | src/lwt/lwt_util.ml | 11 | ||||
-rw-r--r-- | src/mkProjectInfo.ml | 1 | ||||
-rw-r--r-- | src/uicommon.ml | 15 | ||||
-rw-r--r-- | src/uitext.ml | 20 | ||||
-rw-r--r-- | src/unicode.ml | 119 | ||||
-rw-r--r-- | src/unicode.mli | 9 | ||||
-rw-r--r-- | src/unicode_tables.ml | 13 | ||||
-rw-r--r-- | src/update.ml | 1 | ||||
-rw-r--r-- | unicode_utils/README | 2 | ||||
-rw-r--r-- | unicode_utils/codepages/lowcase.dat | bin | 0 -> 131072 bytes | |||
-rw-r--r-- | unicode_utils/codepages/upcase.dat | bin | 0 -> 131072 bytes | |||
-rw-r--r-- | unicode_utils/reorder.ml | 738 | ||||
-rw-r--r-- | unicode_utils/unicode.ml | 815 | ||||
-rw-r--r-- | unicode_utils/unicode_build.ml | 2045 | ||||
-rw-r--r-- | unicode_utils/unicode_test.ml | 83 |
18 files changed, 3891 insertions, 29 deletions
diff --git a/src/RECENTNEWS b/src/RECENTNEWS index b40bffe..4e802d8 100644 --- a/src/RECENTNEWS +++ b/src/RECENTNEWS @@ -1,5 +1,13 @@ CHANGES FROM VERSION 2.40.16 +* Compare filenames up to decomposition in case sensitive mode when + one host is running MacOSX and the unicode preference is set to + true. +* Fixed some non-tail recursive functions + +------------------------------- +CHANGES FROM VERSION 2.40.16 + * GTK UI: typo * Fixed Makefile for compilation under Solaris diff --git a/src/case.ml b/src/case.ml index a6af61b..e8989dd 100644 --- a/src/case.ml +++ b/src/case.ml @@ -45,8 +45,12 @@ let unicode = "When set to {\\tt true}, this flag causes Unison to perform \ case insensitive file comparisons assuming Unicode encoding. \ This is the default. When the flag is set to {\\tt false}, \ - a Latin 1 encoding is assumed. This flag has no effect when \ - Unison runs in case sensitive mode." + a Latin 1 encoding is assumed. When Unison runs in case sensitive \ + mode, this flag only makes a difference if one host is running \ + Windows or Mac OS X. Under Windows, the flag selects between using \ + the Unicode or 8bit Windows API for accessing the filesystem. \ + Under Mac OS X, it selects whether comparing the filenames up to \ + decomposition, or byte-for-byte." let unicodeEncoding = Prefs.createBool "unicodeEnc" false @@ -58,14 +62,19 @@ let useUnicode () = let useUnicodeAPI = useUnicode +let unicodeCaseSensitive = + Prefs.createBool "unicodeEnc" ~local:true false + "*Pseudo-preference for internal use only" "" + (* During startup the client determines the case sensitivity of each root. *) (* If any root is case insensitive, all roots must know it; we ensure this *) (* by storing the information in a pref so that it is propagated to the *) (* server with the rest of the prefs. *) -let init b = +let init b someHostRunningOsX = Prefs.set someHostIsInsensitive (Prefs.read caseInsensitiveMode = `True || (Prefs.read caseInsensitiveMode = `Default && b)); + Prefs.set unicodeCaseSensitive (useUnicode () && someHostRunningOsX); Prefs.set unicodeEncoding (useUnicode ()) (****) @@ -116,7 +125,7 @@ let rmTrailDots s = (****) -type mode = Sensitive | Insensitive | UnicodeInsensitive +type mode = Sensitive | Insensitive | UnicodeSensitive | UnicodeInsensitive (* Important invariant: @@ -151,10 +160,22 @@ let insensitiveOps = object method badEncoding s = false end +let unicodeSensitiveOps = object + method mode = UnicodeSensitive + method modeDesc = "Unicode case sensitive" + method compare s s' = Unicode.case_sensitive_compare s s' + method hash s = Hashtbl.hash (Unicode.decompose s) + method normalizePattern p = Unicode.decompose p + method caseInsensitiveMatch = false + method normalizeMatchedString s = Unicode.decompose s + method normalizeFilename s = Unicode.compose s + method badEncoding s = not (Unicode.check_utf_8 s) +end + let unicodeInsensitiveOps = object method mode = UnicodeInsensitive method modeDesc = "Unicode case insensitive" - method compare s s' = Unicode.compare s s' + method compare s s' = Unicode.case_insensitive_compare s s' method hash s = Hashtbl.hash (Unicode.normalize s) method normalizePattern p = Unicode.normalize p method caseInsensitiveMatch = false @@ -171,6 +192,9 @@ let ops () = else insensitiveOps end else - sensitiveOps + if Prefs.read unicodeCaseSensitive then + unicodeSensitiveOps + else + sensitiveOps let caseSensitiveModeDesc = sensitiveOps#modeDesc diff --git a/src/case.mli b/src/case.mli index 47d6192..1022405 100644 --- a/src/case.mli +++ b/src/case.mli @@ -5,7 +5,7 @@ val caseInsensitiveMode : [`True|`False|`Default] Prefs.t val unicodeEncoding : bool Prefs.t val useUnicodeAPI : unit -> bool -type mode = Sensitive | Insensitive | UnicodeInsensitive +type mode = Sensitive | Insensitive | UnicodeSensitive | UnicodeInsensitive val ops : unit -> < mode : mode; modeDesc : string; (* Current mode *) @@ -25,6 +25,6 @@ val ops : unit -> badEncoding : string -> bool > (* Test whether the string uses the correct encoding *) -val init : bool -> unit +val init : bool -> bool -> unit val caseSensitiveModeDesc : string diff --git a/src/lwt/lwt_util.ml b/src/lwt/lwt_util.ml index e36a8d1..2a686e3 100644 --- a/src/lwt/lwt_util.ml +++ b/src/lwt/lwt_util.ml @@ -2,12 +2,9 @@ open Lwt let rec iter f l = - match l with - [] -> return () - | a :: r -> - let t = f a in - let rt = iter f r in - t >>= (fun () -> rt) + let l = List.fold_left (fun acc a -> f a :: acc) [] l in + let l = List.rev l in + List.fold_left (fun rt t -> t >>= fun () -> rt) (Lwt.return ()) l let rec map f l = match l with @@ -50,7 +47,7 @@ let rec map_serial f l = return [] | v :: r -> f v >>= (fun v' -> - map f r >>= (fun l' -> + map_serial f r >>= (fun l' -> return (v' :: l'))) let join l = iter (fun x -> x) l diff --git a/src/mkProjectInfo.ml b/src/mkProjectInfo.ml index 1e92720..7af4df9 100644 --- a/src/mkProjectInfo.ml +++ b/src/mkProjectInfo.ml @@ -109,3 +109,4 @@ Printf.printf "NAME=%s\n" projectName;; + diff --git a/src/uicommon.ml b/src/uicommon.ml index 4c0d60e..549c287 100644 --- a/src/uicommon.ml +++ b/src/uicommon.ml @@ -434,6 +434,17 @@ let debug = Trace.debug "startup" (* ---- *) +(*FIX: remove when Unison version > 2.40 *) +let _ = Remote.registerRootCmd "unicodeCaseSensitive" (fun _ -> Lwt.return ()) +let supportUnicodeCaseSensitive () = + if Uutil.myMajorVersion > "2.40" (* The test is correct until 2.99... *) then + Lwt.return true + else begin + Globals.allRootsMap + (fun r -> Remote.commandAvailable r "unicodeCaseSensitive") >>= fun l -> + Lwt.return (List.for_all (fun x -> x) l) + end + (* Determine the case sensitivity of a root (does filename FOO==foo?) *) let architecture = Remote.registerRootCmd @@ -446,7 +457,9 @@ let architecture = Windows (needed for permissions) and does some sanity checking. *) let validateAndFixupPrefs () = Props.validatePrefs(); + let supportUnicodeCaseSensitive = supportUnicodeCaseSensitive () in Globals.allRootsMap (fun r -> architecture r ()) >>= (fun archs -> + supportUnicodeCaseSensitive >>= fun unicodeCS -> let someHostIsRunningWindows = Safelist.exists (fun (isWin, _, _) -> isWin) archs in let allHostsAreRunningWindows = @@ -464,7 +477,7 @@ let validateAndFixupPrefs () = Prefs.overrideDefault Fileinfo.allowSymlinks `False; Prefs.overrideDefault Fileinfo.ignoreInodeNumbers true end; - Case.init someHostIsCaseInsensitive; + Case.init someHostIsCaseInsensitive (someHostRunningOsX && unicodeCS); Props.init someHostIsRunningWindows; Osx.init someHostRunningOsX; Fileinfo.init someHostIsRunningBareWindows; diff --git a/src/uitext.ml b/src/uitext.ml index e887416..a3abe87 100644 --- a/src/uitext.ml +++ b/src/uitext.ml @@ -163,14 +163,18 @@ let rec selectAction batch actions tryagain = actions; tryagainOrLoop()) else - try find a actions () with Not_found -> - newLine (); - if a="" then - display ("No default command [type '?' for help]\n") - else - display ("Unrecognized command '" ^ String.escaped a - ^ "': try again [type '?' for help]\n"); - tryagainOrLoop() + let action = try Some (find a actions) with Not_found -> None in + match action with + Some action -> + action () + | None -> + newLine (); + if a="" then + display ("No default command [type '?' for help]\n") + else + display ("Unrecognized command '" ^ String.escaped a + ^ "': try again [type '?' for help]\n"); + tryagainOrLoop() in doAction (match batch with None -> diff --git a/src/unicode.ml b/src/unicode.ml index bb07ade..56bdb21 100644 --- a/src/unicode.ml +++ b/src/unicode.ml @@ -849,7 +849,7 @@ let rec norm s i l s' j = if i < l then begin let c = get s i in if c < 0x80 then begin - set s' j (get ascii_lower c); + set s' j (get norm_ascii c); norm s (i + 1) l s' (j + 1) end else if c < 0xE0 then begin (* 80 - 7FF *) @@ -942,6 +942,99 @@ let normalize s = (****) +let rec decomp s i l s' j = + if i < l then begin + let c = get s i in + if c < 0x80 then begin + set s' j (get decomp_ascii c); + decomp s (i + 1) l s' (j + 1) + end else if c < 0xE0 then begin + (* 80 - 7FF *) + if c < 0xc2 || i + 1 >= l then raise Invalid; + let c1 = get s (i + 1) in + if c1 land 0xc0 <> 0x80 then raise Invalid; + let idx = get decomp_prim (c - 0xc0) in + let idx = idx lsl 6 + c1 - 0x80 in + let k = get decomp_second_high idx in + if k = 0 then begin + set s' j c; + set s' (j + 1) c1; + decomp s (i + 2) l s' (j + 2) + end else begin + let k = (k - 2) lsl 8 + get decomp_second_low idx in + let n = get decomp_repl k in + String.blit decomp_repl (k + 1) s' j n; + decomp s (i + 2) l s' (j + n) + end + end else if c < 0xF0 then begin + (* 800 - FFFF *) + if i + 2 >= l then raise Invalid; + let c1 = get s (i + 1) in + if c1 land 0xc0 <> 0x80 then raise Invalid; + let idx = c lsl 6 + c1 - 0x3880 in + if idx < 0x20 then raise Invalid; + let c2 = get s (i + 2) in + if c2 land 0xc0 <> 0x80 then raise Invalid; + let idx = get decomp_prim idx in + let idx = idx lsl 6 + c2 - 0x80 in + let k = get decomp_second_high idx in + if k = 0 then begin + set s' j c; + set s' (j + 1) c1; + set s' (j + 2) c2; + decomp s (i + 3) l s' (j + 3) + end else if k = 1 then begin + let v = c lsl 12 + c1 lsl 6 + c2 - (0x000E2080 + hangul_sbase) in + if v >= hangul_scount then begin + set s' j c; + set s' (j + 1) c1; + set s' (j + 2) c2; + decomp s (i + 3) l s' (j + 3) + end else begin + set_char_3 s' j (v / hangul_ncount + hangul_lbase); + set_char_3 s' (j + 3) + ((v mod hangul_ncount) / hangul_tcount + hangul_vbase); + if v mod hangul_tcount = 0 then + decomp s (i + 3) l s' (j + 6) + else begin + set_char_3 s' (j + 6) ((v mod hangul_tcount) + hangul_tbase); + decomp s (i + 3) l s' (j + 9) + end + end + end else begin + let k = (k - 2) lsl 8 + get decomp_second_low idx in + let n = get decomp_repl k in + String.blit decomp_repl (k + 1) s' j n; + decomp s (i + 3) l s' (j + n) + end + end else begin + (* 10000 - 10FFFF *) + if i + 3 >= l then raise Invalid; + let c1 = get s (i + 1) in + let c2 = get s (i + 2) in + let c3 = get s (i + 3) in + if (c1 lor c2 lor c3) land 0xc0 <> 0x80 then raise Invalid; + let v = c lsl 18 + c1 lsl 12 + c2 lsl 6 + c3 - 0x03c82080 in + if v < 0x10000 || v > 0x10ffff then raise Invalid; + set s' j c; + set s' (j + 1) c1; + set s' (j + 2) c2; + set s' (j + 3) c3; + decomp s (i + 4) l s' (j + 4) + end + end else + String.sub s' 0 j + +let decompose s = + let l = String.length s in + let s' = String.create (3 * l) in + try + let s' = decomp s 0 l s' 0 in order s'; s' + with Invalid -> + s + +(****) + let rec compare_rec s s' i l = if i = l then begin if l < String.length s then 1 else @@ -951,13 +1044,33 @@ let rec compare_rec s s' i l = let c = get s i in let c' = get s' i in if c < 0x80 && c' < 0x80 then begin - let v = compare (get ascii_lower c) (get ascii_lower c') in + let v = compare (get norm_ascii c) (get norm_ascii c') in if v <> 0 then v else compare_rec s s' (i + 1) l end else compare (normalize s) (normalize s') end -let compare s s' = +let case_insensitive_compare s s' = + compare_rec s s' 0 (min (String.length s) (String.length s')) + +(****) + +let rec compare_cs_rec s s' i l = + if i = l then begin + if l < String.length s then 1 else + if l < String.length s' then -1 else + 0 + end else begin + let c = get s i in + let c' = get s' i in + if c < 0x80 && c' < 0x80 then begin + let v = compare c c' in + if v <> 0 then v else compare_cs_rec s s' (i + 1) l + end else + compare s s' + end + +let case_sensitive_compare s s' = compare_rec s s' 0 (min (String.length s) (String.length s')) (****) diff --git a/src/unicode.mli b/src/unicode.mli index 8bd5bc7..9d4f19f 100644 --- a/src/unicode.mli +++ b/src/unicode.mli @@ -6,11 +6,18 @@ exception Invalid (* Case-insensitive comparison. If two strings are equal according to Mac OS X (Darwin, actually, but the algorithm has hopefully remained unchanged) or Windows (Samba), then this function returns 0 *) -val compare : string -> string -> int +val case_insensitive_compare : string -> string -> int (* Corresponding normalization *) val normalize : string -> string +(* Case-sensitive comparison (but up to decomposition). *) +val case_sensitive_compare : string -> string -> int + +(* Compose Unicode strings. This is the decomposition performed + by Mac OS X. *) +val decompose : string -> string + (* Compose Unicode strings. This reverts the decomposition performed by Mac OS X. *) val compose : string -> string diff --git a/src/unicode_tables.ml b/src/unicode_tables.ml index 73ce319..d6ecbab 100644 --- a/src/unicode_tables.ml +++ b/src/unicode_tables.ml @@ -1,5 +1,5 @@ (*-*-coding: utf-8;-*-*) -let ascii_lower = +let norm_ascii = "\000\001\002\003\004\005\006\007\b\t\n\011\012\r\014\015\016\017\018\019\020\021\022\023\024\025\026\027\028\029\030\031 !\"#$%&'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\127" let norm_repl = "\003à\003á\003â\003ã\003ä\003å\002æ\003ç\003è\003é\003ê\003ë\003ì\003í\003î\003ï\002ð\003ñ\003ò\003ó\003ô\003õ\003ö\002ø\003ù\003ú\003û\003ü\003ý\002þ\003ÿ\003ā\003ă\003ą\003ć\003ĉ\003ċ\003č\003ď\002đ\003ē\003ĕ\003ė\003ę\003ě\003ĝ\003ğ\003ġ\003ģ\003ĥ\002ħ\003ĩ\003ī\003ĭ\003į\003i̇\002ij\003ĵ\003ķ\003ĺ\003ļ\003ľ\002ŀ\002ł\003ń\003ņ\003ň\002ŋ\003ō\003ŏ\003ő\002œ\003ŕ\003ŗ\003ř\003ś\003ŝ\003ş\003š\003ţ\003ť\002ŧ\003ũ\003ū\003ŭ\003ů\003ű\003ų\003ŵ\003ŷ\003ź\003ż\003ž\002ɓ\002ƃ\002ƅ\002ɔ\002ƈ\002ɖ\002ɗ\002ƌ\002ǝ\002ə\002ɛ\002ƒ\002ɠ\002ɣ\002ɩ\002ɨ\002ƙ\002ɯ\002ɲ\002ɵ\003ơ\002ƣ\002ƥ\002ƨ\002ʃ\002ƭ\002ʈ\003ư\002ʊ\002ʋ\002ƴ\002ƶ\002ʒ\002ƹ\002ƽ\002dž\002lj\002nj\003ǎ\003ǐ\003ǒ\003ǔ\005ǖ\005ǘ\005ǚ\005ǜ\005ǟ\005ǡ\004ǣ\002ǥ\003ǧ\003ǩ\003ǫ\005ǭ\004ǯ\003ǰ\002dz\003ǵ\003ǹ\005ǻ\004ǽ\004ǿ\003ȁ\003ȃ\003ȅ\003ȇ\003ȉ\003ȋ\003ȍ\003ȏ\003ȑ\003ȓ\003ȕ\003ȗ\003ș\003ț\003ȟ\003ȧ\003ȩ\005ȫ\005ȭ\003ȯ\005ȱ\003ȳ\002̀\002́\002̓\004̈́\002ʹ\001;\004΅\004ά\002·\004έ\004ή\004ί\004ό\004ύ\004ώ\006ΐ\002α\002β\002γ\002δ\002ε\002ζ\002η\002θ\002ι\002κ\002λ\002μ\002ν\002ξ\002ο\002π\002ρ\002σ\002τ\002υ\002φ\002χ\002ψ\002ω\004ϊ\004ϋ\006ΰ\004ϓ\004ϔ\002ϣ\002ϥ\002ϧ\002ϩ\002ϫ\002ϭ\002ϯ\004ѐ\004ё\002ђ\004ѓ\002є\002ѕ\002і\004ї\002ј\002љ\002њ\002ћ\004ќ\004ѝ\004ў\002џ\002а\002б\002в\002г\002д\002е\002ж\002з\002и\004й\002к\002л\002м\002н\002о\002п\002р\002с\002т\002у\002ф\002х\002ц\002ч\002ш\002щ\002ъ\002ы\002ь\002э\002ю\002я\002ѡ\002ѣ\002ѥ\002ѧ\002ѩ\002ѫ\002ѭ\002ѯ\002ѱ\002ѳ\002ѵ\004ѷ\002ѹ\002ѻ\002ѽ\002ѿ\002ҁ\002ґ\002ғ\002ҕ\002җ\002ҙ\002қ\002ҝ\002ҟ\002ҡ\002ң\002ҥ\002ҧ\002ҩ\002ҫ\002ҭ\002ү\002ұ\002ҳ\002ҵ\002ҷ\002ҹ\002һ\002ҽ\002ҿ\004ӂ\002ӄ\002ӈ\002ӌ\004ӑ\004ӓ\002ӕ\004ӗ\002ә\004ӛ\004ӝ\004ӟ\002ӡ\004ӣ\004ӥ\004ӧ\002ө\004ӫ\004ӭ\004ӯ\004ӱ\004ӳ\004ӵ\004ӹ\002ա\002բ\002գ\002դ\002ե\002զ\002է\002ը\002թ\002ժ\002ի\002լ\002խ\002ծ\002կ\002հ\002ձ\002ղ\002ճ\002մ\002յ\002ն\002շ\002ո\002չ\002պ\002ջ\002ռ\002ս\002վ\002տ\002ր\002ց\002ւ\002փ\002ք\002օ\002ֆ\004آ\004أ\004ؤ\004إ\004ئ\004ۀ\004ۂ\004ۓ\006ऩ\006ऱ\006ऴ\006क़\006ख़\006ग़\006ज़\006ड़\006ढ़\006फ़\006य़\006ো\006ৌ\006ড়\006ঢ়\006য়\006ਲ਼\006ਸ਼\006ਖ਼\006ਗ਼\006ਜ਼\006ਫ਼\006ୈ\006ୋ\006ୌ\006ଡ଼\006ଢ଼\006ஔ\006ொ\006ோ\006ௌ\006ై\006ೀ\006ೇ\006ೈ\006ೊ\009ೋ\006ൊ\006ോ\006ൌ\006ේ\006ො\009ෝ\006ෞ\006གྷ\006ཌྷ\006དྷ\006བྷ\006ཛྷ\006ཀྵ\006ཱི\006ཱུ\006ྲྀ\006ླྀ\006ཱྀ\006ྒྷ\006ྜྷ\006ྡྷ\006ྦྷ\006ྫྷ\006ྐྵ\006ဦ\003ა\003ბ\003გ\003დ\003ე\003ვ\003ზ\003თ\003ი\003კ\003ლ\003მ\003ნ\003ო\003პ\003ჟ\003რ\003ს\003ტ\003უ\003ფ\003ქ\003ღ\003ყ\003შ\003ჩ\003ც\003ძ\003წ\003ჭ\003ხ\003ჯ\003ჰ\003ჱ\003ჲ\003ჳ\003ჴ\003ჵ\003ḁ\003ḃ\003ḅ\003ḇ\005ḉ\003ḋ\003ḍ\003ḏ\003ḑ\003ḓ\005ḕ\005ḗ\003ḙ\003ḛ\005ḝ\003ḟ\003ḡ\003ḣ\003ḥ\003ḧ\003ḩ\003ḫ\003ḭ\005ḯ\003ḱ\003ḳ\003ḵ\003ḷ\005ḹ\003ḻ\003ḽ\003ḿ\003ṁ\003ṃ\003ṅ\003ṇ\003ṉ\003ṋ\005ṍ\005ṏ\005ṑ\005ṓ\003ṕ\003ṗ\003ṙ\003ṛ\005ṝ\003ṟ\003ṡ\003ṣ\005ṥ\005ṧ\005ṩ\003ṫ\003ṭ\003ṯ\003ṱ\003ṳ\003ṵ\003ṷ\005ṹ\005ṻ\003ṽ\003ṿ\003ẁ\003ẃ\003ẅ\003ẇ\003ẉ\003ẋ\003ẍ\003ẏ\003ẑ\003ẓ\003ẕ\003ẖ\003ẗ\003ẘ\003ẙ\004ẛ\003ạ\003ả\005ấ\005ầ\005ẩ\005ẫ\005ậ\005ắ\005ằ\005ẳ\005ẵ\005ặ\003ẹ\003ẻ\003ẽ\005ế\005ề\005ể\005ễ\005ệ\003ỉ\003ị\003ọ\003ỏ\005ố\005ồ\005ổ\005ỗ\005ộ\005ớ\005ờ\005ở\005ỡ\005ợ\003ụ\003ủ\005ứ\005ừ\005ử\005ữ\005ự\003ỳ\003ỵ\003ỷ\003ỹ\004ἀ\004ἁ\006ἂ\006ἃ\006ἄ\006ἅ\006ἆ\006ἇ\004ἐ\004ἑ\006ἒ\006ἓ\006ἔ\006ἕ\004ἠ\004ἡ\006ἢ\006ἣ\006ἤ\006ἥ\006ἦ\006ἧ\004ἰ\004ἱ\006ἲ\006ἳ\006ἴ\006ἵ\006ἶ\006ἷ\004ὀ\004ὁ\006ὂ\006ὃ\006ὄ\006ὅ\004ὐ\004ὑ\006ὒ\006ὓ\006ὔ\006ὕ\006ὖ\006ὗ\004ὠ\004ὡ\006ὢ\006ὣ\006ὤ\006ὥ\006ὦ\006ὧ\004ὰ\004ὲ\004ὴ\004ὶ\004ὸ\004ὺ\004ὼ\006ᾀ\006ᾁ\008ᾂ\008ᾃ\008ᾄ\008ᾅ\008ᾆ\008ᾇ\006ᾐ\006ᾑ\008ᾒ\008ᾓ\008ᾔ\008ᾕ\008ᾖ\008ᾗ\006ᾠ\006ᾡ\008ᾢ\008ᾣ\008ᾤ\008ᾥ\008ᾦ\008ᾧ\004ᾰ\004ᾱ\006ᾲ\004ᾳ\006ᾴ\004ᾶ\006ᾷ\004῁\006ῂ\004ῃ\006ῄ\004ῆ\006ῇ\005῍\005῎\005῏\004ῐ\004ῑ\006ῒ\004ῖ\006ῗ\005῝\005῞\005῟\004ῠ\004ῡ\006ῢ\004ῤ\004ῥ\004ῦ\006ῧ\004῭\001`\006ῲ\004ῳ\006ῴ\004ῶ\006ῷ\002´\000\003ⅰ\003ⅱ\003ⅲ\003ⅳ\003ⅴ\003ⅵ\003ⅶ\003ⅷ\003ⅸ\003ⅹ\003ⅺ\003ⅻ\003ⅼ\003ⅽ\003ⅾ\003ⅿ\003ⓐ\003ⓑ\003ⓒ\003ⓓ\003ⓔ\003ⓕ\003ⓖ\003ⓗ\003ⓘ\003ⓙ\003ⓚ\003ⓛ\003ⓜ\003ⓝ\003ⓞ\003ⓟ\003ⓠ\003ⓡ\003ⓢ\003ⓣ\003ⓤ\003ⓥ\003ⓦ\003ⓧ\003ⓨ\003ⓩ\006が\006ぎ\006ぐ\006げ\006ご\006ざ\006じ\006ず\006ぜ\006ぞ\006だ\006ぢ\006づ\006で\006ど\006ば\006ぱ\006び\006ぴ\006ぶ\006ぷ\006べ\006ぺ\006ぼ\006ぽ\006ゔ\006ゞ\006ガ\006ギ\006グ\006ゲ\006ゴ\006ザ\006ジ\006ズ\006ゼ\006ゾ\006ダ\006ヂ\006ヅ\006デ\006ド\006バ\006パ\006ビ\006ピ\006ブ\006プ\006ベ\006ペ\006ボ\006ポ\006ヴ\006ヷ\006ヸ\006ヹ\006ヺ\006ヾ\001\001\001\001\001\001\001\001\001 \001 @@ -10,3 +10,14 @@ let norm_second_high = "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\000\002\002\002\002\002\002\002\000\002\002\002\002\002\002\000\002\002\002\002\002\002\002\002\002\000\002\002\002\002\002\002\000\000\002\002\002\002\002\000\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\000\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\000\002\002\002\002\002\002\002\002\002\000\002\000\002\002\002\002\000\002\002\002\002\002\002\002\000\002\000\002\002\002\002\002\002\000\003\000\003\003\003\003\003\003\003\000\003\003\003\003\003\003\003\003\003\003\003\003\003\003\003\003\003\003\003\000\003\003\003\003\003\003\003\003\003\003\003\003\003\003\003\003\002\003\003\003\003\003\003\000\000\003\003\000\003\000\003\003\000\003\003\003\000\000\003\003\003\003\000\003\003\000\003\003\003\000\000\000\003\003\000\003\003\003\003\000\003\000\000\003\000\003\000\000\003\000\003\003\003\003\003\003\000\003\000\003\003\000\000\000\003\000\000\000\000\000\000\000\003\003\000\003\003\000\003\003\000\003\003\003\003\003\003\003\003\003\003\003\003\003\003\003\003\000\004\004\004\004\004\004\004\000\004\004\004\004\004\004\004\004\004\004\004\004\004\000\004\004\000\000\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\000\000\004\004\000\000\000\000\000\000\004\004\004\004\004\004\004\004\004\004\004\004\004\004\000\000\000\000\000\000\000\000\000\000\000\000\004\004\000\004\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\004\004\004\004\004\004\000\004\000\004\004\004\004\004\004\004\004\005\005\005\005\005\005\005\005\005\005\005\005\000\005\005\005\005\005\005\005\005\005\004\004\004\004\005\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\000\000\000\000\000\000\000\005\005\004\004\004\000\000\000\000\005\005\000\000\000\000\000\000\000\000\000\000\000\000\000\005\000\005\000\005\000\005\000\005\000\005\000\005\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\006\006\006\000\000\000\000\000\000\000\000\000\005\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\005\000\005\000\000\000\005\000\000\000\000\005\005\005\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\006\006\000\006\000\006\000\006\000\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\006\000\000\006\006\006\000\000\000\006\000\000\000\006\000\000\000\000\006\006\006\006\006\000\006\006\006\000\006\006\006\006\006\006\006\000\006\006\006\006\006\006\006\000\006\006\006\006\006\006\006\006\006\006\006\006\000\000\006\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\006\006\006\006\006\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\007\007\007\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\000\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\000\000\000\000\000\000\000\007\000\000\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\007\007\007\007\007\007\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\007\000\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\008\008\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\008\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\008\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\008\008\000\008\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\008\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\008\008\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\008\000\000\000\000\008\000\000\000\000\008\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\008\000\008\008\000\009\000\000\000\000\000\000\000\000\009\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\009\000\000\000\000\000\000\000\000\000\009\000\000\000\000\009\000\000\000\000\009\000\000\000\000\009\000\000\000\000\000\000\000\000\000\000\000\000\009\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\009\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\000\011\000\000\000\000\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\011\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\000\000\000\000\000\000\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\000\000\012\012\012\012\012\012\000\000\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\013\013\000\000\012\012\012\012\013\013\000\000\013\013\013\013\013\013\013\013\000\013\000\013\000\013\000\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\004\013\004\013\004\013\004\013\004\013\004\013\004\000\000\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\014\014\014\014\013\013\013\013\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\000\014\014\014\014\013\004\014\000\005\000\000\014\014\014\014\000\014\014\013\004\013\004\014\014\014\014\014\014\014\004\000\000\014\014\014\014\013\004\000\014\014\014\014\014\015\005\015\015\015\015\014\014\013\004\015\015\004\015\000\000\015\015\015\000\015\015\013\004\013\004\015\015\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015\015\015\015\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015\015\015\015\015\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015\015\015\015\015\015\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015\000\015\000\015\000\016\000\016\000\016\000\016\000\016\000\016\000\016\000\016\000\016\000\000\016\000\016\000\016\000\000\000\000\000\000\016\016\000\016\016\000\016\016\000\016\016\000\016\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\016\000\016\000\016\000\016\000\016\000\016\000\016\000\016\000\016\000\016\000\016\000\000\017\000\017\000\017\000\000\000\000\000\000\017\017\000\017\017\000\017\017\000\017\017\000\017\017\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\017\000\000\017\017\017\017\000\000\000\017\000\000\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\017\000\017\000\000\000\000\000\000\000\000\000\000\017\017\017\017\017\018\018\018\018\018\018\018\018\000\018\018\018\018\018\000\018\000\018\018\000\018\018\000\018\018\018\018\018\018\018\018\018\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\000\000\000\000\000" let norm_second_low = "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\008\012\016\020\024\027\031\035\039\043\047\051\055\059\063\066\070\074\078\082\086\000\090\093\097\101\105\109\113\000\000\004\008\012\016\020\000\027\031\035\039\043\047\051\055\059\000\066\070\074\078\082\086\000\000\093\097\101\105\109\000\116\120\120\124\124\128\128\132\132\136\136\140\140\144\144\148\148\152\000\155\155\159\159\163\163\167\167\171\171\175\175\179\179\183\183\187\187\191\191\195\000\198\198\202\202\206\206\210\210\214\000\218\000\221\221\225\225\000\229\229\233\233\237\237\241\000\244\000\247\247\251\251\255\255\000\003\000\006\006\010\010\014\014\018\000\021\021\025\025\029\029\033\033\037\037\041\041\045\045\049\049\053\053\057\000\060\060\064\064\068\068\072\072\076\076\080\080\084\084\088\088\116\092\092\096\096\100\100\000\000\104\107\000\110\000\113\116\000\119\122\125\000\000\128\131\134\137\000\140\143\000\146\149\152\000\000\000\155\158\000\161\164\164\168\000\171\000\000\174\000\177\000\000\180\000\183\186\186\190\193\196\000\199\000\202\205\000\000\000\208\000\000\000\000\000\000\000\211\211\000\214\214\000\217\217\000\220\220\224\224\228\228\232\232\236\236\242\242\248\248\254\254\000\004\004\010\010\016\016\021\000\024\024\028\028\032\032\036\036\042\042\047\051\051\000\054\054\000\000\058\058\062\062\068\068\073\073\078\078\082\082\086\086\090\090\094\094\098\098\102\102\106\106\110\110\114\114\118\118\122\122\126\126\130\130\000\000\134\134\000\000\000\000\000\000\138\138\142\142\146\146\152\152\158\158\162\162\168\168\000\000\000\000\000\000\000\000\000\000\000\000\172\175\000\178\181\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\186\000\000\000\000\000\000\000\000\000\189\000\000\000\000\000\000\191\196\201\204\209\214\000\219\000\224\229\234\241\244\247\250\253\000\003\006\009\012\015\018\021\024\027\030\033\000\036\039\042\045\048\051\054\057\062\196\204\209\214\067\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\036\000\000\000\000\000\000\000\057\062\219\224\229\000\000\000\000\074\079\000\000\000\000\000\000\000\000\000\000\000\000\000\084\000\087\000\090\000\093\000\096\000\099\000\102\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\105\110\115\118\123\126\129\132\137\140\143\146\149\154\159\164\167\170\173\176\179\182\185\188\191\194\199\202\205\208\211\214\217\220\223\226\229\232\235\238\241\244\247\250\253\000\003\006\000\000\000\000\000\000\000\000\000\194\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\105\110\000\118\000\000\000\132\000\000\000\000\149\154\159\000\009\000\012\000\015\000\018\000\021\000\024\000\027\000\030\000\033\000\036\000\039\000\042\042\047\000\050\000\053\000\056\000\059\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\062\000\065\000\068\000\071\000\074\000\077\000\080\000\083\000\086\000\089\000\092\000\095\000\098\000\101\000\104\000\107\000\110\000\113\000\116\000\119\000\122\000\125\000\128\000\131\000\000\134\134\139\000\000\000\142\000\000\000\145\000\000\000\000\148\148\153\153\158\000\161\161\166\000\169\169\174\174\179\179\184\000\187\187\192\192\197\197\202\000\205\205\210\210\215\215\220\220\225\225\230\230\000\000\235\235\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\240\243\246\249\252\255\002\005\008\011\014\017\020\023\026\029\032\035\038\041\044\047\050\053\056\059\062\065\068\071\074\077\080\083\086\089\092\095\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\098\103\108\113\118\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\123\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\133\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\138\000\000\000\000\000\000\000\145\000\000\152\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\159\166\173\180\187\194\201\208\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\215\222\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\229\236\000\243\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\250\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\015\022\000\000\029\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\036\000\000\043\050\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\057\064\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\071\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\078\085\092\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\099\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\106\000\000\000\000\000\000\113\120\000\127\134\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\144\151\158\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\165\000\172\179\189\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\196\000\000\000\000\000\000\000\000\000\203\000\000\000\000\210\000\000\000\000\217\000\000\000\000\224\000\000\000\000\000\000\000\000\000\000\000\000\231\000\000\000\000\000\000\000\000\000\238\000\245\252\000\003\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\017\000\000\000\000\000\000\000\000\000\024\000\000\000\000\031\000\000\000\000\038\000\000\000\000\045\000\000\000\000\000\000\000\000\000\000\000\000\052\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\059\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\066\070\074\078\082\086\090\094\098\102\106\110\114\118\122\126\130\134\138\142\146\150\154\158\162\166\170\174\178\182\186\190\194\198\202\206\210\214\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\218\218\222\222\226\226\230\230\234\234\240\240\244\244\248\248\252\252\000\000\004\004\010\010\016\016\020\020\024\024\030\030\034\034\038\038\042\042\046\046\050\050\054\054\058\058\062\062\068\068\072\072\076\076\080\080\084\084\090\090\094\094\098\098\102\102\106\106\110\110\114\114\118\118\122\122\126\126\132\132\138\138\144\144\150\150\154\154\158\158\162\162\166\166\172\172\176\176\180\180\184\184\190\190\196\196\202\202\206\206\210\210\214\214\218\218\222\222\226\226\230\230\236\236\242\242\246\246\250\250\254\254\002\002\006\006\010\010\014\014\018\018\022\022\026\026\030\030\034\034\038\042\046\050\000\054\000\000\000\000\059\059\063\063\067\067\073\073\079\079\085\085\091\091\097\097\103\103\109\109\115\115\121\121\127\127\131\131\135\135\139\139\145\145\151\151\157\157\163\163\169\169\173\173\177\177\181\181\185\185\191\191\197\197\203\203\209\209\215\215\221\221\227\227\233\233\239\239\245\245\249\249\253\253\003\003\009\009\015\015\021\021\027\027\031\031\035\035\039\039\000\000\000\000\000\000\043\048\053\060\067\074\081\088\043\048\053\060\067\074\081\088\095\100\105\112\119\126\000\000\095\100\105\112\119\126\000\000\133\138\143\150\157\164\171\178\133\138\143\150\157\164\171\178\185\190\195\202\209\216\223\230\185\190\195\202\209\216\223\230\237\242\247\254\005\012\000\000\237\242\247\254\005\012\000\000\019\024\029\036\043\050\057\064\000\024\000\036\000\050\000\064\071\076\081\088\095\102\109\116\071\076\081\088\095\102\109\116\123\196\128\204\133\209\138\214\143\219\148\224\153\229\000\000\158\165\172\181\190\199\208\217\158\165\172\181\190\199\208\217\226\233\240\249\002\011\020\029\226\233\240\249\002\011\020\029\038\045\052\061\070\079\088\097\038\045\052\061\070\079\088\097\106\111\116\123\128\000\135\140\106\111\123\196\123\000\009\000\000\147\152\159\164\000\171\176\128\204\133\209\159\183\189\195\201\206\211\234\000\000\218\223\201\206\138\214\000\230\236\242\248\253\002\067\009\014\019\024\248\253\148\224\014\031\191\036\000\000\038\045\050\000\057\062\143\219\153\229\045\069\000\000\000\000\000\000\000\000\000\000\000\000\000\000\072\072\072\072\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\072\072\072\072\072\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\072\072\072\072\072\072\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\073\077\081\085\089\093\097\101\105\109\113\117\121\125\129\133\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\137\141\145\149\153\157\161\165\169\173\177\181\185\189\193\197\201\205\209\213\217\221\225\229\233\237\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\241\000\248\000\255\000\006\000\013\000\020\000\027\000\034\000\041\000\048\000\055\000\062\000\000\069\000\076\000\083\000\000\000\000\000\000\090\097\000\104\111\000\118\125\000\132\139\000\146\153\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\160\000\000\000\000\000\000\000\000\000\167\000\000\000\000\000\000\000\000\000\000\000\000\000\174\000\181\000\188\000\195\000\202\000\209\000\216\000\223\000\230\000\237\000\244\000\251\000\000\002\000\009\000\016\000\000\000\000\000\000\023\030\000\037\044\000\051\058\000\065\072\000\079\086\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\093\000\000\100\107\114\121\000\000\000\128\000\000\135\137\139\141\143\145\147\149\151\153\155\157\159\161\163\165\167\169\171\173\175\177\179\181\183\185\187\189\191\193\195\197\199\201\203\205\207\209\211\213\215\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\217\000\222\000\000\000\000\000\000\000\000\000\000\227\232\237\244\251\000\005\010\015\020\025\030\035\000\040\045\050\055\060\000\065\000\070\075\000\080\085\000\090\095\100\105\110\115\120\125\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\072\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\135\139\143\147\151\155\159\163\167\171\175\179\183\187\191\195\199\203\207\211\215\219\223\227\231\235\000\000\000\000\000" +let decomp_ascii = + "\000\001\002\003\004\005\006\007\b\t\n\011\012\r\014\015\016\017\018\019\020\021\022\023\024\025\026\027\028\029\030\031 !\"#$%&'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\127" +let decomp_repl = + "\003À\003Á\003Â\003Ã\003Ä\003Å\002æ\003Ç\003È\003É\003Ê\003Ë\003Ì\003Í\003Î\003Ï\002ð\003Ñ\003Ò\003Ó\003Ô\003Õ\003Ö\002ø\003Ù\003Ú\003Û\003Ü\003Ý\002þ\003à\003á\003â\003ã\003ä\003å\003ç\003è\003é\003ê\003ë\003ì\003í\003î\003ï\003ñ\003ò\003ó\003ô\003õ\003ö\003ù\003ú\003û\003ü\003ý\003ÿ\003Ā\003ā\003Ă\003ă\003Ą\003ą\003Ć\003ć\003Ĉ\003ĉ\003Ċ\003ċ\003Č\003č\003Ď\003ď\002đ\003Ē\003ē\003Ĕ\003ĕ\003Ė\003ė\003Ę\003ę\003Ě\003ě\003Ĝ\003ĝ\003Ğ\003ğ\003Ġ\003ġ\003Ģ\003ģ\003Ĥ\003ĥ\002ħ\003Ĩ\003ĩ\003Ī\003ī\003Ĭ\003ĭ\003Į\003į\003İ\002ij\003Ĵ\003ĵ\003Ķ\003ķ\003Ĺ\003ĺ\003Ļ\003ļ\003Ľ\003ľ\002ŀ\002ł\003Ń\003ń\003Ņ\003ņ\003Ň\003ň\002ŋ\003Ō\003ō\003Ŏ\003ŏ\003Ő\003ő\002œ\003Ŕ\003ŕ\003Ŗ\003ŗ\003Ř\003ř\003Ś\003ś\003Ŝ\003ŝ\003Ş\003ş\003Š\003š\003Ţ\003ţ\003Ť\003ť\002ŧ\003Ũ\003ũ\003Ū\003ū\003Ŭ\003ŭ\003Ů\003ů\003Ű\003ű\003Ų\003ų\003Ŵ\003ŵ\003Ŷ\003ŷ\003Ÿ\003Ź\003ź\003Ż\003ż\003Ž\003ž\002ɓ\002ƃ\002ƅ\002ɔ\002ƈ\002ɖ\002ɗ\002ƌ\002ǝ\002ə\002ɛ\002ƒ\002ɠ\002ɣ\002ɩ\002ɨ\002ƙ\002ɯ\002ɲ\002ɵ\003Ơ\003ơ\002ƣ\002ƥ\002ƨ\002ʃ\002ƭ\002ʈ\003Ư\003ư\002ʊ\002ʋ\002ƴ\002ƶ\002ʒ\002ƹ\002ƽ\002dž\002lj\002nj\003Ǎ\003ǎ\003Ǐ\003ǐ\003Ǒ\003ǒ\003Ǔ\003ǔ\005Ǖ\005ǖ\005Ǘ\005ǘ\005Ǚ\005ǚ\005Ǜ\005ǜ\005Ǟ\005ǟ\005Ǡ\005ǡ\004Ǣ\004ǣ\002ǥ\003Ǧ\003ǧ\003Ǩ\003ǩ\003Ǫ\003ǫ\005Ǭ\005ǭ\004Ǯ\004ǯ\003ǰ\002dz\003Ǵ\003ǵ\003Ǹ\003ǹ\005Ǻ\005ǻ\004Ǽ\004ǽ\004Ǿ\004ǿ\003Ȁ\003ȁ\003Ȃ\003ȃ\003Ȅ\003ȅ\003Ȇ\003ȇ\003Ȉ\003ȉ\003Ȋ\003ȋ\003Ȍ\003ȍ\003Ȏ\003ȏ\003Ȑ\003ȑ\003Ȓ\003ȓ\003Ȕ\003ȕ\003Ȗ\003ȗ\003Ș\003ș\003Ț\003ț\003Ȟ\003ȟ\003Ȧ\003ȧ\003Ȩ\003ȩ\005Ȫ\005ȫ\005Ȭ\005ȭ\003Ȯ\003ȯ\005Ȱ\005ȱ\003Ȳ\003ȳ\002̀\002́\002̓\004̈́\002ʹ\001;\004΅\004Ά\002·\004Έ\004Ή\004Ί\004Ό\004Ύ\004Ώ\006ΐ\002α\002β\002γ\002δ\002ε\002ζ\002η\002θ\002ι\002κ\002λ\002μ\002ν\002ξ\002ο\002π\002ρ\002σ\002τ\002υ\002φ\002χ\002ψ\002ω\004Ϊ\004Ϋ\004ά\004έ\004ή\004ί\006ΰ\004ϊ\004ϋ\004ό\004ύ\004ώ\004ϓ\004ϔ\002ϣ\002ϥ\002ϧ\002ϩ\002ϫ\002ϭ\002ϯ\004Ѐ\004Ё\002ђ\004Ѓ\002є\002ѕ\002і\004Ї\002ј\002љ\002њ\002ћ\004Ќ\004Ѝ\004Ў\002џ\002а\002б\002в\002г\002д\002е\002ж\002з\002и\004Й\002к\002л\002м\002н\002о\002п\002р\002с\002т\002у\002ф\002х\002ц\002ч\002ш\002щ\002ъ\002ы\002ь\002э\002ю\002я\004й\004ѐ\004ё\004ѓ\004ї\004ќ\004ѝ\004ў\002ѡ\002ѣ\002ѥ\002ѧ\002ѩ\002ѫ\002ѭ\002ѯ\002ѱ\002ѳ\002ѵ\004Ѷ\004ѷ\002ѹ\002ѻ\002ѽ\002ѿ\002ҁ\002ґ\002ғ\002ҕ\002җ\002ҙ\002қ\002ҝ\002ҟ\002ҡ\002ң\002ҥ\002ҧ\002ҩ\002ҫ\002ҭ\002ү\002ұ\002ҳ\002ҵ\002ҷ\002ҹ\002һ\002ҽ\002ҿ\004Ӂ\004ӂ\002ӄ\002ӈ\002ӌ\004Ӑ\004ӑ\004Ӓ\004ӓ\002ӕ\004Ӗ\004ӗ\002ә\004Ӛ\004ӛ\004Ӝ\004ӝ\004Ӟ\004ӟ\002ӡ\004Ӣ\004ӣ\004Ӥ\004ӥ\004Ӧ\004ӧ\002ө\004Ӫ\004ӫ\004Ӭ\004ӭ\004Ӯ\004ӯ\004Ӱ\004ӱ\004Ӳ\004ӳ\004Ӵ\004ӵ\004Ӹ\004ӹ\002ա\002բ\002գ\002դ\002ե\002զ\002է\002ը\002թ\002ժ\002ի\002լ\002խ\002ծ\002կ\002հ\002ձ\002ղ\002ճ\002մ\002յ\002ն\002շ\002ո\002չ\002պ\002ջ\002ռ\002ս\002վ\002տ\002ր\002ց\002ւ\002փ\002ք\002օ\002ֆ\004آ\004أ\004ؤ\004إ\004ئ\004ۀ\004ۂ\004ۓ\006ऩ\006ऱ\006ऴ\006क़\006ख़\006ग़\006ज़\006ड़\006ढ़\006फ़\006य़\006ো\006ৌ\006ড়\006ঢ়\006য়\006ਲ਼\006ਸ਼\006ਖ਼\006ਗ਼\006ਜ਼\006ਫ਼\006ୈ\006ୋ\006ୌ\006ଡ଼\006ଢ଼\006ஔ\006ொ\006ோ\006ௌ\006ై\006ೀ\006ೇ\006ೈ\006ೊ\009ೋ\006ൊ\006ോ\006ൌ\006ේ\006ො\009ෝ\006ෞ\006གྷ\006ཌྷ\006དྷ\006བྷ\006ཛྷ\006ཀྵ\006ཱི\006ཱུ\006ྲྀ\006ླྀ\006ཱྀ\006ྒྷ\006ྜྷ\006ྡྷ\006ྦྷ\006ྫྷ\006ྐྵ\006ဦ\003ა\003ბ\003გ\003დ\003ე\003ვ\003ზ\003თ\003ი\003კ\003ლ\003მ\003ნ\003ო\003პ\003ჟ\003რ\003ს\003ტ\003უ\003ფ\003ქ\003ღ\003ყ\003შ\003ჩ\003ც\003ძ\003წ\003ჭ\003ხ\003ჯ\003ჰ\003ჱ\003ჲ\003ჳ\003ჴ\003ჵ\003Ḁ\003ḁ\003Ḃ\003ḃ\003Ḅ\003ḅ\003Ḇ\003ḇ\005Ḉ\005ḉ\003Ḋ\003ḋ\003Ḍ\003ḍ\003Ḏ\003ḏ\003Ḑ\003ḑ\003Ḓ\003ḓ\005Ḕ\005ḕ\005Ḗ\005ḗ\003Ḙ\003ḙ\003Ḛ\003ḛ\005Ḝ\005ḝ\003Ḟ\003ḟ\003Ḡ\003ḡ\003Ḣ\003ḣ\003Ḥ\003ḥ\003Ḧ\003ḧ\003Ḩ\003ḩ\003Ḫ\003ḫ\003Ḭ\003ḭ\005Ḯ\005ḯ\003Ḱ\003ḱ\003Ḳ\003ḳ\003Ḵ\003ḵ\003Ḷ\003ḷ\005Ḹ\005ḹ\003Ḻ\003ḻ\003Ḽ\003ḽ\003Ḿ\003ḿ\003Ṁ\003ṁ\003Ṃ\003ṃ\003Ṅ\003ṅ\003Ṇ\003ṇ\003Ṉ\003ṉ\003Ṋ\003ṋ\005Ṍ\005ṍ\005Ṏ\005ṏ\005Ṑ\005ṑ\005Ṓ\005ṓ\003Ṕ\003ṕ\003Ṗ\003ṗ\003Ṙ\003ṙ\003Ṛ\003ṛ\005Ṝ\005ṝ\003Ṟ\003ṟ\003Ṡ\003ṡ\003Ṣ\003ṣ\005Ṥ\005ṥ\005Ṧ\005ṧ\005Ṩ\005ṩ\003Ṫ\003ṫ\003Ṭ\003ṭ\003Ṯ\003ṯ\003Ṱ\003ṱ\003Ṳ\003ṳ\003Ṵ\003ṵ\003Ṷ\003ṷ\005Ṹ\005ṹ\005Ṻ\005ṻ\003Ṽ\003ṽ\003Ṿ\003ṿ\003Ẁ\003ẁ\003Ẃ\003ẃ\003Ẅ\003ẅ\003Ẇ\003ẇ\003Ẉ\003ẉ\003Ẋ\003ẋ\003Ẍ\003ẍ\003Ẏ\003ẏ\003Ẑ\003ẑ\003Ẓ\003ẓ\003Ẕ\003ẕ\003ẖ\003ẗ\003ẘ\003ẙ\004ẛ\003Ạ\003ạ\003Ả\003ả\005Ấ\005ấ\005Ầ\005ầ\005Ẩ\005ẩ\005Ẫ\005ẫ\005Ậ\005ậ\005Ắ\005ắ\005Ằ\005ằ\005Ẳ\005ẳ\005Ẵ\005ẵ\005Ặ\005ặ\003Ẹ\003ẹ\003Ẻ\003ẻ\003Ẽ\003ẽ\005Ế\005ế\005Ề\005ề\005Ể\005ể\005Ễ\005ễ\005Ệ\005ệ\003Ỉ\003ỉ\003Ị\003ị\003Ọ\003ọ\003Ỏ\003ỏ\005Ố\005ố\005Ồ\005ồ\005Ổ\005ổ\005Ỗ\005ỗ\005Ộ\005ộ\005Ớ\005ớ\005Ờ\005ờ\005Ở\005ở\005Ỡ\005ỡ\005Ợ\005ợ\003Ụ\003ụ\003Ủ\003ủ\005Ứ\005ứ\005Ừ\005ừ\005Ử\005ử\005Ữ\005ữ\005Ự\005ự\003Ỳ\003ỳ\003Ỵ\003ỵ\003Ỷ\003ỷ\003Ỹ\003ỹ\004ἀ\004ἁ\006ἂ\006ἃ\006ἄ\006ἅ\006ἆ\006ἇ\004Ἀ\004Ἁ\006Ἂ\006Ἃ\006Ἄ\006Ἅ\006Ἆ\006Ἇ\004ἐ\004ἑ\006ἒ\006ἓ\006ἔ\006ἕ\004Ἐ\004Ἑ\006Ἒ\006Ἓ\006Ἔ\006Ἕ\004ἠ\004ἡ\006ἢ\006ἣ\006ἤ\006ἥ\006ἦ\006ἧ\004Ἠ\004Ἡ\006Ἢ\006Ἣ\006Ἤ\006Ἥ\006Ἦ\006Ἧ\004ἰ\004ἱ\006ἲ\006ἳ\006ἴ\006ἵ\006ἶ\006ἷ\004Ἰ\004Ἱ\006Ἲ\006Ἳ\006Ἴ\006Ἵ\006Ἶ\006Ἷ\004ὀ\004ὁ\006ὂ\006ὃ\006ὄ\006ὅ\004Ὀ\004Ὁ\006Ὂ\006Ὃ\006Ὄ\006Ὅ\004ὐ\004ὑ\006ὒ\006ὓ\006ὔ\006ὕ\006ὖ\006ὗ\004Ὑ\006Ὓ\006Ὕ\006Ὗ\004ὠ\004ὡ\006ὢ\006ὣ\006ὤ\006ὥ\006ὦ\006ὧ\004Ὠ\004Ὡ\006Ὢ\006Ὣ\006Ὤ\006Ὥ\006Ὦ\006Ὧ\004ὰ\004ὲ\004ὴ\004ὶ\004ὸ\004ὺ\004ὼ\006ᾀ\006ᾁ\008ᾂ\008ᾃ\008ᾄ\008ᾅ\008ᾆ\008ᾇ\006ᾈ\006ᾉ\008ᾊ\008ᾋ\008ᾌ\008ᾍ\008ᾎ\008ᾏ\006ᾐ\006ᾑ\008ᾒ\008ᾓ\008ᾔ\008ᾕ\008ᾖ\008ᾗ\006ᾘ\006ᾙ\008ᾚ\008ᾛ\008ᾜ\008ᾝ\008ᾞ\008ᾟ\006ᾠ\006ᾡ\008ᾢ\008ᾣ\008ᾤ\008ᾥ\008ᾦ\008ᾧ\006ᾨ\006ᾩ\008ᾪ\008ᾫ\008ᾬ\008ᾭ\008ᾮ\008ᾯ\004ᾰ\004ᾱ\006ᾲ\004ᾳ\006ᾴ\004ᾶ\006ᾷ\004Ᾰ\004Ᾱ\004Ὰ\004ᾼ\004῁\006ῂ\004ῃ\006ῄ\004ῆ\006ῇ\004Ὲ\004Ὴ\004ῌ\005῍\005῎\005῏\004ῐ\004ῑ\006ῒ\004ῖ\006ῗ\004Ῐ\004Ῑ\004Ὶ\005῝\005῞\005῟\004ῠ\004ῡ\006ῢ\004ῤ\004ῥ\004ῦ\006ῧ\004Ῠ\004Ῡ\004Ὺ\004Ῥ\004῭\001`\006ῲ\004ῳ\006ῴ\004ῶ\006ῷ\004Ὸ\004Ὼ\004ῼ\002´\000\003ⅰ\003ⅱ\003ⅲ\003ⅳ\003ⅴ\003ⅵ\003ⅶ\003ⅷ\003ⅸ\003ⅹ\003ⅺ\003ⅻ\003ⅼ\003ⅽ\003ⅾ\003ⅿ\003ⓐ\003ⓑ\003ⓒ\003ⓓ\003ⓔ\003ⓕ\003ⓖ\003ⓗ\003ⓘ\003ⓙ\003ⓚ\003ⓛ\003ⓜ\003ⓝ\003ⓞ\003ⓟ\003ⓠ\003ⓡ\003ⓢ\003ⓣ\003ⓤ\003ⓥ\003ⓦ\003ⓧ\003ⓨ\003ⓩ\006が\006ぎ\006ぐ\006げ\006ご\006ざ\006じ\006ず\006ぜ\006ぞ\006だ\006ぢ\006づ\006で\006ど\006ば\006ぱ\006び\006ぴ\006ぶ\006ぷ\006べ\006ぺ\006ぼ\006ぽ\006ゔ\006ゞ\006ガ\006ギ\006グ\006ゲ\006ゴ\006ザ\006ジ\006ズ\006ゼ\006ゾ\006ダ\006ヂ\006ヅ\006デ\006ド\006バ\006パ\006ビ\006ピ\006ブ\006プ\006ベ\006ペ\006ボ\006ポ\006ヴ\006ヷ\006ヸ\006ヹ\006ヺ\006ヾ\001\001\001\001\001\001\001\001\001 \001 +\001\001\001
\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\"\001*\001:\001<\001>\001?\001\\\001|\001 \001.\004יִ\004ײַ\004שׁ\004שׂ\006שּׁ\006שּׂ\004אַ\004אָ\004אּ\004בּ\004גּ\004דּ\004הּ\004וּ\004זּ\004טּ\004יּ\004ךּ\004כּ\004לּ\004מּ\004נּ\004סּ\004ףּ\004פּ\004צּ\004קּ\004רּ\004שּ\004תּ\004וֹ\004בֿ\004כֿ\004פֿ\003a\003b\003c\003d\003e\003f\003g\003h\003i\003j\003k\003l\003m\003n\003o\003p\003q\003r\003s\003t\003u\003v\003w\003x\003y\003z" +let decomp_prim = + "\000\000\000\002\003\004\005\006\007\000\000\000\000\008\009\010\011\012\013\014\015\016\000\000\017\000\000\018\000\000\000\000\000\000\000\000\019\020\000\021\022\023\000\000\000\024\025\026\000\027\000\028\000\029\000\030\000\000\000\000\000\031\032\000\033\000\034\035\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\036\037\038\039\040\041\042\043\044\045\000\000\000\046\000\000\000\000\000\000\000\000\000\000\000\000\047\048\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\049\050\051\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\052\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\053\054\000\000\000\000\000\000\000\000\000\000\000\000\000\055\056\000\000\000" +let decomp_second_high = + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\000\002\002\002\002\002\002\002\000\002\002\002\002\002\002\000\002\002\002\002\002\002\002\002\002\000\002\002\002\002\002\002\000\000\002\002\002\002\002\000\002\002\002\002\002\002\002\002\002\003\003\003\003\003\003\003\003\003\000\003\003\003\003\003\003\003\003\003\003\003\003\003\003\003\003\003\003\003\003\003\000\003\003\003\003\003\003\003\003\003\000\003\000\003\003\003\003\000\003\003\003\003\003\003\003\000\003\000\003\003\003\003\003\003\000\003\000\003\003\003\003\003\003\003\000\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\000\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\004\000\000\004\004\000\004\000\004\004\000\004\004\004\000\000\004\004\004\004\000\004\004\000\004\004\004\000\000\000\004\004\000\004\004\004\004\000\004\000\000\004\000\004\000\000\004\000\004\004\005\005\005\005\000\005\000\005\005\000\000\000\005\000\000\000\000\000\000\000\005\005\000\005\005\000\005\005\000\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\000\005\005\005\005\005\005\005\000\005\005\005\005\005\005\005\005\005\005\005\005\005\000\005\005\000\000\005\005\005\005\005\005\005\005\005\006\006\006\006\006\006\006\006\006\006\006\006\006\006\006\006\006\006\006\006\006\006\006\006\006\006\006\000\000\006\006\000\000\000\000\000\000\006\006\006\006\006\006\006\006\006\006\006\006\006\006\000\000\000\000\000\000\000\000\000\000\000\000\006\006\000\006\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\000\000\000\000\000\000\000\000\000\006\000\000\000\000\000\000\006\006\006\006\006\006\000\006\000\006\006\006\006\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\000\007\007\007\007\007\007\007\007\007\007\007\007\007\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\000\000\000\000\000\000\000\007\007\007\007\007\000\000\000\000\007\007\000\000\000\000\000\000\000\000\000\000\000\000\000\007\000\007\000\007\000\007\000\007\000\007\000\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\007\008\008\008\008\008\008\008\008\008\008\008\008\008\008\008\008\008\008\008\008\008\008\000\000\000\000\000\000\000\000\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\008\000\008\000\000\000\008\000\000\000\000\008\008\008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\008\008\000\008\000\008\000\008\000\008\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\008\000\000\008\008\008\000\000\000\008\000\000\000\008\000\000\000\000\009\009\009\009\009\000\009\009\009\000\009\009\009\009\009\009\009\000\009\009\009\009\009\009\009\000\009\009\009\009\009\009\009\009\009\009\009\009\000\000\009\009\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\010\010\010\010\010\010\010\010\010\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\010\010\010\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\010\010\010\010\010\010\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\010\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\010\010\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\010\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\011\011\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\000\000\000\000\000\000\011\011\000\011\011\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\011\011\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\000\011\011\011\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\000\000\000\000\000\000\000\000\000\011\000\000\000\000\011\000\000\000\000\011\000\000\000\000\011\000\000\000\000\000\000\000\000\000\000\000\000\011\000\000\000\000\000\000\000\000\000\011\000\011\011\000\011\000\000\000\000\000\000\000\000\011\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\000\000\000\000\000\000\000\000\000\011\000\000\000\000\011\000\000\000\000\011\000\000\000\000\011\000\000\000\000\000\000\000\000\000\000\000\000\011\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\012\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\013\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\000\015\000\000\000\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\016\017\017\017\017\017\017\017\017\000\000\000\000\000\000\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\017\000\000\017\017\017\017\017\017\000\000\017\017\017\017\017\017\017\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\000\000\018\018\018\018\018\018\000\000\018\018\018\019\019\019\019\019\000\019\000\019\000\019\000\019\019\019\019\019\019\019\019\019\019\019\019\019\019\019\019\019\019\007\019\007\019\007\019\007\019\007\019\007\019\007\000\000\019\019\019\019\019\019\019\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\020\021\021\021\021\021\021\021\021\021\021\021\021\021\021\021\021\000\021\021\021\021\021\006\021\000\007\000\000\021\021\021\021\000\021\021\021\006\021\006\021\021\021\021\021\021\021\006\000\000\021\021\022\022\022\006\000\022\022\022\022\022\022\007\022\022\022\022\022\022\022\006\022\022\006\022\000\000\022\022\022\000\022\022\022\006\022\006\022\022\000\000\000\000\000\000\000\000\000\000\000\000\000\000\022\022\022\022\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\022\022\022\022\022\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\022\022\022\022\022\022\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\022\022\022\022\022\022\022\022\022\022\022\022\022\022\022\022\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\022\022\022\022\022\022\022\022\022\022\023\023\023\023\023\023\023\023\023\023\023\023\023\023\023\023\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\023\000\000\023\000\023\000\023\000\000\000\000\000\000\023\023\000\023\023\000\023\023\000\023\023\000\023\023\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\023\000\000\000\000\000\000\000\000\000\023\000\000\000\000\000\000\000\000\000\000\000\000\000\023\000\024\000\024\000\024\000\024\000\024\000\024\000\024\000\024\000\024\000\024\000\024\000\000\024\000\024\000\024\000\000\000\000\000\000\024\024\000\024\024\000\024\024\000\024\024\000\024\024\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\024\000\000\024\024\024\024\000\000\000\024\000\000\024\024\024\024\024\024\024\024\024\024\024\024\024\024\024\024\024\024\024\024\024\025\025\025\025\025\025\025\025\025\025\025\025\025\025\025\025\025\025\025\025\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\025\000\025\000\000\000\000\000\000\000\000\000\000\025\025\025\025\025\025\025\025\025\025\025\025\025\000\025\025\025\025\025\000\025\000\025\025\000\025\025\000\025\025\025\025\025\025\025\025\025\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\022\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\025\025\025\025\025\025\025\025\025\025\025\026\026\026\026\026\026\026\026\026\026\026\026\026\026\026\000\000\000\000\000" +let decomp_second_low = + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\008\012\016\020\024\027\031\035\039\043\047\051\055\059\063\066\070\074\078\082\086\000\090\093\097\101\105\109\113\000\116\120\124\128\132\136\000\140\144\148\152\156\160\164\168\172\000\176\180\184\188\192\196\000\000\200\204\208\212\216\000\220\224\228\232\236\240\244\248\252\000\004\008\012\016\020\024\028\032\000\035\039\043\047\051\055\059\063\067\071\075\079\083\087\091\095\099\103\107\111\115\000\118\122\126\130\134\138\142\146\150\000\154\000\157\161\165\169\000\173\177\181\185\189\193\197\000\200\000\203\207\211\215\219\223\000\227\000\230\234\238\242\246\250\254\000\001\005\009\013\017\021\025\029\033\037\041\045\049\053\057\061\065\069\073\000\076\080\084\088\092\096\100\104\108\112\116\120\124\128\132\136\140\144\148\152\156\160\164\000\000\168\171\000\174\000\177\180\000\183\186\189\000\000\192\195\198\201\000\204\207\000\210\213\216\000\000\000\219\222\000\225\228\232\236\000\239\000\000\242\000\245\000\000\248\000\251\254\002\006\009\012\000\015\000\018\021\000\000\000\024\000\000\000\000\000\000\000\027\027\000\030\030\000\033\033\000\036\040\044\048\052\056\060\064\068\074\080\086\092\098\104\110\000\116\122\128\134\140\145\150\000\153\157\161\165\169\173\177\183\189\194\199\203\203\000\206\210\000\000\214\218\222\228\234\239\244\249\254\002\006\010\014\018\022\026\030\034\038\042\046\050\054\058\062\066\070\074\078\082\086\090\094\098\102\106\000\000\110\114\000\000\000\000\000\000\118\122\126\130\134\140\146\152\158\162\166\172\178\182\000\000\000\000\000\000\000\000\000\000\000\000\186\189\000\192\195\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\203\000\000\000\000\000\000\205\210\215\218\223\228\000\233\000\238\243\248\255\002\005\008\011\014\017\020\023\026\029\032\035\038\041\044\047\000\050\053\056\059\062\065\068\071\076\081\086\091\096\101\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\050\000\000\000\000\000\000\000\108\113\118\123\128\000\000\000\000\133\138\000\000\000\000\000\000\000\000\000\000\000\000\000\143\000\146\000\149\000\152\000\155\000\158\000\161\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\164\169\174\177\182\185\188\191\196\199\202\205\208\213\218\223\226\229\232\235\238\241\244\247\250\253\002\005\008\011\014\017\020\023\026\029\032\035\038\041\044\047\050\053\056\059\062\065\000\000\000\000\000\000\000\000\000\068\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\073\078\000\083\000\000\000\088\000\000\000\000\093\098\103\000\108\000\111\000\114\000\117\000\120\000\123\000\126\000\129\000\132\000\135\000\138\000\141\146\151\000\154\000\157\000\160\000\163\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\166\000\169\000\172\000\175\000\178\000\181\000\184\000\187\000\190\000\193\000\196\000\199\000\202\000\205\000\208\000\211\000\214\000\217\000\220\000\223\000\226\000\229\000\232\000\235\000\000\238\243\248\000\000\000\251\000\000\000\254\000\000\000\000\001\006\011\016\021\000\024\029\034\000\037\042\047\052\057\062\067\000\070\075\080\085\090\095\100\000\103\108\113\118\123\128\133\138\143\148\153\158\000\000\163\168\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\173\176\179\182\185\188\191\194\197\200\203\206\209\212\215\218\221\224\227\230\233\236\239\242\245\248\251\254\001\004\007\010\013\016\019\022\025\028\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\031\036\041\046\051\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\056\000\061\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\066\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\071\000\000\000\000\000\000\000\078\000\000\085\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\092\099\106\113\120\127\134\141\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\148\155\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\162\169\000\176\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\183\000\000\190\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\197\204\211\000\000\218\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\225\000\000\232\239\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\246\253\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\018\025\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\032\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\039\000\000\000\000\000\000\046\053\000\060\067\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\077\084\091\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\098\000\105\112\122\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\129\000\000\000\000\000\000\000\000\000\136\000\000\000\000\143\000\000\000\000\150\000\000\000\000\157\000\000\000\000\000\000\000\000\000\000\000\000\164\000\000\000\000\000\000\000\000\000\171\000\178\185\000\192\000\000\000\000\000\000\000\000\199\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\206\000\000\000\000\000\000\000\000\000\213\000\000\000\000\220\000\000\000\000\227\000\000\000\000\234\000\000\000\000\000\000\000\000\000\000\000\000\241\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\248\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\255\003\007\011\015\019\023\027\031\035\039\043\047\051\055\059\063\067\071\075\079\083\087\091\095\099\103\107\111\115\119\123\127\131\135\139\143\147\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\151\155\159\163\167\171\175\179\183\189\195\199\203\207\211\215\219\223\227\231\235\241\247\253\003\007\011\015\019\025\031\035\039\043\047\051\055\059\063\067\071\075\079\083\087\091\095\101\107\111\115\119\123\127\131\135\139\145\151\155\159\163\167\171\175\179\183\187\191\195\199\203\207\211\215\219\223\229\235\241\247\253\003\009\015\019\023\027\031\035\039\043\047\053\059\063\067\071\075\079\083\089\095\101\107\113\119\123\127\131\135\139\143\147\151\155\159\163\167\171\175\181\187\193\199\203\207\211\215\219\223\227\231\235\239\243\247\251\255\003\007\011\015\019\023\027\031\035\039\043\047\051\055\059\000\063\000\000\000\000\068\072\076\080\084\090\096\102\108\114\120\126\132\138\144\150\156\162\168\174\180\186\192\198\204\208\212\216\220\224\228\234\240\246\252\002\008\014\020\026\032\036\040\044\048\052\056\060\064\070\076\082\088\094\100\106\112\118\124\130\136\142\148\154\160\166\172\178\184\188\192\196\200\206\212\218\224\230\236\242\248\254\004\008\012\016\020\024\028\032\000\000\000\000\000\000\036\041\046\053\060\067\074\081\088\093\098\105\112\119\126\133\140\145\150\157\164\171\000\000\178\183\188\195\202\209\000\000\216\221\226\233\240\247\254\005\012\017\022\029\036\043\050\057\064\069\074\081\088\095\102\109\116\121\126\133\140\147\154\161\168\173\178\185\192\199\000\000\206\211\216\223\230\237\000\000\244\249\254\005\012\019\026\033\000\040\000\045\000\052\000\059\066\071\076\083\090\097\104\111\118\123\128\135\142\149\156\163\170\081\175\086\180\091\185\096\190\118\195\123\200\128\000\000\205\212\219\228\237\246\255\008\017\024\031\040\049\058\067\076\085\092\099\108\117\126\135\144\153\160\167\176\185\194\203\212\221\228\235\244\253\006\015\024\033\040\047\056\065\074\083\092\101\106\111\118\123\000\130\135\142\147\152\210\157\000\023\000\000\162\167\174\179\000\186\191\198\218\203\223\208\213\219\225\231\236\241\248\000\000\248\253\004\009\014\228\000\019\025\031\037\042\047\101\054\059\064\069\076\081\086\238\091\096\205\101\000\000\103\110\115\000\122\127\134\233\139\243\144\149\000\000\000\000\000\000\000\000\000\000\000\000\000\000\152\152\152\152\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\152\152\152\152\152\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\152\152\152\152\152\152\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\153\157\161\165\169\173\177\181\185\189\193\197\201\205\209\213\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\217\221\225\229\233\237\241\245\249\253\001\005\009\013\017\021\025\029\033\037\041\045\049\053\057\061\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\065\000\072\000\079\000\086\000\093\000\100\000\107\000\114\000\121\000\128\000\135\000\142\000\000\149\000\156\000\163\000\000\000\000\000\000\170\177\000\184\191\000\198\205\000\212\219\000\226\233\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\240\000\000\000\000\000\000\000\000\000\247\000\000\000\000\000\000\000\000\000\000\000\000\000\254\000\005\000\012\000\019\000\026\000\033\000\040\000\047\000\054\000\061\000\068\000\075\000\000\082\000\089\000\096\000\000\000\000\000\000\103\110\000\117\124\000\131\138\000\145\152\000\159\166\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\173\000\000\180\187\194\201\000\000\000\208\000\000\215\217\219\221\223\225\227\229\231\233\235\237\239\241\243\245\247\249\251\253\255\001\003\005\007\009\011\013\015\017\019\021\023\025\027\029\031\033\035\037\039\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\041\000\046\000\000\000\000\000\000\000\000\000\000\051\056\061\068\075\080\085\090\095\100\105\110\115\000\120\125\130\135\140\000\145\000\150\155\000\160\165\000\170\175\180\185\190\195\200\205\210\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\152\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\215\219\223\227\231\235\239\243\247\251\255\003\007\011\015\019\023\027\031\035\039\043\047\051\055\059\000\000\000\000\000" diff --git a/src/update.ml b/src/update.ml index 3647618..3fac115 100644 --- a/src/update.ml +++ b/src/update.ml @@ -576,6 +576,7 @@ let makeCaseSensitiveOnRoot = makeCaseSensitive (thisRootsGlobalName fspath); Lwt.return ()) +(*FIX: remove when Unison version > 2.40 *) let canMakeCaseSensitive () = Globals.allRootsMap (fun r -> Remote.commandAvailable r "makeCaseSensitive") >>= fun l -> diff --git a/unicode_utils/README b/unicode_utils/README new file mode 100644 index 0000000..b1b74b1 --- /dev/null +++ b/unicode_utils/README @@ -0,0 +1,2 @@ +This directory contains the code for building the tables in +src/unison_tables.ml. diff --git a/unicode_utils/codepages/lowcase.dat b/unicode_utils/codepages/lowcase.dat Binary files differnew file mode 100644 index 0000000..62b6e2e --- /dev/null +++ b/unicode_utils/codepages/lowcase.dat diff --git a/unicode_utils/codepages/upcase.dat b/unicode_utils/codepages/upcase.dat Binary files differnew file mode 100644 index 0000000..bb6f9be --- /dev/null +++ b/unicode_utils/codepages/upcase.dat diff --git a/unicode_utils/reorder.ml b/unicode_utils/reorder.ml new file mode 100644 index 0000000..3399c5a --- /dev/null +++ b/unicode_utils/reorder.ml @@ -0,0 +1,738 @@ +let combining_property_bitmap = "\ +\x00\x00\x00\x01\x02\x03\x04\x05\ +\x00\x06\x07\x08\x09\x0A\x0B\x0C\ +\x0D\x00\x00\x00\x00\x00\x00\x0E\ +\x0F\x10\x00\x00\x00\x00\x00\x00\ +\x11\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x12\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x13\x00\x00\x14\x00\ +\xE6\xE6\xE6\xE6\xE6\xE6\xE6\xE6\ +\xE6\xE6\xE6\xE6\xE6\xE6\xE6\xE6\ +\xE6\xE6\xE6\xE6\xE6\xE8\xDC\xDC\ +\xDC\xDC\xE8\xD8\xDC\xDC\xDC\xDC\ +\xDC\xCA\xCA\xDC\xDC\xDC\xDC\xCA\ +\xCA\xDC\xDC\xDC\xDC\xDC\xDC\xDC\ +\xDC\xDC\xDC\xDC\x01\x01\x01\x01\ +\x01\xDC\xDC\xDC\xDC\xE6\xE6\xE6\ +\xE6\xE6\xE6\xE6\xE6\xF0\xE6\xDC\ +\xDC\xDC\xE6\xE6\xE6\xDC\xDC\x00\ +\xE6\xE6\xE6\xDC\xDC\xDC\xDC\xE6\ +\x00\x00\x00\x00\x00\xEA\xEA\xE9\ +\xEA\xEA\xE9\xE6\xE6\xE6\xE6\xE6\ +\xE6\xE6\xE6\xE6\xE6\xE6\xE6\xE6\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\xE6\xE6\xE6\xE6\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\xDC\xE6\xE6\xE6\xE6\xDC\xE6\ +\xE6\xE6\xDE\xDC\xE6\xE6\xE6\xE6\ +\xE6\xE6\x00\xDC\xDC\xDC\xDC\xDC\ +\xE6\xE6\xDC\xE6\xE6\xDE\xE4\xE6\ +\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\ +\x12\x13\x00\x14\x15\x16\x00\x17\ +\x00\x18\x19\x00\xE6\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\xE6\xE6\xE6\xE6\xE6\xE6\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x1B\x1C\x1D\x1E\x1F\ +\x20\x21\x22\xE6\xE6\xDC\xDC\xE6\ +\xE6\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x23\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\xE6\xE6\ +\xE6\xE6\xE6\xE6\xE6\x00\x00\xE6\ +\xE6\xE6\xE6\xDC\xE6\x00\x00\xE6\ +\xE6\x00\xDC\xE6\xE6\xDC\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x24\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\xE6\xDC\xE6\xE6\xDC\xE6\xE6\xDC\ +\xDC\xDC\xE6\xDC\xDC\xE6\xDC\xE6\ +\xE6\xE6\xDC\xE6\xDC\xE6\xDC\xE6\ +\xDC\xE6\xE6\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x07\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x09\x00\x00\ +\x00\xE6\xDC\xE6\xE6\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x07\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x09\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x07\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x09\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x07\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x09\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x07\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x09\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x09\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x09\x00\x00\ +\x00\x00\x00\x00\x00\x54\x5B\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x07\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x09\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x09\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x09\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x67\x67\x09\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x6B\x6B\x6B\x6B\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x76\x76\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x7A\x7A\x7A\x7A\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\xDC\xDC\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xDC\x00\xDC\ +\x00\xD8\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x81\x82\x00\x84\x00\x00\x00\ +\x00\x00\x82\x82\x82\x82\x00\x00\ +\x82\x00\xE6\xE6\x09\x00\xE6\xE6\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\xDC\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x07\ +\x00\x09\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x09\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x09\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x09\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xE6\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\xE4\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\xDE\xE6\xDC\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\xE6\xE6\x01\x01\xE6\xE6\xE6\xE6\ +\x01\x01\x01\xE6\xE6\x00\x00\x00\ +\x00\xE6\x00\x00\x00\x01\x01\xE6\ +\xDC\xE6\x01\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\xDA\xE4\xE8\xDE\xE0\xE0\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x08\x08\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x1A\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\xE6\xE6\xE6\xE6\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00" + +let combining_class c = + if c > 0xffff then 0 else + let v = get combining_property_bitmap (c lsr 8) in + if v = 0 then 0 else + get combining_property_bitmap (v lsl 8 + c land 0xff) + +(* +let _ = +for c = 0 to 0xffff do + let v = combining_class c in + if v <> 0 then + Format.printf "%04x => %02x@." c v +done +*) + +let rec find_loc s i l p = + if i = 0 then i else + let i' = prev_char s i in + let (v, _) = decode_char s i' l in + let p' = combining_class v in + if p' <= p then i else + find_loc s i' l p + +let rec scan s i l p = + if i < l then begin + let c = get s i in + if c < 0x80 then + scan s (i + 1) l 0 + else if c < 0xE0 then begin + (* 80 - 7FF *) + if i + 1 >= l then fail () else + let c1 = get s (i + 1) in + let v = c lsl 6 + c1 - 0x3080 in + cont s i l (i + 2) p v + end else if c < 0xF0 then begin + (* 800 - FFFF *) + if i + 2 >= l then fail () else + let c1 = get s (i + 1) in + let c2 = get s (i + 2) in + let v = c lsl 12 + c1 lsl 6 + c2 - 0xe2080 in + cont s i l (i + 3) p v + end else begin + (* 10000 - 10FFFF *) + if i + 3 >= l then fail () else + scan s (i + 4) l 0 + end + end + +and cont s i l j p v = + let p' = combining_class v in + if p' = 0 || p <= p' then + scan s j l p' + else begin + (* move char to the right location *) + let k = find_loc s i l p' in + let d = j - i in + let s' = String.sub s i d in + String.blit s k s (k + d) (i - k); + String.blit s' 0 s k d; + scan s j l p + end + +let order s = + scan s 0 (String.length s) 0 diff --git a/unicode_utils/unicode.ml b/unicode_utils/unicode.ml new file mode 100644 index 0000000..38bfb70 --- /dev/null +++ b/unicode_utils/unicode.ml @@ -0,0 +1,815 @@ + +open Unicode_tables + +exception Invalid + +let fail () = raise Invalid + +let get s i = Char.code (String.unsafe_get s i) +let set s i v = String.unsafe_set s i (Char.unsafe_chr v) + +(****) + +let hangul_sbase = 0xAC00 +let hangul_lbase = 0x1100 +let hangul_vbase = 0x1161 +let hangul_tbase = 0x11A7 + +let hangul_scount = 11172 +let hangul_lcount = 19 +let hangul_vcount = 21 +let hangul_tcount = 28 +let hangul_ncount = hangul_vcount * hangul_tcount + +let set_char_3 s i c = + set s i (c lsr 12 + 0xE0); + set s (i + 1) ((c lsr 6) land 0x3f + 0x80); + set s (i + 2) (c land 0x3f + 0x80) + +let rec norm s i l s' j = + if i < l then begin + let c = get s i in + if c < 0x80 then begin + set s' j (get ascii_lower c); + norm s (i + 1) l s' (j + 1) + end else if c < 0xE0 then begin + (* 80 - 7FF *) + if c < 0xc2 || i + 1 >= l then raise Invalid; + let c1 = get s (i + 1) in + if c1 land 0xc0 <> 0x80 then raise Invalid; + let idx = get norm_prim (c - 0xc0) in + let idx = idx lsl 6 + c1 - 0x80 in + let k = get norm_second_high idx in + if k = 0 then begin + set s' j c; + set s' (j + 1) c1; + norm s (i + 2) l s' (j + 2) + end else begin + let k = (k - 2) lsl 8 + get norm_second_low idx in + let n = get norm_repl k in + String.blit norm_repl (k + 1) s' j n; + norm s (i + 2) l s' (j + n) + end + end else if c < 0xF0 then begin + (* 800 - FFFF *) + if i + 2 >= l then raise Invalid; + let c1 = get s (i + 1) in + if c1 land 0xc0 <> 0x80 then raise Invalid; + let idx = c lsl 6 + c1 - 0x3880 in + if idx < 0x20 then raise Invalid; + let c2 = get s (i + 2) in + if c2 land 0xc0 <> 0x80 then raise Invalid; + let idx = get norm_prim idx in + let idx = idx lsl 6 + c2 - 0x80 in + let k = get norm_second_high idx in + if k = 0 then begin + set s' j c; + set s' (j + 1) c1; + set s' (j + 2) c2; + norm s (i + 3) l s' (j + 3) + end else if k = 1 then begin + let v = c lsl 12 + c1 lsl 6 + c2 - (0x000E2080 + hangul_sbase) in + if v >= hangul_scount then begin + set s' j c; + set s' (j + 1) c1; + set s' (j + 2) c2; + norm s (i + 3) l s' (j + 3) + end else begin + set_char_3 s' j (v / hangul_ncount + hangul_lbase); + set_char_3 s' (j + 3) + ((v mod hangul_ncount) / hangul_tcount + hangul_vbase); + if v mod hangul_tcount = 0 then + norm s (i + 3) l s' (j + 6) + else begin + set_char_3 s' (j + 6) ((v mod hangul_tcount) + hangul_tbase); + norm s (i + 3) l s' (j + 9) + end + end + end else begin + let k = (k - 2) lsl 8 + get norm_second_low idx in + let n = get norm_repl k in + String.blit norm_repl (k + 1) s' j n; + norm s (i + 3) l s' (j + n) + end + end else begin + (* 10000 - 10FFFF *) + if i + 3 >= l then raise Invalid; + let c1 = get s (i + 1) in + let c2 = get s (i + 2) in + let c3 = get s (i + 3) in + if (c1 lor c2 lor c3) land 0xc0 <> 0x80 then raise Invalid; + let v = c lsl 18 + c1 lsl 12 + c2 lsl 6 + c3 - 0x03c82080 in + if v < 0x10000 || v > 0x10ffff then raise Invalid; + set s' j c; + set s' (j + 1) c1; + set s' (j + 2) c2; + set s' (j + 3) c3; + norm s (i + 4) l s' (j + 4) + end + end else + String.sub s' 0 j + +let normalize s = + let l = String.length s in + let s' = String.create (3 * l) in + try norm s 0 l s' 0 with Invalid -> s + +(****) + +let rec compare_rec s s' i l = + if i = l then begin + if l < String.length s then 1 else + if l < String.length s' then -1 else + 0 + end else begin + let c = get s i in + let c' = get s' i in + if c < 0x80 && c' < 0x80 then begin + let v = compare (get ascii_lower c) (get ascii_lower c') in + if v <> 0 then v else compare_rec s s' (i + 1) l + end else + compare (normalize s) (normalize s') + end + +let compare s s' = + compare_rec s s' 0 (min (String.length s) (String.length s')) + +(****) + +let rec decode_char s i l = + if i = l then fail () else + let c = get s i in + if c < 0x80 then + cont s (i + 1) l c + else if c < 0xE0 then begin + (* 80 - 7FF *) + if c < 0xc2 || i + 1 >= l then fail () else + let c1 = get s (i + 1) in + if c1 land 0xc0 <> 0x80 then fail () else + let v = c lsl 6 + c1 - 0x3080 in + cont s (i + 2) l v + end else if c < 0xF0 then begin + (* 800 - FFFF *) + if i + 2 >= l then fail () else + let c1 = get s (i + 1) in + let c2 = get s (i + 2) in + if (c1 lor c2) land 0xc0 <> 0x80 then fail () else + let v = c lsl 12 + c1 lsl 6 + c2 - 0xe2080 in + if v < 0x800 then fail () else + cont s (i + 3) l v + end else begin + (* 10000 - 10FFFF *) + if i + 3 >= l then fail () else + let c1 = get s (i + 1) in + let c2 = get s (i + 2) in + let c3 = get s (i + 3) in + if (c1 lor c2 lor c3) land 0xc0 <> 0x80 then fail () else + let v = c lsl 18 + c1 lsl 12 + c2 lsl 6 + c3 - 0x03c82080 in + if v < 0x10000 || v > 0x10ffff then fail () else + cont s (i + 4) l v + end + +and cont s i l v = (v, i) + +let encode_char s i l c = + if c < 0x80 then begin + if i >= l then fail () else begin + set s i c; + i + 1 + end + end else if c < 0x800 then begin + if i + 1 >= l then fail () else begin + set s i (c lsr 6 + 0xC0); + set s (i + 1) (c land 0x3f + 0x80); + i + 2 + end + end else if c < 0x10000 then begin + if i + 1 >= l then fail () else begin + set s i (c lsr 12 + 0xE0); + set s (i + 1) ((c lsr 6) land 0x3f + 0x80); + set s (i + 2) (c land 0x3f + 0x80); + i + 3 + end + end else begin + if i + 1 >= l then fail () else begin + set s i (c lsr 18 + 0xF0); + set s (i + 1) ((c lsr 12) land 0x3f + 0x80); + set s (i + 2) ((c lsr 6) land 0x3f + 0x80); + set s (i + 3) (c land 0x3f + 0x80); + i + 4 + end + end + +let rec prev_char s i = + let i = i - 1 in + if i < 0 then fail () else + if (get s i) land 0xc0 <> 0x80 then i else prev_char s i + +(****) + +let uniCharPrecompSourceTable = [| + 0x00000300; 0x00540000; 0x00000301; 0x00750054; + 0x00000302; 0x002000C9; 0x00000303; 0x001C00E9; + 0x00000304; 0x002C0105; 0x00000306; 0x00200131; + 0x00000307; 0x002E0151; 0x00000308; 0x0036017F; + 0x00000309; 0x001801B5; 0x0000030A; 0x000601CD; + 0x0000030B; 0x000601D3; 0x0000030C; 0x002501D9; + 0x0000030F; 0x000E01FE; 0x00000311; 0x000C020C; + 0x00000313; 0x000E0218; 0x00000314; 0x00100226; + 0x0000031B; 0x00040236; 0x00000323; 0x002A023A; + 0x00000324; 0x00020264; 0x00000325; 0x00020266; + 0x00000326; 0x00040268; 0x00000327; 0x0016026C; + 0x00000328; 0x000A0282; 0x0000032D; 0x000C028C; + 0x0000032E; 0x00020298; 0x00000330; 0x0006029A; + 0x00000331; 0x001102A0; 0x00000338; 0x002C02B1; + 0x00000342; 0x001D02DD; 0x00000345; 0x003F02FA; + 0x00000653; 0x00010339; 0x00000654; 0x0006033A; + 0x00000655; 0x00010340; 0x0000093C; 0x00030341; + 0x000009BE; 0x00010344; 0x000009D7; 0x00010345; + 0x00000B3E; 0x00010346; 0x00000B56; 0x00010347; + 0x00000B57; 0x00010348; 0x00000BBE; 0x00020349; + 0x00000BD7; 0x0002034B; 0x00000C56; 0x0001034D; + 0x00000CC2; 0x0001034E; 0x00000CD5; 0x0003034F; + 0x00000CD6; 0x00010352; 0x00000D3E; 0x00020353; + 0x00000D57; 0x00010355; 0x00000DCA; 0x00020356; + 0x00000DCF; 0x00010358; 0x00000DDF; 0x00010359; + 0x0000102E; 0x0001035A; 0x00003099; 0x0030035B; + 0x0000309A; 0x000A038B +|] + +let uniCharBMPPrecompDestinationTable = [| + 0x0041; 0x00C0; 0x0045; 0x00C8; 0x0049; 0x00CC; 0x004E; 0x01F8; + 0x004F; 0x00D2; 0x0055; 0x00D9; 0x0057; 0x1E80; 0x0059; 0x1EF2; + 0x0061; 0x00E0; 0x0065; 0x00E8; 0x0069; 0x00EC; 0x006E; 0x01F9; + 0x006F; 0x00F2; 0x0075; 0x00F9; 0x0077; 0x1E81; 0x0079; 0x1EF3; + 0x00A8; 0x1FED; 0x00C2; 0x1EA6; 0x00CA; 0x1EC0; 0x00D4; 0x1ED2; + 0x00DC; 0x01DB; 0x00E2; 0x1EA7; 0x00EA; 0x1EC1; 0x00F4; 0x1ED3; + 0x00FC; 0x01DC; 0x0102; 0x1EB0; 0x0103; 0x1EB1; 0x0112; 0x1E14; + 0x0113; 0x1E15; 0x014C; 0x1E50; 0x014D; 0x1E51; 0x01A0; 0x1EDC; + 0x01A1; 0x1EDD; 0x01AF; 0x1EEA; 0x01B0; 0x1EEB; 0x0391; 0x1FBA; + 0x0395; 0x1FC8; 0x0397; 0x1FCA; 0x0399; 0x1FDA; 0x039F; 0x1FF8; + 0x03A5; 0x1FEA; 0x03A9; 0x1FFA; 0x03B1; 0x1F70; 0x03B5; 0x1F72; + 0x03B7; 0x1F74; 0x03B9; 0x1F76; 0x03BF; 0x1F78; 0x03C5; 0x1F7A; + 0x03C9; 0x1F7C; 0x03CA; 0x1FD2; 0x03CB; 0x1FE2; 0x0415; 0x0400; + 0x0418; 0x040D; 0x0435; 0x0450; 0x0438; 0x045D; 0x1F00; 0x1F02; + 0x1F01; 0x1F03; 0x1F08; 0x1F0A; 0x1F09; 0x1F0B; 0x1F10; 0x1F12; + 0x1F11; 0x1F13; 0x1F18; 0x1F1A; 0x1F19; 0x1F1B; 0x1F20; 0x1F22; + 0x1F21; 0x1F23; 0x1F28; 0x1F2A; 0x1F29; 0x1F2B; 0x1F30; 0x1F32; + 0x1F31; 0x1F33; 0x1F38; 0x1F3A; 0x1F39; 0x1F3B; 0x1F40; 0x1F42; + 0x1F41; 0x1F43; 0x1F48; 0x1F4A; 0x1F49; 0x1F4B; 0x1F50; 0x1F52; + 0x1F51; 0x1F53; 0x1F59; 0x1F5B; 0x1F60; 0x1F62; 0x1F61; 0x1F63; + 0x1F68; 0x1F6A; 0x1F69; 0x1F6B; 0x1FBF; 0x1FCD; 0x1FFE; 0x1FDD; + 0x0041; 0x00C1; 0x0043; 0x0106; 0x0045; 0x00C9; 0x0047; 0x01F4; + 0x0049; 0x00CD; 0x004B; 0x1E30; 0x004C; 0x0139; 0x004D; 0x1E3E; + 0x004E; 0x0143; 0x004F; 0x00D3; 0x0050; 0x1E54; 0x0052; 0x0154; + 0x0053; 0x015A; 0x0055; 0x00DA; 0x0057; 0x1E82; 0x0059; 0x00DD; + 0x005A; 0x0179; 0x0061; 0x00E1; 0x0063; 0x0107; 0x0065; 0x00E9; + 0x0067; 0x01F5; 0x0069; 0x00ED; 0x006B; 0x1E31; 0x006C; 0x013A; + 0x006D; 0x1E3F; 0x006E; 0x0144; 0x006F; 0x00F3; 0x0070; 0x1E55; + 0x0072; 0x0155; 0x0073; 0x015B; 0x0075; 0x00FA; 0x0077; 0x1E83; + 0x0079; 0x00FD; 0x007A; 0x017A; 0x00A8; 0x0385; 0x00C2; 0x1EA4; + 0x00C5; 0x01FA; 0x00C6; 0x01FC; 0x00C7; 0x1E08; 0x00CA; 0x1EBE; + 0x00CF; 0x1E2E; 0x00D4; 0x1ED0; 0x00D5; 0x1E4C; 0x00D8; 0x01FE; + 0x00DC; 0x01D7; 0x00E2; 0x1EA5; 0x00E5; 0x01FB; 0x00E6; 0x01FD; + 0x00E7; 0x1E09; 0x00EA; 0x1EBF; 0x00EF; 0x1E2F; 0x00F4; 0x1ED1; + 0x00F5; 0x1E4D; 0x00F8; 0x01FF; 0x00FC; 0x01D8; 0x0102; 0x1EAE; + 0x0103; 0x1EAF; 0x0112; 0x1E16; 0x0113; 0x1E17; 0x014C; 0x1E52; + 0x014D; 0x1E53; 0x0168; 0x1E78; 0x0169; 0x1E79; 0x01A0; 0x1EDA; + 0x01A1; 0x1EDB; 0x01AF; 0x1EE8; 0x01B0; 0x1EE9; 0x0391; 0x0386; + 0x0395; 0x0388; 0x0397; 0x0389; 0x0399; 0x038A; 0x039F; 0x038C; + 0x03A5; 0x038E; 0x03A9; 0x038F; 0x03B1; 0x03AC; 0x03B5; 0x03AD; + 0x03B7; 0x03AE; 0x03B9; 0x03AF; 0x03BF; 0x03CC; 0x03C5; 0x03CD; + 0x03C9; 0x03CE; 0x03CA; 0x0390; 0x03CB; 0x03B0; 0x03D2; 0x03D3; + 0x0413; 0x0403; 0x041A; 0x040C; 0x0433; 0x0453; 0x043A; 0x045C; + 0x1F00; 0x1F04; 0x1F01; 0x1F05; 0x1F08; 0x1F0C; 0x1F09; 0x1F0D; + 0x1F10; 0x1F14; 0x1F11; 0x1F15; 0x1F18; 0x1F1C; 0x1F19; 0x1F1D; + 0x1F20; 0x1F24; 0x1F21; 0x1F25; 0x1F28; 0x1F2C; 0x1F29; 0x1F2D; + 0x1F30; 0x1F34; 0x1F31; 0x1F35; 0x1F38; 0x1F3C; 0x1F39; 0x1F3D; + 0x1F40; 0x1F44; 0x1F41; 0x1F45; 0x1F48; 0x1F4C; 0x1F49; 0x1F4D; + 0x1F50; 0x1F54; 0x1F51; 0x1F55; 0x1F59; 0x1F5D; 0x1F60; 0x1F64; + 0x1F61; 0x1F65; 0x1F68; 0x1F6C; 0x1F69; 0x1F6D; 0x1FBF; 0x1FCE; + 0x1FFE; 0x1FDE; 0x0041; 0x00C2; 0x0043; 0x0108; 0x0045; 0x00CA; + 0x0047; 0x011C; 0x0048; 0x0124; 0x0049; 0x00CE; 0x004A; 0x0134; + 0x004F; 0x00D4; 0x0053; 0x015C; 0x0055; 0x00DB; 0x0057; 0x0174; + 0x0059; 0x0176; 0x005A; 0x1E90; 0x0061; 0x00E2; 0x0063; 0x0109; + 0x0065; 0x00EA; 0x0067; 0x011D; 0x0068; 0x0125; 0x0069; 0x00EE; + 0x006A; 0x0135; 0x006F; 0x00F4; 0x0073; 0x015D; 0x0075; 0x00FB; + 0x0077; 0x0175; 0x0079; 0x0177; 0x007A; 0x1E91; 0x1EA0; 0x1EAC; + 0x1EA1; 0x1EAD; 0x1EB8; 0x1EC6; 0x1EB9; 0x1EC7; 0x1ECC; 0x1ED8; + 0x1ECD; 0x1ED9; 0x0041; 0x00C3; 0x0045; 0x1EBC; 0x0049; 0x0128; + 0x004E; 0x00D1; 0x004F; 0x00D5; 0x0055; 0x0168; 0x0056; 0x1E7C; + 0x0059; 0x1EF8; 0x0061; 0x00E3; 0x0065; 0x1EBD; 0x0069; 0x0129; + 0x006E; 0x00F1; 0x006F; 0x00F5; 0x0075; 0x0169; 0x0076; 0x1E7D; + 0x0079; 0x1EF9; 0x00C2; 0x1EAA; 0x00CA; 0x1EC4; 0x00D4; 0x1ED6; + 0x00E2; 0x1EAB; 0x00EA; 0x1EC5; 0x00F4; 0x1ED7; 0x0102; 0x1EB4; + 0x0103; 0x1EB5; 0x01A0; 0x1EE0; 0x01A1; 0x1EE1; 0x01AF; 0x1EEE; + 0x01B0; 0x1EEF; 0x0041; 0x0100; 0x0045; 0x0112; 0x0047; 0x1E20; + 0x0049; 0x012A; 0x004F; 0x014C; 0x0055; 0x016A; 0x0059; 0x0232; + 0x0061; 0x0101; 0x0065; 0x0113; 0x0067; 0x1E21; 0x0069; 0x012B; + 0x006F; 0x014D; 0x0075; 0x016B; 0x0079; 0x0233; 0x00C4; 0x01DE; + 0x00C6; 0x01E2; 0x00D5; 0x022C; 0x00D6; 0x022A; 0x00DC; 0x01D5; + 0x00E4; 0x01DF; 0x00E6; 0x01E3; 0x00F5; 0x022D; 0x00F6; 0x022B; + 0x00FC; 0x01D6; 0x01EA; 0x01EC; 0x01EB; 0x01ED; 0x0226; 0x01E0; + 0x0227; 0x01E1; 0x022E; 0x0230; 0x022F; 0x0231; 0x0391; 0x1FB9; + 0x0399; 0x1FD9; 0x03A5; 0x1FE9; 0x03B1; 0x1FB1; 0x03B9; 0x1FD1; + 0x03C5; 0x1FE1; 0x0418; 0x04E2; 0x0423; 0x04EE; 0x0438; 0x04E3; + 0x0443; 0x04EF; 0x1E36; 0x1E38; 0x1E37; 0x1E39; 0x1E5A; 0x1E5C; + 0x1E5B; 0x1E5D; 0x0041; 0x0102; 0x0045; 0x0114; 0x0047; 0x011E; + 0x0049; 0x012C; 0x004F; 0x014E; 0x0055; 0x016C; 0x0061; 0x0103; + 0x0065; 0x0115; 0x0067; 0x011F; 0x0069; 0x012D; 0x006F; 0x014F; + 0x0075; 0x016D; 0x0228; 0x1E1C; 0x0229; 0x1E1D; 0x0391; 0x1FB8; + 0x0399; 0x1FD8; 0x03A5; 0x1FE8; 0x03B1; 0x1FB0; 0x03B9; 0x1FD0; + 0x03C5; 0x1FE0; 0x0410; 0x04D0; 0x0415; 0x04D6; 0x0416; 0x04C1; + 0x0418; 0x0419; 0x0423; 0x040E; 0x0430; 0x04D1; 0x0435; 0x04D7; + 0x0436; 0x04C2; 0x0438; 0x0439; 0x0443; 0x045E; 0x1EA0; 0x1EB6; + 0x1EA1; 0x1EB7; 0x0041; 0x0226; 0x0042; 0x1E02; 0x0043; 0x010A; + 0x0044; 0x1E0A; 0x0045; 0x0116; 0x0046; 0x1E1E; 0x0047; 0x0120; + 0x0048; 0x1E22; 0x0049; 0x0130; 0x004D; 0x1E40; 0x004E; 0x1E44; + 0x004F; 0x022E; 0x0050; 0x1E56; 0x0052; 0x1E58; 0x0053; 0x1E60; + 0x0054; 0x1E6A; 0x0057; 0x1E86; 0x0058; 0x1E8A; 0x0059; 0x1E8E; + 0x005A; 0x017B; 0x0061; 0x0227; 0x0062; 0x1E03; 0x0063; 0x010B; + 0x0064; 0x1E0B; 0x0065; 0x0117; 0x0066; 0x1E1F; 0x0067; 0x0121; + 0x0068; 0x1E23; 0x006D; 0x1E41; 0x006E; 0x1E45; 0x006F; 0x022F; + 0x0070; 0x1E57; 0x0072; 0x1E59; 0x0073; 0x1E61; 0x0074; 0x1E6B; + 0x0077; 0x1E87; 0x0078; 0x1E8B; 0x0079; 0x1E8F; 0x007A; 0x017C; + 0x015A; 0x1E64; 0x015B; 0x1E65; 0x0160; 0x1E66; 0x0161; 0x1E67; + 0x017F; 0x1E9B; 0x1E62; 0x1E68; 0x1E63; 0x1E69; 0x0041; 0x00C4; + 0x0045; 0x00CB; 0x0048; 0x1E26; 0x0049; 0x00CF; 0x004F; 0x00D6; + 0x0055; 0x00DC; 0x0057; 0x1E84; 0x0058; 0x1E8C; 0x0059; 0x0178; + 0x0061; 0x00E4; 0x0065; 0x00EB; 0x0068; 0x1E27; 0x0069; 0x00EF; + 0x006F; 0x00F6; 0x0074; 0x1E97; 0x0075; 0x00FC; 0x0077; 0x1E85; + 0x0078; 0x1E8D; 0x0079; 0x00FF; 0x00D5; 0x1E4E; 0x00F5; 0x1E4F; + 0x016A; 0x1E7A; 0x016B; 0x1E7B; 0x0399; 0x03AA; 0x03A5; 0x03AB; + 0x03B9; 0x03CA; 0x03C5; 0x03CB; 0x03D2; 0x03D4; 0x0406; 0x0407; + 0x0410; 0x04D2; 0x0415; 0x0401; 0x0416; 0x04DC; 0x0417; 0x04DE; + 0x0418; 0x04E4; 0x041E; 0x04E6; 0x0423; 0x04F0; 0x0427; 0x04F4; + 0x042B; 0x04F8; 0x042D; 0x04EC; 0x0430; 0x04D3; 0x0435; 0x0451; + 0x0436; 0x04DD; 0x0437; 0x04DF; 0x0438; 0x04E5; 0x043E; 0x04E7; + 0x0443; 0x04F1; 0x0447; 0x04F5; 0x044B; 0x04F9; 0x044D; 0x04ED; + 0x0456; 0x0457; 0x04D8; 0x04DA; 0x04D9; 0x04DB; 0x04E8; 0x04EA; + 0x04E9; 0x04EB; 0x0041; 0x1EA2; 0x0045; 0x1EBA; 0x0049; 0x1EC8; + 0x004F; 0x1ECE; 0x0055; 0x1EE6; 0x0059; 0x1EF6; 0x0061; 0x1EA3; + 0x0065; 0x1EBB; 0x0069; 0x1EC9; 0x006F; 0x1ECF; 0x0075; 0x1EE7; + 0x0079; 0x1EF7; 0x00C2; 0x1EA8; 0x00CA; 0x1EC2; 0x00D4; 0x1ED4; + 0x00E2; 0x1EA9; 0x00EA; 0x1EC3; 0x00F4; 0x1ED5; 0x0102; 0x1EB2; + 0x0103; 0x1EB3; 0x01A0; 0x1EDE; 0x01A1; 0x1EDF; 0x01AF; 0x1EEC; + 0x01B0; 0x1EED; 0x0041; 0x00C5; 0x0055; 0x016E; 0x0061; 0x00E5; + 0x0075; 0x016F; 0x0077; 0x1E98; 0x0079; 0x1E99; 0x004F; 0x0150; + 0x0055; 0x0170; 0x006F; 0x0151; 0x0075; 0x0171; 0x0423; 0x04F2; + 0x0443; 0x04F3; 0x0041; 0x01CD; 0x0043; 0x010C; 0x0044; 0x010E; + 0x0045; 0x011A; 0x0047; 0x01E6; 0x0048; 0x021E; 0x0049; 0x01CF; + 0x004B; 0x01E8; 0x004C; 0x013D; 0x004E; 0x0147; 0x004F; 0x01D1; + 0x0052; 0x0158; 0x0053; 0x0160; 0x0054; 0x0164; 0x0055; 0x01D3; + 0x005A; 0x017D; 0x0061; 0x01CE; 0x0063; 0x010D; 0x0064; 0x010F; + 0x0065; 0x011B; 0x0067; 0x01E7; 0x0068; 0x021F; 0x0069; 0x01D0; + 0x006A; 0x01F0; 0x006B; 0x01E9; 0x006C; 0x013E; 0x006E; 0x0148; + 0x006F; 0x01D2; 0x0072; 0x0159; 0x0073; 0x0161; 0x0074; 0x0165; + 0x0075; 0x01D4; 0x007A; 0x017E; 0x00DC; 0x01D9; 0x00FC; 0x01DA; + 0x01B7; 0x01EE; 0x0292; 0x01EF; 0x0041; 0x0200; 0x0045; 0x0204; + 0x0049; 0x0208; 0x004F; 0x020C; 0x0052; 0x0210; 0x0055; 0x0214; + 0x0061; 0x0201; 0x0065; 0x0205; 0x0069; 0x0209; 0x006F; 0x020D; + 0x0072; 0x0211; 0x0075; 0x0215; 0x0474; 0x0476; 0x0475; 0x0477; + 0x0041; 0x0202; 0x0045; 0x0206; 0x0049; 0x020A; 0x004F; 0x020E; + 0x0052; 0x0212; 0x0055; 0x0216; 0x0061; 0x0203; 0x0065; 0x0207; + 0x0069; 0x020B; 0x006F; 0x020F; 0x0072; 0x0213; 0x0075; 0x0217; + 0x0391; 0x1F08; 0x0395; 0x1F18; 0x0397; 0x1F28; 0x0399; 0x1F38; + 0x039F; 0x1F48; 0x03A9; 0x1F68; 0x03B1; 0x1F00; 0x03B5; 0x1F10; + 0x03B7; 0x1F20; 0x03B9; 0x1F30; 0x03BF; 0x1F40; 0x03C1; 0x1FE4; + 0x03C5; 0x1F50; 0x03C9; 0x1F60; 0x0391; 0x1F09; 0x0395; 0x1F19; + 0x0397; 0x1F29; 0x0399; 0x1F39; 0x039F; 0x1F49; 0x03A1; 0x1FEC; + 0x03A5; 0x1F59; 0x03A9; 0x1F69; 0x03B1; 0x1F01; 0x03B5; 0x1F11; + 0x03B7; 0x1F21; 0x03B9; 0x1F31; 0x03BF; 0x1F41; 0x03C1; 0x1FE5; + 0x03C5; 0x1F51; 0x03C9; 0x1F61; 0x004F; 0x01A0; 0x0055; 0x01AF; + 0x006F; 0x01A1; 0x0075; 0x01B0; 0x0041; 0x1EA0; 0x0042; 0x1E04; + 0x0044; 0x1E0C; 0x0045; 0x1EB8; 0x0048; 0x1E24; 0x0049; 0x1ECA; + 0x004B; 0x1E32; 0x004C; 0x1E36; 0x004D; 0x1E42; 0x004E; 0x1E46; + 0x004F; 0x1ECC; 0x0052; 0x1E5A; 0x0053; 0x1E62; 0x0054; 0x1E6C; + 0x0055; 0x1EE4; 0x0056; 0x1E7E; 0x0057; 0x1E88; 0x0059; 0x1EF4; + 0x005A; 0x1E92; 0x0061; 0x1EA1; 0x0062; 0x1E05; 0x0064; 0x1E0D; + 0x0065; 0x1EB9; 0x0068; 0x1E25; 0x0069; 0x1ECB; 0x006B; 0x1E33; + 0x006C; 0x1E37; 0x006D; 0x1E43; 0x006E; 0x1E47; 0x006F; 0x1ECD; + 0x0072; 0x1E5B; 0x0073; 0x1E63; 0x0074; 0x1E6D; 0x0075; 0x1EE5; + 0x0076; 0x1E7F; 0x0077; 0x1E89; 0x0079; 0x1EF5; 0x007A; 0x1E93; + 0x01A0; 0x1EE2; 0x01A1; 0x1EE3; 0x01AF; 0x1EF0; 0x01B0; 0x1EF1; + 0x0055; 0x1E72; 0x0075; 0x1E73; 0x0041; 0x1E00; 0x0061; 0x1E01; + 0x0053; 0x0218; 0x0054; 0x021A; 0x0073; 0x0219; 0x0074; 0x021B; + 0x0043; 0x00C7; 0x0044; 0x1E10; 0x0045; 0x0228; 0x0047; 0x0122; + 0x0048; 0x1E28; 0x004B; 0x0136; 0x004C; 0x013B; 0x004E; 0x0145; + 0x0052; 0x0156; 0x0053; 0x015E; 0x0054; 0x0162; 0x0063; 0x00E7; + 0x0064; 0x1E11; 0x0065; 0x0229; 0x0067; 0x0123; 0x0068; 0x1E29; + 0x006B; 0x0137; 0x006C; 0x013C; 0x006E; 0x0146; 0x0072; 0x0157; + 0x0073; 0x015F; 0x0074; 0x0163; 0x0041; 0x0104; 0x0045; 0x0118; + 0x0049; 0x012E; 0x004F; 0x01EA; 0x0055; 0x0172; 0x0061; 0x0105; + 0x0065; 0x0119; 0x0069; 0x012F; 0x006F; 0x01EB; 0x0075; 0x0173; + 0x0044; 0x1E12; 0x0045; 0x1E18; 0x004C; 0x1E3C; 0x004E; 0x1E4A; + 0x0054; 0x1E70; 0x0055; 0x1E76; 0x0064; 0x1E13; 0x0065; 0x1E19; + 0x006C; 0x1E3D; 0x006E; 0x1E4B; 0x0074; 0x1E71; 0x0075; 0x1E77; + 0x0048; 0x1E2A; 0x0068; 0x1E2B; 0x0045; 0x1E1A; 0x0049; 0x1E2C; + 0x0055; 0x1E74; 0x0065; 0x1E1B; 0x0069; 0x1E2D; 0x0075; 0x1E75; + 0x0042; 0x1E06; 0x0044; 0x1E0E; 0x004B; 0x1E34; 0x004C; 0x1E3A; + 0x004E; 0x1E48; 0x0052; 0x1E5E; 0x0054; 0x1E6E; 0x005A; 0x1E94; + 0x0062; 0x1E07; 0x0064; 0x1E0F; 0x0068; 0x1E96; 0x006B; 0x1E35; + 0x006C; 0x1E3B; 0x006E; 0x1E49; 0x0072; 0x1E5F; 0x0074; 0x1E6F; + 0x007A; 0x1E95; 0x003C; 0x226E; 0x003D; 0x2260; 0x003E; 0x226F; + 0x2190; 0x219A; 0x2192; 0x219B; 0x2194; 0x21AE; 0x21D0; 0x21CD; + 0x21D2; 0x21CF; 0x21D4; 0x21CE; 0x2203; 0x2204; 0x2208; 0x2209; + 0x220B; 0x220C; 0x2223; 0x2224; 0x2225; 0x2226; 0x223C; 0x2241; + 0x2243; 0x2244; 0x2245; 0x2247; 0x2248; 0x2249; 0x224D; 0x226D; + 0x2261; 0x2262; 0x2264; 0x2270; 0x2265; 0x2271; 0x2272; 0x2274; + 0x2273; 0x2275; 0x2276; 0x2278; 0x2277; 0x2279; 0x227A; 0x2280; + 0x227B; 0x2281; 0x227C; 0x22E0; 0x227D; 0x22E1; 0x2282; 0x2284; + 0x2283; 0x2285; 0x2286; 0x2288; 0x2287; 0x2289; 0x2291; 0x22E2; + 0x2292; 0x22E3; 0x22A2; 0x22AC; 0x22A8; 0x22AD; 0x22A9; 0x22AE; + 0x22AB; 0x22AF; 0x22B2; 0x22EA; 0x22B3; 0x22EB; 0x22B4; 0x22EC; + 0x22B5; 0x22ED; 0x00A8; 0x1FC1; 0x03B1; 0x1FB6; 0x03B7; 0x1FC6; + 0x03B9; 0x1FD6; 0x03C5; 0x1FE6; 0x03C9; 0x1FF6; 0x03CA; 0x1FD7; + 0x03CB; 0x1FE7; 0x1F00; 0x1F06; 0x1F01; 0x1F07; 0x1F08; 0x1F0E; + 0x1F09; 0x1F0F; 0x1F20; 0x1F26; 0x1F21; 0x1F27; 0x1F28; 0x1F2E; + 0x1F29; 0x1F2F; 0x1F30; 0x1F36; 0x1F31; 0x1F37; 0x1F38; 0x1F3E; + 0x1F39; 0x1F3F; 0x1F50; 0x1F56; 0x1F51; 0x1F57; 0x1F59; 0x1F5F; + 0x1F60; 0x1F66; 0x1F61; 0x1F67; 0x1F68; 0x1F6E; 0x1F69; 0x1F6F; + 0x1FBF; 0x1FCF; 0x1FFE; 0x1FDF; 0x0391; 0x1FBC; 0x0397; 0x1FCC; + 0x03A9; 0x1FFC; 0x03AC; 0x1FB4; 0x03AE; 0x1FC4; 0x03B1; 0x1FB3; + 0x03B7; 0x1FC3; 0x03C9; 0x1FF3; 0x03CE; 0x1FF4; 0x1F00; 0x1F80; + 0x1F01; 0x1F81; 0x1F02; 0x1F82; 0x1F03; 0x1F83; 0x1F04; 0x1F84; + 0x1F05; 0x1F85; 0x1F06; 0x1F86; 0x1F07; 0x1F87; 0x1F08; 0x1F88; + 0x1F09; 0x1F89; 0x1F0A; 0x1F8A; 0x1F0B; 0x1F8B; 0x1F0C; 0x1F8C; + 0x1F0D; 0x1F8D; 0x1F0E; 0x1F8E; 0x1F0F; 0x1F8F; 0x1F20; 0x1F90; + 0x1F21; 0x1F91; 0x1F22; 0x1F92; 0x1F23; 0x1F93; 0x1F24; 0x1F94; + 0x1F25; 0x1F95; 0x1F26; 0x1F96; 0x1F27; 0x1F97; 0x1F28; 0x1F98; + 0x1F29; 0x1F99; 0x1F2A; 0x1F9A; 0x1F2B; 0x1F9B; 0x1F2C; 0x1F9C; + 0x1F2D; 0x1F9D; 0x1F2E; 0x1F9E; 0x1F2F; 0x1F9F; 0x1F60; 0x1FA0; + 0x1F61; 0x1FA1; 0x1F62; 0x1FA2; 0x1F63; 0x1FA3; 0x1F64; 0x1FA4; + 0x1F65; 0x1FA5; 0x1F66; 0x1FA6; 0x1F67; 0x1FA7; 0x1F68; 0x1FA8; + 0x1F69; 0x1FA9; 0x1F6A; 0x1FAA; 0x1F6B; 0x1FAB; 0x1F6C; 0x1FAC; + 0x1F6D; 0x1FAD; 0x1F6E; 0x1FAE; 0x1F6F; 0x1FAF; 0x1F70; 0x1FB2; + 0x1F74; 0x1FC2; 0x1F7C; 0x1FF2; 0x1FB6; 0x1FB7; 0x1FC6; 0x1FC7; + 0x1FF6; 0x1FF7; 0x0627; 0x0622; 0x0627; 0x0623; 0x0648; 0x0624; + 0x064A; 0x0626; 0x06C1; 0x06C2; 0x06D2; 0x06D3; 0x06D5; 0x06C0; + 0x0627; 0x0625; 0x0928; 0x0929; 0x0930; 0x0931; 0x0933; 0x0934; + 0x09C7; 0x09CB; 0x09C7; 0x09CC; 0x0B47; 0x0B4B; 0x0B47; 0x0B48; + 0x0B47; 0x0B4C; 0x0BC6; 0x0BCA; 0x0BC7; 0x0BCB; 0x0B92; 0x0B94; + 0x0BC6; 0x0BCC; 0x0C46; 0x0C48; 0x0CC6; 0x0CCA; 0x0CBF; 0x0CC0; + 0x0CC6; 0x0CC7; 0x0CCA; 0x0CCB; 0x0CC6; 0x0CC8; 0x0D46; 0x0D4A; + 0x0D47; 0x0D4B; 0x0D46; 0x0D4C; 0x0DD9; 0x0DDA; 0x0DDC; 0x0DDD; + 0x0DD9; 0x0DDC; 0x0DD9; 0x0DDE; 0x1025; 0x1026; 0x3046; 0x3094; + 0x304B; 0x304C; 0x304D; 0x304E; 0x304F; 0x3050; 0x3051; 0x3052; + 0x3053; 0x3054; 0x3055; 0x3056; 0x3057; 0x3058; 0x3059; 0x305A; + 0x305B; 0x305C; 0x305D; 0x305E; 0x305F; 0x3060; 0x3061; 0x3062; + 0x3064; 0x3065; 0x3066; 0x3067; 0x3068; 0x3069; 0x306F; 0x3070; + 0x3072; 0x3073; 0x3075; 0x3076; 0x3078; 0x3079; 0x307B; 0x307C; + 0x309D; 0x309E; 0x30A6; 0x30F4; 0x30AB; 0x30AC; 0x30AD; 0x30AE; + 0x30AF; 0x30B0; 0x30B1; 0x30B2; 0x30B3; 0x30B4; 0x30B5; 0x30B6; + 0x30B7; 0x30B8; 0x30B9; 0x30BA; 0x30BB; 0x30BC; 0x30BD; 0x30BE; + 0x30BF; 0x30C0; 0x30C1; 0x30C2; 0x30C4; 0x30C5; 0x30C6; 0x30C7; + 0x30C8; 0x30C9; 0x30CF; 0x30D0; 0x30D2; 0x30D3; 0x30D5; 0x30D6; + 0x30D8; 0x30D9; 0x30DB; 0x30DC; 0x30EF; 0x30F7; 0x30F0; 0x30F8; + 0x30F1; 0x30F9; 0x30F2; 0x30FA; 0x30FD; 0x30FE; 0x306F; 0x3071; + 0x3072; 0x3074; 0x3075; 0x3077; 0x3078; 0x307A; 0x307B; 0x307D; + 0x30CF; 0x30D1; 0x30D2; 0x30D4; 0x30D5; 0x30D7; 0x30D8; 0x30DA; + 0x30DB; 0x30DD +|] + +let uniCharCombiningBitmap = "\ +\x00\x00\x00\x01\x02\x03\x04\x05\ +\x00\x06\x07\x08\x09\x0A\x0B\x0C\ +\x0D\x14\x00\x00\x00\x00\x00\x0E\ +\x0F\x00\x00\x00\x00\x00\x00\x00\ +\x10\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x11\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x12\x00\x00\x13\x00\ +\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\ +\xFF\xFF\x00\x00\xFF\xFF\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x78\x03\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\xFE\xFF\xFB\xFF\xFF\xBB\ +\x16\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\xF8\x3F\x00\x00\x00\x01\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\xC0\xFF\x9F\x3D\x00\x00\ +\x00\x00\x02\x00\x00\x00\xFF\xFF\ +\xFF\x07\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\xC0\xFF\x01\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x0E\x00\x00\x00\x00\x00\x00\xD0\ +\xFF\x3F\x1E\x00\x0C\x00\x00\x00\ +\x0E\x00\x00\x00\x00\x00\x00\xD0\ +\x9F\x39\x80\x00\x0C\x00\x00\x00\ +\x04\x00\x00\x00\x00\x00\x00\xD0\ +\x87\x39\x00\x00\x00\x00\x03\x00\ +\x0E\x00\x00\x00\x00\x00\x00\xD0\ +\xBF\x3B\x00\x00\x00\x00\x00\x00\ +\x0E\x00\x00\x00\x00\x00\x00\xD0\ +\x8F\x39\xC0\x00\x00\x00\x00\x00\ +\x04\x00\x00\x00\x00\x00\x00\xC0\ +\xC7\x3D\x80\x00\x00\x00\x00\x00\ +\x0E\x00\x00\x00\x00\x00\x00\xC0\ +\xDF\x3D\x60\x00\x00\x00\x00\x00\ +\x0C\x00\x00\x00\x00\x00\x00\xC0\ +\xDF\x3D\x60\x00\x00\x00\x00\x00\ +\x0C\x00\x00\x00\x00\x00\x00\xC0\ +\xCF\x3D\x80\x00\x00\x00\x00\x00\ +\x0C\x00\x00\x00\x00\x00\x00\x00\ +\x00\x84\x5F\xFF\x00\x00\x0C\x00\ +\x00\x00\x00\x00\x00\x00\xF2\x07\ +\x80\x7F\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\xF2\x1B\ +\x00\x3F\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x03\x00\x00\xA0\xC2\ +\x00\x00\x00\x00\x00\x00\xFE\xFF\ +\xDF\x00\xFF\xFE\xFF\xFF\xFF\x1F\ +\x40\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xF0\xC7\x03\ +\x00\x00\xC0\x03\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x1C\x00\x00\x00\x1C\x00\ +\x00\x00\x0C\x00\x00\x00\x0C\x00\ +\x00\x00\x00\x00\x00\x00\xF0\xFF\ +\xFF\xFF\x0F\x00\x00\x00\x00\x00\ +\x00\x38\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\xFF\xFF\xFF\x07\x00\x00\ +\x00\x00\x00\x00\x00\xFC\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x06\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x40\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\xFF\xFF\x00\x00\x0F\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\xFE\xFF\x3F\x00\ +\x00\x00\x00\x00\x00\xFF\xFF\xFF\ +\x07\x00\x00\x00\x00\x00\x00\x00" + +(****) + +let bitmap_test base bitmap character = + character >= base && character < 0x10000 + && + (let value = get bitmap ((character lsr 8) land 0xFF) in + value = 0xFF + || + (value <> 0 + && + get bitmap ((value - 1) * 32 + 256 + (character land 0xFF) / 8) + land (1 lsl (character land 7)) <> 0)) + +let unicode_combinable character = + bitmap_test 0x0300 uniCharCombiningBitmap character + +let rec find_rec t i j v = + if i + 1 = j then begin + if t.(i * 2) = v then t.(i * 2 + 1) else 0 + end else begin + let k = (i + j) / 2 in + if v < t.(k * 2) then + find_rec t i k v + else + find_rec t k j v + end + +let find t i n v = + let j = i + n in + if v < t.(2 * i) || v > t.(2 * (j - 1)) then 0 else + find_rec t i j v + +let uniCharPrecompSourceTableLen = Array.length uniCharPrecompSourceTable / 2 + +let combine v v' = + if v' >= hangul_vbase && v' < hangul_tbase + hangul_tcount then begin + if + v' < hangul_vbase + hangul_vcount && + v >= hangul_lbase && v < hangul_lbase + hangul_lcount + then + hangul_sbase + ((v - hangul_lbase) * (hangul_vcount * hangul_tcount)) + + ((v' - hangul_vbase) * hangul_tcount) + else if + v' > hangul_tbase && + v >= hangul_sbase && v < hangul_sbase + hangul_scount + then + if (v - hangul_sbase) mod hangul_tcount <> 0 then 0 else + v + v' - hangul_tbase + else + 0 + end else begin + let k = + find uniCharPrecompSourceTable 0 + uniCharPrecompSourceTableLen v' + in + if k = 0 then 0 else + find uniCharBMPPrecompDestinationTable (k land 0xFFFF) (k lsr 16) v + end + +(****) + +let rec scan d s i l = + if i < l then begin + let c = get s i in + if c < 0x80 then + cont d s i l (i + 1) c + else if c < 0xE0 then begin + (* 80 - 7FF *) + if c < 0xc2 || i + 1 >= l then fail () else + let c1 = get s (i + 1) in + if c1 land 0xc0 <> 0x80 then fail () else + let v = c lsl 6 + c1 - 0x3080 in + cont d s i l (i + 2) v + end else if c < 0xF0 then begin + (* 800 - FFFF *) + if i + 2 >= l then fail () else + let c1 = get s (i + 1) in + let c2 = get s (i + 2) in + if (c1 lor c2) land 0xc0 <> 0x80 then fail () else + let v = c lsl 12 + c1 lsl 6 + c2 - 0xe2080 in + if v < 0x800 then fail () else + cont d s i l (i + 3) v + end else begin + (* 10000 - 10FFFF *) + if i + 3 >= l then fail () else + let c1 = get s (i + 1) in + let c2 = get s (i + 2) in + let c3 = get s (i + 3) in + if (c1 lor c2 lor c3) land 0xc0 <> 0x80 then fail () else + let v = c lsl 18 + c1 lsl 12 + c2 lsl 6 + c3 - 0x03c82080 in + if v < 0x10000 || v > 0x10ffff then fail () else + cont d s i l (i + 4) v + end + end else begin + let (i1, i2) = d in + String.blit s i2 s i1 (l - i2); + String.sub s 0 (i1 + l - i2) + end + +and cont d s i l j v' = + if unicode_combinable v' then begin + let i = prev_char s i in + let (v, _) = decode_char s i l in + let v'' = combine v v' in + if v'' = 0 then + scan d s j l + else begin + let (i1, i2) = d in + String.blit s i2 s i1 (i - i2); + let i1 = i1 + i - i2 in + let (v'', i) = compose_rec s j l v'' in + let i1 = encode_char s i1 l v'' in + scan (i1, i) s i l + end + end else + scan d s j l + +and compose_rec s i l v = + try + let (v', j) = decode_char s i l in + if unicode_combinable v' then begin + let v'' = combine v v' in + if v'' = 0 then + (v, i) + else + compose_rec s j l v'' + end else + (v, i) + with Invalid -> + (v, i) + +let compose s = + try scan (0, 0) (String.copy s) 0 (String.length s) with Invalid -> s + +(***) + +let set_2 s i v = + set s i (v land 0xff); + set s (i + 1) (v lsr 8) + +let get_2 s i = (get s (i + 1)) lsl 8 + get s i + +let rec scan s' j s i l = + if i < l then begin + let c = get s i in + if c < 0x80 then + cont s' j s (i + 1) l c + else if c < 0xE0 then begin + (* 80 - 7FF *) + if c < 0xc2 || i + 1 >= l then fail () else + let c1 = get s (i + 1) in + if c1 land 0xc0 <> 0x80 then fail () else + let v = c lsl 6 + c1 - 0x3080 in + cont s' j s (i + 2) l v + end else if c < 0xF0 then begin + (* 800 - FFFF *) + if i + 2 >= l then fail () else + let c1 = get s (i + 1) in + let c2 = get s (i + 2) in + if (c1 lor c2) land 0xc0 <> 0x80 then fail () else + let v = c lsl 12 + c1 lsl 6 + c2 - 0xe2080 in + if v < 0x800 then fail () else + cont s' j s (i + 3) l v + end else begin + (* 10000 - 10FFFF *) + if i + 3 >= l then fail () else + let c1 = get s (i + 1) in + let c2 = get s (i + 2) in + let c3 = get s (i + 3) in + if (c1 lor c2 lor c3) land 0xc0 <> 0x80 then fail () else + let v = c lsl 18 + c1 lsl 12 + c2 lsl 6 + c3 - 0x03c82080 in + if v < 0x10000 || v > 0x10ffff then fail () else + cont s' j s (i + 4) l v + end + end else + String.sub s' 0 j + +and cont s' j s i l v = + if v < 0x10000 then begin + set_2 s' j v; + scan s' (j + 2) s i l + end else begin + let v = v - 0x10000 in + set_2 s' j (v lsr 10 + 0xD800); + set_2 s' (j + 2) (v land 0x3FF + 0xDC00); + scan s' (j + 4) s i l + end + +let to_utf_16 s = + let l = String.length s in + let s' = String.create (2 * l) in + scan s' 0 s 0 l + +(****) + +let rec scan s' i' l' s i l = + if i + 2 <= l then begin + let v = get_2 s i in + if v < 0xD800 || v > 0xDFFF then + let i' = encode_char s' i' l' v in + scan s' i' l' s (i + 2) l + else if v >= 0xdc00 || i + 4 > l then + fail () + else begin + let v' = get_2 s (i + 2) in + if v' < 0xDC00 || v' > 0XDFFF then fail () else + let i' = + encode_char s' i' l' ((v - 0xD800) lsl 10 + (v' - 0xDC00) + 0x10000) + in + scan s' i' l' s (i + 4) l + end + end else if i < l then + fail () + else + String.sub s' 0 i' + + +let from_utf_16 s = + let l = String.length s in + let l' = 3 * l / 2 in + let s' = String.create l' in + scan s' 0 l' s 0 l + +(* +from_utf16 + +2 bytes -> 3 bytes +4 bytes -> 4 bytes +*)
\ No newline at end of file diff --git a/unicode_utils/unicode_build.ml b/unicode_utils/unicode_build.ml new file mode 100644 index 0000000..1be25f5 --- /dev/null +++ b/unicode_utils/unicode_build.ml @@ -0,0 +1,2045 @@ + +let pr_utf8 = false + +let encode_utf8 c = + if c < 0x80 then + String.make 1 (Char.chr c) + else if c < 0x800 then + let s = String.create 2 in + s.[0] <- Char.chr (c lsr 6 + 0xC0); + s.[1] <- Char.chr (c land 0x3f + 0x80); + s + else if c < 0x10000 then + let s = String.create 3 in + s.[0] <- Char.chr (c lsr 12 + 0xE0); + s.[1] <- Char.chr ((c lsr 6) land 0x3f + 0x80); + s.[2] <- Char.chr (c land 0x3f + 0x80); + s + else + let s = String.create 4 in + s.[0] <- Char.chr (c lsr 18 + 0xF0); + s.[1] <- Char.chr ((c lsr 12) land 0x3f + 0x80); + s.[2] <- Char.chr ((c lsr 6) land 0x3f + 0x80); + s.[3] <- Char.chr (c land 0x3f + 0x80); + s + +let print_uni ch c = + if pr_utf8 then + let s = encode_utf8 c in + Format.fprintf ch "%02x" (Char.code s.[0]); + for i = 1 to String.length s - 1 do + Format.fprintf ch ",%02x" (Char.code s.[i]); + done + else + Format.fprintf ch "%04x" c + +(*let print_uni ch c = Format.fprintf ch "%s" (encode_utf8 c)*) + +let rec print_chars ch s = + match s with + [] -> () + | [c] -> Format.fprintf ch "%a" print_uni c + | c :: r -> Format.fprintf ch "%a,%a" print_uni c print_chars r + +(****) + +module IntMap = Map.Make (struct type t = int let compare = compare end) + +let convert m c = try IntMap.find c m with Not_found -> [c] + +let convert_list m l = List.flatten (List.map (convert m) l) + +let compose m m' = IntMap.map (fun l -> convert_list m l) m' + +let add m c l = + let l = if l = [0xffff] then [0] else l in +(* + Format.printf "%a -> %a@." print_uni c print_chars l; +*) + m := IntMap.add c l !m + +let empty () = ref (IntMap.empty) + +(****) + +(**** From vfs_utfconvdata.h *) + +let uniCharDecompositionTable = [| + 0x00C0; 0x2000; 0x00C1; 0x2002; 0x00C2; 0x2004; 0x00C3; 0x2006; + 0x00C4; 0x2008; 0x00C5; 0x200A; 0x00C7; 0x200C; 0x00C8; 0x200E; + 0x00C9; 0x2010; 0x00CA; 0x2012; 0x00CB; 0x2014; 0x00CC; 0x2016; + 0x00CD; 0x2018; 0x00CE; 0x201A; 0x00CF; 0x201C; 0x00D1; 0x201E; + 0x00D2; 0x2020; 0x00D3; 0x2022; 0x00D4; 0x2024; 0x00D5; 0x2026; + 0x00D6; 0x2028; 0x00D9; 0x202A; 0x00DA; 0x202C; 0x00DB; 0x202E; + 0x00DC; 0x2030; 0x00DD; 0x2032; 0x00E0; 0x2034; 0x00E1; 0x2036; + 0x00E2; 0x2038; 0x00E3; 0x203A; 0x00E4; 0x203C; 0x00E5; 0x203E; + 0x00E7; 0x2040; 0x00E8; 0x2042; 0x00E9; 0x2044; 0x00EA; 0x2046; + 0x00EB; 0x2048; 0x00EC; 0x204A; 0x00ED; 0x204C; 0x00EE; 0x204E; + 0x00EF; 0x2050; 0x00F1; 0x2052; 0x00F2; 0x2054; 0x00F3; 0x2056; + 0x00F4; 0x2058; 0x00F5; 0x205A; 0x00F6; 0x205C; 0x00F9; 0x205E; + 0x00FA; 0x2060; 0x00FB; 0x2062; 0x00FC; 0x2064; 0x00FD; 0x2066; + 0x00FF; 0x2068; 0x0100; 0x206A; 0x0101; 0x206C; 0x0102; 0x206E; + 0x0103; 0x2070; 0x0104; 0x2072; 0x0105; 0x2074; 0x0106; 0x2076; + 0x0107; 0x2078; 0x0108; 0x207A; 0x0109; 0x207C; 0x010A; 0x207E; + 0x010B; 0x2080; 0x010C; 0x2082; 0x010D; 0x2084; 0x010E; 0x2086; + 0x010F; 0x2088; 0x0112; 0x208A; 0x0113; 0x208C; 0x0114; 0x208E; + 0x0115; 0x2090; 0x0116; 0x2092; 0x0117; 0x2094; 0x0118; 0x2096; + 0x0119; 0x2098; 0x011A; 0x209A; 0x011B; 0x209C; 0x011C; 0x209E; + 0x011D; 0x20A0; 0x011E; 0x20A2; 0x011F; 0x20A4; 0x0120; 0x20A6; + 0x0121; 0x20A8; 0x0122; 0x20AA; 0x0123; 0x20AC; 0x0124; 0x20AE; + 0x0125; 0x20B0; 0x0128; 0x20B2; 0x0129; 0x20B4; 0x012A; 0x20B6; + 0x012B; 0x20B8; 0x012C; 0x20BA; 0x012D; 0x20BC; 0x012E; 0x20BE; + 0x012F; 0x20C0; 0x0130; 0x20C2; 0x0134; 0x20C4; 0x0135; 0x20C6; + 0x0136; 0x20C8; 0x0137; 0x20CA; 0x0139; 0x20CC; 0x013A; 0x20CE; + 0x013B; 0x20D0; 0x013C; 0x20D2; 0x013D; 0x20D4; 0x013E; 0x20D6; + 0x0143; 0x20D8; 0x0144; 0x20DA; 0x0145; 0x20DC; 0x0146; 0x20DE; + 0x0147; 0x20E0; 0x0148; 0x20E2; 0x014C; 0x20E4; 0x014D; 0x20E6; + 0x014E; 0x20E8; 0x014F; 0x20EA; 0x0150; 0x20EC; 0x0151; 0x20EE; + 0x0154; 0x20F0; 0x0155; 0x20F2; 0x0156; 0x20F4; 0x0157; 0x20F6; + 0x0158; 0x20F8; 0x0159; 0x20FA; 0x015A; 0x20FC; 0x015B; 0x20FE; + 0x015C; 0x2100; 0x015D; 0x2102; 0x015E; 0x2104; 0x015F; 0x2106; + 0x0160; 0x2108; 0x0161; 0x210A; 0x0162; 0x210C; 0x0163; 0x210E; + 0x0164; 0x2110; 0x0165; 0x2112; 0x0168; 0x2114; 0x0169; 0x2116; + 0x016A; 0x2118; 0x016B; 0x211A; 0x016C; 0x211C; 0x016D; 0x211E; + 0x016E; 0x2120; 0x016F; 0x2122; 0x0170; 0x2124; 0x0171; 0x2126; + 0x0172; 0x2128; 0x0173; 0x212A; 0x0174; 0x212C; 0x0175; 0x212E; + 0x0176; 0x2130; 0x0177; 0x2132; 0x0178; 0x2134; 0x0179; 0x2136; + 0x017A; 0x2138; 0x017B; 0x213A; 0x017C; 0x213C; 0x017D; 0x213E; + 0x017E; 0x2140; 0x01A0; 0x2142; 0x01A1; 0x2144; 0x01AF; 0x2146; + 0x01B0; 0x2148; 0x01CD; 0x214A; 0x01CE; 0x214C; 0x01CF; 0x214E; + 0x01D0; 0x2150; 0x01D1; 0x2152; 0x01D2; 0x2154; 0x01D3; 0x2156; + 0x01D4; 0x2158; 0x01D5; 0xA15A; 0x01D6; 0xA15C; 0x01D7; 0xA15E; + 0x01D8; 0xA160; 0x01D9; 0xA162; 0x01DA; 0xA164; 0x01DB; 0xA166; + 0x01DC; 0xA168; 0x01DE; 0xA16A; 0x01DF; 0xA16C; 0x01E0; 0xA16E; + 0x01E1; 0xA170; 0x01E2; 0x2172; 0x01E3; 0x2174; 0x01E6; 0x2176; + 0x01E7; 0x2178; 0x01E8; 0x217A; 0x01E9; 0x217C; 0x01EA; 0x217E; + 0x01EB; 0x2180; 0x01EC; 0xA182; 0x01ED; 0xA184; 0x01EE; 0x2186; + 0x01EF; 0x2188; 0x01F0; 0x218A; 0x01F4; 0x218C; 0x01F5; 0x218E; + 0x01F8; 0x2190; 0x01F9; 0x2192; 0x01FA; 0xA194; 0x01FB; 0xA196; + 0x01FC; 0x2198; 0x01FD; 0x219A; 0x01FE; 0x219C; 0x01FF; 0x219E; + 0x0200; 0x21A0; 0x0201; 0x21A2; 0x0202; 0x21A4; 0x0203; 0x21A6; + 0x0204; 0x21A8; 0x0205; 0x21AA; 0x0206; 0x21AC; 0x0207; 0x21AE; + 0x0208; 0x21B0; 0x0209; 0x21B2; 0x020A; 0x21B4; 0x020B; 0x21B6; + 0x020C; 0x21B8; 0x020D; 0x21BA; 0x020E; 0x21BC; 0x020F; 0x21BE; + 0x0210; 0x21C0; 0x0211; 0x21C2; 0x0212; 0x21C4; 0x0213; 0x21C6; + 0x0214; 0x21C8; 0x0215; 0x21CA; 0x0216; 0x21CC; 0x0217; 0x21CE; + 0x0218; 0x21D0; 0x0219; 0x21D2; 0x021A; 0x21D4; 0x021B; 0x21D6; + 0x021E; 0x21D8; 0x021F; 0x21DA; 0x0226; 0x21DC; 0x0227; 0x21DE; + 0x0228; 0x21E0; 0x0229; 0x21E2; 0x022A; 0xA1E4; 0x022B; 0xA1E6; + 0x022C; 0xA1E8; 0x022D; 0xA1EA; 0x022E; 0x21EC; 0x022F; 0x21EE; + 0x0230; 0xA1F0; 0x0231; 0xA1F2; 0x0232; 0x21F4; 0x0233; 0x21F6; + 0x0340; 0x1300; 0x0341; 0x1301; 0x0343; 0x1313; 0x0344; 0x21F8; + 0x0374; 0x12B9; 0x037E; 0x103B; 0x0385; 0x21FA; 0x0386; 0x21FC; + 0x0387; 0x10B7; 0x0388; 0x21FE; 0x0389; 0x2200; 0x038A; 0x2202; + 0x038C; 0x2204; 0x038E; 0x2206; 0x038F; 0x2208; 0x0390; 0xA20A; + 0x03AA; 0x220C; 0x03AB; 0x220E; 0x03AC; 0x2210; 0x03AD; 0x2212; + 0x03AE; 0x2214; 0x03AF; 0x2216; 0x03B0; 0xA218; 0x03CA; 0x221A; + 0x03CB; 0x221C; 0x03CC; 0x221E; 0x03CD; 0x2220; 0x03CE; 0x2222; + 0x03D3; 0x2224; 0x03D4; 0x2226; 0x0400; 0x2228; 0x0401; 0x222A; + 0x0403; 0x222C; 0x0407; 0x222E; 0x040C; 0x2230; 0x040D; 0x2232; + 0x040E; 0x2234; 0x0419; 0x2236; 0x0439; 0x2238; 0x0450; 0x223A; + 0x0451; 0x223C; 0x0453; 0x223E; 0x0457; 0x2240; 0x045C; 0x2242; + 0x045D; 0x2244; 0x045E; 0x2246; 0x0476; 0x2248; 0x0477; 0x224A; + 0x04C1; 0x224C; 0x04C2; 0x224E; 0x04D0; 0x2250; 0x04D1; 0x2252; + 0x04D2; 0x2254; 0x04D3; 0x2256; 0x04D6; 0x2258; 0x04D7; 0x225A; + 0x04DA; 0x225C; 0x04DB; 0x225E; 0x04DC; 0x2260; 0x04DD; 0x2262; + 0x04DE; 0x2264; 0x04DF; 0x2266; 0x04E2; 0x2268; 0x04E3; 0x226A; + 0x04E4; 0x226C; 0x04E5; 0x226E; 0x04E6; 0x2270; 0x04E7; 0x2272; + 0x04EA; 0x2274; 0x04EB; 0x2276; 0x04EC; 0x2278; 0x04ED; 0x227A; + 0x04EE; 0x227C; 0x04EF; 0x227E; 0x04F0; 0x2280; 0x04F1; 0x2282; + 0x04F2; 0x2284; 0x04F3; 0x2286; 0x04F4; 0x2288; 0x04F5; 0x228A; + 0x04F8; 0x228C; 0x04F9; 0x228E; 0x0622; 0x2290; 0x0623; 0x2292; + 0x0624; 0x2294; 0x0625; 0x2296; 0x0626; 0x2298; 0x06C0; 0x229A; + 0x06C2; 0x229C; 0x06D3; 0x229E; 0x0929; 0x22A0; 0x0931; 0x22A2; + 0x0934; 0x22A4; 0x0958; 0x22A6; 0x0959; 0x22A8; 0x095A; 0x22AA; + 0x095B; 0x22AC; 0x095C; 0x22AE; 0x095D; 0x22B0; 0x095E; 0x22B2; + 0x095F; 0x22B4; 0x09CB; 0x22B6; 0x09CC; 0x22B8; 0x09DC; 0x22BA; + 0x09DD; 0x22BC; 0x09DF; 0x22BE; 0x0A33; 0x22C0; 0x0A36; 0x22C2; + 0x0A59; 0x22C4; 0x0A5A; 0x22C6; 0x0A5B; 0x22C8; 0x0A5E; 0x22CA; + 0x0B48; 0x22CC; 0x0B4B; 0x22CE; 0x0B4C; 0x22D0; 0x0B5C; 0x22D2; + 0x0B5D; 0x22D4; 0x0B94; 0x22D6; 0x0BCA; 0x22D8; 0x0BCB; 0x22DA; + 0x0BCC; 0x22DC; 0x0C48; 0x22DE; 0x0CC0; 0x22E0; 0x0CC7; 0x22E2; + 0x0CC8; 0x22E4; 0x0CCA; 0x22E6; 0x0CCB; 0xA2E8; 0x0D4A; 0x22EA; + 0x0D4B; 0x22EC; 0x0D4C; 0x22EE; 0x0DDA; 0x22F0; 0x0DDC; 0x22F2; + 0x0DDD; 0xA2F4; 0x0DDE; 0x22F6; 0x0F43; 0x22F8; 0x0F4D; 0x22FA; + 0x0F52; 0x22FC; 0x0F57; 0x22FE; 0x0F5C; 0x2300; 0x0F69; 0x2302; + 0x0F73; 0x2304; 0x0F75; 0x2306; 0x0F76; 0x2308; 0x0F78; 0x230A; + 0x0F81; 0x230C; 0x0F93; 0x230E; 0x0F9D; 0x2310; 0x0FA2; 0x2312; + 0x0FA7; 0x2314; 0x0FAC; 0x2316; 0x0FB9; 0x2318; 0x1026; 0x231A; + 0x1E00; 0x231C; 0x1E01; 0x231E; 0x1E02; 0x2320; 0x1E03; 0x2322; + 0x1E04; 0x2324; 0x1E05; 0x2326; 0x1E06; 0x2328; 0x1E07; 0x232A; + 0x1E08; 0xA32C; 0x1E09; 0xA32E; 0x1E0A; 0x2330; 0x1E0B; 0x2332; + 0x1E0C; 0x2334; 0x1E0D; 0x2336; 0x1E0E; 0x2338; 0x1E0F; 0x233A; + 0x1E10; 0x233C; 0x1E11; 0x233E; 0x1E12; 0x2340; 0x1E13; 0x2342; + 0x1E14; 0xA344; 0x1E15; 0xA346; 0x1E16; 0xA348; 0x1E17; 0xA34A; + 0x1E18; 0x234C; 0x1E19; 0x234E; 0x1E1A; 0x2350; 0x1E1B; 0x2352; + 0x1E1C; 0xA354; 0x1E1D; 0xA356; 0x1E1E; 0x2358; 0x1E1F; 0x235A; + 0x1E20; 0x235C; 0x1E21; 0x235E; 0x1E22; 0x2360; 0x1E23; 0x2362; + 0x1E24; 0x2364; 0x1E25; 0x2366; 0x1E26; 0x2368; 0x1E27; 0x236A; + 0x1E28; 0x236C; 0x1E29; 0x236E; 0x1E2A; 0x2370; 0x1E2B; 0x2372; + 0x1E2C; 0x2374; 0x1E2D; 0x2376; 0x1E2E; 0xA378; 0x1E2F; 0xA37A; + 0x1E30; 0x237C; 0x1E31; 0x237E; 0x1E32; 0x2380; 0x1E33; 0x2382; + 0x1E34; 0x2384; 0x1E35; 0x2386; 0x1E36; 0x2388; 0x1E37; 0x238A; + 0x1E38; 0xA38C; 0x1E39; 0xA38E; 0x1E3A; 0x2390; 0x1E3B; 0x2392; + 0x1E3C; 0x2394; 0x1E3D; 0x2396; 0x1E3E; 0x2398; 0x1E3F; 0x239A; + 0x1E40; 0x239C; 0x1E41; 0x239E; 0x1E42; 0x23A0; 0x1E43; 0x23A2; + 0x1E44; 0x23A4; 0x1E45; 0x23A6; 0x1E46; 0x23A8; 0x1E47; 0x23AA; + 0x1E48; 0x23AC; 0x1E49; 0x23AE; 0x1E4A; 0x23B0; 0x1E4B; 0x23B2; + 0x1E4C; 0xA3B4; 0x1E4D; 0xA3B6; 0x1E4E; 0xA3B8; 0x1E4F; 0xA3BA; + 0x1E50; 0xA3BC; 0x1E51; 0xA3BE; 0x1E52; 0xA3C0; 0x1E53; 0xA3C2; + 0x1E54; 0x23C4; 0x1E55; 0x23C6; 0x1E56; 0x23C8; 0x1E57; 0x23CA; + 0x1E58; 0x23CC; 0x1E59; 0x23CE; 0x1E5A; 0x23D0; 0x1E5B; 0x23D2; + 0x1E5C; 0xA3D4; 0x1E5D; 0xA3D6; 0x1E5E; 0x23D8; 0x1E5F; 0x23DA; + 0x1E60; 0x23DC; 0x1E61; 0x23DE; 0x1E62; 0x23E0; 0x1E63; 0x23E2; + 0x1E64; 0xA3E4; 0x1E65; 0xA3E6; 0x1E66; 0xA3E8; 0x1E67; 0xA3EA; + 0x1E68; 0xA3EC; 0x1E69; 0xA3EE; 0x1E6A; 0x23F0; 0x1E6B; 0x23F2; + 0x1E6C; 0x23F4; 0x1E6D; 0x23F6; 0x1E6E; 0x23F8; 0x1E6F; 0x23FA; + 0x1E70; 0x23FC; 0x1E71; 0x23FE; 0x1E72; 0x2400; 0x1E73; 0x2402; + 0x1E74; 0x2404; 0x1E75; 0x2406; 0x1E76; 0x2408; 0x1E77; 0x240A; + 0x1E78; 0xA40C; 0x1E79; 0xA40E; 0x1E7A; 0xA410; 0x1E7B; 0xA412; + 0x1E7C; 0x2414; 0x1E7D; 0x2416; 0x1E7E; 0x2418; 0x1E7F; 0x241A; + 0x1E80; 0x241C; 0x1E81; 0x241E; 0x1E82; 0x2420; 0x1E83; 0x2422; + 0x1E84; 0x2424; 0x1E85; 0x2426; 0x1E86; 0x2428; 0x1E87; 0x242A; + 0x1E88; 0x242C; 0x1E89; 0x242E; 0x1E8A; 0x2430; 0x1E8B; 0x2432; + 0x1E8C; 0x2434; 0x1E8D; 0x2436; 0x1E8E; 0x2438; 0x1E8F; 0x243A; + 0x1E90; 0x243C; 0x1E91; 0x243E; 0x1E92; 0x2440; 0x1E93; 0x2442; + 0x1E94; 0x2444; 0x1E95; 0x2446; 0x1E96; 0x2448; 0x1E97; 0x244A; + 0x1E98; 0x244C; 0x1E99; 0x244E; 0x1E9B; 0x2450; 0x1EA0; 0x2452; + 0x1EA1; 0x2454; 0x1EA2; 0x2456; 0x1EA3; 0x2458; 0x1EA4; 0xA45A; + 0x1EA5; 0xA45C; 0x1EA6; 0xA45E; 0x1EA7; 0xA460; 0x1EA8; 0xA462; + 0x1EA9; 0xA464; 0x1EAA; 0xA466; 0x1EAB; 0xA468; 0x1EAC; 0xA46A; + 0x1EAD; 0xA46C; 0x1EAE; 0xA46E; 0x1EAF; 0xA470; 0x1EB0; 0xA472; + 0x1EB1; 0xA474; 0x1EB2; 0xA476; 0x1EB3; 0xA478; 0x1EB4; 0xA47A; + 0x1EB5; 0xA47C; 0x1EB6; 0xA47E; 0x1EB7; 0xA480; 0x1EB8; 0x2482; + 0x1EB9; 0x2484; 0x1EBA; 0x2486; 0x1EBB; 0x2488; 0x1EBC; 0x248A; + 0x1EBD; 0x248C; 0x1EBE; 0xA48E; 0x1EBF; 0xA490; 0x1EC0; 0xA492; + 0x1EC1; 0xA494; 0x1EC2; 0xA496; 0x1EC3; 0xA498; 0x1EC4; 0xA49A; + 0x1EC5; 0xA49C; 0x1EC6; 0xA49E; 0x1EC7; 0xA4A0; 0x1EC8; 0x24A2; + 0x1EC9; 0x24A4; 0x1ECA; 0x24A6; 0x1ECB; 0x24A8; 0x1ECC; 0x24AA; + 0x1ECD; 0x24AC; 0x1ECE; 0x24AE; 0x1ECF; 0x24B0; 0x1ED0; 0xA4B2; + 0x1ED1; 0xA4B4; 0x1ED2; 0xA4B6; 0x1ED3; 0xA4B8; 0x1ED4; 0xA4BA; + 0x1ED5; 0xA4BC; 0x1ED6; 0xA4BE; 0x1ED7; 0xA4C0; 0x1ED8; 0xA4C2; + 0x1ED9; 0xA4C4; 0x1EDA; 0xA4C6; 0x1EDB; 0xA4C8; 0x1EDC; 0xA4CA; + 0x1EDD; 0xA4CC; 0x1EDE; 0xA4CE; 0x1EDF; 0xA4D0; 0x1EE0; 0xA4D2; + 0x1EE1; 0xA4D4; 0x1EE2; 0xA4D6; 0x1EE3; 0xA4D8; 0x1EE4; 0x24DA; + 0x1EE5; 0x24DC; 0x1EE6; 0x24DE; 0x1EE7; 0x24E0; 0x1EE8; 0xA4E2; + 0x1EE9; 0xA4E4; 0x1EEA; 0xA4E6; 0x1EEB; 0xA4E8; 0x1EEC; 0xA4EA; + 0x1EED; 0xA4EC; 0x1EEE; 0xA4EE; 0x1EEF; 0xA4F0; 0x1EF0; 0xA4F2; + 0x1EF1; 0xA4F4; 0x1EF2; 0x24F6; 0x1EF3; 0x24F8; 0x1EF4; 0x24FA; + 0x1EF5; 0x24FC; 0x1EF6; 0x24FE; 0x1EF7; 0x2500; 0x1EF8; 0x2502; + 0x1EF9; 0x2504; 0x1F00; 0x2506; 0x1F01; 0x2508; 0x1F02; 0xA50A; + 0x1F03; 0xA50C; 0x1F04; 0xA50E; 0x1F05; 0xA510; 0x1F06; 0xA512; + 0x1F07; 0xA514; 0x1F08; 0x2516; 0x1F09; 0x2518; 0x1F0A; 0xA51A; + 0x1F0B; 0xA51C; 0x1F0C; 0xA51E; 0x1F0D; 0xA520; 0x1F0E; 0xA522; + 0x1F0F; 0xA524; 0x1F10; 0x2526; 0x1F11; 0x2528; 0x1F12; 0xA52A; + 0x1F13; 0xA52C; 0x1F14; 0xA52E; 0x1F15; 0xA530; 0x1F18; 0x2532; + 0x1F19; 0x2534; 0x1F1A; 0xA536; 0x1F1B; 0xA538; 0x1F1C; 0xA53A; + 0x1F1D; 0xA53C; 0x1F20; 0x253E; 0x1F21; 0x2540; 0x1F22; 0xA542; + 0x1F23; 0xA544; 0x1F24; 0xA546; 0x1F25; 0xA548; 0x1F26; 0xA54A; + 0x1F27; 0xA54C; 0x1F28; 0x254E; 0x1F29; 0x2550; 0x1F2A; 0xA552; + 0x1F2B; 0xA554; 0x1F2C; 0xA556; 0x1F2D; 0xA558; 0x1F2E; 0xA55A; + 0x1F2F; 0xA55C; 0x1F30; 0x255E; 0x1F31; 0x2560; 0x1F32; 0xA562; + 0x1F33; 0xA564; 0x1F34; 0xA566; 0x1F35; 0xA568; 0x1F36; 0xA56A; + 0x1F37; 0xA56C; 0x1F38; 0x256E; 0x1F39; 0x2570; 0x1F3A; 0xA572; + 0x1F3B; 0xA574; 0x1F3C; 0xA576; 0x1F3D; 0xA578; 0x1F3E; 0xA57A; + 0x1F3F; 0xA57C; 0x1F40; 0x257E; 0x1F41; 0x2580; 0x1F42; 0xA582; + 0x1F43; 0xA584; 0x1F44; 0xA586; 0x1F45; 0xA588; 0x1F48; 0x258A; + 0x1F49; 0x258C; 0x1F4A; 0xA58E; 0x1F4B; 0xA590; 0x1F4C; 0xA592; + 0x1F4D; 0xA594; 0x1F50; 0x2596; 0x1F51; 0x2598; 0x1F52; 0xA59A; + 0x1F53; 0xA59C; 0x1F54; 0xA59E; 0x1F55; 0xA5A0; 0x1F56; 0xA5A2; + 0x1F57; 0xA5A4; 0x1F59; 0x25A6; 0x1F5B; 0xA5A8; 0x1F5D; 0xA5AA; + 0x1F5F; 0xA5AC; 0x1F60; 0x25AE; 0x1F61; 0x25B0; 0x1F62; 0xA5B2; + 0x1F63; 0xA5B4; 0x1F64; 0xA5B6; 0x1F65; 0xA5B8; 0x1F66; 0xA5BA; + 0x1F67; 0xA5BC; 0x1F68; 0x25BE; 0x1F69; 0x25C0; 0x1F6A; 0xA5C2; + 0x1F6B; 0xA5C4; 0x1F6C; 0xA5C6; 0x1F6D; 0xA5C8; 0x1F6E; 0xA5CA; + 0x1F6F; 0xA5CC; 0x1F70; 0x25CE; 0x1F71; 0x93AC; 0x1F72; 0x25D0; + 0x1F73; 0x93AD; 0x1F74; 0x25D2; 0x1F75; 0x93AE; 0x1F76; 0x25D4; + 0x1F77; 0x93AF; 0x1F78; 0x25D6; 0x1F79; 0x93CC; 0x1F7A; 0x25D8; + 0x1F7B; 0x93CD; 0x1F7C; 0x25DA; 0x1F7D; 0x93CE; 0x1F80; 0xA5DC; + 0x1F81; 0xA5DE; 0x1F82; 0xA5E0; 0x1F83; 0xA5E2; 0x1F84; 0xA5E4; + 0x1F85; 0xA5E6; 0x1F86; 0xA5E8; 0x1F87; 0xA5EA; 0x1F88; 0xA5EC; + 0x1F89; 0xA5EE; 0x1F8A; 0xA5F0; 0x1F8B; 0xA5F2; 0x1F8C; 0xA5F4; + 0x1F8D; 0xA5F6; 0x1F8E; 0xA5F8; 0x1F8F; 0xA5FA; 0x1F90; 0xA5FC; + 0x1F91; 0xA5FE; 0x1F92; 0xA600; 0x1F93; 0xA602; 0x1F94; 0xA604; + 0x1F95; 0xA606; 0x1F96; 0xA608; 0x1F97; 0xA60A; 0x1F98; 0xA60C; + 0x1F99; 0xA60E; 0x1F9A; 0xA610; 0x1F9B; 0xA612; 0x1F9C; 0xA614; + 0x1F9D; 0xA616; 0x1F9E; 0xA618; 0x1F9F; 0xA61A; 0x1FA0; 0xA61C; + 0x1FA1; 0xA61E; 0x1FA2; 0xA620; 0x1FA3; 0xA622; 0x1FA4; 0xA624; + 0x1FA5; 0xA626; 0x1FA6; 0xA628; 0x1FA7; 0xA62A; 0x1FA8; 0xA62C; + 0x1FA9; 0xA62E; 0x1FAA; 0xA630; 0x1FAB; 0xA632; 0x1FAC; 0xA634; + 0x1FAD; 0xA636; 0x1FAE; 0xA638; 0x1FAF; 0xA63A; 0x1FB0; 0x263C; + 0x1FB1; 0x263E; 0x1FB2; 0xA640; 0x1FB3; 0x2642; 0x1FB4; 0xA644; + 0x1FB6; 0x2646; 0x1FB7; 0xA648; 0x1FB8; 0x264A; 0x1FB9; 0x264C; + 0x1FBA; 0x264E; 0x1FBB; 0x9386; 0x1FBC; 0x2650; 0x1FBE; 0x13B9; + 0x1FC1; 0x2652; 0x1FC2; 0xA654; 0x1FC3; 0x2656; 0x1FC4; 0xA658; + 0x1FC6; 0x265A; 0x1FC7; 0xA65C; 0x1FC8; 0x265E; 0x1FC9; 0x9388; + 0x1FCA; 0x2660; 0x1FCB; 0x9389; 0x1FCC; 0x2662; 0x1FCD; 0x2664; + 0x1FCE; 0x2666; 0x1FCF; 0x2668; 0x1FD0; 0x266A; 0x1FD1; 0x266C; + 0x1FD2; 0xA66E; 0x1FD3; 0x9390; 0x1FD6; 0x2670; 0x1FD7; 0xA672; + 0x1FD8; 0x2674; 0x1FD9; 0x2676; 0x1FDA; 0x2678; 0x1FDB; 0x938A; + 0x1FDD; 0x267A; 0x1FDE; 0x267C; 0x1FDF; 0x267E; 0x1FE0; 0x2680; + 0x1FE1; 0x2682; 0x1FE2; 0xA684; 0x1FE3; 0x93B0; 0x1FE4; 0x2686; + 0x1FE5; 0x2688; 0x1FE6; 0x268A; 0x1FE7; 0xA68C; 0x1FE8; 0x268E; + 0x1FE9; 0x2690; 0x1FEA; 0x2692; 0x1FEB; 0x938E; 0x1FEC; 0x2694; + 0x1FED; 0x2696; 0x1FEE; 0x9385; 0x1FEF; 0x1060; 0x1FF2; 0xA698; + 0x1FF3; 0x269A; 0x1FF4; 0xA69C; 0x1FF6; 0x269E; 0x1FF7; 0xA6A0; + 0x1FF8; 0x26A2; 0x1FF9; 0x938C; 0x1FFA; 0x26A4; 0x1FFB; 0x938F; + 0x1FFC; 0x26A6; 0x1FFD; 0x10B4; 0x304C; 0x26A8; 0x304E; 0x26AA; + 0x3050; 0x26AC; 0x3052; 0x26AE; 0x3054; 0x26B0; 0x3056; 0x26B2; + 0x3058; 0x26B4; 0x305A; 0x26B6; 0x305C; 0x26B8; 0x305E; 0x26BA; + 0x3060; 0x26BC; 0x3062; 0x26BE; 0x3065; 0x26C0; 0x3067; 0x26C2; + 0x3069; 0x26C4; 0x3070; 0x26C6; 0x3071; 0x26C8; 0x3073; 0x26CA; + 0x3074; 0x26CC; 0x3076; 0x26CE; 0x3077; 0x26D0; 0x3079; 0x26D2; + 0x307A; 0x26D4; 0x307C; 0x26D6; 0x307D; 0x26D8; 0x3094; 0x26DA; + 0x309E; 0x26DC; 0x30AC; 0x26DE; 0x30AE; 0x26E0; 0x30B0; 0x26E2; + 0x30B2; 0x26E4; 0x30B4; 0x26E6; 0x30B6; 0x26E8; 0x30B8; 0x26EA; + 0x30BA; 0x26EC; 0x30BC; 0x26EE; 0x30BE; 0x26F0; 0x30C0; 0x26F2; + 0x30C2; 0x26F4; 0x30C5; 0x26F6; 0x30C7; 0x26F8; 0x30C9; 0x26FA; + 0x30D0; 0x26FC; 0x30D1; 0x26FE; 0x30D3; 0x2700; 0x30D4; 0x2702; + 0x30D6; 0x2704; 0x30D7; 0x2706; 0x30D9; 0x2708; 0x30DA; 0x270A; + 0x30DC; 0x270C; 0x30DD; 0x270E; 0x30F4; 0x2710; 0x30F7; 0x2712; + 0x30F8; 0x2714; 0x30F9; 0x2716; 0x30FA; 0x2718; 0x30FE; 0x271A; + 0xFB1D; 0x271C; 0xFB1F; 0x271E; 0xFB2A; 0x2720; 0xFB2B; 0x2722; + 0xFB2C; 0xA724; 0xFB2D; 0xA726; 0xFB2E; 0x2728; 0xFB2F; 0x272A; + 0xFB30; 0x272C; 0xFB31; 0x272E; 0xFB32; 0x2730; 0xFB33; 0x2732; + 0xFB34; 0x2734; 0xFB35; 0x2736; 0xFB36; 0x2738; 0xFB38; 0x273A; + 0xFB39; 0x273C; 0xFB3A; 0x273E; 0xFB3B; 0x2740; 0xFB3C; 0x2742; + 0xFB3E; 0x2744; 0xFB40; 0x2746; 0xFB41; 0x2748; 0xFB43; 0x274A; + 0xFB44; 0x274C; 0xFB46; 0x274E; 0xFB47; 0x2750; 0xFB48; 0x2752; + 0xFB49; 0x2754; 0xFB4A; 0x2756; 0xFB4B; 0x2758; 0xFB4C; 0x275A; + 0xFB4D; 0x275C; 0xFB4E; 0x275E +|] + +let uniCharMultipleDecompositionTable = [| + 0x0041; 0x0300; 0x0041; 0x0301; 0x0041; 0x0302; 0x0041; 0x0303; + 0x0041; 0x0308; 0x0041; 0x030A; 0x0043; 0x0327; 0x0045; 0x0300; + 0x0045; 0x0301; 0x0045; 0x0302; 0x0045; 0x0308; 0x0049; 0x0300; + 0x0049; 0x0301; 0x0049; 0x0302; 0x0049; 0x0308; 0x004E; 0x0303; + 0x004F; 0x0300; 0x004F; 0x0301; 0x004F; 0x0302; 0x004F; 0x0303; + 0x004F; 0x0308; 0x0055; 0x0300; 0x0055; 0x0301; 0x0055; 0x0302; + 0x0055; 0x0308; 0x0059; 0x0301; 0x0061; 0x0300; 0x0061; 0x0301; + 0x0061; 0x0302; 0x0061; 0x0303; 0x0061; 0x0308; 0x0061; 0x030A; + 0x0063; 0x0327; 0x0065; 0x0300; 0x0065; 0x0301; 0x0065; 0x0302; + 0x0065; 0x0308; 0x0069; 0x0300; 0x0069; 0x0301; 0x0069; 0x0302; + 0x0069; 0x0308; 0x006E; 0x0303; 0x006F; 0x0300; 0x006F; 0x0301; + 0x006F; 0x0302; 0x006F; 0x0303; 0x006F; 0x0308; 0x0075; 0x0300; + 0x0075; 0x0301; 0x0075; 0x0302; 0x0075; 0x0308; 0x0079; 0x0301; + 0x0079; 0x0308; 0x0041; 0x0304; 0x0061; 0x0304; 0x0041; 0x0306; + 0x0061; 0x0306; 0x0041; 0x0328; 0x0061; 0x0328; 0x0043; 0x0301; + 0x0063; 0x0301; 0x0043; 0x0302; 0x0063; 0x0302; 0x0043; 0x0307; + 0x0063; 0x0307; 0x0043; 0x030C; 0x0063; 0x030C; 0x0044; 0x030C; + 0x0064; 0x030C; 0x0045; 0x0304; 0x0065; 0x0304; 0x0045; 0x0306; + 0x0065; 0x0306; 0x0045; 0x0307; 0x0065; 0x0307; 0x0045; 0x0328; + 0x0065; 0x0328; 0x0045; 0x030C; 0x0065; 0x030C; 0x0047; 0x0302; + 0x0067; 0x0302; 0x0047; 0x0306; 0x0067; 0x0306; 0x0047; 0x0307; + 0x0067; 0x0307; 0x0047; 0x0327; 0x0067; 0x0327; 0x0048; 0x0302; + 0x0068; 0x0302; 0x0049; 0x0303; 0x0069; 0x0303; 0x0049; 0x0304; + 0x0069; 0x0304; 0x0049; 0x0306; 0x0069; 0x0306; 0x0049; 0x0328; + 0x0069; 0x0328; 0x0049; 0x0307; 0x004A; 0x0302; 0x006A; 0x0302; + 0x004B; 0x0327; 0x006B; 0x0327; 0x004C; 0x0301; 0x006C; 0x0301; + 0x004C; 0x0327; 0x006C; 0x0327; 0x004C; 0x030C; 0x006C; 0x030C; + 0x004E; 0x0301; 0x006E; 0x0301; 0x004E; 0x0327; 0x006E; 0x0327; + 0x004E; 0x030C; 0x006E; 0x030C; 0x004F; 0x0304; 0x006F; 0x0304; + 0x004F; 0x0306; 0x006F; 0x0306; 0x004F; 0x030B; 0x006F; 0x030B; + 0x0052; 0x0301; 0x0072; 0x0301; 0x0052; 0x0327; 0x0072; 0x0327; + 0x0052; 0x030C; 0x0072; 0x030C; 0x0053; 0x0301; 0x0073; 0x0301; + 0x0053; 0x0302; 0x0073; 0x0302; 0x0053; 0x0327; 0x0073; 0x0327; + 0x0053; 0x030C; 0x0073; 0x030C; 0x0054; 0x0327; 0x0074; 0x0327; + 0x0054; 0x030C; 0x0074; 0x030C; 0x0055; 0x0303; 0x0075; 0x0303; + 0x0055; 0x0304; 0x0075; 0x0304; 0x0055; 0x0306; 0x0075; 0x0306; + 0x0055; 0x030A; 0x0075; 0x030A; 0x0055; 0x030B; 0x0075; 0x030B; + 0x0055; 0x0328; 0x0075; 0x0328; 0x0057; 0x0302; 0x0077; 0x0302; + 0x0059; 0x0302; 0x0079; 0x0302; 0x0059; 0x0308; 0x005A; 0x0301; + 0x007A; 0x0301; 0x005A; 0x0307; 0x007A; 0x0307; 0x005A; 0x030C; + 0x007a; 0x030C; 0x004F; 0x031B; 0x006F; 0x031B; 0x0055; 0x031B; + 0x0075; 0x031B; 0x0041; 0x030C; 0x0061; 0x030C; 0x0049; 0x030C; + 0x0069; 0x030C; 0x004F; 0x030C; 0x006F; 0x030C; 0x0055; 0x030C; + 0x0075; 0x030C; 0x00DC; 0x0304; 0x00FC; 0x0304; 0x00DC; 0x0301; + 0x00FC; 0x0301; 0x00DC; 0x030C; 0x00FC; 0x030C; 0x00DC; 0x0300; + 0x00FC; 0x0300; 0x00C4; 0x0304; 0x00E4; 0x0304; 0x0226; 0x0304; + 0x0227; 0x0304; 0x00C6; 0x0304; 0x00E6; 0x0304; 0x0047; 0x030C; + 0x0067; 0x030C; 0x004B; 0x030C; 0x006B; 0x030C; 0x004F; 0x0328; + 0x006F; 0x0328; 0x01EA; 0x0304; 0x01EB; 0x0304; 0x01B7; 0x030C; + 0x0292; 0x030C; 0x006A; 0x030C; 0x0047; 0x0301; 0x0067; 0x0301; + 0x004E; 0x0300; 0x006E; 0x0300; 0x00C5; 0x0301; 0x00E5; 0x0301; + 0x00C6; 0x0301; 0x00E6; 0x0301; 0x00D8; 0x0301; 0x00F8; 0x0301; + 0x0041; 0x030F; 0x0061; 0x030F; 0x0041; 0x0311; 0x0061; 0x0311; + 0x0045; 0x030F; 0x0065; 0x030F; 0x0045; 0x0311; 0x0065; 0x0311; + 0x0049; 0x030F; 0x0069; 0x030F; 0x0049; 0x0311; 0x0069; 0x0311; + 0x004F; 0x030F; 0x006F; 0x030F; 0x004F; 0x0311; 0x006F; 0x0311; + 0x0052; 0x030F; 0x0072; 0x030F; 0x0052; 0x0311; 0x0072; 0x0311; + 0x0055; 0x030F; 0x0075; 0x030F; 0x0055; 0x0311; 0x0075; 0x0311; + 0x0053; 0x0326; 0x0073; 0x0326; 0x0054; 0x0326; 0x0074; 0x0326; + 0x0048; 0x030C; 0x0068; 0x030C; 0x0041; 0x0307; 0x0061; 0x0307; + 0x0045; 0x0327; 0x0065; 0x0327; 0x00D6; 0x0304; 0x00F6; 0x0304; + 0x00D5; 0x0304; 0x00F5; 0x0304; 0x004F; 0x0307; 0x006F; 0x0307; + 0x022E; 0x0304; 0x022F; 0x0304; 0x0059; 0x0304; 0x0079; 0x0304; + 0x0308; 0x0301; 0x00A8; 0x0301; 0x0391; 0x0301; 0x0395; 0x0301; + 0x0397; 0x0301; 0x0399; 0x0301; 0x039F; 0x0301; 0x03A5; 0x0301; + 0x03A9; 0x0301; 0x03CA; 0x0301; 0x0399; 0x0308; 0x03A5; 0x0308; + 0x03B1; 0x0301; 0x03B5; 0x0301; 0x03B7; 0x0301; 0x03B9; 0x0301; + 0x03CB; 0x0301; 0x03B9; 0x0308; 0x03C5; 0x0308; 0x03BF; 0x0301; + 0x03C5; 0x0301; 0x03C9; 0x0301; 0x03D2; 0x0301; 0x03D2; 0x0308; + 0x0415; 0x0300; 0x0415; 0x0308; 0x0413; 0x0301; 0x0406; 0x0308; + 0x041A; 0x0301; 0x0418; 0x0300; 0x0423; 0x0306; 0x0418; 0x0306; + 0x0438; 0x0306; 0x0435; 0x0300; 0x0435; 0x0308; 0x0433; 0x0301; + 0x0456; 0x0308; 0x043A; 0x0301; 0x0438; 0x0300; 0x0443; 0x0306; + 0x0474; 0x030F; 0x0475; 0x030F; 0x0416; 0x0306; 0x0436; 0x0306; + 0x0410; 0x0306; 0x0430; 0x0306; 0x0410; 0x0308; 0x0430; 0x0308; + 0x0415; 0x0306; 0x0435; 0x0306; 0x04D8; 0x0308; 0x04D9; 0x0308; + 0x0416; 0x0308; 0x0436; 0x0308; 0x0417; 0x0308; 0x0437; 0x0308; + 0x0418; 0x0304; 0x0438; 0x0304; 0x0418; 0x0308; 0x0438; 0x0308; + 0x041E; 0x0308; 0x043E; 0x0308; 0x04E8; 0x0308; 0x04E9; 0x0308; + 0x042D; 0x0308; 0x044D; 0x0308; 0x0423; 0x0304; 0x0443; 0x0304; + 0x0423; 0x0308; 0x0443; 0x0308; 0x0423; 0x030B; 0x0443; 0x030B; + 0x0427; 0x0308; 0x0447; 0x0308; 0x042B; 0x0308; 0x044B; 0x0308; + 0x0627; 0x0653; 0x0627; 0x0654; 0x0648; 0x0654; 0x0627; 0x0655; + 0x064A; 0x0654; 0x06D5; 0x0654; 0x06C1; 0x0654; 0x06D2; 0x0654; + 0x0928; 0x093C; 0x0930; 0x093C; 0x0933; 0x093C; 0x0915; 0x093C; + 0x0916; 0x093C; 0x0917; 0x093C; 0x091C; 0x093C; 0x0921; 0x093C; + 0x0922; 0x093C; 0x092B; 0x093C; 0x092F; 0x093C; 0x09C7; 0x09BE; + 0x09C7; 0x09D7; 0x09A1; 0x09BC; 0x09A2; 0x09BC; 0x09AF; 0x09BC; + 0x0A32; 0x0A3C; 0x0A38; 0x0A3C; 0x0A16; 0x0A3C; 0x0A17; 0x0A3C; + 0x0A1C; 0x0A3C; 0x0A2B; 0x0A3C; 0x0B47; 0x0B56; 0x0B47; 0x0B3E; + 0x0B47; 0x0B57; 0x0B21; 0x0B3C; 0x0B22; 0x0B3C; 0x0B92; 0x0BD7; + 0x0BC6; 0x0BBE; 0x0BC7; 0x0BBE; 0x0BC6; 0x0BD7; 0x0C46; 0x0C56; + 0x0CBF; 0x0CD5; 0x0CC6; 0x0CD5; 0x0CC6; 0x0CD6; 0x0CC6; 0x0CC2; + 0x0CCA; 0x0CD5; 0x0D46; 0x0D3E; 0x0D47; 0x0D3E; 0x0D46; 0x0D57; + 0x0DD9; 0x0DCA; 0x0DD9; 0x0DCF; 0x0DDC; 0x0DCA; 0x0DD9; 0x0DDF; + 0x0F42; 0x0FB7; 0x0F4C; 0x0FB7; 0x0F51; 0x0FB7; 0x0F56; 0x0FB7; + 0x0F5B; 0x0FB7; 0x0F40; 0x0FB5; 0x0F71; 0x0F72; 0x0F71; 0x0F74; + 0x0FB2; 0x0F80; 0x0FB3; 0x0F80; 0x0F71; 0x0F80; 0x0F92; 0x0FB7; + 0x0F9C; 0x0FB7; 0x0FA1; 0x0FB7; 0x0FA6; 0x0FB7; 0x0FAB; 0x0FB7; + 0x0F90; 0x0FB5; 0x1025; 0x102E; 0x0041; 0x0325; 0x0061; 0x0325; + 0x0042; 0x0307; 0x0062; 0x0307; 0x0042; 0x0323; 0x0062; 0x0323; + 0x0042; 0x0331; 0x0062; 0x0331; 0x00C7; 0x0301; 0x00E7; 0x0301; + 0x0044; 0x0307; 0x0064; 0x0307; 0x0044; 0x0323; 0x0064; 0x0323; + 0x0044; 0x0331; 0x0064; 0x0331; 0x0044; 0x0327; 0x0064; 0x0327; + 0x0044; 0x032D; 0x0064; 0x032D; 0x0112; 0x0300; 0x0113; 0x0300; + 0x0112; 0x0301; 0x0113; 0x0301; 0x0045; 0x032D; 0x0065; 0x032D; + 0x0045; 0x0330; 0x0065; 0x0330; 0x0228; 0x0306; 0x0229; 0x0306; + 0x0046; 0x0307; 0x0066; 0x0307; 0x0047; 0x0304; 0x0067; 0x0304; + 0x0048; 0x0307; 0x0068; 0x0307; 0x0048; 0x0323; 0x0068; 0x0323; + 0x0048; 0x0308; 0x0068; 0x0308; 0x0048; 0x0327; 0x0068; 0x0327; + 0x0048; 0x032E; 0x0068; 0x032E; 0x0049; 0x0330; 0x0069; 0x0330; + 0x00CF; 0x0301; 0x00EF; 0x0301; 0x004B; 0x0301; 0x006B; 0x0301; + 0x004B; 0x0323; 0x006B; 0x0323; 0x004B; 0x0331; 0x006B; 0x0331; + 0x004C; 0x0323; 0x006C; 0x0323; 0x1E36; 0x0304; 0x1E37; 0x0304; + 0x004C; 0x0331; 0x006C; 0x0331; 0x004C; 0x032D; 0x006C; 0x032D; + 0x004D; 0x0301; 0x006D; 0x0301; 0x004D; 0x0307; 0x006D; 0x0307; + 0x004D; 0x0323; 0x006D; 0x0323; 0x004E; 0x0307; 0x006E; 0x0307; + 0x004E; 0x0323; 0x006E; 0x0323; 0x004E; 0x0331; 0x006E; 0x0331; + 0x004E; 0x032D; 0x006E; 0x032D; 0x00D5; 0x0301; 0x00F5; 0x0301; + 0x00D5; 0x0308; 0x00F5; 0x0308; 0x014C; 0x0300; 0x014D; 0x0300; + 0x014C; 0x0301; 0x014D; 0x0301; 0x0050; 0x0301; 0x0070; 0x0301; + 0x0050; 0x0307; 0x0070; 0x0307; 0x0052; 0x0307; 0x0072; 0x0307; + 0x0052; 0x0323; 0x0072; 0x0323; 0x1E5A; 0x0304; 0x1E5B; 0x0304; + 0x0052; 0x0331; 0x0072; 0x0331; 0x0053; 0x0307; 0x0073; 0x0307; + 0x0053; 0x0323; 0x0073; 0x0323; 0x015A; 0x0307; 0x015B; 0x0307; + 0x0160; 0x0307; 0x0161; 0x0307; 0x1E62; 0x0307; 0x1E63; 0x0307; + 0x0054; 0x0307; 0x0074; 0x0307; 0x0054; 0x0323; 0x0074; 0x0323; + 0x0054; 0x0331; 0x0074; 0x0331; 0x0054; 0x032D; 0x0074; 0x032D; + 0x0055; 0x0324; 0x0075; 0x0324; 0x0055; 0x0330; 0x0075; 0x0330; + 0x0055; 0x032D; 0x0075; 0x032D; 0x0168; 0x0301; 0x0169; 0x0301; + 0x016A; 0x0308; 0x016B; 0x0308; 0x0056; 0x0303; 0x0076; 0x0303; + 0x0056; 0x0323; 0x0076; 0x0323; 0x0057; 0x0300; 0x0077; 0x0300; + 0x0057; 0x0301; 0x0077; 0x0301; 0x0057; 0x0308; 0x0077; 0x0308; + 0x0057; 0x0307; 0x0077; 0x0307; 0x0057; 0x0323; 0x0077; 0x0323; + 0x0058; 0x0307; 0x0078; 0x0307; 0x0058; 0x0308; 0x0078; 0x0308; + 0x0059; 0x0307; 0x0079; 0x0307; 0x005A; 0x0302; 0x007A; 0x0302; + 0x005A; 0x0323; 0x007A; 0x0323; 0x005A; 0x0331; 0x007A; 0x0331; + 0x0068; 0x0331; 0x0074; 0x0308; 0x0077; 0x030A; 0x0079; 0x030A; + 0x017F; 0x0307; 0x0041; 0x0323; 0x0061; 0x0323; 0x0041; 0x0309; + 0x0061; 0x0309; 0x00C2; 0x0301; 0x00E2; 0x0301; 0x00C2; 0x0300; + 0x00E2; 0x0300; 0x00C2; 0x0309; 0x00E2; 0x0309; 0x00C2; 0x0303; + 0x00E2; 0x0303; 0x1EA0; 0x0302; 0x1EA1; 0x0302; 0x0102; 0x0301; + 0x0103; 0x0301; 0x0102; 0x0300; 0x0103; 0x0300; 0x0102; 0x0309; + 0x0103; 0x0309; 0x0102; 0x0303; 0x0103; 0x0303; 0x1EA0; 0x0306; + 0x1EA1; 0x0306; 0x0045; 0x0323; 0x0065; 0x0323; 0x0045; 0x0309; + 0x0065; 0x0309; 0x0045; 0x0303; 0x0065; 0x0303; 0x00CA; 0x0301; + 0x00EA; 0x0301; 0x00CA; 0x0300; 0x00EA; 0x0300; 0x00CA; 0x0309; + 0x00EA; 0x0309; 0x00CA; 0x0303; 0x00EA; 0x0303; 0x1EB8; 0x0302; + 0x1EB9; 0x0302; 0x0049; 0x0309; 0x0069; 0x0309; 0x0049; 0x0323; + 0x0069; 0x0323; 0x004F; 0x0323; 0x006F; 0x0323; 0x004F; 0x0309; + 0x006F; 0x0309; 0x00D4; 0x0301; 0x00F4; 0x0301; 0x00D4; 0x0300; + 0x00F4; 0x0300; 0x00D4; 0x0309; 0x00F4; 0x0309; 0x00D4; 0x0303; + 0x00F4; 0x0303; 0x1ECC; 0x0302; 0x1ECD; 0x0302; 0x01A0; 0x0301; + 0x01A1; 0x0301; 0x01A0; 0x0300; 0x01A1; 0x0300; 0x01A0; 0x0309; + 0x01A1; 0x0309; 0x01A0; 0x0303; 0x01A1; 0x0303; 0x01A0; 0x0323; + 0x01A1; 0x0323; 0x0055; 0x0323; 0x0075; 0x0323; 0x0055; 0x0309; + 0x0075; 0x0309; 0x01AF; 0x0301; 0x01B0; 0x0301; 0x01AF; 0x0300; + 0x01B0; 0x0300; 0x01AF; 0x0309; 0x01B0; 0x0309; 0x01AF; 0x0303; + 0x01B0; 0x0303; 0x01AF; 0x0323; 0x01B0; 0x0323; 0x0059; 0x0300; + 0x0079; 0x0300; 0x0059; 0x0323; 0x0079; 0x0323; 0x0059; 0x0309; + 0x0079; 0x0309; 0x0059; 0x0303; 0x0079; 0x0303; 0x03B1; 0x0313; + 0x03B1; 0x0314; 0x1F00; 0x0300; 0x1F01; 0x0300; 0x1F00; 0x0301; + 0x1F01; 0x0301; 0x1F00; 0x0342; 0x1F01; 0x0342; 0x0391; 0x0313; + 0x0391; 0x0314; 0x1F08; 0x0300; 0x1F09; 0x0300; 0x1F08; 0x0301; + 0x1F09; 0x0301; 0x1F08; 0x0342; 0x1F09; 0x0342; 0x03B5; 0x0313; + 0x03B5; 0x0314; 0x1F10; 0x0300; 0x1F11; 0x0300; 0x1F10; 0x0301; + 0x1F11; 0x0301; 0x0395; 0x0313; 0x0395; 0x0314; 0x1F18; 0x0300; + 0x1F19; 0x0300; 0x1F18; 0x0301; 0x1F19; 0x0301; 0x03B7; 0x0313; + 0x03B7; 0x0314; 0x1F20; 0x0300; 0x1F21; 0x0300; 0x1F20; 0x0301; + 0x1F21; 0x0301; 0x1F20; 0x0342; 0x1F21; 0x0342; 0x0397; 0x0313; + 0x0397; 0x0314; 0x1F28; 0x0300; 0x1F29; 0x0300; 0x1F28; 0x0301; + 0x1F29; 0x0301; 0x1F28; 0x0342; 0x1F29; 0x0342; 0x03B9; 0x0313; + 0x03B9; 0x0314; 0x1F30; 0x0300; 0x1F31; 0x0300; 0x1F30; 0x0301; + 0x1F31; 0x0301; 0x1F30; 0x0342; 0x1F31; 0x0342; 0x0399; 0x0313; + 0x0399; 0x0314; 0x1F38; 0x0300; 0x1F39; 0x0300; 0x1F38; 0x0301; + 0x1F39; 0x0301; 0x1F38; 0x0342; 0x1F39; 0x0342; 0x03BF; 0x0313; + 0x03BF; 0x0314; 0x1F40; 0x0300; 0x1F41; 0x0300; 0x1F40; 0x0301; + 0x1F41; 0x0301; 0x039F; 0x0313; 0x039F; 0x0314; 0x1F48; 0x0300; + 0x1F49; 0x0300; 0x1F48; 0x0301; 0x1F49; 0x0301; 0x03C5; 0x0313; + 0x03C5; 0x0314; 0x1F50; 0x0300; 0x1F51; 0x0300; 0x1F50; 0x0301; + 0x1F51; 0x0301; 0x1F50; 0x0342; 0x1F51; 0x0342; 0x03A5; 0x0314; + 0x1F59; 0x0300; 0x1F59; 0x0301; 0x1F59; 0x0342; 0x03C9; 0x0313; + 0x03C9; 0x0314; 0x1F60; 0x0300; 0x1F61; 0x0300; 0x1F60; 0x0301; + 0x1F61; 0x0301; 0x1F60; 0x0342; 0x1F61; 0x0342; 0x03A9; 0x0313; + 0x03A9; 0x0314; 0x1F68; 0x0300; 0x1F69; 0x0300; 0x1F68; 0x0301; + 0x1F69; 0x0301; 0x1F68; 0x0342; 0x1F69; 0x0342; 0x03B1; 0x0300; + 0x03B5; 0x0300; 0x03B7; 0x0300; 0x03B9; 0x0300; 0x03BF; 0x0300; + 0x03C5; 0x0300; 0x03C9; 0x0300; 0x1F00; 0x0345; 0x1F01; 0x0345; + 0x1F02; 0x0345; 0x1F03; 0x0345; 0x1F04; 0x0345; 0x1F05; 0x0345; + 0x1F06; 0x0345; 0x1F07; 0x0345; 0x1F08; 0x0345; 0x1F09; 0x0345; + 0x1F0A; 0x0345; 0x1F0B; 0x0345; 0x1F0C; 0x0345; 0x1F0D; 0x0345; + 0x1F0E; 0x0345; 0x1F0F; 0x0345; 0x1F20; 0x0345; 0x1F21; 0x0345; + 0x1F22; 0x0345; 0x1F23; 0x0345; 0x1F24; 0x0345; 0x1F25; 0x0345; + 0x1F26; 0x0345; 0x1F27; 0x0345; 0x1F28; 0x0345; 0x1F29; 0x0345; + 0x1F2A; 0x0345; 0x1F2B; 0x0345; 0x1F2C; 0x0345; 0x1F2D; 0x0345; + 0x1F2E; 0x0345; 0x1F2F; 0x0345; 0x1F60; 0x0345; 0x1F61; 0x0345; + 0x1F62; 0x0345; 0x1F63; 0x0345; 0x1F64; 0x0345; 0x1F65; 0x0345; + 0x1F66; 0x0345; 0x1F67; 0x0345; 0x1F68; 0x0345; 0x1F69; 0x0345; + 0x1F6A; 0x0345; 0x1F6B; 0x0345; 0x1F6C; 0x0345; 0x1F6D; 0x0345; + 0x1F6E; 0x0345; 0x1F6F; 0x0345; 0x03B1; 0x0306; 0x03B1; 0x0304; + 0x1F70; 0x0345; 0x03B1; 0x0345; 0x03AC; 0x0345; 0x03B1; 0x0342; + 0x1FB6; 0x0345; 0x0391; 0x0306; 0x0391; 0x0304; 0x0391; 0x0300; + 0x0391; 0x0345; 0x00A8; 0x0342; 0x1F74; 0x0345; 0x03B7; 0x0345; + 0x03AE; 0x0345; 0x03B7; 0x0342; 0x1FC6; 0x0345; 0x0395; 0x0300; + 0x0397; 0x0300; 0x0397; 0x0345; 0x1FBF; 0x0300; 0x1FBF; 0x0301; + 0x1FBF; 0x0342; 0x03B9; 0x0306; 0x03B9; 0x0304; 0x03CA; 0x0300; + 0x03B9; 0x0342; 0x03CA; 0x0342; 0x0399; 0x0306; 0x0399; 0x0304; + 0x0399; 0x0300; 0x1FFE; 0x0300; 0x1FFE; 0x0301; 0x1FFE; 0x0342; + 0x03C5; 0x0306; 0x03C5; 0x0304; 0x03CB; 0x0300; 0x03C1; 0x0313; + 0x03C1; 0x0314; 0x03C5; 0x0342; 0x03CB; 0x0342; 0x03A5; 0x0306; + 0x03A5; 0x0304; 0x03A5; 0x0300; 0x03A1; 0x0314; 0x00A8; 0x0300; + 0x1F7C; 0x0345; 0x03C9; 0x0345; 0x03CE; 0x0345; 0x03C9; 0x0342; + 0x1FF6; 0x0345; 0x039F; 0x0300; 0x03A9; 0x0300; 0x03A9; 0x0345; + 0x304B; 0x3099; 0x304D; 0x3099; 0x304F; 0x3099; 0x3051; 0x3099; + 0x3053; 0x3099; 0x3055; 0x3099; 0x3057; 0x3099; 0x3059; 0x3099; + 0x305B; 0x3099; 0x305D; 0x3099; 0x305F; 0x3099; 0x3061; 0x3099; + 0x3064; 0x3099; 0x3066; 0x3099; 0x3068; 0x3099; 0x306F; 0x3099; + 0x306F; 0x309A; 0x3072; 0x3099; 0x3072; 0x309A; 0x3075; 0x3099; + 0x3075; 0x309A; 0x3078; 0x3099; 0x3078; 0x309A; 0x307B; 0x3099; + 0x307B; 0x309A; 0x3046; 0x3099; 0x309D; 0x3099; 0x30AB; 0x3099; + 0x30AD; 0x3099; 0x30AF; 0x3099; 0x30B1; 0x3099; 0x30B3; 0x3099; + 0x30B5; 0x3099; 0x30B7; 0x3099; 0x30B9; 0x3099; 0x30BB; 0x3099; + 0x30BD; 0x3099; 0x30BF; 0x3099; 0x30C1; 0x3099; 0x30C4; 0x3099; + 0x30C6; 0x3099; 0x30C8; 0x3099; 0x30CF; 0x3099; 0x30CF; 0x309A; + 0x30D2; 0x3099; 0x30D2; 0x309A; 0x30D5; 0x3099; 0x30D5; 0x309A; + 0x30D8; 0x3099; 0x30D8; 0x309A; 0x30DB; 0x3099; 0x30DB; 0x309A; + 0x30A6; 0x3099; 0x30EF; 0x3099; 0x30F0; 0x3099; 0x30F1; 0x3099; + 0x30F2; 0x3099; 0x30FD; 0x3099; 0x05D9; 0x05B4; 0x05F2; 0x05B7; + 0x05E9; 0x05C1; 0x05E9; 0x05C2; 0xFB49; 0x05C1; 0xFB49; 0x05C2; + 0x05D0; 0x05B7; 0x05D0; 0x05B8; 0x05D0; 0x05BC; 0x05D1; 0x05BC; + 0x05D2; 0x05BC; 0x05D3; 0x05BC; 0x05D4; 0x05BC; 0x05D5; 0x05BC; + 0x05D6; 0x05BC; 0x05D8; 0x05BC; 0x05D9; 0x05BC; 0x05DA; 0x05BC; + 0x05DB; 0x05BC; 0x05DC; 0x05BC; 0x05DE; 0x05BC; 0x05E0; 0x05BC; + 0x05E1; 0x05BC; 0x05E3; 0x05BC; 0x05E4; 0x05BC; 0x05E6; 0x05BC; + 0x05E7; 0x05BC; 0x05E8; 0x05BC; 0x05E9; 0x05BC; 0x05EA; 0x05BC; + 0x05D5; 0x05B9; 0x05D1; 0x05BF; 0x05DB; 0x05BF; 0x05E4; 0x05BF +|] + +let uniCharDecomposableBitmap = [| + 0x01; 0x02; 0x03; 0x04; 0x05; 0x00; 0x06; 0x00; + 0x00; 0x07; 0x08; 0x09; 0x0A; 0x0B; 0x00; 0x0C; + 0x0D; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x0E; 0x0F; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x10; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0xFF; 0xFF; 0xFF; 0xFF; + 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; + 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; + 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; + 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; + 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0x11; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x12; 0x00; 0x00; 0x00; 0x00; + + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0xBF; 0xFF; 0x7E; 0x3E; 0xBF; 0xFF; 0x7E; 0xBE; + 0xFF; 0xFF; 0xFC; 0xFF; 0x3F; 0xFF; 0xF1; 0x7E; + 0xF8; 0xF1; 0xF3; 0xFF; 0x3F; 0xFF; 0xFF; 0x7F; + 0x00; 0x00; 0x00; 0x00; 0x03; 0x80; 0x01; 0x00; + 0x00; 0xE0; 0xFF; 0xDF; 0xCF; 0xFF; 0x31; 0xFF; + 0xFF; 0xFF; 0xFF; 0xCF; 0xC0; 0xFF; 0x0F; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x1B; 0x00; 0x00; 0x00; 0x00; 0x00; 0x10; 0x40; + 0xE0; 0xD7; 0x01; 0x00; 0x00; 0xFC; 0x01; 0x00; + 0x00; 0x7C; 0x18; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x8B; 0x70; 0x00; 0x02; 0x00; 0x00; 0x00; 0x02; + 0x00; 0x00; 0x8B; 0x70; 0x00; 0x00; 0xC0; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x06; 0x00; 0xCF; 0xFC; 0xFC; 0xFC; 0x3F; 0x03; + 0x00; 0x00; 0x00; 0x00; 0x7C; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x05; 0x00; 0x08; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x02; 0x12; 0x00; + 0x00; 0x00; 0x00; 0xFF; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x18; 0x00; 0xB0; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x48; 0x00; + 0x00; 0x00; 0x00; 0x4E; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x19; 0x00; 0x30; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x10; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x1C; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x01; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x81; 0x0D; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x1C; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x74; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x08; 0x20; 0x84; 0x10; 0x00; 0x02; 0x68; 0x01; + 0x02; 0x00; 0x08; 0x20; 0x84; 0x10; 0x00; 0x02; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x40; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; + 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; + 0xFF; 0xFF; 0xFF; 0x0B; 0xFF; 0xFF; 0xFF; 0xFF; + 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0x03; + 0xFF; 0xFF; 0x3F; 0x3F; 0xFF; 0xFF; 0xFF; 0xFF; + 0x3F; 0x3F; 0xFF; 0xAA; 0xFF; 0xFF; 0xFF; 0x3F; + 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xDF; 0x5F; + 0xDE; 0xFF; 0xCF; 0xEF; 0xFF; 0xFF; 0xDC; 0x3F; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x50; 0x55; 0x55; 0xA5; 0x02; 0xDB; 0x36; + 0x00; 0x00; 0x10; 0x40; 0x00; 0x50; 0x55; 0x55; + 0xA5; 0x02; 0xDB; 0x36; 0x00; 0x00; 0x90; 0x47; + 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; + 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; + 0xFF; 0xFF; 0xFF; 0xFF; 0x0F; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0xA0; 0x00; 0xFC; 0x7F; 0x5F; + 0xDB; 0x7F; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00 +|] + +let uniCharPrecompSourceTable = [| + 0x00000300; 0x00540000; 0x00000301; 0x00750054; + 0x00000302; 0x002000C9; 0x00000303; 0x001C00E9; + 0x00000304; 0x002C0105; 0x00000306; 0x00200131; + 0x00000307; 0x002E0151; 0x00000308; 0x0036017F; + 0x00000309; 0x001801B5; 0x0000030A; 0x000601CD; + 0x0000030B; 0x000601D3; 0x0000030C; 0x002501D9; + 0x0000030F; 0x000E01FE; 0x00000311; 0x000C020C; + 0x00000313; 0x000E0218; 0x00000314; 0x00100226; + 0x0000031B; 0x00040236; 0x00000323; 0x002A023A; + 0x00000324; 0x00020264; 0x00000325; 0x00020266; + 0x00000326; 0x00040268; 0x00000327; 0x0016026C; + 0x00000328; 0x000A0282; 0x0000032D; 0x000C028C; + 0x0000032E; 0x00020298; 0x00000330; 0x0006029A; + 0x00000331; 0x001102A0; 0x00000338; 0x002C02B1; + 0x00000342; 0x001D02DD; 0x00000345; 0x003F02FA; + 0x00000653; 0x00010339; 0x00000654; 0x0006033A; + 0x00000655; 0x00010340; 0x0000093C; 0x00030341; + 0x000009BE; 0x00010344; 0x000009D7; 0x00010345; + 0x00000B3E; 0x00010346; 0x00000B56; 0x00010347; + 0x00000B57; 0x00010348; 0x00000BBE; 0x00020349; + 0x00000BD7; 0x0002034B; 0x00000C56; 0x0001034D; + 0x00000CC2; 0x0001034E; 0x00000CD5; 0x0003034F; + 0x00000CD6; 0x00010352; 0x00000D3E; 0x00020353; + 0x00000D57; 0x00010355; 0x00000DCA; 0x00020356; + 0x00000DCF; 0x00010358; 0x00000DDF; 0x00010359; + 0x0000102E; 0x0001035A; 0x00003099; 0x0030035B; + 0x0000309A; 0x000A038B +|] + + +let uniCharBMPPrecompDestinationTable = [| + 0x0041; 0x00C0; 0x0045; 0x00C8; 0x0049; 0x00CC; 0x004E; 0x01F8; + 0x004F; 0x00D2; 0x0055; 0x00D9; 0x0057; 0x1E80; 0x0059; 0x1EF2; + 0x0061; 0x00E0; 0x0065; 0x00E8; 0x0069; 0x00EC; 0x006E; 0x01F9; + 0x006F; 0x00F2; 0x0075; 0x00F9; 0x0077; 0x1E81; 0x0079; 0x1EF3; + 0x00A8; 0x1FED; 0x00C2; 0x1EA6; 0x00CA; 0x1EC0; 0x00D4; 0x1ED2; + 0x00DC; 0x01DB; 0x00E2; 0x1EA7; 0x00EA; 0x1EC1; 0x00F4; 0x1ED3; + 0x00FC; 0x01DC; 0x0102; 0x1EB0; 0x0103; 0x1EB1; 0x0112; 0x1E14; + 0x0113; 0x1E15; 0x014C; 0x1E50; 0x014D; 0x1E51; 0x01A0; 0x1EDC; + 0x01A1; 0x1EDD; 0x01AF; 0x1EEA; 0x01B0; 0x1EEB; 0x0391; 0x1FBA; + 0x0395; 0x1FC8; 0x0397; 0x1FCA; 0x0399; 0x1FDA; 0x039F; 0x1FF8; + 0x03A5; 0x1FEA; 0x03A9; 0x1FFA; 0x03B1; 0x1F70; 0x03B5; 0x1F72; + 0x03B7; 0x1F74; 0x03B9; 0x1F76; 0x03BF; 0x1F78; 0x03C5; 0x1F7A; + 0x03C9; 0x1F7C; 0x03CA; 0x1FD2; 0x03CB; 0x1FE2; 0x0415; 0x0400; + 0x0418; 0x040D; 0x0435; 0x0450; 0x0438; 0x045D; 0x1F00; 0x1F02; + 0x1F01; 0x1F03; 0x1F08; 0x1F0A; 0x1F09; 0x1F0B; 0x1F10; 0x1F12; + 0x1F11; 0x1F13; 0x1F18; 0x1F1A; 0x1F19; 0x1F1B; 0x1F20; 0x1F22; + 0x1F21; 0x1F23; 0x1F28; 0x1F2A; 0x1F29; 0x1F2B; 0x1F30; 0x1F32; + 0x1F31; 0x1F33; 0x1F38; 0x1F3A; 0x1F39; 0x1F3B; 0x1F40; 0x1F42; + 0x1F41; 0x1F43; 0x1F48; 0x1F4A; 0x1F49; 0x1F4B; 0x1F50; 0x1F52; + 0x1F51; 0x1F53; 0x1F59; 0x1F5B; 0x1F60; 0x1F62; 0x1F61; 0x1F63; + 0x1F68; 0x1F6A; 0x1F69; 0x1F6B; 0x1FBF; 0x1FCD; 0x1FFE; 0x1FDD; + 0x0041; 0x00C1; 0x0043; 0x0106; 0x0045; 0x00C9; 0x0047; 0x01F4; + 0x0049; 0x00CD; 0x004B; 0x1E30; 0x004C; 0x0139; 0x004D; 0x1E3E; + 0x004E; 0x0143; 0x004F; 0x00D3; 0x0050; 0x1E54; 0x0052; 0x0154; + 0x0053; 0x015A; 0x0055; 0x00DA; 0x0057; 0x1E82; 0x0059; 0x00DD; + 0x005A; 0x0179; 0x0061; 0x00E1; 0x0063; 0x0107; 0x0065; 0x00E9; + 0x0067; 0x01F5; 0x0069; 0x00ED; 0x006B; 0x1E31; 0x006C; 0x013A; + 0x006D; 0x1E3F; 0x006E; 0x0144; 0x006F; 0x00F3; 0x0070; 0x1E55; + 0x0072; 0x0155; 0x0073; 0x015B; 0x0075; 0x00FA; 0x0077; 0x1E83; + 0x0079; 0x00FD; 0x007A; 0x017A; 0x00A8; 0x0385; 0x00C2; 0x1EA4; + 0x00C5; 0x01FA; 0x00C6; 0x01FC; 0x00C7; 0x1E08; 0x00CA; 0x1EBE; + 0x00CF; 0x1E2E; 0x00D4; 0x1ED0; 0x00D5; 0x1E4C; 0x00D8; 0x01FE; + 0x00DC; 0x01D7; 0x00E2; 0x1EA5; 0x00E5; 0x01FB; 0x00E6; 0x01FD; + 0x00E7; 0x1E09; 0x00EA; 0x1EBF; 0x00EF; 0x1E2F; 0x00F4; 0x1ED1; + 0x00F5; 0x1E4D; 0x00F8; 0x01FF; 0x00FC; 0x01D8; 0x0102; 0x1EAE; + 0x0103; 0x1EAF; 0x0112; 0x1E16; 0x0113; 0x1E17; 0x014C; 0x1E52; + 0x014D; 0x1E53; 0x0168; 0x1E78; 0x0169; 0x1E79; 0x01A0; 0x1EDA; + 0x01A1; 0x1EDB; 0x01AF; 0x1EE8; 0x01B0; 0x1EE9; 0x0391; 0x0386; + 0x0395; 0x0388; 0x0397; 0x0389; 0x0399; 0x038A; 0x039F; 0x038C; + 0x03A5; 0x038E; 0x03A9; 0x038F; 0x03B1; 0x03AC; 0x03B5; 0x03AD; + 0x03B7; 0x03AE; 0x03B9; 0x03AF; 0x03BF; 0x03CC; 0x03C5; 0x03CD; + 0x03C9; 0x03CE; 0x03CA; 0x0390; 0x03CB; 0x03B0; 0x03D2; 0x03D3; + 0x0413; 0x0403; 0x041A; 0x040C; 0x0433; 0x0453; 0x043A; 0x045C; + 0x1F00; 0x1F04; 0x1F01; 0x1F05; 0x1F08; 0x1F0C; 0x1F09; 0x1F0D; + 0x1F10; 0x1F14; 0x1F11; 0x1F15; 0x1F18; 0x1F1C; 0x1F19; 0x1F1D; + 0x1F20; 0x1F24; 0x1F21; 0x1F25; 0x1F28; 0x1F2C; 0x1F29; 0x1F2D; + 0x1F30; 0x1F34; 0x1F31; 0x1F35; 0x1F38; 0x1F3C; 0x1F39; 0x1F3D; + 0x1F40; 0x1F44; 0x1F41; 0x1F45; 0x1F48; 0x1F4C; 0x1F49; 0x1F4D; + 0x1F50; 0x1F54; 0x1F51; 0x1F55; 0x1F59; 0x1F5D; 0x1F60; 0x1F64; + 0x1F61; 0x1F65; 0x1F68; 0x1F6C; 0x1F69; 0x1F6D; 0x1FBF; 0x1FCE; + 0x1FFE; 0x1FDE; 0x0041; 0x00C2; 0x0043; 0x0108; 0x0045; 0x00CA; + 0x0047; 0x011C; 0x0048; 0x0124; 0x0049; 0x00CE; 0x004A; 0x0134; + 0x004F; 0x00D4; 0x0053; 0x015C; 0x0055; 0x00DB; 0x0057; 0x0174; + 0x0059; 0x0176; 0x005A; 0x1E90; 0x0061; 0x00E2; 0x0063; 0x0109; + 0x0065; 0x00EA; 0x0067; 0x011D; 0x0068; 0x0125; 0x0069; 0x00EE; + 0x006A; 0x0135; 0x006F; 0x00F4; 0x0073; 0x015D; 0x0075; 0x00FB; + 0x0077; 0x0175; 0x0079; 0x0177; 0x007A; 0x1E91; 0x1EA0; 0x1EAC; + 0x1EA1; 0x1EAD; 0x1EB8; 0x1EC6; 0x1EB9; 0x1EC7; 0x1ECC; 0x1ED8; + 0x1ECD; 0x1ED9; 0x0041; 0x00C3; 0x0045; 0x1EBC; 0x0049; 0x0128; + 0x004E; 0x00D1; 0x004F; 0x00D5; 0x0055; 0x0168; 0x0056; 0x1E7C; + 0x0059; 0x1EF8; 0x0061; 0x00E3; 0x0065; 0x1EBD; 0x0069; 0x0129; + 0x006E; 0x00F1; 0x006F; 0x00F5; 0x0075; 0x0169; 0x0076; 0x1E7D; + 0x0079; 0x1EF9; 0x00C2; 0x1EAA; 0x00CA; 0x1EC4; 0x00D4; 0x1ED6; + 0x00E2; 0x1EAB; 0x00EA; 0x1EC5; 0x00F4; 0x1ED7; 0x0102; 0x1EB4; + 0x0103; 0x1EB5; 0x01A0; 0x1EE0; 0x01A1; 0x1EE1; 0x01AF; 0x1EEE; + 0x01B0; 0x1EEF; 0x0041; 0x0100; 0x0045; 0x0112; 0x0047; 0x1E20; + 0x0049; 0x012A; 0x004F; 0x014C; 0x0055; 0x016A; 0x0059; 0x0232; + 0x0061; 0x0101; 0x0065; 0x0113; 0x0067; 0x1E21; 0x0069; 0x012B; + 0x006F; 0x014D; 0x0075; 0x016B; 0x0079; 0x0233; 0x00C4; 0x01DE; + 0x00C6; 0x01E2; 0x00D5; 0x022C; 0x00D6; 0x022A; 0x00DC; 0x01D5; + 0x00E4; 0x01DF; 0x00E6; 0x01E3; 0x00F5; 0x022D; 0x00F6; 0x022B; + 0x00FC; 0x01D6; 0x01EA; 0x01EC; 0x01EB; 0x01ED; 0x0226; 0x01E0; + 0x0227; 0x01E1; 0x022E; 0x0230; 0x022F; 0x0231; 0x0391; 0x1FB9; + 0x0399; 0x1FD9; 0x03A5; 0x1FE9; 0x03B1; 0x1FB1; 0x03B9; 0x1FD1; + 0x03C5; 0x1FE1; 0x0418; 0x04E2; 0x0423; 0x04EE; 0x0438; 0x04E3; + 0x0443; 0x04EF; 0x1E36; 0x1E38; 0x1E37; 0x1E39; 0x1E5A; 0x1E5C; + 0x1E5B; 0x1E5D; 0x0041; 0x0102; 0x0045; 0x0114; 0x0047; 0x011E; + 0x0049; 0x012C; 0x004F; 0x014E; 0x0055; 0x016C; 0x0061; 0x0103; + 0x0065; 0x0115; 0x0067; 0x011F; 0x0069; 0x012D; 0x006F; 0x014F; + 0x0075; 0x016D; 0x0228; 0x1E1C; 0x0229; 0x1E1D; 0x0391; 0x1FB8; + 0x0399; 0x1FD8; 0x03A5; 0x1FE8; 0x03B1; 0x1FB0; 0x03B9; 0x1FD0; + 0x03C5; 0x1FE0; 0x0410; 0x04D0; 0x0415; 0x04D6; 0x0416; 0x04C1; + 0x0418; 0x0419; 0x0423; 0x040E; 0x0430; 0x04D1; 0x0435; 0x04D7; + 0x0436; 0x04C2; 0x0438; 0x0439; 0x0443; 0x045E; 0x1EA0; 0x1EB6; + 0x1EA1; 0x1EB7; 0x0041; 0x0226; 0x0042; 0x1E02; 0x0043; 0x010A; + 0x0044; 0x1E0A; 0x0045; 0x0116; 0x0046; 0x1E1E; 0x0047; 0x0120; + 0x0048; 0x1E22; 0x0049; 0x0130; 0x004D; 0x1E40; 0x004E; 0x1E44; + 0x004F; 0x022E; 0x0050; 0x1E56; 0x0052; 0x1E58; 0x0053; 0x1E60; + 0x0054; 0x1E6A; 0x0057; 0x1E86; 0x0058; 0x1E8A; 0x0059; 0x1E8E; + 0x005A; 0x017B; 0x0061; 0x0227; 0x0062; 0x1E03; 0x0063; 0x010B; + 0x0064; 0x1E0B; 0x0065; 0x0117; 0x0066; 0x1E1F; 0x0067; 0x0121; + 0x0068; 0x1E23; 0x006D; 0x1E41; 0x006E; 0x1E45; 0x006F; 0x022F; + 0x0070; 0x1E57; 0x0072; 0x1E59; 0x0073; 0x1E61; 0x0074; 0x1E6B; + 0x0077; 0x1E87; 0x0078; 0x1E8B; 0x0079; 0x1E8F; 0x007A; 0x017C; + 0x015A; 0x1E64; 0x015B; 0x1E65; 0x0160; 0x1E66; 0x0161; 0x1E67; + 0x017F; 0x1E9B; 0x1E62; 0x1E68; 0x1E63; 0x1E69; 0x0041; 0x00C4; + 0x0045; 0x00CB; 0x0048; 0x1E26; 0x0049; 0x00CF; 0x004F; 0x00D6; + 0x0055; 0x00DC; 0x0057; 0x1E84; 0x0058; 0x1E8C; 0x0059; 0x0178; + 0x0061; 0x00E4; 0x0065; 0x00EB; 0x0068; 0x1E27; 0x0069; 0x00EF; + 0x006F; 0x00F6; 0x0074; 0x1E97; 0x0075; 0x00FC; 0x0077; 0x1E85; + 0x0078; 0x1E8D; 0x0079; 0x00FF; 0x00D5; 0x1E4E; 0x00F5; 0x1E4F; + 0x016A; 0x1E7A; 0x016B; 0x1E7B; 0x0399; 0x03AA; 0x03A5; 0x03AB; + 0x03B9; 0x03CA; 0x03C5; 0x03CB; 0x03D2; 0x03D4; 0x0406; 0x0407; + 0x0410; 0x04D2; 0x0415; 0x0401; 0x0416; 0x04DC; 0x0417; 0x04DE; + 0x0418; 0x04E4; 0x041E; 0x04E6; 0x0423; 0x04F0; 0x0427; 0x04F4; + 0x042B; 0x04F8; 0x042D; 0x04EC; 0x0430; 0x04D3; 0x0435; 0x0451; + 0x0436; 0x04DD; 0x0437; 0x04DF; 0x0438; 0x04E5; 0x043E; 0x04E7; + 0x0443; 0x04F1; 0x0447; 0x04F5; 0x044B; 0x04F9; 0x044D; 0x04ED; + 0x0456; 0x0457; 0x04D8; 0x04DA; 0x04D9; 0x04DB; 0x04E8; 0x04EA; + 0x04E9; 0x04EB; 0x0041; 0x1EA2; 0x0045; 0x1EBA; 0x0049; 0x1EC8; + 0x004F; 0x1ECE; 0x0055; 0x1EE6; 0x0059; 0x1EF6; 0x0061; 0x1EA3; + 0x0065; 0x1EBB; 0x0069; 0x1EC9; 0x006F; 0x1ECF; 0x0075; 0x1EE7; + 0x0079; 0x1EF7; 0x00C2; 0x1EA8; 0x00CA; 0x1EC2; 0x00D4; 0x1ED4; + 0x00E2; 0x1EA9; 0x00EA; 0x1EC3; 0x00F4; 0x1ED5; 0x0102; 0x1EB2; + 0x0103; 0x1EB3; 0x01A0; 0x1EDE; 0x01A1; 0x1EDF; 0x01AF; 0x1EEC; + 0x01B0; 0x1EED; 0x0041; 0x00C5; 0x0055; 0x016E; 0x0061; 0x00E5; + 0x0075; 0x016F; 0x0077; 0x1E98; 0x0079; 0x1E99; 0x004F; 0x0150; + 0x0055; 0x0170; 0x006F; 0x0151; 0x0075; 0x0171; 0x0423; 0x04F2; + 0x0443; 0x04F3; 0x0041; 0x01CD; 0x0043; 0x010C; 0x0044; 0x010E; + 0x0045; 0x011A; 0x0047; 0x01E6; 0x0048; 0x021E; 0x0049; 0x01CF; + 0x004B; 0x01E8; 0x004C; 0x013D; 0x004E; 0x0147; 0x004F; 0x01D1; + 0x0052; 0x0158; 0x0053; 0x0160; 0x0054; 0x0164; 0x0055; 0x01D3; + 0x005A; 0x017D; 0x0061; 0x01CE; 0x0063; 0x010D; 0x0064; 0x010F; + 0x0065; 0x011B; 0x0067; 0x01E7; 0x0068; 0x021F; 0x0069; 0x01D0; + 0x006A; 0x01F0; 0x006B; 0x01E9; 0x006C; 0x013E; 0x006E; 0x0148; + 0x006F; 0x01D2; 0x0072; 0x0159; 0x0073; 0x0161; 0x0074; 0x0165; + 0x0075; 0x01D4; 0x007A; 0x017E; 0x00DC; 0x01D9; 0x00FC; 0x01DA; + 0x01B7; 0x01EE; 0x0292; 0x01EF; 0x0041; 0x0200; 0x0045; 0x0204; + 0x0049; 0x0208; 0x004F; 0x020C; 0x0052; 0x0210; 0x0055; 0x0214; + 0x0061; 0x0201; 0x0065; 0x0205; 0x0069; 0x0209; 0x006F; 0x020D; + 0x0072; 0x0211; 0x0075; 0x0215; 0x0474; 0x0476; 0x0475; 0x0477; + 0x0041; 0x0202; 0x0045; 0x0206; 0x0049; 0x020A; 0x004F; 0x020E; + 0x0052; 0x0212; 0x0055; 0x0216; 0x0061; 0x0203; 0x0065; 0x0207; + 0x0069; 0x020B; 0x006F; 0x020F; 0x0072; 0x0213; 0x0075; 0x0217; + 0x0391; 0x1F08; 0x0395; 0x1F18; 0x0397; 0x1F28; 0x0399; 0x1F38; + 0x039F; 0x1F48; 0x03A9; 0x1F68; 0x03B1; 0x1F00; 0x03B5; 0x1F10; + 0x03B7; 0x1F20; 0x03B9; 0x1F30; 0x03BF; 0x1F40; 0x03C1; 0x1FE4; + 0x03C5; 0x1F50; 0x03C9; 0x1F60; 0x0391; 0x1F09; 0x0395; 0x1F19; + 0x0397; 0x1F29; 0x0399; 0x1F39; 0x039F; 0x1F49; 0x03A1; 0x1FEC; + 0x03A5; 0x1F59; 0x03A9; 0x1F69; 0x03B1; 0x1F01; 0x03B5; 0x1F11; + 0x03B7; 0x1F21; 0x03B9; 0x1F31; 0x03BF; 0x1F41; 0x03C1; 0x1FE5; + 0x03C5; 0x1F51; 0x03C9; 0x1F61; 0x004F; 0x01A0; 0x0055; 0x01AF; + 0x006F; 0x01A1; 0x0075; 0x01B0; 0x0041; 0x1EA0; 0x0042; 0x1E04; + 0x0044; 0x1E0C; 0x0045; 0x1EB8; 0x0048; 0x1E24; 0x0049; 0x1ECA; + 0x004B; 0x1E32; 0x004C; 0x1E36; 0x004D; 0x1E42; 0x004E; 0x1E46; + 0x004F; 0x1ECC; 0x0052; 0x1E5A; 0x0053; 0x1E62; 0x0054; 0x1E6C; + 0x0055; 0x1EE4; 0x0056; 0x1E7E; 0x0057; 0x1E88; 0x0059; 0x1EF4; + 0x005A; 0x1E92; 0x0061; 0x1EA1; 0x0062; 0x1E05; 0x0064; 0x1E0D; + 0x0065; 0x1EB9; 0x0068; 0x1E25; 0x0069; 0x1ECB; 0x006B; 0x1E33; + 0x006C; 0x1E37; 0x006D; 0x1E43; 0x006E; 0x1E47; 0x006F; 0x1ECD; + 0x0072; 0x1E5B; 0x0073; 0x1E63; 0x0074; 0x1E6D; 0x0075; 0x1EE5; + 0x0076; 0x1E7F; 0x0077; 0x1E89; 0x0079; 0x1EF5; 0x007A; 0x1E93; + 0x01A0; 0x1EE2; 0x01A1; 0x1EE3; 0x01AF; 0x1EF0; 0x01B0; 0x1EF1; + 0x0055; 0x1E72; 0x0075; 0x1E73; 0x0041; 0x1E00; 0x0061; 0x1E01; + 0x0053; 0x0218; 0x0054; 0x021A; 0x0073; 0x0219; 0x0074; 0x021B; + 0x0043; 0x00C7; 0x0044; 0x1E10; 0x0045; 0x0228; 0x0047; 0x0122; + 0x0048; 0x1E28; 0x004B; 0x0136; 0x004C; 0x013B; 0x004E; 0x0145; + 0x0052; 0x0156; 0x0053; 0x015E; 0x0054; 0x0162; 0x0063; 0x00E7; + 0x0064; 0x1E11; 0x0065; 0x0229; 0x0067; 0x0123; 0x0068; 0x1E29; + 0x006B; 0x0137; 0x006C; 0x013C; 0x006E; 0x0146; 0x0072; 0x0157; + 0x0073; 0x015F; 0x0074; 0x0163; 0x0041; 0x0104; 0x0045; 0x0118; + 0x0049; 0x012E; 0x004F; 0x01EA; 0x0055; 0x0172; 0x0061; 0x0105; + 0x0065; 0x0119; 0x0069; 0x012F; 0x006F; 0x01EB; 0x0075; 0x0173; + 0x0044; 0x1E12; 0x0045; 0x1E18; 0x004C; 0x1E3C; 0x004E; 0x1E4A; + 0x0054; 0x1E70; 0x0055; 0x1E76; 0x0064; 0x1E13; 0x0065; 0x1E19; + 0x006C; 0x1E3D; 0x006E; 0x1E4B; 0x0074; 0x1E71; 0x0075; 0x1E77; + 0x0048; 0x1E2A; 0x0068; 0x1E2B; 0x0045; 0x1E1A; 0x0049; 0x1E2C; + 0x0055; 0x1E74; 0x0065; 0x1E1B; 0x0069; 0x1E2D; 0x0075; 0x1E75; + 0x0042; 0x1E06; 0x0044; 0x1E0E; 0x004B; 0x1E34; 0x004C; 0x1E3A; + 0x004E; 0x1E48; 0x0052; 0x1E5E; 0x0054; 0x1E6E; 0x005A; 0x1E94; + 0x0062; 0x1E07; 0x0064; 0x1E0F; 0x0068; 0x1E96; 0x006B; 0x1E35; + 0x006C; 0x1E3B; 0x006E; 0x1E49; 0x0072; 0x1E5F; 0x0074; 0x1E6F; + 0x007A; 0x1E95; 0x003C; 0x226E; 0x003D; 0x2260; 0x003E; 0x226F; + 0x2190; 0x219A; 0x2192; 0x219B; 0x2194; 0x21AE; 0x21D0; 0x21CD; + 0x21D2; 0x21CF; 0x21D4; 0x21CE; 0x2203; 0x2204; 0x2208; 0x2209; + 0x220B; 0x220C; 0x2223; 0x2224; 0x2225; 0x2226; 0x223C; 0x2241; + 0x2243; 0x2244; 0x2245; 0x2247; 0x2248; 0x2249; 0x224D; 0x226D; + 0x2261; 0x2262; 0x2264; 0x2270; 0x2265; 0x2271; 0x2272; 0x2274; + 0x2273; 0x2275; 0x2276; 0x2278; 0x2277; 0x2279; 0x227A; 0x2280; + 0x227B; 0x2281; 0x227C; 0x22E0; 0x227D; 0x22E1; 0x2282; 0x2284; + 0x2283; 0x2285; 0x2286; 0x2288; 0x2287; 0x2289; 0x2291; 0x22E2; + 0x2292; 0x22E3; 0x22A2; 0x22AC; 0x22A8; 0x22AD; 0x22A9; 0x22AE; + 0x22AB; 0x22AF; 0x22B2; 0x22EA; 0x22B3; 0x22EB; 0x22B4; 0x22EC; + 0x22B5; 0x22ED; 0x00A8; 0x1FC1; 0x03B1; 0x1FB6; 0x03B7; 0x1FC6; + 0x03B9; 0x1FD6; 0x03C5; 0x1FE6; 0x03C9; 0x1FF6; 0x03CA; 0x1FD7; + 0x03CB; 0x1FE7; 0x1F00; 0x1F06; 0x1F01; 0x1F07; 0x1F08; 0x1F0E; + 0x1F09; 0x1F0F; 0x1F20; 0x1F26; 0x1F21; 0x1F27; 0x1F28; 0x1F2E; + 0x1F29; 0x1F2F; 0x1F30; 0x1F36; 0x1F31; 0x1F37; 0x1F38; 0x1F3E; + 0x1F39; 0x1F3F; 0x1F50; 0x1F56; 0x1F51; 0x1F57; 0x1F59; 0x1F5F; + 0x1F60; 0x1F66; 0x1F61; 0x1F67; 0x1F68; 0x1F6E; 0x1F69; 0x1F6F; + 0x1FBF; 0x1FCF; 0x1FFE; 0x1FDF; 0x0391; 0x1FBC; 0x0397; 0x1FCC; + 0x03A9; 0x1FFC; 0x03AC; 0x1FB4; 0x03AE; 0x1FC4; 0x03B1; 0x1FB3; + 0x03B7; 0x1FC3; 0x03C9; 0x1FF3; 0x03CE; 0x1FF4; 0x1F00; 0x1F80; + 0x1F01; 0x1F81; 0x1F02; 0x1F82; 0x1F03; 0x1F83; 0x1F04; 0x1F84; + 0x1F05; 0x1F85; 0x1F06; 0x1F86; 0x1F07; 0x1F87; 0x1F08; 0x1F88; + 0x1F09; 0x1F89; 0x1F0A; 0x1F8A; 0x1F0B; 0x1F8B; 0x1F0C; 0x1F8C; + 0x1F0D; 0x1F8D; 0x1F0E; 0x1F8E; 0x1F0F; 0x1F8F; 0x1F20; 0x1F90; + 0x1F21; 0x1F91; 0x1F22; 0x1F92; 0x1F23; 0x1F93; 0x1F24; 0x1F94; + 0x1F25; 0x1F95; 0x1F26; 0x1F96; 0x1F27; 0x1F97; 0x1F28; 0x1F98; + 0x1F29; 0x1F99; 0x1F2A; 0x1F9A; 0x1F2B; 0x1F9B; 0x1F2C; 0x1F9C; + 0x1F2D; 0x1F9D; 0x1F2E; 0x1F9E; 0x1F2F; 0x1F9F; 0x1F60; 0x1FA0; + 0x1F61; 0x1FA1; 0x1F62; 0x1FA2; 0x1F63; 0x1FA3; 0x1F64; 0x1FA4; + 0x1F65; 0x1FA5; 0x1F66; 0x1FA6; 0x1F67; 0x1FA7; 0x1F68; 0x1FA8; + 0x1F69; 0x1FA9; 0x1F6A; 0x1FAA; 0x1F6B; 0x1FAB; 0x1F6C; 0x1FAC; + 0x1F6D; 0x1FAD; 0x1F6E; 0x1FAE; 0x1F6F; 0x1FAF; 0x1F70; 0x1FB2; + 0x1F74; 0x1FC2; 0x1F7C; 0x1FF2; 0x1FB6; 0x1FB7; 0x1FC6; 0x1FC7; + 0x1FF6; 0x1FF7; 0x0627; 0x0622; 0x0627; 0x0623; 0x0648; 0x0624; + 0x064A; 0x0626; 0x06C1; 0x06C2; 0x06D2; 0x06D3; 0x06D5; 0x06C0; + 0x0627; 0x0625; 0x0928; 0x0929; 0x0930; 0x0931; 0x0933; 0x0934; + 0x09C7; 0x09CB; 0x09C7; 0x09CC; 0x0B47; 0x0B4B; 0x0B47; 0x0B48; + 0x0B47; 0x0B4C; 0x0BC6; 0x0BCA; 0x0BC7; 0x0BCB; 0x0B92; 0x0B94; + 0x0BC6; 0x0BCC; 0x0C46; 0x0C48; 0x0CC6; 0x0CCA; 0x0CBF; 0x0CC0; + 0x0CC6; 0x0CC7; 0x0CCA; 0x0CCB; 0x0CC6; 0x0CC8; 0x0D46; 0x0D4A; + 0x0D47; 0x0D4B; 0x0D46; 0x0D4C; 0x0DD9; 0x0DDA; 0x0DDC; 0x0DDD; + 0x0DD9; 0x0DDC; 0x0DD9; 0x0DDE; 0x1025; 0x1026; 0x3046; 0x3094; + 0x304B; 0x304C; 0x304D; 0x304E; 0x304F; 0x3050; 0x3051; 0x3052; + 0x3053; 0x3054; 0x3055; 0x3056; 0x3057; 0x3058; 0x3059; 0x305A; + 0x305B; 0x305C; 0x305D; 0x305E; 0x305F; 0x3060; 0x3061; 0x3062; + 0x3064; 0x3065; 0x3066; 0x3067; 0x3068; 0x3069; 0x306F; 0x3070; + 0x3072; 0x3073; 0x3075; 0x3076; 0x3078; 0x3079; 0x307B; 0x307C; + 0x309D; 0x309E; 0x30A6; 0x30F4; 0x30AB; 0x30AC; 0x30AD; 0x30AE; + 0x30AF; 0x30B0; 0x30B1; 0x30B2; 0x30B3; 0x30B4; 0x30B5; 0x30B6; + 0x30B7; 0x30B8; 0x30B9; 0x30BA; 0x30BB; 0x30BC; 0x30BD; 0x30BE; + 0x30BF; 0x30C0; 0x30C1; 0x30C2; 0x30C4; 0x30C5; 0x30C6; 0x30C7; + 0x30C8; 0x30C9; 0x30CF; 0x30D0; 0x30D2; 0x30D3; 0x30D5; 0x30D6; + 0x30D8; 0x30D9; 0x30DB; 0x30DC; 0x30EF; 0x30F7; 0x30F0; 0x30F8; + 0x30F1; 0x30F9; 0x30F2; 0x30FA; 0x30FD; 0x30FE; 0x306F; 0x3071; + 0x3072; 0x3074; 0x3075; 0x3077; 0x3078; 0x307A; 0x307B; 0x307D; + 0x30CF; 0x30D1; 0x30D2; 0x30D4; 0x30D5; 0x30D7; 0x30D8; 0x30DA; + 0x30DB; 0x30DD +|] + +let uniCharCombiningBitmap = [| + 0x00; 0x00; 0x00; 0x01; 0x02; 0x03; 0x04; 0x05; + 0x00; 0x06; 0x07; 0x08; 0x09; 0x0A; 0x0B; 0x0C; + 0x0D; 0x14; 0x00; 0x00; 0x00; 0x00; 0x00; 0x0E; + 0x0F; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x10; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x11; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x12; 0x00; 0x00; 0x13; 0x00; + + 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; 0xFF; + 0xFF; 0xFF; 0x00; 0x00; 0xFF; 0xFF; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x78; 0x03; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0xFE; 0xFF; 0xFB; 0xFF; 0xFF; 0xBB; + 0x16; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0xF8; 0x3F; 0x00; 0x00; 0x00; 0x01; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0xC0; 0xFF; 0x9F; 0x3D; 0x00; 0x00; + 0x00; 0x00; 0x02; 0x00; 0x00; 0x00; 0xFF; 0xFF; + 0xFF; 0x07; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0xC0; 0xFF; 0x01; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x0E; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0xD0; + 0xFF; 0x3F; 0x1E; 0x00; 0x0C; 0x00; 0x00; 0x00; + 0x0E; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0xD0; + 0x9F; 0x39; 0x80; 0x00; 0x0C; 0x00; 0x00; 0x00; + 0x04; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0xD0; + 0x87; 0x39; 0x00; 0x00; 0x00; 0x00; 0x03; 0x00; + 0x0E; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0xD0; + 0xBF; 0x3B; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x0E; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0xD0; + 0x8F; 0x39; 0xC0; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x04; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0xC0; + 0xC7; 0x3D; 0x80; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x0E; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0xC0; + 0xDF; 0x3D; 0x60; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x0C; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0xC0; + 0xDF; 0x3D; 0x60; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x0C; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0xC0; + 0xCF; 0x3D; 0x80; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x0C; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x84; 0x5F; 0xFF; 0x00; 0x00; 0x0C; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0xF2; 0x07; + 0x80; 0x7F; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0xF2; 0x1B; + 0x00; 0x3F; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x03; 0x00; 0x00; 0xA0; 0xC2; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0xFE; 0xFF; + 0xDF; 0x00; 0xFF; 0xFE; 0xFF; 0xFF; 0xFF; 0x1F; + 0x40; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0xF0; 0xC7; 0x03; + 0x00; 0x00; 0xC0; 0x03; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x1C; 0x00; 0x00; 0x00; 0x1C; 0x00; + 0x00; 0x00; 0x0C; 0x00; 0x00; 0x00; 0x0C; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0xF0; 0xFF; + 0xFF; 0xFF; 0x0F; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x38; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x02; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0xFF; 0xFF; 0xFF; 0x07; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0xFC; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x06; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x40; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0xFF; 0xFF; 0x00; 0x00; 0x0F; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; + 0x00; 0x00; 0x00; 0x00; 0xFE; 0xFF; 0x3F; 0x00; + 0x00; 0x00; 0x00; 0x00; 0x00; 0xFF; 0xFF; 0xFF; + 0x07; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00; 0x00 +|] + +(**** From FastUnicodeCompare.c; + I checked they are equivalent to the tables in UCStringCompareData.h *) + +let lowerCaseTable = [| + + (* High-byte indices ( == 0 iff no case mapping and no ignorables ) *) + + + (* 0 *) 0x0100; 0x0200; 0x0000; 0x0300; 0x0400; 0x0500; 0x0000; 0x0000; + 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + (* 1 *) 0x0600; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + (* 2 *) 0x0700; 0x0800; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + (* 3 *) 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + (* 4 *) 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + (* 5 *) 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + (* 6 *) 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + (* 7 *) 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + (* 8 *) 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + (* 9 *) 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + (* A *) 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + (* B *) 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + (* C *) 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + (* D *) 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + (* E *) 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + (* F *) 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0900; 0x0A00; + + (* Table 1 (for high byte 0x00) *) + + (* 0 *) 0xFFFF; 0x0001; 0x0002; 0x0003; 0x0004; 0x0005; 0x0006; 0x0007; + 0x0008; 0x0009; 0x000A; 0x000B; 0x000C; 0x000D; 0x000E; 0x000F; + (* 1 *) 0x0010; 0x0011; 0x0012; 0x0013; 0x0014; 0x0015; 0x0016; 0x0017; + 0x0018; 0x0019; 0x001A; 0x001B; 0x001C; 0x001D; 0x001E; 0x001F; + (* 2 *) 0x0020; 0x0021; 0x0022; 0x0023; 0x0024; 0x0025; 0x0026; 0x0027; + 0x0028; 0x0029; 0x002A; 0x002B; 0x002C; 0x002D; 0x002E; 0x002F; + (* 3 *) 0x0030; 0x0031; 0x0032; 0x0033; 0x0034; 0x0035; 0x0036; 0x0037; + 0x0038; 0x0039; 0x003A; 0x003B; 0x003C; 0x003D; 0x003E; 0x003F; + (* 4 *) 0x0040; 0x0061; 0x0062; 0x0063; 0x0064; 0x0065; 0x0066; 0x0067; + 0x0068; 0x0069; 0x006A; 0x006B; 0x006C; 0x006D; 0x006E; 0x006F; + (* 5 *) 0x0070; 0x0071; 0x0072; 0x0073; 0x0074; 0x0075; 0x0076; 0x0077; + 0x0078; 0x0079; 0x007A; 0x005B; 0x005C; 0x005D; 0x005E; 0x005F; + (* 6 *) 0x0060; 0x0061; 0x0062; 0x0063; 0x0064; 0x0065; 0x0066; 0x0067; + 0x0068; 0x0069; 0x006A; 0x006B; 0x006C; 0x006D; 0x006E; 0x006F; + (* 7 *) 0x0070; 0x0071; 0x0072; 0x0073; 0x0074; 0x0075; 0x0076; 0x0077; + 0x0078; 0x0079; 0x007A; 0x007B; 0x007C; 0x007D; 0x007E; 0x007F; + (* 8 *) 0x0080; 0x0081; 0x0082; 0x0083; 0x0084; 0x0085; 0x0086; 0x0087; + 0x0088; 0x0089; 0x008A; 0x008B; 0x008C; 0x008D; 0x008E; 0x008F; + (* 9 *) 0x0090; 0x0091; 0x0092; 0x0093; 0x0094; 0x0095; 0x0096; 0x0097; + 0x0098; 0x0099; 0x009A; 0x009B; 0x009C; 0x009D; 0x009E; 0x009F; + (* A *) 0x00A0; 0x00A1; 0x00A2; 0x00A3; 0x00A4; 0x00A5; 0x00A6; 0x00A7; + 0x00A8; 0x00A9; 0x00AA; 0x00AB; 0x00AC; 0x00AD; 0x00AE; 0x00AF; + (* B *) 0x00B0; 0x00B1; 0x00B2; 0x00B3; 0x00B4; 0x00B5; 0x00B6; 0x00B7; + 0x00B8; 0x00B9; 0x00BA; 0x00BB; 0x00BC; 0x00BD; 0x00BE; 0x00BF; + (* C *) 0x00C0; 0x00C1; 0x00C2; 0x00C3; 0x00C4; 0x00C5; 0x00E6; 0x00C7; + 0x00C8; 0x00C9; 0x00CA; 0x00CB; 0x00CC; 0x00CD; 0x00CE; 0x00CF; + (* D *) 0x00F0; 0x00D1; 0x00D2; 0x00D3; 0x00D4; 0x00D5; 0x00D6; 0x00D7; + 0x00F8; 0x00D9; 0x00DA; 0x00DB; 0x00DC; 0x00DD; 0x00FE; 0x00DF; + (* E *) 0x00E0; 0x00E1; 0x00E2; 0x00E3; 0x00E4; 0x00E5; 0x00E6; 0x00E7; + 0x00E8; 0x00E9; 0x00EA; 0x00EB; 0x00EC; 0x00ED; 0x00EE; 0x00EF; + (* F *) 0x00F0; 0x00F1; 0x00F2; 0x00F3; 0x00F4; 0x00F5; 0x00F6; 0x00F7; + 0x00F8; 0x00F9; 0x00FA; 0x00FB; 0x00FC; 0x00FD; 0x00FE; 0x00FF; + + (* Table 2 (for high byte 0x01) *) + + (* 0 *) 0x0100; 0x0101; 0x0102; 0x0103; 0x0104; 0x0105; 0x0106; 0x0107; + 0x0108; 0x0109; 0x010A; 0x010B; 0x010C; 0x010D; 0x010E; 0x010F; + (* 1 *) 0x0111; 0x0111; 0x0112; 0x0113; 0x0114; 0x0115; 0x0116; 0x0117; + 0x0118; 0x0119; 0x011A; 0x011B; 0x011C; 0x011D; 0x011E; 0x011F; + (* 2 *) 0x0120; 0x0121; 0x0122; 0x0123; 0x0124; 0x0125; 0x0127; 0x0127; + 0x0128; 0x0129; 0x012A; 0x012B; 0x012C; 0x012D; 0x012E; 0x012F; + (* 3 *) 0x0130; 0x0131; 0x0133; 0x0133; 0x0134; 0x0135; 0x0136; 0x0137; + 0x0138; 0x0139; 0x013A; 0x013B; 0x013C; 0x013D; 0x013E; 0x0140; + (* 4 *) 0x0140; 0x0142; 0x0142; 0x0143; 0x0144; 0x0145; 0x0146; 0x0147; + 0x0148; 0x0149; 0x014B; 0x014B; 0x014C; 0x014D; 0x014E; 0x014F; + (* 5 *) 0x0150; 0x0151; 0x0153; 0x0153; 0x0154; 0x0155; 0x0156; 0x0157; + 0x0158; 0x0159; 0x015A; 0x015B; 0x015C; 0x015D; 0x015E; 0x015F; + (* 6 *) 0x0160; 0x0161; 0x0162; 0x0163; 0x0164; 0x0165; 0x0167; 0x0167; + 0x0168; 0x0169; 0x016A; 0x016B; 0x016C; 0x016D; 0x016E; 0x016F; + (* 7 *) 0x0170; 0x0171; 0x0172; 0x0173; 0x0174; 0x0175; 0x0176; 0x0177; + 0x0178; 0x0179; 0x017A; 0x017B; 0x017C; 0x017D; 0x017E; 0x017F; + (* 8 *) 0x0180; 0x0253; 0x0183; 0x0183; 0x0185; 0x0185; 0x0254; 0x0188; + 0x0188; 0x0256; 0x0257; 0x018C; 0x018C; 0x018D; 0x01DD; 0x0259; + (* 9 *) 0x025B; 0x0192; 0x0192; 0x0260; 0x0263; 0x0195; 0x0269; 0x0268; + 0x0199; 0x0199; 0x019A; 0x019B; 0x026F; 0x0272; 0x019E; 0x0275; + (* A *) 0x01A0; 0x01A1; 0x01A3; 0x01A3; 0x01A5; 0x01A5; 0x01A6; 0x01A8; + 0x01A8; 0x0283; 0x01AA; 0x01AB; 0x01AD; 0x01AD; 0x0288; 0x01AF; + (* B *) 0x01B0; 0x028A; 0x028B; 0x01B4; 0x01B4; 0x01B6; 0x01B6; 0x0292; + 0x01B9; 0x01B9; 0x01BA; 0x01BB; 0x01BD; 0x01BD; 0x01BE; 0x01BF; + (* C *) 0x01C0; 0x01C1; 0x01C2; 0x01C3; 0x01C6; 0x01C6; 0x01C6; 0x01C9; + 0x01C9; 0x01C9; 0x01CC; 0x01CC; 0x01CC; 0x01CD; 0x01CE; 0x01CF; + (* D *) 0x01D0; 0x01D1; 0x01D2; 0x01D3; 0x01D4; 0x01D5; 0x01D6; 0x01D7; + 0x01D8; 0x01D9; 0x01DA; 0x01DB; 0x01DC; 0x01DD; 0x01DE; 0x01DF; + (* E *) 0x01E0; 0x01E1; 0x01E2; 0x01E3; 0x01E5; 0x01E5; 0x01E6; 0x01E7; + 0x01E8; 0x01E9; 0x01EA; 0x01EB; 0x01EC; 0x01ED; 0x01EE; 0x01EF; + (* F *) 0x01F0; 0x01F3; 0x01F3; 0x01F3; 0x01F4; 0x01F5; 0x01F6; 0x01F7; + 0x01F8; 0x01F9; 0x01FA; 0x01FB; 0x01FC; 0x01FD; 0x01FE; 0x01FF; + + (* Table 3 (for high byte 0x03) *) + + (* 0 *) 0x0300; 0x0301; 0x0302; 0x0303; 0x0304; 0x0305; 0x0306; 0x0307; + 0x0308; 0x0309; 0x030A; 0x030B; 0x030C; 0x030D; 0x030E; 0x030F; + (* 1 *) 0x0310; 0x0311; 0x0312; 0x0313; 0x0314; 0x0315; 0x0316; 0x0317; + 0x0318; 0x0319; 0x031A; 0x031B; 0x031C; 0x031D; 0x031E; 0x031F; + (* 2 *) 0x0320; 0x0321; 0x0322; 0x0323; 0x0324; 0x0325; 0x0326; 0x0327; + 0x0328; 0x0329; 0x032A; 0x032B; 0x032C; 0x032D; 0x032E; 0x032F; + (* 3 *) 0x0330; 0x0331; 0x0332; 0x0333; 0x0334; 0x0335; 0x0336; 0x0337; + 0x0338; 0x0339; 0x033A; 0x033B; 0x033C; 0x033D; 0x033E; 0x033F; + (* 4 *) 0x0340; 0x0341; 0x0342; 0x0343; 0x0344; 0x0345; 0x0346; 0x0347; + 0x0348; 0x0349; 0x034A; 0x034B; 0x034C; 0x034D; 0x034E; 0x034F; + (* 5 *) 0x0350; 0x0351; 0x0352; 0x0353; 0x0354; 0x0355; 0x0356; 0x0357; + 0x0358; 0x0359; 0x035A; 0x035B; 0x035C; 0x035D; 0x035E; 0x035F; + (* 6 *) 0x0360; 0x0361; 0x0362; 0x0363; 0x0364; 0x0365; 0x0366; 0x0367; + 0x0368; 0x0369; 0x036A; 0x036B; 0x036C; 0x036D; 0x036E; 0x036F; + (* 7 *) 0x0370; 0x0371; 0x0372; 0x0373; 0x0374; 0x0375; 0x0376; 0x0377; + 0x0378; 0x0379; 0x037A; 0x037B; 0x037C; 0x037D; 0x037E; 0x037F; + (* 8 *) 0x0380; 0x0381; 0x0382; 0x0383; 0x0384; 0x0385; 0x0386; 0x0387; + 0x0388; 0x0389; 0x038A; 0x038B; 0x038C; 0x038D; 0x038E; 0x038F; + (* 9 *) 0x0390; 0x03B1; 0x03B2; 0x03B3; 0x03B4; 0x03B5; 0x03B6; 0x03B7; + 0x03B8; 0x03B9; 0x03BA; 0x03BB; 0x03BC; 0x03BD; 0x03BE; 0x03BF; + (* A *) 0x03C0; 0x03C1; 0x03A2; 0x03C3; 0x03C4; 0x03C5; 0x03C6; 0x03C7; + 0x03C8; 0x03C9; 0x03AA; 0x03AB; 0x03AC; 0x03AD; 0x03AE; 0x03AF; + (* B *) 0x03B0; 0x03B1; 0x03B2; 0x03B3; 0x03B4; 0x03B5; 0x03B6; 0x03B7; + 0x03B8; 0x03B9; 0x03BA; 0x03BB; 0x03BC; 0x03BD; 0x03BE; 0x03BF; + (* C *) 0x03C0; 0x03C1; 0x03C2; 0x03C3; 0x03C4; 0x03C5; 0x03C6; 0x03C7; + 0x03C8; 0x03C9; 0x03CA; 0x03CB; 0x03CC; 0x03CD; 0x03CE; 0x03CF; + (* D *) 0x03D0; 0x03D1; 0x03D2; 0x03D3; 0x03D4; 0x03D5; 0x03D6; 0x03D7; + 0x03D8; 0x03D9; 0x03DA; 0x03DB; 0x03DC; 0x03DD; 0x03DE; 0x03DF; + (* E *) 0x03E0; 0x03E1; 0x03E3; 0x03E3; 0x03E5; 0x03E5; 0x03E7; 0x03E7; + 0x03E9; 0x03E9; 0x03EB; 0x03EB; 0x03ED; 0x03ED; 0x03EF; 0x03EF; + (* F *) 0x03F0; 0x03F1; 0x03F2; 0x03F3; 0x03F4; 0x03F5; 0x03F6; 0x03F7; + 0x03F8; 0x03F9; 0x03FA; 0x03FB; 0x03FC; 0x03FD; 0x03FE; 0x03FF; + + (* Table 4 (for high byte 0x04) *) + + (* 0 *) 0x0400; 0x0401; 0x0452; 0x0403; 0x0454; 0x0455; 0x0456; 0x0407; + 0x0458; 0x0459; 0x045A; 0x045B; 0x040C; 0x040D; 0x040E; 0x045F; + (* 1 *) 0x0430; 0x0431; 0x0432; 0x0433; 0x0434; 0x0435; 0x0436; 0x0437; + 0x0438; 0x0419; 0x043A; 0x043B; 0x043C; 0x043D; 0x043E; 0x043F; + (* 2 *) 0x0440; 0x0441; 0x0442; 0x0443; 0x0444; 0x0445; 0x0446; 0x0447; + 0x0448; 0x0449; 0x044A; 0x044B; 0x044C; 0x044D; 0x044E; 0x044F; + (* 3 *) 0x0430; 0x0431; 0x0432; 0x0433; 0x0434; 0x0435; 0x0436; 0x0437; + 0x0438; 0x0439; 0x043A; 0x043B; 0x043C; 0x043D; 0x043E; 0x043F; + (* 4 *) 0x0440; 0x0441; 0x0442; 0x0443; 0x0444; 0x0445; 0x0446; 0x0447; + 0x0448; 0x0449; 0x044A; 0x044B; 0x044C; 0x044D; 0x044E; 0x044F; + (* 5 *) 0x0450; 0x0451; 0x0452; 0x0453; 0x0454; 0x0455; 0x0456; 0x0457; + 0x0458; 0x0459; 0x045A; 0x045B; 0x045C; 0x045D; 0x045E; 0x045F; + (* 6 *) 0x0461; 0x0461; 0x0463; 0x0463; 0x0465; 0x0465; 0x0467; 0x0467; + 0x0469; 0x0469; 0x046B; 0x046B; 0x046D; 0x046D; 0x046F; 0x046F; + (* 7 *) 0x0471; 0x0471; 0x0473; 0x0473; 0x0475; 0x0475; 0x0476; 0x0477; + 0x0479; 0x0479; 0x047B; 0x047B; 0x047D; 0x047D; 0x047F; 0x047F; + (* 8 *) 0x0481; 0x0481; 0x0482; 0x0483; 0x0484; 0x0485; 0x0486; 0x0487; + 0x0488; 0x0489; 0x048A; 0x048B; 0x048C; 0x048D; 0x048E; 0x048F; + (* 9 *) 0x0491; 0x0491; 0x0493; 0x0493; 0x0495; 0x0495; 0x0497; 0x0497; + 0x0499; 0x0499; 0x049B; 0x049B; 0x049D; 0x049D; 0x049F; 0x049F; + (* A *) 0x04A1; 0x04A1; 0x04A3; 0x04A3; 0x04A5; 0x04A5; 0x04A7; 0x04A7; + 0x04A9; 0x04A9; 0x04AB; 0x04AB; 0x04AD; 0x04AD; 0x04AF; 0x04AF; + (* B *) 0x04B1; 0x04B1; 0x04B3; 0x04B3; 0x04B5; 0x04B5; 0x04B7; 0x04B7; + 0x04B9; 0x04B9; 0x04BB; 0x04BB; 0x04BD; 0x04BD; 0x04BF; 0x04BF; + (* C *) 0x04C0; 0x04C1; 0x04C2; 0x04C4; 0x04C4; 0x04C5; 0x04C6; 0x04C8; + 0x04C8; 0x04C9; 0x04CA; 0x04CC; 0x04CC; 0x04CD; 0x04CE; 0x04CF; + (* D *) 0x04D0; 0x04D1; 0x04D2; 0x04D3; 0x04D4; 0x04D5; 0x04D6; 0x04D7; + 0x04D8; 0x04D9; 0x04DA; 0x04DB; 0x04DC; 0x04DD; 0x04DE; 0x04DF; + (* E *) 0x04E0; 0x04E1; 0x04E2; 0x04E3; 0x04E4; 0x04E5; 0x04E6; 0x04E7; + 0x04E8; 0x04E9; 0x04EA; 0x04EB; 0x04EC; 0x04ED; 0x04EE; 0x04EF; + (* F *) 0x04F0; 0x04F1; 0x04F2; 0x04F3; 0x04F4; 0x04F5; 0x04F6; 0x04F7; + 0x04F8; 0x04F9; 0x04FA; 0x04FB; 0x04FC; 0x04FD; 0x04FE; 0x04FF; + + (* Table 5 (for high byte 0x05) *) + + (* 0 *) 0x0500; 0x0501; 0x0502; 0x0503; 0x0504; 0x0505; 0x0506; 0x0507; + 0x0508; 0x0509; 0x050A; 0x050B; 0x050C; 0x050D; 0x050E; 0x050F; + (* 1 *) 0x0510; 0x0511; 0x0512; 0x0513; 0x0514; 0x0515; 0x0516; 0x0517; + 0x0518; 0x0519; 0x051A; 0x051B; 0x051C; 0x051D; 0x051E; 0x051F; + (* 2 *) 0x0520; 0x0521; 0x0522; 0x0523; 0x0524; 0x0525; 0x0526; 0x0527; + 0x0528; 0x0529; 0x052A; 0x052B; 0x052C; 0x052D; 0x052E; 0x052F; + (* 3 *) 0x0530; 0x0561; 0x0562; 0x0563; 0x0564; 0x0565; 0x0566; 0x0567; + 0x0568; 0x0569; 0x056A; 0x056B; 0x056C; 0x056D; 0x056E; 0x056F; + (* 4 *) 0x0570; 0x0571; 0x0572; 0x0573; 0x0574; 0x0575; 0x0576; 0x0577; + 0x0578; 0x0579; 0x057A; 0x057B; 0x057C; 0x057D; 0x057E; 0x057F; + (* 5 *) 0x0580; 0x0581; 0x0582; 0x0583; 0x0584; 0x0585; 0x0586; 0x0557; + 0x0558; 0x0559; 0x055A; 0x055B; 0x055C; 0x055D; 0x055E; 0x055F; + (* 6 *) 0x0560; 0x0561; 0x0562; 0x0563; 0x0564; 0x0565; 0x0566; 0x0567; + 0x0568; 0x0569; 0x056A; 0x056B; 0x056C; 0x056D; 0x056E; 0x056F; + (* 7 *) 0x0570; 0x0571; 0x0572; 0x0573; 0x0574; 0x0575; 0x0576; 0x0577; + 0x0578; 0x0579; 0x057A; 0x057B; 0x057C; 0x057D; 0x057E; 0x057F; + (* 8 *) 0x0580; 0x0581; 0x0582; 0x0583; 0x0584; 0x0585; 0x0586; 0x0587; + 0x0588; 0x0589; 0x058A; 0x058B; 0x058C; 0x058D; 0x058E; 0x058F; + (* 9 *) 0x0590; 0x0591; 0x0592; 0x0593; 0x0594; 0x0595; 0x0596; 0x0597; + 0x0598; 0x0599; 0x059A; 0x059B; 0x059C; 0x059D; 0x059E; 0x059F; + (* A *) 0x05A0; 0x05A1; 0x05A2; 0x05A3; 0x05A4; 0x05A5; 0x05A6; 0x05A7; + 0x05A8; 0x05A9; 0x05AA; 0x05AB; 0x05AC; 0x05AD; 0x05AE; 0x05AF; + (* B *) 0x05B0; 0x05B1; 0x05B2; 0x05B3; 0x05B4; 0x05B5; 0x05B6; 0x05B7; + 0x05B8; 0x05B9; 0x05BA; 0x05BB; 0x05BC; 0x05BD; 0x05BE; 0x05BF; + (* C *) 0x05C0; 0x05C1; 0x05C2; 0x05C3; 0x05C4; 0x05C5; 0x05C6; 0x05C7; + 0x05C8; 0x05C9; 0x05CA; 0x05CB; 0x05CC; 0x05CD; 0x05CE; 0x05CF; + (* D *) 0x05D0; 0x05D1; 0x05D2; 0x05D3; 0x05D4; 0x05D5; 0x05D6; 0x05D7; + 0x05D8; 0x05D9; 0x05DA; 0x05DB; 0x05DC; 0x05DD; 0x05DE; 0x05DF; + (* E *) 0x05E0; 0x05E1; 0x05E2; 0x05E3; 0x05E4; 0x05E5; 0x05E6; 0x05E7; + 0x05E8; 0x05E9; 0x05EA; 0x05EB; 0x05EC; 0x05ED; 0x05EE; 0x05EF; + (* F *) 0x05F0; 0x05F1; 0x05F2; 0x05F3; 0x05F4; 0x05F5; 0x05F6; 0x05F7; + 0x05F8; 0x05F9; 0x05FA; 0x05FB; 0x05FC; 0x05FD; 0x05FE; 0x05FF; + + (* Table 6 (for high byte 0x10) *) + + (* 0 *) 0x1000; 0x1001; 0x1002; 0x1003; 0x1004; 0x1005; 0x1006; 0x1007; + 0x1008; 0x1009; 0x100A; 0x100B; 0x100C; 0x100D; 0x100E; 0x100F; + (* 1 *) 0x1010; 0x1011; 0x1012; 0x1013; 0x1014; 0x1015; 0x1016; 0x1017; + 0x1018; 0x1019; 0x101A; 0x101B; 0x101C; 0x101D; 0x101E; 0x101F; + (* 2 *) 0x1020; 0x1021; 0x1022; 0x1023; 0x1024; 0x1025; 0x1026; 0x1027; + 0x1028; 0x1029; 0x102A; 0x102B; 0x102C; 0x102D; 0x102E; 0x102F; + (* 3 *) 0x1030; 0x1031; 0x1032; 0x1033; 0x1034; 0x1035; 0x1036; 0x1037; + 0x1038; 0x1039; 0x103A; 0x103B; 0x103C; 0x103D; 0x103E; 0x103F; + (* 4 *) 0x1040; 0x1041; 0x1042; 0x1043; 0x1044; 0x1045; 0x1046; 0x1047; + 0x1048; 0x1049; 0x104A; 0x104B; 0x104C; 0x104D; 0x104E; 0x104F; + (* 5 *) 0x1050; 0x1051; 0x1052; 0x1053; 0x1054; 0x1055; 0x1056; 0x1057; + 0x1058; 0x1059; 0x105A; 0x105B; 0x105C; 0x105D; 0x105E; 0x105F; + (* 6 *) 0x1060; 0x1061; 0x1062; 0x1063; 0x1064; 0x1065; 0x1066; 0x1067; + 0x1068; 0x1069; 0x106A; 0x106B; 0x106C; 0x106D; 0x106E; 0x106F; + (* 7 *) 0x1070; 0x1071; 0x1072; 0x1073; 0x1074; 0x1075; 0x1076; 0x1077; + 0x1078; 0x1079; 0x107A; 0x107B; 0x107C; 0x107D; 0x107E; 0x107F; + (* 8 *) 0x1080; 0x1081; 0x1082; 0x1083; 0x1084; 0x1085; 0x1086; 0x1087; + 0x1088; 0x1089; 0x108A; 0x108B; 0x108C; 0x108D; 0x108E; 0x108F; + (* 9 *) 0x1090; 0x1091; 0x1092; 0x1093; 0x1094; 0x1095; 0x1096; 0x1097; + 0x1098; 0x1099; 0x109A; 0x109B; 0x109C; 0x109D; 0x109E; 0x109F; + (* A *) 0x10D0; 0x10D1; 0x10D2; 0x10D3; 0x10D4; 0x10D5; 0x10D6; 0x10D7; + 0x10D8; 0x10D9; 0x10DA; 0x10DB; 0x10DC; 0x10DD; 0x10DE; 0x10DF; + (* B *) 0x10E0; 0x10E1; 0x10E2; 0x10E3; 0x10E4; 0x10E5; 0x10E6; 0x10E7; + 0x10E8; 0x10E9; 0x10EA; 0x10EB; 0x10EC; 0x10ED; 0x10EE; 0x10EF; + (* C *) 0x10F0; 0x10F1; 0x10F2; 0x10F3; 0x10F4; 0x10F5; 0x10C6; 0x10C7; + 0x10C8; 0x10C9; 0x10CA; 0x10CB; 0x10CC; 0x10CD; 0x10CE; 0x10CF; + (* D *) 0x10D0; 0x10D1; 0x10D2; 0x10D3; 0x10D4; 0x10D5; 0x10D6; 0x10D7; + 0x10D8; 0x10D9; 0x10DA; 0x10DB; 0x10DC; 0x10DD; 0x10DE; 0x10DF; + (* E *) 0x10E0; 0x10E1; 0x10E2; 0x10E3; 0x10E4; 0x10E5; 0x10E6; 0x10E7; + 0x10E8; 0x10E9; 0x10EA; 0x10EB; 0x10EC; 0x10ED; 0x10EE; 0x10EF; + (* F *) 0x10F0; 0x10F1; 0x10F2; 0x10F3; 0x10F4; 0x10F5; 0x10F6; 0x10F7; + 0x10F8; 0x10F9; 0x10FA; 0x10FB; 0x10FC; 0x10FD; 0x10FE; 0x10FF; + + (* Table 7 (for high byte 0x20) *) + + (* 0 *) 0x2000; 0x2001; 0x2002; 0x2003; 0x2004; 0x2005; 0x2006; 0x2007; + 0x2008; 0x2009; 0x200A; 0x200B; 0x0000; 0x0000; 0x0000; 0x0000; + (* 1 *) 0x2010; 0x2011; 0x2012; 0x2013; 0x2014; 0x2015; 0x2016; 0x2017; + 0x2018; 0x2019; 0x201A; 0x201B; 0x201C; 0x201D; 0x201E; 0x201F; + (* 2 *) 0x2020; 0x2021; 0x2022; 0x2023; 0x2024; 0x2025; 0x2026; 0x2027; + 0x2028; 0x2029; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x202F; + (* 3 *) 0x2030; 0x2031; 0x2032; 0x2033; 0x2034; 0x2035; 0x2036; 0x2037; + 0x2038; 0x2039; 0x203A; 0x203B; 0x203C; 0x203D; 0x203E; 0x203F; + (* 4 *) 0x2040; 0x2041; 0x2042; 0x2043; 0x2044; 0x2045; 0x2046; 0x2047; + 0x2048; 0x2049; 0x204A; 0x204B; 0x204C; 0x204D; 0x204E; 0x204F; + (* 5 *) 0x2050; 0x2051; 0x2052; 0x2053; 0x2054; 0x2055; 0x2056; 0x2057; + 0x2058; 0x2059; 0x205A; 0x205B; 0x205C; 0x205D; 0x205E; 0x205F; + (* 6 *) 0x2060; 0x2061; 0x2062; 0x2063; 0x2064; 0x2065; 0x2066; 0x2067; + 0x2068; 0x2069; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; 0x0000; + (* 7 *) 0x2070; 0x2071; 0x2072; 0x2073; 0x2074; 0x2075; 0x2076; 0x2077; + 0x2078; 0x2079; 0x207A; 0x207B; 0x207C; 0x207D; 0x207E; 0x207F; + (* 8 *) 0x2080; 0x2081; 0x2082; 0x2083; 0x2084; 0x2085; 0x2086; 0x2087; + 0x2088; 0x2089; 0x208A; 0x208B; 0x208C; 0x208D; 0x208E; 0x208F; + (* 9 *) 0x2090; 0x2091; 0x2092; 0x2093; 0x2094; 0x2095; 0x2096; 0x2097; + 0x2098; 0x2099; 0x209A; 0x209B; 0x209C; 0x209D; 0x209E; 0x209F; + (* A *) 0x20A0; 0x20A1; 0x20A2; 0x20A3; 0x20A4; 0x20A5; 0x20A6; 0x20A7; + 0x20A8; 0x20A9; 0x20AA; 0x20AB; 0x20AC; 0x20AD; 0x20AE; 0x20AF; + (* B *) 0x20B0; 0x20B1; 0x20B2; 0x20B3; 0x20B4; 0x20B5; 0x20B6; 0x20B7; + 0x20B8; 0x20B9; 0x20BA; 0x20BB; 0x20BC; 0x20BD; 0x20BE; 0x20BF; + (* C *) 0x20C0; 0x20C1; 0x20C2; 0x20C3; 0x20C4; 0x20C5; 0x20C6; 0x20C7; + 0x20C8; 0x20C9; 0x20CA; 0x20CB; 0x20CC; 0x20CD; 0x20CE; 0x20CF; + (* D *) 0x20D0; 0x20D1; 0x20D2; 0x20D3; 0x20D4; 0x20D5; 0x20D6; 0x20D7; + 0x20D8; 0x20D9; 0x20DA; 0x20DB; 0x20DC; 0x20DD; 0x20DE; 0x20DF; + (* E *) 0x20E0; 0x20E1; 0x20E2; 0x20E3; 0x20E4; 0x20E5; 0x20E6; 0x20E7; + 0x20E8; 0x20E9; 0x20EA; 0x20EB; 0x20EC; 0x20ED; 0x20EE; 0x20EF; + (* F *) 0x20F0; 0x20F1; 0x20F2; 0x20F3; 0x20F4; 0x20F5; 0x20F6; 0x20F7; + 0x20F8; 0x20F9; 0x20FA; 0x20FB; 0x20FC; 0x20FD; 0x20FE; 0x20FF; + + (* Table 8 (for high byte 0x21) *) + + (* 0 *) 0x2100; 0x2101; 0x2102; 0x2103; 0x2104; 0x2105; 0x2106; 0x2107; + 0x2108; 0x2109; 0x210A; 0x210B; 0x210C; 0x210D; 0x210E; 0x210F; + (* 1 *) 0x2110; 0x2111; 0x2112; 0x2113; 0x2114; 0x2115; 0x2116; 0x2117; + 0x2118; 0x2119; 0x211A; 0x211B; 0x211C; 0x211D; 0x211E; 0x211F; + (* 2 *) 0x2120; 0x2121; 0x2122; 0x2123; 0x2124; 0x2125; 0x2126; 0x2127; + 0x2128; 0x2129; 0x212A; 0x212B; 0x212C; 0x212D; 0x212E; 0x212F; + (* 3 *) 0x2130; 0x2131; 0x2132; 0x2133; 0x2134; 0x2135; 0x2136; 0x2137; + 0x2138; 0x2139; 0x213A; 0x213B; 0x213C; 0x213D; 0x213E; 0x213F; + (* 4 *) 0x2140; 0x2141; 0x2142; 0x2143; 0x2144; 0x2145; 0x2146; 0x2147; + 0x2148; 0x2149; 0x214A; 0x214B; 0x214C; 0x214D; 0x214E; 0x214F; + (* 5 *) 0x2150; 0x2151; 0x2152; 0x2153; 0x2154; 0x2155; 0x2156; 0x2157; + 0x2158; 0x2159; 0x215A; 0x215B; 0x215C; 0x215D; 0x215E; 0x215F; + (* 6 *) 0x2170; 0x2171; 0x2172; 0x2173; 0x2174; 0x2175; 0x2176; 0x2177; + 0x2178; 0x2179; 0x217A; 0x217B; 0x217C; 0x217D; 0x217E; 0x217F; + (* 7 *) 0x2170; 0x2171; 0x2172; 0x2173; 0x2174; 0x2175; 0x2176; 0x2177; + 0x2178; 0x2179; 0x217A; 0x217B; 0x217C; 0x217D; 0x217E; 0x217F; + (* 8 *) 0x2180; 0x2181; 0x2182; 0x2183; 0x2184; 0x2185; 0x2186; 0x2187; + 0x2188; 0x2189; 0x218A; 0x218B; 0x218C; 0x218D; 0x218E; 0x218F; + (* 9 *) 0x2190; 0x2191; 0x2192; 0x2193; 0x2194; 0x2195; 0x2196; 0x2197; + 0x2198; 0x2199; 0x219A; 0x219B; 0x219C; 0x219D; 0x219E; 0x219F; + (* A *) 0x21A0; 0x21A1; 0x21A2; 0x21A3; 0x21A4; 0x21A5; 0x21A6; 0x21A7; + 0x21A8; 0x21A9; 0x21AA; 0x21AB; 0x21AC; 0x21AD; 0x21AE; 0x21AF; + (* B *) 0x21B0; 0x21B1; 0x21B2; 0x21B3; 0x21B4; 0x21B5; 0x21B6; 0x21B7; + 0x21B8; 0x21B9; 0x21BA; 0x21BB; 0x21BC; 0x21BD; 0x21BE; 0x21BF; + (* C *) 0x21C0; 0x21C1; 0x21C2; 0x21C3; 0x21C4; 0x21C5; 0x21C6; 0x21C7; + 0x21C8; 0x21C9; 0x21CA; 0x21CB; 0x21CC; 0x21CD; 0x21CE; 0x21CF; + (* D *) 0x21D0; 0x21D1; 0x21D2; 0x21D3; 0x21D4; 0x21D5; 0x21D6; 0x21D7; + 0x21D8; 0x21D9; 0x21DA; 0x21DB; 0x21DC; 0x21DD; 0x21DE; 0x21DF; + (* E *) 0x21E0; 0x21E1; 0x21E2; 0x21E3; 0x21E4; 0x21E5; 0x21E6; 0x21E7; + 0x21E8; 0x21E9; 0x21EA; 0x21EB; 0x21EC; 0x21ED; 0x21EE; 0x21EF; + (* F *) 0x21F0; 0x21F1; 0x21F2; 0x21F3; 0x21F4; 0x21F5; 0x21F6; 0x21F7; + 0x21F8; 0x21F9; 0x21FA; 0x21FB; 0x21FC; 0x21FD; 0x21FE; 0x21FF; + + (* Table 9 (for high byte 0xFE) *) + + (* 0 *) 0xFE00; 0xFE01; 0xFE02; 0xFE03; 0xFE04; 0xFE05; 0xFE06; 0xFE07; + 0xFE08; 0xFE09; 0xFE0A; 0xFE0B; 0xFE0C; 0xFE0D; 0xFE0E; 0xFE0F; + (* 1 *) 0xFE10; 0xFE11; 0xFE12; 0xFE13; 0xFE14; 0xFE15; 0xFE16; 0xFE17; + 0xFE18; 0xFE19; 0xFE1A; 0xFE1B; 0xFE1C; 0xFE1D; 0xFE1E; 0xFE1F; + (* 2 *) 0xFE20; 0xFE21; 0xFE22; 0xFE23; 0xFE24; 0xFE25; 0xFE26; 0xFE27; + 0xFE28; 0xFE29; 0xFE2A; 0xFE2B; 0xFE2C; 0xFE2D; 0xFE2E; 0xFE2F; + (* 3 *) 0xFE30; 0xFE31; 0xFE32; 0xFE33; 0xFE34; 0xFE35; 0xFE36; 0xFE37; + 0xFE38; 0xFE39; 0xFE3A; 0xFE3B; 0xFE3C; 0xFE3D; 0xFE3E; 0xFE3F; + (* 4 *) 0xFE40; 0xFE41; 0xFE42; 0xFE43; 0xFE44; 0xFE45; 0xFE46; 0xFE47; + 0xFE48; 0xFE49; 0xFE4A; 0xFE4B; 0xFE4C; 0xFE4D; 0xFE4E; 0xFE4F; + (* 5 *) 0xFE50; 0xFE51; 0xFE52; 0xFE53; 0xFE54; 0xFE55; 0xFE56; 0xFE57; + 0xFE58; 0xFE59; 0xFE5A; 0xFE5B; 0xFE5C; 0xFE5D; 0xFE5E; 0xFE5F; + (* 6 *) 0xFE60; 0xFE61; 0xFE62; 0xFE63; 0xFE64; 0xFE65; 0xFE66; 0xFE67; + 0xFE68; 0xFE69; 0xFE6A; 0xFE6B; 0xFE6C; 0xFE6D; 0xFE6E; 0xFE6F; + (* 7 *) 0xFE70; 0xFE71; 0xFE72; 0xFE73; 0xFE74; 0xFE75; 0xFE76; 0xFE77; + 0xFE78; 0xFE79; 0xFE7A; 0xFE7B; 0xFE7C; 0xFE7D; 0xFE7E; 0xFE7F; + (* 8 *) 0xFE80; 0xFE81; 0xFE82; 0xFE83; 0xFE84; 0xFE85; 0xFE86; 0xFE87; + 0xFE88; 0xFE89; 0xFE8A; 0xFE8B; 0xFE8C; 0xFE8D; 0xFE8E; 0xFE8F; + (* 9 *) 0xFE90; 0xFE91; 0xFE92; 0xFE93; 0xFE94; 0xFE95; 0xFE96; 0xFE97; + 0xFE98; 0xFE99; 0xFE9A; 0xFE9B; 0xFE9C; 0xFE9D; 0xFE9E; 0xFE9F; + (* A *) 0xFEA0; 0xFEA1; 0xFEA2; 0xFEA3; 0xFEA4; 0xFEA5; 0xFEA6; 0xFEA7; + 0xFEA8; 0xFEA9; 0xFEAA; 0xFEAB; 0xFEAC; 0xFEAD; 0xFEAE; 0xFEAF; + (* B *) 0xFEB0; 0xFEB1; 0xFEB2; 0xFEB3; 0xFEB4; 0xFEB5; 0xFEB6; 0xFEB7; + 0xFEB8; 0xFEB9; 0xFEBA; 0xFEBB; 0xFEBC; 0xFEBD; 0xFEBE; 0xFEBF; + (* C *) 0xFEC0; 0xFEC1; 0xFEC2; 0xFEC3; 0xFEC4; 0xFEC5; 0xFEC6; 0xFEC7; + 0xFEC8; 0xFEC9; 0xFECA; 0xFECB; 0xFECC; 0xFECD; 0xFECE; 0xFECF; + (* D *) 0xFED0; 0xFED1; 0xFED2; 0xFED3; 0xFED4; 0xFED5; 0xFED6; 0xFED7; + 0xFED8; 0xFED9; 0xFEDA; 0xFEDB; 0xFEDC; 0xFEDD; 0xFEDE; 0xFEDF; + (* E *) 0xFEE0; 0xFEE1; 0xFEE2; 0xFEE3; 0xFEE4; 0xFEE5; 0xFEE6; 0xFEE7; + 0xFEE8; 0xFEE9; 0xFEEA; 0xFEEB; 0xFEEC; 0xFEED; 0xFEEE; 0xFEEF; + (* F *) 0xFEF0; 0xFEF1; 0xFEF2; 0xFEF3; 0xFEF4; 0xFEF5; 0xFEF6; 0xFEF7; + 0xFEF8; 0xFEF9; 0xFEFA; 0xFEFB; 0xFEFC; 0xFEFD; 0xFEFE; 0x0000; + + (* Table 10 (for high byte 0xFF) *) + + (* 0 *) 0xFF00; 0xFF01; 0xFF02; 0xFF03; 0xFF04; 0xFF05; 0xFF06; 0xFF07; + 0xFF08; 0xFF09; 0xFF0A; 0xFF0B; 0xFF0C; 0xFF0D; 0xFF0E; 0xFF0F; + (* 1 *) 0xFF10; 0xFF11; 0xFF12; 0xFF13; 0xFF14; 0xFF15; 0xFF16; 0xFF17; + 0xFF18; 0xFF19; 0xFF1A; 0xFF1B; 0xFF1C; 0xFF1D; 0xFF1E; 0xFF1F; + (* 2 *) 0xFF20; 0xFF41; 0xFF42; 0xFF43; 0xFF44; 0xFF45; 0xFF46; 0xFF47; + 0xFF48; 0xFF49; 0xFF4A; 0xFF4B; 0xFF4C; 0xFF4D; 0xFF4E; 0xFF4F; + (* 3 *) 0xFF50; 0xFF51; 0xFF52; 0xFF53; 0xFF54; 0xFF55; 0xFF56; 0xFF57; + 0xFF58; 0xFF59; 0xFF5A; 0xFF3B; 0xFF3C; 0xFF3D; 0xFF3E; 0xFF3F; + (* 4 *) 0xFF40; 0xFF41; 0xFF42; 0xFF43; 0xFF44; 0xFF45; 0xFF46; 0xFF47; + 0xFF48; 0xFF49; 0xFF4A; 0xFF4B; 0xFF4C; 0xFF4D; 0xFF4E; 0xFF4F; + (* 5 *) 0xFF50; 0xFF51; 0xFF52; 0xFF53; 0xFF54; 0xFF55; 0xFF56; 0xFF57; + 0xFF58; 0xFF59; 0xFF5A; 0xFF5B; 0xFF5C; 0xFF5D; 0xFF5E; 0xFF5F; + (* 6 *) 0xFF60; 0xFF61; 0xFF62; 0xFF63; 0xFF64; 0xFF65; 0xFF66; 0xFF67; + 0xFF68; 0xFF69; 0xFF6A; 0xFF6B; 0xFF6C; 0xFF6D; 0xFF6E; 0xFF6F; + (* 7 *) 0xFF70; 0xFF71; 0xFF72; 0xFF73; 0xFF74; 0xFF75; 0xFF76; 0xFF77; + 0xFF78; 0xFF79; 0xFF7A; 0xFF7B; 0xFF7C; 0xFF7D; 0xFF7E; 0xFF7F; + (* 8 *) 0xFF80; 0xFF81; 0xFF82; 0xFF83; 0xFF84; 0xFF85; 0xFF86; 0xFF87; + 0xFF88; 0xFF89; 0xFF8A; 0xFF8B; 0xFF8C; 0xFF8D; 0xFF8E; 0xFF8F; + (* 9 *) 0xFF90; 0xFF91; 0xFF92; 0xFF93; 0xFF94; 0xFF95; 0xFF96; 0xFF97; + 0xFF98; 0xFF99; 0xFF9A; 0xFF9B; 0xFF9C; 0xFF9D; 0xFF9E; 0xFF9F; + (* A *) 0xFFA0; 0xFFA1; 0xFFA2; 0xFFA3; 0xFFA4; 0xFFA5; 0xFFA6; 0xFFA7; + 0xFFA8; 0xFFA9; 0xFFAA; 0xFFAB; 0xFFAC; 0xFFAD; 0xFFAE; 0xFFAF; + (* B *) 0xFFB0; 0xFFB1; 0xFFB2; 0xFFB3; 0xFFB4; 0xFFB5; 0xFFB6; 0xFFB7; + 0xFFB8; 0xFFB9; 0xFFBA; 0xFFBB; 0xFFBC; 0xFFBD; 0xFFBE; 0xFFBF; + (* C *) 0xFFC0; 0xFFC1; 0xFFC2; 0xFFC3; 0xFFC4; 0xFFC5; 0xFFC6; 0xFFC7; + 0xFFC8; 0xFFC9; 0xFFCA; 0xFFCB; 0xFFCC; 0xFFCD; 0xFFCE; 0xFFCF; + (* D *) 0xFFD0; 0xFFD1; 0xFFD2; 0xFFD3; 0xFFD4; 0xFFD5; 0xFFD6; 0xFFD7; + 0xFFD8; 0xFFD9; 0xFFDA; 0xFFDB; 0xFFDC; 0xFFDD; 0xFFDE; 0xFFDF; + (* E *) 0xFFE0; 0xFFE1; 0xFFE2; 0xFFE3; 0xFFE4; 0xFFE5; 0xFFE6; 0xFFE7; + 0xFFE8; 0xFFE9; 0xFFEA; 0xFFEB; 0xFFEC; 0xFFED; 0xFFEE; 0xFFEF; + (* F *) 0xFFF0; 0xFFF1; 0xFFF2; 0xFFF3; 0xFFF4; 0xFFF5; 0xFFF6; 0xFFF7; + 0xFFF8; 0xFFF9; 0xFFFA; 0xFFFB; 0xFFFC; 0xFFFD; 0xFFFE; 0xFFFF; +|] + +(****) + +let bitmap_test base bitmap character = + character >= base + && + (let value = bitmap.((character lsr 8) land 0xFF) in + value = 0xFF + || + (value <> 0 + && + bitmap.((value - 1) * 32 + 256 + (character land 0xFF) / 8) + land (1 lsl (character mod 8)) <> 0)) + +let unicode_combinable character = + bitmap_test 0x0300 uniCharCombiningBitmap character + +let unicode_decomposeable character = + bitmap_test 0x00C0 uniCharDecomposableBitmap character + +(****) + +let decompose_map = empty () + +let hangul_sbase = 0xAC00 +let hangul_lbase = 0x1100 +let hangul_vbase = 0x1161 +let hangul_tbase = 0x11A7 + +let hangul_scount = 11172 +let hangul_lcount = 19 +let hangul_vcount = 21 +let hangul_tcount = 28 +let hangul_ncount = hangul_vcount * hangul_tcount + +let convert_hangul character = + let character = character - hangul_sbase in + (* length = (character % HANGUL_TCOUNT ? 3 : 2); *) + let length = if character mod hangul_tcount = 0 then 2 else 3 in + (character / hangul_ncount + hangul_lbase :: + (character mod hangul_ncount) / hangul_tcount + hangul_vbase :: + if length = 2 then [] else + [(character mod hangul_tcount) + hangul_tbase]) + +let _ = + (* Note that there is an off-by-one bug in vfs_utfconv.c *) + (* This is not an issue as the last character is not marked + as decomposeable in the bitmap *) + assert (not (unicode_decomposeable (hangul_sbase + hangul_scount))); + for character = hangul_sbase to hangul_sbase + hangul_scount - 1 do + let l = convert_hangul character in +(* add decompose_map character l;*) + assert (unicode_decomposeable character) + done + +(****) + +let extractCount value = (value lsr 12) land 0x0007 + +let recursiveDecomposition = 1 lsl 15 + +let _ = + let rec get_multiple i l = + if l = 0 then [] else + uniCharMultipleDecompositionTable.(i) :: get_multiple (i + 1) (l - 1) + in + let tbl = uniCharDecompositionTable in + + let rec decode v = + let l = extractCount v in + let ch = v land 0xFFF in + let recurs = v land recursiveDecomposition <> 0 in + let s = if l = 1 then [ch] else get_multiple ch l in + if recurs then + match s with + [] -> + assert false + | ch :: r -> + decompose ch 0 @ r + else + s + and decompose ch i = + if tbl.(2 * i) = ch then decode tbl.(2 * i + 1) else + decompose ch (i + 1) + in + + let len = Array.length tbl / 2 in + for i = 0 to len - 1 do + let ch = tbl.(i * 2) in + let v = tbl.(i * 2 + 1) in + add decompose_map ch (decode v); + assert (unicode_decomposeable ch) + done + +let _ = + let tbl = uniCharDecompositionTable in + for c = 0 to 0xffff do + if + unicode_decomposeable c && + (c < hangul_sbase || c >= hangul_sbase + hangul_scount) + then begin + let found = ref false in + for i = 0 to (Array.length tbl) / 2 - 1 do + if tbl.(i * 2) = c then found := true + done; + assert !found + end + done + +(* +let _ = + IntMap.iter (fun c l -> Format.printf "%a -> %a@." print_uni c print_chars l) + !decompose_map; + exit 0 +*) + +(****) +let compose_map = empty () + +let add_comp m c v = + let l = try IntMap.find c !m with Not_found -> ref [] in + l := v :: !l; + m := IntMap.add c l !m + +let _ = + let t1 = uniCharPrecompSourceTable in + let t2 = uniCharBMPPrecompDestinationTable in + for i = 0 to Array.length t1 / 2 - 1 do + let c = t1.(2 * i) in + let v = t1.(2 * i + 1) in + let j = v land 0xFFFF in + let l = v lsr 16 in + for j = j to j + l - 1 do + add_comp compose_map c (t2.(2 * j), t2.(2 * j + 1)); +(* + Format.printf "%a %a -> %a@." + print_uni t2.(2 * j) print_uni c print_uni t2.(2 * j + 1) +*) + done + done + +(****) + +let lower_map = empty () +let lower_map = decompose_map + +let _ = + for i = 0 to 255 do + let c1 = lowerCaseTable.(i) in + if c1 <> 0 then begin + for j = 0 to 255 do + let c2 = lowerCaseTable.(j + c1) in + let c = i * 256 + j in + if c2 = 0 then + add lower_map c [] + else if c <> c2 then + add lower_map c [c2] + done + end + done + +(* +let _ = + IntMap.iter (fun c l -> Format.printf "%a -> %a@." print_uni c print_chars l) + !lower_map; + exit 0 +*) + +(****) + +(* Support for Microsoft Windows NT Services for Macintosh (SFM) + convention (http://support.microsoft.com/kb/q117258) *) + +let alternative_table = + [('\x01', 0xf001); ('\x02', 0xf002); ('\x03', 0xf003); + ('\x04', 0xf004); ('\x05', 0xf005); ('\x06', 0xf006); ('\x07', 0xf007); + ('\x08', 0xf008); ('\x09', 0xf009); ('\x0a', 0xf00a); ('\x0b', 0xf00b); + ('\x0c', 0xf00c); ('\x0d', 0xf00d); ('\x0e', 0xf00e); ('\x0f', 0xf00f); + ('\x10', 0xf010); ('\x11', 0xf011); ('\x12', 0xf012); ('\x13', 0xf013); + ('\x14', 0xf014); ('\x15', 0xf015); ('\x16', 0xf016); ('\x17', 0xf017); + ('\x18', 0xf018); ('\x19', 0xf019); ('\x1a', 0xf01a); ('\x1b', 0xf01b); + ('\x1c', 0xf01c); ('\x1d', 0xf01d); ('\x1e', 0xf01e); ('\x1f', 0xf01f); + ('"', 0xf020); ('*', 0xf021); (':', 0xf022); ('<', 0xf023); ('>', 0xf024); + ('?', 0xf025); ('\\', 0xf026); ('|', 0xf027); (' ', 0xf028); ('.', 0xf029)] + +let _ = +List.iter (fun (c, c') -> add decompose_map c' [Char.code c]) alternative_table + +(****) + +(* In Samba but not in MacOSX *) + +let missing_lower = + [(0x03c2, 0x03c3); (0x04d4, 0x04d5); (0x04d8, 0x04d9); (0x04e0, 0x04e1); + (0x04e8, 0x04e9); (0x24b6, 0x24d0); (0x24b7, 0x24d1); (0x24b8, 0x24d2); + (0x24b9, 0x24d3); (0x24ba, 0x24d4); (0x24bb, 0x24d5); (0x24bc, 0x24d6); + (0x24bd, 0x24d7); (0x24be, 0x24d8); (0x24bf, 0x24d9); (0x24c0, 0x24da); + (0x24c1, 0x24db); (0x24c2, 0x24dc); (0x24c3, 0x24dd); (0x24c4, 0x24de); + (0x24c5, 0x24df); (0x24c6, 0x24e0); (0x24c7, 0x24e1); (0x24c8, 0x24e2); + (0x24c9, 0x24e3); (0x24ca, 0x24e4); (0x24cb, 0x24e5); (0x24cc, 0x24e6); + (0x24cd, 0x24e7); (0x24ce, 0x24e8); (0x24cf, 0x24e9)] + +let _ = List.iter (fun (c, c') -> add lower_map c [c']) missing_lower + +(****) + +let normalize_map = compose !lower_map !decompose_map + +let conv c = + if c >= hangul_sbase && c < hangul_sbase + hangul_scount then + String.concat "" (List.map encode_utf8 (convert_hangul c)) + else + try + String.concat "" + (List.map encode_utf8 (IntMap.find c normalize_map)) + with Not_found -> + encode_utf8 c + +let _ = + IntMap.iter (fun c l -> +(* Format.printf "%a -> %a@." print_uni c print_chars l;*) + let s1 = encode_utf8 c in + let s2 = conv c in + assert (String.length s2 <= 3 * String.length s1)) + normalize_map + +(****) + +(**** Samba tables *) + +let read_file nm l = + let ch = open_in ("codepages/" ^ nm) in + let s = String.create l in + really_input ch s 0 l; + s + +let load nm = + let tbl = read_file nm (2 * 65536) in + fun c -> Char.code tbl.[c * 2] + 256 * Char.code tbl.[c * 2 + 1] + +let to_upper = load "upcase.dat" +let to_lower = load "lowcase.dat" + +let toupper_ascii_fast_table = + [| 0x0; 0x1; 0x2; 0x3; 0x4; 0x5; 0x6; 0x7; 0x8; 0x9; 0xa; 0xb; 0xc; + 0xd; 0xe; 0xf; 0x10; 0x11; 0x12; 0x13; 0x14; 0x15; 0x16; 0x17; + 0x18; 0x19; 0x1a; 0x1b; 0x1c; 0x1d; 0x1e; 0x1f; 0x20; 0x21; 0x22; + 0x23; 0x24; 0x25; 0x26; 0x27; 0x28; 0x29; 0x2a; 0x2b; 0x2c; 0x2d; + 0x2e; 0x2f; 0x30; 0x31; 0x32; 0x33; 0x34; 0x35; 0x36; 0x37; 0x38; + 0x39; 0x3a; 0x3b; 0x3c; 0x3d; 0x3e; 0x3f; 0x40; 0x41; 0x42; 0x43; + 0x44; 0x45; 0x46; 0x47; 0x48; 0x49; 0x4a; 0x4b; 0x4c; 0x4d; 0x4e; + 0x4f; 0x50; 0x51; 0x52; 0x53; 0x54; 0x55; 0x56; 0x57; 0x58; 0x59; + 0x5a; 0x5b; 0x5c; 0x5d; 0x5e; 0x5f; 0x60; 0x41; 0x42; 0x43; 0x44; + 0x45; 0x46; 0x47; 0x48; 0x49; 0x4a; 0x4b; 0x4c; 0x4d; 0x4e; 0x4f; + 0x50; 0x51; 0x52; 0x53; 0x54; 0x55; 0x56; 0x57; 0x58; 0x59; 0x5a; + 0x7b; 0x7c; 0x7d; 0x7e; 0x7f |] + +let _ = + for i = 0 to 127 do + assert (toupper_ascii_fast_table.(i) = to_upper i) + done + +(* +let _ = + Format.printf "================@."; + for c = 0 to 65535 do + let c' = to_upper c in + let l = convert normalize_map c in + let l' = convert normalize_map c' in + if c <> c' && l <> l' then + Format.printf "%a (%a) -> %a (%a)@." + print_uni c print_chars l print_uni c' print_chars l' + done +*) + +(* +let _ = + Format.printf "================@."; + for c = 0 to 65535 do + begin match convert normalize_map c with + [c'] -> + let d = to_upper c in + let d' = to_upper c' in + if c <> c' && d <> d' then + Format.printf "%a (%a) -> %a (%a)@." + print_uni c print_uni d print_uni c' print_uni d' + | _ -> + () + end + done +*) + +(****) + +type action = Copy | Replace of int list | Scan of int * int * action array + +let make_level () = Array.make 256 Copy + +let table = make_level () + +let get tbl c = tbl.(c) +let rec set tbl c v = tbl.(c) <- v + +let rec insert tbl c l = + match c with + [] -> assert false + | [c] -> +if get tbl c = Copy then set tbl c (Replace l) +(*XXXXXXXXXXXXXX + assert (get tbl c = Copy); set tbl c (Replace l) +*) + | c :: r -> + let a = + match get tbl c with + Copy -> + let a = make_level () in set tbl c (Scan (0, 256, a)); a + | Scan (_, _, a) -> + a + | _ -> + let a = make_level () in set tbl c (Scan (0, 256, a)); a +(*XXXXXXXXXX assert false*) + in + insert a r l + +let rec list_of_string_rec s i l = + if i = l then [] else Char.code s.[i] :: list_of_string_rec s (i + 1) l + +let list_of_string s = list_of_string_rec s 0 (String.length s) + +let _ = + IntMap.iter + (fun c l -> let s = encode_utf8 c in insert table (list_of_string s) l) + normalize_map + +let rec print_seq ch s = + match s with + [] -> () + | [c] -> Format.fprintf ch "%2x" c + | c :: r -> Format.fprintf ch "%2x,%a" c print_seq r + +(* +let sz = ref 0 + +let rec compress loc tbl = + for i = 0 to Array.length tbl - 1 do + match tbl.(i) with + Copy -> () + | Replace _ -> () + | Scan (j, k, a) -> + let loc = i :: loc in + compress loc a; + let l = k - j in + let j' = ref 0 in + while !j' < l && a.(!j') = Copy do incr j' done; + let k' = ref (l - 1) in + while !k' >= 0 && a.(!k') = Copy do decr k' done; + incr k'; + assert (!j' < !k'); + let l' = !k' - !j' in + sz := !sz + l' + 5; + let a = Array.sub a !j' l' in +Format.eprintf "%a: %2x %d@." print_seq (List.rev loc) (j + !j') l'; + tbl.(i) <- Scan (j + !j', j + !k', a) + done + +let _ = compress [] table + +let _ = Format.eprintf "size: %d@." !sz + + +let table = make_level () + +let _ = + IntMap.iter + (fun c l -> + let s = + List.flatten + (List.map (fun c -> list_of_string (encode_utf8 c)) l) + in + if s <> [] then insert table s [c]) + normalize_map + +let _ = sz := 0; compress [] table; Format.eprintf "size: %d@." !sz + *) + +(****) + +type 'a t = { l : int; tbl : 'a option array array } + +let dummy = [||] +let make l = {l = l; tbl = Array.make (65536 / l) dummy} +let set tbl n v = + let i = n / tbl.l in + let j = n mod tbl.l in + if tbl.tbl.(i) == dummy then + tbl.tbl.(i) <- Array.make tbl.l None; + tbl.tbl.(i).(j) <- Some v +let size tbl = + let n = ref 0 in + let l = Array.length tbl.tbl in + for i = 0 to l - 1 do if tbl.tbl.(i) != dummy then incr n done; + let n = !n in +(* + if n >= 255 then + l * 2 + (n + 2) * tbl.l * 2 + else + l + (n + 2) * tbl.l * 2 +*) + (0x309a + tbl.l - 1) / tbl.l + (n + 1) * tbl.l +(* + l + (n + 1) * tbl.l +*) + +let build m l = + let tbl = make (1 lsl l) in IntMap.iter (fun c l -> if c > 127 then set tbl c l) m; tbl + +(* +let _ = + for l = 1 to 15 do + Format.eprintf "%d %d@." l (size (build normalize_map l)) + done + +let _ = + for l = 1 to 15 do + Format.eprintf "%d %d@." l (size (build !compose_map l)) + done +*) + +let print_tbl nm ch tbl = + (* ASCII *) + Format.fprintf ch "@[<2>let %s_%s =@ @[<1>\"" nm "ascii"; + for c = 0 to 127 do + Format.fprintf ch "%s" (String.escaped (conv c)) + done; + Format.fprintf ch "\"@]@]@."; + (* Replacement *) + let l = ref [] in + let p = ref 0 in + Format.fprintf ch "@[<2>let %s_%s =@ @[<1>\"" nm "repl"; + for i = 0 to Array.length tbl.tbl - 1 do + let a = tbl.tbl.(i) in + if a != dummy then begin + for j = 0 to tbl.l - 1 do + match a.(j) with + None -> + () + | Some v -> + if not (List.mem_assoc v !l) then begin + l := (v, !p) :: !l; + let s = String.concat "" (List.map encode_utf8 v) in + Format.fprintf ch "\\%03d%s" + (String.length s) (if s = "\\" then "\\\\" else + if s = "\"" then "\\\"" else s); + p := !p + String.length s + 1 + end + done + end + done; + Format.fprintf ch "\"@]@]@."; + (* Primary level *) + Format.fprintf ch "@[<2>let %s_%s =@ @[<1>\"" nm "prim"; + let n = ref 1 in + for i = 0 to Array.length tbl.tbl - 1 do + let j = + if i * tbl.l < hangul_sbase + hangul_scount && + (i + 1) * tbl.l - 1 >= hangul_sbase then begin + assert (tbl.tbl.(i) == dummy); 1 + end else if tbl.tbl.(i) == dummy then 0 else begin incr n; !n end in + Format.fprintf ch "\\%03d" j + done; + Format.fprintf ch "\"@]@]@."; + (* Secondary level *) + Format.fprintf ch "@[<2>let %s_%s =@ @[<1>\"" nm "second_high"; + for i = 0 to tbl.l - 1 do (* Empty table *) + Format.fprintf ch "\\%03d" 0 + done; + for i = 0 to tbl.l - 1 do (* Hangul table *) + Format.fprintf ch "\\%03d" 1 + done; + for i = 0 to Array.length tbl.tbl - 1 do + let a = tbl.tbl.(i) in + if a != dummy then begin + for j = 0 to tbl.l - 1 do + match a.(j) with + None -> + Format.fprintf ch "\\%03d" 0 + | Some v -> + let n = List.assoc v !l in + (* 0 is unchanged; 1 is Hangul *) + Format.fprintf ch "\\%03d" (n / 256 + 2) + done + end + done; + Format.fprintf ch "\"@]@]@."; + Format.fprintf ch "@[<2>let %s_%s =@ @[<1>\"" nm "second_low"; + for i = 0 to 2 * tbl.l - 1 do (* Two unused entries *) + Format.fprintf ch "\\%03d" 0 + done; + for i = 0 to Array.length tbl.tbl - 1 do + let a = tbl.tbl.(i) in + if a != dummy then begin + for j = 0 to tbl.l - 1 do + match a.(j) with + None -> + Format.fprintf ch "\\%03d" 0 + | Some v -> + let n = List.assoc v !l in + Format.fprintf ch "\\%03d" (n mod 256) + done + end + done; + Format.fprintf ch "\"@]@]@." + +let print_compose prim snd ch tbl = + (* Primary level *) + Format.fprintf ch "@[<2>let %s =@ @[<1>\"" prim; + let n = ref 1 in + for i = 0 to Array.length tbl.tbl - 1 do + let j = +(*XXX Hangul*) +(* + if i * tbl.l < hangul_sbase + hangul_scount && + (i + 1) * tbl.l - 1 >= hangul_sbase then begin + assert (tbl.tbl.(i) == dummy); 1 + end else*) if tbl.tbl.(i) == dummy then 0 else begin incr n; !n end in + Format.fprintf ch "\\%03d" j + done; + Format.fprintf ch "\"@]@]@."; + (* Secondary level *) + let n = ref 1 in + Format.fprintf ch "@[<2>let %s =@ @[<1>\"" snd; + for i = 0 to tbl.l - 1 do (* Empty table *) + Format.fprintf ch "\\%03d" 0 + done; + for i = 0 to tbl.l - 1 do (* Hangul table *) + Format.fprintf ch "\\%03d" 1 + done; + for i = 0 to Array.length tbl.tbl - 1 do + let a = tbl.tbl.(i) in + if a != dummy then begin + for j = 0 to tbl.l - 1 do + match a.(j) with + None -> + Format.fprintf ch "\\%03d" 0 + | Some v -> + incr n; + Format.fprintf ch "\\%03d" !n + done + end + done; + Format.fprintf ch "\"@]@]@." + +let _ = + let o = open_out "unicode_tables.ml" in + let ch = Format.formatter_of_out_channel o in + Format.fprintf ch "(*-*-coding: utf-8;-*-*)@."; + Format.fprintf ch "%a" (print_tbl "norm") + (build normalize_map 6); + Format.fprintf ch "%a" (print_tbl "decomp") + (build !decompose_map 6); +(* + Format.fprintf ch "%a" (print_compose "comp_prim" "comp_snd") + (build !compose_map 6); +*) + close_out o + +(* +let k = Char.code first.(i)) lsl 6 + j in +let fst = Char.code second.(k) in +if fst = 0 then ... else +let snd = Char.code second'.(k) in +let i = fst lsl 8 + snd - 256 in +let s = tbl.(i) in +... +*) + +(* +let next s = + let c = Ibuffer.look_ahead s in + if c = -1 then begin + 0xffff (* EOF *) + end else if c < 0x80 then begin + c + end else if c < 0xE0 then begin + (* 80 - 7FF *) + if c < 0xC2 then raise Failed; + if not (Ibuffer.advance s 1) then raise Failed; + let c1 = Ibuffer.read s 1 in + if c1 land 192 <> 128 then raise Failed; + (c - 0xC0) lsl 6 + c1 - 0x80 + end else if c < 0xF0 then begin + (* 800 - FFFF *) + if not (Ibuffer.advance s 2) then raise Failed; + let c1 = Ibuffer.read s 1 in + if c1 land 192 <> 128 then raise Failed; + if c = 0xE0 && c1 < 0xA0 then raise Failed; + let c2 = Ibuffer.read s 2 in + if c2 land 192 <> 128 then raise Failed; + let res = (c - 0xE0) lsl 12 + (c1 - 0x80) lsl 6 + c2 - 0x80 in + if res = 0xFFFF then raise Failed; + res end else if c < 0xF5 then begin + (* 10000 - 10FFFF *) + if not (Ibuffer.advance s 3) then raise Failed; + let c1 = Ibuffer.read s 1 in + if c1 land 192 <> 128 then raise Failed; + if c = 0xF0 && c1 < 0x90 then raise Failed; + if c = 0xF4 && c1 >= 0x90 then raise Failed; + let c2 = Ibuffer.read s 2 in + if c2 land 192 <> 128 then raise Failed; + let c3 = Ibuffer.read s 3 in + if c3 land 192 <> 128 then raise Failed; + (c - 0xF0) lsl 18 + (c1 - 0x80) lsl 12 + (c2 - 0x80) lsl 6 + c3 - 0x80 + end else + raise Failed +*) diff --git a/unicode_utils/unicode_test.ml b/unicode_utils/unicode_test.ml new file mode 100644 index 0000000..859b174 --- /dev/null +++ b/unicode_utils/unicode_test.ml @@ -0,0 +1,83 @@ +(*-*-coding: utf-8;-*-*) + +#use "unicode_build.ml" +#load "unix.cma" + +let _ = +Unix.system "test -f unicode_tables.cmo || ocamlc -c unicode_tables.ml";; + +#load "unicode_tables.cmo" +#use "unicode.ml" +#use "reorder.ml" + +let _ = + let b1 = Buffer.create 1024 in + let b2 = Buffer.create 1024 in + for i = 0 to 0x1ffff do + if i < 0xd800 || i > 0xdfff then begin + Buffer.add_string b1 (encode_utf8 i); + Buffer.add_string b2 (conv i) + end + done; + let s1 = Buffer.contents b1 in + let s2 = Buffer.contents b2 in +prerr_endline "==="; +Format.printf "%d %d@." (String.length s1) (String.length s2); +Format.printf "%d %d@." (String.length (normalize s1)) (String.length s2); + assert (normalize s1 = s2); + assert (normalize s2 = s2); + assert (normalize (compose s2) = s2); + assert (from_utf_16 (to_utf_16 s1) = s1) + +let _ = + let b1 = Buffer.create 1024 in + let b2 = Buffer.create 1024 in + for i = hangul_sbase -128 to hangul_sbase + hangul_scount - 1 + 128 do + Buffer.add_string b1 (encode_utf8 i); + Buffer.add_string b2 (conv i) + done; + let s1 = Buffer.contents b1 in + let s2 = Buffer.contents b2 in + assert (compose s2 = s1) + +let _ = + assert (compare "abcdéfgh" "ABCDÉFGH" = 0); + assert (compare "abcdéfghi" "ABCDÉFGH" = 1); + assert (compare "abcdefghi" "ABCDeFGH" = 1); + assert (compare "abcdéfgh" "ABCDÉFGHi" = -1); + assert (compare "abcdefgh" "ABCDeFGHi" = -1); + assert (compare "abcdéfgh" "ACCDÉFGH" = -1); + assert (compare "abcdéfgh" "ABCDÉFFH" = 1) + +let _ = + for i = 0 to 0xffff do + if i < 0xd800 || i > 0xdfff then begin + let s = to_utf_16 (conv i) in +(*Format.printf "%04x@." (String.length s);*) + for j = 0 to String.length s / 2 - 2 do + let c1 = get s (j * 2) + get s (j * 2 + 1) * 256 in + let c2 = get s (j * 2 + 2) + get s (j * 2 + 3) * 256 in + let v1 = combining_class c1 in + let v2 = combining_class c2 in +(*Format.printf "%04x %04x => %02x %02x@." c1 c2 v1 v2;*) +(* if v1 > 0 && v2 > 0 then Format.printf "%d %d@." v1 v2;*) + assert (v1 = 0 || v2 = 0 || v1 <= v2) + done + end + done + +let _ = +let s = from_utf_16 "\x61\x00\x01\x03\x63\x00\x01\x03\x27\x03" in +order s; +assert (s = from_utf_16 "\x61\x00\x01\x03\x63\x00\x27\x03\x01\x03"); +let s = from_utf_16 "\x01\x03\x27\x03" in +order s; +assert (s = from_utf_16 "\x27\x03\x01\x03") +(* +0061;LATIN SMALL LETTER A;...0;... +0063;LATIN SMALL LETTER C;...0;... +00E1;LATIN SMALL LETTER A WITH ACUTE;...0;...0061 0301;... +0107;LATIN SMALL LETTER C WITH ACUTE;...0;...0063 0301;... +0301;COMBINING ACUTE ACCENT;...230;... +0327;COMBINING CEDILLA;...202;... +*) |