diff --git a/.gitignore b/.gitignore index f0eaeb719..c7cd454f5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ generated GNUmakefile .DS_Store .*.sw* +Makefile diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..4ba296901 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,27 @@ +Guidelines for Contributing +=========================== + +Welcome to the D community and thanks for your interest in contributing! + +# [How to contribute pull requests?](http://wiki.dlang.org/Pull_Requests) + +# More Links + +* Fork [on Github](https://github.com/D-Programming-Language/phobos) +* Use our [Bugzilla bug tracker](http://d.puremagic.com/issues/) +* Follow the [Styleguide](http://dlang.org/dstyle.html) +* Participate in [our forum](http://forum.dlang.org/) +* [Review Queue](http://wiki.dlang.org/Review_Queue). + + +Tips for Development +-------------------- + +1. Build and test (e.g. the regex module) + + rdmd -unittest -main std/regex.d + +2. Do not forget to test your changes. + Aim for a [high code coverage of your tests](http://forum.dlang.org/thread/ki5ovr$17m1$1@digitalmars.com). + +3. Do not forget the [API Documentation](http://dlang.org/phobos/). diff --git a/README.md b/README.md new file mode 100644 index 000000000..291f6b1d2 --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +![D Logo](http://dlang.org/images/dlogo.png) Phobos Standard Library +=================================================================== + +Phobos is the standard library that comes with the +[D Programming Language](http://dlang.org) Compiler. + + +* [Bugzilla bug tracker](http://d.puremagic.com/issues/) +* [Forum](http://forum.dlang.org/) +* [API Documentation](http://dlang.org/phobos/) +* [Wiki](http://wiki.dlang.org/) + +Download +-------- + +Phobos is packaged together with the compiler. +You should +[download the whole precompiled package](http://dlang.org/download.html). + +To [build everything yourself](http://wiki.dlang.org/Building_DMD), +there is a [description in the wiki](http://wiki.dlang.org/Building_DMD). + +Phobos is distributed under Boost Software Licence. +See the [licence file](LICENSE_1_0.txt). + +I Want to Contribute +-------------------- + +Great! +See the [CONTRIBUTING.md file](CONTRIBUTING.md). + diff --git a/posix.mak b/posix.mak index 2f1a59f52..63c072a43 100644 --- a/posix.mak +++ b/posix.mak @@ -1,56 +1,77 @@ # Makefile to build linux D runtime library libphobos2.a and its unit test # +# make => makes release build of the library +# # make clean => removes all targets built by the makefile # # make zip => creates a zip file of all the sources (not targets) # referred to by the makefile, including the makefile # -# make release => makes release build of the library (this is also the -# default target) +# make BUILD=debug => makes debug build of the library # -# make debug => makes debug build of the library +# make unittest => builds all unittests (for release) and runs them # -# make unittest => builds all unittests (for both debug and release) -# and runs them +# make BUILD=debug unittest => builds all unittests (for debug) and runs them # # make html => makes html documentation # # make install => copies library to /usr/lib +# +# make unittest/std/somemodule.d => only builds and unittests std.somemodule +# +################################################################################ # Configurable stuff, usually from the command line # -# OS can be linux, win32, win32remote, win32wine, osx, or freebsd. If left -# blank, the system will be determined by using uname +# OS can be linux, win32, win32wine, osx, or freebsd. The system will be +# determined by using uname QUIET:=@ OS:= uname_S:=$(shell uname -s) ifeq (Darwin,$(uname_S)) - OS:=osx + OS:=osx endif ifeq (Linux,$(uname_S)) - OS:=linux + OS:=linux endif ifeq (FreeBSD,$(uname_S)) - OS:=freebsd + OS:=freebsd endif ifeq (OpenBSD,$(uname_S)) - OS:=openbsd + OS:=openbsd endif ifeq (Solaris,$(uname_S)) - OS:=solaris + OS:=solaris endif ifeq (SunOS,$(uname_S)) - OS:=solaris + OS:=solaris endif ifeq (,$(OS)) - $(error Unrecognized or unsupported OS for uname: $(uname_S)) + $(error Unrecognized or unsupported OS for uname: $(uname_S)) endif -MODEL:=default -ifneq (default,$(MODEL)) - MODEL_FLAG:=-m$(MODEL) +ifeq (,$(MODEL)) + uname_M:=$(shell uname -m) + ifeq (x86_64,$(uname_M)) + MODEL=64 + else + ifeq (i686,$(uname_M)) + MODEL=32 + else + $(error Cannot figure 32/64 model from uname -m: $(uname_M)) + endif + endif +endif + +# Default to a release built, override with BUILD=debug +BUILD=release + +ifneq ($(BUILD),release) + ifneq ($(BUILD),debug) + $(error Unrecognized BUILD=$(BUILD), must be 'debug' or 'release') + endif endif override PIC:=$(if $(PIC),-fPIC,) @@ -69,14 +90,9 @@ BIGDOC_OUTPUT_DIR = /tmp SRC_DOCUMENTABLES = index.d $(addsuffix .d,$(STD_MODULES) $(STD_NET_MODULES) $(STD_DIGEST_MODULES) $(EXTRA_DOCUMENTABLES)) STDDOC = $(DOCSRC)/std.ddoc BIGSTDDOC = $(DOCSRC)/std_consolidated.ddoc -DDOCFLAGS=$(MODEL_FLAG) -d -c -o- -version=StdDdoc -I$(DRUNTIME_PATH)/import $(DMDEXTRAFLAGS) - -# BUILD can be debug or release, but is unset by default; recursive -# invocation will set it. See the debug and release targets below. -BUILD = - -# Fetch the makefile name, will use it in recursive calls -MAKEFILE:=$(lastword $(MAKEFILE_LIST)) +# Set DDOC, the documentation generator +DDOC=$(DMD) -m$(MODEL) -w -d -c -o- -version=StdDdoc \ + -I$(DRUNTIME_PATH)/import $(DMDEXTRAFLAGS) # Set DRUNTIME name and full path ifeq (,$(findstring win,$(OS))) @@ -89,27 +105,22 @@ endif # Set CC and DMD ifeq ($(OS),win32wine) CC = wine dmc.exe - DMD ?= wine dmd.exe + DMD = wine dmd.exe RUN = wine else - ifeq ($(OS),win32remote) - DMD ?= ssh 206.125.170.138 "cd code/dmd/phobos && dmd" - CC = ssh 206.125.170.138 "cd code/dmd/phobos && dmc" + DMD = ../dmd/src/dmd + ifeq ($(OS),win32) + CC = dmc else - DMD ?= dmd - ifeq ($(OS),win32) - CC = dmc - else - CC = cc - endif + CC = cc endif RUN = endif # Set CFLAGS -CFLAGS := +CFLAGS= ifneq (,$(filter cc% gcc% clang% icc% egcc%, $(CC))) - CFLAGS += $(MODEL_FLAG) $(PIC) + CFLAGS += -m$(MODEL) -fPIC ifeq ($(BUILD),debug) CFLAGS += -g else @@ -118,7 +129,7 @@ ifneq (,$(filter cc% gcc% clang% icc% egcc%, $(CC))) endif # Set DFLAGS -DFLAGS := -I$(DRUNTIME_PATH)/import $(DMDEXTRAFLAGS) -w -d -property $(MODEL_FLAG) $(PIC) +DFLAGS=-I$(DRUNTIME_PATH)/import $(DMDEXTRAFLAGS) -w -d -m$(MODEL) $(PIC) ifeq ($(BUILD),debug) DFLAGS += -g -debug else @@ -136,40 +147,32 @@ else PATHSEP:=$(shell echo "\\") endif -# Set LINKOPTS -ifeq (,$(findstring win,$(OS))) - ifeq (freebsd,$(OS)) - LINKOPTS=-L-L$(ROOT) - else - LINKOPTS=-L-ldl -L-L$(ROOT) - endif -else - LINKOPTS=-L/co $(LIB) -endif - -# Set DDOC, the documentation generator -DDOC=$(DMD) +LINKDL:=$(if $(findstring $(OS),linux),-L-ldl,) # Set VERSION, where the file is that contains the version string VERSION=../dmd/VERSION -# Set SONAME, the name of the shared library. -# The awk script will produce the last 2 digits of the version string, i.e. 2.063 produces 63 -SONAME = libphobos2.so.0.$(shell awk -F. '{ print $$NF + 0 }' $(VERSION)) - # Set LIB, the ultimate target ifeq (,$(findstring win,$(OS))) - LIB = $(ROOT)/libphobos2.a - LIBSO = $(ROOT)/$(SONAME).0 + LIB:=$(ROOT)/libphobos2.a + # 2.064.2 => libphobos2.so.0.64.2 + # 2.065 => libphobos2.so.0.65.0 + # MAJOR version is 0 for now, which means the ABI is still unstable + MAJOR:=0 + MINOR:=$(shell awk -F. '{ print int($$2) }' $(VERSION)) + PATCH:=$(shell awk -F. '{ print int($$3) }' $(VERSION)) + # SONAME doesn't use patch level (ABI compatible) + SONAME:=libphobos2.so.$(MAJOR).$(MINOR) + LIBSO:=$(ROOT)/$(SONAME).$(PATCH) else - LIB = $(ROOT)/phobos.lib + LIB:=$(ROOT)/phobos.lib endif ################################################################################ MAIN = $(ROOT)/emptymain.d # Stuff in std/ -STD_MODULES = $(addprefix std/, algorithm array ascii base64 bigint \ +STD_MODULES = $(addprefix std/, algorithm array ascii base64 bigint \ bitmanip compiler complex concurrency container conv \ cstream csv datetime demangle encoding exception \ file format functional getopt json math mathspecial md5 \ @@ -202,10 +205,12 @@ EXTRA_MODULES += $(EXTRA_DOCUMENTABLES) $(addprefix \ std/internal/digest/, sha_SSSE3 ) $(addprefix \ std/internal/math/, biguintcore biguintnoasm biguintx86 \ gammafunction errorfunction) $(addprefix std/internal/, \ - processinit uni uni_tab) + processinit uni uni_tab unicode_tables \ + unicode_comp unicode_decomp unicode_grapheme unicode_norm) # Aggregate all D modules relevant to this build -D_MODULES = crc32 $(STD_MODULES) $(EXTRA_MODULES) $(STD_NET_MODULES) $(STD_DIGEST_MODULES) +D_MODULES = crc32 $(STD_MODULES) $(EXTRA_MODULES) $(STD_NET_MODULES) \ + $(STD_DIGEST_MODULES) # Add the .d suffix to the module names D_FILES = $(addsuffix .d,$(D_MODULES)) # Aggregate all D modules over all OSs (this is for the zip file) @@ -230,38 +235,36 @@ ALL_C_FILES = $(C_FILES) $(C_EXTRAS) OBJS = $(addsuffix $(DOTOBJ),$(addprefix $(ROOT)/,$(C_MODULES))) +MAKEFILE = $(firstword $(MAKEFILE_LIST)) + +SUBMAKE = $(MAKE) --no-print-directory OS=$(OS) -f $(MAKEFILE) + ################################################################################ # Rules begin here ################################################################################ -ifeq ($(BUILD),) -# No build was defined, so here we define release and debug -# targets. BUILD is not defined in user runs, only by recursive -# self-invocations. So the targets in this branch are accessible to -# end users. +# Main target (builds the dll on linux, too) ifeq (linux,$(OS)) -release : - $(MAKE) --no-print-directory -f $(MAKEFILE) OS=$(OS) MODEL=$(MODEL) BUILD=release PIC=1 dll - $(MAKE) --no-print-directory -f $(MAKEFILE) OS=$(OS) MODEL=$(MODEL) BUILD=release +all : $(BUILD) $(BUILD)_pic +$(BUILD)_pic : + $(SUBMAKE) MODEL=$(MODEL) BUILD=$(BUILD) PIC=1 dll else -release : - $(MAKE) --no-print-directory -f $(MAKEFILE) OS=$(OS) MODEL=$(MODEL) BUILD=release -endif -debug : - $(MAKE) --no-print-directory -f $(MAKEFILE) OS=$(OS) MODEL=$(MODEL) BUILD=debug -unittest : - $(MAKE) --no-print-directory -f $(MAKEFILE) OS=$(OS) MODEL=$(MODEL) BUILD=debug unittest - $(MAKE) --no-print-directory -f $(MAKEFILE) OS=$(OS) MODEL=$(MODEL) BUILD=release unittest -install : - $(MAKE) --no-print-directory -f $(MAKEFILE) OS=$(OS) MODEL=$(MODEL) BUILD=release INSTALL_DIR=$(INSTALL_DIR) DMD=$(DMD) install2 -else -# This branch is normally taken in recursive builds. All we need to do -# is set the default build to $(BUILD) (which is either debug or -# release) and then let the unittest depend on that build's unittests. -$(BUILD) : $(LIB) -unittest : $(addsuffix $(DOTEXE),$(addprefix $(ROOT)/unittest/,$(D_MODULES))) +all : $(BUILD) endif +install : + $(SUBMAKE) MODEL=$(MODEL) BUILD=release INSTALL_DIR=$(INSTALL_DIR) \ + DMD=$(DMD) install2 + +$(BUILD) : $(LIB) +unittest : $(addsuffix .d,$(addprefix unittest/,$(D_MODULES))) + +depend: $(addprefix $(ROOT)/unittest/,$(addsuffix .deps,$(D_MODULES))) + +-include $(addprefix $(ROOT)/unittest/,$(addsuffix .deps,$(D_MODULES))) + +################################################################################ +# Patterns begin here ################################################################################ $(ROOT)/%$(DOTOBJ) : %.c @@ -274,42 +277,66 @@ $(LIB) : $(OBJS) $(ALL_D_FILES) $(DRUNTIME) dll : $(ROOT)/libphobos2.so $(ROOT)/libphobos2.so: $(ROOT)/$(SONAME) - ln -sf $(notdir $(LIBSO)) $@ + ln -sf $(notdir $(LIBSO)) $@ $(ROOT)/$(SONAME): $(LIBSO) ln -sf $(notdir $(LIBSO)) $@ $(LIBSO): $(OBJS) $(ALL_D_FILES) $(DRUNTIME) - $(DMD) $(DFLAGS) -shared -debuglib= -defaultlib= -of$@ -L-soname=$(SONAME) $(DRUNTIMESO) $(D_FILES) $(OBJS) + $(DMD) $(DFLAGS) -shared -debuglib= -defaultlib= -of$@ -L-soname=$(SONAME) $(DRUNTIMESO) $(LINKDL) $(D_FILES) $(OBJS) ifeq (osx,$(OS)) # Build fat library that combines the 32 bit and the 64 bit libraries -libphobos2.a : generated/osx/release/32/libphobos2.a generated/osx/release/64/libphobos2.a - lipo generated/osx/release/32/libphobos2.a generated/osx/release/64/libphobos2.a -create -output generated/osx/release/libphobos2.a +libphobos2.a: $(ROOT_OF_THEM_ALL)/osx/release/libphobos2.a +$(ROOT_OF_THEM_ALL)/osx/release/libphobos2.a: + $(SUBMAKE) MODEL=32 BUILD=release + $(SUBMAKE) MODEL=64 BUILD=release + lipo $(ROOT_OF_THEM_ALL)/osx/release/32/libphobos2.a \ + $(ROOT_OF_THEM_ALL)/osx/release/64/libphobos2.a \ + -create -output $@ endif $(addprefix $(ROOT)/unittest/,$(DISABLED_TESTS)) : @echo Testing $@ - disabled -$(ROOT)/unittest/%$(DOTEXE) : %.d $(LIB) $(ROOT)/emptymain.d - @echo Testing $@ - $(QUIET)$(DMD) $(DFLAGS) -unittest $(LINKOPTS) $(subst /,$(PATHSEP),"-of$@") \ - $(ROOT)/emptymain.d $< -# make the file very old so it builds and runs again if it fails - @touch -t 197001230123 $@ -# run unittest in its own directory - $(QUIET)$(RUN) $@ -# succeeded, render the file new again - @touch $@ +UT_D_OBJS:=$(addprefix $(ROOT)/unittest/,$(addsuffix .o,$(D_MODULES))) +$(UT_D_OBJS): $(ROOT)/unittest/%.o: %.d + @mkdir -p $(dir $@) + $(DMD) $(DFLAGS) -unittest -c -of$@ -deps=$(@:.o=.deps.tmp) $< + @echo $@: `sed 's|.*(\(.*\)).*|\1|' $(@:.o=.deps.tmp) | sort | uniq` \ + >$(@:.o=.deps) + @rm $(@:.o=.deps.tmp) +# $(DMD) $(DFLAGS) -unittest -c -of$@ $*.d + +ifneq (linux,$(OS)) + +$(ROOT)/unittest/test_runner: $(DRUNTIME_PATH)/src/test_runner.d $(UT_D_OBJS) $(OBJS) $(DRUNTIME) + $(DMD) $(DFLAGS) -unittest -of$@ $(DRUNTIME_PATH)/src/test_runner.d $(UT_D_OBJS) $(OBJS) $(DRUNTIME) -defaultlib= -debuglib= -L-lcurl + +else + +UT_LIBSO:=$(ROOT)/unittest/libphobos2-ut.so + +$(UT_LIBSO): override PIC:=-fPIC +$(UT_LIBSO): $(UT_D_OBJS) $(OBJS) $(DRUNTIMESO) + $(DMD) $(DFLAGS) -shared -unittest -of$@ $(UT_D_OBJS) $(OBJS) $(DRUNTIMESO) $(LINKDL) -defaultlib= -debuglib= -L-lcurl + +$(ROOT)/unittest/test_runner: $(DRUNTIME_PATH)/src/test_runner.d $(UT_LIBSO) + $(DMD) $(DFLAGS) -of$@ $< -L$(UT_LIBSO) -defaultlib= -debuglib= + +endif + +# macro that returns the module name given the src path +moduleName=$(subst /,.,$(1)) + +unittest/%.d : $(ROOT)/unittest/test_runner + $(QUIET)$(RUN) $< $(call moduleName,$*) # Disable implicit rule %$(DOTEXE) : %$(DOTOBJ) -$(ROOT)/emptymain.d : $(ROOT)/.directory - @echo 'void main(){}' >$@ - -$(ROOT)/.directory : - mkdir -p $(ROOT) || exists $(ROOT) +%/.directory : + mkdir -p $* || exists $* touch $@ clean : @@ -321,6 +348,9 @@ zip : install2 : release mkdir -p $(INSTALL_DIR)/lib cp $(LIB) $(INSTALL_DIR)/lib/ +ifneq (,$(findstring $(OS),linux)) + cp -P $(LIBSO) $(ROOT)/$(SONAME) $(ROOT)/libphobos2.so $(INSTALL_DIR)/lib/ +endif mkdir -p $(INSTALL_DIR)/import/etc mkdir -p $(INSTALL_DIR)/import/std cp crc32.d $(INSTALL_DIR)/import/ @@ -328,7 +358,7 @@ install2 : release cp -r etc/* $(INSTALL_DIR)/import/etc/ cp LICENSE_1_0.txt $(INSTALL_DIR)/phobos-LICENSE.txt -$(DRUNTIME) : +$(DRUNTIME) $(DRUNTIMESO) : $(MAKE) -C $(DRUNTIME_PATH) -f posix.mak MODEL=$(MODEL) ########################################################### @@ -343,28 +373,28 @@ $(DOC_OUTPUT_DIR)/. : mkdir -p $@ $(DOC_OUTPUT_DIR)/std_%.html : std/%.d $(STDDOC) - $(DDOC) $(DDOCFLAGS) $(STDDOC) -Df$@ $< + $(DDOC) $(STDDOC) -Df$@ $< $(DOC_OUTPUT_DIR)/std_c_%.html : std/c/%.d $(STDDOC) - $(DDOC) $(DDOCFLAGS) $(STDDOC) -Df$@ $< + $(DDOC) $(STDDOC) -Df$@ $< $(DOC_OUTPUT_DIR)/std_c_linux_%.html : std/c/linux/%.d $(STDDOC) - $(DDOC) $(DDOCFLAGS) $(STDDOC) -Df$@ $< + $(DDOC) $(STDDOC) -Df$@ $< $(DOC_OUTPUT_DIR)/std_c_windows_%.html : std/c/windows/%.d $(STDDOC) - $(DDOC) $(DDOCFLAGS) -Df$@ $< + $(DDOC) -Df$@ $< $(DOC_OUTPUT_DIR)/std_net_%.html : std/net/%.d $(STDDOC) - $(DDOC) $(DDOCFLAGS) $(STDDOC) -Df$@ $< + $(DDOC) $(STDDOC) -Df$@ $< $(DOC_OUTPUT_DIR)/std_digest_%.html : std/digest/%.d $(STDDOC) - $(DDOC) $(DDOCFLAGS) $(STDDOC) -Df$@ $< + $(DDOC) $(STDDOC) -Df$@ $< $(DOC_OUTPUT_DIR)/etc_c_%.html : etc/c/%.d $(STDDOC) - $(DDOC) $(DDOCFLAGS) $(STDDOC) -Df$@ $< + $(DDOC) $(STDDOC) -Df$@ $< $(DOC_OUTPUT_DIR)/%.html : %.d $(STDDOC) - $(DDOC) $(DDOCFLAGS) $(STDDOC) -Df$@ $< + $(DDOC) $(STDDOC) -Df$@ $< html : $(DOC_OUTPUT_DIR)/. $(HTMLS) $(STYLECSS_TGT) @@ -373,9 +403,11 @@ rsync-prerelease : html rsync -avz $(WEBSITE_DIR)/ d-programming@digitalmars.com:data/phobos-prerelase/ html_consolidated : - $(DDOC) $(DDOCFLAGS) -Df$(DOCSRC)/std_consolidated_header.html $(DOCSRC)/std_consolidated_header.dd - $(DDOC) $(DDOCFLAGS) -Df$(DOCSRC)/std_consolidated_footer.html $(DOCSRC)/std_consolidated_footer.dd + $(DDOC) -Df$(DOCSRC)/std_consolidated_header.html $(DOCSRC)/std_consolidated_header.dd + $(DDOC) -Df$(DOCSRC)/std_consolidated_footer.html $(DOCSRC)/std_consolidated_footer.dd $(MAKE) DOC_OUTPUT_DIR=$(BIGDOC_OUTPUT_DIR) STDDOC=$(BIGSTDDOC) html -j 8 cat $(DOCSRC)/std_consolidated_header.html $(BIGHTMLS) \ $(DOCSRC)/std_consolidated_footer.html > $(DOC_OUTPUT_DIR)/std_consolidated.html +############################# + diff --git a/std/algorithm.d b/std/algorithm.d index 8d36c776a..2213898cc 100644 --- a/std/algorithm.d +++ b/std/algorithm.d @@ -10,9 +10,9 @@ $(TR $(TDNW Searching) $(TD $(MYREF all) $(MYREF any) $(MYREF balancedParens) $( boyerMooreFinder) $(MYREF canFind) $(MYREF count) $(MYREF countUntil) $(MYREF commonPrefix) $(MYREF endsWith) $(MYREF find) $(MYREF findAdjacent) $(MYREF findAmong) $(MYREF findSkip) $(MYREF findSplit) -$(MYREF findSplitAfter) $(MYREF findSplitBefore) $(MYREF indexOf) -$(MYREF minCount) $(MYREF minPos) $(MYREF mismatch) $(MYREF skipOver) -$(MYREF startsWith) $(MYREF until) ) +$(MYREF findSplitAfter) $(MYREF findSplitBefore) $(MYREF minCount) +$(MYREF minPos) $(MYREF mismatch) $(MYREF skipOver) $(MYREF startsWith) +$(MYREF until) ) ) $(TR $(TDNW Comparison) $(TD $(MYREF cmp) $(MYREF equal) $(MYREF levenshteinDistance) $(MYREF levenshteinDistanceAndPath) $(MYREF max) @@ -35,15 +35,18 @@ setSymmetricDifference) $(MYREF setUnion) ) ) $(TR $(TDNW Mutation) $(TD $(MYREF bringToFront) $(MYREF copy) $(MYREF fill) $(MYREF initializeAll) $(MYREF move) $(MYREF moveAll) $(MYREF -moveSome) $(MYREF remove) $(MYREF reverse) $(MYREF swap) $(MYREF -swapRanges) $(MYREF uninitializedFill) )) +moveSome) $(MYREF remove) $(MYREF reverse) $(MYREF strip) $(MYREF stripLeft) +$(MYREF stripRight) $(MYREF swap) $(MYREF swapRanges) $(MYREF uninitializedFill) )) ) Implements algorithms oriented mainly towards processing of sequences. Some functions are semantic equivalents or supersets of those found in the $(D $(LESS)_algorithm$(GREATER)) header in $(WEB sgi.com/tech/stl/, Alexander Stepanov's Standard Template Library) for -C++. +C++. Sequences processed by these functions define range-based interfaces. + +$(LINK2 std_range.html, Reference on ranges)$(BR) +$(LINK2 http://ddili.org/ders/d.en/ranges.html, Tutorial on ranges) Many functions in this module are parameterized with a function or a $(GLOSSARY predicate). The predicate may be passed either as a @@ -177,7 +180,7 @@ $(TR $(TDNW $(LREF mismatch)) $(TD $(D mismatch("oh hi", $(LEADINGROW Iteration ) $(TR $(TDNW $(LREF filter)) $(TD $(D filter!"a > 0"([1, -1, 2, -0, -3])) iterates over elements $(D 1), $(D 2), and $(D 0).) +0, -3])) iterates over elements $(D 1) and $(D 2).) ) $(TR $(TDNW $(LREF filterBidirectional)) $(TD Similar to $(D filter), but also provides $(D back) and $(D popBack) at a small @@ -188,7 +191,7 @@ returns a range containing the tuples $(D tuple(5, 1)), $(D tuple(2, 2)), and $(D tuple(3, 2)).) ) $(TR $(TDNW $(LREF joiner)) $(TD $(D joiner(["hello", -"world!"], ";")) returns a range that iterates over the characters $(D +"world!"], "; ")) returns a range that iterates over the characters $(D "hello; world!"). No new string is created - the existing inputs are iterated.) ) @@ -303,6 +306,21 @@ possible from one range to another.) $(TR $(TDNW $(LREF reverse)) $(TD If $(D a = [1, 2, 3]), $(D reverse(a)) changes it to $(D [3, 2, 1]).) ) +$(TR $(TDNW $(LREF strip)) $(TD Strips all leading and trailing +elements equal to a value, or that satisfy a predicate. +If $(D a = [1, 1, 0, 1, 1]), then $(D strip(a, 1)) and $(D strip!(e => e == 1)(a)) +returns $(D [0]).) +) +$(TR $(TDNW $(LREF stripLeft)) $(TD Strips all leading elements equal to a value, +or that satisfy a predicate. +If $(D a = [1, 1, 0, 1, 1]), then $(D stripLeft(a, 1)) and $(D stripLeft!(e => e == 1)(a)) +returns $(D [0, 1, 1]).) +) +$(TR $(TDNW $(LREF stripRight)) $(TD Strips all trailing elements equal to a value, +or that satisfy a predicate. +If $(D a = [1, 1, 0, 1, 1]), then $(D stripRight(a, 1)) and $(D stripRight!(e => e == 1)(a)) +returns $(D [1, 1, 0]).) +) $(TR $(TDNW $(LREF swap)) $(TD Swaps two values.) ) $(TR $(TDNW $(LREF swapRanges)) $(TD Swaps all elements of two @@ -349,6 +367,8 @@ version(unittest) mixin(dummyRanges); } +private T* addressOf(T)(ref T val) { return &val; } + /** $(D auto map(Range)(Range r) if (isInputRange!(Unqual!Range));) @@ -357,36 +377,6 @@ in many languages of functional flavor. The call $(D map!(fun)(range)) returns a range of which elements are obtained by applying $(D fun(x)) left to right for all $(D x) in $(D range). The original ranges are not changed. Evaluation is done lazily. - -Example: ----- -int[] arr1 = [ 1, 2, 3, 4 ]; -int[] arr2 = [ 5, 6 ]; -auto squares = map!(a => a * a)(chain(arr1, arr2)); -assert(equal(squares, [ 1, 4, 9, 16, 25, 36 ])); ----- - -Multiple functions can be passed to $(D map). In that case, the -element type of $(D map) is a tuple containing one element for each -function. - -Example: - ----- -auto arr1 = [ 1, 2, 3, 4 ]; -foreach (e; map!("a + a", "a * a")(arr1)) -{ - writeln(e[0], " ", e[1]); -} ----- - -You may alias $(D map) with some function(s) to a symbol and use -it separately: - ----- -alias map!(to!string) stringize; -assert(equal(stringize([ 1, 2, 3, 4 ]), [ "1", "2", "3", "4" ])); ----- */ template map(fun...) if (fun.length >= 1) { @@ -405,6 +395,44 @@ template map(fun...) if (fun.length >= 1) } } +/// +unittest +{ + int[] arr1 = [ 1, 2, 3, 4 ]; + int[] arr2 = [ 5, 6 ]; + auto squares = map!(a => a * a)(chain(arr1, arr2)); + assert(equal(squares, [ 1, 4, 9, 16, 25, 36 ])); +} + +/** +Multiple functions can be passed to $(D map). In that case, the +element type of $(D map) is a tuple containing one element for each +function. +*/ +unittest +{ + auto sums = [2, 4, 6, 8]; + auto products = [1, 4, 9, 16]; + + size_t i = 0; + foreach (result; [ 1, 2, 3, 4 ].map!("a + a", "a * a")) + { + assert(result[0] == sums[i]); + assert(result[1] == products[i]); + ++i; + } +} + +/** +You may alias $(D map) with some function(s) to a symbol and use +it separately: +*/ +unittest +{ + alias map!(to!string) stringize; + assert(equal(stringize([ 1, 2, 3, 4 ]), [ "1", "2", "3", "4" ])); +} + private struct MapResult(alias fun, Range) { alias Unqual!Range R; @@ -465,7 +493,7 @@ private struct MapResult(alias fun, Range) } } - static if (hasLength!R || isSomeString!R) + static if (hasLength!R) { @property auto length() { @@ -475,16 +503,33 @@ private struct MapResult(alias fun, Range) alias length opDollar; } - static if (!isInfinite!R && hasSlicing!R) + static if (hasSlicing!R) { static if (is(typeof(_input[ulong.max .. ulong.max]))) - private alias ulong opSlice_t; + private alias opSlice_t = ulong; else - private alias uint opSlice_t; + private alias opSlice_t = uint; - auto opSlice(opSlice_t lowerBound, opSlice_t upperBound) + static if (hasLength!R) { - return typeof(this)(_input[lowerBound..upperBound]); + auto opSlice(opSlice_t low, opSlice_t high) + { + return typeof(this)(_input[low .. high]); + } + } + else static if (is(typeof(_input[opSlice_t.max .. $]))) + { + struct DollarToken{} + enum opDollar = DollarToken.init; + auto opSlice(opSlice_t low, DollarToken) + { + return typeof(this)(_input[low .. $]); + } + + auto opSlice(opSlice_t low, opSlice_t high) + { + return this[low .. $].take(high - low); + } } } @@ -609,6 +654,30 @@ unittest assert(equal(m, [1L, 4L, 9L])); } +unittest +{ + // Issue #10130 - map of iota with const step. + const step = 2; + static assert(__traits(compiles, map!(i => i)(iota(0, 10, step)))); + + // Need these to all by const to repro the float case, due to the + // CommonType template used in the float specialization of iota. + const floatBegin = 0.0; + const floatEnd = 1.0; + const floatStep = 0.02; + static assert(__traits(compiles, map!(i => i)(iota(floatBegin, floatEnd, floatStep)))); +} + +unittest +{ + //slicing infinites + auto rr = iota(0, 5).cycle().map!"a * a"(); + alias RR = typeof(rr); + static assert(hasSlicing!RR); + rr = rr[6 .. $]; //Advances 1 cycle and 1 unit + assert(equal(rr[0 .. 5], [1, 4, 9, 16, 0])); +} + /** $(D auto reduce(Args...)(Args args) if (Args.length > 0 && Args.length <= 2 && isIterable!(Args[$ - 1]));) @@ -622,81 +691,7 @@ range), $(D result = fun(result, x)) gets evaluated. Finally, $(D result) is returned. The one-argument version $(D reduce!(fun)(range)) works similarly, but it uses the first element of the range as the seed (the range must be non-empty). - -Many aggregate range operations turn out to be solved with $(D reduce) -quickly and easily. The example below illustrates $(D reduce)'s -remarkable power and flexibility. - -Example: ----- -int[] arr = [ 1, 2, 3, 4, 5 ]; -// Sum all elements -auto sum = reduce!((a,b) => a + b)(0, arr); -assert(sum == 15); - -// Sum again, using a string predicate with "a" and "b" -sum = reduce!"a + b"(0, arr); -assert(sum == 15); - -// Compute the maximum of all elements -auto largest = reduce!(max)(arr); -assert(largest == 5); - -// Max again, but with Uniform Function Call Syntax (UFCS) -largest = arr.reduce!(max); -assert(largest == 5); - -// Compute the number of odd elements -auto odds = reduce!((a,b) => a + (b & 1))(0, arr); -assert(odds == 3); - -// Compute the sum of squares -auto ssquares = reduce!((a,b) => a + b * b)(0, arr); -assert(ssquares == 55); - -// Chain multiple ranges into seed -int[] a = [ 3, 4 ]; -int[] b = [ 100 ]; -auto r = reduce!("a + b")(chain(a, b)); -assert(r == 107); - -// Mixing convertible types is fair game, too -double[] c = [ 2.5, 3.0 ]; -auto r1 = reduce!("a + b")(chain(a, b, c)); -assert(approxEqual(r1, 112.5)); - -// To minimize nesting of parentheses, Uniform Function Call Syntax can be used -auto r2 = chain(a, b, c).reduce!("a + b"); -assert(approxEqual(r2, 112.5)); ----- - -$(DDOC_SECTION_H Multiple functions:) Sometimes it is very useful to -compute multiple aggregates in one pass. One advantage is that the -computation is faster because the looping overhead is shared. That's -why $(D reduce) accepts multiple functions. If two or more functions -are passed, $(D reduce) returns a $(XREF typecons, Tuple) object with -one member per passed-in function. The number of seeds must be -correspondingly increased. - -Example: ----- -double[] a = [ 3.0, 4, 7, 11, 3, 2, 5 ]; -// Compute minimum and maximum in one pass -auto r = reduce!(min, max)(a); -// The type of r is Tuple!(int, int) -assert(approxEqual(r[0], 2)); // minimum -assert(approxEqual(r[1], 11)); // maximum - -// Compute sum and sum of squares in one pass -r = reduce!("a + b", "a + b * b")(tuple(0.0, 0.0), a); -assert(approxEqual(r[0], 35)); // sum -assert(approxEqual(r[1], 233)); // sum of squares -// Compute average and standard deviation from the above -auto avg = r[0] / a.length; -auto stdev = sqrt(r[1] / a.length - avg * avg); ----- */ - template reduce(fun...) if (fun.length >= 1) { auto reduce(Args...)(Args args) @@ -739,11 +734,12 @@ template reduce(fun...) if (fun.length >= 1) else { static assert(fun.length > 1); - typeof(adjoin!(staticMap!(binaryFun, fun))(r.front, r.front)) + Unqual!(typeof(r.front)) seed = r.front; + typeof(adjoin!(staticMap!(binaryFun, fun))(seed, seed)) result = void; foreach (i, T; result.Types) { - emplace(&result[i], r.front); + emplace(&result[i], seed); } r.popFront(); return reduce(result, r); @@ -825,6 +821,80 @@ template reduce(fun...) if (fun.length >= 1) } } +/** +Many aggregate range operations turn out to be solved with $(D reduce) +quickly and easily. The example below illustrates $(D reduce)'s +remarkable power and flexibility. +*/ +unittest +{ + int[] arr = [ 1, 2, 3, 4, 5 ]; + // Sum all elements + auto sum = reduce!((a,b) => a + b)(0, arr); + assert(sum == 15); + + // Sum again, using a string predicate with "a" and "b" + sum = reduce!"a + b"(0, arr); + assert(sum == 15); + + // Compute the maximum of all elements + auto largest = reduce!(max)(arr); + assert(largest == 5); + + // Max again, but with Uniform Function Call Syntax (UFCS) + largest = arr.reduce!(max); + assert(largest == 5); + + // Compute the number of odd elements + auto odds = reduce!((a,b) => a + (b & 1))(0, arr); + assert(odds == 3); + + // Compute the sum of squares + auto ssquares = reduce!((a,b) => a + b * b)(0, arr); + assert(ssquares == 55); + + // Chain multiple ranges into seed + int[] a = [ 3, 4 ]; + int[] b = [ 100 ]; + auto r = reduce!("a + b")(chain(a, b)); + assert(r == 107); + + // Mixing convertible types is fair game, too + double[] c = [ 2.5, 3.0 ]; + auto r1 = reduce!("a + b")(chain(a, b, c)); + assert(approxEqual(r1, 112.5)); + + // To minimize nesting of parentheses, Uniform Function Call Syntax can be used + auto r2 = chain(a, b, c).reduce!("a + b"); + assert(approxEqual(r2, 112.5)); +} + +/** +Sometimes it is very useful to compute multiple aggregates in one pass. +One advantage is that the computation is faster because the looping overhead +is shared. That's why $(D reduce) accepts multiple functions. +If two or more functions are passed, $(D reduce) returns a +$(XREF typecons, Tuple) object with one member per passed-in function. +The number of seeds must be correspondingly increased. +*/ +unittest +{ + double[] a = [ 3.0, 4, 7, 11, 3, 2, 5 ]; + // Compute minimum and maximum in one pass + auto r = reduce!(min, max)(a); + // The type of r is Tuple!(int, int) + assert(approxEqual(r[0], 2)); // minimum + assert(approxEqual(r[1], 11)); // maximum + + // Compute sum and sum of squares in one pass + r = reduce!("a + b", "a + b * b")(tuple(0.0, 0.0), a); + assert(approxEqual(r[0], 35)); // sum + assert(approxEqual(r[1], 233)); // sum of squares + // Compute average and standard deviation from the above + auto avg = r[0] / a.length; + auto stdev = sqrt(r[1] / a.length - avg * avg); +} + unittest { debug(std_algorithm) scope(success) @@ -901,15 +971,18 @@ unittest r = reduce!"a + b"(a, c); } +unittest +{ + // Issue #10408 - Two-function reduce of a const array. + const numbers = [10, 30, 20]; + immutable m = reduce!(min)(numbers); + assert(m == 10); + immutable minmax = reduce!(min, max)(numbers); + assert(minmax == tuple(10, 30)); +} + /** Fills $(D range) with a $(D filler). - -Example: ----- -int[] a = [ 1, 2, 3, 4 ]; -fill(a, 5); -assert(a == [ 5, 5, 5, 5 ]); ----- */ void fill(Range, Value)(Range range, Value filler) if (isInputRange!Range && is(typeof(range.front = filler))) @@ -933,6 +1006,14 @@ void fill(Range, Value)(Range range, Value filler) } } +/// +unittest +{ + int[] a = [ 1, 2, 3, 4 ]; + fill(a, 5); + assert(a == [ 5, 5, 5, 5 ]); +} + unittest { import std.typecons; @@ -960,6 +1041,7 @@ unittest foreach (value; range.arr) assert(value == filler); } + unittest { import std.typecons; @@ -981,6 +1063,7 @@ unittest er8638_1.fill(5); //generic case er8638_2.fill(5); //opSlice(T.init) case } + unittest { { @@ -999,14 +1082,6 @@ unittest Fills $(D range) with a pattern copied from $(D filler). The length of $(D range) does not have to be a multiple of the length of $(D filler). If $(D filler) is empty, an exception is thrown. - -Example: ----- -int[] a = [ 1, 2, 3, 4, 5 ]; -int[] b = [ 8, 9 ]; -fill(a, b); -assert(a == [ 8, 9, 8, 9, 8 ]); ----- */ void fill(Range1, Range2)(Range1 range, Range2 filler) if (isInputRange!Range1 @@ -1075,6 +1150,15 @@ void fill(Range1, Range2)(Range1 range, Range2 filler) } } +/// +unittest +{ + int[] a = [ 1, 2, 3, 4, 5 ]; + int[] b = [ 8, 9 ]; + fill(a, b); + assert(a == [ 8, 9, 8, 9, 8 ]); +} + unittest { import std.typecons; @@ -1126,22 +1210,16 @@ void uninitializedFill(Range, Value)(Range range, Value filler) { alias ElementType!Range T; static if (hasElaborateAssign!T) + { // Must construct stuff by the book for (; !range.empty; range.popFront()) - emplace(&range.front(), filler); + emplace(addressOf(range.front), filler); + } else // Doesn't matter whether fill is initialized or not return fill(range, filler); } -deprecated("Cannot reliably call uninitializedFill on range that does not expose references. Use fill instead.") -void uninitializedFill(Range, Value)(Range range, Value filler) - if (isInputRange!Range && !hasLvalueElements!Range && is(typeof(range.front = filler))) -{ - static assert(hasElaborateAssign!T, "Cannot execute uninitializedFill a range that does not expose references, and whose objects have an elaborate assign."); - return fill(range, filler); -} - /** Initializes all elements of a range with their $(D .init) value. Assumes that the range does not currently contain meaningful @@ -1172,13 +1250,13 @@ void initializeAll(Range)(Range range) auto p = typeid(T).init().ptr; if (p) for ( ; !range.empty ; range.popFront() ) - memcpy(&range.front(), p, T.sizeof); + memcpy(addressOf(range.front), p, T.sizeof); else static if (isDynamicArray!Range) memset(range.ptr, 0, range.length * T.sizeof); else for ( ; !range.empty ; range.popFront() ) - memset(&range.front(), 0, T.sizeof); + memset(addressOf(range.front), 0, T.sizeof); } else fill(range, T.init); @@ -1194,7 +1272,7 @@ void initializeAll(Range)(Range range) unittest { - import std.typecons; + import std.typecons; debug(std_algorithm) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done."); @@ -1228,12 +1306,12 @@ unittest static struct S3 { int i; - this(this){}; + this(this){} } static struct S4 { int i = 1; - this(this){}; + this(this){} } static assert (!hasElaborateAssign!S1); static assert (!hasElaborateAssign!S2); @@ -1283,30 +1361,6 @@ Implements the homonym function present in various programming languages of functional flavor. The call $(D filter!(predicate)(range)) returns a new range only containing elements $(D x) in $(D range) for which $(D predicate(x)) is $(D true). - -Example: ----- -int[] arr = [ 1, 2, 3, 4, 5 ]; - -// Sum all elements -auto small = filter!(a => a < 3)(arr); -assert(equal(small, [ 1, 2 ])); - -// Sum again, but with Uniform Function Call Syntax (UFCS) -auto sum = arr.filter!(a => a < 3); -assert(equal(sum, [ 1, 2 ])); - -// In combination with chain() to span multiple ranges -int[] a = [ 3, -2, 400 ]; -int[] b = [ 100, -101, 102 ]; -auto r = chain(a, b).filter!(a => a > 0); -assert(equal(r, [ 3, 400, 100, 102 ])); - -// Mixing convertible types is fair game, too -double[] c = [ 2.5, 3.0 ]; -auto r1 = chain(c, a, b).filter!(a => cast(int) a != a); -assert(approxEqual(r1, [ 2.5 ])); ----- */ template filter(alias pred) if (is(typeof(unaryFun!pred))) { @@ -1316,6 +1370,31 @@ template filter(alias pred) if (is(typeof(unaryFun!pred))) } } +/// +unittest +{ + int[] arr = [ 1, 2, 3, 4, 5 ]; + + // Sum all elements + auto small = filter!(a => a < 3)(arr); + assert(equal(small, [ 1, 2 ])); + + // Sum again, but with Uniform Function Call Syntax (UFCS) + auto sum = arr.filter!(a => a < 3); + assert(equal(sum, [ 1, 2 ])); + + // In combination with chain() to span multiple ranges + int[] a = [ 3, -2, 400 ]; + int[] b = [ 100, -101, 102 ]; + auto r = chain(a, b).filter!(a => a > 0); + assert(equal(r, [ 3, 400, 100, 102 ])); + + // Mixing convertible types is fair game, too + double[] c = [ 2.5, 3.0 ]; + auto r1 = chain(c, a, b).filter!(a => cast(int) a != a); + assert(approxEqual(r1, [ 2.5 ])); +} + private struct FilterResult(alias pred, Range) { alias Unqual!Range R; @@ -1358,7 +1437,7 @@ private struct FilterResult(alias pred, Range) { @property auto save() { - return typeof(this)(_input); + return typeof(this)(_input.save); } } } @@ -1460,19 +1539,6 @@ unittest * that the filtered range can be spanned from both directions. Also, * $(XREF range, retro) can be applied against the filtered range. * -Example: ----- -int[] arr = [ 1, 2, 3, 4, 5 ]; -auto small = filterBidirectional!("a < 3")(arr); -assert(small.back == 2); -assert(equal(small, [ 1, 2 ])); -assert(equal(retro(small), [ 2, 1 ])); -// In combination with chain() to span multiple ranges -int[] a = [ 3, -2, 400 ]; -int[] b = [ 100, -101, 102 ]; -auto r = filterBidirectional!("a > 0")(chain(a, b)); -assert(r.back == 102); ----- */ template filterBidirectional(alias pred) { @@ -1482,6 +1548,22 @@ template filterBidirectional(alias pred) } } +/// +unittest +{ + int[] arr = [ 1, 2, 3, 4, 5 ]; + auto small = filterBidirectional!("a < 3")(arr); + static assert(isBidirectionalRange!(typeof(small))); + assert(small.back == 2); + assert(equal(small, [ 1, 2 ])); + assert(equal(retro(small), [ 2, 1 ])); + // In combination with chain() to span multiple ranges + int[] a = [ 3, -2, 400 ]; + int[] b = [ 100, -101, 102 ]; + auto r = filterBidirectional!("a > 0")(chain(a, b)); + assert(r.back == 102); +} + private struct FilterBidiResult(alias pred, Range) { alias Unqual!Range R; @@ -1528,21 +1610,6 @@ private struct FilterBidiResult(alias pred, Range) } } -unittest -{ - int[] arr = [ 1, 2, 3, 4, 5 ]; - auto small = filterBidirectional!("a < 3")(arr); - static assert(isBidirectionalRange!(typeof(small))); - assert(small.back == 2); - assert(equal(small, [ 1, 2 ])); - assert(equal(retro(small), [ 2, 1 ])); - // In combination with chain() to span multiple ranges - int[] a = [ 3, -2, 400 ]; - int[] b = [ 100, -101, 102 ]; - auto r = filterBidirectional!("a > 0")(chain(a, b)); - assert(r.back == 102); -} - // move /** Moves $(D source) into $(D target) via a destructive @@ -1871,31 +1938,43 @@ unittest // swap /** -Swaps $(D lhs) and $(D rhs). See also $(XREF exception, pointsTo). +Swaps $(D lhs) and $(D rhs). The instances $(D lhs) and $(D rhs) are moved in +memory, without ever calling $(D opAssign), nor any other function. $(D T) +need not be assignable at all to be swapped. + +If $(D lhs) and $(D rhs) reference the same instance, then nothing is done. + +$(D lhs) and $(D rhs) must be mutable. If $(D T) is a struct or union, then +its fields must also all be (recursivelly) mutable. Preconditions: $(D !pointsTo(lhs, lhs) && !pointsTo(lhs, rhs) && !pointsTo(rhs, lhs) && !pointsTo(rhs, rhs)) + +See_Also: + $(XREF exception, pointsTo) */ void swap(T)(ref T lhs, ref T rhs) @trusted pure nothrow -if (isMutable!T && !is(typeof(T.init.proxySwap(T.init)))) +if (allMutableFields!T && !is(typeof(T.init.proxySwap(T.init)))) { - static if (hasElaborateAssign!T) + static if (!isAssignable!T || hasElaborateAssign!T) { - if (&lhs != &rhs) { - // For structs with non-trivial assignment, move memory directly - // First check for undue aliasing - assert(!pointsTo(lhs, rhs) && !pointsTo(rhs, lhs) - && !pointsTo(lhs, lhs) && !pointsTo(rhs, rhs)); - // Swap bits - ubyte[T.sizeof] t = void; - auto a = (cast(ubyte*) &lhs)[0 .. T.sizeof]; - auto b = (cast(ubyte*) &rhs)[0 .. T.sizeof]; - t[] = a[]; - a[] = b[]; - b[] = t[]; - } + if (&lhs != &rhs) + { + // For structs with non-trivial assignment, move memory directly + // First check for undue aliasing + static if (hasIndirections!T) + assert(!pointsTo(lhs, rhs) && !pointsTo(rhs, lhs) + && !pointsTo(lhs, lhs) && !pointsTo(rhs, rhs)); + // Swap bits + ubyte[T.sizeof] t = void; + auto a = (cast(ubyte*) &lhs)[0 .. T.sizeof]; + auto b = (cast(ubyte*) &rhs)[0 .. T.sizeof]; + t[] = a[]; + a[] = b[]; + b[] = t[]; + } } else { @@ -1924,6 +2003,36 @@ void swap(T)(T lhs, T rhs) if (is(typeof(T.init.proxySwap(T.init)))) lhs.proxySwap(rhs); } +/+ + Trait like isMutable. It also verifies that the fields inside a value + type aggregate are also mutable. + + A "value type aggregate" is a struct or an union, but not a class nor + an interface. ++/ +private template allMutableFields(T) +{ + alias OT = OriginalType!T; + static if (is(OT == struct) || is(OT == union)) + enum allMutableFields = isMutable!OT && allSatisfy!(.allMutableFields, FieldTypeTuple!OT); + else + enum allMutableFields = isMutable!OT; +} + +unittest +{ + static assert( allMutableFields!int); + static assert(!allMutableFields!(const int)); + + class C{const int i;} + static assert( allMutableFields!C); + + struct S1{int i;} + struct S2{const int i;} + static assert( allMutableFields!S1); + static assert(!allMutableFields!S2); +} + unittest { debug(std_algorithm) scope(success) @@ -1994,6 +2103,30 @@ unittest swap(s, s); } +unittest +{ + static struct NoAssign + { + int i; + void opAssign(NoAssign) @disable; + } + auto s1 = NoAssign(1); + auto s2 = NoAssign(2); + swap(s1, s2); + assert(s1.i == 2); + assert(s2.i == 1); +} + +unittest +{ + struct S + { + const int i; + } + S s; + static assert(!__traits(compiles, swap(s, s))); +} + void swapFront(R1, R2)(R1 r1, R2 r2) if (isInputRange!R1 && isInputRange!R2) { @@ -2011,37 +2144,10 @@ void swapFront(R1, R2)(R1 r1, R2 r2) /** Forwards function arguments with saving ref-ness. - -Example: ---- -int foo(int n) { return 1; } -int foo(ref int n) { return 2; } -int bar()(auto ref int x) { return foo(forward!x); } - -assert(bar(1) == 1); -int i; -assert(bar(i) == 2); ---- - ---- -void foo(int n, ref string s) { s = null; foreach (i; 0..n) s ~= "Hello"; } - -// forwards all arguments which are bound to parameter tuple -void bar(Args...)(auto ref Args args) { return foo(forward!args); } - -// forwards all arguments with swapping order -void baz(Args...)(auto ref Args args) { return foo(forward!args[$/2..$], forward!args[0..$/2]); } - -string s; -bar(1, s); -assert(s == "Hello"); -baz(s, 2); -assert(s == "HelloHello"); ---- */ template forward(args...) { - import std.typecons; + import std.typecons; static if (args.length) { alias arg = args[0]; @@ -2055,6 +2161,7 @@ template forward(args...) alias forward = std.typecons.TypeTuple!(); } +/// unittest { class C @@ -2069,12 +2176,15 @@ unittest assert(bar(i) == 2); } +/// unittest { void foo(int n, ref string s) { s = null; foreach (i; 0..n) s ~= "Hello"; } + // forwards all arguments which are bound to parameter tuple void bar(Args...)(auto ref Args args) { return foo(forward!args); } + // forwards all arguments with swapping order void baz(Args...)(auto ref Args args) { return foo(forward!args[$/2..$], forward!args[0..$/2]); } string s; @@ -2139,20 +2249,6 @@ the split range. If the empty range is given, the result is a range with one empty element. If a range with one separator is given, the result is a range with two empty elements. - -Example: ---- -assert(equal(splitter("hello world", ' '), [ "hello", "", "world" ])); -int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ]; -int[][] w = [ [1, 2], [], [3], [4, 5] ]; -assert(equal(splitter(a, 0), w)); -a = null; -assert(equal(splitter(a, 0), [ (int[]).init ])); -a = [ 0 ]; -assert(equal(splitter(a, 0), [ (int[]).init, (int[]).init ])); -a = [ 0, 1 ]; -assert(equal(splitter(a, 0), [ [], [1] ])); ----- */ auto splitter(Range, Separator)(Range r, Separator s) if (is(typeof(ElementType!Range.init == Separator.init)) @@ -2169,6 +2265,15 @@ if (is(typeof(ElementType!Range.init == Separator.init)) IndexType _frontLength = _unComputed; IndexType _backLength = _unComputed; + static if (isNarrowString!Range) + { + size_t _separatorLength; + } + else + { + enum _separatorLength = 1; + } + static if (isBidirectionalRange!Range) { static IndexType lastIndexOf(Range haystack, Separator needle) @@ -2183,6 +2288,13 @@ if (is(typeof(ElementType!Range.init == Separator.init)) { _input = input; _separator = separator; + + static if (isNarrowString!Range) + { + _separatorLength = codeLength!(ElementEncodingType!Range)(separator); + } + if (_input.empty) + _frontLength = _atEnd; } static if (isInfinite!Range) @@ -2226,8 +2338,7 @@ if (is(typeof(ElementType!Range.init == Separator.init)) } else { - _input = _input[_frontLength .. _input.length]; - skipOver(_input, _separator) || assert(false); + _input = _input[_frontLength + _separatorLength .. _input.length]; _frontLength = _unComputed; } } @@ -2279,15 +2390,7 @@ if (is(typeof(ElementType!Range.init == Separator.init)) } else { - _input = _input[0 .. _input.length - _backLength]; - if (!_input.empty && _input.back == _separator) - { - _input.popBack(); - } - else - { - assert(false); - } + _input = _input[0 .. _input.length - _backLength - _separatorLength]; _backLength = _unComputed; } } @@ -2297,11 +2400,25 @@ if (is(typeof(ElementType!Range.init == Separator.init)) return Result(r, s); } +/// +unittest +{ + assert(equal(splitter("hello world", ' '), [ "hello", "", "world" ])); + int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ]; + int[][] w = [ [1, 2], [], [3], [4, 5], [] ]; + assert(equal(splitter(a, 0), w)); + a = [ 0 ]; + assert(equal(splitter(a, 0), [ (int[]).init, (int[]).init ])); + a = [ 0, 1 ]; + assert(equal(splitter(a, 0), [ [], [1] ])); +} + unittest { debug(std_algorithm) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done."); assert(equal(splitter("hello world", ' '), [ "hello", "", "world" ])); + assert(equal(splitter("žlutoučkýřkůň", 'ř'), [ "žlutoučký", "kůň" ])); int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ]; int[][] w = [ [1, 2], [], [3], [4, 5], [] ]; static assert(isForwardRange!(typeof(splitter(a, 0)))); @@ -2311,7 +2428,7 @@ unittest // } assert(equal(splitter(a, 0), w)); a = null; - assert(equal(splitter(a, 0), [ (int[]).init ][])); + assert(equal(splitter(a, 0), (int[][]).init)); a = [ 0 ]; assert(equal(splitter(a, 0), [ (int[]).init, (int[]).init ][])); a = [ 0, 1 ]; @@ -2375,7 +2492,9 @@ with string types. */ auto splitter(Range, Separator)(Range r, Separator s) if (is(typeof(Range.init.front == Separator.init.front) : bool) - && (hasSlicing!Range || isNarrowString!Range)) + && (hasSlicing!Range || isNarrowString!Range) + && isForwardRange!Separator + && (hasLength!Separator || isNarrowString!Separator)) { static struct Result { @@ -2395,7 +2514,8 @@ if (is(typeof(Range.init.front == Separator.init.front) : bool) if (_frontLength != _frontLength.max) return; assert(!_input.empty); // compute front length - _frontLength = _input.length - find(_input, _separator).length; + _frontLength = (_separator.empty) ? 1 : + _input.length - find(_input, _separator).length; static if (isBidirectionalRange!Range) if (_frontLength == _input.length) _backLength = _frontLength; } @@ -2406,7 +2526,7 @@ if (is(typeof(Range.init.front == Separator.init.front) : bool) if (_backLength != _backLength.max) return; assert(!_input.empty); // compute back length - static if (isBidirectionalRange!Range) + static if (isBidirectionalRange!Range && isBidirectionalRange!Separator) { _backLength = _input.length - find(retro(_input), retro(_separator)).source.length; @@ -2479,8 +2599,8 @@ if (is(typeof(Range.init.front == Separator.init.front) : bool) } } -// Bidirectional functionality as suggested by Brad Roberts. - static if (isBidirectionalRange!Range) + // Bidirectional functionality as suggested by Brad Roberts. + static if (isBidirectionalRange!Range && isBidirectionalRange!Separator) { @property Range back() { @@ -2571,32 +2691,73 @@ unittest assert(equal(sp6, ["", ""][])); } +unittest +{ + // Issue 10773 + auto s = splitter("abc", ""); + assert(s.equal(["a", "b", "c"])); +} + +unittest +{ + // Test by-reference separator + class RefSep { + string _impl; + this(string s) { _impl = s; } + @property empty() { return _impl.empty; } + @property auto front() { return _impl.front; } + void popFront() { _impl = _impl[1..$]; } + @property RefSep save() { return new RefSep(_impl); } + @property auto length() { return _impl.length; } + } + auto sep = new RefSep("->"); + auto data = "i->am->pointing"; + auto words = splitter(data, sep); + assert(words.equal([ "i", "am", "pointing" ])); +} + +///ditto auto splitter(alias isTerminator, Range)(Range input) -if (is(typeof(unaryFun!(isTerminator)(ElementType!(Range).init)))) +if (isForwardRange!Range && is(typeof(unaryFun!isTerminator(input.front)))) { return SplitterResult!(unaryFun!isTerminator, Range)(input); } private struct SplitterResult(alias isTerminator, Range) { + enum fullSlicing = (hasLength!Range && hasSlicing!Range) || isSomeString!Range; + private Range _input; - private size_t _end; + private size_t _end = 0; + static if(!fullSlicing) + private Range _next; + + private void findTerminator() + { + static if (fullSlicing) + { + auto r = find!isTerminator(_input.save); + _end = _input.length - r.length; + } + else + for ( _end = 0; !_next.empty ; _next.popFront) + { + if (isTerminator(_next.front)) + break; + ++_end; + } + } this(Range input) { _input = input; - if (_input.empty) - { - _end = _end.max; - } + static if(!fullSlicing) + _next = _input.save; + + if (!_input.empty) + findTerminator(); else - { - // Chase first terminator - while (_end < _input.length && !isTerminator(_input[_end])) - { - ++_end; - } - } + _end = size_t.max; } static if (isInfinite!Range) @@ -2607,59 +2768,54 @@ private struct SplitterResult(alias isTerminator, Range) { @property bool empty() { - return _end == _end.max; + return _end == size_t.max; } } - @property Range front() + @property auto front() { - assert(!empty); - return _input[0 .. _end]; + version(assert) if (empty) throw new RangeError(); + static if (fullSlicing) + return _input[0 .. _end]; + else + return _input.save.takeExactly(_end); } void popFront() { - assert(!empty); - if (_input.empty) - { - _end = _end.max; - return; - } - // Skip over existing word - _input = _input[_end .. _input.length]; - // Skip terminator - for (;;) + version(assert) if (empty) throw new RangeError(); + + static if (fullSlicing) { + _input = _input[_end .. _input.length]; if (_input.empty) { - // Nothing following the terminator - done - _end = _end.max; + _end = size_t.max; return; } - if (!isTerminator(_input.front)) - { - // Found a legit next field - break; - } _input.popFront(); } - assert(!_input.empty && !isTerminator(_input.front)); - // Prepare _end - _end = 1; - while (_end < _input.length && !isTerminator(_input[_end])) + else { - ++_end; + if (_next.empty) + { + _input = _next; + _end = size_t.max; + return; + } + _next.popFront(); + _input = _next.save; } + findTerminator(); } - static if (isForwardRange!Range) + @property typeof(this) save() { - @property typeof(this) save() - { - auto ret = this; - ret._input = _input.save; - return ret; - } + auto ret = this; + ret._input = _input.save; + static if (!fullSlicing) + ret._next = _next.save; + return ret; } } @@ -2680,22 +2836,18 @@ unittest writeln("unittest @", __FILE__, ":", __LINE__, " done."); void compare(string sentence, string[] witness) { - foreach (word; splitter!"a == ' '"(sentence)) - { - assert(word == witness.front, word); - witness.popFront(); - } - assert(witness.empty, witness[0]); + auto r = splitter!"a == ' '"(sentence); + assert(equal(r.save, witness), format("got: %(%s, %) expected: %(%s, %)", r, witness)); } - compare(" Mary has a little lamb. ", - ["", "Mary", "has", "a", "little", "lamb."]); - compare("Mary has a little lamb. ", - ["Mary", "has", "a", "little", "lamb."]); - compare("Mary has a little lamb.", - ["Mary", "has", "a", "little", "lamb."]); - compare("", []); - compare(" ", [""]); + compare(" Mary has a little lamb. ", + ["", "Mary", "", "has", "a", "little", "lamb.", "", "", ""]); + compare("Mary has a little lamb. ", + ["Mary", "", "has", "a", "little", "lamb.", "", "", ""]); + compare("Mary has a little lamb.", + ["Mary", "", "has", "a", "little", "lamb."]); + compare("", (string[]).init); + compare(" ", ["", ""]); static assert(isForwardRange!(typeof(splitter!"a == ' '"("ABC")))); @@ -2711,10 +2863,45 @@ unittest } } +unittest +{ + struct Entry + { + int low; + int high; + int[][] result; + } + Entry[] entries = [ + Entry(0, 0, []), + Entry(0, 1, [[0]]), + Entry(1, 2, [[], []]), + Entry(2, 7, [[2], [4], [6]]), + Entry(1, 8, [[], [2], [4], [6], []]), + ]; + foreach ( entry ; entries ) + { + auto a = iota(entry.low, entry.high).filter!"true"(); + auto b = splitter!"a%2"(a); + assert(equal!equal(b.save, entry.result), format("got: %(%s, %) expected: %(%s, %)", b, entry.result)); + } +} + +unittest +{ + //@@@6791@@@ + assert(equal(std.array.splitter("là dove terminava quella valle"), ["là", "dove", "terminava", "quella", "valle"])); + assert(equal(splitter!(std.uni.isWhite)("là dove terminava quella valle"), ["là", "dove", "terminava", "quella", "valle"])); + assert(equal(splitter!"a=='本'"("日本語"), ["日", "語"])); +} + +//@@@6730@@@ This exists already in std.array, so this declaration, at best, will only create ambiguity. +//unfortunatly, an alias will conflict with the existing splitter in std.algorithm. +//It needs to be removed. +deprecated("Please use std.array.splitter for string specific splitting") auto splitter(Range)(Range input) if (isSomeString!Range) { - return splitter!(std.uni.isWhite)(input); + return std.array.splitter(input); } unittest @@ -2727,7 +2914,7 @@ unittest lines[1] = "line \ttwo".dup; lines[2] = "yah last line\ryah".dup; foreach (line; lines) { - foreach (word; splitter(strip(line))) { + foreach (word; std.array.splitter(std.string.strip(line))) { if (word in dictionary) continue; // Nothing to do auto newID = dictionary.length; dictionary[to!string(word)] = cast(uint)newID; @@ -2741,23 +2928,78 @@ unittest assert(dictionary["last"]== 4); } +unittest +{ + // Check consistency: + // All flavors of split should produce the same results + foreach (input; [(int[]).init, + [0], + [0, 1, 0], + [1, 1, 0, 0, 1, 1], + ]) + { + foreach (s; [0, 1]) + { + auto result = split(input, s); + + assert(equal(result, split(input, [s])), format(`"[%(%s,%)]"`, split(input, [s]))); + //assert(equal(result, split(input, [s].filter!"true"()))); //Not yet implemented + assert(equal(result, split!((a) => a == s)(input)), text(split!((a) => a == s)(input))); + + //assert(equal!equal(result, split(input.filter!"true"(), s))); //Not yet implemented + //assert(equal!equal(result, split(input.filter!"true"(), [s]))); //Not yet implemented + //assert(equal!equal(result, split(input.filter!"true"(), [s].filter!"true"()))); //Not yet implemented + assert(equal!equal(result, split!((a) => a == s)(input.filter!"true"()))); + + assert(equal(result, splitter(input, s))); + assert(equal(result, splitter(input, [s]))); + //assert(equal(result, splitter(input, [s].filter!"true"()))); //Not yet implemented + assert(equal(result, splitter!((a) => a == s)(input))); + + //assert(equal!equal(result, splitter(input.filter!"true"(), s))); //Not yet implemented + //assert(equal!equal(result, splitter(input.filter!"true"(), [s]))); //Not yet implemented + //assert(equal!equal(result, splitter(input.filter!"true"(), [s].filter!"true"()))); //Not yet implemented + assert(equal!equal(result, splitter!((a) => a == s)(input.filter!"true"()))); + } + } + foreach (input; [string.init, + " ", + " hello ", + "hello hello", + " hello what heck this ? " + ]) + { + foreach (s; [' ', 'h']) + { + auto result = split(input, s); + + assert(equal(result, split(input, [s]))); + //assert(equal(result, split(input, [s].filter!"true"()))); //Not yet implemented + assert(equal(result, split!((a) => a == s)(input))); + + //assert(equal!equal(result, split(input.filter!"true"(), s))); //Not yet implemented + //assert(equal!equal(result, split(input.filter!"true"(), [s]))); //Not yet implemented + //assert(equal!equal(result, split(input.filter!"true"(), [s].filter!"true"()))); //Not yet implemented + assert(equal!equal(result, split!((a) => a == s)(input.filter!"true"()))); + + assert(equal(result, splitter(input, s))); + assert(equal(result, splitter(input, [s]))); + //assert(equal(result, splitter(input, [s].filter!"true"()))); //Not yet implemented + assert(equal(result, splitter!((a) => a == s)(input))); + + //assert(equal!equal(result, splitter(input.filter!"true"(), s))); //Not yet implemented + //assert(equal!equal(result, splitter(input.filter!"true"(), [s]))); //Not yet implemented + //assert(equal!equal(result, splitter(input.filter!"true"(), [s].filter!"true"()))); //Not yet implemented + assert(equal!equal(result, splitter!((a) => a == s)(input.filter!"true"()))); + } + } +} // joiner /** Lazily joins a range of ranges with a separator. The separator itself is a range. If you do not provide a separator, then the ranges are joined directly without anything in between them. -Example: ----- -assert(equal(joiner([""], "xyz"), "")); -assert(equal(joiner(["", ""], "xyz"), "xyz")); -assert(equal(joiner(["", "abc"], "xyz"), "xyzabc")); -assert(equal(joiner(["abc", ""], "xyz"), "abcxyz")); -assert(equal(joiner(["abc", "def"], "xyz"), "abcxyzdef")); -assert(equal(joiner(["Mary", "has", "a", "little", "lamb"], "..."), - "Mary...has...a...little...lamb")); -assert(equal(joiner(["abc", "def"]), "abcdef")); ----- */ auto joiner(RoR, Separator)(RoR r, Separator sep) if (isInputRange!RoR && isInputRange!(ElementType!RoR) @@ -2844,7 +3086,27 @@ if (isInputRange!RoR && isInputRange!(ElementType!RoR) { _items = items; _sep = sep; - mixin(useItem); // _current should be initialized in place + + //mixin(useItem); // _current should be initialized in place + if (_items.empty) + _current = _current.init; // set invalid state + else + { + // If we're exporting .save, we must not consume any of the + // subranges, since RoR.save does not guarantee that the states + // of the subranges are also saved. + static if (isForwardRange!RoR && + isForwardRange!(ElementType!RoR)) + _current = _items.front.save; + else + _current = _items.front; + + if (_current.empty) + { + // No data in the current item - toggle to use the separator + useSeparator(); + } + } } @property auto empty() @@ -2894,6 +3156,7 @@ if (isInputRange!RoR && isInputRange!(ElementType!RoR) return Result(r, sep); } +/// unittest { import std.conv : text; @@ -3032,7 +3295,24 @@ if (isInputRange!RoR && isInputRange!(ElementType!RoR)) this(RoR r) { _items = r; - mixin(prepare); // _current should be initialized in place + //mixin(prepare); // _current should be initialized in place + + // Skip over empty subranges. + while (!_items.empty && _items.front.empty) + _items.popFront(); + + if (_items.empty) + _current = _current.init; // set invalid state + else + { + // We cannot export .save method unless we ensure subranges are not + // consumed when a .save'd copy of ourselves is iterated over. So + // we need to .save each subrange we traverse. + static if (isForwardRange!RoR && isForwardRange!(ElementType!RoR)) + _current = _items.front.save; + else + _current = _items.front; + } } static if (isInfinite!RoR) { @@ -3216,12 +3496,6 @@ akin to the $(WEB wikipedia.org/wiki/_Uniq, _uniq) system utility). Equivalence of elements is assessed by using the predicate $(D pred), by default $(D "a == b"). If the given range is bidirectional, $(D uniq) also yields a bidirectional range. - -Example: ----- -int[] arr = [ 1, 2, 2, 2, 2, 3, 4, 4, 4, 5 ]; -assert(equal(uniq(arr), [ 1, 2, 3, 4, 5 ][])); ----- */ auto uniq(alias pred = "a == b", Range)(Range r) if (isInputRange!Range && is(typeof(binaryFun!pred(r.front, r.front)) == bool)) @@ -3229,6 +3503,13 @@ if (isInputRange!Range && is(typeof(binaryFun!pred(r.front, r.front)) == bool)) return UniqResult!(binaryFun!pred, Range)(r); } +/// +unittest +{ + int[] arr = [ 1, 2, 2, 2, 2, 3, 4, 4, 4, 5 ]; + assert(equal(uniq(arr), [ 1, 2, 3, 4, 5 ][])); +} + private struct UniqResult(alias pred, Range) { Range _input; @@ -3320,13 +3601,6 @@ the predicate $(D pred), by default $(D "a == b"). $(D Group) is an input range if $(D R) is an input range, and a forward range in all other cases. - -Example: ----- -int[] arr = [ 1, 2, 2, 2, 2, 3, 4, 4, 4, 5 ]; -assert(equal(group(arr), [ tuple(1, 1u), tuple(2, 4u), tuple(3, 1u), - tuple(4, 3u), tuple(5, 1u) ][])); ----- */ struct Group(alias pred, R) if (isInputRange!R) { @@ -3392,6 +3666,14 @@ Group!(pred, Range) group(alias pred = "a == b", Range)(Range r) return typeof(return)(r); } +/// +unittest +{ + int[] arr = [ 1, 2, 2, 2, 2, 3, 4, 4, 4, 5 ]; + assert(equal(group(arr), [ tuple(1, 1u), tuple(2, 4u), tuple(3, 1u), + tuple(4, 3u), tuple(5, 1u) ][])); +} + unittest { debug(std_algorithm) scope(success) @@ -3487,10 +3769,10 @@ assert(r == [ 1, 2, 3, 4, 5 ]); Finds an individual element in an input range. Elements of $(D haystack) are compared with $(D needle) by using predicate $(D pred). Performs $(BIGOH walkLength(haystack)) evaluations of $(D -pred). See also $(WEB sgi.com/tech/stl/_find.html, STL's _find). +pred). To _find the last occurence of $(D needle) in $(D haystack), call $(D -find(retro(haystack), needle)). See also $(XREF range, retro). +find(retro(haystack), needle)). See $(XREF range, retro). Params: @@ -3500,7 +3782,7 @@ needle = The element searched for. Constraints: -$(D isInputRange!R && is(typeof(binaryFun!pred(haystack.front, needle) +$(D isInputRange!InputRange && is(typeof(binaryFun!pred(haystack.front, needle) : bool))) Returns: @@ -3509,32 +3791,150 @@ $(D haystack) advanced such that $(D binaryFun!pred(haystack.front, needle)) is $(D true) (if no such position exists, returns $(D haystack) after exhaustion). -Example: - ----- -assert(find("hello, world", ',') == ", world"); -assert(find([1, 2, 3, 5], 4) == []); -assert(find(SList!int(1, 2, 3, 4, 5)[], 4) == SList!int(4, 5)[]); -assert(find!"a > b"([1, 2, 3, 5], 2) == [3, 5]); - -auto a = [ 1, 2, 3 ]; -assert(find(a, 5).empty); // not found -assert(!find(a, 2).empty); // found - -// Case-insensitive find of a string -string[] s = [ "Hello", "world", "!" ]; -assert(!find!("toLower(a) == b")(s, "hello").empty); ----- +See_Also: + $(WEB sgi.com/tech/stl/_find.html, STL's _find) */ -R find(alias pred = "a == b", R, E)(R haystack, E needle) -if (isInputRange!R && - is(typeof(binaryFun!pred(haystack.front, needle)) : bool)) +InputRange find(alias pred = "a == b", InputRange, Element)(InputRange haystack, Element needle) +if (isInputRange!InputRange && + is (typeof(binaryFun!pred(haystack.front, needle)) : bool)) { - for (; !haystack.empty; haystack.popFront()) + alias R = InputRange; + alias E = Element; + alias predFun = binaryFun!pred; + static if (is(typeof(pred == "a == b"))) + enum isDefaultPred = pred == "a == b"; + else + enum isDefaultPred = false; + enum isIntegralNeedle = isSomeChar!E || isIntegral!E || isBoolean!E; + + alias EType = ElementType!R; + + static if (isNarrowString!R) { - if (binaryFun!pred(haystack.front, needle)) break; + alias EEType = ElementEncodingType!R; + alias UEEType = Unqual!EEType; + + //These are two special cases which can search without decoding the UTF stream. + static if (isDefaultPred && isIntegralNeedle) + { + //This special case deals with UTF8 search, when the needle + //is represented by a single code point. + //Note: "needle <= 0x7F" properly handles sign via unsigned promotion + static if (is(UEEType == char)) + { + if (!__ctfe && canSearchInCodeUnits!char(needle)) + { + static R trustedMemchr(ref R haystack, ref E needle) @trusted nothrow pure + { + auto ptr = memchr(haystack.ptr, needle, haystack.length); + return ptr ? + haystack[ptr - haystack.ptr .. $] : + haystack[$ .. $]; + } + return trustedMemchr(haystack, needle); + } + } + + //Ditto, but for UTF16 + static if (is(UEEType == wchar)) + { + if (canSearchInCodeUnits!wchar(needle)) + { + foreach (i, ref EEType e; haystack) + { + if (e == needle) + return haystack[i .. $]; + } + return haystack[$ .. $]; + } + } + } + + //Previous conditonal optimizations did not succeed. Fallback to + //unconditional implementations + static if (isDefaultPred) + { + //In case of default pred, it is faster to do string/string search. + UEEType[is(UEEType == char) ? 4 : 2] buf; + + size_t len = encode(buf, needle); + //TODO: Make find!(R, R) @safe + R trustedFindRR(ref R haystack, UEEType[] needle) @trusted pure + { + return cast(R) std.algorithm.find(haystack, needle); + } + return trustedFindRR(haystack, buf[0 .. len]); + } + else + { + //Explicit pred: we must test each character by the book. + //We choose a manual decoding approach, because it is faster than + //the built-in foreach, or doing a front/popFront for-loop. + immutable len = haystack.length; + size_t i = 0, next = 0; + while (next < len) + { + if (predFun(decode(haystack, next), needle)) + return haystack[i .. $]; + i = next; + } + return haystack[$ .. $]; + } } - return haystack; + else static if (isArray!R) + { + //10403 optimization + static if (isDefaultPred && isIntegral!EType && EType.sizeof == 1 && isIntegralNeedle) + { + R findHelper(ref R haystack, ref E needle) @trusted nothrow pure + { + EType* ptr = null; + //Note: we use "min/max" to handle sign mismatch. + if (min(EType.min, needle) == EType.min && max(EType.max, needle) == EType.max) + ptr = cast(EType*) memchr(haystack.ptr, needle, haystack.length); + + return ptr ? + haystack[ptr - haystack.ptr .. $] : + haystack[$ .. $]; + } + + if (!__ctfe) + return findHelper(haystack, needle); + } + + //Default implementation. + foreach (i, ref e; haystack) + if (predFun(e, needle)) + return haystack[i .. $]; + return haystack[$ .. $]; + } + else + { + //Everything else. Walk. + for ( ; !haystack.empty; haystack.popFront() ) + { + if (predFun(haystack.front, needle)) + break; + } + return haystack; + } +} + +/// +unittest +{ + assert(find("hello, world", ',') == ", world"); + assert(find([1, 2, 3, 5], 4) == []); + assert(equal(find(SList!int(1, 2, 3, 4, 5)[], 4), SList!int(4, 5)[])); + assert(find!"a > b"([1, 2, 3, 5], 2) == [3, 5]); + + auto a = [ 1, 2, 3 ]; + assert(find(a, 5).empty); // not found + assert(!find(a, 2).empty); // found + + // Case-insensitive find of a string + string[] s = [ "Hello", "world", "!" ]; + assert(!find!("toLower(a) == b")(s, "hello").empty); } unittest @@ -3547,6 +3947,90 @@ unittest auto r = find(lst[], 5); assert(equal(r, SList!int(5, 7, 3)[])); assert(find([1, 2, 3, 5], 4).empty); + assert(equal(find!"a>b"("hello", 'k'), "llo")); +} + +@safe pure nothrow unittest +{ + int[] a1 = [1, 2, 3]; + assert(!find ([1, 2, 3], 2).empty); + assert(!find!((a,b)=>a==b)([1, 2, 3], 2).empty); + ubyte[] a2 = [1, 2, 3]; + ubyte b2 = 2; + assert(!find ([1, 2, 3], 2).empty); + assert(!find!((a,b)=>a==b)([1, 2, 3], 2).empty); +} + +@safe pure unittest +{ + foreach(R; TypeTuple!(string, wstring, dstring)) + { + foreach(E; TypeTuple!(char, wchar, dchar)) + { + R r1 = "hello world"; + E e1 = 'w'; + assert(find ("hello world", 'w') == "world"); + assert(find!((a,b)=>a==b)("hello world", 'w') == "world"); + R r2 = "日c語"; + E e2 = 'c'; + assert(find ("日c語", 'c') == "c語"); + assert(find!((a,b)=>a==b)("日c語", 'c') == "c語"); + static if (E.sizeof >= 2) + { + R r3 = "hello world"; + E e3 = 'w'; + assert(find ("日本語", '本') == "本語"); + assert(find!((a,b)=>a==b)("日本語", '本') == "本語"); + } + } + } +} + +unittest +{ + //CTFE + static assert (find("abc", 'b') == "bc"); + static assert (find("日b語", 'b') == "b語"); + static assert (find("日本語", '本') == "本語"); + static assert (find([1, 2, 3], 2) == [2, 3]); + + int[] a1 = [1, 2, 3]; + static assert(find ([1, 2, 3], 2)); + static assert(find!((a,b)=>a==b)([1, 2, 3], 2)); + ubyte[] a2 = [1, 2, 3]; + ubyte b2 = 2; + static assert(find ([1, 2, 3], 2)); + static assert(find!((a,b)=>a==b)([1, 2, 3], 2)); +} + +unittest +{ + void dg() pure @safe nothrow + { + byte[] sarr = [1, 2, 3, 4]; + ubyte[] uarr = [1, 2, 3, 4]; + foreach(arr; TypeTuple!(sarr, uarr)) + { + foreach(T; TypeTuple!(byte, ubyte, int, uint)) + { + assert(find(arr, cast(T) 3) == arr[2 .. $]); + assert(find(arr, cast(T) 9) == arr[$ .. $]); + } + assert(find(arr, 256) == arr[$ .. $]); + } + } + dg(); + assertCTFEable!dg; +} + +unittest +{ + // Bugzilla 11603 + enum Foo : ubyte { A } + assert([Foo.A].find(Foo.A).empty == false); + + ubyte x = 0; + assert([x].find(x).empty == false); } /** @@ -3571,12 +4055,6 @@ Returns: $(D haystack) advanced such that $(D needle) is a prefix of it (if no such position exists, returns $(D haystack) advanced to termination). - ----- -assert(find("hello, world", "World").empty); -assert(find("hello, world", "wo") == "world"); -assert(find([1, 2, 3, 4], SList!(2, 3)[]) == [2, 3, 4]); ----- */ R1 find(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle) if (isForwardRange!R1 && isForwardRange!R2 @@ -3601,6 +4079,14 @@ if (isForwardRange!R1 && isForwardRange!R2 } } +/// +unittest +{ + assert(find("hello, world", "World").empty); + assert(find("hello, world", "wo") == "world"); + assert([1, 2, 3, 4].find(SList!int(2, 3)[]) == [2, 3, 4]); +} + unittest { import std.container; @@ -3904,16 +4390,6 @@ short[]), and conversely a $(D long) can be searched for a $(D float) or a $(D double[]). This makes for efficient searches without the need to coerce one side of the comparison into the other's side type. -Example: ----- -int[] a = [ 1, 4, 2, 3 ]; -assert(find(a, 4) == [ 4, 2, 3 ]); -assert(find(a, [ 1, 4 ]) == [ 1, 4, 2, 3 ]); -assert(find(a, [ 1, 3 ], 4) == tuple([ 4, 2, 3 ], 2)); -// Mixed types allowed if comparable -assert(find(a, 5, [ 1.2, 3.5 ], 2.0, [ 1 ]) == tuple([ 2, 3 ], 3)); ----- - The complexity of the search is $(BIGOH haystack.length * max(needles.length)). (For needles that are individual items, length is considered to be 1.) The strategy used in searching several @@ -3934,6 +4410,17 @@ if (Ranges.length > 1 && is(typeof(startsWith!pred(haystack, needles)))) } } +/// +unittest +{ + int[] a = [ 1, 4, 2, 3 ]; + assert(find(a, 4) == [ 4, 2, 3 ]); + assert(find(a, [ 1, 4 ]) == [ 1, 4, 2, 3 ]); + assert(find(a, [ 1, 3 ], 4) == tuple([ 4, 2, 3 ], 2)); + // Mixed types allowed if comparable + assert(find(a, 5, [ 1.2, 3.5 ], 2.0) == tuple([ 2, 3 ], 3)); +} + unittest { debug(std_algorithm) scope(success) @@ -3948,7 +4435,7 @@ unittest unittest { - import std.typecons; + import std.typecons; debug(std_algorithm) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done."); int[] a = [ 1, 2, 3 ]; @@ -3964,7 +4451,7 @@ unittest assert(find(b, 200).length == b.length - b.length / 4); } -// Case-insensitive find of a string + // Case-insensitive find of a string string[] s = [ "Hello", "world", "!" ]; //writeln(find!("toUpper(a) == toUpper(b)")(s, "hello")); assert(find!("toUpper(a) == toUpper(b)")(s, "hello").length == 3); @@ -3976,7 +4463,7 @@ unittest unittest { - import std.typecons; + import std.typecons; debug(std_algorithm) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done."); int[] a = [ 1, 2, 3, 2, 6 ]; @@ -4014,7 +4501,7 @@ unittest struct BoyerMooreFinder(alias pred, Range) { private: - size_t skip[]; + size_t[] skip; ptrdiff_t[ElementType!(Range)] occ; Range needle; @@ -4150,38 +4637,76 @@ unittest Advances the input range $(D haystack) by calling $(D haystack.popFront) until either $(D pred(haystack.front)), or $(D haystack.empty). Performs $(BIGOH haystack.length) evaluations of $(D -pred). See also $(WEB sgi.com/tech/stl/find_if.html, STL's find_if). +pred). To find the last element of a bidirectional $(D haystack) satisfying -$(D pred), call $(D find!(pred)(retro(haystack))). See also $(XREF +$(D pred), call $(D find!(pred)(retro(haystack))). See $(XREF range, retro). -Example: ----- -auto arr = [ 1, 2, 3, 4, 1 ]; -assert(find!("a > 2")(arr) == [ 3, 4, 1 ]); - -// with predicate alias -bool pred(int x) { return x + 1 > 1.5; } -assert(find!(pred)(arr) == arr); ----- +See_Also: + $(WEB sgi.com/tech/stl/find_if.html, STL's find_if) */ -Range find(alias pred, Range)(Range haystack) if (isInputRange!(Range)) +InputRange find(alias pred, InputRange)(InputRange haystack) +if (isInputRange!InputRange) { - alias unaryFun!(pred) predFun; - for (; !haystack.empty && !predFun(haystack.front); haystack.popFront()) + alias R = InputRange; + alias predFun = unaryFun!pred; + static if (isNarrowString!R) { + immutable len = haystack.length; + size_t i = 0, next = 0; + while (next < len) + { + if (predFun(decode(haystack, next))) + return haystack[i .. $]; + i = next; + } + return haystack[$ .. $]; + } + else static if (!isInfinite!R && hasSlicing!R && is(typeof(haystack[cast(size_t)0 .. $]))) + { + size_t i = 0; + foreach (ref e; haystack) + { + if (predFun(e)) + return haystack[i .. $]; + ++i; + } + return haystack[$ .. $]; + } + else + { + //standard range + for ( ; !haystack.empty; haystack.popFront() ) + { + if (predFun(haystack.front)) + break; + } + return haystack; } - return haystack; } +/// unittest { - //scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done."); - int[] a = [ 1, 2, 3 ]; - assert(find!("a > 2")(a) == [3]); + auto arr = [ 1, 2, 3, 4, 1 ]; + assert(find!("a > 2")(arr) == [ 3, 4, 1 ]); + + // with predicate alias bool pred(int x) { return x + 1 > 1.5; } - assert(find!(pred)(a) == a); + assert(find!(pred)(arr) == arr); +} + +@safe pure unittest +{ + //scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done."); + int[] r = [ 1, 2, 3 ]; + assert(find!(a=>a > 2)(r) == [3]); + bool pred(int x) { return x + 1 > 1.5; } + assert(find!(pred)(r) == r); + + assert(find!(a=>a > 'v')("hello world") == "world"); + assert(find!(a=>a%4 == 0)("日本語") == "本語"); } // findSkip @@ -4190,15 +4715,6 @@ unittest * right after the first occurrence of $(D needle) and returns $(D * true). Otherwise, leaves $(D haystack) as is and returns $(D * false). - * - * Example: ----- -string s = "abcdef"; -assert(findSkip(s, "cd") && s == "ef"); -s = "abcdef"; -assert(!findSkip(s, "cxd") && s == "abcdef"); -assert(findSkip(s, "def") && s.empty); ----- */ bool findSkip(alias pred = "a == b", R1, R2)(ref R1 haystack, R2 needle) if (isForwardRange!R1 && isForwardRange!R2 @@ -4211,6 +4727,7 @@ if (isForwardRange!R1 && isForwardRange!R2 return true; } +/// unittest { string s = "abcdef"; @@ -4252,25 +4769,6 @@ If $(D haystack) is a random-access range, all three components of the tuple have the same type as $(D haystack). Otherwise, $(D haystack) must be a forward range and the type of $(D result[0]) and $(D result[1]) is the same as $(XREF range,takeExactly). - -Example: ----- -auto a = "Carl Sagan Memorial Station"; -auto r = findSplit(a, "Velikovsky"); -assert(r[0] == a); -assert(r[1].empty); -assert(r[2].empty); -r = findSplit(a, " "); -assert(r[0] == "Carl"); -assert(r[1] == " "); -assert(r[2] == "Sagan Memorial Station"); -auto r1 = findSplitBefore(a, "Sagan"); -assert(r1[0] == "Carl ", r1[0]); -assert(r1[1] == "Sagan Memorial Station"); -auto r2 = findSplitAfter(a, "Sagan"); -assert(r2[0] == "Carl Sagan"); -assert(r2[1] == " Memorial Station"); ----- */ auto findSplit(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle) if (isForwardRange!R1 && isForwardRange!R2) @@ -4391,6 +4889,26 @@ if (isForwardRange!R1 && isForwardRange!R2) } } +/// +unittest +{ + auto a = "Carl Sagan Memorial Station"; + auto r = findSplit(a, "Velikovsky"); + assert(r[0] == a); + assert(r[1].empty); + assert(r[2].empty); + r = findSplit(a, " "); + assert(r[0] == "Carl"); + assert(r[1] == " "); + assert(r[2] == "Sagan Memorial Station"); + auto r1 = findSplitBefore(a, "Sagan"); + assert(r1[0] == "Carl ", r1[0]); + assert(r1[1] == "Sagan Memorial Station"); + auto r2 = findSplitAfter(a, "Sagan"); + assert(r2[0] == "Carl Sagan"); + assert(r2[1] == " Memorial Station"); +} + unittest { auto a = [ 1, 2, 3, 4, 5, 6, 7, 8 ]; @@ -4454,20 +4972,6 @@ unittest $(D haystack), then $(D -1) is returned. $(D needles) may be either an element or a range. - - Examples: --------------------- -assert(countUntil("hello world", "world") == 6); -assert(countUntil("hello world", 'r') == 8); -assert(countUntil("hello world", "programming") == -1); -assert(countUntil("日本語", "本語") == 1); -assert(countUntil("日本語", '語') == 2); -assert(countUntil("日本語", "五") == -1); -assert(countUntil("日本語", '五') == -1); -assert(countUntil([0, 7, 12, 22, 9], [12, 22]) == 2); -assert(countUntil([0, 7, 12, 22, 9], 9) == 4); -assert(countUntil!"a > b"([0, 7, 12, 22, 9], 20) == 3); --------------------- +/ ptrdiff_t countUntil(alias pred = "a == b", R, Rs...)(R haystack, Rs needles) if (isForwardRange!R @@ -4553,6 +5057,7 @@ ptrdiff_t countUntil(alias pred = "a == b", R, Rs...)(R haystack, Rs needles) static if (isInfinite!R) assert(0); else return -1; } + /// ditto ptrdiff_t countUntil(alias pred = "a == b", R, N)(R haystack, N needle) if (isInputRange!R && @@ -4562,7 +5067,7 @@ ptrdiff_t countUntil(alias pred = "a == b", R, N)(R haystack, N needle) return countUntil!pred2(haystack); } -//Verify Examples. +/// unittest { assert(countUntil("hello world", "world") == 6); @@ -4576,6 +5081,7 @@ unittest assert(countUntil([0, 7, 12, 22, 9], 9) == 4); assert(countUntil!"a > b"([0, 7, 12, 22, 9], 20) == 3); } + unittest { assert(countUntil("日本語", "") == 0); @@ -4611,13 +5117,6 @@ unittest /++ Returns the number of elements which must be popped from $(D haystack) before $(D pred(haystack.front)) is $(D true). - - Examples: --------------------- -assert(countUntil!(std.uni.isWhite)("hello world") == 5); -assert(countUntil!(std.ascii.isDigit)("hello world") == -1); -assert(countUntil!"a > 20"([0, 7, 12, 22, 9]) == 3); --------------------- +/ ptrdiff_t countUntil(alias pred, R)(R haystack) if (isInputRange!R && @@ -4662,13 +5161,14 @@ ptrdiff_t countUntil(alias pred, R)(R haystack) else return -1; } -//Verify Examples. +/// unittest { assert(countUntil!(std.uni.isWhite)("hello world") == 5); assert(countUntil!(std.ascii.isDigit)("hello world") == -1); assert(countUntil!"a > 20"([0, 7, 12, 22, 9]) == 3); } + unittest { // References @@ -4716,13 +5216,6 @@ enum OpenRight /** Lazily iterates $(D range) until value $(D sentinel) is found, at which point it stops. - -Example: ----- -int[] a = [ 1, 2, 4, 7, 7, 2, 4, 7, 3, 5]; -assert(equal(a.until(7), [1, 2, 4][])); -assert(equal(a.until(7, OpenRight.no), [1, 2, 4, 7][])); ----- */ struct Until(alias pred, Range, Sentinel) if (isInputRange!Range) { @@ -4835,6 +5328,14 @@ until(alias pred, Range) return typeof(return)(range, openRight); } +/// +unittest +{ + int[] a = [ 1, 2, 4, 7, 7, 2, 4, 7, 3, 5]; + assert(equal(a.until(7), [1, 2, 4][])); + assert(equal(a.until(7, OpenRight.no), [1, 2, 4, 7][])); +} + unittest { //scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done."); @@ -4858,21 +5359,6 @@ with multiple of the ranges or elements in $(D withOneOfThese), then the shortest one matches (if there are two which match which are of the same length (e.g. $(D "a") and $(D 'a')), then the left-most of them in the argument list matches). - -Example: ----- -assert(startsWith("abc", "")); -assert(startsWith("abc", "a")); -assert(!startsWith("abc", "b")); -assert(startsWith("abc", 'a', "b") == 1); -assert(startsWith("abc", "b", "a") == 2); -assert(startsWith("abc", "a", "a") == 1); -assert(startsWith("abc", "ab", "a") == 2); -assert(startsWith("abc", "x", "a", "b") == 2); -assert(startsWith("abc", "x", "aa", "ab") == 3); -assert(startsWith("abc", "x", "aaa", "sab") == 0); -assert(startsWith("abc", "x", "aaa", "a", "sab") == 3); ----- */ uint startsWith(alias pred = "a == b", Range, Needles...)(Range doesThisStart, Needles withOneOfThese) if (isInputRange!Range && Needles.length > 1 && @@ -5025,9 +5511,25 @@ if (isInputRange!R && : binaryFun!pred(doesThisStart.front, withThis); } +/// unittest { - import std.typecons; + assert(startsWith("abc", "")); + assert(startsWith("abc", "a")); + assert(!startsWith("abc", "b")); + assert(startsWith("abc", 'a', "b") == 1); + assert(startsWith("abc", "b", "a") == 2); + assert(startsWith("abc", "a", "a") == 1); + assert(startsWith("abc", "ab", "a") == 2); + assert(startsWith("abc", "x", "a", "b") == 2); + assert(startsWith("abc", "x", "aa", "ab") == 3); + assert(startsWith("abc", "x", "aaa", "sab") == 0); + assert(startsWith("abc", "x", "aaa", "a", "sab") == 3); +} + +unittest +{ + import std.typecons; debug(std_algorithm) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done."); @@ -5207,20 +5709,6 @@ unittest /** The reciprocal of $(D startsWith). - -Example: ----- -assert(endsWith("abc", "")); -assert(!endsWith("abc", "b")); -assert(endsWith("abc", "a", 'c') == 2); -assert(endsWith("abc", "c", "a") == 1); -assert(endsWith("abc", "c", "c") == 1); -assert(endsWith("abc", "bc", "c") == 2); -assert(endsWith("abc", "x", "c", "b") == 2); -assert(endsWith("abc", "x", "aa", "bc") == 3); -assert(endsWith("abc", "x", "aaa", "sab") == 0); -assert(endsWith("abc", "x", "aaa", 'c', "sab") == 3); ----- */ uint endsWith(alias pred = "a == b", Range, Needles...)(Range doesThisEnd, Needles withOneOfThese) if (isBidirectionalRange!Range && Needles.length > 1 && @@ -5325,9 +5813,24 @@ if (isBidirectionalRange!R && : binaryFun!pred(doesThisEnd.back, withThis); } +/// unittest { - import std.typecons; + assert(endsWith("abc", "")); + assert(!endsWith("abc", "b")); + assert(endsWith("abc", "a", 'c') == 2); + assert(endsWith("abc", "c", "a") == 1); + assert(endsWith("abc", "c", "c") == 1); + assert(endsWith("abc", "bc", "c") == 2); + assert(endsWith("abc", "x", "c", "b") == 2); + assert(endsWith("abc", "x", "aa", "bc") == 3); + assert(endsWith("abc", "x", "aaa", "sab") == 0); + assert(endsWith("abc", "x", "aaa", 'c', "sab") == 3); +} + +unittest +{ + import std.typecons; debug(std_algorithm) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done."); @@ -5409,11 +5912,7 @@ unittest } /** -Returns the common prefix of two ranges. Example: - ----- -assert(commonPrefix("hello, world", "hello, there") == "hello, "); ----- +Returns the common prefix of two ranges. If the first argument is a string, then the result is a slice of $(D r1) which contains the characters that both ranges start with. For all other types, the @@ -5454,6 +5953,12 @@ if (isForwardRange!R1 && isInputRange!R2 && } } +/// +unittest +{ + assert(commonPrefix("hello, world", "hello, there") == "hello, "); +} + auto commonPrefix(alias pred, R1, R2)(R1 r1, R2 r2) if (isNarrowString!R1 && isInputRange!R2 && is(typeof(binaryFun!pred(r1.front, r2.front)))) @@ -5507,7 +6012,7 @@ if (isNarrowString!R1 && isNarrowString!R2) unittest { - import std.typecons; + import std.typecons; assert(commonPrefix([1, 2, 3], [1, 2, 3, 4, 5]) == [1, 2, 3]); assert(commonPrefix([1, 2, 3, 4, 5], [1, 2, 3]) == [1, 2, 3]); assert(commonPrefix([1, 2, 3, 4], [1, 2, 3, 4]) == [1, 2, 3, 4]); @@ -5568,17 +6073,10 @@ unittest /** Advances $(D r) until it finds the first two adjacent elements $(D a), $(D b) that satisfy $(D pred(a, b)). Performs $(BIGOH r.length) -evaluations of $(D pred). See also $(WEB -sgi.com/tech/stl/adjacent_find.html, STL's adjacent_find). +evaluations of $(D pred). -Example: ----- -int[] a = [ 11, 10, 10, 9, 8, 8, 7, 8, 9 ]; -auto r = findAdjacent(a); -assert(r == [ 10, 10, 9, 8, 8, 7, 8, 9 ]); -p = findAdjacent!("a < b")(a); -assert(p == [ 7, 8, 9 ]); ----- +See_Also: + $(WEB sgi.com/tech/stl/adjacent_find.html, STL's adjacent_find) */ Range findAdjacent(alias pred = "a == b", Range)(Range r) if (isForwardRange!(Range)) @@ -5595,6 +6093,17 @@ Range findAdjacent(alias pred = "a == b", Range)(Range r) return ahead; } +/// +unittest +{ + int[] a = [ 11, 10, 10, 9, 8, 8, 7, 8, 9 ]; + auto r = findAdjacent(a); + assert(r == [ 10, 10, 9, 8, 8, 7, 8, 9 ]); + auto p = findAdjacent!("a < b")(a); + assert(p == [ 7, 8, 9 ]); + +} + unittest { //scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done."); @@ -5625,15 +6134,10 @@ unittest Advances $(D seq) by calling $(D seq.popFront) until either $(D find!(pred)(choices, seq.front)) is $(D true), or $(D seq) becomes empty. Performs $(BIGOH seq.length * choices.length) evaluations of -$(D pred). See also $(WEB sgi.com/tech/stl/find_first_of.html, STL's -find_first_of). +$(D pred). -Example: ----- -int[] a = [ -1, 0, 1, 2, 3, 4, 5 ]; -int[] b = [ 3, 1, 2 ]; -assert(findAmong(a, b) == a[2 .. $]); ----- +See_Also: + $(WEB sgi.com/tech/stl/find_first_of.html, STL's find_first_of) */ Range1 findAmong(alias pred = "a == b", Range1, Range2)( Range1 seq, Range2 choices) @@ -5645,6 +6149,14 @@ Range1 findAmong(alias pred = "a == b", Range1, Range2)( return seq; } +/// +unittest +{ + int[] a = [ -1, 0, 1, 2, 3, 4, 5 ]; + int[] b = [ 3, 1, 2 ]; + assert(findAmong(a, b) == a[2 .. $]); +} + unittest { //scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done."); @@ -5673,22 +6185,6 @@ true). Performs $(BIGOH r.length) evaluations of $(D pred). Note: Regardless of the overload, $(D count) will not accept infinite ranges for $(D haystack). - -Example: ----- -// count elements in range -int[] a = [ 1, 2, 4, 3, 2, 5, 3, 2, 4 ]; -assert(count(a, 2) == 3); -assert(count!("a > b")(a, 2) == 5); -// count range in range -assert(count("abcadfabf", "ab") == 2); -assert(count("ababab", "abab") == 1); -assert(count("ababab", "abx") == 0); -// fuzzy count range in range -assert(count!"std.uni.toLower(a) == std.uni.toLower(b)"("AbcAdFaBf", "ab") == 2); -// count predicate in range -assert(count!("a > 1")(a) == 8); ----- */ size_t count(alias pred = "a == b", Range, E)(Range haystack, E needle) if (isInputRange!Range && !isInfinite!Range && @@ -5698,6 +6194,23 @@ size_t count(alias pred = "a == b", Range, E)(Range haystack, E needle) return count!pred2(haystack); } +/// +unittest +{ + // count elements in range + int[] a = [ 1, 2, 4, 3, 2, 5, 3, 2, 4 ]; + assert(count(a, 2) == 3); + assert(count!("a > b")(a, 2) == 5); + // count range in range + assert(count("abcadfabf", "ab") == 2); + assert(count("ababab", "abab") == 1); + assert(count("ababab", "abx") == 0); + // fuzzy count range in range + assert(count!"std.uni.toLower(a) == std.uni.toLower(b)"("AbcAdFaBf", "ab") == 2); + // count predicate in range + assert(count!("a > 1")(a) == 8); +} + unittest { import std.conv : text; @@ -5748,14 +6261,6 @@ size_t count(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle) } } -unittest -{ - assert(count("abcadfabf", "ab") == 2); - assert(count("ababab", "abab") == 1); - assert(count("ababab", "abx") == 0); - assert(count!"std.uni.toLower(a) == std.uni.toLower(b)"("AbcAdFaBf", "ab") == 2); -} - /// Ditto size_t count(alias pred = "true", R)(R haystack) if (isInputRange!R && !isInfinite!R && @@ -5784,20 +6289,7 @@ of $(D lPar) are closed by corresponding instances of $(D rPar). The parameter $(D maxNestingLevel) controls the nesting level allowed. The most common uses are the default or $(D 0). In the latter case, no nesting is allowed. - -Example: ----- -auto s = "1 + $(LPAREN)2 * (3 + 1 / 2)"; -assert(!balancedParens(s, '(', ')')); -s = "1 + (2 * (3 + 1) / 2)"; -assert(balancedParens(s, '(', ')')); -s = "1 + (2 * (3 + 1) / 2)"; -assert(!balancedParens(s, '(', ')', 1)); -s = "1 + (2 * 3 + 1) / (2 - 5)"; -assert(balancedParens(s, '(', ')', 1)); ----- */ - bool balancedParens(Range, E)(Range r, E lPar, E rPar, size_t maxNestingLevel = size_t.max) if (isInputRange!(Range) && is(typeof(r.front == lPar))) @@ -5819,6 +6311,7 @@ if (isInputRange!(Range) && is(typeof(r.front == lPar))) return count == 0; } +/// unittest { auto s = "1 + (2 * (3 + 1 / 2)"; @@ -5837,24 +6330,10 @@ Returns $(D true) if and only if the two ranges compare equal element for element, according to binary predicate $(D pred). The ranges may have different element types, as long as $(D pred(a, b)) evaluates to $(D bool) for $(D a) in $(D r1) and $(D b) in $(D r2). Performs -$(BIGOH min(r1.length, r2.length)) evaluations of $(D pred). See also -$(WEB sgi.com/tech/stl/_equal.html, STL's _equal). +$(BIGOH min(r1.length, r2.length)) evaluations of $(D pred). -Example: ----- -int[] a = [ 1, 2, 4, 3 ]; -assert(!equal(a, a[1..$])); -assert(equal(a, a)); - -// different types -double[] b = [ 1.0, 2, 4, 3]; -assert(!equal(a, b[1..$])); -assert(equal(a, b)); - -// predicated: ensure that two vectors are approximately equal -double[] c = [ 1.005, 2, 4, 3]; -assert(equal!(approxEqual)(b, c)); ----- +See_Also: + $(WEB sgi.com/tech/stl/_equal.html, STL's _equal) */ bool equal(Range1, Range2)(Range1 r1, Range2 r2) if (isInputRange!Range1 && isInputRange!Range2 @@ -5906,23 +6385,30 @@ bool equal(alias pred, Range1, Range2)(Range1 r1, Range2 r2) } } +/// unittest { - import std.math; + import std.math; debug(std_algorithm) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done."); - int[] a = [ 1, 2, 4, 3]; + int[] a = [ 1, 2, 4, 3 ]; assert(!equal(a, a[1..$])); assert(equal(a, a)); - // test with different types + + // different types double[] b = [ 1.0, 2, 4, 3]; assert(!equal(a, b[1..$])); assert(equal(a, b)); - // predicated + // predicated: ensure that two vectors are approximately equal double[] c = [ 1.005, 2, 4, 3]; assert(equal!(approxEqual)(b, c)); +} +unittest +{ + debug(std_algorithm) scope(success) + writeln("unittest @", __FILE__, ":", __LINE__, " done."); // various strings assert(equal("æøå", "æøå")); //UTF8 vs UTF8 assert(!equal("???", "æøå")); //UTF8 vs UTF8 @@ -5952,7 +6438,10 @@ unittest equal!equal(["hello", "world"], ["hello"d, "world"d]); //Tests, with more fancy map ranges + int[] a = [ 1, 2, 4, 3 ]; assert(equal([2, 4, 8, 6], map!"a*2"(a))); + double[] b = [ 1.0, 2, 4, 3]; + double[] c = [ 1.005, 2, 4, 3]; assert(equal!approxEqual(map!"a*2"(b), map!"a*2"(c))); assert(!equal([2, 4, 1, 3], map!"a*2"(a))); assert(!equal([2, 4, 1], map!"a*2"(a))); @@ -5989,7 +6478,6 @@ elements. If the ranges are strings, $(D cmp) performs UTF decoding appropriately and compares the ranges one code point at a time. */ - int cmp(alias pred = "a < b", R1, R2)(R1 r1, R2 r2) if (isInputRange!R1 && isInputRange!R2 && !(isSomeString!R1 && isSomeString!R2)) { @@ -6034,7 +6522,16 @@ int cmp(alias pred = "a < b", R1, R2)(R1 r1, R2 r2) if (isSomeString!R1 && isSom static if (typeof(r1[0]).sizeof == 1) { immutable len = min(r1.length, r2.length); - immutable result = std.c.string.memcmp(r1.ptr, r2.ptr, len); + immutable result = __ctfe ? + { + foreach (i; 0 .. len) + { + if (r1[i] != r2[i]) + return threeWayInt(r1[i], r2[i]); + } + return 0; + }() + : std.c.string.memcmp(r1.ptr, r2.ptr, len); if (result) return result; } else @@ -6208,19 +6705,6 @@ template MaxType(T...) /** Returns the maximum of the passed-in values. The type of the result is computed by using $(XREF traits, CommonType). - -Example: ----- -int a = 5; -short b = 6; -double c = 2; -auto d = max(a, b); -assert(is(typeof(d) == int)); -assert(d == 6); -auto e = min(a, b, c); -assert(is(typeof(e) == double)); -assert(e == 2); ----- */ MaxType!(T1, T2, T) max(T1, T2, T...)(T1 a, T2 b, T xs) if (is(typeof(a < b))) @@ -6245,6 +6729,20 @@ MaxType!(T1, T2, T) max(T1, T2, T...)(T1 a, T2 b, T xs) } } +/// +unittest +{ + int a = 5; + short b = 6; + double c = 2; + auto d = max(a, b); + assert(is(typeof(d) == int)); + assert(d == 6); + auto e = min(a, b, c); + assert(is(typeof(e) == double)); + assert(e == 2); +} + unittest { debug(std_algorithm) scope(success) @@ -6281,61 +6779,169 @@ Returns the minimum element of a range together with the number of occurrences. The function can actually be used for counting the maximum or any other ordering predicate (that's why $(D maxCount) is not provided). - -Example: ----- -int[] a = [ 2, 3, 4, 1, 2, 4, 1, 1, 2 ]; -// Minimum is 1 and occurs 3 times -assert(minCount(a) == tuple(1, 3)); -// Maximum is 4 and occurs 2 times -assert(minCount!("a > b")(a) == tuple(4, 2)); ----- */ Tuple!(ElementType!Range, size_t) minCount(alias pred = "a < b", Range)(Range range) if (isInputRange!Range && !isInfinite!Range && is(typeof(binaryFun!pred(range.front, range.front)))) { + alias T = ElementType!Range; + alias UT = Unqual!T; + alias RetType = Tuple!(T, size_t); + + static assert (is(typeof(RetType(range.front, 1))), + format("Error: Cannot call minCount on a %s, because it is not possible " + "to copy the result value (a %s) into a Tuple.", Range.stringof, T.stringof)); + enforce(!range.empty, "Can't count elements from an empty range"); size_t occurrences = 1; - auto v = range.front; - for (range.popFront(); !range.empty; range.popFront()) + + static if (isForwardRange!Range) { - auto v2 = range.front; - if (binaryFun!pred(v, v2)) continue; - if (binaryFun!pred(v2, v)) + Range least = range.save; + for (range.popFront(); !range.empty; range.popFront()) { - // change the min - move(v2, v); - occurrences = 1; - } - else - { - ++occurrences; + if (binaryFun!pred(least.front, range.front)) continue; + if (binaryFun!pred(range.front, least.front)) + { + // change the min + least = range.save; + occurrences = 1; + } + else + ++occurrences; } + return RetType(least.front, occurrences); } - return typeof(return)(v, occurrences); + else static if (isAssignable!(UT, T) || (isAssignable!UT && !hasElaborateAssign!UT)) + { + UT v = UT.init; + static if (isAssignable!(UT, T)) v = range.front; + else v = cast(UT)range.front; + + for (range.popFront(); !range.empty; range.popFront()) + { + if (binaryFun!pred(*cast(T*)&v, range.front)) continue; + if (binaryFun!pred(range.front, *cast(T*)&v)) + { + // change the min + static if (isAssignable!(UT, T)) v = range.front; + else v = cast(UT)range.front; //Safe because !hasElaborateAssign!UT + occurrences = 1; + } + else + ++occurrences; + } + return RetType(*cast(T*)&v, occurrences); + } + else static if (hasLvalueElements!Range) + { + T* p = &(range.front()); + for (range.popFront(); !range.empty; range.popFront()) + { + if (binaryFun!pred(*p, range.front)) continue; + if (binaryFun!pred(range.front, *p)) + { + // change the min + p = &(range.front()); + occurrences = 1; + } + else + ++occurrences; + } + return RetType(*p, occurrences); + } + else + static assert(false, + format("Sorry, can't find the minCount of a %s: Don't know how " + "to keep track of the smallest %s element.", Range.stringof, T.stringof)); } +/// unittest { import std.conv : text; debug(std_algorithm) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done."); int[] a = [ 2, 3, 4, 1, 2, 4, 1, 1, 2 ]; + // Minimum is 1 and occurs 3 times assert(minCount(a) == tuple(1, 3)); + // Maximum is 4 and occurs 2 times assert(minCount!("a > b")(a) == tuple(4, 2)); +} + +unittest +{ + debug(std_algorithm) scope(success) + writeln("unittest @", __FILE__, ":", __LINE__, " done."); int[][] b = [ [4], [2, 4], [4], [4] ]; auto c = minCount!("a[0] < b[0]")(b); assert(c == tuple([2, 4], 1), text(c[0])); //Test empty range - assertThrown(minCount(a[$..$])); + assertThrown(minCount(b[$..$])); //test with reference ranges. Test both input and forward. assert(minCount(new ReferenceInputRange!int([1, 2, 1, 0, 2, 0])) == tuple(0, 2)); assert(minCount(new ReferenceForwardRange!int([1, 2, 1, 0, 2, 0])) == tuple(0, 2)); +} +unittest +{ + debug(std_algorithm) scope(success) + writeln("unittest @", __FILE__, ":", __LINE__, " done."); + + static struct R(T) //input range + { + T[] a; + bool empty() @property{return a.empty;} + ref T front() @property{return a.front;} + void popFront() {a.popFront();} + } + + immutable a = [ 2, 3, 4, 1, 2, 4, 1, 1, 2 ]; + R!(immutable int) b = R!(immutable int)(a); + + assert(minCount(a) == tuple(1, 3)); + assert(minCount(b) == tuple(1, 3)); + assert(minCount!((ref immutable int a, ref immutable int b) => (a > b))(a) == tuple(4, 2)); + assert(minCount!((ref immutable int a, ref immutable int b) => (a > b))(b) == tuple(4, 2)); + + immutable(int[])[] c = [ [4], [2, 4], [4], [4] ]; + assert(minCount!("a[0] < b[0]")(c) == tuple([2, 4], 1), text(c[0])); + + static struct S1 + { + int i; + } + alias IS1 = immutable(S1); + static assert( isAssignable!S1); + static assert( isAssignable!(S1, IS1)); + + static struct S2 + { + int* p; + this(ref immutable int i) immutable {p = &i;} + this(ref int i) {p = &i;} + @property ref inout(int) i() inout {return *p;} + bool opEquals(const S2 other) const {return i == other.i;} + } + alias IS2 = immutable(S2); + static assert( isAssignable!S2); + static assert(!isAssignable!(S2, IS2)); + static assert(!hasElaborateAssign!S2); + + foreach (Type; TypeTuple!(S1, immutable(S1), S2, immutable(S2))) + { + static if (is(Type == immutable)) alias V = immutable int; + else alias V = int; + V one = 1, two = 2; + auto r1 = [Type(two), Type(one), Type(one)]; + auto r2 = R!Type(r1); + assert(minCount!"a.i < b.i"(r1) == tuple(Type(one), 2)); + assert(minCount!"a.i < b.i"(r2) == tuple(Type(one), 2)); + assert(one == 1 && two == 2); + } } // minPos @@ -6345,15 +6951,6 @@ range), i.e. a subrange of $(D range) starting at the position of its smallest element and with the same ending as $(D range). The function can actually be used for counting the maximum or any other ordering predicate (that's why $(D maxPos) is not provided). - -Example: ----- -int[] a = [ 2, 3, 4, 1, 2, 4, 1, 1, 2 ]; -// Minimum is 1 and first occurs in position 3 -assert(minPos(a) == [ 1, 2, 4, 1, 1, 2 ]); -// Maximum is 4 and first occurs in position 2 -assert(minPos!("a > b")(a) == [ 4, 1, 2, 4, 1, 1, 2 ]); ----- */ Range minPos(alias pred = "a < b", Range)(Range range) if (isForwardRange!Range && !isInfinite!Range && @@ -6374,16 +6971,21 @@ Range minPos(alias pred = "a < b", Range)(Range range) return result; } +/// +unittest +{ + int[] a = [ 2, 3, 4, 1, 2, 4, 1, 1, 2 ]; + // Minimum is 1 and first occurs in position 3 + assert(minPos(a) == [ 1, 2, 4, 1, 1, 2 ]); + // Maximum is 4 and first occurs in position 2 + assert(minPos!("a > b")(a) == [ 4, 1, 2, 4, 1, 1, 2 ]); +} + unittest { debug(std_algorithm) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done."); int[] a = [ 2, 3, 4, 1, 2, 4, 1, 1, 2 ]; - // Minimum is 1 and first occurs in position 3 - assert(minPos(a) == [ 1, 2, 4, 1, 1, 2 ]); - // Maximum is 4 and first occurs in position 5 - assert(minPos!("a > b")(a) == [ 4, 1, 2, 4, 1, 1, 2 ]); - //Test that an empty range works int[] b = a[$..$]; assert(equal(minPos(b), b)); @@ -6391,6 +6993,7 @@ unittest //test with reference range. assert( equal( minPos(new ReferenceForwardRange!int([1, 2, 1, 0, 2, 0])), [0, 2, 0] ) ); } + unittest { //Rvalue range @@ -6402,6 +7005,7 @@ unittest .minPos() .equal([ 1, 2, 4, 1, 1, 2 ])); } + unittest { //BUG 9299 @@ -6423,19 +7027,11 @@ Sequentially compares elements in $(D r1) and $(D r2) in lockstep, and stops at the first mismatch (according to $(D pred), by default equality). Returns a tuple with the reduced ranges that start with the two mismatched values. Performs $(BIGOH min(r1.length, r2.length)) -evaluations of $(D pred). See also $(WEB -sgi.com/tech/stl/_mismatch.html, STL's _mismatch). +evaluations of $(D pred). -Example: ----- -int[] x = [ 1, 5, 2, 7, 4, 3 ]; -double[] y = [ 1.0, 5, 2, 7.3, 4, 8 ]; -auto m = mismatch(x, y); -assert(m[0] == x[3 .. $]); -assert(m[1] == y[3 .. $]); ----- +See_Also: + $(WEB sgi.com/tech/stl/_mismatch.html, STL's _mismatch) */ - Tuple!(Range1, Range2) mismatch(alias pred = "a == b", Range1, Range2)(Range1 r1, Range2 r2) if (isInputRange!(Range1) && isInputRange!(Range2)) @@ -6447,16 +7043,20 @@ mismatch(alias pred = "a == b", Range1, Range2)(Range1 r1, Range2 r2) return tuple(r1, r2); } +/// +unittest +{ + int[] x = [ 1, 5, 2, 7, 4, 3 ]; + double[] y = [ 1.0, 5, 2, 7.3, 4, 8 ]; + auto m = mismatch(x, y); + assert(m[0] == x[3 .. $]); + assert(m[1] == y[3 .. $]); +} + unittest { debug(std_algorithm) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done."); - // doc example - int[] x = [ 1, 5, 2, 7, 4, 3 ]; - double[] y = [ 1.0, 5, 2, 7.3, 4, 8 ]; - auto m = mismatch(x, y); - assert(m[0] == [ 7, 4, 3 ]); - assert(m[1] == [ 7.3, 4, 8 ]); int[] a = [ 1, 2, 3 ]; int[] b = [ 1, 2, 4, 5 ]; @@ -6588,7 +7188,7 @@ private: void AllocMatrix(size_t r, size_t c) { rows = r; cols = c; - if (!_matrix || _matrix.length < r || _matrix[0].length < c) { + if (_matrix.length < r || _matrix[0].length < c) { delete _matrix; _matrix = new CostType[][](r, c); InitMatrix(); @@ -6599,7 +7199,7 @@ private: foreach (i, row; _matrix) { row[0] = i * _deletionIncrement; } - if (!_matrix) return; + if (!_matrix.length) return; for (auto i = 0u; i != _matrix[0].length; ++i) { _matrix[0][i] = i * _insertionIncrement; } @@ -6624,16 +7224,6 @@ distance) between $(D s) and $(D t). The Levenshtein distance computes the minimal amount of edit operations necessary to transform $(D s) into $(D t). Performs $(BIGOH s.length * t.length) evaluations of $(D equals) and occupies $(BIGOH s.length * t.length) storage. - -Example: ----- -assert(levenshteinDistance("cat", "rat") == 1); -assert(levenshteinDistance("parks", "spark") == 2); -assert(levenshteinDistance("kitten", "sitting") == 3); -// ignore case -assert(levenshteinDistance!("std.uni.toUpper(a) == std.uni.toUpper(b)") - ("parks", "SPARK") == 2); ----- */ size_t levenshteinDistance(alias equals = "a == b", Range1, Range2) (Range1 s, Range2 t) @@ -6643,27 +7233,19 @@ size_t levenshteinDistance(alias equals = "a == b", Range1, Range2) return lev.distance(s, t); } -//Verify Examples. +/// unittest { assert(levenshteinDistance("cat", "rat") == 1); assert(levenshteinDistance("parks", "spark") == 2); assert(levenshteinDistance("kitten", "sitting") == 3); - assert(levenshteinDistance!("std.uni.toUpper(a) == std.uni.toUpper(b)") + assert(levenshteinDistance!((a, b) => std.uni.toUpper(a) == std.uni.toUpper(b)) ("parks", "SPARK") == 2); } /** Returns the Levenshtein distance and the edit path between $(D s) and $(D t). - -Example: ---- -string a = "Saturday", b = "Sunday"; -auto p = levenshteinDistanceAndPath(a, b); -assert(p[0] == 3); -assert(equal(p[1], "nrrnsnnn")); ---- */ Tuple!(size_t, EditOp[]) levenshteinDistanceAndPath(alias equals = "a == b", Range1, Range2) @@ -6675,6 +7257,15 @@ levenshteinDistanceAndPath(alias equals = "a == b", Range1, Range2) return tuple(d, lev.path()); } +/// +unittest +{ + string a = "Saturday", b = "Sunday"; + auto p = levenshteinDistanceAndPath(a, b); + assert(p[0] == 3); + assert(equal(p[1], "nrrnsnnn")); +} + unittest { debug(std_algorithm) scope(success) @@ -6685,55 +7276,15 @@ unittest assert(levenshteinDistance("aa", "abc") == 2); assert(levenshteinDistance("Saturday", "Sunday") == 3); assert(levenshteinDistance("kitten", "sitting") == 3); - //lev.deletionIncrement = 2; - //lev.insertionIncrement = 100; - string a = "Saturday", b = "Sunday"; - auto p = levenshteinDistanceAndPath(a, b); - assert(cast(string) p[1] == "nrrnsnnn"); } // copy /** Copies the content of $(D source) into $(D target) and returns the -remaining (unfilled) part of $(D target). See also $(WEB -sgi.com/tech/stl/_copy.html, STL's _copy). If a behavior similar to -$(WEB sgi.com/tech/stl/copy_backward.html, STL's copy_backward) is -needed, use $(D copy(retro(source), retro(target))). See also $(XREF -range, retro). - -Example: ----- -int[] a = [ 1, 5 ]; -int[] b = [ 9, 8 ]; -int[] c = new int[a.length + b.length + 10]; -auto d = copy(b, copy(a, c)); -assert(c[0 .. a.length + b.length] == a ~ b); -assert(d.length == 10); ----- - -As long as the target range elements support assignment from source -range elements, different types of ranges are accepted. - -Example: ----- -float[] a = [ 1.0f, 5 ]; -double[] b = new double[a.length]; -auto d = copy(a, b); ----- - -To copy at most $(D n) elements from range $(D a) to range $(D b), you -may want to use $(D copy(take(a, n), b)). To copy those elements from -range $(D a) that satisfy predicate $(D pred) to range $(D b), you may -want to use $(D copy(filter!(pred)(a), b)). - -Example: ----- -int[] a = [ 1, 5, 8, 9, 10, 1, 2, 0 ]; -auto b = new int[a.length]; -auto c = copy(filter!("(a & 1) == 1")(a), b); -assert(b[0 .. $ - c.length] == [ 1, 5, 9, 1 ]); ----- +remaining (unfilled) part of $(D target). +See_Also: + $(WEB sgi.com/tech/stl/_copy.html, STL's _copy) */ Range2 copy(Range1, Range2)(Range1 source, Range2 target) if (isInputRange!Range1 && isOutputRange!(Range2, ElementType!Range1)) @@ -6787,18 +7338,59 @@ if (isInputRange!Range1 && isOutputRange!(Range2, ElementType!Range1)) } } +/// +unittest +{ + int[] a = [ 1, 5 ]; + int[] b = [ 9, 8 ]; + int[] c = new int[a.length + b.length + 10]; + auto d = copy(b, copy(a, c)); + assert(c[0 .. a.length + b.length] == a ~ b); + assert(d.length == 10); +} + +/** +As long as the target range elements support assignment from source +range elements, different types of ranges are accepted. +*/ +unittest +{ + float[] a = [ 1.0f, 5 ]; + double[] b = new double[a.length]; + auto d = copy(a, b); +} + +/** +To copy at most $(D n) elements from range $(D a) to range $(D b), you +may want to use $(D copy(take(a, n), b)). To copy those elements from +range $(D a) that satisfy predicate $(D pred) to range $(D b), you may +want to use $(D copy(a.filter!(pred), b)). +*/ +unittest +{ + int[] a = [ 1, 5, 8, 9, 10, 1, 2, 0 ]; + auto b = new int[a.length]; + auto c = copy(a.filter!(a => (a & 1) == 1), b); + assert(b[0 .. $ - c.length] == [ 1, 5, 9, 1 ]); +} + +/** +$(XREF range, retro) can be used to achieve behavior similar to +$(WEB sgi.com/tech/stl/copy_backward.html, STL's copy_backward'). +*/ +unittest +{ + import std.algorithm, std.range; + int[] src = [1, 2, 4]; + int[] dst = [0, 0, 0, 0, 0]; + copy(src.retro, dst.retro); + assert(dst == [0, 0, 1, 2, 4]); +} + unittest { debug(std_algorithm) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done."); - { - int[] a = [ 1, 5 ]; - int[] b = [ 9, 8 ]; - int[] c = new int[a.length + b.length + 10]; - auto d = copy(b, copy(a, c)); - assert(c[0 .. a.length + b.length] == a ~ b); - assert(d.length == 10); - } { int[] a = [ 1, 5 ]; int[] b = [ 9, 8 ]; @@ -6831,16 +7423,6 @@ Returns a tuple containing the remainder portions of $(D r1) and $(D r2) that were not swapped (one of them will be empty). The ranges may be of different types but must have the same element type and support swapping. - -Example: ----- -int[] a = [ 100, 101, 102, 103 ]; -int[] b = [ 0, 1, 2, 3 ]; -auto c = swapRanges(a[1 .. 3], b[2 .. 4]); -assert(c[0].empty && c[1].empty); -assert(a == [ 100, 2, 3, 103 ]); -assert(b == [ 0, 1, 101, 102 ]); ----- */ Tuple!(Range1, Range2) swapRanges(Range1, Range2)(Range1 r1, Range2 r2) @@ -6855,10 +7437,9 @@ swapRanges(Range1, Range2)(Range1 r1, Range2 r2) return tuple(r1, r2); } +/// unittest { - debug(std_algorithm) scope(success) - writeln("unittest @", __FILE__, ":", __LINE__, " done."); int[] a = [ 100, 101, 102, 103 ]; int[] b = [ 0, 1, 2, 3 ]; auto c = swapRanges(a[1 .. 3], b[2 .. 4]); @@ -6870,14 +7451,10 @@ unittest // reverse /** Reverses $(D r) in-place. Performs $(D r.length / 2) evaluations of $(D -swap). See also $(WEB sgi.com/tech/stl/_reverse.html, STL's _reverse). +swap). -Example: ----- -int[] arr = [ 1, 2, 3 ]; -reverse(arr); -assert(arr == [ 3, 2, 1 ]); ----- +See_Also: + $(WEB sgi.com/tech/stl/_reverse.html, STL's _reverse) */ void reverse(Range)(Range r) if (isBidirectionalRange!Range && !isRandomAccessRange!Range @@ -6892,6 +7469,14 @@ if (isBidirectionalRange!Range && !isRandomAccessRange!Range } } +/// +unittest +{ + int[] arr = [ 1, 2, 3 ]; + reverse(arr); + assert(arr == [ 3, 2, 1 ]); +} + ///ditto void reverse(Range)(Range r) if (isRandomAccessRange!Range && hasLength!Range) @@ -6926,13 +7511,6 @@ unittest Reverses $(D r) in-place, where $(D r) is a narrow string (having elements of type $(D char) or $(D wchar)). UTF sequences consisting of multiple code units are preserved properly. - -Example: ----- -char[] arr = "hello\U00010143\u0100\U00010143".dup; -reverse(arr); -assert(arr == "\U00010143\u0100\U00010143olleh"); ----- */ void reverse(Char)(Char[] s) if (isNarrowString!(Char[]) && !is(Char == const) && !is(Char == immutable)) @@ -6954,6 +7532,14 @@ if (isNarrowString!(Char[]) && !is(Char == const) && !is(Char == immutable)) reverse(r); } +/// +unittest +{ + char[] arr = "hello\U00010143\u0100\U00010143".dup; + reverse(arr); + assert(arr == "\U00010143\u0100\U00010143olleh"); +} + unittest { void test(string a, string b) @@ -6973,6 +7559,134 @@ unittest test("hello\U00010143\u0100\U00010143", "\U00010143\u0100\U00010143olleh"); } +/** + The strip group of functions allow stripping of either leading, trailing, + or both leading and trailing elements. + + The $(D stripLeft) function will strip the $(D front) of the range, + the $(D stripRight) function will strip the $(D back) of the range, + while the $(D strip) function will strip both the $(D front) and $(D back) + of the range. + + Note that the $(D strip) and $(D stripRight) functions require the range to + be a $(LREF BidirectionalRange) range. + + All of these functions come in two varieties: one takes a target element, + where the range will be stripped as long as this element can be found. + The other takes a lambda predicate, where the range will be stripped as + long as the predicate returns true. +*/ +Range strip(Range, E)(Range range, E element) + if (isBidirectionalRange!Range && is(typeof(range.front == element) : bool)) +{ + return range.stripLeft(element).stripRight(element); +} + +/// ditto +Range strip(alias pred, Range)(Range range) + if (isBidirectionalRange!Range && is(typeof(pred(range.back)) : bool)) +{ + return range.stripLeft!pred().stripRight!pred(); +} + +/// ditto +Range stripLeft(Range, E)(Range range, E element) + if (isInputRange!Range && is(typeof(range.front == element) : bool)) +{ + return find!((auto ref a) => a != element)(range); +} + +/// ditto +Range stripLeft(alias pred, Range)(Range range) + if (isInputRange!Range && is(typeof(pred(range.front)) : bool)) +{ + return find!(not!pred)(range); +} + +/// ditto +Range stripRight(Range, E)(Range range, E element) + if (isBidirectionalRange!Range && is(typeof(range.back == element) : bool)) +{ + for (; !range.empty; range.popBack()) + { + if (range.back != element) + break; + } + return range; +} + +/// ditto +Range stripRight(alias pred, Range)(Range range) + if (isBidirectionalRange!Range && is(typeof(pred(range.back)) : bool)) +{ + for (; !range.empty; range.popBack()) + { + if (!pred(range.back)) + break; + } + return range; +} + +/// Strip leading and trailing elements equal to the target element. +@safe pure unittest +{ + assert(" foobar ".strip(' ') == "foobar"); + assert("00223.444500".strip('0') == "223.4445"); + assert("ëëêéüŗōpéêëë".strip('ë') == "êéüŗōpéê"); + assert([1, 1, 0, 1, 1].strip(1) == [0]); + assert([0.0, 0.01, 0.01, 0.0].strip(0).length == 2); +} + +/// Strip leading and trailing elements while the predicate returns true. +@safe pure unittest +{ + assert(" foobar ".strip!(a => a == ' ')() == "foobar"); + assert("00223.444500".strip!(a => a == '0')() == "223.4445"); + assert("ëëêéüŗōpéêëë".strip!(a => a == 'ë')() == "êéüŗōpéê"); + assert([1, 1, 0, 1, 1].strip!(a => a == 1)() == [0]); + assert([0.0, 0.01, 0.5, 0.6, 0.01, 0.0].strip!(a => a < 0.4)().length == 2); +} + +/// Strip leading elements equal to the target element. +@safe pure unittest +{ + assert(" foobar ".stripLeft(' ') == "foobar "); + assert("00223.444500".stripLeft('0') == "223.444500"); + assert("ůůűniçodêéé".stripLeft('ů') == "űniçodêéé"); + assert([1, 1, 0, 1, 1].stripLeft(1) == [0, 1, 1]); + assert([0.0, 0.01, 0.01, 0.0].stripLeft(0).length == 3); +} + +/// Strip leading elements while the predicate returns true. +@safe pure unittest +{ + assert(" foobar ".stripLeft!(a => a == ' ')() == "foobar "); + assert("00223.444500".stripLeft!(a => a == '0')() == "223.444500"); + assert("ůůűniçodêéé".stripLeft!(a => a == 'ů')() == "űniçodêéé"); + assert([1, 1, 0, 1, 1].stripLeft!(a => a == 1)() == [0, 1, 1]); + assert([0.0, 0.01, 0.10, 0.5, 0.6].stripLeft!(a => a < 0.4)().length == 2); +} + +/// Strip trailing elements equal to the target element. +@safe pure unittest +{ + assert(" foobar ".stripRight(' ') == " foobar"); + assert("00223.444500".stripRight('0') == "00223.4445"); + assert("ùniçodêéé".stripRight('é') == "ùniçodê"); + assert([1, 1, 0, 1, 1].stripRight(1) == [1, 1, 0]); + assert([0.0, 0.01, 0.01, 0.0].stripRight(0).length == 3); +} + +/// Strip trailing elements while the predicate returns true. +@safe pure unittest +{ + assert(" foobar ".stripRight!(a => a == ' ')() == " foobar"); + assert("00223.444500".stripRight!(a => a == '0')() == "00223.4445"); + assert("ùniçodêéé".stripRight!(a => a == 'é')() == "ùniçodê"); + assert([1, 1, 0, 1, 1].stripRight!(a => a == 1)() == [1, 1, 0]); + assert([0.0, 0.01, 0.10, 0.5, 0.6].stripRight!(a => a > 0.4)().length == 3); +} + // bringToFront /** The $(D bringToFront) function has considerable flexibility and @@ -6987,41 +7701,8 @@ range such that all elements in $(D back) are brought to the beginning of the unified range. The relative ordering of elements in $(D front) and $(D back), respectively, remains unchanged. -The simplest use of $(D bringToFront) is for rotating elements in a -buffer. For example: - ----- -auto arr = [4, 5, 6, 7, 1, 2, 3]; -bringToFront(arr[0 .. 4], arr[4 .. $]); -assert(arr == [ 1, 2, 3, 4, 5, 6, 7 ]); ----- - -The $(D front) range may actually "step over" the $(D back) -range. This is very useful with forward ranges that cannot compute -comfortably right-bounded subranges like $(D arr[0 .. 4]) above. In -the example below, $(D r2) is a right subrange of $(D r1). - ----- -auto list = SList!(int)(4, 5, 6, 7, 1, 2, 3); -auto r1 = list[]; -auto r2 = list[]; popFrontN(r2, 4); -assert(equal(r2, [ 1, 2, 3 ])); -bringToFront(r1, r2); -assert(equal(list[], [ 1, 2, 3, 4, 5, 6, 7 ])); ----- - -Elements can be swapped across ranges of different types: - ----- -auto list = SList!(int)(4, 5, 6, 7); -auto vec = [ 1, 2, 3 ]; -bringToFront(list[], vec); -assert(equal(list[], [ 1, 2, 3, 4 ])); -assert(equal(vec, [ 5, 6, 7 ])); ----- - Performs $(BIGOH max(front.length, back.length)) evaluations of $(D -swap). See also $(WEB sgi.com/tech/stl/_rotate.html, STL's rotate). +swap). Preconditions: @@ -7033,6 +7714,9 @@ Returns: The number of elements brought to the front, i.e., the length of $(D back). + +See_Also: + $(WEB sgi.com/tech/stl/_rotate.html, STL's rotate) */ size_t bringToFront(Range1, Range2)(Range1 front, Range2 back) if (isInputRange!Range1 && isForwardRange!Range2) @@ -7094,34 +7778,53 @@ size_t bringToFront(Range1, Range2)(Range1 front, Range2 back) return result; } +/** +The simplest use of $(D bringToFront) is for rotating elements in a +buffer. For example: +*/ +unittest +{ + auto arr = [4, 5, 6, 7, 1, 2, 3]; + auto p = bringToFront(arr[0 .. 4], arr[4 .. $]); + assert(p == arr.length - 4); + assert(arr == [ 1, 2, 3, 4, 5, 6, 7 ]); +} + +/** +The $(D front) range may actually "step over" the $(D back) +range. This is very useful with forward ranges that cannot compute +comfortably right-bounded subranges like $(D arr[0 .. 4]) above. In +the example below, $(D r2) is a right subrange of $(D r1). +*/ +unittest +{ + auto list = SList!(int)(4, 5, 6, 7, 1, 2, 3); + auto r1 = list[]; + auto r2 = list[]; popFrontN(r2, 4); + assert(equal(r2, [ 1, 2, 3 ])); + bringToFront(r1, r2); + assert(equal(list[], [ 1, 2, 3, 4, 5, 6, 7 ])); +} + + +/** +Elements can be swapped across ranges of different types: +*/ +unittest +{ + auto list = SList!(int)(4, 5, 6, 7); + auto vec = [ 1, 2, 3 ]; + bringToFront(list[], vec); + assert(equal(list[], [ 1, 2, 3, 4 ])); + assert(equal(vec, [ 5, 6, 7 ])); +} + unittest { import std.container; import std.conv : text; debug(std_algorithm) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done."); - // doc example - { - int[] arr = [4, 5, 6, 7, 1, 2, 3]; - auto p = bringToFront(arr[0 .. 4], arr[4 .. $]); - assert(p == arr.length - 4); - assert(arr == [ 1, 2, 3, 4, 5, 6, 7 ], text(arr)); - } - { - auto list = SList!(int)(4, 5, 6, 7, 1, 2, 3); - auto r1 = list[]; - auto r2 = list[]; popFrontN(r2, 4); - assert(equal(r2, [ 1, 2, 3 ])); - bringToFront(r1, r2); - assert(equal(list[], [ 1, 2, 3, 4, 5, 6, 7 ])); - } - { - auto list = SList!(int)(4, 5, 6, 7); - auto vec = [ 1, 2, 3 ]; - bringToFront(list[], vec); - assert(equal(list[], [ 1, 2, 3, 4 ])); - assert(equal(vec, [ 5, 6, 7 ])); - } // a more elaborate test { auto rnd = Random(unpredictableSeed); @@ -7307,120 +8010,89 @@ cases.)) Range remove (SwapStrategy s = SwapStrategy.stable, Range, Offset...) (Range range, Offset offset) -if (isBidirectionalRange!Range && hasLength!Range && s != SwapStrategy.stable +if (s != SwapStrategy.stable + && isBidirectionalRange!Range && hasLength!Range && Offset.length >= 1) { - enum bool tupleLeft = is(typeof(offset[0][0])) - && is(typeof(offset[0][1])); - enum bool tupleRight = is(typeof(offset[$ - 1][0])) - && is(typeof(offset[$ - 1][1])); - static if (!tupleLeft) + Tuple!(size_t, "pos", size_t, "len")[offset.length] blackouts; + foreach (i, v; offset) { - alias offset[0] lStart; - auto lEnd = lStart + 1; - } - else - { - auto lStart = offset[0][0]; - auto lEnd = offset[0][1]; - } - static if (!tupleRight) - { - alias offset[$ - 1] rStart; - auto rEnd = rStart + 1; - } - else - { - auto rStart = offset[$ - 1][0]; - auto rEnd = offset[$ - 1][1]; - } - // Begin. Test first to see if we need to remove the rightmost - // element(s) in the range. In that case, life is simple - chop - // and recurse. - if (rEnd == range.length) - { - // must remove the last elements of the range - range.popBackN(rEnd - rStart); - static if (Offset.length > 1) + static if (is(typeof(v[0]) : size_t) && is(typeof(v[1]) : size_t)) { - return .remove!(s, Range, Offset[0 .. $ - 1]) - (range, offset[0 .. $ - 1]); + blackouts[i].pos = v[0]; + blackouts[i].len = v[1] - v[0]; } else { - return range; + static assert(is(typeof(v) : size_t), typeof(v).stringof); + blackouts[i].pos = v; + blackouts[i].len = 1; + } + static if (i > 0) + { + enforce(blackouts[i - 1].pos + blackouts[i - 1].len + <= blackouts[i].pos, + "remove(): incorrect ordering of elements to remove"); } } - // Ok, there are "live" elements at the end of the range - auto t = range; - auto lDelta = lEnd - lStart, rDelta = rEnd - rStart; - auto rid = min(lDelta, rDelta); - foreach (i; 0 .. rid) + size_t left = 0, right = offset.length - 1; + auto tgt = range.save; + size_t steps = 0; + + while (left <= right) { - move(range.back, t.front); - range.popBack(); - t.popFront(); - } - if (rEnd - rStart == lEnd - lStart) - { - // We got rid of both left and right - static if (Offset.length > 2) + // Look for a blackout on the right + if (blackouts[right].pos + blackouts[right].len >= range.length) { - return .remove!(s, Range, Offset[1 .. $ - 1]) - (range, offset[1 .. $ - 1]); + range.popBackN(blackouts[right].len); + + // Since right is unsigned, we must check for this case, otherwise + // we might turn it into size_t.max and the loop condition will not + // fail when it should. + if (right > 0) + { + --right; + continue; + } + else + break; } - else + // Advance to next blackout on the left + assert(blackouts[left].pos >= steps); + tgt.popFrontN(blackouts[left].pos - steps); + steps = blackouts[left].pos; + auto toMove = min( + blackouts[left].len, + range.length - (blackouts[right].pos + blackouts[right].len)); + foreach (i; 0 .. toMove) { - return range; - } - } - else if (rEnd - rStart < lEnd - lStart) - { - // We got rid of the entire right subrange - static if (Offset.length > 2) - { - return .remove!(s, Range) - (range, tuple(lStart + rid, lEnd), - offset[1 .. $ - 1]); - } - else - { - auto tmp = tuple(lStart + rid, lEnd); - return .remove!(s, Range, typeof(tmp)) - (range, tmp); - } - } - else - { - // We got rid of the entire left subrange - static if (Offset.length > 2) - { - return .remove!(s, Range) - (range, offset[1 .. $ - 1], - tuple(rStart, lEnd - rid)); - } - else - { - auto tmp = tuple(rStart, lEnd - rid); - return .remove!(s, Range, typeof(tmp)) - (range, tmp); + move(range.back, tgt.front); + range.popBack(); + tgt.popFront(); + } + steps += toMove; + if (toMove == blackouts[left].len) + { + // Filled the entire left hole + ++left; + continue; } } + + return range; } // Ditto Range remove (SwapStrategy s = SwapStrategy.stable, Range, Offset...) (Range range, Offset offset) -if ((isForwardRange!Range && !isBidirectionalRange!Range - || !hasLength!Range || s == SwapStrategy.stable) - && Offset.length >= 1) +if (s == SwapStrategy.stable && isForwardRange!Range && Offset.length >= 1) { auto result = range; auto src = range, tgt = range; size_t pos; - foreach (i; offset) + foreach (pass, i; offset) { static if (is(typeof(i[0])) && is(typeof(i[1]))) { @@ -7431,10 +8103,20 @@ if ((isForwardRange!Range && !isBidirectionalRange!Range auto from = i; enum delta = 1; } - assert(pos <= from); - for (; pos < from; ++pos, src.popFront(), tgt.popFront()) + enforce(pos <= from, + "remove(): incorrect ordering of elements to remove"); + if (pass > 0) { - move(src.front, tgt.front); + for (; pos < from; ++pos, src.popFront(), tgt.popFront()) + { + move(src.front, tgt.front); + } + } + else + { + src.popFrontN(from); + tgt.popFrontN(from); + pos = from; } // now skip source to the "to" position src.popFrontN(delta); @@ -7446,6 +8128,16 @@ if ((isForwardRange!Range && !isBidirectionalRange!Range return result; } +unittest +{ + // http://d.puremagic.com/issues/show_bug.cgi?id=10173 + int[] test = iota(0, 10).array(); + assertThrown(remove!(SwapStrategy.stable)(test, tuple(2, 4), tuple(1, 3))); + assertThrown(remove!(SwapStrategy.unstable)(test, tuple(2, 4), tuple(1, 3))); + assertThrown(remove!(SwapStrategy.stable)(test, 2, 4, 1, 3)); + assertThrown(remove!(SwapStrategy.unstable)(test, 2, 4, 1, 3)); +} + unittest { debug(std_algorithm) scope(success) @@ -7458,11 +8150,15 @@ unittest a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]; assert(remove!(SwapStrategy.unstable)(a, 0, 10) == - [ 9, 1, 2, 3, 4, 5, 6, 7, 8 ]); + [ 9, 1, 2, 3, 4, 5, 6, 7, 8 ]); a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]; assert(remove!(SwapStrategy.unstable)(a, 0, tuple(9, 11)) == [ 8, 1, 2, 3, 4, 5, 6, 7 ]); + // http://d.puremagic.com/issues/show_bug.cgi?id=5224 + a = [ 1, 2, 3, 4 ]; + assert(remove!(SwapStrategy.unstable)(a, 2) == + [ 1, 2, 4 ]); a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]; //writeln(remove!(SwapStrategy.stable)(a, 1, 5)); @@ -7480,6 +8176,18 @@ unittest a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]; assert(remove!(SwapStrategy.stable)(a, 1, tuple(3, 5)) == [ 0, 2, 5, 6, 7, 8, 9, 10]); + + a = iota(0, 10).array(); + assert(remove!(SwapStrategy.unstable)(a, tuple(1, 4), tuple(6, 7)) + == [0, 9, 8, 7, 4, 5]); +} + +unittest +{ + // Issue 11576 + auto arr = [1,2,3]; + arr = arr.remove!(SwapStrategy.unstable)(2); + assert(arr == [1,2]); } /** @@ -7489,13 +8197,7 @@ elements are moved from the right end of the range over the elements to eliminate. If $(D s = SwapStrategy.stable) (the default), elements are moved progressively to front such that their relative order is preserved. Returns the filtered range. - -Example: ----- -int[] a = [ 1, 2, 3, 2, 3, 4, 5, 2, 5, 6 ]; -assert(remove!("a == 2")(a) == [ 1, 3, 3, 4, 5, 5, 6 ]); ----- - */ +*/ Range remove(alias pred, SwapStrategy s = SwapStrategy.stable, Range) (Range range) if (isBidirectionalRange!Range) @@ -7505,7 +8207,7 @@ if (isBidirectionalRange!Range) { for (;!range.empty;) { - if (!unaryFun!(pred)(range.front)) + if (!unaryFun!pred(range.front)) { range.popFront(); continue; @@ -7534,6 +8236,13 @@ if (isBidirectionalRange!Range) return result; } +/// +unittest +{ + int[] a = [ 1, 2, 3, 2, 3, 4, 5, 2, 5, 6 ]; + assert(remove!("a == 2")(a) == [ 1, 3, 3, 4, 5, 5, 6 ]); +} + unittest { debug(std_algorithm) scope(success) @@ -7627,9 +8336,6 @@ swap). The unstable version computes the minimum possible evaluations of $(D swap) (roughly half of those performed by the semistable version). -See also STL's $(WEB sgi.com/tech/stl/_partition.html, _partition) and -$(WEB sgi.com/tech/stl/stable_partition.html, stable_partition). - Returns: The right part of $(D r) after partitioning. @@ -7640,41 +8346,9 @@ $(D pred(a) == pred(b)). If $(D ss == SwapStrategy.semistable), $(D partition) preserves the relative ordering of all elements $(D a), $(D b) in the left part of $(D r) for which $(D pred(a) == pred(b)). -Example: - ----- -auto Arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; -auto arr = Arr.dup; -static bool even(int a) { return (a & 1) == 0; } -// Partition arr such that even numbers come first -auto r = partition!(even)(arr); -// Now arr is separated in evens and odds. -// Numbers may have become shuffled due to instability -assert(r == arr[5 .. $]); -assert(count!(even)(arr[0 .. 5]) == 5); -assert(find!(even)(r).empty); - -// Can also specify the predicate as a string. -// Use 'a' as the predicate argument name -arr[] = Arr[]; -r = partition!(q{(a & 1) == 0})(arr); -assert(r == arr[5 .. $]); - -// Now for a stable partition: -arr[] = Arr[]; -r = partition!(q{(a & 1) == 0}, SwapStrategy.stable)(arr); -// Now arr is [2 4 6 8 10 1 3 5 7 9], and r points to 1 -assert(arr == [2, 4, 6, 8, 10, 1, 3, 5, 7, 9] && r == arr[5 .. $]); - -// In case the predicate needs to hold its own state, use a delegate: -arr[] = Arr[]; -int x = 3; -// Put stuff greater than 3 on the left -bool fun(int a) { return a > x; } -r = partition!(fun, SwapStrategy.semistable)(arr); -// Now arr is [4 5 6 7 8 9 10 2 3 1] and r points to 2 -assert(arr == [4, 5, 6, 7, 8, 9, 10, 2, 3, 1] && r == arr[7 .. $]); ----- +See_Also: + STL's $(WEB sgi.com/tech/stl/_partition.html, _partition)$(BR) + STL's $(WEB sgi.com/tech/stl/stable_partition.html, stable_partition) */ Range partition(alias predicate, SwapStrategy ss = SwapStrategy.unstable, Range)(Range r) @@ -7755,57 +8429,59 @@ Range partition(alias predicate, } } -unittest // partition +/// +unittest { import std.conv : text; auto Arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; auto arr = Arr.dup; static bool even(int a) { return (a & 1) == 0; } -// Partition a such that even numbers come first - auto p1 = partition!(even)(arr); -// Now arr is separated in evens and odds. - assert(p1 == arr[5 .. $], text(p1)); - assert(count!(even)(arr[0 .. $ - p1.length]) == p1.length); - assert(find!(even)(p1).empty); -// Notice that numbers have become shuffled due to instability + // Partition arr such that even numbers come first + auto r = partition!(even)(arr); + // Now arr is separated in evens and odds. + // Numbers may have become shuffled due to instability + assert(r == arr[5 .. $]); + assert(count!(even)(arr[0 .. 5]) == 5); + assert(find!(even)(r).empty); + + // Can also specify the predicate as a string. + // Use 'a' as the predicate argument name arr[] = Arr[]; -// Can also specify the predicate as a string. -// Use 'a' as the predicate argument name - p1 = partition!(q{(a & 1) == 0})(arr); - assert(p1 == arr[5 .. $]); -// Same result as above. Now for a stable partition: + r = partition!(q{(a & 1) == 0})(arr); + assert(r == arr[5 .. $]); + + // Now for a stable partition: arr[] = Arr[]; - p1 = partition!(q{(a & 1) == 0}, SwapStrategy.stable)(arr); -// Now arr is [2 4 6 8 10 1 3 5 7 9], and p points to 1 - assert(arr == [2, 4, 6, 8, 10, 1, 3, 5, 7, 9], text(arr)); - assert(p1 == arr[5 .. $], text(p1)); -// In case the predicate needs to hold its own state, use a delegate: + r = partition!(q{(a & 1) == 0}, SwapStrategy.stable)(arr); + // Now arr is [2 4 6 8 10 1 3 5 7 9], and r points to 1 + assert(arr == [2, 4, 6, 8, 10, 1, 3, 5, 7, 9] && r == arr[5 .. $]); + + // In case the predicate needs to hold its own state, use a delegate: arr[] = Arr[]; int x = 3; -// Put stuff greater than 3 on the left + // Put stuff greater than 3 on the left bool fun(int a) { return a > x; } - p1 = partition!(fun, SwapStrategy.semistable)(arr); -// Now arr is [4 5 6 7 8 9 10 2 3 1] and p points to 2 - assert(arr == [4, 5, 6, 7, 8, 9, 10, 2, 3, 1] && p1 == arr[7 .. $]); + r = partition!(fun, SwapStrategy.semistable)(arr); + // Now arr is [4 5 6 7 8 9 10 2 3 1] and r points to 2 + assert(arr == [4, 5, 6, 7, 8, 9, 10, 2, 3, 1] && r == arr[7 .. $]); +} + +unittest +{ + static bool even(int a) { return (a & 1) == 0; } // test with random data - auto a = rndstuff!(int)(); - partition!(even)(a); - assert(isPartitioned!(even)(a)); - auto b = rndstuff!(string)(); - partition!(`a.length < 5`)(b); - assert(isPartitioned!(`a.length < 5`)(b)); + auto a = rndstuff!int(); + partition!even(a); + assert(isPartitioned!even(a)); + auto b = rndstuff!string(); + partition!`a.length < 5`(b); + assert(isPartitioned!`a.length < 5`(b)); } /** Returns $(D true) if $(D r) is partitioned according to predicate $(D pred). - -Example: ----- -int[] r = [ 1, 3, 5, 7, 8, 2, 4, ]; -assert(isPartitioned!("a & 1")(r)); ----- */ bool isPartitioned(alias pred, Range)(Range r) if (isForwardRange!(Range)) @@ -7822,12 +8498,11 @@ bool isPartitioned(alias pred, Range)(Range r) return true; } +/// unittest { - debug(std_algorithm) scope(success) - writeln("unittest @", __FILE__, ":", __LINE__, " done."); int[] r = [ 1, 3, 5, 7, 8, 2, 4, ]; - assert(isPartitioned!("a & 1")(r)); + assert(isPartitioned!"a & 1"(r)); } // partition3 @@ -7840,16 +8515,6 @@ and rightmost range only contains elements in $(D r) that are greater than $(D pivot). The less-than test is defined by the binary function $(D less). -Example: ----- -auto a = [ 8, 3, 4, 1, 4, 7, 4 ]; -auto pieces = partition3(a, 4); -assert(a == [ 1, 3, 4, 4, 4, 7, 8 ]); -assert(pieces[0] == [ 1, 3 ]); -assert(pieces[1] == [ 4, 4, 4 ]); -assert(pieces[2] == [ 7, 8 ]); ----- - BUGS: stable $(D partition3) has not been implemented yet. */ auto partition3(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range, E) @@ -7903,28 +8568,24 @@ if (ss == SwapStrategy.unstable && isRandomAccessRange!Range r[r.length - strictlyGreater .. r.length]); } +/// unittest { auto a = [ 8, 3, 4, 1, 4, 7, 4 ]; auto pieces = partition3(a, 4); - assert(a == [ 1, 3, 4, 4, 4, 8, 7 ]); assert(pieces[0] == [ 1, 3 ]); assert(pieces[1] == [ 4, 4, 4 ]); assert(pieces[2] == [ 8, 7 ]); +} - a = null; - pieces = partition3(a, 4); - assert(a.empty); - assert(pieces[0].empty); - assert(pieces[1].empty); - assert(pieces[2].empty); - - a.length = uniform(0, 100); +unittest +{ + auto a = new int[](uniform(0, 100)); foreach (ref e; a) { e = uniform(0, 50); } - pieces = partition3(a, 25); + auto pieces = partition3(a, 25); assert(pieces[0].length + pieces[1].length + pieces[2].length == a.length); foreach (e; pieces[0]) { @@ -7950,21 +8611,12 @@ and all elements $(D e2) from $(D r[nth]) to $(D r[r.length]) satisfy $(D !less(e2, r[nth])). Effectively, it finds the nth smallest (according to $(D less)) elements in $(D r). Performs an expected $(BIGOH r.length) (if unstable) or $(BIGOH r.length * log(r.length)) -(if stable) evaluations of $(D less) and $(D swap). See also $(WEB -sgi.com/tech/stl/nth_element.html, STL's nth_element). +(if stable) evaluations of $(D less) and $(D swap). If $(D n >= r.length), the algorithm has no effect. -Examples: ----- -int[] v = [ 25, 7, 9, 2, 0, 5, 21 ]; -auto n = 4; -topN!(less)(v, n); -assert(v[n] == 9); -// Equivalent form: -topN!("a < b")(v, n); -assert(v[n] == 9); ----- +See_Also: + $(WEB sgi.com/tech/stl/nth_element.html, STL's nth_element) BUGS: @@ -8004,6 +8656,15 @@ void topN(alias less = "a < b", } } +/// +unittest +{ + int[] v = [ 25, 7, 9, 2, 0, 5, 21 ]; + auto n = 4; + topN!"a < b"(v, n); + assert(v[n] == 9); +} + unittest { debug(std_algorithm) scope(success) @@ -8090,7 +8751,7 @@ void topN(alias less = "a < b", } } -/// Ditto +/// unittest { int[] a = [ 5, 7, 2, 6, 7 ]; @@ -8103,10 +8764,8 @@ unittest // sort /** Sorts a random-access range according to the predicate $(D less). Performs -$(BIGOH r.length * log(r.length)) (if unstable) or $(BIGOH r.length * -log(r.length) * log(r.length)) (if stable) evaluations of $(D less) -and $(D swap). See also STL's $(WEB sgi.com/tech/stl/_sort.html, _sort) -and $(WEB sgi.com/tech/stl/stable_sort.html, stable_sort). +$(BIGOH r.length * log(r.length)) evaluations of $(D less). Stable sorting +requires $(D hasAssignableElements!Range) to be true. $(D sort) returns a $(XREF range, SortedRange) over the original range, which functions that can take advantage of sorted data can then use to know that the @@ -8115,30 +8774,31 @@ wrapper around the original range, so both it and the original range are sorted, but other functions won't know that the original range has been sorted, whereas they $(I can) know that $(XREF range, SortedRange) has been sorted. +The predicate is expected to satisfy certain rules in order for $(D sort) to +behave as expected - otherwise, the program may fail on certain inputs (but not +others) when not compiled in release mode, due to the cursory $(D assumeSorted) +check. Specifically, $(D sort) expects $(D less(a,b) && less(b,c)) to imply +$(D less(a,c)) (transitivity), and, conversely, $(D !less(a,b) && !less(b,c)) to +imply $(D !less(a,c)). Note that the default predicate ($(D "a < b")) does not +always satisfy these conditions for floating point types, because the expression +will always be $(D false) when either $(D a) or $(D b) is NaN. + +Returns: The initial range wrapped as a $(D SortedRange) with the predicate +$(D binaryFun!less). + +Algorithms: $(WEB en.wikipedia.org/wiki/Introsort) is used for unstable sorting and +$(WEB en.wikipedia.org/wiki/Timsort, Timsort) is used for stable sorting. +Each algorithm has benefits beyond stability. Introsort is generally faster but +Timsort may achieve greater speeds on data with low entropy or if predicate calls +are expensive. Introsort performs no allocations whereas Timsort will perform one +or more allocations per call. Both algorithms have $(BIGOH n log n) worst-case +time complexity. + See_Also: - $(XREF range, assumeSorted) - -Remark: Stable sort is implementated as Timsort, the original code at -$(WEB github.com/Xinok/XSort, XSort) by Xinok, public domain. - -Example: ----- -int[] array = [ 1, 2, 3, 4 ]; -// sort in descending order -sort!("a > b")(array); -assert(array == [ 4, 3, 2, 1 ]); -// sort in ascending order -sort(array); -assert(array == [ 1, 2, 3, 4 ]); -// sort with a delegate -bool myComp(int x, int y) { return x > y; } -sort!(myComp)(array); -assert(array == [ 4, 3, 2, 1 ]); -// Showcase stable sorting -string[] words = [ "aBc", "a", "abc", "b", "ABC", "c" ]; -sort!("toUpper(a) < toUpper(b)", SwapStrategy.stable)(words); -assert(words == [ "a", "aBc", "abc", "ABC", "b", "c" ]); ----- + $(XREF range, assumeSorted)$(BR) + $(XREF range, SortedRange)$(BR) + $(XREF algorithm, SwapStrategy)$(BR) + $(XREF functional, binaryFun) */ SortedRange!(Range, less) @@ -8161,7 +8821,7 @@ sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, static if (is(LessRet == bool)) { static if (ss == SwapStrategy.unstable) - quickSortImpl!(lessFun)(r); + quickSortImpl!(lessFun)(r, cast(real)r.length); else //use Tim Sort for semistable & stable TimSortImpl!(lessFun, Range).sort(r, null); @@ -8178,6 +8838,26 @@ sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, return assumeSorted!less(r); } +/// +unittest +{ + int[] array = [ 1, 2, 3, 4 ]; + // sort in descending order + sort!("a > b")(array); + assert(array == [ 4, 3, 2, 1 ]); + // sort in ascending order + sort(array); + assert(array == [ 1, 2, 3, 4 ]); + // sort with a delegate + bool myComp(int x, int y) { return x > y; } + sort!(myComp)(array); + assert(array == [ 4, 3, 2, 1 ]); + // Showcase stable sorting + string[] words = [ "aBc", "a", "abc", "b", "ABC", "c" ]; + sort!("toUpper(a) < toUpper(b)", SwapStrategy.stable)(words); + assert(words == [ "a", "aBc", "abc", "ABC", "b", "c" ]); +} + unittest { debug(std_algorithm) scope(success) @@ -8230,6 +8910,29 @@ unittest auto a_10317 = new E_10317[10]; sort(a_10317); } + + { + // Issue 7767 + // Unstable sort should complete without an excessive number of predicate calls + // This would suggest it's running in quadratic time + + // Compilation error if predicate is not static, i.e. a nested function + static uint comp; + static bool pred(size_t a, size_t b) + { + ++comp; + return a < b; + } + + size_t[] arr; + arr.length = 1024; + + foreach(k; 0..arr.length) arr[k] = k; + swapRanges(arr[0..$/2], arr[$/2..$]); + + sort!(pred, SwapStrategy.unstable)(arr); + assert(comp < 25_000); + } } private template validPredicates(E, less...) { @@ -8253,15 +8956,6 @@ and sorts elements that have the same $(D id) by $(D date) descending. Such a call is equivalent to $(D sort!"a.id != b.id ? a.id < b.id : a.date > b.date"(r)), but $(D multiSort) is faster because it does fewer comparisons (in addition to being more convenient). - -Example: ----- -static struct Point { int x, y; } -auto pts1 = [ Point(0, 0), Point(5, 5), Point(0, 1), Point(0, 2) ]; -auto pts2 = [ Point(0, 0), Point(0, 1), Point(0, 2), Point(5, 5) ]; -multiSort!("a.x < b.x", "a.y < b.y", SwapStrategy.unstable)(pts1); -assert(pts1 == pts2); ----- */ template multiSort(less...) //if (less.length > 1) { @@ -8307,6 +9001,16 @@ template multiSort(less...) //if (less.length > 1) } } +/// +unittest +{ + static struct Point { int x, y; } + auto pts1 = [ Point(0, 0), Point(5, 5), Point(0, 1), Point(0, 2) ]; + auto pts2 = [ Point(0, 0), Point(0, 1), Point(0, 2), Point(5, 5) ]; + multiSort!("a.x < b.x", "a.y < b.y", SwapStrategy.unstable)(pts1); + assert(pts1 == pts2); +} + unittest { static struct Point { int x, y; } @@ -8388,20 +9092,34 @@ private size_t getPivot(alias less, Range)(Range r) private void optimisticInsertionSort(alias less, Range)(Range r) { alias binaryFun!(less) pred; - if (r.length < 2) { - return ; + if (r.length < 2) + { + return; } immutable maxJ = r.length - 1; - for (size_t i = r.length - 2; i != size_t.max; --i) { + for (size_t i = r.length - 2; i != size_t.max; --i) + { size_t j = i; - auto temp = r[i]; - for (; j < maxJ && pred(r[j + 1], temp); ++j) { - r[j] = r[j + 1]; + static if (hasAssignableElements!Range) + { + auto temp = r[i]; + + for (; j < maxJ && pred(r[j + 1], temp); ++j) + { + r[j] = r[j + 1]; + } + + r[j] = temp; + } + else + { + for (; j < maxJ && pred(r[j + 1], r[j]); ++j) + { + swapAt(r, j, j + 1); + } } - - r[j] = temp; } } @@ -8436,7 +9154,7 @@ void swapAt(R)(R r, size_t i1, size_t i2) } } -private void quickSortImpl(alias less, Range)(Range r) +private void quickSortImpl(alias less, Range)(Range r, real depth) { alias ElementType!(Range) Elem; enum size_t optimisticInsertionSortGetsBetter = 25; @@ -8445,6 +9163,13 @@ private void quickSortImpl(alias less, Range)(Range r) // partition while (r.length > optimisticInsertionSortGetsBetter) { + if(depth < 1.0) + { + HeapSortImpl!(less, Range).heapSort(r); + return; + } + depth *= (2.0/3.0); + const pivotIdx = getPivot!(less)(r); auto pivot = r[pivotIdx]; @@ -8474,7 +9199,7 @@ private void quickSortImpl(alias less, Range)(Range r) { swap(left, right); } - .quickSortImpl!(less, Range)(right); + .quickSortImpl!(less, Range)(right, depth); r = left; } // residual sort @@ -8484,14 +9209,67 @@ private void quickSortImpl(alias less, Range)(Range r) } } -/+ - Tim Sort for Random-Access Ranges +// Bottom-Up Heap-Sort Implementation +private template HeapSortImpl(alias less, Range) +{ + static assert(isRandomAccessRange!Range); + static assert(hasLength!Range); + static assert(hasAssignableElements!Range); - Written and tested for DMD 2.059 and Phobos + alias binaryFun!less lessFun; - Authors: Xinok - License: Public Domain -+/ + void heapSort(Range r) + { + // If true, there is nothing to do + if(r.length < 2) return; + + // Build Heap + size_t i = r.length / 2; + while(i > 0) sift(r, --i, r.length); + + // Sort + i = r.length - 1; + while(i > 0) + { + swapAt(r, 0, i); + sift(r, 0, i); + --i; + } + } + + void sift(Range r, size_t parent, immutable size_t end) + { + immutable root = parent; + size_t child = void; + + // Sift down + while(true) + { + child = parent * 2 + 1; + + if(child >= end) break; + + if(child + 1 < end && lessFun(r[child], r[child + 1])) child += 1; + + swapAt(r, parent, child); + parent = child; + } + + child = parent; + + // Sift up + while(child > root) + { + parent = (child - 1) / 2; + if(lessFun(r[parent], r[child])) + { + swapAt(r, parent, child); + child = parent; + } + else break; + } + } +} // Tim Sort implementation private template TimSortImpl(alias pred, R) @@ -9182,7 +9960,7 @@ unittest { debug(std_algorithm) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " done."); - import std.math; + import std.math; static double entropy(double[] probs) { double result = 0; foreach (p; probs) { @@ -9246,13 +10024,6 @@ the range $(D r[mid .. r.length]) in no particular order. Performs $(BIGOH r.length * log(mid)) evaluations of $(D pred). The implementation simply calls $(D topN!(less, ss)(r, n)) and then $(D sort!(less, ss)(r[0 .. n])). - -Example: ----- -int[] a = [ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 ]; -partialSort(a, 5); -assert(a[0 .. 5] == [ 0, 1, 2, 3, 4 ]); ----- */ void partialSort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range)(Range r, size_t n) @@ -9262,10 +10033,9 @@ void partialSort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, sort!(less, ss)(r[0 .. n]); } +/// unittest { - debug(std_algorithm) scope(success) - writeln("unittest @", __FILE__, ":", __LINE__, " done."); int[] a = [ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 ]; partialSort(a, 5); assert(a[0 .. 5] == [ 0, 1, 2, 3, 4 ]); @@ -9280,15 +10050,6 @@ exact strategy chosen depends on the relative sizes of $(D lhs) and $(D rhs). Performs $(BIGOH lhs.length + rhs.length * log(rhs.length)) (best case) to $(BIGOH (lhs.length + rhs.length) * log(lhs.length + rhs.length)) (worst-case) evaluations of $(D swap). - -Example: ----- -int[] a = [ 1, 2, 3 ]; -int[] b = [ 4, 0, 6, 5 ]; -completeSort(assumeSorted(a), b); -assert(a == [ 0, 1, 2 ]); -assert(b == [ 3, 4, 5, 6 ]); ----- */ void completeSort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range1, Range2)(SortedRange!(Range1, less) lhs, Range2 rhs) @@ -9306,16 +10067,12 @@ if (hasLength!(Range2) && hasSlicing!(Range2)) } } +/// unittest { - debug(std_algorithm) scope(success) - writeln("unittest @", __FILE__, ":", __LINE__, " done."); int[] a = [ 1, 2, 3 ]; int[] b = [ 4, 0, 6, 5 ]; - // @@@BUG@@@ The call below should work - // completeSort(assumeSorted(a), b); - completeSort!("a < b", SwapStrategy.unstable, int[], int[])( - assumeSorted(a), b); + completeSort(assumeSorted(a), b); assert(a == [ 0, 1, 2 ]); assert(b == [ 3, 4, 5, 6 ]); } @@ -9325,16 +10082,6 @@ unittest Checks whether a forward range is sorted according to the comparison operation $(D less). Performs $(BIGOH r.length) evaluations of $(D less). - -Example: ----- -int[] arr = [4, 3, 2, 1]; -assert(!isSorted(arr)); -sort(arr); -assert(isSorted(arr)); -sort!("a > b")(arr); -assert(isSorted!("a > b")(arr)); ----- */ bool isSorted(alias less = "a < b", Range)(Range r) if (isForwardRange!(Range)) { @@ -9378,6 +10125,17 @@ bool isSorted(alias less = "a < b", Range)(Range r) if (isForwardRange!(Range)) return true; } +/// +unittest +{ + int[] arr = [4, 3, 2, 1]; + assert(!isSorted(arr)); + sort(arr); + assert(isSorted(arr)); + sort!("a > b")(arr); + assert(isSorted!("a > b")(arr)); +} + unittest { // Issue 9457 @@ -9428,21 +10186,6 @@ relation involves not only $(D index) but also $(D r). Throws: If the second argument's length is less than that of the range indexed, an exception is thrown. - -Example: ----- -immutable(int[]) arr = [ 2, 3, 1, 5, 0 ]; -// index using pointers -auto index1 = new immutable(int)*[arr.length]; -makeIndex!("a < b")(arr, index1); -assert(isSorted!("*a < *b")(index1)); -// index using offsets -auto index2 = new size_t[arr.length]; -makeIndex!("a < b")(arr, index2); -assert(isSorted! - ((size_t a, size_t b){ return arr[a] < arr[b];}) - (index2)); ----- */ SortedRange!(RangeIndex, (a, b) => binaryFun!less(*a, *b)) makeIndex( @@ -9457,7 +10200,7 @@ makeIndex( // assume collection already ordered size_t i; for (; !r.empty; r.popFront(), ++i) - index[i] = &(r.front); + index[i] = addressOf(r.front); enforce(index.length == i); // sort the index sort!((a, b) => binaryFun!less(*a, *b), ss)(index); @@ -9495,6 +10238,22 @@ if (isRandomAccessRange!Range && !isInfinite!Range && (index); } +/// +unittest +{ + immutable(int[]) arr = [ 2, 3, 1, 5, 0 ]; + // index using pointers + auto index1 = new immutable(int)*[arr.length]; + makeIndex!("a < b")(arr, index1); + assert(isSorted!("*a < *b")(index1)); + // index using offsets + auto index2 = new size_t[arr.length]; + makeIndex!("a < b")(arr, index2); + assert(isSorted! + ((size_t a, size_t b){ return arr[a] < arr[b];}) + (index2)); +} + unittest { debug(std_algorithm) scope(success) @@ -9793,8 +10552,8 @@ unittest // random data auto b = rndstuff!(string)(); auto index = new string*[b.length]; - partialIndex!("std.uni.toUpper(a) < std.uni.toUpper(b)")(b, index); - assert(isSorted!("std.uni.toUpper(*a) < std.uni.toUpper(*b)")(index)); + partialIndex!((a, b) => std.uni.toUpper(a) < std.uni.toUpper(b))(b, index); + assert(isSorted!((a, b) => std.uni.toUpper(*a) < std.uni.toUpper(*b))(index)); // random data with indexes auto index1 = new size_t[b.length]; @@ -9878,17 +10637,31 @@ unittest +/ // canFind -/** -Returns $(D true) if and only if $(D value) can be found in $(D -range). Performs $(BIGOH needle.length) evaluations of $(D pred). - */ -bool canFind(alias pred = "a == b", R, E)(R haystack, E needle) -if (is(typeof(find!pred(haystack, needle)))) -{ - return !find!pred(haystack, needle).empty; -} - /++ +Convenience function. Like find, but only returns whether or not the search +was succesful. + +/ +template canFind(alias pred="a == b") +{ + //Explictly Undocumented. Do not use. It may be deprecated in the future. + //Use any instead. + bool canFind(Range)(Range haystack) + if (is(typeof(find!pred(haystack)))) + { + return any!pred(haystack); + } + + /++ + Returns $(D true) if and only if $(D value) can be found in $(D + range). Performs $(BIGOH needle.length) evaluations of $(D pred). + +/ + bool canFind(Range, Element)(Range haystack, Element needle) + if (is(typeof(find!pred(haystack, needle)))) + { + return !find!pred(haystack, needle).empty; + } + + /++ Returns the 1-based index of the first needle found in $(D haystack). If no needle is found, then $(D 0) is returned. @@ -9898,13 +10671,14 @@ if (is(typeof(find!pred(haystack, needle)))) $(D bool) for the same effect or used to get which needle was found first without having to deal with the tuple that $(D LREF find) returns for the same operation. - +/ -size_t canFind(alias pred = "a == b", Range, Ranges...)(Range haystack, Ranges needles) -if (Ranges.length > 1 && - allSatisfy!(isForwardRange, Ranges) && - is(typeof(find!pred(haystack, needles)))) -{ - return find!pred(haystack, needles)[1]; + +/ + size_t canFind(Range, Ranges...)(Range haystack, Ranges needles) + if (Ranges.length > 1 && + allSatisfy!(isForwardRange, Ranges) && + is(typeof(find!pred(haystack, needles)))) + { + return find!pred(haystack, needles)[1]; + } } unittest @@ -9929,22 +10703,34 @@ unittest assert(canFind([0, 1, 2, 3], [1, 3], [2, 4]) == 0); } -//Explictly Undocumented. Do not use. It may be deprecated in the future. -//Use any instead. -bool canFind(alias pred, Range)(Range range) +unittest { - return any!pred(range); + assert(equal!(canFind!"a < b")([[1, 2, 3], [7, 8, 9]], [2, 8])); } -/** -Returns $(D true) if and only if a value $(D v) satisfying the -predicate $(D pred) can be found in the forward range $(D -range). Performs $(BIGOH r.length) evaluations of $(D pred). - */ -bool any(alias pred, Range)(Range range) -if (is(typeof(find!pred(range)))) +/++ +Checks if $(I _any) of the elements verifies $(D pred). + +/ +template any(alias pred) { - return !find!pred(range).empty; + /++ + Returns $(D true) if and only if $(I _any) value $(D v) found in the + input range $(D range) satisfies the predicate $(D pred). + Performs (at most) $(BIGOH r.length) evaluations of $(D pred). + +/ + bool any(Range)(Range range) + if (isInputRange!Range && is(typeof(unaryFun!pred(range.front)))) + { + return !find!pred(range).empty; + } +} + +/// +unittest +{ + import std.ascii : isWhite; + assert( all!(any!isWhite)(["a a", "b b"])); + assert(!any!(all!isWhite)(["a a", "b b"])); } unittest @@ -9955,29 +10741,37 @@ unittest assert(any!"a == 2"(a)); } -/** -Returns $(D true) if and only if all values in $(D range) satisfy the -predicate $(D pred). Performs $(BIGOH r.length) evaluations of $(D pred). - -Examples: ---- -assert(all!"a & 1"([1, 3, 5, 7, 9])); -assert(!all!"a & 1"([1, 2, 3, 5, 7, 9])); ---- -*/ -bool all(alias pred, R)(R range) -if (isInputRange!R && is(typeof(unaryFun!pred(range.front)))) +/++ +Checks if $(I _all) of the elements verify $(D pred). + +/ +template all(alias pred) { - // dmd @@@BUG9578@@@ workaround - // return find!(not!(unaryFun!pred))(range).empty; - bool notPred(ElementType!R a) { return !unaryFun!pred(a); } - return find!notPred(range).empty; + /++ + Returns $(D true) if and only if $(I _all) values $(D v) found in the + input range $(D range) satisfy the predicate $(D pred). + Performs (at most) $(BIGOH r.length) evaluations of $(D pred). + +/ + bool all(Range)(Range range) + if (isInputRange!Range && is(typeof(unaryFun!pred(range.front)))) + { + return find!(not!(unaryFun!pred))(range).empty; + } +} + +/// +unittest +{ + assert( all!"a & 1"([1, 3, 5, 7, 9])); + assert(!all!"a & 1"([1, 2, 3, 5, 7, 9])); +} +unittest +{ + int x = 1; + assert(all!(a => a > x)([2, 3])); } unittest { - assert(all!"a & 1"([1, 3, 5, 7, 9])); - assert(!all!"a & 1"([1, 2, 3, 5, 7, 9])); int x = 1; assert(all!(a => a > x)([2, 3])); } @@ -9988,14 +10782,6 @@ random-access range $(D target), where $(D n = target.length). Elements of $(D source) are not touched. If $(D sorted) is $(D true), the target is sorted. Otherwise, the target respects the $(WEB en.wikipedia.org/wiki/Binary_heap, heap property). - -Example: ----- -int[] a = [ 10, 16, 2, 3, 1, 5, 0 ]; -int[] b = new int[3]; -topNCopy(a, b, true); -assert(b == [ 0, 1, 2 ]); ----- */ TRange topNCopy(alias less = "a < b", SRange, TRange) (SRange source, TRange target, SortOutput sorted = SortOutput.no) @@ -10013,10 +10799,9 @@ TRange topNCopy(alias less = "a < b", SRange, TRange) return result; } +/// unittest { - debug(std_algorithm) scope(success) - writeln("unittest @", __FILE__, ":", __LINE__, " done."); int[] a = [ 10, 16, 2, 3, 1, 5, 0 ]; int[] b = new int[3]; topNCopy(a, b, SortOutput.yes); @@ -10044,17 +10829,6 @@ are assumed to be sorted by $(D less). Elements in the output are not unique; the length of the output is the sum of the lengths of the inputs. (The $(D length) member is offered if all ranges also have length.) The element types of all ranges must have a common type. - -Example: ----- -int[] a = [ 1, 2, 4, 5, 7, 9 ]; -int[] b = [ 0, 1, 2, 4, 7, 8 ]; -int[] c = [ 10 ]; -assert(setUnion(a, b).length == a.length + b.length); -assert(equal(setUnion(a, b), [0, 1, 1, 2, 2, 4, 4, 5, 7, 7, 8, 9][])); -assert(equal(setUnion(a, c, b), - [0, 1, 1, 2, 2, 4, 4, 5, 7, 7, 8, 9, 10][])); ----- */ struct SetUnion(alias less = "a < b", Rs...) if (allSatisfy!(isInputRange, Rs)) { @@ -10171,14 +10945,13 @@ SetUnion!(less, Rs) setUnion(alias less = "a < b", Rs...) return typeof(return)(rs); } +/// unittest { - debug(std_algorithm) scope(success) - writeln("unittest @", __FILE__, ":", __LINE__, " done."); int[] a = [ 1, 2, 4, 5, 7, 9 ]; int[] b = [ 0, 1, 2, 4, 7, 8 ]; int[] c = [ 10 ]; - //foreach (e; setUnion(a, b)) writeln(e); + assert(setUnion(a, b).length == a.length + b.length); assert(equal(setUnion(a, b), [0, 1, 1, 2, 2, 4, 4, 5, 7, 7, 8, 9][])); assert(equal(setUnion(a, c, b), @@ -10188,19 +10961,9 @@ unittest } /** -Lazily computes the intersection of two or more input ranges $(D +Lazily computes the intersection of two input ranges $(D rs). The ranges are assumed to be sorted by $(D less). The element -types of all ranges must have a common type. - -Example: ----- -int[] a = [ 1, 2, 4, 5, 7, 9 ]; -int[] b = [ 0, 1, 2, 4, 7, 8 ]; -int[] c = [ 0, 1, 4, 5, 7, 8 ]; -assert(equal(setIntersection(a, a), a)); -assert(equal(setIntersection(a, b), [1, 2, 4, 7][])); -assert(equal(setIntersection(a, b, c), [1, 4, 7][])); ----- +types of both ranges must have a common type. */ struct SetIntersection(alias less = "a < b", Rs...) if (allSatisfy!(isInputRange, Rs)) @@ -10286,38 +11049,32 @@ if (allSatisfy!(isInputRange, Rs)) return typeof(return)(ranges); } +/+ setIntersection doesn't yet support more than two inputs +/// unittest { - debug(std_algorithm) scope(success) - writeln("unittest @", __FILE__, ":", __LINE__, " done."); int[] a = [ 1, 2, 4, 5, 7, 9 ]; int[] b = [ 0, 1, 2, 4, 7, 8 ]; int[] c = [ 0, 1, 4, 5, 7, 8 ]; - //foreach (e; setIntersection(a, b, c)) writeln(e); - assert(equal(setIntersection(a, b), [1, 2, 4, 7][])); assert(equal(setIntersection(a, a), a)); + assert(equal(setIntersection(a, b), [1, 2, 4, 7][])); + assert(equal(setIntersection(a, b, c), [1, 4, 7][])); +} ++/ - static assert(isForwardRange!(typeof(setIntersection(a, a)))); - // assert(equal(setIntersection(a, b, b, a), [1, 2, 4, 7][])); - // assert(equal(setIntersection(a, b, c), [1, 4, 7][])); - // assert(equal(setIntersection(a, c, b), [1, 4, 7][])); - // assert(equal(setIntersection(b, a, c), [1, 4, 7][])); - // assert(equal(setIntersection(b, c, a), [1, 4, 7][])); - // assert(equal(setIntersection(c, a, b), [1, 4, 7][])); - // assert(equal(setIntersection(c, b, a), [1, 4, 7][])); +/// +unittest +{ + int[] a = [ 1, 2, 4, 5, 7, 9 ]; + int[] b = [ 0, 1, 2, 4, 7, 8 ]; + assert(equal(setIntersection(a, a), a)); + assert(equal(setIntersection(a, b), [1, 2, 4, 7][])); } /** Lazily computes the difference of $(D r1) and $(D r2). The two ranges are assumed to be sorted by $(D less). The element types of the two ranges must have a common type. - -Example: ----- -int[] a = [ 1, 2, 4, 5, 7, 9 ]; -int[] b = [ 0, 1, 2, 4, 7, 8 ]; -assert(equal(setDifference(a, b), [5, 9][])); ----- */ struct SetDifference(alias less = "a < b", R1, R2) if (isInputRange!(R1) && isInputRange!(R2)) @@ -10387,13 +11144,11 @@ SetDifference!(less, R1, R2) setDifference(alias less = "a < b", R1, R2) return typeof(return)(r1, r2); } +/// unittest { - debug(std_algorithm) scope(success) - writeln("unittest @", __FILE__, ":", __LINE__, " done."); int[] a = [ 1, 2, 4, 5, 7, 9 ]; int[] b = [ 0, 1, 2, 4, 7, 8 ]; - //foreach (e; setDifference(a, b)) writeln(e); assert(equal(setDifference(a, b), [5, 9][])); static assert(isForwardRange!(typeof(setDifference(a, b)))); } @@ -10404,13 +11159,6 @@ i.e. the elements that are present in exactly one of $(D r1) and $(D r2). The two ranges are assumed to be sorted by $(D less), and the output is also sorted by $(D less). The element types of the two ranges must have a common type. - -Example: ----- -int[] a = [ 1, 2, 4, 5, 7, 9 ]; -int[] b = [ 0, 1, 2, 4, 7, 8 ]; -assert(equal(setSymmetricDifference(a, b), [0, 5, 8, 9][])); ----- */ struct SetSymmetricDifference(alias less = "a < b", R1, R2) if (isInputRange!(R1) && isInputRange!(R2)) @@ -10500,20 +11248,16 @@ setSymmetricDifference(alias less = "a < b", R1, R2) return typeof(return)(r1, r2); } +/// unittest { - debug(std_algorithm) scope(success) - writeln("unittest @", __FILE__, ":", __LINE__, " done."); int[] a = [ 1, 2, 4, 5, 7, 9 ]; int[] b = [ 0, 1, 2, 4, 7, 8 ]; - //foreach (e; setSymmetricDifference(a, b)) writeln(e); assert(equal(setSymmetricDifference(a, b), [0, 5, 8, 9][])); - static assert(isForwardRange!(typeof(setSymmetricDifference(a, b)))); } // Internal random array generators - version(unittest) { private enum size_t maxArraySize = 50; @@ -10627,22 +11371,6 @@ of $(D ror) and discretionarily swaps and advances elements of it. If you want $(D ror) to preserve its contents after the call, you may want to pass a duplicate to $(D NWayUnion) (and perhaps cache the duplicate in between calls). - -Example: ----- -double[][] a = -[ - [ 1, 4, 7, 8 ], - [ 1, 7 ], - [ 1, 7, 8], - [ 4 ], - [ 7 ], -]; -auto witness = [ - 1, 1, 1, 4, 4, 7, 7, 7, 7, 8, 8 -]; -assert(equal(nWayUnion(a), witness[])); ----- */ struct NWayUnion(alias less, RangeOfRanges) { @@ -10698,10 +11426,9 @@ NWayUnion!(less, RangeOfRanges) nWayUnion return typeof(return)(ror); } +/// unittest { - debug(std_algorithm) scope(success) - writeln("unittest @", __FILE__, ":", __LINE__, " done."); double[][] a = [ [ 1, 4, 7, 8 ], @@ -10713,8 +11440,7 @@ unittest auto witness = [ 1, 1, 1, 4, 4, 7, 7, 7, 7, 8, 8 ]; - //foreach (e; nWayUnion(a)) writeln(e); - assert(equal(nWayUnion(a), witness[])); + assert(equal(nWayUnion(a), witness)); } // largestPartialIntersection @@ -10919,34 +11645,6 @@ while (nextPermutation(a)) * Returns: false if the range was lexicographically the greatest, in which * case the range is reversed back to the lexicographically smallest * permutation; otherwise returns true. - * - * Example: ----- -// Step through all permutations of a sorted array in lexicographic order -int[] a = [1,2,3]; -assert(nextPermutation(a) == true); -assert(a == [1,3,2]); -assert(nextPermutation(a) == true); -assert(a == [2,1,3]); -assert(nextPermutation(a) == true); -assert(a == [2,3,1]); -assert(nextPermutation(a) == true); -assert(a == [3,1,2]); -assert(nextPermutation(a) == true); -assert(a == [3,2,1]); -assert(nextPermutation(a) == false); -assert(a == [1,2,3]); ----- ----- -// Step through permutations of an array containing duplicate elements: -int[] a = [1,1,2]; -assert(nextPermutation(a) == true); -assert(a == [1,2,1]); -assert(nextPermutation(a) == true); -assert(a == [2,1,1]); -assert(nextPermutation(a) == false); -assert(a == [1,1,2]); ----- */ bool nextPermutation(alias less="a arr.length) - arr = arr.ptr[0 .. cap]; + arr = ()@trusted{ return arr.ptr[0 .. cap]; }(); // we assume no reallocation occurred assert(arr.ptr is _data.arr.ptr); _data.capacity = arr.length; } -/** -Reserve at least newCapacity elements for appending. Note that more elements -may be reserved than requested. If newCapacity < capacity, then nothing is -done. -*/ - void reserve(size_t newCapacity) + /** + * Reserve at least newCapacity elements for appending. Note that more elements + * may be reserved than requested. If newCapacity <= capacity, then nothing is + * done. + */ + void reserve(size_t newCapacity) @safe pure nothrow { - if (!_data) - _data = new Data; - if (_data.capacity < newCapacity) + if (_data) { - // need to increase capacity - immutable len = _data.arr.length; - if (__ctfe) - { - static if (is(Unqual!T == void)) - { - // void[] - _data.arr.length = newCapacity; - } - else - { - // avoid restriction of @disable this() - _data.arr = _data.arr[0.._data.capacity]; - foreach (i; _data.capacity .. newCapacity) - _data.arr ~= Unqual!T.init; - assert(_data.arr.length == newCapacity); - _data.arr = _data.arr[0..len]; - } - _data.capacity = newCapacity; - return; - } - immutable growsize = (newCapacity - len) * T.sizeof; - auto u = GC.extend(_data.arr.ptr, growsize, growsize); - if (u) - { - // extend worked, update the capacity - _data.capacity = u / T.sizeof; - } - else - { - // didn't work, must reallocate - auto bi = GC.qalloc(newCapacity * T.sizeof, - (typeid(T[]).next.flags & 1) ? 0 : GC.BlkAttr.NO_SCAN); - _data.capacity = bi.size / T.sizeof; - if (len) - memcpy(bi.base, _data.arr.ptr, len * T.sizeof); - _data.arr = (cast(Unqual!(T)*)bi.base)[0..len]; - // leave the old data, for safety reasons - } + if (newCapacity > _data.capacity) + ensureAddable(newCapacity - _data.arr.length); + } + else + { + ensureAddable(newCapacity); } } -/** -Returns the capacity of the array (the maximum number of elements the -managed array can accommodate before triggering a reallocation). If any -appending will reallocate, $(D capacity) returns $(D 0). - */ - @property size_t capacity() const + /** + * Returns the capacity of the array (the maximum number of elements the + * managed array can accommodate before triggering a reallocation). If any + * appending will reallocate, $(D capacity) returns $(D 0). + */ + @property size_t capacity() const @safe pure nothrow { return _data ? _data.capacity : 0; } -/** -Returns the managed array. - */ - @property inout(T)[] data() inout + /** + * Returns the managed array. + */ + @property inout(T)[] data() inout @trusted pure nothrow { + /* @trusted operation: + * casting Unqual!T[] to inout(T)[] + */ return cast(typeof(return))(_data ? _data.arr : null); } // ensure we can add nelems elements, resizing as necessary - private void ensureAddable(size_t nelems) + private void ensureAddable(size_t nelems) @safe pure nothrow { if (!_data) _data = new Data; immutable len = _data.arr.length; immutable reqlen = len + nelems; - if (reqlen > _data.capacity) + + if (()@trusted{ return _data.capacity; }() >= reqlen) + return; + + // need to increase capacity + if (__ctfe) { - if (__ctfe) + static if (__traits(compiles, new Unqual!T[1])) { - static if (is(Unqual!T == void)) - { - // void[] - _data.arr.length = reqlen; - } - else - { - // avoid restriction of @disable this() - _data.arr = _data.arr[0.._data.capacity]; - foreach (i; _data.capacity .. reqlen) - _data.arr ~= Unqual!T.init; - _data.arr = _data.arr[0..len]; - } - _data.capacity = reqlen; - return; + _data.arr.length = reqlen; } + else + { + // avoid restriction of @disable this() + ()@trusted{ _data.arr = _data.arr[0 .. _data.capacity]; }(); + foreach (i; _data.capacity .. reqlen) + _data.arr ~= Unqual!T.init; + } + _data.arr = _data.arr[0 .. len]; + _data.capacity = reqlen; + } + else + { // Time to reallocate. // We need to almost duplicate what's in druntime, except we // have better access to the capacity field. - auto newlen = newCapacity(reqlen); + auto newlen = appenderNewCapacity!(T.sizeof)(_data.capacity, reqlen); // first, try extending the current block - auto u = GC.extend(_data.arr.ptr, nelems * T.sizeof, (newlen - len) * T.sizeof); + auto u = ()@trusted{ return + GC.extend(_data.arr.ptr, nelems * T.sizeof, (newlen - len) * T.sizeof); + }(); if (u) { // extend worked, update the capacity @@ -2273,52 +2342,47 @@ Returns the managed array. else { // didn't work, must reallocate - auto bi = GC.qalloc(newlen * T.sizeof, - (typeid(T[]).next.flags & 1) ? 0 : GC.BlkAttr.NO_SCAN); + auto bi = ()@trusted{ return + GC.qalloc(newlen * T.sizeof, (typeid(T[]).next.flags & 1) ? 0 : GC.BlkAttr.NO_SCAN); + }(); _data.capacity = bi.size / T.sizeof; if (len) - memcpy(bi.base, _data.arr.ptr, len * T.sizeof); - _data.arr = (cast(Unqual!(T)*)bi.base)[0..len]; + ()@trusted{ memcpy(bi.base, _data.arr.ptr, len * T.sizeof); }(); + _data.arr = ()@trusted{ return (cast(Unqual!T*)bi.base)[0 .. len]; }(); // leave the old data, for safety reasons } } } - private static size_t newCapacity(size_t newlength) - { - long mult = 100 + (1000L) / (bsr(newlength * T.sizeof) + 1); - // limit to doubling the length, we don't want to grow too much - if(mult > 200) - mult = 200; - auto newext = cast(size_t)((newlength * mult + 99) / 100); - return newext > newlength ? newext : newlength; - } - private template canPutItem(U) { - enum bool canPutItem = isImplicitlyConvertible!(U, T) || + enum bool canPutItem = + isImplicitlyConvertible!(U, T) || isSomeChar!T && isSomeChar!U; } - private template canPutConstRange(Range) { - enum bool canPutConstRange = isInputRange!(Unqual!Range) && + enum bool canPutConstRange = + isInputRange!(Unqual!Range) && !isInputRange!Range; } - private template canPutRange(Range) { - enum bool canPutRange = isInputRange!Range && + enum bool canPutRange = + isInputRange!Range && is(typeof(Appender.init.put(Range.init.front))); } -/** -Appends one item to the managed array. - */ + /** + * Appends one item to the managed array. + */ void put(U)(U item) if (canPutItem!U) { static if (isSomeChar!T && isSomeChar!U && T.sizeof < U.sizeof) { + /* may throwable operation: + * - std.utf.encode + */ // must do some transcoding around here Unqual!T[T.sizeof == 1 ? 4 : 2] encoded; auto len = std.utf.encode(encoded, item); @@ -2328,8 +2392,30 @@ Appends one item to the managed array. { ensureAddable(1); immutable len = _data.arr.length; - _data.arr.ptr[len] = cast(Unqual!T)item; - _data.arr = _data.arr.ptr[0 .. len + 1]; + + auto bigDataFun() @trusted nothrow { return _data.arr.ptr[0 .. len + 1];} + auto bigData = bigDataFun(); + + static if (is(Unqual!T == T)) + alias uitem = item; + else + auto ref uitem() @trusted nothrow @property { return cast(Unqual!T)item;} + + //The idea is to only call emplace if we must. + static if ( is(typeof(bigData[0].opAssign(uitem))) || + !is(typeof(bigData[0] = uitem))) + { + //pragma(msg, T.stringof); pragma(msg, U.stringof); + emplace(&bigData[len], uitem); + } + else + { + //pragma(msg, T.stringof); pragma(msg, U.stringof); + bigData[len] = uitem; + } + + //We do this at the end, in case of exceptions + _data.arr = bigData; } } @@ -2340,17 +2426,15 @@ Appends one item to the managed array. p(items); } -/** -Appends an entire range to the managed array. - */ + /** + * Appends an entire range to the managed array. + */ void put(Range)(Range items) if (canPutRange!Range) { // note, we disable this branch for appending one type of char to // another because we can't trust the length portion. static if (!(isSomeChar!T && isSomeChar!(ElementType!Range) && - !is(Range == Unqual!T[]) && - !is(Range == const(Unqual!T)[]) && - !is(Range == immutable(T)[])) && + !is(immutable Range == immutable T[])) && is(typeof(items.length) == size_t)) { // optimization -- if this type is something other than a string, @@ -2369,16 +2453,44 @@ Appends an entire range to the managed array. ensureAddable(items.length); immutable len = _data.arr.length; immutable newlen = len + items.length; - _data.arr = _data.arr.ptr[0..newlen]; - static if (is(typeof(_data.arr[] = items[]))) + + auto bigDataFun() @trusted nothrow { return _data.arr.ptr[0 .. newlen];} + auto bigData = bigDataFun(); + + enum mustEmplace = is(typeof(bigData[0].opAssign(cast(Unqual!T)items.front))) || + !is(typeof(bigData[0] = cast(Unqual!T)items.front)); + + static if (is(typeof(_data.arr[] = items[])) && !mustEmplace) { - _data.arr.ptr[len..newlen] = items[]; + //pragma(msg, T.stringof); pragma(msg, Range.stringof); + bigData[len .. newlen] = items[]; + } + else static if (is(Unqual!T == ElementType!Range)) + { + foreach (ref it ; bigData[len .. newlen]) + { + static if (mustEmplace) + emplace(&it, items.front); + else + it = items.front; + items.popFront(); + } } else { - for (size_t i = len; !items.empty; items.popFront(), ++i) - _data.arr.ptr[i] = cast(Unqual!T)items.front; + static auto ref getUItem(U)(U item) @trusted {return cast(Unqual!T)item;} + foreach (ref it ; bigData[len .. newlen]) + { + static if (mustEmplace) + emplace(&it, getUItem(items.front)); + else + it = getUItem(items.front); + items.popFront(); + } } + + //We do this at the end, in case of exceptions + _data.arr = bigData; } else { @@ -2391,9 +2503,9 @@ Appends an entire range to the managed array. } } -/** -Appends one item to the managed array. - */ + /** + * Appends one item to the managed array. + */ void opOpAssign(string op : "~", U)(U item) if (canPutItem!U) { put(item); @@ -2405,43 +2517,43 @@ Appends one item to the managed array. put(items); } -/** -Appends an entire range to the managed array. - */ + /** + * Appends an entire range to the managed array. + */ void opOpAssign(string op : "~", Range)(Range items) if (canPutRange!Range) { put(items); } // only allow overwriting data on non-immutable and non-const data - static if (!is(T == immutable) && !is(T == const)) + static if (isMutable!T) { -/** -Clears the managed array. This allows the elements of the array to be reused -for appending. - -Note that clear is disabled for immutable or const element types, due to the -possibility that $(D Appender) might overwrite immutable data. -*/ - void clear() + /** + * Clears the managed array. This allows the elements of the array to be reused + * for appending. + * + * Note that clear is disabled for immutable or const element types, due to the + * possibility that $(D Appender) might overwrite immutable data. + */ + void clear() @safe pure nothrow { if (_data) { - _data.arr = _data.arr.ptr[0..0]; + _data.arr = ()@trusted{ return _data.arr.ptr[0 .. 0]; }(); } } -/** -Shrinks the managed array to the given length. - -Throws: $(D Exception) if newlength is greater than the current array length. -*/ - void shrinkTo(size_t newlength) + /** + * Shrinks the managed array to the given length. + * + * Throws: $(D Exception) if newlength is greater than the current array length. + */ + void shrinkTo(size_t newlength) @safe pure { if (_data) { enforce(newlength <= _data.arr.length); - _data.arr = _data.arr.ptr[0..newlength]; + _data.arr = ()@trusted{ return _data.arr.ptr[0 .. newlength]; }(); } else enforce(newlength == 0); @@ -2449,11 +2561,28 @@ Throws: $(D Exception) if newlength is greater than the current array length. } } +//Calculates an efficient growth scheme based on the old capacity +//of data, and the minimum requested capacity. +//arg curLen: The current length +//arg reqLen: The length as requested by the user +//ret sugLen: A suggested growth. +private size_t appenderNewCapacity(size_t TSizeOf)(size_t curLen, size_t reqLen) @safe pure nothrow +{ + if(curLen == 0) + return max(reqLen,8); + ulong mult = 100 + (1000UL) / (bsr(curLen * TSizeOf) + 1); + // limit to doubling the length, we don't want to grow too much + if(mult > 200) + mult = 200; + auto sugLen = cast(size_t)((curLen * mult + 99) / 100); + return max(reqLen, sugLen); +} + /** -An appender that can update an array in-place. It forwards all calls to an -underlying appender implementation. Any calls made to the appender also update -the pointer to the original array passed in. -*/ + * An appender that can update an array in-place. It forwards all calls to an + * underlying appender implementation. Any calls made to the appender also update + * the pointer to the original array passed in. + */ struct RefAppender(A : T[], T) { private @@ -2462,16 +2591,16 @@ struct RefAppender(A : T[], T) T[] *arr; } -/** -Construct a ref appender with a given array reference. This does not copy the -data. If the array has a larger capacity as determined by arr.capacity, it -will be used by the appender. $(D RefAppender) assumes that arr is a non-null -value. - -Note, do not use builtin appending (i.e. ~=) on the original array passed in -until you are done with the appender, because calls to the appender override -those appends. -*/ + /** + * Construct a ref appender with a given array reference. This does not copy the + * data. If the array has a larger capacity as determined by arr.capacity, it + * will be used by the appender. $(D RefAppender) assumes that arr is a non-null + * value. + * + * Note, do not use builtin appending (i.e. ~=) on the original array passed in + * until you are done with the appender, because calls to the appender override + * those appends. + */ this(T[] *arr) { impl = Appender!(A, T)(*arr); @@ -2487,9 +2616,9 @@ those appends. private alias Appender!(A, T) AppenderType; -/** -Appends one item to the managed array. - */ + /** + * Appends one item to the managed array. + */ void opOpAssign(string op : "~", U)(U item) if (AppenderType.canPutItem!U) { scope(exit) *this.arr = impl.data; @@ -2503,28 +2632,28 @@ Appends one item to the managed array. impl.put(items); } -/** -Appends an entire range to the managed array. - */ + /** + * Appends an entire range to the managed array. + */ void opOpAssign(string op : "~", Range)(Range items) if (AppenderType.canPutRange!Range) { scope(exit) *this.arr = impl.data; impl.put(items); } -/** -Returns the capacity of the array (the maximum number of elements the -managed array can accommodate before triggering a reallocation). If any -appending will reallocate, $(D capacity) returns $(D 0). - */ + /** + * Returns the capacity of the array (the maximum number of elements the + * managed array can accommodate before triggering a reallocation). If any + * appending will reallocate, $(D capacity) returns $(D 0). + */ @property size_t capacity() const { return impl.capacity; } -/** -Returns the managed array. - */ + /** + * Returns the managed array. + */ @property inout(T)[] data() inout { return impl.data; @@ -2532,15 +2661,30 @@ Returns the managed array. } /++ - Convenience function that returns an $(D Appender!(A)) object initialized + Convenience function that returns an $(D Appender!A) object initialized with $(D array). +/ -Appender!(E[]) appender(A : E[], E)(A array = null) +Appender!(E[]) appender(A : E[], E)() { - return Appender!(E[])(array); + return Appender!(E[])(null); +} +/// ditto +Appender!(E[]) appender(A : E[], E)(A array) +{ + static if (isMutable!E) + { + return Appender!(E[])(array); + } + else + { + /* @system operation: + * - casting array to Unqual!E[] (remove qualifiers) + */ + return Appender!(E[])(cast(Unqual!E[])array); + } } -unittest +@safe pure nothrow unittest { { auto app = appender!(char[])(); @@ -2577,7 +2721,11 @@ unittest app2.reserve(5); assert(app2.capacity >= 5); - app2.shrinkTo(3); + try // shrinkTo may throw + { + app2.shrinkTo(3); + } + catch (Exception) assert(0); assert(app2.data == [ 1, 2, 3 ]); assertThrown(app2.shrinkTo(5)); @@ -2586,7 +2734,11 @@ unittest assert(app3.data == [1, 2, 3]); auto app4 = appender([]); - app4.shrinkTo(0); + try // shrinkTo may throw + { + app4.shrinkTo(0); + } + catch (Exception) assert(0); // Issue 5663 & 9725 tests foreach (S; TypeTuple!(char[], const(char)[], string)) @@ -2601,7 +2753,7 @@ unittest assert(app5663c.data == "\xE3"); Appender!S app5663m; - assertNotThrown(app5663m.put(cast(char[])"\xE3")); + assertNotThrown(app5663m.put("\xE3".dup)); assert(app5663m.data == "\xE3"); } // ditto for ~= @@ -2615,7 +2767,7 @@ unittest assert(app5663c.data == "\xE3"); Appender!S app5663m; - assertNotThrown(app5663m ~= cast(char[])"\xE3"); + assertNotThrown(app5663m ~= "\xE3".dup); assert(app5663m.data == "\xE3"); } } @@ -2625,7 +2777,7 @@ unittest int val; @disable this(); - this(int v) { val = v; } + this(int v) @safe pure nothrow { val = v; } } assertCTFEable!( { @@ -2635,8 +2787,147 @@ unittest }); } +@safe pure nothrow unittest +{ + { + auto w = appender!string(); + w.reserve(4); + w.capacity; + w.data; + try + { + wchar wc = 'a'; + dchar dc = 'a'; + w.put(wc); // decoding may throw + w.put(dc); // decoding may throw + } + catch (Exception) assert(0); + } + { + auto w = appender!(int[])(); + w.reserve(4); + w.capacity; + w.data; + w.put(10); + w.put([10]); + w.clear(); + try + { + w.shrinkTo(0); + } + catch (Exception) assert(0); + + struct N + { + int payload; + alias payload this; + } + w.put(N(1)); + w.put([N(2)]); + + struct S(T) + { + @property bool empty() { return true; } + @property T front() { return T.init; } + void popFront() {} + } + S!int r; + w.put(r); + } +} + +unittest +{ + //10690 + [tuple(1)].filter!(t => true).array; // No error + [tuple("A")].filter!(t => true).array; // error +} + +unittest +{ + //Coverage for put(Range) + struct S1 + { + } + struct S2 + { + void opAssign(S2){} + } + auto a1 = Appender!(S1[])(); + auto a2 = Appender!(S2[])(); + auto au1 = Appender!(const(S1)[])(); + auto au2 = Appender!(const(S2)[])(); + a1.put(S1().repeat().take(10)); + a2.put(S2().repeat().take(10)); + auto sc1 = const(S1)(); + auto sc2 = const(S2)(); + au1.put(sc1.repeat().take(10)); + au2.put(sc2.repeat().take(10)); +} + +unittest +{ + struct S + { + int* p; + } + + auto a0 = Appender!(S[])(); + auto a1 = Appender!(const(S)[])(); + auto a2 = Appender!(immutable(S)[])(); + auto s0 = S(null); + auto s1 = const(S)(null); + auto s2 = immutable(S)(null); + a1.put(s0); + a1.put(s1); + a1.put(s2); + a1.put([s0]); + a1.put([s1]); + a1.put([s2]); + a0.put(s0); + static assert(!is(typeof(a0.put(a1)))); + static assert(!is(typeof(a0.put(a2)))); + a0.put([s0]); + static assert(!is(typeof(a0.put([a1])))); + static assert(!is(typeof(a0.put([a2])))); + static assert(!is(typeof(a2.put(a0)))); + static assert(!is(typeof(a2.put(a1)))); + a2.put(s2); + static assert(!is(typeof(a2.put([a0])))); + static assert(!is(typeof(a2.put([a1])))); + a2.put([s2]); +} + +unittest +{ //9528 + const(E)[] fastCopy(E)(E[] src) { + auto app = appender!(const(E)[])(); + foreach (i, e; src) + app.put(e); + return app.data; + } + + class C {} + struct S { const(C) c; } + S[] s = [ S(new C) ]; + + auto t = fastCopy(s); // Does not compile +} + +unittest +{ //10753 + struct Foo { + immutable dchar d; + } + struct Bar { + immutable int x; + } + "12".map!Foo.array; + [1, 2].map!Bar.array; +} + /++ - Convenience function that returns a $(D RefAppender!(A)) object initialized + Convenience function that returns a $(D RefAppender!A) object initialized with $(D array). Don't use null for the $(D array) pointer, use the other version of $(D appender) instead. +/ @@ -2686,7 +2977,11 @@ unittest app2.reserve(5); assert(app2.capacity >= 5); - app2.shrinkTo(3); + try // shrinkTo may throw + { + app2.shrinkTo(3); + } + catch (Exception) assert(0); assert(app2.data == [ 1, 2, 3 ]); assertThrown(app2.shrinkTo(5)); @@ -2695,6 +2990,14 @@ unittest assert(app3.data == [1, 2, 3]); } +unittest +{ + Appender!(int[]) app; + short[] range = [1, 2, 3]; + app.put(range); + assert(app.data == [1, 2, 3]); +} + /* A simple slice type only holding pointers to the beginning and the end of an array. Experimental duplication of the built-in slice - do not diff --git a/std/ascii.d b/std/ascii.d index b919721f7..fb05529a3 100644 --- a/std/ascii.d +++ b/std/ascii.d @@ -3,11 +3,12 @@ /++ Functions which operate on ASCII characters. - All of the functions in std.ascii accept unicode characters but effectively - ignore them. All $(D isX) functions return $(D false) for unicode - characters, and all $(D toX) functions do nothing to unicode characters. + All of the functions in std.ascii accept Unicode characters but effectively + ignore them if they're not ASCII. All $(D isX) functions return $(D false) + for non-ASCII characters, and all $(D toX) functions do nothing to non-ASCII + characters. - For functions which operate on unicode characters, see + For functions which operate on Unicode characters, see $(LINK2 std_uni.html, std.uni). References: @@ -17,26 +18,40 @@ Macros: WIKI=Phobos/StdASCII - Copyright: Copyright 2000 - + Copyright: Copyright 2000 - 2013 License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). Authors: $(WEB digitalmars.com, Walter Bright) and Jonathan M Davis Source: $(PHOBOSSRC std/_ascii.d) +/ module std.ascii; -version(unittest) import std.range; +version (unittest) +{ + // FIXME: When dmd bug #314 is fixed, make these selective. + import std.range; // : chain; + import std.traits; // : functionAttributes, FunctionAttribute, isSafe; + import std.typetuple; // : TypeTuple; +} -immutable hexDigits = "0123456789ABCDEF"; /// 0..9A..F immutable fullHexDigits = "0123456789ABCDEFabcdef"; /// 0..9A..Fa..f -immutable digits = "0123456789"; /// 0..9 -immutable octalDigits = "01234567"; /// 0..7 -immutable lowercase = "abcdefghijklmnopqrstuvwxyz"; /// a..z -immutable letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ~ - "abcdefghijklmnopqrstuvwxyz"; /// A..Za..z -immutable uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; /// A..Z +immutable hexDigits = fullHexDigits[0..16]; /// 0..9A..F +immutable lowerHexDigits = "0123456789abcdef"; /// 0..9a..f +immutable digits = hexDigits[0..10]; /// 0..9 +immutable octalDigits = digits[0..8]; /// 0..7 +immutable letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; /// A..Za..z +immutable uppercase = letters[0..26]; /// A..Z +immutable lowercase = letters[26..52]; /// a..z immutable whitespace = " \t\v\r\n\f"; /// ASCII whitespace +/** +Letter case specifier. + */ +enum LetterCase : bool +{ + upper, /// Upper case letters + lower /// Lower case letters +} version(Windows) { @@ -57,7 +72,7 @@ else +/ bool isAlphaNum(dchar c) @safe pure nothrow { - return c <= 0x7F ? cast(bool)(_ctype[c] & (_ALP|_DIG)) : false; + return c <= 'z' && c >= '0' && (c <= '9' || c >= 'a' || (c >= 'A' && c <= 'Z')); } unittest @@ -75,7 +90,8 @@ unittest +/ bool isAlpha(dchar c) @safe pure nothrow { - return c <= 0x7F ? cast(bool)(_ctype[c] & _ALP) : false; + // Optimizer can turn this into a bitmask operation on 64 bit code + return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); } unittest @@ -93,7 +109,7 @@ unittest +/ bool isLower(dchar c) @safe pure nothrow { - return c <= 0x7F ? cast(bool)(_ctype[c] & _LC) : false; + return c >= 'a' && c <= 'z'; } unittest @@ -111,7 +127,7 @@ unittest +/ bool isUpper(dchar c) @safe pure nothrow { - return c <= 0x7F ? cast(bool)(_ctype[c] & _UC) : false; + return c <= 'Z' && 'A' <= c; } unittest @@ -129,7 +145,7 @@ unittest +/ bool isDigit(dchar c) @safe pure nothrow { - return c <= 0x7F ? cast(bool)(_ctype[c] & _DIG) : false; + return '0' <= c && c <= '9'; } unittest @@ -165,7 +181,7 @@ unittest +/ bool isHexDigit(dchar c) @safe pure nothrow { - return c <= 0x7F ? cast(bool)(_ctype[c] & _HEX) : false; + return c <= 'f' && c >= '0' && (c <= '9' || c >= 'a' || (c >= 'A' && c <= 'F')); } unittest @@ -184,7 +200,7 @@ unittest +/ bool isWhite(dchar c) @safe pure nothrow { - return c <= 0x7F ? cast(bool)(_ctype[c] & _SPC) : false; + return c == ' ' || (c >= 0x09 && c <= 0x0D); } unittest @@ -202,12 +218,12 @@ unittest +/ bool isControl(dchar c) @safe pure nothrow { - return c <= 0x7F ? cast(bool)(_ctype[c] & _CTL) : false; + return c < 0x20 || c == 0x7F; } unittest { - foreach(dchar c; iota(0, 32)) + foreach(dchar c; 0 .. 32) assert(isControl(c)); assert(isControl(127)); @@ -222,12 +238,12 @@ unittest +/ bool isPunctuation(dchar c) @safe pure nothrow { - return c <= 0x7F ? cast(bool)(_ctype[c] & _PNC) : false; + return c <= '~' && c >= '!' && !isAlphaNum(c); } unittest { - foreach(dchar c; iota(0, 128)) + foreach(dchar c; 0 .. 128) { if(isControl(c) || isAlphaNum(c) || c == ' ') assert(!isPunctuation(c)); @@ -243,12 +259,12 @@ unittest +/ bool isGraphical(dchar c) @safe pure nothrow { - return c <= 0x7F ? cast(bool)(_ctype[c] & (_ALP|_DIG|_PNC)) : false; + return '!' <= c && c <= '~'; } unittest { - foreach(dchar c; iota(0, 128)) + foreach(dchar c; 0 .. 128) { if(isControl(c) || c == ' ') assert(!isGraphical(c)); @@ -257,18 +273,19 @@ unittest } } + /++ Whether or not $(D c) is a printable character - including the space character. +/ bool isPrintable(dchar c) @safe pure nothrow { - return c <= 0x7F ? cast(bool)(_ctype[c] & (_ALP|_DIG|_PNC|_BLK)) : false; + return c >= ' ' && c <= '~'; } unittest { - foreach(dchar c; iota(0, 128)) + foreach(dchar c; 0 .. 128) { if(isControl(c)) assert(!isPrintable(c)); @@ -289,7 +306,7 @@ bool isASCII(dchar c) @safe pure nothrow unittest { - foreach(dchar c; iota(0, 128)) + foreach(dchar c; 0 .. 128) assert(isASCII(c)); assert(!isASCII(128)); @@ -299,26 +316,48 @@ unittest /++ If $(D c) is an uppercase ASCII character, then its corresponding lowercase letter is returned. Otherwise, $(D c) is returned. + + $(D C) can be any type which implicitly converts to $(D dchar). In the case + where it's a built-in type, or an enum of a built-in type, + $(D Unqual!(OriginalType!C)) is returned, whereas if it's a user-defined + type, $(D dchar) is returned. +/ -dchar toLower(dchar c) @safe pure nothrow -out(result) +auto toLower(C)(C c) + if(is(C : dchar)) { - assert(!isUpper(result)); -} -body -{ - return isUpper(c) ? c + cast(dchar)('a' - 'A') : c; + import std.traits : isAggregateType, OriginalType, Unqual; + + alias OC = OriginalType!C; + static if (isAggregateType!OC) + alias R = dchar; + else + alias R = Unqual!OC; + + return isUpper(c) ? cast(R)(cast(R)c + 'a' - 'A') : cast(R)c; } -unittest +@safe pure nothrow unittest { - foreach(i, c; uppercase) - assert(toLower(c) == lowercase[i]); - foreach(dchar c; iota(0, 128)) + foreach(C; TypeTuple!(char, wchar, dchar, immutable char, ubyte)) { - if(c < 'A' || c > 'Z') + foreach(i, c; uppercase) + assert(toLower(cast(C)c) == lowercase[i]); + + foreach(C c; 0 .. 128) + { + if(c < 'A' || c > 'Z') + assert(toLower(c) == c); + else + assert(toLower(c) != c); + } + + foreach(C c; 128 .. C.max) assert(toLower(c) == c); + + //CTFE + static assert(toLower(cast(C)'a') == 'a'); + static assert(toLower(cast(C)'A') == 'a'); } } @@ -326,66 +365,102 @@ unittest /++ If $(D c) is a lowercase ASCII character, then its corresponding uppercase letter is returned. Otherwise, $(D c) is returned. + + $(D C) can be any type which implicitly converts to $(D dchar). In the case + where it's a built-in type, or an enum of a built-in type, + $(D Unqual!(OriginalType!C)) is returned, whereas if it's a user-defined + type, $(D dchar) is returned. +/ -dchar toUpper(dchar c) @safe pure nothrow -out(result) +auto toUpper(C)(C c) + if(is(C : dchar)) { - assert(!isLower(result)); -} -body -{ - return isLower(c) ? c - cast(dchar)('a' - 'A') : c; + import std.traits : isAggregateType, OriginalType, Unqual; + + alias OC = OriginalType!C; + static if (isAggregateType!OC) + alias R = dchar; + else + alias R = Unqual!OC; + + return isLower(c) ? cast(R)(cast(R)c - ('a' - 'A')) : cast(R)c; } -unittest +@safe pure nothrow unittest { - foreach(i, c; lowercase) - assert(toUpper(c) == uppercase[i]); - - foreach(dchar c; iota(0, 128)) + foreach(C; TypeTuple!(char, wchar, dchar, immutable char, ubyte)) { - if(c < 'a' || c > 'z') + foreach(i, c; lowercase) + assert(toUpper(cast(C)c) == uppercase[i]); + + foreach(C c; 0 .. 128) + { + if(c < 'a' || c > 'z') + assert(toUpper(c) == c); + else + assert(toUpper(c) != c); + } + + foreach(C c; 128 .. C.max) assert(toUpper(c) == c); + + //CTFE + static assert(toUpper(cast(C)'a') == 'A'); + static assert(toUpper(cast(C)'A') == 'A'); } } -//============================================================================== -// Private Section. -//============================================================================== -private: - -enum +unittest //Test both toUpper and toLower with non-builtin { - _SPC = 8, - _CTL = 0x20, - _BLK = 0x40, - _HEX = 0x80, - _UC = 1, - _LC = 2, - _PNC = 0x10, - _DIG = 4, - _ALP = _UC|_LC, + //User Defined [Char|Wchar|Dchar] + static struct UDC { char c; alias c this; } + static struct UDW { wchar c; alias c this; } + static struct UDD { dchar c; alias c this; } + //[Char|Wchar|Dchar] Enum + enum CE : char {a = 'a', A = 'A'} + enum WE : wchar {a = 'a', A = 'A'} + enum DE : dchar {a = 'a', A = 'A'} + //User Defined [Char|Wchar|Dchar] Enum + enum UDCE : UDC {a = UDC('a'), A = UDC('A')} + enum UDWE : UDW {a = UDW('a'), A = UDW('A')} + enum UDDE : UDD {a = UDD('a'), A = UDD('A')} + + //User defined types with implicit cast to dchar test. + foreach (Char; TypeTuple!(UDC, UDW, UDD)) + { + assert(toLower(Char('a')) == 'a'); + assert(toLower(Char('A')) == 'a'); + static assert(toLower(Char('a')) == 'a'); + static assert(toLower(Char('A')) == 'a'); + static assert(toUpper(Char('a')) == 'A'); + static assert(toUpper(Char('A')) == 'A'); + } + + //Various enum tests. + foreach (Enum; TypeTuple!(CE, WE, DE, UDCE, UDWE, UDDE)) + { + assert(toLower(Enum.a) == 'a'); + assert(toLower(Enum.A) == 'a'); + assert(toUpper(Enum.a) == 'A'); + assert(toUpper(Enum.A) == 'A'); + static assert(toLower(Enum.a) == 'a'); + static assert(toLower(Enum.A) == 'a'); + static assert(toUpper(Enum.a) == 'A'); + static assert(toUpper(Enum.A) == 'A'); + } + + //Return value type tests for enum of non-UDT. These should be the original type. + foreach (T; TypeTuple!(CE, WE, DE)) + { + alias C = OriginalType!T; + static assert(is(typeof(toLower(T.init)) == C)); + static assert(is(typeof(toUpper(T.init)) == C)); + } + + //Return value tests for UDT and enum of UDT. These should be dchar + foreach (T; TypeTuple!(UDC, UDW, UDD, UDCE, UDWE, UDDE)) + { + static assert(is(typeof(toLower(T.init)) == dchar)); + static assert(is(typeof(toUpper(T.init)) == dchar)); + } } - -immutable ubyte _ctype[128] = -[ - _CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL, - _CTL,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL,_CTL, - _CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL, - _CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL, - _SPC|_BLK,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC, - _PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC, - _DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX, - _DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX, - _PNC,_PNC,_PNC,_PNC,_PNC,_PNC, - _PNC,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC, - _UC,_UC,_UC,_UC,_UC,_UC,_UC,_UC, - _UC,_UC,_UC,_UC,_UC,_UC,_UC,_UC, - _UC,_UC,_UC,_PNC,_PNC,_PNC,_PNC,_PNC, - _PNC,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC, - _LC,_LC,_LC,_LC,_LC,_LC,_LC,_LC, - _LC,_LC,_LC,_LC,_LC,_LC,_LC,_LC, - _LC,_LC,_LC,_PNC,_PNC,_PNC,_PNC,_CTL -]; - diff --git a/std/base64.d b/std/base64.d index c9f7b2942..5613f9ef2 100644 --- a/std/base64.d +++ b/std/base64.d @@ -6,40 +6,35 @@ * Implemented according to $(WEB tools.ietf.org/html/rfc4648, * RFC 4648 - The Base16, Base32, and Base64 Data Encodings). * -* Example: - * $(D_RUN_CODE - * $(ARGS + * Example: * ----- - *ubyte[] data = [0x14, 0xfb, 0x9c, 0x03, 0xd9, 0x7e]; + * ubyte[] data = [0x14, 0xfb, 0x9c, 0x03, 0xd9, 0x7e]; * - *const(char)[] encoded = Base64.encode(data); - *assert(encoded == "FPucA9l+"); + * const(char)[] encoded = Base64.encode(data); + * assert(encoded == "FPucA9l+"); * - *ubyte[] decoded = Base64.decode("FPucA9l+"); - *assert(decoded == [0x14, 0xfb, 0x9c, 0x03, 0xd9, 0x7e]); + * ubyte[] decoded = Base64.decode("FPucA9l+"); + * assert(decoded == [0x14, 0xfb, 0x9c, 0x03, 0xd9, 0x7e]); * ----- - * ), $(ARGS), $(ARGS), $(ARGS import std.base64;)) + * * Support Range interface using Encoder / Decoder. * * Example: - * $(D_RUN_CODE - * $(ARGS * ----- * // Create MIME Base64 with CRLF, per line 76. - *File f = File("./text.txt", "r"); - *scope(exit) f.close(); + * File f = File("./text.txt", "r"); + * scope(exit) f.close(); * - *Appender!string mime64 = appender!string; + * Appender!string mime64 = appender!string; * - *foreach (encoded; Base64.encoder(f.byChunk(57))) - *{ - * mime64.put(encoded); - * mime64.put("\r\n"); - *} + * foreach (encoded; Base64.encoder(f.byChunk(57))) + * { + * mime64.put(encoded); + * mime64.put("\r\n"); + * } * - *writeln(mime64.data); + * writeln(mime64.data); * ----- - *), $(ARGS), $(ARGS), $(ARGS import std.base64, std.array, std.stdio: File, writeln;)) * * Copyright: Masahiro Nakagawa 2010-. * License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). @@ -134,7 +129,7 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=') * * Params: * source = an $(D InputRange) to encode. - * range = a buffer to store encoded result. + * buffer = a buffer to store encoded result. * * Returns: * the encoded string that slices buffer. @@ -459,7 +454,7 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=') * true if there are no more elements to be iterated. */ @property @trusted - bool empty() const + bool empty() { return range_.empty; } @@ -672,36 +667,30 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=') * Default $(D Encoder) encodes chunk data. * * Example: - *$(D_RUN_CODE - *$(ARGS * ----- - *File f = File("text.txt", "r"); - *scope(exit) f.close(); + * File f = File("text.txt", "r"); + * scope(exit) f.close(); * - *uint line = 0; - *foreach (encoded; Base64.encoder(f.byLine())) - *{ - * writeln(++line, ". ", encoded); - *} + * uint line = 0; + * foreach (encoded; Base64.encoder(f.byLine())) + * { + * writeln(++line, ". ", encoded); + * } * ----- - *), $(ARGS), $(ARGS), $(ARGS import std.base64, std.stdio: File, writeln;)) * * In addition, You can use $(D Encoder) that returns encoded single character. * This $(D Encoder) performs Range-based and lazy encoding. * * Example: - *$(D_RUN_CODE - *$(ARGS * ----- - *ubyte[] data = cast(ubyte[]) "0123456789"; + * ubyte[] data = cast(ubyte[]) "0123456789"; * * // The ElementType of data is not aggregation type - *foreach (encoded; Base64.encoder(data)) - *{ - * writeln(encoded); - *} + * foreach (encoded; Base64.encoder(data)) + * { + * writeln(encoded); + * } * ----- - *), $(ARGS), $(ARGS), $(ARGS import std.base64, std.stdio: writeln;)) * * Params: * range = an $(D InputRange) to iterate. @@ -1125,7 +1114,7 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=') * true if there are no more elements to be iterated. */ @property @trusted - bool empty() const + bool empty() { return range_.empty; } @@ -1357,31 +1346,24 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=') * Default $(D Decoder) decodes chunk data. * * Example: - *$(D_RUN_CODE - *$(ARGS * ----- - *foreach (decoded; Base64.decoder(stdin.byLine())) - *{ - * writeln(decoded); - *} + * foreach (decoded; Base64.decoder(stdin.byLine())) + * { + * writeln(decoded); + * } * ----- - *), $(ARGS FPucA9l+), $(ARGS), $(ARGS import std.base64, std.stdio;)) * * In addition, You can use $(D Decoder) that returns decoded single character. * This $(D Decoder) performs Range-based and lazy decoding. * * Example: - *$(D_RUN_CODE - *$(ARGS * ----- - *auto encoded = Base64.encoder(cast(ubyte[])"0123456789"); - *foreach (n; map!q{a - '0'}(Base64.decoder(encoded))) - *{ - * writeln(n); - *} + * auto encoded = Base64.encoder(cast(ubyte[])"0123456789"); + * foreach (n; map!q{a - '0'}(Base64.decoder(encoded))) + * { + * writeln(n); + * } * ----- - *), $(ARGS), $(ARGS), $(ARGS import std.base64, std.stdio: writeln; - *import std.algorithm: map;)) * * NOTE: * If you use $(D ByChunk), chunk-size should be the multiple of 4. @@ -1430,6 +1412,7 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=') */ class Base64Exception : Exception { + @safe pure nothrow this(string s, string fn = __FILE__, size_t ln = __LINE__) { super(s, fn, ln); @@ -1576,6 +1559,9 @@ unittest assert(tv["foobar"] == b.data); a.clear(); b.clear(); } + // @@@9543@@@ These tests were disabled because they actually relied on the input range having length. + // The implementation (currently) doesn't support encoding/decoding from a length-less source. + version(none) { // with InputRange // InputRange to ubyte[] or char[] auto encoded = Base64.encode(map!(to!(ubyte))(["20", "251", "156", "3", "217", "126"])); diff --git a/std/bigint.d b/std/bigint.d index 73c4e416d..a9fd0d421 100644 --- a/std/bigint.d +++ b/std/bigint.d @@ -32,7 +32,7 @@ private import std.traits; /** A struct representing an arbitrary precision integer * * All arithmetic operations are supported, except - * unsigned shift right (>>>). Logical operations are not currently supported. + * unsigned shift right (>>>). Bitwise operations (|, &, ^, ~) are supported, and behave as if BigInt was an infinite length 2's complement number. * * BigInt implements value semantics using copy-on-write. This means that * assignment is cheap, but operations such as x++ will cause heap @@ -111,6 +111,12 @@ public: data = data.init; // @@@: Workaround for compiler bug opAssign(x); } + + /// + this(T)(T x) pure if (is(Unqual!T == BigInt)) + { + opAssign(x); + } /// BigInt opAssign(T)(T x) pure if (isIntegral!T) @@ -131,7 +137,7 @@ public: // BigInt op= integer BigInt opOpAssign(string op, T)(T y) pure if ((op=="+" || op=="-" || op=="*" || op=="/" || op=="%" - || op==">>" || op=="<<" || op=="^^") && isIntegral!T) + || op==">>" || op=="<<" || op=="^^" || op=="|" || op=="&" || op=="^") && isIntegral!T) { ulong u = absUnsign(y); @@ -196,13 +202,18 @@ public: sign = (y & 1) ? sign : false; data = BigUint.pow(data, u); } + else static if (op=="|" || op=="&" || op=="^") + { + BigInt b = y; + opOpAssign!op(b); + } else static assert(0, "BigInt " ~ op[0..$-1] ~ "= " ~ T.stringof ~ " is not supported"); return this; } // BigInt op= BigInt BigInt opOpAssign(string op, T)(T y) pure - if ((op=="+" || op== "-" || op=="*" || op=="/" || op=="%") + if ((op=="+" || op== "-" || op=="*" || op=="/" || op=="%" || op=="|" || op=="&" || op=="^") && is (T: BigInt)) { static if (op == "+") @@ -238,13 +249,17 @@ public: sign = false; } } + else static if (op == "|" || op == "&" || op == "^") + { + data = BigUint.bitwiseOp!op(data, y.data, sign, y.sign, sign); + } else static assert(0, "BigInt " ~ op[0..$-1] ~ "= " ~ T.stringof ~ " is not supported"); return this; } // BigInt op BigInt - BigInt opBinary(string op, T)(T y) pure - if ((op=="+" || op == "*" || op=="-" || op=="/" || op=="%") + BigInt opBinary(string op, T)(T y) pure const + if ((op=="+" || op == "*" || op=="-" || op=="/" || op=="%" || op=="|" || op=="&" || op=="^") && is (T: BigInt)) { BigInt r = this; @@ -252,8 +267,8 @@ public: } // BigInt op integer - BigInt opBinary(string op, T)(T y) pure - if ((op=="+" || op == "*" || op=="-" || op=="/" + BigInt opBinary(string op, T)(T y) pure const + if ((op=="+" || op == "*" || op=="-" || op=="/" || op=="|" || op=="&" || op=="^" || op==">>" || op=="<<" || op=="^^") && isIntegral!T) { BigInt r = this; @@ -261,7 +276,7 @@ public: } // - int opBinary(string op, T : int)(T y) pure + int opBinary(string op, T : int)(T y) pure const if (op == "%" && isIntegral!T) { assert(y!=0); @@ -273,14 +288,14 @@ public: } // Commutative operators - BigInt opBinaryRight(string op, T)(T y) pure - if ((op=="+" || op=="*") && isIntegral!T) + BigInt opBinaryRight(string op, T)(T y) pure const + if ((op=="+" || op=="*" || op=="|" || op=="&" || op=="^") && isIntegral!T) { return opBinary!(op)(y); } // BigInt = integer op BigInt - BigInt opBinaryRight(string op, T)(T y) pure + BigInt opBinaryRight(string op, T)(T y) pure const if (op == "-" && isIntegral!T) { ulong u = absUnsign(y); @@ -295,7 +310,7 @@ public: } // integer = integer op BigInt - T opBinaryRight(string op, T)(T x) pure + T opBinaryRight(string op, T)(T x) pure const if ((op=="%" || op=="/") && isIntegral!T) { static if (op == "%") @@ -318,7 +333,7 @@ public: } } // const unary operations - BigInt opUnary(string op)() pure /*const*/ if (op=="+" || op=="-") + BigInt opUnary(string op)() pure const if (op=="+" || op=="-" || op=="~") { static if (op=="-") { @@ -326,6 +341,10 @@ public: r.negate(); return r; } + else static if (op=="~") + { + return -(this+1); + } else static if (op=="+") return this; } @@ -360,13 +379,27 @@ public: } /// - T opCast(T:bool)() pure + T opCast(T:bool)() pure const { return !isZero(); } + + /// + T opCast(T)() pure const if (is(Unqual!T == BigInt)) { + return this; + } + + // Hack to make BigInt's typeinfo.compare work properly. + // Note that this must appear before the other opCmp overloads, otherwise + // DMD won't find it. + int opCmp(ref const BigInt y) const + { + // Simply redirect to the "real" opCmp implementation. + return this.opCmp!BigInt(y); + } /// - int opCmp(T)(T y) pure if (isIntegral!T) + int opCmp(T)(T y) pure const if (isIntegral!T) { if (sign != (y<0) ) return sign ? -1 : 1; @@ -374,7 +407,7 @@ public: return sign? -cmp: cmp; } /// - int opCmp(T:BigInt)(T y) pure + int opCmp(T:BigInt)(const T y) pure const { if (sign!=y.sign) return sign ? -1 : 1; @@ -504,9 +537,15 @@ private: if (isZero()) throw new Error("BigInt division by zero"); } + + // Implement toHash so that BigInt works properly as an AA key. + size_t toHash() const @trusted nothrow + { + return data.toHash() + sign; + } } -string toDecimalString(BigInt x) +string toDecimalString(const(BigInt) x) { string outbuff=""; void sink(const(char)[] s) { outbuff ~= s; } @@ -514,7 +553,7 @@ string toDecimalString(BigInt x) return outbuff; } -string toHex(BigInt x) +string toHex(const(BigInt) x) { string outbuff=""; void sink(const(char)[] s) { outbuff ~= s; } @@ -527,6 +566,7 @@ Unsigned!T absUnsign(T)(T x) if (isIntegral!T) { static if (isSigned!T) { + import std.conv; /* This returns the correct result even when x = T.min * on two's complement machines because unsigned(T.min) = |T.min| * even though -T.min = T.min. @@ -774,6 +814,11 @@ unittest import std.math:abs; auto r = abs(BigInt(-1000)); // 6486 assert(r == 1000); + + auto r2 = abs(const(BigInt)(-500)); // 11188 + assert(r2 == 500); + auto r3 = abs(immutable(BigInt)(-733)); // 11188 + assert(r3 == 733); // opCast!bool BigInt one = 1, zero; @@ -791,3 +836,110 @@ unittest // 6850 assert(pureTest() == 1337); } + +unittest // 8435 & 10118 +{ + auto i = BigInt(100); + auto j = BigInt(100); + + // Two separate BigInt instances representing same value should have same + // hash. + assert(typeid(i).getHash(&i) == typeid(j).getHash(&j)); + assert(typeid(i).compare(&i, &j) == 0); + + // BigInt AA keys should behave consistently. + int[BigInt] aa; + aa[BigInt(123)] = 123; + assert(BigInt(123) in aa); + + aa[BigInt(123)] = 321; + assert(aa[BigInt(123)] == 321); + + auto keys = aa.byKey; + assert(keys.front == BigInt(123)); + keys.popFront(); + assert(keys.empty); +} + +unittest // 11148 +{ + void foo(BigInt) {} + const BigInt cbi = 3; + immutable BigInt ibi = 3; + + assert(__traits(compiles, foo(cbi))); + assert(__traits(compiles, foo(ibi))); + + import std.typetuple : TypeTuple; + import std.conv : to; + + foreach (T1; TypeTuple!(BigInt, const(BigInt), immutable(BigInt))) + { + foreach (T2; TypeTuple!(BigInt, const(BigInt), immutable(BigInt))) + { + T1 t1 = 2; + T2 t2 = t1; + + T2 t2_1 = to!T2(t1); + T2 t2_2 = cast(T2)t1; + + assert(t2 == t1); + assert(t2 == 2); + + assert(t2_1 == t1); + assert(t2_1 == 2); + + assert(t2_2 == t1); + assert(t2_2 == 2); + } + } + + BigInt n = 2; + n *= 2; +} + +unittest // 8167 +{ + BigInt a = BigInt(3); + BigInt b = BigInt(a); +} + +unittest // 9061 +{ + long l1 = 0x12345678_90ABCDEF; + long l2 = 0xFEDCBA09_87654321; + long l3 = l1 | l2; + long l4 = l1 & l2; + long l5 = l1 ^ l2; + + BigInt b1 = l1; + BigInt b2 = l2; + BigInt b3 = b1 | b2; + BigInt b4 = b1 & b2; + BigInt b5 = b1 ^ b2; + + assert(l3 == b3); + assert(l4 == b4); + assert(l5 == b5); +} + +unittest // 11600 +{ + import std.conv; + import std.exception : assertThrown; + + // Original bug report + assertThrown!ConvException(to!BigInt("avadakedavra")); + + // Digit string lookalikes that are actually invalid + assertThrown!ConvException(to!BigInt("0123hellothere")); + assertThrown!ConvException(to!BigInt("-hihomarylowe")); + assertThrown!ConvException(to!BigInt("__reallynow__")); + assertThrown!ConvException(to!BigInt("-123four")); +} + +unittest // 11583 +{ + BigInt x = 0; + assert((x > 0) == false); +} diff --git a/std/bitmanip.d b/std/bitmanip.d index dc0e0949e..11dcd9b16 100644 --- a/std/bitmanip.d +++ b/std/bitmanip.d @@ -69,23 +69,22 @@ private template createAccessors( } else { - static if (len + offset <= uint.sizeof * 8) - alias uint MasksType; - else - alias ulong MasksType; - enum MasksType - maskAllElse = ((1uL << len) - 1u) << offset, - signBitCheck = 1uL << (len - 1), - extendSign = ~((cast(MasksType)1u << len) - 1); + enum ulong + maskAllElse = ((~0uL) >> (64 - len)) << offset, + signBitCheck = 1uL << (len - 1); + static if (T.min < 0) { enum long minVal = -(1uL << (len - 1)); enum ulong maxVal = (1uL << (len - 1)) - 1; + alias Unsigned!(T) UT; + enum UT extendSign = cast(UT)~((~0uL) >> (64 - len)); } else { enum ulong minVal = 0; - enum ulong maxVal = (1uL << len) - 1; + enum ulong maxVal = (~0uL) >> (64 - len); + enum extendSign = 0; } static if (is(T == bool)) @@ -216,6 +215,106 @@ template bitfields(T...) enum { bitfields = createFields!(createStoreName!(T), 0, T).result } } +unittest +{ + // Degenerate bitfields (#8474 / #11160) tests mixed with range tests + struct Test1 + { + mixin(bitfields!(uint, "a", 32, + uint, "b", 4, + uint, "c", 4, + uint, "d", 8, + uint, "e", 16,)); + + static assert(Test1.b_min == 0); + static assert(Test1.b_max == 15); + } + + struct Test2 + { + mixin(bitfields!(bool, "a", 0, + ulong, "b", 64)); + + static assert(Test2.b_min == ulong.min); + static assert(Test2.b_max == ulong.max); + } + + struct Test1b + { + mixin(bitfields!(bool, "a", 0, + int, "b", 8)); + } + + struct Test2b + { + mixin(bitfields!(int, "a", 32, + int, "b", 4, + int, "c", 4, + int, "d", 8, + int, "e", 16,)); + + static assert(Test2b.b_min == -8); + static assert(Test2b.b_max == 7); + } + + struct Test3b + { + mixin(bitfields!(bool, "a", 0, + long, "b", 64)); + + static assert(Test3b.b_min == long.min); + static assert(Test3b.b_max == long.max); + } + + struct Test4b + { + mixin(bitfields!(long, "a", 32, + int, "b", 32)); + } + + // Sign extension tests + Test2b t2b; + Test4b t4b; + t2b.b = -5; assert(t2b.b == -5); + t2b.d = -5; assert(t2b.d == -5); + t2b.e = -5; assert(t2b.e == -5); + t4b.a = -5; assert(t4b.a == -5L); +} + +unittest +{ + // Bug #6686 + union S { + ulong bits = ulong.max; + mixin (bitfields!( + ulong, "back", 31, + ulong, "front", 33) + ); + } + S num; + + num.bits = ulong.max; + num.back = 1; + assert(num.bits == 0xFFFF_FFFF_8000_0001uL); +} + +unittest +{ + // Bug #5942 + struct S + { + mixin(bitfields!( + int, "a" , 32, + int, "b" , 32 + )); + } + + S data; + data.b = 42; + data.a = 1; + assert(data.b == 42); +} + unittest { struct Test @@ -723,9 +822,8 @@ struct BitArray lo++; hi--; } - Ldone: - ; } + Ldone: return this; } diff --git a/std/c/linux/tipc.d b/std/c/linux/tipc.d index 7ed6a85ea..b2e60e388 100644 --- a/std/c/linux/tipc.d +++ b/std/c/linux/tipc.d @@ -36,7 +36,7 @@ struct tipc_subscr tipc_name_seq seq; uint timeout; uint filter; - ubyte usr_handle[8]; + ubyte[8] usr_handle; } struct tipc_event diff --git a/std/c/stdio.d b/std/c/stdio.d index b31a855ae..40ea1b228 100644 --- a/std/c/stdio.d +++ b/std/c/stdio.d @@ -18,13 +18,4 @@ extern (C): version (Windows) { extern shared ubyte[_NFILE] __fhnd_info; - - enum - { - FHND_APPEND = 0x04, - FHND_DEVICE = 0x08, - FHND_TEXT = 0x10, - FHND_BYTE = 0x20, - FHND_WCHAR = 0x40, - } } diff --git a/std/c/windows/com.d b/std/c/windows/com.d index 5d97fcd30..4aa0f2fa1 100644 --- a/std/c/windows/com.d +++ b/std/c/windows/com.d @@ -1,4 +1,5 @@ module std.c.windows.com; +version (Windows): pragma(lib,"uuid"); @@ -38,7 +39,7 @@ struct GUID { // size is 16 DWORD Data1; WORD Data2; WORD Data3; - BYTE Data4[8]; + BYTE[8] Data4; } enum @@ -58,11 +59,11 @@ enum } enum -{ +{ COINIT_APARTMENTTHREADED = 0x2, COINIT_MULTITHREADED = 0x0, COINIT_DISABLE_OLE1DDE = 0x4, - COINIT_SPEED_OVER_MEMORY = 0x8 + COINIT_SPEED_OVER_MEMORY = 0x8 } alias DWORD COINIT; enum RPC_E_CHANGED_MODE = 0x80010106; diff --git a/std/c/windows/stat.d b/std/c/windows/stat.d index daada90d4..1d219e1ee 100644 --- a/std/c/windows/stat.d +++ b/std/c/windows/stat.d @@ -3,13 +3,12 @@ /// Author: Walter Bright module std.c.windows.stat; +version (Windows): extern (C): // linux version is in std.c.linux.linux -version (Windows) -{ const S_IFMT = 0xF000; const S_IFDIR = 0x4000; const S_IFCHR = 0x2000; @@ -46,4 +45,3 @@ struct struct_stat int stat(char *, struct_stat *); int fstat(int, struct_stat *); int _wstat(wchar *, struct_stat *); -} diff --git a/std/c/windows/windows.d b/std/c/windows/windows.d index 792ec7e8f..8e44ed07f 100644 --- a/std/c/windows/windows.d +++ b/std/c/windows/windows.d @@ -3,13 +3,6 @@ States and other countries. */ module std.c.windows.windows; +version (Windows): public import core.sys.windows.windows; - -version (Windows) -{ -} -else -{ - static assert(0); // Windows only -} diff --git a/std/c/windows/winsock.d b/std/c/windows/winsock.d index 9f1d62f5f..9028545f8 100644 --- a/std/c/windows/winsock.d +++ b/std/c/windows/winsock.d @@ -5,6 +5,7 @@ module std.c.windows.winsock; +version (Windows): private import std.stdint; private import std.c.windows.windows; @@ -25,8 +26,8 @@ struct WSADATA { WORD wVersion; WORD wHighVersion; - char szDescription[WSADESCRIPTION_LEN + 1]; - char szSystemStatus[WSASYS_STATUS_LEN + 1]; + char[WSADESCRIPTION_LEN + 1] szDescription; + char[WSASYS_STATUS_LEN + 1] szSystemStatus; USHORT iMaxSockets; USHORT iMaxUdpDg; char* lpVendorInfo; diff --git a/std/complex.d b/std/complex.d index d77347849..80e77e08f 100644 --- a/std/complex.d +++ b/std/complex.d @@ -15,10 +15,7 @@ module std.complex; -import std.format; -import std.math; -import std.numeric; -import std.traits; +import std.format, std.math, std.numeric, std.traits; /** Helper function that returns a _complex number with the specified @@ -115,36 +112,85 @@ struct Complex(T) if (isFloatingPoint!T) /** Converts the complex number to a string representation. - If a $(D sink) delegate is specified, the string is passed to it - and this function returns $(D null). Otherwise, this function - returns the string representation directly. + The second form of this function is usually not called directly; + instead, it is used via $(XREF string,format), as shown in the examples + below. Supported format characters are 'e', 'f', 'g', 'a', and 's'. - The output format is controlled via $(D formatSpec), which should consist - of a single POSIX format specifier, including the percent (%) character. - Note that complex numbers are floating point numbers, so the only - valid format characters are 'e', 'f', 'g', 'a', and 's', where 's' - gives the default behaviour. Positional parameters are not valid - in this context. - - See the $(LINK2 std_format.html, std.format documentation) for - more information. + See the $(LINK2 std_format.html, std.format) and $(XREF string, format) + documentation for more information. */ - string toString(scope void delegate(const(char)[]) sink = null, + string toString() const /* TODO: pure @safe nothrow */ + { + import std.exception : assumeUnique; + char[] buf; + buf.reserve(100); + auto fmt = FormatSpec!char("%s"); + toString((const(char)[] s) { buf ~= s; }, fmt); + return assumeUnique(buf); + } + + static if (is(T == double)) + /// + unittest + { + auto c = complex(1.2, 3.4); + + // Vanilla toString formatting: + assert(c.toString() == "1.2+3.4i"); + + // Formatting with std.string.format specs: the precision and width + // specifiers apply to both the real and imaginary parts of the + // complex number. + import std.string : format; + assert(format("%.2f", c) == "1.20+3.40i"); + assert(format("%4.1f", c) == " 1.2+ 3.4i"); + } + + /// ditto + void toString(Char)(scope void delegate(const(Char)[]) sink, + FormatSpec!Char formatSpec) const + { + formatValue(sink, re, formatSpec); + if (signbit(im) == 0) sink("+"); + formatValue(sink, im, formatSpec); + sink("i"); + } + + /** + * $(RED Deprecated. This function will be removed in March 2014. + * Please use $(XREF string,format) instead.) + * + * Converts the complex number to a string representation. + * + * If a $(D sink) delegate is specified, the string is passed to it + * and this function returns $(D null). Otherwise, this function + * returns the string representation directly. + + * The output format is controlled via $(D formatSpec), which should consist + * of a single POSIX format specifier, including the percent (%) character. + * Note that complex numbers are floating point numbers, so the only + * valid format characters are 'e', 'f', 'g', 'a', and 's', where 's' + * gives the default behaviour. Positional parameters are not valid + * in this context. + * + * See the $(LINK2 std_format.html, std.format) and $(XREF string, format) + * documentation for more information. + */ + deprecated("Please use std.string.format instead.") + string toString(scope void delegate(const(char)[]) sink, string formatSpec = "%s") const { if (sink == null) { + import std.exception : assumeUnique; char[] buf; buf.reserve(100); - toString((const(char)[] s) { buf ~= s; }, formatSpec); - return cast(string) buf; + formattedWrite((const(char)[] s) { buf ~= s; }, formatSpec, this); + return assumeUnique(buf); } - formattedWrite(sink, formatSpec, re); - if (signbit(im) == 0) sink("+"); - formattedWrite(sink, formatSpec, im); - sink("i"); + formattedWrite(sink, formatSpec, this); return null; } @@ -155,7 +201,7 @@ struct Complex(T) if (isFloatingPoint!T) re = z.re; im = z.im; } - + this(Rx : T, Ry : T)(Rx x, Ry y) { re = x; @@ -276,6 +322,30 @@ struct Complex(T) if (isFloatingPoint!T) return w; } + // numeric ^^ complex + Complex!(CommonType!(T, R)) opBinaryRight(string op, R)(R lhs) const + if (op == "^^" && isNumeric!R) + { + FPTemporary!(CommonType!(T, R)) ab = void, ar = void; + + if (lhs >= 0) + { + // r = lhs + // theta = 0 + ab = lhs ^^ this.re; + ar = log(lhs) * this.im; + } + else + { + // r = -lhs + // theta = PI + ab = (-lhs) ^^ this.re * exp(-PI * this.im); + ar = PI * this.re + log(-lhs) * this.im; + } + + return typeof(return)(ab * std.math.cos(ar), ab * std.math.sin(ar)); + } + // OP-ASSIGN OPERATORS // complex += complex, complex -= complex @@ -446,6 +516,10 @@ unittest assert (approxEqual(abs(cdr), abs(c1)/a, EPS)); assert (approxEqual(arg(cdr), arg(c1), EPS)); + auto cer = c1^^3.0; + assert (approxEqual(abs(cer), abs(c1)^^3, EPS)); + assert (approxEqual(arg(cer), arg(c1)*3, EPS)); + auto rpc = a + c1; assert (rpc == cpr); @@ -460,9 +534,60 @@ unittest assert (approxEqual(abs(rdc), a/abs(c1), EPS)); assert (approxEqual(arg(rdc), -arg(c1), EPS)); - auto cer = c1^^3.0; - assert (approxEqual(abs(cer), abs(c1)^^3, EPS)); - assert (approxEqual(arg(cer), arg(c1)*3, EPS)); + auto rec1a = 1.0 ^^ c1; + assert(rec1a.re == 1.0); + assert(rec1a.im == 0.0); + + auto rec2a = 1.0 ^^ c2; + assert(rec2a.re == 1.0); + assert(rec2a.im == 0.0); + + auto rec1b = (-1.0) ^^ c1; + assert(approxEqual(abs(rec1b), std.math.exp(-PI * c1.im), EPS)); + auto arg1b = arg(rec1b); + /* The argument _should_ be PI, but floating-point rounding error + * means that in fact the imaginary part is very slightly negative. + */ + assert(approxEqual(arg1b, PI, EPS) || approxEqual(arg1b, -PI, EPS)); + + auto rec2b = (-1.0) ^^ c2; + assert(approxEqual(abs(rec2b), std.math.exp(-2 * PI), EPS)); + assert(approxEqual(arg(rec2b), PI_2, EPS)); + + auto rec3a = 0.79 ^^ complex(6.8, 5.7); + auto rec3b = complex(0.79, 0.0) ^^ complex(6.8, 5.7); + assert(approxEqual(rec3a.re, rec3b.re, EPS)); + assert(approxEqual(rec3a.im, rec3b.im, EPS)); + + auto rec4a = (-0.79) ^^ complex(6.8, 5.7); + auto rec4b = complex(-0.79, 0.0) ^^ complex(6.8, 5.7); + assert(approxEqual(rec4a.re, rec4b.re, EPS)); + assert(approxEqual(rec4a.im, rec4b.im, EPS)); + + auto rer = a ^^ complex(2.0, 0.0); + auto rcheck = a ^^ 2.0; + static assert(is(typeof(rcheck) == double)); + assert(feqrel(rer.re, rcheck) == double.mant_dig); + assert(isIdentical(rer.re, rcheck)); + assert(rer.im == 0.0); + + auto rer2 = (-a) ^^ complex(2.0, 0.0); + rcheck = (-a) ^^ 2.0; + assert(feqrel(rer2.re, rcheck) == double.mant_dig); + assert(isIdentical(rer2.re, rcheck)); + assert(approxEqual(rer2.im, 0.0, EPS)); + + auto rer3 = (-a) ^^ complex(-2.0, 0.0); + rcheck = (-a) ^^ (-2.0); + assert(feqrel(rer3.re, rcheck) == double.mant_dig); + assert(isIdentical(rer3.re, rcheck)); + assert(approxEqual(rer3.im, 0.0, EPS)); + + auto rer4 = a ^^ complex(-2.0, 0.0); + rcheck = a ^^ (-2.0); + assert(feqrel(rer4.re, rcheck) == double.mant_dig); + assert(isIdentical(rer4.re, rcheck)); + assert(rer4.im == 0.0); // Check Complex-int operations. foreach (i; 0..6) @@ -497,7 +622,7 @@ unittest } unittest -{ +{ // Assignments and comparisons Complex!double z; @@ -740,3 +865,36 @@ unittest assert (sqrt(complex(1.0L, 0)) == std.math.sqrt(1.0L)); assert (sqrt(complex(-1.0L, 0)) == complex(0, 1.0L)); } + +// Issue 10881: support %f formatting of complex numbers +unittest +{ + import std.string : format; + + auto x = complex(1.2, 3.4); + assert(format("%.2f", x) == "1.20+3.40i"); + + auto y = complex(1.2, -3.4); + assert(format("%.2f", y) == "1.20-3.40i"); +} + +unittest +{ + // Test wide string formatting + wstring wformat(T)(string format, Complex!T c) + { + import std.array : appender; + auto w = appender!wstring(); + auto n = formattedWrite(w, format, c); + return w.data; + } + + auto x = complex(1.2, 3.4); + assert(wformat("%.2f", x) == "1.20+3.40i"w); +} + +unittest +{ + // Test ease of use (vanilla toString() should be supported) + assert(complex(1.2, 3.4).toString() == "1.2+3.4i"); +} diff --git a/std/concurrency.d b/std/concurrency.d index 66be70b8b..6335e5301 100644 --- a/std/concurrency.d +++ b/std/concurrency.d @@ -13,8 +13,6 @@ * additional features specific to in-process messaging. * * Synposis: - *$(D_RUN_CODE - *$(ARGS * --- * import std.stdio; * import std.concurrency; @@ -45,7 +43,6 @@ * writeln("Successfully printed number."); * } * --- - *), $(ARGS), $(ARGS), $(ARGS)) * * Copyright: Copyright Sean Kelly 2009 - 2010. * License: Boost License 1.0. @@ -194,17 +191,6 @@ private } -shared static this() -{ - // NOTE: Normally, mbox is initialized by spawn() or thisTid(). This - // doesn't support the simple case of calling only receive() in main - // however. To ensure that this works, initialize the main thread's - // mbox field here (as shared static ctors are run once on startup - // by the main thread). - mbox = new MessageBox; -} - - static ~this() { if( mbox !is null ) @@ -425,8 +411,6 @@ private template isSpawnable(F, T...) * threads. * * Example: - *$(D_RUN_CODE - *$(ARGS * --- * import std.stdio, std.concurrency; * @@ -451,7 +435,6 @@ private template isSpawnable(F, T...) * auto tid2 = spawn(&f2, str.dup); * } * --- - *), $(ARGS), $(ARGS), $(ARGS)) */ Tid spawn(F, T...)( F fn, T args ) if ( isSpawnable!(F, T) ) @@ -619,8 +602,6 @@ private void _send(T...)( MsgType type, Tid tid, T vals ) * sent. * * Example: - *$(D_RUN_CODE - *$(ARGS * --- * import std.stdio; * import std.variant; @@ -641,9 +622,14 @@ private void _send(T...)( MsgType type, Tid tid, T vals ) * send(tid, 42); * } * --- - *), $(ARGS), $(ARGS), $(ARGS)) */ void receive(T...)( T ops ) +in +{ + assert(mbox !is null, "Cannot receive a message until a thread was spawned " + "or thisTid was passed to a running thread."); +} +body { checkops( ops ); mbox.get( ops ); @@ -702,11 +688,9 @@ private template receiveOnlyRet(T...) * the message will be packed into a $(XREF typecons, Tuple). * * Example: - *$(D_RUN_CODE - *$(ARGS * --- * import std.concurrency; - + * * void spawnedFunc() * { * auto msg = receiveOnly!(int, string)(); @@ -720,9 +704,14 @@ private template receiveOnlyRet(T...) * send(tid, 42, "42"); * } * --- - *), $(ARGS), $(ARGS), $(ARGS)) */ receiveOnlyRet!(T) receiveOnly(T...)() +in +{ + assert(mbox !is null, "Cannot receive a message until a thread was spawned " + "or thisTid was passed to a running thread."); +} +body { Tuple!(T) ret; @@ -784,6 +773,12 @@ unittest message and $(D false) if it timed out waiting for one. +/ bool receiveTimeout(T...)( Duration duration, T ops ) +in +{ + assert(mbox !is null, "Cannot receive a message until a thread was spawned " + "or thisTid was passed to a running thread."); +} +body { checkops( ops ); return mbox.get( duration, ops ); diff --git a/std/container.d b/std/container.d index b17c4197b..938d70bbc 100644 --- a/std/container.d +++ b/std/container.d @@ -267,7 +267,7 @@ the type of the $(D k)th key of the container. A container may define both $(D KeyType) and $(D KeyTypes), e.g. in the case it has the notion of primary/preferred key. */ - alias TypeTuple!(T) KeyTypes; + alias TypeTuple!T KeyTypes; /** If the container has a notion of key-value mapping, $(D ValueType) @@ -1882,7 +1882,7 @@ Appends the contents of stuff into this. insertBack(rhs); return this; } - + // Private implementations helpers for opOpBinaryRight DList opOpAssignRightPrivate(string op, Stuff)(Stuff lhs) if (op == "~" && isInputRange!Stuff && isImplicitlyConvertible!(ElementType!Stuff, T)) @@ -2112,7 +2112,7 @@ $(D r) and $(D m) is the length of $(D stuff). last = new Node(item, last, null); ++result; } - + //We have created a first-last chain. Now we insert it. if(!_first) { @@ -2233,7 +2233,7 @@ Complexity: $(BIGOH 1) /// ditto template linearRemove(R) if (is(R == Range)) { - Range linearRemove(R r) { return remove(r); }; + Range linearRemove(R r) { return remove(r); } } /// ditto @@ -2446,7 +2446,7 @@ unittest auto d = DList!int([4, 5, 6]); assert((a ~ b[])[].empty); - + assert((c ~ d[])[].equal([1, 2, 3, 4, 5, 6])); assert(c[].equal([1, 2, 3])); assert(d[].equal([4, 5, 6])); @@ -2492,7 +2492,8 @@ for the array is reclaimed as soon as possible; there is no reliance on the garbage collector. $(D Array) uses $(D malloc) and $(D free) for managing its own memory. */ -struct Array(T) if (!is(T : const(bool))) +struct Array(T) +if (!is(Unqual!T == bool)) { // This structure is not copyable. private struct Payload @@ -2517,7 +2518,7 @@ struct Array(T) if (!is(T : const(bool))) assert(0); } - void opAssign(Array!(T).Payload rhs) + void opAssign(Payload rhs) { assert(false); } @@ -2581,9 +2582,9 @@ struct Array(T) if (!is(T : const(bool))) */ immutable oldLength = length; auto newPayload = - enforce((cast(T*) malloc(sz))[0 .. oldLength]); + enforce(cast(T*) malloc(sz))[0 .. oldLength]; // copy old data over to new array - newPayload[] = _payload[]; + memcpy(newPayload.ptr, _payload.ptr, T.sizeof * oldLength); // Zero out unused capacity to prevent gc from seeing // false pointers memset(newPayload.ptr + oldLength, @@ -3679,6 +3680,31 @@ unittest assert(r.equal([0, 0, 40])); } +// Test issue 11194 +unittest { + static struct S { + int i = 1337; + void* p; + this(this) { assert(i == 1337); } + ~this() { assert(i == 1337); } + } + Array!S arr; + S s; + arr ~= s; + arr ~= s; +} + +unittest //11459 +{ + static struct S + { + bool b; + alias b this; + } + alias A = Array!S; + alias B = Array!(shared bool); +} + // BinaryHeap /** Implements a $(WEB en.wikipedia.org/wiki/Binary_heap, binary heap) @@ -3727,8 +3753,12 @@ if (isRandomAccessRange!(Store) || isRandomAccessRange!(typeof(Store.init[]))) //private: // The payload includes the support store and the effective length - private RefCounted!(Tuple!(Store, "_store", size_t, "_length"), - RefCountedAutoInitialize.no) _payload; + private static struct Data + { + Store _store; + size_t _length; + } + private RefCounted!(Data, RefCountedAutoInitialize.no) _payload; // Comparison predicate private alias binaryFun!(less) comp; // Convenience accessors @@ -4097,11 +4127,15 @@ unittest _Array specialized for $(D bool). Packs together values efficiently by allocating one bit per element. */ -struct Array(T) if (is(T == bool)) +struct Array(T) +if (is(Unqual!T == bool)) { static immutable uint bitsPerWord = size_t.sizeof * 8; - private alias Tuple!(Array!(size_t).Payload, "_backend", ulong, "_length") - Data; + private static struct Data + { + Array!size_t.Payload _backend; + size_t _length; + } private RefCounted!(Data, RefCountedAutoInitialize.no) _store; private @property ref size_t[] data() @@ -4115,8 +4149,8 @@ struct Array(T) if (is(T == bool)) */ struct Range { - private Array!bool _outer; - private ulong _a, _b; + private Array _outer; + private size_t _a, _b; /// Range primitives @property Range save() { @@ -4166,6 +4200,12 @@ struct Array(T) if (is(T == bool)) return _outer[_b - 1]; } /// Ditto + @property void back(bool value) + { + enforce(!empty); + _outer[_b - 1] = value; + } + /// Ditto T moveBack() { enforce(!empty); @@ -4193,11 +4233,18 @@ struct Array(T) if (is(T == bool)) return _outer.moveAt(_a + i); } /// Ditto - @property ulong length() const + @property size_t length() const { assert(_a <= _b); return _b - _a; } + alias opDollar = length; + /// ditto + Range opSlice(size_t low, size_t high) + { + assert(_a <= low && low <= high && high <= _b); + return Range(_outer, _a + low, _a + high); + } } /** @@ -4226,9 +4273,9 @@ struct Array(T) if (is(T == bool)) Complexity: $(BIGOH n). */ - @property Array!bool dup() + @property Array dup() { - Array!bool result; + Array result; result.insertBack(this[]); return result; } @@ -4248,10 +4295,14 @@ struct Array(T) if (is(T == bool)) Complexity: $(BIGOH log(n)). */ - @property ulong length() + @property size_t length() const { return _store.refCountedStore.isInitialized ? _store._length : 0; } + size_t opDollar() const + { + return length; + } unittest { @@ -4268,10 +4319,10 @@ struct Array(T) if (is(T == bool)) Complexity: $(BIGOH log(n)). */ - @property ulong capacity() + @property size_t capacity() { return _store.refCountedStore.isInitialized - ? cast(ulong) bitsPerWord * _store._backend.capacity + ? cast(size_t) bitsPerWord * _store._backend.capacity : 0; } @@ -4294,7 +4345,7 @@ struct Array(T) if (is(T == bool)) Complexity: $(BIGOH log(e - capacity)) if $(D e > capacity), otherwise $(BIGOH 1). */ - void reserve(ulong e) + void reserve(size_t e) { _store.refCountedStore.ensureInitialized(); _store._backend.reserve(to!size_t((e + bitsPerWord - 1) / bitsPerWord)); @@ -4334,7 +4385,7 @@ struct Array(T) if (is(T == bool)) Complexity: $(BIGOH log(n)) */ - Range opSlice(ulong a, ulong b) + Range opSlice(size_t a, size_t b) { enforce(a <= b && b <= length); return Range(this, a, b); @@ -4410,7 +4461,7 @@ struct Array(T) if (is(T == bool)) /** Indexing operators yield or modify the value at a specified index. */ - bool opIndex(ulong i) + bool opIndex(size_t i) { auto div = cast(size_t) (i / bitsPerWord); auto rem = i % bitsPerWord; @@ -4418,7 +4469,7 @@ struct Array(T) if (is(T == bool)) return cast(bool)(data.ptr[div] & (cast(size_t)1 << rem)); } /// ditto - void opIndexAssign(bool value, ulong i) + void opIndexAssign(bool value, size_t i) { auto div = cast(size_t) (i / bitsPerWord); auto rem = i % bitsPerWord; @@ -4427,7 +4478,7 @@ struct Array(T) if (is(T == bool)) else data.ptr[div] &= ~(cast(size_t)1 << rem); } /// ditto - void opIndexOpAssign(string op)(bool value, ulong i) + void opIndexOpAssign(string op)(bool value, size_t i) { auto div = cast(size_t) (i / bitsPerWord); auto rem = i % bitsPerWord; @@ -4443,7 +4494,7 @@ struct Array(T) if (is(T == bool)) } } /// Ditto - T moveAt(ulong i) + T moveAt(size_t i) { return this[i]; } @@ -4520,7 +4571,7 @@ struct Array(T) if (is(T == bool)) */ void clear() { - this = Array!bool(); + this = Array(); } unittest @@ -4541,7 +4592,7 @@ struct Array(T) if (is(T == bool)) Postcondition: $(D _length == newLength) */ - @property void length(ulong newLength) + @property void length(size_t newLength) { _store.refCountedStore.ensureInitialized(); auto newDataLength = @@ -4631,7 +4682,7 @@ struct Array(T) if (is(T == bool)) Complexity: $(BIGOH log(n)) */ - ulong insertBack(Stuff)(Stuff stuff) if (is(Stuff : bool)) + size_t insertBack(Stuff)(Stuff stuff) if (is(Stuff : bool)) { _store.refCountedStore.ensureInitialized(); auto rem = _store._length % bitsPerWord; @@ -4656,10 +4707,10 @@ struct Array(T) if (is(T == bool)) return 1; } /// Ditto - ulong insertBack(Stuff)(Stuff stuff) + size_t insertBack(Stuff)(Stuff stuff) if (isInputRange!Stuff && is(ElementType!Stuff : bool)) { - static if (!hasLength!Stuff) ulong result; + static if (!hasLength!Stuff) size_t result; for (; !stuff.empty; stuff.popFront()) { insertBack(stuff.front); @@ -4715,7 +4766,7 @@ struct Array(T) if (is(T == bool)) Complexity: $(BIGOH howMany * log(n)). */ /// ditto - ulong removeBack(ulong howMany) + size_t removeBack(size_t howMany) { if (howMany >= length) { @@ -4754,7 +4805,7 @@ struct Array(T) if (is(T == bool)) Complexity: $(BIGOH n + m), where $(D m) is the length of $(D stuff) */ - ulong insertBefore(Stuff)(Range r, Stuff stuff) + size_t insertBefore(Stuff)(Range r, Stuff stuff) { // TODO: make this faster, it moves one bit at a time immutable inserted = stableInsertBack(stuff); @@ -4781,7 +4832,7 @@ struct Array(T) if (is(T == bool)) } /// ditto - ulong insertAfter(Stuff)(Range r, Stuff stuff) + size_t insertAfter(Stuff)(Range r, Stuff stuff) { // TODO: make this faster, it moves one bit at a time immutable inserted = stableInsertBack(stuff); @@ -4858,6 +4909,27 @@ unittest assert(a.empty); } +unittest +{ + Array!bool arr; + arr.insert([false, false, false, false]); + assert(arr.front == false); + assert(arr.back == false); + assert(arr[1] == false); + auto slice = arr[]; + slice = arr[0 .. $]; + slice = slice[1 .. $]; + slice.front = true; + slice.back = true; + slice[1] = true; + assert(slice.front == true); + assert(slice.back == true); + assert(slice[1] == true); + assert(slice.moveFront == true); + assert(slice.moveBack == true); + assert(slice.moveAt(1) == true); +} + /* * Implementation for a Red Black node for use in a Red Black Tree (see below) * diff --git a/std/conv.d b/std/conv.d index fda09a42f..a94200731 100644 --- a/std/conv.d +++ b/std/conv.d @@ -37,43 +37,47 @@ import std.format; */ class ConvException : Exception { + @safe pure nothrow this(string s, string fn = __FILE__, size_t ln = __LINE__) { super(s, fn, ln); } } -private string convError_unexpected(S)(S source) { +private string convError_unexpected(S)(S source) +{ return source.empty ? "end of input" : text("'", source.front, "'"); } -private void convError(S, T)(S source, string fn = __FILE__, size_t ln = __LINE__) +private auto convError(S, T)(S source, string fn = __FILE__, size_t ln = __LINE__) { - throw new ConvException( + return new ConvException( text("Unexpected ", convError_unexpected(source), " when converting from type "~S.stringof~" to type "~T.stringof), fn, ln); } -private void convError(S, T)(S source, int radix, string fn = __FILE__, size_t ln = __LINE__) +private auto convError(S, T)(S source, int radix, string fn = __FILE__, size_t ln = __LINE__) { - throw new ConvException( + return new ConvException( text("Unexpected ", convError_unexpected(source), " when converting from type "~S.stringof~" base ", radix, " to type "~T.stringof), fn, ln); } -private void parseError(lazy string msg, string fn = __FILE__, size_t ln = __LINE__) +@safe pure/* nothrow*/ // lazy parameter bug +private auto parseError(lazy string msg, string fn = __FILE__, size_t ln = __LINE__) { - throw new ConvException(text("Can't parse string: ", msg), fn, ln); + return new ConvException(text("Can't parse string: ", msg), fn, ln); } private void parseCheck(alias source)(dchar c, string fn = __FILE__, size_t ln = __LINE__) { - if (source.empty) parseError(text("unexpected end of input when expecting", "\"", c, "\"")); + if (source.empty) + throw parseError(text("unexpected end of input when expecting", "\"", c, "\"")); if (source.front != c) - parseError(text("\"", c, "\" is missing"), fn, ln); + throw parseError(text("\"", c, "\" is missing"), fn, ln); source.popFront(); } @@ -81,17 +85,17 @@ private { template isImaginary(T) { - enum bool isImaginary = staticIndexOf!(Unqual!(T), + enum bool isImaginary = staticIndexOf!(Unqual!T, ifloat, idouble, ireal) >= 0; } template isComplex(T) { - enum bool isComplex = staticIndexOf!(Unqual!(T), + enum bool isComplex = staticIndexOf!(Unqual!T, cfloat, cdouble, creal) >= 0; } template isNarrowInteger(T) { - enum bool isNarrowInteger = staticIndexOf!(Unqual!(T), + enum bool isNarrowInteger = staticIndexOf!(Unqual!T, byte, ubyte, short, ushort) >= 0; } @@ -117,7 +121,7 @@ private template isNullToStr(S, T) { enum isNullToStr = isImplicitlyConvertible!(S, T) && - is(S == typeof(null)) && isExactSomeString!T; + (is(Unqual!S == typeof(null))) && isExactSomeString!T; } template isRawStaticArray(T, A...) @@ -137,6 +141,7 @@ private */ class ConvOverflowException : ConvException { + @safe pure nothrow this(string s, string fn = __FILE__, size_t ln = __LINE__) { super(s, fn, ln); @@ -285,7 +290,7 @@ template to(T) } // Tests for issue 6175 -unittest +@safe pure unittest { char[9] sarr = "blablabla"; auto darr = to!(char[])(sarr); @@ -294,34 +299,43 @@ unittest } // Tests for issue 7348 -unittest +@safe pure unittest { assert(to!string(null) == "null"); assert(text(null) == "null"); } -// Tests for issue 8729: do NOT skip leading WS -unittest +// Tests for issue 11390 +@safe pure unittest { - foreach(T;TypeTuple!(byte, ubyte, short, ushort, int, uint, long, ulong)) + const(typeof(null)) ctn; + immutable(typeof(null)) itn; + assert(to!string(ctn) == "null"); + assert(to!string(itn) == "null"); +} + +// Tests for issue 8729: do NOT skip leading WS +@safe pure unittest +{ + foreach (T; TypeTuple!(byte, ubyte, short, ushort, int, uint, long, ulong)) { assertThrown!ConvException(to!T(" 0")); assertThrown!ConvException(to!T(" 0", 8)); } - foreach(T;TypeTuple!(float, double, real)) + foreach (T; TypeTuple!(float, double, real)) { assertThrown!ConvException(to!T(" 0")); } - assertThrown!ConvException(to!bool (" true")); + assertThrown!ConvException(to!bool(" true")); - alias typeof(null) NullType; + alias NullType = typeof(null); assertThrown!ConvException(to!NullType(" null")); - alias int[] ARR; + alias ARR = int[]; assertThrown!ConvException(to!ARR(" [1]")); - alias int[int] AA; + alias AA = int[int]; assertThrown!ConvException(to!AA(" [1:1]")); } @@ -333,7 +347,11 @@ T toImpl(T, S)(S value) if (isImplicitlyConvertible!(S, T) && !isEnumStrToStr!(S, T) && !isNullToStr!(S, T)) { - alias isUnsigned isUnsignedInt; + template isSignedInt(T) + { + enum isSignedInt = isIntegral!T && isSigned!T; + } + alias isUnsignedInt = isUnsigned; // Conversion from integer to integer, and changing its sign static if (isUnsignedInt!S && isSignedInt!T && S.sizeof == T.sizeof) @@ -350,19 +368,14 @@ T toImpl(T, S)(S value) return value; } -unittest +@safe pure unittest { enum E { a } // Issue 9523 - Allow identity enum conversion auto e = to!E(E.a); assert(e == E.a); } -private template isSignedInt(T) -{ - enum isSignedInt = isIntegral!T && isSigned!T; -} - -unittest +@safe pure unittest { debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded."); int a = 42; @@ -371,25 +384,25 @@ unittest } // Tests for issue 6377 -unittest +@safe pure unittest { // Conversion between same size foreach (S; TypeTuple!(byte, short, int, long)) { alias Unsigned!S U; - foreach (Sint; TypeTuple!(S, const(S), immutable(S))) - foreach (Uint; TypeTuple!(U, const(U), immutable(U))) + foreach (Sint; TypeTuple!(S, const S, immutable S)) + foreach (Uint; TypeTuple!(U, const U, immutable U)) { // positive overflow Uint un = Uint.max; - assertThrown!ConvOverflowException(to!Sint(un), text( - Sint.stringof, ' ', Uint.stringof, ' ', un)); + assertThrown!ConvOverflowException(to!Sint(un), + text(Sint.stringof, ' ', Uint.stringof, ' ', un)); // negative overflow Sint sn = -1; - assertThrown!ConvOverflowException(to!Uint(sn), text( - Sint.stringof, ' ', Uint.stringof, ' ', un)); + assertThrown!ConvOverflowException(to!Uint(sn), + text(Sint.stringof, ' ', Uint.stringof, ' ', un)); } } @@ -403,8 +416,8 @@ unittest static assert(U1.sizeof < S2.sizeof); // small unsigned to big signed - foreach (Uint; TypeTuple!(U1, const(U1), immutable(U1))) - foreach (Sint; TypeTuple!(S2, const(S2), immutable(S2))) + foreach (Uint; TypeTuple!(U1, const U1, immutable U1)) + foreach (Sint; TypeTuple!(S2, const S2, immutable S2)) { Uint un = Uint.max; assertNotThrown(to!Sint(un)); @@ -412,8 +425,8 @@ unittest } // big unsigned to small signed - foreach (Uint; TypeTuple!(U2, const(U2), immutable(U2))) - foreach (Sint; TypeTuple!(S1, const(S1), immutable(S1))) + foreach (Uint; TypeTuple!(U2, const U2, immutable U2)) + foreach (Sint; TypeTuple!(S1, const S1, immutable S1)) { Uint un = Uint.max; assertThrown(to!Sint(un)); @@ -422,16 +435,16 @@ unittest static assert(S1.sizeof < U2.sizeof); // small signed to big unsigned - foreach (Sint; TypeTuple!(S1, const(S1), immutable(S1))) - foreach (Uint; TypeTuple!(U2, const(U2), immutable(U2))) + foreach (Sint; TypeTuple!(S1, const S1, immutable S1)) + foreach (Uint; TypeTuple!(U2, const U2, immutable U2)) { Sint sn = -1; assertThrown!ConvOverflowException(to!Uint(sn)); } // big signed to small unsigned - foreach (Sint; TypeTuple!(S2, const(S2), immutable(S2))) - foreach (Uint; TypeTuple!(U1, const(U1), immutable(U1))) + foreach (Sint; TypeTuple!(S2, const S2, immutable S2)) + foreach (Uint; TypeTuple!(U1, const U1, immutable U1)) { Sint sn = -1; assertThrown!ConvOverflowException(to!Uint(sn)); @@ -448,7 +461,7 @@ T toImpl(T, S)(ref S s) return toImpl!(T, typeof(s[0])[])(s); } -unittest +@safe pure unittest { char[4] test = ['a', 'b', 'c', 'd']; static assert(!isInputRange!(Unqual!(char[4]))); @@ -459,13 +472,14 @@ unittest When source type supports member template function opCast, is is used. */ T toImpl(T, S)(S value) - if (is(typeof(S.init.opCast!T()) : T) && + if (!isImplicitlyConvertible!(S, T) && + is(typeof(S.init.opCast!T()) : T) && !isExactSomeString!T) { return value.opCast!T(); } -unittest +@safe pure unittest { debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded."); class B @@ -497,7 +511,7 @@ T toImpl(T, S)(S value) } // Bugzilla 3961 -unittest +@safe pure unittest { debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded."); struct Int @@ -509,14 +523,14 @@ unittest static struct Int2 { int x; - this(int x) { this.x = x; } + this(int x) @safe pure { this.x = x; } } Int2 i2 = to!Int2(1); static struct Int3 { int x; - static Int3 opCall(int x) + static Int3 opCall(int x) @safe pure { Int3 i; i.x = x; @@ -527,11 +541,11 @@ unittest } // Bugzilla 6808 -unittest +@safe pure unittest { static struct FakeBigInt { - this(string s){} + this(string s) @safe pure {} } string s = "101"; @@ -546,7 +560,7 @@ T toImpl(T, S)(S value) return new T(value); } -unittest +@safe pure unittest { static struct S { @@ -555,14 +569,14 @@ unittest static class C { int x; - this(int x) { this.x = x; } + this(int x) @safe pure { this.x = x; } } static class B { int value; - this(S src) { value = src.x; } - this(C src) { value = src.x; } + this(S src) @safe pure { value = src.x; } + this(C src) @safe pure { value = src.x; } } S s = S(1); @@ -577,34 +591,35 @@ unittest assert(c2.x == 3); } -version (unittest) +@safe pure unittest { - class A + struct S { - this(B b) {} + class A + { + this(B b) @safe pure {} + } + class B : A + { + this() @safe pure { super(this); } + } } - class B : A - { - this() { super(this); } - } -} -unittest -{ - B b = new B(); - A a = to!A(b); // == cast(A)b - // (do not run construction conversion like new A(b)) + + S.B b = new S.B(); + S.A a = to!(S.A)(b); // == cast(S.A)b + // (do not run construction conversion like new S.A(b)) assert(b is a); static class C : Object { - this() {} - this(Object o) {} + this() @safe pure {} + this(Object o) @safe pure {} } Object oc = new C(); C a2 = to!C(oc); // == new C(a) // Construction conversion overrides down-casting conversion - assert(a2 != a); // + assert(a2 !is a); // } /** @@ -652,7 +667,7 @@ T toImpl(T, S)(S value) } static assert(isModConvertible, "Bad modifier conversion: "~S.stringof~" to "~T.stringof); - auto result = cast(T) value; + auto result = ()@trusted{ return cast(T) value; }(); if (!result && value) { throw new ConvException("Cannot convert object of static type " @@ -662,7 +677,7 @@ T toImpl(T, S)(S value) return result; } -unittest +@safe pure unittest { debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded."); // Testing object conversions @@ -676,14 +691,14 @@ unittest } // Unittest for 6288 -version (unittest) +@safe pure unittest { - private template Identity(T) { alias T Identity; } - private template toConst(T) { alias const(T) toConst; } - private template toShared(T) { alias shared(T) toShared; } - private template toSharedConst(T) { alias shared(const(T)) toSharedConst; } - private template toImmutable(T) { alias immutable(T) toImmutable; } - private template AddModifier(int n) if (0 <= n && n < 5) + template Identity(T) { alias T Identity; } + template toConst(T) { alias const(T) toConst; } + template toShared(T) { alias shared(T) toShared; } + template toSharedConst(T) { alias shared(const(T)) toSharedConst; } + template toImmutable(T) { alias immutable(T) toImmutable; } + template AddModifier(int n) if (0 <= n && n < 5) { static if (n == 0) alias Identity AddModifier; else static if (n == 1) alias toConst AddModifier; @@ -691,9 +706,7 @@ version (unittest) else static if (n == 3) alias toSharedConst AddModifier; else static if (n == 4) alias toImmutable AddModifier; } -} -unittest -{ + interface I {} interface J {} @@ -767,10 +780,12 @@ $(UL $(DD Convert integral value to string in $(D_PARAM radix) radix. radix must be a value from 2 to 36. value is treated as a signed value only if radix is 10. - The characters A through Z are used to represent values 10 through 36.))) + The characters A through Z are used to represent values 10 through 36 + and their case is determined by the $(D_PARAM letterCase) parameter.))) $(LI All floating point types to all string types.) $(LI Pointer to string conversions prints the pointer as a $(D size_t) value. - If pointer is $(D char*), treat it as C-style strings.)) + If pointer is $(D char*), treat it as C-style strings. + In that case, this function is $(D @system).)) */ T toImpl(T, S)(S value) if (!(isImplicitlyConvertible!(S, T) && @@ -793,8 +808,16 @@ T toImpl(T, S)(S value) } else static if (isExactSomeString!S) { - // other string-to-string conversions always run decode/encode - return toStr!T(value); + // other string-to-string + //Use Appender directly instead of toStr, which also uses a formatedWrite + auto w = appender!T(); + w.put(value); + return w.data; + } + else static if (isIntegral!S && !is(S == enum)) + { + // other integral-to-string conversions with default radix + return toImpl!(T, S)(value, 10); } else static if (is(S == void[]) || is(S == const(void)[]) || is(S == immutable(void)[])) { @@ -806,13 +829,47 @@ T toImpl(T, S)(S value) ~ S.stringof ~ " to a " ~ T.stringof)); auto result = new Char[raw.length / Char.sizeof]; - memcpy(result.ptr, value.ptr, value.length); + ()@trusted{ memcpy(result.ptr, value.ptr, value.length); }(); return cast(T) result; } else static if (isPointer!S && is(S : const(char)*)) { + // It is unsafe because we cannot guarantee that the pointer is null terminated. return value ? cast(T) value[0 .. strlen(value)].dup : cast(string)null; } + else static if (isSomeString!T && is(S == enum)) + { + static if (isSwitchable!(OriginalType!S) && EnumMembers!S.length <= 50) + { + switch(value) + { + foreach (I, member; NoDuplicates!(EnumMembers!S)) + { + case member: + return to!T(enumRep!(immutable(T), S, I)); + } + default: + } + } + else + { + foreach (I, member; EnumMembers!S) + { + if (value == member) + return to!T(enumRep!(immutable(T), S, I)); + } + } + + //Default case, delegate to format + //Note: we don't call toStr directly, to avoid duplicate work. + auto app = appender!T(); + app.put("cast("); + app.put(S.stringof); + app.put(')'); + FormatSpec!char f; + formatValue(app, cast(OriginalType!S)value, f); + return app.data; + } else { // other non-string values runs formatting @@ -820,48 +877,81 @@ T toImpl(T, S)(S value) } } +/* + Check whether type $(D T) can be used in a switch statement. + This is useful for compile-time generation of switch case statements. +*/ +private template isSwitchable(E) +{ + enum bool isSwitchable = is(typeof({ + switch (E.init) { default: } + })); +} + +// unittest { - // string to string conversion - debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded."); + static assert(isSwitchable!int); + static assert(!isSwitchable!double); + static assert(!isSwitchable!real); +} - alias TypeTuple!(char, wchar, dchar) Chars; - foreach (LhsC; Chars) +//Static representation of the index I of the enum S, +//In representation T. +//T must be an immutable string (avoids un-necessary initializations). +private template enumRep(T, S, size_t I) +if (is (T == immutable) && isExactSomeString!T && is(S == enum)) +{ + static T enumRep = to!T(__traits(allMembers, S)[I]); +} + +@safe pure unittest +{ + void dg() { - alias TypeTuple!(LhsC[], const(LhsC)[], immutable(LhsC)[]) LhStrings; - foreach (Lhs; LhStrings) + // string to string conversion + debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded."); + + alias TypeTuple!(char, wchar, dchar) Chars; + foreach (LhsC; Chars) { - foreach (RhsC; Chars) + alias TypeTuple!(LhsC[], const(LhsC)[], immutable(LhsC)[]) LhStrings; + foreach (Lhs; LhStrings) { - alias TypeTuple!(RhsC[], const(RhsC)[], immutable(RhsC)[]) - RhStrings; - foreach (Rhs; RhStrings) + foreach (RhsC; Chars) { - Lhs s1 = to!Lhs("wyda"); - Rhs s2 = to!Rhs(s1); - //writeln(Lhs.stringof, " -> ", Rhs.stringof); - assert(s1 == to!Lhs(s2)); + alias TypeTuple!(RhsC[], const(RhsC)[], immutable(RhsC)[]) + RhStrings; + foreach (Rhs; RhStrings) + { + Lhs s1 = to!Lhs("wyda"); + Rhs s2 = to!Rhs(s1); + //writeln(Lhs.stringof, " -> ", Rhs.stringof); + assert(s1 == to!Lhs(s2)); + } } } } - } - foreach (T; Chars) - { - foreach (U; Chars) + foreach (T; Chars) { - T[] s1 = to!(T[])("Hello, world!"); - auto s2 = to!(U[])(s1); - assert(s1 == to!(T[])(s2)); - auto s3 = to!(const(U)[])(s1); - assert(s1 == to!(T[])(s3)); - auto s4 = to!(immutable(U)[])(s1); - assert(s1 == to!(T[])(s4)); + foreach (U; Chars) + { + T[] s1 = to!(T[])("Hello, world!"); + auto s2 = to!(U[])(s1); + assert(s1 == to!(T[])(s2)); + auto s3 = to!(const(U)[])(s1); + assert(s1 == to!(T[])(s3)); + auto s4 = to!(immutable(U)[])(s1); + assert(s1 == to!(T[])(s4)); + } } } + dg(); + assertCTFEable!dg; } -unittest +@safe pure unittest { // Conversion reinterpreting void array to string debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded."); @@ -874,7 +964,7 @@ unittest assert(c == "abcx"); } -unittest +@system pure unittest { // char* to string conversion debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded."); @@ -884,7 +974,7 @@ unittest assert(to!string("foo\0".ptr) == "foo"); } -unittest +@safe pure unittest { // Conversion representing bool value with string debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded."); @@ -895,15 +985,15 @@ unittest assert(to!string(b) == "true"); } -unittest +@safe pure unittest { // Conversion representing character value with string debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded."); alias TypeTuple!( - char, wchar, dchar, - const(char), const(wchar), const(dchar), - immutable(char), immutable(wchar), immutable(dchar)) AllChars; + char, const( char), immutable( char), + wchar, const(wchar), immutable(wchar), + dchar, const(dchar), immutable(dchar)) AllChars; foreach (Char1; AllChars) { foreach (Char2; AllChars) @@ -925,7 +1015,7 @@ unittest assert(s2 == "foo"); } -unittest +@safe pure unittest { // Conversion representing integer values with string @@ -966,7 +1056,7 @@ unittest }); } -unittest +@safe pure unittest { // Conversion representing dynamic/static array with string debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded."); @@ -974,12 +1064,14 @@ unittest long[] b = [ 1, 3, 5 ]; auto s = to!string(b); assert(to!string(b) == "[1, 3, 5]", s); - +} +/*@safe pure */unittest // sprintf issue +{ double[2] a = [ 1.5, 2.5 ]; assert(to!string(a) == "[1.5, 2.5]"); } -unittest +/*@safe pure */unittest { // Conversion representing associative array with string int[string] a = ["0":1, "1":2]; @@ -1063,8 +1155,36 @@ unittest assert(to!dstring(o) == "cast(EU)5"d); } +unittest +{ + enum E + { + foo, + bar, + doo = foo, // check duplicate switch statements + } + + foreach (S; TypeTuple!(string, wstring, dstring, const(char[]), const(wchar[]), const(dchar[]))) + { + auto s1 = to!S(E.foo); + auto s2 = to!S(E.foo); + assert(s1 == s2); + // ensure we don't allocate when it's unnecessary + assert(s1 is s2); + } + + foreach (S; TypeTuple!(char[], wchar[], dchar[])) + { + auto s1 = to!S(E.foo); + auto s2 = to!S(E.foo); + assert(s1 == s2); + // ensure each mutable array is unique + assert(s1 !is s2); + } +} + /// ditto -T toImpl(T, S)(S value, uint radix) +@trusted pure T toImpl(T, S)(S value, uint radix, LetterCase letterCase = LetterCase.upper) if (isIntegral!S && isExactSomeString!T) in @@ -1073,34 +1193,71 @@ in } body { - static if (!is(IntegralTypeOf!S == ulong)) - { - enforce(radix >= 2 && radix <= 36, new ConvException("Radix error")); - if (radix == 10) - return to!string(value); // handle signed cases only for radix 10 - return to!string(cast(ulong) value, radix); - } - else - { - char[value.sizeof * 8] buffer; - uint i = buffer.length; + alias EEType = Unqual!(ElementEncodingType!T); - if (value < radix && value < hexDigits.length) - return hexDigits[cast(size_t)value .. cast(size_t)value + 1]; + T toStringRadixConvert(size_t bufLen, uint radix = 0, bool neg = false)(uint runtimeRadix = 0) + { + static if (neg) + ulong div = void, mValue = unsigned(-value); + else + Unsigned!(Unqual!S) div = void, mValue = unsigned(value); + + size_t index = bufLen; + EEType[bufLen] buffer = void; + char baseChar = letterCase == LetterCase.lower ? 'a' : 'A'; + char mod = void; do { - ubyte c; - c = cast(ubyte)(value % radix); - value = value / radix; - i--; - buffer[i] = cast(char)((c < 10) ? c + '0' : c + 'A' - 10); - } while (value); - return to!T(buffer[i .. $].dup); + static if (radix == 0) + { + div = cast(S)(mValue / runtimeRadix ); + mod = cast(ubyte)(mValue % runtimeRadix); + mod += mod < 10 ? '0' : baseChar - 10; + } + else static if (radix > 10) + { + div = cast(S)(mValue / radix ); + mod = cast(ubyte)(mValue % radix); + mod += mod < 10 ? '0' : baseChar - 10; + } + else + { + div = cast(S)(mValue / radix); + mod = mValue % radix + '0'; + } + buffer[--index] = cast(char)mod; + mValue = div; + } while (mValue); + + static if (neg) + { + buffer[--index] = '-'; + } + return cast(T)buffer[index .. $].dup; + } + + enforce(radix >= 2 && radix <= 36, new ConvException("Radix error")); + + switch(radix) + { + case 10: + if (value < 0) + return toStringRadixConvert!(S.sizeof * 3 + 1, 10, true)(); + else + return toStringRadixConvert!(S.sizeof * 3, 10)(); + case 16: + return toStringRadixConvert!(S.sizeof * 2, 16)(); + case 2: + return toStringRadixConvert!(S.sizeof * 8, 2)(); + case 8: + return toStringRadixConvert!(S.sizeof * 3, 8)(); + default: + return toStringRadixConvert!(S.sizeof * 6)(radix); } } -unittest +@safe pure unittest { foreach (Int; TypeTuple!(uint, ulong)) { @@ -1111,6 +1268,8 @@ unittest assert(to!string(to!Int(15), 2u) == "1111"); assert(to!string(to!Int(1), 2u) == "1"); assert(to!string(to!Int(0x1234AF), 16u) == "1234AF"); + assert(to!string(to!Int(0x1234BCD), 16u, LetterCase.upper) == "1234BCD"); + assert(to!string(to!Int(0x1234AF), 16u, LetterCase.lower) == "1234af"); } foreach (Int; TypeTuple!(int, long)) @@ -1120,6 +1279,10 @@ unittest assert(to!string(to!Int(-10), 10u) == "-10"); } + + assert(to!string(cast(byte)-10, 16) == "F6"); + assert(to!string(long.min) == "-9223372036854775808"); + assert(to!string(long.max) == "9223372036854775807"); } // Explicitly undocumented. It will be removed in November 2013. @@ -1252,8 +1415,8 @@ fit in the narrower type. */ T toImpl(T, S)(S value) if (!isImplicitlyConvertible!(S, T) && - (isNumeric!S || isSomeChar!S) && !is(S == enum) && - (isNumeric!T || isSomeChar!T) && !is(T == enum)) + (isNumeric!S || isSomeChar!S || isBoolean!S) && + (isNumeric!T || isSomeChar!T || isBoolean!T) && !is(T == enum)) { enum sSmallest = mostNegative!S; enum tSmallest = mostNegative!T; @@ -1278,10 +1441,10 @@ T toImpl(T, S)(S value) if (value > T.max) throw new ConvOverflowException("Conversion positive overflow"); } - return cast(T) value; + return (ref value)@trusted{ return cast(T) value; }(value); } -unittest +@safe pure unittest { dchar a = ' '; assert(to!char(a) == ' '); @@ -1304,6 +1467,37 @@ unittest dchar to4 = to!dchar(from4); } +unittest +{ + // Narrowing conversions from enum -> integral should be allowed, but they + // should throw at runtime if the enum value doesn't fit in the target + // type. + enum E1 : ulong { A = 1, B = 1UL<<48, C = 0 } + assert(to!int(E1.A) == 1); + assert(to!bool(E1.A) == true); + assertThrown!ConvOverflowException(to!int(E1.B)); // E1.B overflows int + assertThrown!ConvOverflowException(to!bool(E1.B)); // E1.B overflows bool + assert(to!bool(E1.C) == false); + + enum E2 : long { A = -1L<<48, B = -1<<31, C = 1<<31 } + assertThrown!ConvOverflowException(to!int(E2.A)); // E2.A overflows int + assertThrown!ConvOverflowException(to!uint(E2.B)); // E2.B overflows uint + assert(to!int(E2.B) == -1<<31); // but does not overflow int + assert(to!int(E2.C) == 1<<31); // E2.C does not overflow int + + enum E3 : int { A = -1, B = 1, C = 255, D = 0 } + assertThrown!ConvOverflowException(to!ubyte(E3.A)); + assertThrown!ConvOverflowException(to!bool(E3.A)); + assert(to!byte(E3.A) == -1); + assert(to!byte(E3.B) == 1); + assert(to!ubyte(E3.C) == 255); + assert(to!bool(E3.B) == true); + assertThrown!ConvOverflowException(to!byte(E3.C)); + assertThrown!ConvOverflowException(to!bool(E3.C)); + assert(to!bool(E3.D) == false); + +} + /** Array-to-array conversion (except when target is a string type) converts each element in turn by using $(D to). @@ -1313,19 +1507,18 @@ T toImpl(T, S)(S value) !isSomeString!S && isDynamicArray!S && !isExactSomeString!T && isArray!T) { - alias typeof(T.init[0]) E; - auto result = new E[value.length]; - foreach (i, e; value) + alias E = typeof(T.init[0]); + + auto w = appender!(E[])(); + w.reserve(value.length); + foreach (i, ref e; value) { - /* Temporarily cast to mutable type, so we can get it initialized, - * this is ok because there are no other references to result[] - */ - cast()(result[i]) = to!E(e); + w.put(to!E(e)); } - return result; + return w.data; } -unittest +@safe pure unittest { // array to array conversions debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded."); @@ -1334,8 +1527,8 @@ unittest auto b = to!(float[])(a); assert(b == [ 1.0f, 2, 3 ]); - auto c = to!(string[])(b); - assert(c[0] == "1" && c[1] == "2" && c[2] == "3"); + //auto c = to!(string[])(b); + //assert(c[0] == "1" && c[1] == "2" && c[2] == "3"); immutable(int)[3] d = [ 1, 2, 3 ]; b = to!(float[])(d); @@ -1353,6 +1546,13 @@ unittest } Wrap[] warr = to!(Wrap[])(["foo", "bar"]); // should work } +/*@safe pure */unittest +{ + auto b = [ 1.0f, 2, 3 ]; + + auto c = to!(string[])(b); + assert(c[0] == "1" && c[1] == "2" && c[2] == "3"); +} /** Associative array to associative array conversion converts each key @@ -1362,6 +1562,8 @@ T toImpl(T, S)(S value) if (isAssociativeArray!S && isAssociativeArray!T && !is(T == enum)) { + /* This code is potentially unsafe. + */ alias KeyType!T K2; alias ValueType!T V2; @@ -1377,7 +1579,7 @@ T toImpl(T, S)(S value) return cast(T)result; } -unittest +@safe /*pure */unittest { // hash to hash conversions int[string] a; @@ -1386,7 +1588,7 @@ unittest auto b = to!(double[dstring])(a); assert(b["0"d] == 1 && b["1"d] == 2); } -unittest // Bugzilla 8705, from doc +@safe /*pure */unittest // Bugzilla 8705, from doc { int[string][double[int[]]] a; auto b = to!(short[wstring][string[double[]]])(a); @@ -1472,14 +1674,13 @@ private void testFloatingToIntegral(Floating, Integral)() } } -unittest +@safe pure unittest { debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded."); - alias TypeTuple!(byte, ubyte, short, ushort, int, uint, long, ulong) - AllInts; - alias TypeTuple!(float, double, real) AllFloats; - alias TypeTuple!(AllInts, AllFloats) AllNumerics; + alias AllInts = TypeTuple!(byte, ubyte, short, ushort, int, uint, long, ulong); + alias AllFloats = TypeTuple!(float, double, real); + alias AllNumerics = TypeTuple!(AllInts, AllFloats); // test with same type { foreach (T; AllNumerics) @@ -1550,6 +1751,12 @@ unittest assert(a == 42); } } +} +/*@safe pure */unittest +{ + alias AllInts = TypeTuple!(byte, ubyte, short, ushort, int, uint, long, ulong); + alias AllFloats = TypeTuple!(float, double, real); + alias AllNumerics = TypeTuple!(AllInts, AllFloats); // test conversions to string { foreach (T; AllNumerics) @@ -1594,7 +1801,7 @@ T toImpl(T, S)(S value) { if (value.length) { - convError!(S, T)(value); + throw convError!(S, T)(value); } } return parse!T(value); @@ -1609,25 +1816,25 @@ T toImpl(T, S)(S value, uint radix) { if (value.length) { - convError!(S, T)(value); + throw convError!(S, T)(value); } } return parse!T(value, radix); } -unittest +@safe pure unittest { // Issue 6668 - ensure no collaterals thrown try { to!uint("-1"); } catch (ConvException e) { assert(e.next is null); } } -unittest +@safe pure unittest { debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded."); - foreach (Char; TypeTuple!(char, wchar, dchar)) + foreach (Str; TypeTuple!(string, wstring, dstring)) { - auto a = to!(Char[])("123"); + Str a = "123"; assert(to!int(a) == 123); assert(to!double(a) == 123); } @@ -1644,7 +1851,8 @@ a ConvException is thrown. Enums with floating-point or string base types are not supported. */ T toImpl(T, S)(S value) - if (is(T == enum) && !is(S == enum) && is(S : OriginalType!T) + if (is(T == enum) && !is(S == enum) + && is(typeof(value == OriginalType!T.init)) && !isFloatingPoint!(OriginalType!T) && !isSomeString!(OriginalType!T)) { foreach (Member; EnumMembers!T) @@ -1656,7 +1864,7 @@ T toImpl(T, S)(S value) throw new ConvException(format("Value (%s) does not match any member value of enum '%s'", value, T.stringof)); } -unittest +@safe pure unittest { enum En8143 : int { A = 10, B = 20, C = 30, D = 20 } enum En8143[][] m3 = to!(En8143[][])([[10, 30], [30, 10]]); @@ -1729,17 +1937,17 @@ unittest * was meaningfully converted. * * Example: --------------- -string test = "123 \t 76.14"; -auto a = parse!uint(test); -assert(a == 123); -assert(test == " \t 76.14"); // parse bumps string -munch(test, " \t\n\r"); // skip ws -assert(test == "76.14"); -auto b = parse!double(test); -assert(b == 76.14); -assert(test == ""); --------------- + * -------------- + * string test = "123 \t 76.14"; + * auto a = parse!uint(test); + * assert(a == 123); + * assert(test == " \t 76.14"); // parse bumps string + * munch(test, " \t\n\r"); // skip ws + * assert(test == "76.14"); + * auto b = parse!double(test); + * assert(b == 76.14); + * assert(test == ""); + * -------------- */ Target parse(Target, Source)(ref Source s) @@ -1750,7 +1958,7 @@ Target parse(Target, Source)(ref Source s) { // smaller types are handled like integers auto v = .parse!(Select!(Target.min < 0, int, uint))(s); - auto result = cast(Target) v; + auto result = ()@trusted{ return cast(Target) v; }(); if (result != v) goto Loverflow; return result; @@ -1772,7 +1980,7 @@ Target parse(Target, Source)(ref Source s) if (c >= '0' && c <= '9') { if (v >= Target.max/10 && - (v != Target.max/10|| c + sign > maxLastDigit)) + (v != Target.max/10 || c + sign > maxLastDigit)) goto Loverflow; v = cast(Target) (v * 10 + (c - '0')); s.popFront(); @@ -1808,18 +2016,17 @@ Target parse(Target, Source)(ref Source s) Loverflow: throw new ConvOverflowException("Overflow in integral conversion"); Lerr: - convError!(Source, Target)(s); - assert(0); + throw convError!(Source, Target)(s); } -unittest +@safe pure unittest { debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded."); string s = "123"; auto a = parse!int(s); } -unittest +@safe pure unittest { foreach (Int; TypeTuple!(byte, ubyte, short, ushort, int, uint, long, ulong)) { @@ -1916,7 +2123,7 @@ unittest } } -unittest +@safe pure unittest { // parsing error check foreach (Int; TypeTuple!(byte, ubyte, short, ushort, int, uint, long, ulong)) @@ -1995,7 +2202,7 @@ unittest } } -unittest +@safe pure unittest { assertCTFEable!({ string s = "1234abc"; assert(parse! int(s) == 1234 && s == "abc"); }); assertCTFEable!({ string s = "-1234abc"; assert(parse! int(s) == -1234 && s == "abc"); }); @@ -2053,11 +2260,10 @@ body Loverflow: throw new ConvOverflowException("Overflow in integral conversion"); Lerr: - convError!(Source, Target)(s, radix); - assert(0); + throw convError!(Source, Target)(s, radix); } -unittest +@safe pure unittest { debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded."); // @@@BUG@@@ the size of China @@ -2092,7 +2298,7 @@ unittest assert(parse!int(s, 10) == -42); } -unittest // bugzilla 7302 +@safe pure unittest // bugzilla 7302 { auto r = cycle("2A!"); auto u = parse!uint(r, 16); @@ -2117,9 +2323,9 @@ Target parse(Target, Source)(ref Source s) } } - if( longest_match > 0 ) + if (longest_match > 0) { - s = s[longest_match..$]; + s = s[longest_match .. $]; return result ; } @@ -2149,7 +2355,7 @@ unittest } } -unittest // bugzilla 4744 +@safe pure unittest // bugzilla 4744 { enum A { member1, member11, member111 } assert(to!A("member1" ) == A.member1 ); @@ -2163,16 +2369,18 @@ Target parse(Target, Source)(ref Source p) if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum) && isFloatingPoint!Target && !is(Target == enum)) { - static immutable real negtab[14] = + static import core.stdc.math/* : HUGE_VAL*/; + + static immutable real[14] negtab = [ 1e-4096L,1e-2048L,1e-1024L,1e-512L,1e-256L,1e-128L,1e-64L,1e-32L, 1e-16L,1e-8L,1e-4L,1e-2L,1e-1L,1.0L ]; - static immutable real postab[13] = + static immutable real[13] postab = [ 1e+4096L,1e+2048L,1e+1024L,1e+512L,1e+256L,1e+128L,1e+64L,1e+32L, 1e+16L,1e+8L,1e+4L,1e+2L,1e+1L ]; // static immutable string infinity = "infinity"; // static immutable string nans = "nans"; - ConvException bailOut(string msg = null, string fn = __FILE__, size_t ln = __LINE__) + ConvException bailOut()(string msg = null, string fn = __FILE__, size_t ln = __LINE__) { if (!msg) msg = "Floating point conversion error"; @@ -2345,8 +2553,8 @@ Target parse(Target, Source)(ref Source p) } // Stuff mantissa directly into real - *cast(long *)&ldval = msdec; - (cast(ushort *)&ldval)[4] = cast(ushort) e2; + ()@trusted{ *cast(long*)&ldval = msdec; }(); + ()@trusted{ (cast(ushort*)&ldval)[4] = cast(ushort) e2; }(); // Exponent is power of 2, not power of 10 ldval = ldexp(ldval,exp); @@ -2556,7 +2764,7 @@ unittest debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded."); struct longdouble { - ushort value[5]; + ushort[5] value; } real ld; @@ -2594,50 +2802,38 @@ unittest // printf("\n"); } -// Unittest for bug 4959 -unittest +@safe pure unittest { - auto s = "0 "; - auto x = parse!double(s); - assert(s == " "); - assert(x == 0.0); -} + // Bugzilla 4959 + { + auto s = "0 "; + auto x = parse!double(s); + assert(s == " "); + assert(x == 0.0); + } -// Unittest for bug 3369 -unittest -{ + // Bugzilla 3369 assert(to!float("inf") == float.infinity); assert(to!float("-inf") == -float.infinity); -} -// Unittest for bug 6160 -unittest -{ + // Bugzilla 6160 assert(6_5.536e3L == to!real("6_5.536e3")); // 2^16 assert(0x1000_000_000_p10 == to!real("0x1000_000_000_p10")); // 7.03687e+13 -} -// Unittest for bug 6258 -unittest -{ + // Bugzilla 6258 assertThrown!ConvException(to!real("-")); assertThrown!ConvException(to!real("in")); -} -// Unittest for bug 7055 -unittest -{ + // Bugzilla 7055 assertThrown!ConvException(to!float("INF2")); -} -unittest -{ + //extra stress testing auto ssOK = ["1.", "1.1.1", "1.e5", "2e1e", "2a", "2e1_1", "inf", "-inf", "infa", "-infa", "inf2e2", "-inf2e2"]; auto ssKO = ["", " ", "2e", "2e+", "2e-", "2ee", "2e++1", "2e--1", "2e_1", "+inf"]; - foreach(s; ssOK) + foreach (s; ssOK) parse!double(s); - foreach(s; ssKO) + foreach (s; ssKO) assertThrown!ConvException(parse!double(s)); } @@ -2649,7 +2845,8 @@ Target parse(Target, Source)(ref Source s) if (isExactSomeString!Source && staticIndexOf!(Unqual!Target, dchar, Unqual!(ElementEncodingType!Source)) >= 0) { - if (s.empty) convError!(Source, Target)(s); + if (s.empty) + throw convError!(Source, Target)(s); static if (is(Unqual!Target == dchar)) { Target result = s.front; @@ -2665,7 +2862,7 @@ Target parse(Target, Source)(ref Source s) } } -unittest +@safe pure unittest { foreach (Str; TypeTuple!(string, wstring, dstring)) { @@ -2686,7 +2883,8 @@ Target parse(Target, Source)(ref Source s) if (!isSomeString!Source && isInputRange!Source && isSomeChar!(ElementType!Source) && isSomeChar!Target && Target.sizeof >= ElementType!Source.sizeof && !is(Target == enum)) { - if (s.empty) convError!(Source, Target)(s); + if (s.empty) + throw convError!(Source, Target)(s); Target result = s.front; s.popFront(); return result; @@ -2697,24 +2895,23 @@ Target parse(Target, Source)(ref Source s) if (isExactSomeString!Source && is(Unqual!Target == bool)) { - if (s.length >= 4 && icmp(s[0 .. 4], "true")==0) + if (s.length >= 4 && icmp(s[0 .. 4], "true") == 0) { s = s[4 .. $]; return true; } - if (s.length >= 5 && icmp(s[0 .. 5], "false")==0) + if (s.length >= 5 && icmp(s[0 .. 5], "false") == 0) { s = s[5 .. $]; return false; } - parseError("bool should be case-insensitive 'true' or 'false'"); - assert(0); + throw parseError("bool should be case-insensitive 'true' or 'false'"); } /* Tests for to!bool and parse!bool */ -unittest +@safe pure unittest { debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded."); debug(conv) printf("conv.to!bool.unittest\n"); @@ -2745,16 +2942,15 @@ Target parse(Target, Source)(ref Source s) if (isExactSomeString!Source && is(Unqual!Target == typeof(null))) { - if (s.length >= 4 && icmp(s[0 .. 4], "null")==0) + if (s.length >= 4 && icmp(s[0 .. 4], "null") == 0) { s = s[4 .. $]; return null; } - parseError("null should be case-insensitive 'null'"); - assert(0); + throw parseError("null should be case-insensitive 'null'"); } -unittest +@safe pure unittest { alias typeof(null) NullType; auto s1 = "null"; @@ -2770,7 +2966,7 @@ unittest assert(m == "maybe"); // m shouldn't change on failure auto s = "NULL"; - assert(parse!(const(NullType))(s) is null); + assert(parse!(const NullType)(s) is null); } //Used internally by parse Array/AA, to remove ascii whites @@ -2779,7 +2975,7 @@ package void skipWS(R)(ref R r) static if (isSomeString!R) { //Implementation inspired from stripLeft. - foreach(i, dchar c; r) + foreach (i, dchar c; r) { if (!std.ascii.isWhite(c)) { @@ -2792,8 +2988,8 @@ package void skipWS(R)(ref R r) } else { - for ( ; !r.empty && std.ascii.isWhite(r.front) ; r.popFront()) - { } + for (; !r.empty && std.ascii.isWhite(r.front); r.popFront()) + {} } } @@ -2810,7 +3006,8 @@ Target parse(Target, Source)(ref Source s, dchar lbracket = '[', dchar rbracket parseCheck!s(lbracket); skipWS(s); - if (s.empty) convError!(Source, Target)(s); + if (s.empty) + throw convError!(Source, Target)(s); if (s.front == rbracket) { s.popFront(); @@ -2820,7 +3017,8 @@ Target parse(Target, Source)(ref Source s, dchar lbracket = '[', dchar rbracket { result ~= parseElement!(ElementType!Target)(s); skipWS(s); - if (s.empty) convError!(Source, Target)(s); + if (s.empty) + throw convError!(Source, Target)(s); if (s.front != comma) break; } @@ -2854,7 +3052,7 @@ unittest assert( ia == ia2); } -unittest +@safe pure unittest { auto s1 = `[['h', 'e', 'l', 'l', 'o'], "world"]`; auto a1 = parse!(string[])(s1); @@ -2865,11 +3063,11 @@ unittest assert(a2 == ["aaa", "bbb", "ccc"]); } -unittest +@safe pure unittest { //Check proper failure auto s = "[ 1 , 2 , 3 ]"; - foreach(i ; 0..s.length-1) + foreach (i ; 0..s.length-1) { auto ss = s[0 .. i]; assertThrown!ConvException(parse!(int[])(ss)); @@ -2877,7 +3075,7 @@ unittest int[] arr = parse!(int[])(s); } -unittest +@safe pure unittest { //Checks parsing of strings with escaped characters string s1 = `[ @@ -2910,11 +3108,15 @@ Target parse(Target, Source)(ref Source s, dchar lbracket = '[', dchar rbracket if (isExactSomeString!Source && isStaticArray!Target && !is(Target == enum)) { - Target result = void; + static if (hasIndirections!Target) + Target result = Target.init[0].init; + else + Target result = void; parseCheck!s(lbracket); skipWS(s); - if (s.empty) convError!(Source, Target)(s); + if (s.empty) + throw convError!(Source, Target)(s); if (s.front == rbracket) { static if (result.length != 0) @@ -2931,7 +3133,8 @@ Target parse(Target, Source)(ref Source s, dchar lbracket = '[', dchar rbracket goto Lmanyerr; result[i++] = parseElement!(ElementType!Target)(s); skipWS(s); - if (s.empty) convError!(Source, Target)(s); + if (s.empty) + throw convError!(Source, Target)(s); if (s.front != comma) { if (i != result.length) @@ -2944,15 +3147,13 @@ Target parse(Target, Source)(ref Source s, dchar lbracket = '[', dchar rbracket return result; Lmanyerr: - parseError(text("Too many elements in input, ", result.length, " elements expected.")); - assert(0); + throw parseError(text("Too many elements in input, ", result.length, " elements expected.")); Lfewerr: - parseError(text("Too few elements in input, ", result.length, " elements expected.")); - assert(0); + throw parseError(text("Too few elements in input, ", result.length, " elements expected.")); } -unittest +@safe pure unittest { auto s1 = "[1,2,3,4]"; auto sa1 = parse!(int[4])(s1); @@ -2978,14 +3179,15 @@ Target parse(Target, Source)(ref Source s, dchar lbracket = '[', dchar rbracket if (isExactSomeString!Source && isAssociativeArray!Target && !is(Target == enum)) { - alias typeof(Target.keys[0]) KeyType; - alias typeof(Target.values[0]) ValueType; + alias KeyType = typeof(Target.init.keys[0]); + alias ValType = typeof(Target.init.values[0]); Target result; parseCheck!s(lbracket); skipWS(s); - if (s.empty) convError!(Source, Target)(s); + if (s.empty) + throw convError!(Source, Target)(s); if (s.front == rbracket) { s.popFront(); @@ -2997,18 +3199,20 @@ Target parse(Target, Source)(ref Source s, dchar lbracket = '[', dchar rbracket skipWS(s); parseCheck!s(keyval); skipWS(s); - auto val = parseElement!ValueType(s); + auto val = parseElement!ValType(s); skipWS(s); result[key] = val; - if (s.empty) convError!(Source, Target)(s); - if (s.front != comma) break; + if (s.empty) + throw convError!(Source, Target)(s); + if (s.front != comma) + break; } parseCheck!s(rbracket); return result; } -unittest +@safe pure unittest { auto s1 = "[1:10, 2:20, 3:30]"; auto aa1 = parse!(int[int])(s1); @@ -3023,11 +3227,11 @@ unittest assert(aa3 == ["aaa":[1], "bbb":[2,3], "ccc":[4,5,6]]); } -unittest +@safe pure unittest { //Check proper failure auto s = "[1:10, 2:20, 3:30]"; - foreach(i ; 0..s.length-1) + foreach (i ; 0 .. s.length-1) { auto ss = s[0 .. i]; assertThrown!ConvException(parse!(int[int])(ss)); @@ -3039,16 +3243,19 @@ private dchar parseEscape(Source)(ref Source s) if (isInputRange!Source && isSomeChar!(ElementType!Source)) { parseCheck!s('\\'); - if (s.empty) parseError("Unterminated escape sequence"); + if (s.empty) + throw parseError("Unterminated escape sequence"); - dchar getHexDigit() + dchar getHexDigit()(ref Source s_ = s) // workaround { - if (s.empty) parseError("Unterminated escape sequence"); - s.popFront(); - if (s.empty) parseError("Unterminated escape sequence"); - dchar c = s.front; + if (s_.empty) + throw parseError("Unterminated escape sequence"); + s_.popFront(); + if (s_.empty) + throw parseError("Unterminated escape sequence"); + dchar c = s_.front; if (!isHexDigit(c)) - parseError("Hex digit is missing"); + throw parseError("Hex digit is missing"); return std.ascii.isAlpha(c) ? ((c & ~0x20) - ('A' - 10)) : c - '0'; } @@ -3071,14 +3278,12 @@ private dchar parseEscape(Source)(ref Source s) case 'x': result = getHexDigit() << 4; result |= getHexDigit(); - if (s.empty) parseError("Unterminated escape sequence"); break; case 'u': result = getHexDigit() << 12; result |= getHexDigit() << 8; result |= getHexDigit() << 4; result |= getHexDigit(); - if (s.empty) parseError("Unterminated escape sequence"); break; case 'U': result = getHexDigit() << 28; @@ -3089,24 +3294,24 @@ private dchar parseEscape(Source)(ref Source s) result |= getHexDigit() << 8; result |= getHexDigit() << 4; result |= getHexDigit(); - if (s.empty) parseError("Unterminated escape sequence"); break; default: - parseError("Unknown escape character " ~ to!string(s.front)); - break; + throw parseError("Unknown escape character " ~ to!string(s.front)); } + if (s.empty) + throw parseError("Unterminated escape sequence"); s.popFront(); return result; } -unittest +@safe pure unittest { string[] s1 = [ `\"`, `\'`, `\?`, `\\`, `\a`, `\b`, `\f`, `\n`, `\r`, `\t`, `\v`, //Normal escapes //`\141`, //@@@9621@@@ Octal escapes. - `\x61`, + `\x61`, `\u65E5`, `\U00012456` //`\&`, `\"`, //@@@9621@@@ Named Character Entities. ]; @@ -3114,7 +3319,7 @@ unittest const(dchar)[] s2 = [ '\"', '\'', '\?', '\\', '\a', '\b', '\f', '\n', '\r', '\t', '\v', //Normal escapes //'\141', //@@@9621@@@ Octal escapes. - '\x61', + '\x61', '\u65E5', '\U00012456' //'\&', '\"', //@@@9621@@@ Named Character Entities. ]; @@ -3126,7 +3331,7 @@ unittest } } -unittest +@safe pure unittest { string[] ss = [ `hello!`, //Not an escape @@ -3153,12 +3358,14 @@ Target parseElement(Target, Source)(ref Source s) auto result = appender!Target(); // parse array of chars - if (s.empty) convError!(Source, Target)(s); + if (s.empty) + throw convError!(Source, Target)(s); if (s.front == '[') return parse!Target(s); parseCheck!s('\"'); - if (s.empty) convError!(Source, Target)(s); + if (s.empty) + throw convError!(Source, Target)(s); if (s.front == '\"') { s.popFront(); @@ -3167,7 +3374,7 @@ Target parseElement(Target, Source)(ref Source s) while (true) { if (s.empty) - parseError("Unterminated quoted string"); + throw parseError("Unterminated quoted string"); switch (s.front) { case '\"': @@ -3193,7 +3400,8 @@ Target parseElement(Target, Source)(ref Source s) Target c; parseCheck!s('\''); - if (s.empty) convError!(Source, Target)(s); + if (s.empty) + throw convError!(Source, Target)(s); if (s.front != '\\') { c = s.front; @@ -3216,54 +3424,44 @@ Target parseElement(Target, Source)(ref Source s) /*************************************************************** - Convenience functions for converting any number and types of - arguments into _text (the three character widths). - - Example: ----- -assert(text(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"); -assert(wtext(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"w); -assert(dtext(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"d); ----- -*/ -string text(T...)(T args) -{ - return textImpl!string(args); -} + * Convenience functions for converting any number and types of + * arguments into _text (the three character widths). + */ +string text(T...)(T args) { return textImpl!string(args); } ///ditto -wstring wtext(T...)(T args) -{ - return textImpl!wstring(args); -} +wstring wtext(T...)(T args) { return textImpl!wstring(args); } ///ditto -dstring dtext(T...)(T args) -{ - return textImpl!dstring(args); -} +dstring dtext(T...)(T args) { return textImpl!dstring(args); } -private S textImpl(S, U...)(U args) if (U.length == 0) +private S textImpl(S, U...)(U args) { - return null; + static if (U.length == 0) + { + return null; + } + else + { + auto result = to!S(args[0]); + foreach (arg; args[1 .. $]) + result ~= to!S(arg); + return result; + } } - -private S textImpl(S, U...)(U args) if (U.length > 0) -{ - auto result = to!S(args[0]); - foreach (arg; args[1 .. $]) result ~= to!S(arg); - return result; -} - +/// unittest { - debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded."); - assert(text(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"); + assert( text(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"c); assert(wtext(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"w); assert(dtext(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"d); +} +unittest +{ assert(text() is null); assert(wtext() is null); assert(dtext() is null); } + /*************************************************************** The $(D octal) facility is intended as an experimental facility to replace _octal literals starting with $(D '0'), which many find @@ -3513,25 +3711,18 @@ Given a pointer $(D chunk) to uninitialized memory (but already typed as $(D T)), constructs an object of non-$(D class) type $(D T) at that address. -This function can be $(D @trusted) if the corresponding constructor of -$(D T) is $(D @safe). - Returns: A pointer to the newly constructed object (which is the same as $(D chunk)). */ -T* emplace(T)(T* chunk) - if (!is(T == class)) +T* emplace(T)(T* chunk) @safe nothrow pure { - static T i; // Can't use `= T.init` here because of @@@BUG8902@@@. - memcpy(chunk, &i, T.sizeof); - return chunk; -} -///ditto -T* emplace(T)(T* chunk) - if (is(T == class)) -{ - *chunk = null; - return chunk; + static assert (is(T* : void*), + format("Cannot emplace a %s because it is qualified.", T.stringof)); + + static assert (is(typeof({static T i;})), + format("Cannot emplace a %1$s because %1$s.this() is annotated with @disable.", T.stringof)); + + return emplaceInitializer(chunk); } version(unittest) private struct __conv_EmplaceTest @@ -3576,6 +3767,7 @@ unittest struct S { @disable this(); } S s = void; static assert(!__traits(compiles, emplace(&s))); + static assert( __traits(compiles, emplace(&s, S.init))); } unittest @@ -3592,6 +3784,67 @@ unittest assert(i is null); } +unittest +{ + static struct S {int i = 5;} + S[2] s2 = void; + emplace(&s2); + assert(s2[0].i == 5 && s2[1].i == 5); +} + +unittest +{ + struct S1 + {} + + struct S2 + { + void opAssign(S2); + } + + S1 s1 = void; + S2 s2 = void; + S1[2] as1 = void; + S2[2] as2 = void; + emplace(&s1); + emplace(&s2); + emplace(&as1); + emplace(&as2); +} + +unittest +{ + static struct S1 + { + this(this) @disable; + } + static struct S2 + { + this() @disable; + } + S1[2] ss1 = void; + S2[2] ss2 = void; + static assert( __traits(compiles, emplace(&ss1))); + static assert(!__traits(compiles, emplace(&ss2))); + S1 s1 = S1.init; + S2 s2 = S2.init; + static assert(!__traits(compiles, emplace(&ss1, s1))); + static assert( __traits(compiles, emplace(&ss2, s2))); +} + +unittest +{ + struct S + { + immutable int i; + } + S s = void; + S[2] ss1 = void; + S[2] ss2 = void; + emplace(&s, 5); + emplace(&ss1, s); + emplace(&ss2, ss1); +} /** Given a pointer $(D chunk) to uninitialized memory (but already typed @@ -3604,11 +3857,92 @@ $(D T) is $(D @safe). Returns: A pointer to the newly constructed object (which is the same as $(D chunk)). */ -T* emplace(T, Args...)(T* chunk, Args args) +T* emplace(T, Args...)(T* chunk, auto ref Args args) if (!is(T == struct) && Args.length == 1) { - *chunk = args[0]; - return chunk; + alias Arg = Args[0]; + alias arg = args[0]; + + static assert (is(T* : void*), + format("Cannot emplace a %s because it is qualified.", T.stringof)); + + static assert(is(typeof({T t = args[0];})), + format("%s cannot be emplaced from a %s.", T.stringof, Arg.stringof)); + + static if (isStaticArray!T) + { + alias UArg = Unqual!Arg; + alias E = typeof(chunk.ptr[0]); + enum N = T.length; + + static if (is(Arg : T)) + { + //Matching static array + static if (isAssignable!(T, Arg) && !hasElaborateAssign!T) + *chunk = arg; + else static if (is(UArg == T)) + { + memcpy(chunk, &arg, T.sizeof); + static if (hasElaborateCopyConstructor!T) + typeid(T).postblit(cast(void*)&chunk); + } + else + emplace(chunk, cast(T)arg); + } + else static if (is(Arg : E[])) + { + //Matching dynamic array + static if (is(typeof((*chunk)[] = arg[])) && !hasElaborateAssign!T) + (*chunk)[] = arg[]; + else static if (is(UArg == E[])) + { + assert(N == chunk.length, "Array length missmatch in emplace"); + memcpy(cast(void*)chunk, arg.ptr, T.sizeof); + static if (hasElaborateCopyConstructor!T) + typeid(T).postblit(cast(void*)&chunk); + } + else + emplace(chunk, cast(E[])arg); + } + else static if (is(Arg : E)) + { + //Case matching single element to array. + static if (is(typeof((*chunk)[] = arg)) && !hasElaborateAssign!T) + (*chunk)[] = arg; + else static if (is(UArg == E)) + { + //Note: We copy everything, and then postblit just once. + //This is as exception safe as what druntime can provide us. + foreach(i; 0 .. N) + memcpy(cast(void*)(chunk.ptr + i), &arg, E.sizeof); + static if (hasElaborateCopyConstructor!T) + typeid(T).postblit(chunk); + } + else + //Alias this. Coerce. + emplace(chunk, cast(E)arg); + } + else static if (is(typeof(emplace(chunk.ptr, arg)))) + { + //Final case for everything else: + //Types that don't match (int to uint[2]) + //Recursion for multidimensions + static if (is(typeof((*chunk)[] = arg)) && !hasElaborateAssign!T) + (*chunk)[] = arg; + + foreach(i; 0 .. N) + emplace(chunk.ptr + i, arg); + } + else + static assert(0, format("Sorry, this implementation doesn't know how to emplace a %s with a %s", T.stringof, Arg.stringof)); + + return chunk; + } + else + { + *chunk = arg; + return chunk; + } } unittest @@ -3635,43 +3969,115 @@ unittest assert(i is k); } -// Specialization for struct +unittest +{ + static struct S + { + int i = 5; + void opAssign(S){assert(0);} + } + S[2] sa = void; + S[2] sb; + emplace(&sa, sb); + assert(sa[0].i == 5 && sa[1].i == 5); +} + +/// ditto T* emplace(T, Args...)(T* chunk, auto ref Args args) if (is(T == struct)) { - void initialize() - { - if(auto p = typeid(T).init().ptr) - memcpy(chunk, p, T.sizeof); - else - memset(chunk, 0, T.sizeof); - } + static assert (is(T* : void*), + format("Cannot emplace a %s because it is qualified.", T.stringof)); - static if (is(typeof(chunk.__ctor(args)))) + static if (Args.length == 1 && is(Args[0] : T) && + is (typeof({T t = args[0];})) //Check for legal postblit + ) + { + static if (is(T == Unqual!(Args[0]))) + { + //Types match exactly: we postblit + static if (isAssignable!T && !hasElaborateAssign!T) + *chunk = args[0]; + else + { + memcpy(chunk, &args[0], T.sizeof); + static if (hasElaborateCopyConstructor!T) + typeid(T).postblit(chunk); + } + } + else + //Alias this. Coerce to type T. + emplace(chunk, cast(T)args[0]); + } + else static if (is(typeof(chunk.__ctor(args)))) { // T defines a genuine constructor accepting args // Go the classic route: write .init first, then call ctor - initialize(); + emplaceInitializer(chunk); chunk.__ctor(args); } + else static if (is(typeof(T.opCall(args)))) + { + //Can be built calling opCall + emplaceOpCaller(chunk, args); //emplaceOpCaller is deprecated + } else static if (is(typeof(T(args)))) { // Struct without constructor that has one matching field for - // each argument - *chunk = T(args); + // each argument. Individually emplace each field + emplaceInitializer(chunk); + foreach (i, ref field; chunk.tupleof[0 .. Args.length]) + emplace(emplaceGetAddr(field), args[i]); } - else //static if (Args.length == 1 && is(Args[0] : T)) + else { - static assert(Args.length == 1); - //static assert(0, T.stringof ~ " " ~ Args.stringof); - // initialize(); - *chunk = args[0]; + //We can't emplace. Try to diagnose a disabled postblit. + static assert(!(Args.length == 1 && is(Args[0] : T)), + format("Cannot emplace a %1$s because %1$s.this(this) is annotated with @disable.", T.stringof)); + + //We can't emplace. + static assert(false, + format("%s cannot be emplaced from %s.", T.stringof, Args[].stringof)); } + return chunk; } -// Test constructor branch +//emplace helper functions +private T* emplaceInitializer(T)(T* chunk) @trusted pure nothrow +{ + static if (isAssignable!T && !hasElaborateAssign!T) + *chunk = T.init; + else + { + static immutable T init = T.init; + memcpy(chunk, &init, T.sizeof); + } + return chunk; +} +private deprecated("Using static opCall for emplace is deprecated. Plase use emplace(chunk, T(args)) instead.") +T* emplaceOpCaller(T, Args...)(T* chunk, auto ref Args args) +{ + static assert (is(typeof({T t = T.opCall(args);})), + format("%s.opCall does not return adequate data for construction.", T.stringof)); + return emplace(chunk, chunk.opCall(args)); +} +private +{ + //Helper to keep simple aggregate emplace safe. + auto emplaceGetAddr(T)(ref T t) @trusted + if (is(T == Unqual!T)) + { + return &t; + } + auto emplaceGetAddr(T)(ref T t) + if (!is(T == Unqual!T)) + { + return cast(Unqual!T*)&t; + } +} +// Test constructor branch unittest { debug(conv) scope(success) writeln("unittest @", __FILE__, ":", __LINE__, " succeeded."); @@ -3709,7 +4115,6 @@ unittest } // Test matching fields branch - unittest { struct S { uint n; } @@ -3737,9 +4142,563 @@ unittest assert(s2.a == 2 && s2.b == 3); } -// Test assignment branch +//opAssign +unittest +{ + static struct S + { + int i = 5; + void opAssign(int){assert(0);} + void opAssign(S){assert(0);} + } + S sa1 = void; + S sa2 = void; + S sb1 = S(1); + emplace(&sa1, sb1); + emplace(&sa2, 2); + assert(sa1.i == 1); + assert(sa2.i == 2); +} -// FIXME: no tests +//postblit precedence +unittest +{ + //Works, but breaks in "-w -O" because of @@@9332@@@. + //Uncomment test when 9332 is fixed. + static struct S + { + int i; + + this(S other){assert(false);} + this(int i){this.i = i;} + this(this){} + } + S a = void; + assert(is(typeof({S b = a;}))); //Postblit + assert(is(typeof({S b = S(a);}))); //Constructor + auto b = S(5); + emplace(&a, b); + assert(a.i == 5); + + static struct S2 + { + int* p; + this(const S2){}; + } + static assert(!is(immutable S2 : S2)); + S2 s2 = void; + immutable is2 = (immutable S2).init; + emplace(&s2, is2); +} + +//nested structs and postblit +unittest +{ + static struct S + { + int* p; + this(int i){p = [i].ptr;} + this(this) + { + if (p) + p = [*p].ptr; + } + } + static struct SS + { + S s; + void opAssign(const SS) + { + assert(0); + } + } + SS ssa = void; + SS ssb = SS(S(5)); + emplace(&ssa, ssb); + assert(*ssa.s.p == 5); + assert(ssa.s.p != ssb.s.p); +} + +//disabled postblit +unittest +{ + static struct S1 + { + int i; + @disable this(this); + } + S1 s1 = void; + static assert( __traits(compiles, emplace(&s1, 1))); + static assert(!__traits(compiles, emplace(&s1, S1.init))); + + static struct S2 + { + int i; + @disable this(this); + this(ref S2){} + } + S2 s2 = void; + static assert(!__traits(compiles, emplace(&s2, 1))); + static assert( __traits(compiles, emplace(&s2, S2.init))); + + static struct SS1 + { + S1 s; + } + SS1 ss1 = void; + static assert( __traits(compiles, emplace(&ss1))); + static assert(!__traits(compiles, emplace(&ss1, SS1.init))); + + static struct SS2 + { + S2 s; + } + SS2 ss2 = void; + static assert( __traits(compiles, emplace(&ss2))); + static assert(!__traits(compiles, emplace(&ss2, SS2.init))); + + + // SS1 sss1 = s1; //This doesn't compile + // SS1 sss1 = SS1(s1); //This doesn't compile + // So emplace shouldn't compile either + static assert(!__traits(compiles, emplace(&sss1, s1))); + static assert(!__traits(compiles, emplace(&sss2, s2))); +} + +//Imutability +unittest +{ + //Castable immutability + { + static struct S1 + { + int i; + } + static assert(is( immutable(S1) : S1)); + S1 sa = void; + auto sb = immutable(S1)(5); + emplace(&sa, sb); + assert(sa.i == 5); + } + //Un-castable immutability + { + static struct S2 + { + int* p; + } + static assert(!is(immutable(S2) : S2)); + S2 sa = void; + auto sb = immutable(S2)(null); + assert(!__traits(compiles, emplace(&sa, sb))); + } +} + +unittest +{ + static struct S + { + immutable int i; + immutable(int)* j; + } + S s = void; + emplace(&s, 1, null); + emplace(&s, 2, &s.i); + assert(s is S(2, &s.i)); +} + +//Context pointer +unittest +{ + int i = 0; + { + struct S1 + { + void foo(){++i;} + } + S1 sa = void; + S1 sb; + emplace(&sa, sb); + sa.foo(); + assert(i == 1); + } + { + struct S2 + { + void foo(){++i;} + this(this){} + } + S2 sa = void; + S2 sb; + emplace(&sa, sb); + sa.foo(); + assert(i == 2); + } + + ////NOTE: THESE WILL COMPILE + ////But will not correctly emplace the context pointer + ////The problem lies with voldemort, and not emplace. + //{ + // struct S3 + // { + // int k; + // void foo(){++i;} + // } + //} + //S3 s3 = void; + //emplace(&s3); //S3.init has no context pointer information + //emplace(&s3, 1); //No way to obtain context pointer once inside emplace +} + +//Alias this +unittest +{ + static struct S + { + int i; + } + //By Ref + { + static struct SS1 + { + int j; + S s; + alias s this; + } + S s = void; + SS1 ss = SS1(1, S(2)); + emplace(&s, ss); + assert(s.i == 2); + } + //By Value + { + static struct SS2 + { + int j; + S s; + S foo() @property{return s;} + alias foo this; + } + S s = void; + SS2 ss = SS2(1, S(2)); + emplace(&s, ss); + assert(s.i == 2); + } +} +version(unittest) +{ + //Ambiguity + struct __std_conv_S + { + int i; + this(__std_conv_SS ss) {assert(0);} + static opCall(__std_conv_SS ss) + { + __std_conv_S s; s.i = ss.j; + return s; + } + } + struct __std_conv_SS + { + int j; + __std_conv_S s; + ref __std_conv_S foo() @property {s.i = j; return s;} + alias foo this; + } + static assert(is(__std_conv_SS : __std_conv_S)); + unittest + { + __std_conv_S s = void; + __std_conv_SS ss = __std_conv_SS(1); + + __std_conv_S sTest1 = ss; //this calls "SS alias this" (and not "S.this(SS)") + emplace(&s, ss); //"alias this" should take precedence in emplace over "opCall" + assert(s.i == 1); + } +} + +//Nested classes +unittest +{ + class A{} + static struct S + { + A a; + } + S s1 = void; + S s2 = S(new A); + emplace(&s1, s2); + assert(s1.a is s2.a); +} + +//safety & nothrow & CTFE +unittest +{ + //emplace should be safe for anything with no elaborate opassign + static struct S1 + { + int i; + } + static struct S2 + { + int i; + this(int j)@safe nothrow{i = j;} + } + + int i; + S1 s1 = void; + S2 s2 = void; + + auto pi = &i; + auto ps1 = &s1; + auto ps2 = &s2; + + void foo() @safe nothrow + { + emplace(pi); + emplace(pi, 5); + emplace(ps1); + emplace(ps1, 5); + emplace(ps1, S1.init); + emplace(ps2); + emplace(ps2, 5); + emplace(ps2, S2.init); + } + + T bar(T)() @property + { + T t/+ = void+/; //CTFE void illegal + emplace(&t, 5); + return t; + } + enum a = bar!int; + enum b = bar!S1; + enum c = bar!S2; +} + + +unittest +{ + struct S + { + int[2] get(){return [1, 2];} + alias get this; + } + struct SS + { + int[2] ii; + } + struct ISS + { + int[2] ii; + } + S s; + SS ss = void; + ISS iss = void; + emplace(&ss, s); + emplace(&iss, s); + assert(ss.ii == [1, 2]); + assert(iss.ii == [1, 2]); +} + +//disable opAssign +unittest +{ + static struct S + { + @disable void opAssign(S); + } + S s; + emplace(&s, S.init); +} + +//opCall +unittest +{ + int i; + //Without constructor + { + static struct S1 + { + int i; + static S1 opCall(int*){assert(0);} + } + S1 s = void; + static assert(!__traits(compiles, emplace(&s, 1))); + static assert( __traits(compiles, emplace(&s, &i))); //(works, but deprected) + } + //With constructor + { + static struct S2 + { + int i = 0; + static S2 opCall(int*){assert(0);} + static S2 opCall(int){assert(0);} + this(int i){this.i = i;} + } + S2 s = void; + static assert( __traits(compiles, emplace(&s, 1))); //(works, but deprected) + static assert( __traits(compiles, emplace(&s, &i))); //(works, but deprected) + emplace(&s, 1); + assert(s.i == 1); + } + //With postblit ambiguity + { + static struct S3 + { + int i = 0; + static S3 opCall(ref S3){assert(0);} + } + S3 s = void; + static assert( __traits(compiles, emplace(&s, S3.init))); + } +} + +unittest //@@@9559@@@ +{ + alias Nullable!int I; + auto ints = [0, 1, 2].map!(i => i & 1 ? I.init : I(i))(); + auto asArray = std.array.array(ints); +} + +unittest //http://forum.dlang.org/thread/nxbdgtdlmwscocbiypjs@forum.dlang.org +{ + import std.datetime; + static struct A + { + double i; + } + + static struct B + { + invariant() + { + if(j == 0) + assert(a.i.isNaN, "why is 'j' zero?? and i is not NaN?"); + else + assert(!a.i.isNaN); + } + SysTime when; // comment this line avoid the breakage + int j; + A a; + } + + B b1 = B.init; + assert(&b1); // verify that default eyes invariants are ok; + + auto b2 = B(SysTime(0, UTC()), 1, A(1)); + assert(&b2); + auto b3 = B(SysTime(0, UTC()), 1, A(1)); + assert(&b3); + + import std.array; + auto arr = [b2, b3]; + + assert(arr[0].j == 1); + assert(arr[1].j == 1); + auto a2 = arr.array(); // << bang, invariant is raised, also if b2 and b3 are good +} + +//static arrays +unittest +{ + static struct S + { + int[2] ii; + } + static struct IS + { + immutable int[2] ii; + } + int[2] ii; + S s = void; + IS ims = void; + ubyte ub = 2; + emplace(&s, ub); + emplace(&s, ii); + emplace(&ims, ub); + emplace(&ims, ii); + uint[2] uu; + static assert(!__traits(compiles, {S ss = S(uu);})); + static assert(!__traits(compiles, emplace(&s, uu))); +} + +unittest +{ + int[2] sii; + int[2] sii2; + uint[2] uii; + uint[2] uii2; + emplace(&sii, 1); + emplace(&sii, 1U); + emplace(&uii, 1); + emplace(&uii, 1U); + emplace(&sii, sii2); + //emplace(&sii, uii2); //Sorry, this implementation doesn't know how to... + //emplace(&uii, sii2); //Sorry, this implementation doesn't know how to... + emplace(&uii, uii2); + emplace(&sii, sii2[]); + //emplace(&sii, uii2[]); //Sorry, this implementation doesn't know how to... + //emplace(&uii, sii2[]); //Sorry, this implementation doesn't know how to... + emplace(&uii, uii2[]); +} + +unittest +{ + bool allowDestruction = false; + struct S + { + int i; + this(this){} + ~this(){assert(allowDestruction);} + } + S s = S(1); + S[2] ss1 = void; + S[2] ss2 = void; + S[2] ss3 = void; + emplace(&ss1, s); + emplace(&ss2, ss1); + emplace(&ss3, ss2[]); + assert(ss1[1] == s); + assert(ss2[1] == s); + assert(ss3[1] == s); + allowDestruction = true; +} + +unittest +{ + //Checks postblit, construction, and context pointer + int count = 0; + struct S + { + this(this) + { + ++count; + } + ~this() + { + --count; + } + } + + S s; + { + S[4] ss = void; + emplace(&ss, s); + assert(count == 4); + } + assert(count == 0); +} + +unittest +{ + struct S + { + int i; + } + S s; + S[2][2][2] sss = void; + emplace(&sss, s); +} private void testEmplaceChunk(void[] chunk, size_t typeSize, size_t typeAlignment, string typeName) { @@ -3764,7 +4723,8 @@ $(D T) is $(D @safe). Returns: A pointer to the newly constructed object. */ -T emplace(T, Args...)(void[] chunk, auto ref Args args) if (is(T == class)) +T emplace(T, Args...)(void[] chunk, auto ref Args args) + if (is(T == class)) { enum classSize = __traits(classInstanceSize, T); testEmplaceChunk(chunk, classSize, classInstanceAlignment!T, T.stringof); @@ -3903,3 +4863,138 @@ unittest toTextRange(-1, result); assert(result.data == "-1"); } + + +/** + Returns the corresponding unsigned value for $(D x) (e.g. if $(D x) has type + $(D int), it returns $(D cast(uint) x)). The advantage compared to the cast + is that you do not need to rewrite the cast if $(D x) later changes type + (e.g from $(D int) to $(D long)). + + Note that the result is always mutable even if the original type was const + or immutable. In order to retain the constness, use $(XREF traits, Unsigned). + */ +auto unsigned(T)(T x) if (isIntegral!T) +{ + return cast(Unqual!(Unsigned!T))x; +} + +/// +unittest +{ + uint s = 42; + auto u1 = unsigned(s); //not qualified + Unsigned!(typeof(s)) u2 = unsigned(s); //same qualification + immutable u3 = unsigned(s); //totally qualified +} + +unittest +{ + foreach(T; TypeTuple!(byte, ubyte)) + { + static assert(is(typeof(unsigned(cast(T)1)) == ubyte)); + static assert(is(typeof(unsigned(cast(const T)1)) == ubyte)); + static assert(is(typeof(unsigned(cast(immutable T)1)) == ubyte)); + } + + foreach(T; TypeTuple!(short, ushort)) + { + static assert(is(typeof(unsigned(cast(T)1)) == ushort)); + static assert(is(typeof(unsigned(cast(const T)1)) == ushort)); + static assert(is(typeof(unsigned(cast(immutable T)1)) == ushort)); + } + + foreach(T; TypeTuple!(int, uint)) + { + static assert(is(typeof(unsigned(cast(T)1)) == uint)); + static assert(is(typeof(unsigned(cast(const T)1)) == uint)); + static assert(is(typeof(unsigned(cast(immutable T)1)) == uint)); + } + + foreach(T; TypeTuple!(long, ulong)) + { + static assert(is(typeof(unsigned(cast(T)1)) == ulong)); + static assert(is(typeof(unsigned(cast(const T)1)) == ulong)); + static assert(is(typeof(unsigned(cast(immutable T)1)) == ulong)); + } +} + +auto unsigned(T)(T x) if (isSomeChar!T) +{ + // All characters are unsigned + static assert(T.min == 0); + return cast(Unqual!T) x; +} + +unittest +{ + foreach(T; TypeTuple!(char, wchar, dchar)) + { + static assert(is(typeof(unsigned(cast(T)'A')) == T)); + static assert(is(typeof(unsigned(cast(const T)'A')) == T)); + static assert(is(typeof(unsigned(cast(immutable T)'A')) == T)); + } +} + + +/** + Returns the corresponding signed value for $(D x) (e.g. if $(D x) has type + $(D uint), it returns $(D cast(int) x)). The advantage compared to the cast + is that you do not need to rewrite the cast if $(D x) later changes type + (e.g from $(D uint) to $(D ulong)). + + Note that the result is always mutable even if the original type was const + or immutable. In order to retain the constness, use $(XREF traits, Signed). + */ +auto signed(T)(T x) if (isIntegral!T) +{ + return cast(Unqual!(Signed!T))x; +} + +/// +unittest +{ + uint u = 42; + auto s1 = unsigned(u); //not qualified + Unsigned!(typeof(u)) s2 = unsigned(u); //same qualification + immutable s3 = unsigned(u); //totally qualified +} + +unittest +{ + foreach(T; TypeTuple!(byte, ubyte)) + { + static assert(is(typeof(signed(cast(T)1)) == byte)); + static assert(is(typeof(signed(cast(const T)1)) == byte)); + static assert(is(typeof(signed(cast(immutable T)1)) == byte)); + } + + foreach(T; TypeTuple!(short, ushort)) + { + static assert(is(typeof(signed(cast(T)1)) == short)); + static assert(is(typeof(signed(cast(const T)1)) == short)); + static assert(is(typeof(signed(cast(immutable T)1)) == short)); + } + + foreach(T; TypeTuple!(int, uint)) + { + static assert(is(typeof(signed(cast(T)1)) == int)); + static assert(is(typeof(signed(cast(const T)1)) == int)); + static assert(is(typeof(signed(cast(immutable T)1)) == int)); + } + + foreach(T; TypeTuple!(long, ulong)) + { + static assert(is(typeof(signed(cast(T)1)) == long)); + static assert(is(typeof(signed(cast(const T)1)) == long)); + static assert(is(typeof(signed(cast(immutable T)1)) == long)); + } +} + +unittest +{ + // issue 10874 + enum Test { a = 0 } + ulong l = 0; + auto t = l.to!Test; +} diff --git a/std/cstream.d b/std/cstream.d index 923272478..732245740 100644 --- a/std/cstream.d +++ b/std/cstream.d @@ -38,6 +38,7 @@ class CFile : Stream { /** * Create the stream wrapper for the given C file. * Params: + * cfile = a valid C $(B FILE) pointer to wrap. * mode = a bitwise combination of $(B FileMode.In) for a readable file * and $(B FileMode.Out) for a writeable file. * seekable = indicates if the stream should be _seekable. @@ -102,7 +103,7 @@ class CFile : Stream { * Ditto */ override char ungetc(char c) { - return cast(char).std.c.stdio.ungetc(c,cfile); + return cast(char)std.c.stdio.ungetc(c,cfile); } /** diff --git a/std/csv.d b/std/csv.d index fedf41042..45744118f 100644 --- a/std/csv.d +++ b/std/csv.d @@ -430,7 +430,7 @@ unittest int value; } - Layout ans[3]; + Layout[3] ans; ans[0].name = "one"; ans[0].value = 1; ans[1].name = "two"; @@ -481,7 +481,7 @@ unittest double other; } - Layout ans[2]; + Layout[2] ans; ans[0].name = "\U00010143Hello"; ans[0].value = 65; ans[0].other = 63.63; @@ -528,7 +528,7 @@ unittest auto records = csvReader!Layout(str, ["b","c","a"]); - Layout ans[2]; + Layout[2] ans; ans[0].name = "Hello"; ans[0].value = 65; ans[0].other = 63.63; @@ -1165,7 +1165,7 @@ public: void popFront() { // Skip last of record when header is depleted. - if(_popCount && _popCount.empty) + if(_popCount.ptr && _popCount.empty) while(!recordEnd()) { prime(1); diff --git a/std/datetime.d b/std/datetime.d index 57af05e2b..3491d4411 100644 --- a/std/datetime.d +++ b/std/datetime.d @@ -26393,6 +26393,13 @@ public: } + /++ Ditto +/ + /+ref+/ IntervalRange opAssign(IntervalRange rhs) pure nothrow + { + return this = rhs; + } + + /++ Whether this $(D IntervalRange) is empty. +/ @@ -26910,6 +26917,13 @@ public: } + /++ Ditto +/ + /+ref+/ PosInfIntervalRange opAssign(PosInfIntervalRange rhs) pure nothrow + { + return this = rhs; + } + + /++ This is an infinite range, so it is never empty. +/ @@ -27209,6 +27223,13 @@ public: } + /++ Ditto +/ + /+ref+/ NegInfIntervalRange opAssign(NegInfIntervalRange rhs) pure nothrow + { + return this = rhs; + } + + /++ This is an infinite range, so it is never empty. +/ @@ -28181,9 +28202,9 @@ public: try { auto currYear = (cast(Date)Clock.currTime()).year; - auto janOffset = SysTime(Date(currYear, 1, 4), this).stdTime - + auto janOffset = SysTime(Date(currYear, 1, 4), cast(immutable)this).stdTime - SysTime(Date(currYear, 1, 4), UTC()).stdTime; - auto julyOffset = SysTime(Date(currYear, 7, 4), this).stdTime - + auto julyOffset = SysTime(Date(currYear, 7, 4), cast(immutable)this).stdTime - SysTime(Date(currYear, 7, 4), UTC()).stdTime; return janOffset != julyOffset; @@ -30441,6 +30462,7 @@ string tzDatabaseNameToWindowsTZName(string tzName) case "Africa/Johannesburg": return "South Africa Standard Time"; case "Africa/Lagos": return "W. Central Africa Standard Time"; case "Africa/Nairobi": return "E. Africa Standard Time"; + case "Africa/Tripoli": return "Libya Standard Time"; case "Africa/Windhoek": return "Namibia Standard Time"; case "America/Anchorage": return "Alaskan Standard Time"; case "America/Asuncion": return "Paraguay Standard Time"; @@ -30635,6 +30657,7 @@ string windowsTZNameToTZDatabaseName(string tzName) case "Kaliningrad Standard Time": return "Europe/Kaliningrad"; case "Kamchatka Standard Time": return "Asia/Kamchatka"; case "Korea Standard Time": return "Asia/Seoul"; + case "Libya Standard Time": return "Africa/Tripoli"; case "Magadan Standard Time": return "Asia/Magadan"; case "Mauritius Standard Time": return "Indian/Mauritius"; case "Mexico Standard Time": return "America/Mexico_City"; @@ -32242,7 +32265,7 @@ version(testStdDateTime) @safe unittest { @safe static void func(TickDuration td) { - assert(td.to!("seconds", real)() <>= 0); + assert(!td.to!("seconds", real)().isNaN); } auto mt = measureTime!(func)(); @@ -32260,7 +32283,7 @@ version(testStdDateTime) unittest { static void func(TickDuration td) { - assert(td.to!("seconds", real)() <>= 0); + assert(!td.to!("seconds", real)().isNaN); } auto mt = measureTime!(func)(); diff --git a/std/digest/crc.d b/std/digest/crc.d index a9d47cd84..c900eb90b 100644 --- a/std/digest/crc.d +++ b/std/digest/crc.d @@ -46,39 +46,6 @@ $(TR $(TDNW Helpers) $(TD $(MYREF crcHexString) $(MYREF crc32Of)) * * CTFE: * Digests do not work in CTFE - * - * Examples: - * --------- - * //Template API - * import std.digest.crc; - * - * ubyte[4] hash = crc32Of("The quick brown fox jumps over the lazy dog"); - * assert(crcHexString(hash) == "414FA339"); - * - * //Feeding data - * ubyte[1024] data; - * CRC32 crc; - * crc.put(data[]); - * crc.start(); //Start again - * crc.put(data[]); - * hash = crc.finish(); - * --------- - * - * --------- - * //OOP API - * import std.digest.crc; - * - * auto crc = new CRC32Digest(); - * ubyte[] hash = crc.digest("The quick brown fox jumps over the lazy dog"); - * assert(crcHexString(hash) == "414FA339"); - * - * //Feeding data - * ubyte[1024] data; - * crc.put(data[]); - * crc.reset(); //Start again - * crc.put(data[]); - * hash = crc.finish(); - * --------- */ /* * Copyright (c) 2001 - 2002 @@ -98,7 +65,7 @@ version(unittest) import std.bitmanip; -//verify example +/// unittest { //Template API @@ -116,7 +83,7 @@ unittest hash = crc.finish(); } -//verify example +/// unittest { //OOP API @@ -178,36 +145,6 @@ private immutable uint[256] crc32_table = /** * Template API CRC32 implementation. * See $(D std.digest.digest) for differences between template and OOP API. - * - * Examples: - * -------- - * //Simple example, hashing a string using crc32Of helper function - * ubyte[4] hash = crc32Of("abc"); - * //Let's get a hash string - * assert(crcHexString(hash) == "352441C2"); - * -------- - * - * -------- - * //Using the basic API - * CRC32 hash; - * ubyte[1024] data; - * //Initialize data here... - * hash.put(data); - * ubyte[4] result = hash.finish(); - * -------- - * - * -------- - * //Let's use the template features: - * //Note: When passing a CRC32 to a function, it must be passed by reference! - * void doSomething(T)(ref T hash) if(isDigest!T) - * { - * hash.put(cast(ubyte)0); - * } - * CRC32 crc; - * crc.start(); - * doSomething(crc); - * assert(crcHexString(crc.finish()) == "D202EF8D"); - * -------- */ struct CRC32 { @@ -220,21 +157,21 @@ struct CRC32 * Use this to feed the digest with data. * Also implements the $(XREF range, OutputRange) interface for $(D ubyte) and * $(D const(ubyte)[]). - * - * Examples: - * ---- - * CRC32 dig; - * dig.put(cast(ubyte)0); //single ubyte - * dig.put(cast(ubyte)0, cast(ubyte)0); //variadic - * ubyte[10] buf; - * dig.put(buf); //buffer - * ---- */ @trusted pure nothrow void put(scope const(ubyte)[] data...) { foreach (val; data) _state = (_state >> 8) ^ crc32_table[cast(ubyte)_state ^ val]; } + /// + unittest + { + CRC32 dig; + dig.put(cast(ubyte)0); //single ubyte + dig.put(cast(ubyte)0, cast(ubyte)0); //variadic + ubyte[10] buf; + dig.put(buf); //buffer + } /** * Used to initialize the CRC32 digest. @@ -244,30 +181,22 @@ struct CRC32 * is not necessary. Calling start is only necessary to reset the Digest. * * Generic code which deals with different Digest types should always call start though. - * - * Examples: - * -------- - * CRC32 digest; - * //digest.start(); //Not necessary - * digest.put(0); - * -------- */ @trusted pure nothrow void start() { this = CRC32.init; } + /// + unittest + { + CRC32 digest; + //digest.start(); //Not necessary + digest.put(0); + } /** * Returns the finished CRC32 hash. This also calls $(LREF start) to * reset the internal state. - * - * Examples: - * -------- - * //Simple example - * CRC32 hash; - * hash.put(cast(ubyte)0); - * ubyte[4] result = hash.finish(); - * -------- */ @trusted pure nothrow ubyte[4] finish() { @@ -275,6 +204,14 @@ struct CRC32 start(); return tmp; } + /// + unittest + { + //Simple example + CRC32 hash; + hash.put(cast(ubyte)0); + ubyte[4] result = hash.finish(); + } /** * Works like $(D finish) but does not reset the internal state, so it's possible @@ -287,7 +224,7 @@ struct CRC32 } } -//verify example +/// unittest { //Simple example, hashing a string using crc32Of helper function @@ -296,7 +233,7 @@ unittest assert(crcHexString(hash) == "352441C2"); } -//verify example +/// unittest { //Using the basic API @@ -307,11 +244,11 @@ unittest ubyte[4] result = hash.finish(); } -//verify example +/// unittest { //Let's use the template features: - //Note: When passing a CRC32 to a function, it must be passed by referece! + //Note: When passing a CRC32 to a function, it must be passed by reference! void doSomething(T)(ref T hash) if(isDigest!T) { hash.put(cast(ubyte)0); @@ -369,12 +306,6 @@ unittest /** * This is a convenience alias for $(XREF digest.digest, digest) using the * CRC32 implementation. - * - * Examples: - * --------- - * ubyte[4] hash = crc32Of("abc"); - * assert(hash == digest!CRC32("abc")); //This is the same as above - * --------- */ //simple alias doesn't work here, hope this gets inlined... auto crc32Of(T...)(T data) @@ -390,7 +321,7 @@ public alias toHexString!(Order.decreasing) crcHexString; ///ditto public alias toHexString!(Order.decreasing, 16) crcHexString; -//verify example +/// unittest { ubyte[4] hash = crc32Of("abc"); @@ -403,34 +334,10 @@ unittest * * This is an alias for $(XREF digest.digest, WrapperDigest)!CRC32, see * $(XREF digest.digest, WrapperDigest) for more information. - * - * Examples: - * -------- - * //Simple example, hashing a string using Digest.digest helper function - * auto crc = new CRC32Digest(); - * ubyte[] hash = crc.digest("abc"); - * //Let's get a hash string - * assert(crcHexString(hash) == "352441C2"); - * -------- - * - * -------- - * //Let's use the OOP features: - * void test(Digest dig) - * { - * dig.put(cast(ubyte)0); - * } - * auto crc = new CRC32Digest(); - * test(crc); - * - * //Let's use a custom buffer: - * ubyte[4] buf; - * ubyte[] result = crc.finish(buf[]); - * assert(crcHexString(result) == "D202EF8D"); - * -------- */ alias WrapperDigest!CRC32 CRC32Digest; -//verify example +/// unittest { //Simple example, hashing a string using Digest.digest helper function @@ -440,7 +347,7 @@ unittest assert(crcHexString(hash) == "352441C2"); } -//verify example +/// unittest { //Let's use the OOP features: @@ -457,7 +364,7 @@ unittest assert(crcHexString(result) == "D202EF8D"); } -//verify example +/// unittest { //Simple example @@ -466,7 +373,7 @@ unittest ubyte[] result = hash.finish(); } -//verify example +/// unittest { //using a supplied buffer diff --git a/std/digest/digest.d b/std/digest/digest.d index 0a845f6e6..247bcf42f 100644 --- a/std/digest/digest.d +++ b/std/digest/digest.d @@ -53,117 +53,6 @@ $(TR $(TDNW Implementation helpers) $(TD $(MYREF digestLength) $(MYREF WrapperDi * CTFE: * Digests do not work in CTFE * - * Examples: - * --------- - * import std.digest.crc; - * - * //Simple example - * char[8] hexHash = hexDigest!CRC32("The quick brown fox jumps over the lazy dog"); - * assert(hexHash == "39A34F41"); - * - * //Simple example, using the API manually - * CRC32 context = makeDigest!CRC32(); - * context.put(cast(ubyte[])"The quick brown fox jumps over the lazy dog"); - * ubyte[4] hash = context.finish(); - * assert(toHexString(hash) == "39A34F41"); - * --------- - * - * --------- - * //Generating the hashes of a file, idiomatic D way - * import std.digest.crc, std.digest.sha, std.digest.md; - * import std.stdio; - * - * // Digests a file and prints the result. - * void digestFile(Hash)(string filename) if(isDigest!Hash) - * { - * auto file = File(filename); - * auto result = digest!Hash(file.byChunk(4096 * 1024)); - * writefln("%s (%s) = %s", Hash.stringof, filename, toHexString(result)); - * } - * - * void main(string[] args) - * { - * foreach (name; args[1 .. $]) - * { - * digestFile!MD5(name); - * digestFile!SHA1(name); - * digestFile!CRC32(name); - * } - * } - * --------- - * - * --------- - * //Generating the hashes of a file using the template API, old school way - * import std.digest.crc, std.digest.sha, std.digest.md; - * import std.stdio; - * - * void main(string[] args) - * { - * MD5 md5; - * SHA1 sha1; - * CRC32 crc32; - * - * md5.start(); - * sha1.start(); - * crc32.start(); - * - * foreach (arg; args[1 .. $]) - * { - * digestFile(md5, arg); - * digestFile(sha1, arg); - * digestFile(crc32, arg); - * } - * } - * - * // Digests a file and prints the result. - * void digestFile(Hash)(ref Hash hash, string filename) if(isDigest!Hash) - * { - * File file = File(filename); - * - * //As digests implement OutputRange, we could use std.algorithm.copy - * //Let's do it manually for now - * foreach (buffer; file.byChunk(4096 * 1024)) - * hash.put(buffer); - * - * auto result = hash.finish(); - * writefln("%s (%s) = %s", hash.stringof, filename, toHexString(result)); - * } - * --------- - * - * --------- - * //The same using the OOP API - * import std.digest.crc, std.digest.sha, std.digest.md; - * import std.stdio; - * - * void main(string[] args) - * { - * auto md5 = new MD5Digest(); - * auto sha1 = new SHA1Digest(); - * auto crc32 = new CRC32Digest(); - * - * foreach (arg; args[1 .. $]) - * { - * digestFile(md5, arg); - * digestFile(sha1, arg); - * digestFile(crc32, arg); - * } - * } - * - * // Digests a file and prints the result. - * void digestFile(Digest hash, string filename) - * { - * File file = File(filename); - * - * //As digests implement OutputRange, we could use std.algorithm.copy - * //Let's do it manually for now - * foreach (buffer; file.byChunk(4096 * 1024)) - * hash.put(buffer); - * - * ubyte[] result = hash.finish(); - * writefln("%s (%s) = %s", typeid(hash).toString(), filename, toHexString(result)); - * } - * --------- - * * TODO: * Digesting single bits (as opposed to bytes) is not implemented. This will be done as another * template constraint helper (hasBitDigesting!T) and an additional interface (BitDigest) @@ -178,8 +67,9 @@ module std.digest.digest; import std.exception, std.range, std.traits; import std.algorithm : copy; import std.typetuple : allSatisfy; +import std.ascii : LetterCase; -//verify example +/// unittest { import std.digest.crc; @@ -195,7 +85,7 @@ unittest assert(toHexString(hash) == "39A34F41"); } -//verify example +/// unittest { //Generating the hashes of a file, idiomatic D way @@ -220,7 +110,7 @@ unittest } } } -//verify example +/// unittest { //Generating the hashes of a file using the template API @@ -259,7 +149,7 @@ unittest } } -//verify example +/// unittest { import std.digest.crc, std.digest.sha, std.digest.md; @@ -309,19 +199,6 @@ version(ExampleDigest) * $(LI A digest must be a struct (value type) to pass the $(LREF isDigest) test.) * $(LI A digest passing the $(LREF isDigest) test is always an $(D OutputRange)) * ) - * - * Examples: - * ---- - * //Using the OutputRange feature - * import std.algorithm : copy; - * import std.range : repeat; - * import std.digest.md; - * - * auto oneMillionRange = repeat!ubyte(cast(ubyte)'a', 1000000); - * auto ctx = makeDigest!MD5(); - * copy(oneMillionRange, &ctx); //Note: You must pass a pointer to copy! - * assert(ctx.finish().toHexString() == "7707D6AE4E027C70EEA2A935C2296F21"); - * ---- */ struct ExampleDigest { @@ -375,7 +252,7 @@ version(ExampleDigest) } } -//verify example +/// unittest { //Using the OutputRange feature @@ -396,21 +273,6 @@ unittest * Note: * This is very useful as a template constraint (see examples) * - * Examples: - * --------- - * import std.digest.crc; - * static assert(isDigest!CRC32); - * --------- - * - * --------- - * void myFunction(T)() if(isDigest!T) - * { - * T dig; - * dig.start(); - * auto result = dig.finish(); - * } - * --------- - * * BUGS: * $(UL * $(LI Does not yet verify that put takes scope parameters.) @@ -430,13 +292,13 @@ template isDigest(T) })); } -//verify example +/// unittest { import std.digest.crc; static assert(isDigest!CRC32); } -//verify example +/// unittest { import std.digest.crc; @@ -451,19 +313,6 @@ unittest /** * Use this template to get the type which is returned by a digest's $(LREF finish) method. - * - * Examples: - * -------- - * import std.digest.crc; - * assert(is(DigestType!(CRC32) == ubyte[4])); - * -------- - * - * -------- - * import std.digest.crc; - * CRC32 dig; - * dig.start(); - * DigestType!CRC32 result = dig.finish(); - * -------- */ template DigestType(T) { @@ -479,13 +328,13 @@ template DigestType(T) static assert(false, T.stringof ~ " is not a digest! (fails isDigest!T)"); } -//verify example +/// unittest { import std.digest.crc; assert(is(DigestType!(CRC32) == ubyte[4])); } -//verify example +/// unittest { import std.digest.crc; @@ -504,22 +353,6 @@ unittest * $(LI This is very useful as a template constraint (see examples)) * $(LI This also checks if T passes $(LREF isDigest)) * ) - * - * Examples: - * --------- - * import std.digest.crc, std.digest.md; - * assert(!hasPeek!(MD5)); - * assert(hasPeek!CRC32); - * --------- - * - * --------- - * void myFunction(T)() if(hasPeek!T) - * { - * T dig; - * dig.start(); - * auto result = dig.peek(); - * } - * --------- */ template hasPeek(T) { @@ -531,14 +364,14 @@ template hasPeek(T) })); } -//verify example +/// unittest { import std.digest.crc, std.digest.md; assert(!hasPeek!(MD5)); assert(hasPeek!CRC32); } -//verify example +/// unittest { import std.digest.crc; @@ -568,14 +401,6 @@ private template isDigestibleRange(Range) * * Params: * range= an $(D InputRange) with $(D ElementType) $(D ubyte), $(D ubyte[]) or $(D ubyte[num]) - * - * - * Examples: - * --------- - * import std.digest.md; - * auto testRange = repeat!ubyte(cast(ubyte)'a', 100); - * auto md5 = digest!MD5(testRange); - * --------- */ DigestType!Hash digest(Hash, Range)(auto ref Range range) if(!isArray!Range && isDigestibleRange!Range) @@ -586,7 +411,7 @@ DigestType!Hash digest(Hash, Range)(auto ref Range range) if(!isArray!Range return hash.finish(); } -//verify example +/// unittest { import std.digest.md; @@ -599,22 +424,6 @@ unittest * * Params: * data= one or more arrays of any type - * - * Examples: - * --------- - * import std.digest.md, std.digest.sha, std.digest.crc; - * auto md5 = digest!MD5( "The quick brown fox jumps over the lazy dog"); - * auto sha1 = digest!SHA1( "The quick brown fox jumps over the lazy dog"); - * auto crc32 = digest!CRC32("The quick brown fox jumps over the lazy dog"); - * assert(toHexString(crc32) == "39A34F41"); - * --------- - * - * --------- - * //It's also possible to pass multiple values to this function: - * import std.digest.crc; - * auto crc32 = digest!CRC32("The quick ", "brown ", "fox jumps over the lazy dog"); - * assert(toHexString(crc32) == "39A34F41"); - * --------- */ DigestType!Hash digest(Hash, T...)(scope const T data) if(allSatisfy!(isArray, typeof(data))) { @@ -625,7 +434,7 @@ DigestType!Hash digest(Hash, T...)(scope const T data) if(allSatisfy!(isArray, t return hash.finish(); } -//verify example +/// unittest { import std.digest.md, std.digest.sha, std.digest.crc; @@ -635,7 +444,7 @@ unittest assert(toHexString(crc32) == "39A34F41"); } -//verify example +/// unittest { import std.digest.crc; @@ -649,16 +458,8 @@ unittest * function. * * Params: - * Order= the order in which the bytes are processed (see $(LREF toHexString)) + * order= the order in which the bytes are processed (see $(LREF toHexString)) * range= an $(D InputRange) with $(D ElementType) $(D ubyte), $(D ubyte[]) or $(D ubyte[num]) - * - * - * Examples: - * --------- - * import std.digest.md; - * auto testRange = repeat!ubyte(cast(ubyte)'a', 100); - * assert(hexDigest!MD5(testRange) == "36A92CC94A9E0FA21F625F8BFB007ADF"); - * --------- */ char[digestLength!(Hash)*2] hexDigest(Hash, Order order = Order.increasing, Range)(ref Range range) if(!isArray!Range && isDigestibleRange!Range) @@ -666,7 +467,7 @@ char[digestLength!(Hash)*2] hexDigest(Hash, Order order = Order.increasing, Rang return toHexString!order(digest!Hash(range)); } -//verify example +/// unittest { import std.digest.md; @@ -678,20 +479,8 @@ unittest * This overload of the hexDigest function handles arrays. * * Params: - * Order= the order in which the bytes are processed (see $(LREF toHexString)) + * order= the order in which the bytes are processed (see $(LREF toHexString)) * data= one or more arrays of any type - * - * Examples: - * --------- - * import std.digest.crc; - * assert(hexDigest!(CRC32, Order.decreasing)("The quick brown fox jumps over the lazy dog") == "414FA339"); - * --------- - * - * --------- - * //It's also possible to pass multiple values to this function: - * import std.digest.crc; - * assert(hexDigest!(CRC32, Order.decreasing)("The quick ", "brown ", "fox jumps over the lazy dog") == "414FA339"); - * --------- */ char[digestLength!(Hash)*2] hexDigest(Hash, Order order = Order.increasing, T...)(scope const T data) if(allSatisfy!(isArray, typeof(data))) @@ -699,13 +488,13 @@ char[digestLength!(Hash)*2] hexDigest(Hash, Order order = Order.increasing, T... return toHexString!order(digest!Hash(data)); } -//verify example +/// unittest { import std.digest.crc; assert(hexDigest!(CRC32, Order.decreasing)("The quick brown fox jumps over the lazy dog") == "414FA339"); } -//verify example +/// unittest { import std.digest.crc; @@ -715,14 +504,6 @@ unittest /** * This is a convenience function which returns an initialized digest, so it's not necessary to call * start manually. - * - * Examples: - * --------- - * import std.digest.md; - * auto md5 = makeDigest!MD5(); - * md5.put("Hello"); - * assert(toHexString(md5.finish()) == "93B885ADFE0DA089CDF634904FD59F71"); - * --------- */ Hash makeDigest(Hash)() { @@ -731,7 +512,7 @@ Hash makeDigest(Hash)() return hash; } -//verify example +/// unittest { import std.digest.md; @@ -750,19 +531,6 @@ unittest * * Note: * A Digest implementation is always an $(D OutputRange) - * - * Examples: - * ---- - * //Using the OutputRange feature - * import std.algorithm : copy; - * import std.range : repeat; - * import std.digest.md; - * - * auto oneMillionRange = repeat!ubyte(cast(ubyte)'a', 1000000); - * auto ctx = new MD5Digest(); - * copy(oneMillionRange, ctx); - * assert(ctx.finish().toHexString() == "7707D6AE4E027C70EEA2A935C2296F21"); - * ---- */ interface Digest { @@ -814,22 +582,6 @@ interface Digest /** * This is a convenience function to calculate the hash of a value using the OOP API. - * - * Examples: - * --------- - * import std.digest.md, std.digest.sha, std.digest.crc; - * ubyte[] md5 = (new MD5Digest()).digest("The quick brown fox jumps over the lazy dog"); - * ubyte[] sha1 = (new SHA1Digest()).digest("The quick brown fox jumps over the lazy dog"); - * ubyte[] crc32 = (new CRC32Digest()).digest("The quick brown fox jumps over the lazy dog"); - * assert(crcHexString(crc32) == "414FA339"); - * --------- - * - * --------- - * //It's also possible to pass multiple values to this function: - * import std.digest.crc; - * ubyte[] crc32 = (new CRC32Digest()).digest("The quick ", "brown ", "fox jumps over the lazy dog"); - * assert(crcHexString(crc32) == "414FA339"); - * --------- */ final @trusted nothrow ubyte[] digest(scope const(void[])[] data...) { @@ -840,7 +592,7 @@ interface Digest } } -//verify example +/// unittest { //Using the OutputRange feature @@ -854,7 +606,7 @@ unittest assert(ctx.finish().toHexString() == "7707D6AE4E027C70EEA2A935C2296F21"); } -//verify example +/// unittest { import std.digest.md, std.digest.sha, std.digest.crc; @@ -864,7 +616,7 @@ unittest assert(crcHexString(crc32) == "414FA339"); } -//verify example +/// unittest { import std.digest.crc; @@ -878,7 +630,7 @@ unittest assert(isOutputRange!(Digest, ubyte)); } -//verify example +/// unittest { void test(Digest dig) @@ -901,6 +653,7 @@ enum Order : bool decreasing /// } + /** * Used to convert a hash value (a static or dynamic array of ubytes) to a string. * Can be used with the OOP and with the template API. @@ -908,34 +661,24 @@ enum Order : bool * The additional order parameter can be used to specify the order of the input data. * By default the data is processed in increasing order, starting at index 0. To process it in the * opposite order, pass Order.decreasing as a parameter. - * - * Examples: - * -------- - * //With template API: - * auto crc32 = digest!CRC32("The quick ", "brown ", "fox jumps over the lazy dog"); - * assert(toHexString(crc32) == "39A34F41"); - * -------- - * - * -------- - * //Usually CRCs are printed in this order, though: - * auto crc32 = digest!CRC32("The quick ", "brown ", "fox jumps over the lazy dog"); - * assert(toHexString!(Order.decreasing)(crc32) == "414FA339"); - * -------- - * - * -------- - * //With OOP API: - * auto crc32 = (new CRC32Digest()).digest("The quick ", "brown ", "fox jumps over the lazy dog"); - * assert(toHexString(crc32) == "39A34F41"); - * -------- - * - * -------- - * //Usually CRCs are printed in this order, though: - * auto crc32 = (new CRC32Digest()).digest("The quick ", "brown ", "fox jumps over the lazy dog"); - * assert(toHexString!(Order.decreasing)(crc32) == "414FA339"); - * -------- + * + * The additional letterCase parameter can be used to specify the case of the output data. + * By default the output is in upper case. To change it to the lower case + * pass LetterCase.lower as a parameter. */ -char[num*2] toHexString(Order order = Order.increasing, size_t num)(in ubyte[num] digest) +char[num*2] toHexString(Order order = Order.increasing, size_t num, LetterCase letterCase = LetterCase.upper) +(in ubyte[num] digest) { + static if (letterCase == LetterCase.upper) + { + import std.ascii : hexDigits = hexDigits; + } + else + { + import std.ascii : hexDigits = lowerHexDigits; + } + + char[num*2] result; size_t i; @@ -943,8 +686,8 @@ char[num*2] toHexString(Order order = Order.increasing, size_t num)(in ubyte[num { foreach(u; digest) { - result[i++] = std.ascii.hexDigits[u >> 4]; - result[i++] = std.ascii.hexDigits[u & 15]; + result[i++] = hexDigits[u >> 4]; + result[i++] = hexDigits[u & 15]; } } else @@ -952,8 +695,8 @@ char[num*2] toHexString(Order order = Order.increasing, size_t num)(in ubyte[num size_t j = num - 1; while(i < num*2) { - result[i++] = std.ascii.hexDigits[digest[j] >> 4]; - result[i++] = std.ascii.hexDigits[digest[j] & 15]; + result[i++] = hexDigits[digest[j] >> 4]; + result[i++] = hexDigits[digest[j] & 15]; j--; } } @@ -961,8 +704,24 @@ char[num*2] toHexString(Order order = Order.increasing, size_t num)(in ubyte[num } ///ditto -string toHexString(Order order = Order.increasing)(in ubyte[] digest) +auto toHexString(LetterCase letterCase, Order order = Order.increasing, size_t num)(in ubyte[num] digest) { + return toHexString!(order, num, letterCase)(digest); +} + +///ditto +string toHexString(Order order = Order.increasing, LetterCase letterCase = LetterCase.upper) +(in ubyte[] digest) +{ + static if (letterCase == LetterCase.upper) + { + import std.ascii : hexDigits = hexDigits; + } + else + { + import std.ascii : hexDigits = lowerHexDigits; + } + auto result = new char[digest.length*2]; size_t i; @@ -970,38 +729,49 @@ string toHexString(Order order = Order.increasing)(in ubyte[] digest) { foreach(u; digest) { - result[i++] = std.ascii.hexDigits[u >> 4]; - result[i++] = std.ascii.hexDigits[u & 15]; + result[i++] = hexDigits[u >> 4]; + result[i++] = hexDigits[u & 15]; } } else { foreach(u; retro(digest)) { - result[i++] = std.ascii.hexDigits[u >> 4]; - result[i++] = std.ascii.hexDigits[u & 15]; + result[i++] = hexDigits[u >> 4]; + result[i++] = hexDigits[u & 15]; } } return assumeUnique(result); } -//For more example unittests, see Digest.digest, digest - -//verify example -unittest +///ditto +auto toHexString(LetterCase letterCase, Order order = Order.increasing)(in ubyte[] digest) { - import std.digest.crc; - //Usually CRCs are printed in this order, though: - auto crc32 = digest!CRC32("The quick ", "brown ", "fox jumps over the lazy dog"); - assert(toHexString!(Order.decreasing)(crc32) == "414FA339"); + return toHexString!(order, letterCase)(digest); } -//verify example +//For more example unittests, see Digest.digest, digest + +/// unittest { import std.digest.crc; + //Test with template API: + auto crc32 = digest!CRC32("The quick ", "brown ", "fox jumps over the lazy dog"); + //Lower case variant: + assert(toHexString!(LetterCase.lower)(crc32) == "39a34f41"); //Usually CRCs are printed in this order, though: + assert(toHexString!(Order.decreasing)(crc32) == "414FA339"); + assert(toHexString!(LetterCase.lower, Order.decreasing)(crc32) == "414fa339"); +} + +/// +unittest +{ + import std.digest.crc; + // With OOP API auto crc32 = (new CRC32Digest()).digest("The quick ", "brown ", "fox jumps over the lazy dog"); + //Usually CRCs are printed in this order, though: assert(toHexString!(Order.decreasing)(crc32) == "414FA339"); } @@ -1013,6 +783,7 @@ unittest assert(toHexString(cast(ubyte[4])[42, 43, 44, 45]) == "2A2B2C2D"); assert(toHexString(cast(ubyte[])[42, 43, 44, 45]) == "2A2B2C2D"); assert(toHexString!(Order.decreasing)(cast(ubyte[4])[42, 43, 44, 45]) == "2D2C2B2A"); + assert(toHexString!(Order.decreasing, LetterCase.lower)(cast(ubyte[4])[42, 43, 44, 45]) == "2d2c2b2a"); assert(toHexString!(Order.decreasing)(cast(ubyte[])[42, 43, 44, 45]) == "2D2C2B2A"); } @@ -1062,17 +833,6 @@ class WrapperDigest(T) if(isDigest!T) : Digest * Use this to feed the digest with data. * Also implements the $(XREF range, OutputRange) interface for $(D ubyte) and * $(D const(ubyte)[]). - * - * Examples: - * ---- - * void test(Digest dig) - * { - * dig.put(cast(ubyte)0); //single ubyte - * dig.put(cast(ubyte)0, cast(ubyte)0); //variadic - * ubyte[10] buf; - * dig.put(buf); //buffer - * } - * ---- */ @trusted nothrow void put(scope const(ubyte)[] data...) { @@ -1105,15 +865,7 @@ class WrapperDigest(T) if(isDigest!T) : Digest * * Examples: * -------- - * //Simple example - * import std.digest.md; - * auto hash = new WrapperDigest!MD5(); - * hash.put(cast(ubyte)0); - * auto result = hash.finish(); - * -------- - * - * -------- - * //using a supplied buffer + * * import std.digest.md; * ubyte[16] buf; * auto hash = new WrapperDigest!MD5(); @@ -1183,7 +935,7 @@ class WrapperDigest(T) if(isDigest!T) : Digest } } -//verify example +/// unittest { import std.digest.md; @@ -1193,9 +945,10 @@ unittest auto result = hash.finish(); } -//verify example +/// unittest { + //using a supplied buffer import std.digest.md; ubyte[16] buf; auto hash = new WrapperDigest!MD5(); diff --git a/std/digest/md.d b/std/digest/md.d index d85de7eee..9f4dcbdd8 100644 --- a/std/digest/md.d +++ b/std/digest/md.d @@ -39,40 +39,6 @@ $(TR $(TDNW Helpers) $(TD $(MYREF md5Of)) * Macros: * WIKI = Phobos/StdMd5 * MYREF = $1  - * - * Examples: - * --------- - * //Template API - * import std.digest.md; - * - * ubyte[16] hash = md5Of("abc"); - * assert(toHexString(hash) == "900150983CD24FB0D6963F7D28E17F72"); - * - * //Feeding data - * ubyte[1024] data; - * MD5 md5; - * md5.start(); - * md5.put(data[]); - * md5.start(); //Start again - * md5.put(data[]); - * hash = md5.finish(); - * --------- - * - * --------- - * //OOP API - * import std.digest.md; - * - * auto md5 = new MD5Digest(); - * ubyte[] hash = md5.digest("abc"); - * assert(toHexString(hash) == "900150983CD24FB0D6963F7D28E17F72"); - * - * //Feeding data - * ubyte[1024] data; - * md5.put(data[]); - * md5.reset(); //Start again - * md5.put(data[]); - * hash = md5.finish(); - * --------- */ /* md5.d - RSA Data Security, Inc., MD5 message-digest algorithm @@ -84,15 +50,12 @@ import std.bitmanip, std.exception, std.string; public import std.digest.digest; -//verify example +/// unittest { //Template API import std.digest.md; - ubyte[16] hash = md5Of("abc"); - assert(toHexString(hash) == "900150983CD24FB0D6963F7D28E17F72"); - //Feeding data ubyte[1024] data; MD5 md5; @@ -100,10 +63,10 @@ unittest md5.put(data[]); md5.start(); //Start again md5.put(data[]); - hash = md5.finish(); + auto hash = md5.finish(); } -//verify example +/// unittest { //OOP API @@ -132,47 +95,16 @@ private nothrow pure uint rotateLeft(uint x, uint n) /** * Template API MD5 implementation. * See $(D std.digest.digest) for differences between template and OOP API. - * - * Examples: - * -------- - * //Simple example, hashing a string using md5Of helper function - * ubyte[16] hash = md5Of("abc"); - * //Let's get a hash string - * assert(toHexString(hash) == "900150983CD24FB0D6963F7D28E17F72"); - * -------- - * - * -------- - * //Using the basic API - * MD5 hash; - * hash.start(); - * ubyte[1024] data; - * //Initialize data here... - * hash.put(data); - * ubyte[16] result = hash.finish(); - * -------- - * - * -------- - * //Let's use the template features: - * //Note: When passing a MD5 to a function, it must be passed by referece! - * void doSomething(T)(ref T hash) if(isDigest!T) - * { - * hash.put(cast(ubyte)0); - * } - * MD5 md5; - * md5.start(); - * doSomething(md5); - * assert(toHexString(md5.finish()) == "93B885ADFE0DA089CDF634904FD59F71"); - * -------- */ struct MD5 { private: // magic initialization constants - uint _state[4] = [0x67452301,0xefcdab89,0x98badcfe,0x10325476]; // state (ABCD) + uint[4] _state = [0x67452301,0xefcdab89,0x98badcfe,0x10325476]; // state (ABCD) ulong _count; //number of bits, modulo 2^64 ubyte[64] _buffer; // input buffer - enum ubyte[64] _padding = + static immutable ubyte[64] _padding = [ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -423,16 +355,7 @@ struct MD5 /** * Returns the finished MD5 hash. This also calls $(LREF start) to * reset the internal state. - * - * Examples: - * -------- - * //Simple example - * MD5 hash; - * hash.start(); - * hash.put(cast(ubyte)0); - * ubyte[16] result = hash.finish(); - * -------- - */ + */ @trusted nothrow pure ubyte[16] finish() { ubyte[16] data = void; @@ -460,9 +383,18 @@ struct MD5 start(); return data; } + /// + unittest + { + //Simple example + MD5 hash; + hash.start(); + hash.put(cast(ubyte)0); + ubyte[16] result = hash.finish(); + } } -//verify example +/// unittest { //Simple example, hashing a string using md5Of helper function @@ -471,7 +403,7 @@ unittest assert(toHexString(hash) == "900150983CD24FB0D6963F7D28E17F72"); } -//verify example +/// unittest { //Using the basic API @@ -483,7 +415,7 @@ unittest ubyte[16] result = hash.finish(); } -//verify example +/// unittest { //Let's use the template features: @@ -497,16 +429,6 @@ unittest assert(toHexString(md5.finish()) == "93B885ADFE0DA089CDF634904FD59F71"); } -//verify example -unittest -{ - //Simple example - MD5 hash; - hash.start(); - hash.put(cast(ubyte)0); - ubyte[16] result = hash.finish(); -} - unittest { assert(isDigest!MD5); @@ -565,12 +487,6 @@ unittest /** * This is a convenience alias for $(XREF digest.digest, digest) using the * MD5 implementation. - * - * Examples: - * --------- - * ubyte[16] hash = md5Of("abc"); - * assert(hash == digest!MD5("abc")); //This is the same as above - * --------- */ //simple alias doesn't work here, hope this gets inlined... auto md5Of(T...)(T data) @@ -578,7 +494,7 @@ auto md5Of(T...)(T data) return digest!(MD5, T)(data); } -//verify example +/// unittest { ubyte[16] hash = md5Of("abc"); @@ -591,34 +507,10 @@ unittest * * This is an alias for $(XREF digest.digest, WrapperDigest)!MD5, see * $(XREF digest.digest, WrapperDigest) for more information. - * - * Examples: - * -------- - * //Simple example, hashing a string using Digest.digest helper function - * auto md5 = new MD5Digest(); - * ubyte[] hash = md5.digest("abc"); - * //Let's get a hash string - * assert(toHexString(hash) == "900150983CD24FB0D6963F7D28E17F72"); - * -------- - * - * -------- - * //Let's use the OOP features: - * void test(Digest dig) - * { - * dig.put(cast(ubyte)0); - * } - * auto md5 = new MD5Digest(); - * test(md5); - * - * //Let's use a custom buffer: - * ubyte[16] buf; - * ubyte[] result = md5.finish(buf[]); - * assert(toHexString(result) == "93B885ADFE0DA089CDF634904FD59F71"); - * -------- */ alias WrapperDigest!MD5 MD5Digest; -//verify example +/// unittest { //Simple example, hashing a string using Digest.digest helper function @@ -628,7 +520,7 @@ unittest assert(toHexString(hash) == "900150983CD24FB0D6963F7D28E17F72"); } -//verify example +/// unittest { //Let's use the OOP features: diff --git a/std/digest/ripemd.d b/std/digest/ripemd.d index 9699bd5b4..67d471efe 100644 --- a/std/digest/ripemd.d +++ b/std/digest/ripemd.d @@ -43,40 +43,6 @@ $(TR $(TDNW Helpers) $(TD $(MYREF ripemd160Of)) * Macros: * WIKI = Phobos/StdRipemd * MYREF = $1  - * - * Examples: - * --------- - * //Template API - * import std.digest.ripemd; - * - * ubyte[20] hash = ripemd160Of("abc"); - * assert(toHexString(hash) == "8EB208F7E05D987A9B044A8E98C6B087F15A0BFC"); - * - * //Feeding data - * ubyte[1024] data; - * RIPEMD160 md; - * md.start(); - * md.put(data[]); - * md.start(); //Start again - * md.put(data[]); - * hash = md.finish(); - * --------- - * - * --------- - * //OOP API - * import std.digest.ripemd; - * - * auto md = new RIPEMD160Digest(); - * ubyte[] hash = md.digest("abc"); - * assert(toHexString(hash) == "8EB208F7E05D987A9B044A8E98C6B087F15A0BFC"); - * - * //Feeding data - * ubyte[1024] data; - * md.put(data[]); - * md.reset(); //Start again - * md.put(data[]); - * hash = md.finish(); - * --------- */ module std.digest.ripemd; @@ -85,7 +51,7 @@ import std.bitmanip, std.exception, std.string; public import std.digest.digest; -//verify example +/// unittest { //Template API @@ -104,7 +70,7 @@ unittest hash = md.finish(); } -//verify example +/// unittest { //OOP API @@ -133,43 +99,12 @@ private nothrow pure uint rotateLeft(uint x, uint n) /** * Template API RIPEMD160 implementation. * See $(D std.digest.digest) for differences between template and OOP API. - * - * Examples: - * -------- - * //Simple example, hashing a string using ripemd160Of helper function - * ubyte[20] hash = ripemd160Of("abc"); - * //Let's get a hash string - * assert(toHexString(hash) == "8EB208F7E05D987A9B044A8E98C6B087F15A0BFC"); - * -------- - * - * -------- - * //Using the basic API - * RIPEMD160 hash; - * hash.start(); - * ubyte[1024] data; - * //Initialize data here... - * hash.put(data); - * ubyte[20] result = hash.finish(); - * -------- - * - * -------- - * //Let's use the template features: - * //Note: When passing a RIPEMD160 to a function, it must be passed by referece! - * void doSomething(T)(ref T hash) if(isDigest!T) - * { - * hash.put(cast(ubyte)0); - * } - * RIPEMD160 md; - * md.start(); - * doSomething(md); - * assert(toHexString(md.finish()) == "C81B94933420221A7AC004A90242D8B1D3E5070D"); - * -------- */ struct RIPEMD160 { private: // magic initialization constants - uint _state[5] = [0x67452301,0xefcdab89,0x98badcfe,0x10325476,0xc3d2e1f0]; // state (ABCDE) + uint[5] _state = [0x67452301,0xefcdab89,0x98badcfe,0x10325476,0xc3d2e1f0]; // state (ABCDE) ulong _count; //number of bits, modulo 2^64 ubyte[64] _buffer; // input buffer @@ -610,7 +545,7 @@ struct RIPEMD160 } } -//verify example +/// unittest { //Simple example, hashing a string using ripemd160Of helper function @@ -619,7 +554,7 @@ unittest assert(toHexString(hash) == "8EB208F7E05D987A9B044A8E98C6B087F15A0BFC"); } -//verify example +/// unittest { //Using the basic API @@ -631,7 +566,7 @@ unittest ubyte[20] result = hash.finish(); } -//verify example +/// unittest { //Let's use the template features: @@ -645,7 +580,7 @@ unittest assert(toHexString(md.finish()) == "C81B94933420221A7AC004A90242D8B1D3E5070D"); } -//verify example +/// unittest { //Simple example @@ -714,12 +649,6 @@ unittest /** * This is a convenience alias for $(XREF digest.digest, digest) using the * RIPEMD160 implementation. - * - * Examples: - * --------- - * ubyte[20] hash = ripemd160Of("abc"); - * assert(hash == digest!RIPEMD160("abc")); //This is the same as above - * --------- */ //simple alias doesn't work here, hope this gets inlined... auto ripemd160Of(T...)(T data) @@ -727,7 +656,7 @@ auto ripemd160Of(T...)(T data) return digest!(RIPEMD160, T)(data); } -//verify example +/// unittest { ubyte[20] hash = ripemd160Of("abc"); @@ -740,34 +669,10 @@ unittest * * This is an alias for $(XREF digest.digest, WrapperDigest)!RIPEMD160, see * $(XREF digest.digest, WrapperDigest) for more information. - * - * Examples: - * -------- - * //Simple example, hashing a string using Digest.digest helper function - * auto md = new RIPEMD160Digest(); - * ubyte[] hash = md.digest("abc"); - * //Let's get a hash string - * assert(toHexString(hash) == "8EB208F7E05D987A9B044A8E98C6B087F15A0BFC"); - * -------- - * - * -------- - * //Let's use the OOP features: - * void test(Digest dig) - * { - * dig.put(cast(ubyte)0); - * } - * auto md = new RIPEMD160Digest(); - * test(md); - * - * //Let's use a custom buffer: - * ubyte[20] buf; - * ubyte[] result = md.finish(buf[]); - * assert(toHexString(result) == "C81B94933420221A7AC004A90242D8B1D3E5070D"); - * -------- */ alias WrapperDigest!RIPEMD160 RIPEMD160Digest; -//verify example +/// unittest { //Simple example, hashing a string using Digest.digest helper function @@ -777,10 +682,10 @@ unittest assert(toHexString(hash) == "8EB208F7E05D987A9B044A8E98C6B087F15A0BFC"); } -//verify example +/// unittest { - //Let's use the OOP features: + //Let's use the OOP features: void test(Digest dig) { dig.put(cast(ubyte)0); diff --git a/std/digest/sha.d b/std/digest/sha.d index f49ac3c74..f7c418051 100644 --- a/std/digest/sha.d +++ b/std/digest/sha.d @@ -45,40 +45,6 @@ $(TR $(TDNW Helpers) $(TD $(MYREF sha1Of)) * Macros: * WIKI = Phobos/StdSha1 * MYREF = $1  - * - * Examples: - * --------- - * //Template API - * import std.digest.sha; - * - * ubyte[20] hash = sha1Of("abc"); - * assert(toHexString(hash) == "A9993E364706816ABA3E25717850C26C9CD0D89D"); - * - * //Feeding data - * ubyte[1024] data; - * SHA1 sha; - * sha.start(); - * sha.put(data[]); - * sha.start(); //Start again - * sha.put(data[]); - * hash = sha.finish(); - * --------- - * - * --------- - * //OOP API - * import std.digest.sha; - * - * auto sha = new SHA1Digest(); - * ubyte[] hash = sha.digest("abc"); - * assert(toHexString(hash) == "A9993E364706816ABA3E25717850C26C9CD0D89D"); - * - * //Feeding data - * ubyte[1024] data; - * sha.put(data[]); - * sha.reset(); //Start again - * sha.put(data[]); - * hash = sha.finish(); - * --------- */ /* Copyright Kai Nacke 2012. @@ -88,7 +54,7 @@ $(TR $(TDNW Helpers) $(TD $(MYREF sha1Of)) */ module std.digest.sha; -//verify example +/// unittest { //Template API @@ -107,7 +73,7 @@ unittest hash = sha.finish(); } -//verify example +/// unittest { //OOP API @@ -194,37 +160,6 @@ private nothrow pure uint rotateLeft(uint x, uint n) /** * Template API SHA1 implementation. * See $(D std.digest.digest) for differences between template and OOP API. - * - * Examples: - * -------- - * //Simple example, hashing a string using sha1Of helper function - * ubyte[20] hash = sha1Of("abc"); - * //Let's get a hash string - * assert(toHexString(hash) == "A9993E364706816ABA3E25717850C26C9CD0D89D"); - * -------- - * - * -------- - * //Using the basic API - * SHA1 hash; - * hash.start(); - * ubyte[1024] data; - * //Initialize data here... - * hash.put(data); - * ubyte[20] result = hash.finish(); - * -------- - * - * -------- - * //Let's use the template features: - * //Note: When passing a SHA1 to a function, it must be passed by referece! - * void doSomething(T)(ref T hash) if(isDigest!T) - * { - * hash.put(cast(ubyte)0); - * } - * SHA1 sha; - * sha.start(); - * doSomething(sha); - * assert(toHexString(sha.finish()) == "5BA93C9DB0CFF93F52B521D7420E43F6EDA2784F"); - * -------- */ struct SHA1 { @@ -234,7 +169,7 @@ struct SHA1 shared static this() { - transform = hasSSSE3Support() ? &transformSSSE3 : &transformX86; + transform = hasSSSE3Support ? &transformSSSE3 : &transformX86; } } else @@ -243,7 +178,7 @@ struct SHA1 } private: - uint state[5] = /* state (ABCDE) */ + uint[5] state = /* state (ABCDE) */ /* magic initialization constants */ [0x67452301,0xefcdab89,0x98badcfe,0x10325476,0xc3d2e1f0]; @@ -437,15 +372,6 @@ struct SHA1 * Use this to feed the digest with data. * Also implements the $(XREF range, OutputRange) interface for $(D ubyte) and * $(D const(ubyte)[]). - * - * Examples: - * ---- - * SHA1 dig; - * dig.put(cast(ubyte)0); //single ubyte - * dig.put(cast(ubyte)0, cast(ubyte)0); //variadic - * ubyte[10] buf; - * dig.put(buf); //buffer - * ---- */ @trusted nothrow pure void put(scope const(ubyte)[] input...) { @@ -478,19 +404,20 @@ struct SHA1 if (inputLen - i) (&buffer[index])[0 .. inputLen-i] = (&input[i])[0 .. inputLen-i]; } + /// + unittest + { + SHA1 dig; + dig.put(cast(ubyte)0); //single ubyte + dig.put(cast(ubyte)0, cast(ubyte)0); //variadic + ubyte[10] buf; + dig.put(buf); //buffer + } + /** * Returns the finished SHA1 hash. This also calls $(LREF start) to * reset the internal state. - * - * Examples: - * -------- - * //Simple example - * SHA1 hash; - * hash.start(); - * hash.put(cast(ubyte)0); - * ubyte[20] result = hash.finish(); - * -------- */ @trusted nothrow pure ubyte[20] finish() { @@ -516,9 +443,18 @@ struct SHA1 start(); return data; } + /// + unittest + { + //Simple example + SHA1 hash; + hash.start(); + hash.put(cast(ubyte)0); + ubyte[20] result = hash.finish(); + } } -//verify example +/// unittest { //Simple example, hashing a string using sha1Of helper function @@ -527,7 +463,7 @@ unittest assert(toHexString(hash) == "A9993E364706816ABA3E25717850C26C9CD0D89D"); } -//verify example +/// unittest { //Using the basic API @@ -539,7 +475,7 @@ unittest ubyte[20] result = hash.finish(); } -//verify example +/// unittest { //Let's use the template features: @@ -554,26 +490,6 @@ unittest assert(toHexString(sha.finish()) == "5BA93C9DB0CFF93F52B521D7420E43F6EDA2784F"); } -//verify example -unittest -{ - SHA1 dig; - dig.put(cast(ubyte)0); //single ubyte - dig.put(cast(ubyte)0, cast(ubyte)0); //variadic - ubyte[10] buf; - dig.put(buf); //buffer -} - -//verify example -unittest -{ - //Simple example - SHA1 hash; - hash.start(); - hash.put(cast(ubyte)0); - ubyte[20] result = hash.finish(); -} - unittest { assert(isDigest!SHA1); @@ -632,12 +548,6 @@ unittest /** * This is a convenience alias for $(XREF digest.digest, digest) using the * SHA1 implementation. - * - * Examples: - * --------- - * ubyte[20] hash = sha1Of("abc"); - * assert(hash == digest!SHA1("abc")); //This is the same as above - * --------- */ //simple alias doesn't work here, hope this gets inlined... auto sha1Of(T...)(T data) @@ -645,7 +555,7 @@ auto sha1Of(T...)(T data) return digest!(SHA1, T)(data); } -//verify example +/// unittest { ubyte[20] hash = sha1Of("abc"); @@ -669,34 +579,10 @@ unittest * * This is an alias for $(XREF digest.digest, WrapperDigest)!SHA1, see * $(XREF digest.digest, WrapperDigest) for more information. - * - * Examples: - * -------- - * //Simple example, hashing a string using Digest.digest helper function - * auto sha = new SHA1Digest(); - * ubyte[] hash = sha.digest("abc"); - * //Let's get a hash string - * assert(toHexString(hash) == "A9993E364706816ABA3E25717850C26C9CD0D89D"); - * -------- - * - * -------- - * //Let's use the OOP features: - * void test(Digest dig) - * { - * dig.put(cast(ubyte)0); - * } - * auto sha = new SHA1Digest(); - * test(sha); - * - * //Let's use a custom buffer: - * ubyte[20] buf; - * ubyte[] result = sha.finish(buf[]); - * assert(toHexString(result) == "5BA93C9DB0CFF93F52B521D7420E43F6EDA2784F"); - * -------- */ alias WrapperDigest!SHA1 SHA1Digest; -//verify example +/// unittest { //Simple example, hashing a string using Digest.digest helper function @@ -706,7 +592,7 @@ unittest assert(toHexString(hash) == "A9993E364706816ABA3E25717850C26C9CD0D89D"); } -//verify example +/// unittest { //Let's use the OOP features: diff --git a/std/encoding.d b/std/encoding.d index 6fdbd0fd5..fd6b0b0c8 100644 --- a/std/encoding.d +++ b/std/encoding.d @@ -645,7 +645,7 @@ template EncoderInstance(E) //============================================================================= /** Defines various character sets. */ -enum AsciiChar : ubyte { init }; +enum AsciiChar : ubyte { init } /// Ditto alias immutable(AsciiChar)[] AsciiString; @@ -725,7 +725,7 @@ template EncoderInstance(CharType : AsciiChar) //============================================================================= /** Defines an Latin1-encoded character. */ -enum Latin1Char : ubyte { init }; +enum Latin1Char : ubyte { init } /** Defines an Latin1-encoded string (as an array of $(D immutable(Latin1Char))). @@ -801,7 +801,7 @@ template EncoderInstance(CharType : Latin1Char) //============================================================================= /** Defines a Windows1252-encoded character. */ -enum Windows1252Char : ubyte { init }; +enum Windows1252Char : ubyte { init } /** Defines an Windows1252-encoded string (as an array of $(D immutable(Windows1252Char))). @@ -1514,6 +1514,7 @@ unittest Params: s = the string to be counted + n = the current code point index */ ptrdiff_t index(E)(const(E)[] s,int n) in @@ -1688,7 +1689,8 @@ body Standards: Unicode 5.0, ASCII, ISO-8859-1, WINDOWS-1252 Params: - c = the code point to be encoded + c = the code point to be encoded + array = the destination array Returns: the number of code units written to the array @@ -1741,34 +1743,35 @@ Encodes $(D c) in units of type $(D E) and writes the result to the output range $(D R). Returns the number of $(D E)s written. */ -size_t encode(E, R)(dchar c, R range) +size_t encode(E, R)(dchar c, auto ref R range) +if (isNativeOutputRange!(R, E)) { static if (is(Unqual!E == char)) { if (c <= 0x7F) { - range.put(cast(char) c); + doPut(range, cast(char) c); return 1; } if (c <= 0x7FF) { - range.put(cast(char)(0xC0 | (c >> 6))); - range.put(cast(char)(0x80 | (c & 0x3F))); + doPut(range, cast(char)(0xC0 | (c >> 6))); + doPut(range, cast(char)(0x80 | (c & 0x3F))); return 2; } if (c <= 0xFFFF) { - range.put(cast(char)(0xE0 | (c >> 12))); - range.put(cast(char)(0x80 | ((c >> 6) & 0x3F))); - range.put(cast(char)(0x80 | (c & 0x3F))); + doPut(range, cast(char)(0xE0 | (c >> 12))); + doPut(range, cast(char)(0x80 | ((c >> 6) & 0x3F))); + doPut(range, cast(char)(0x80 | (c & 0x3F))); return 3; } if (c <= 0x10FFFF) { - range.put(cast(char)(0xF0 | (c >> 18))); - range.put(cast(char)(0x80 | ((c >> 12) & 0x3F))); - range.put(cast(char)(0x80 | ((c >> 6) & 0x3F))); - range.put(cast(char)(0x80 | (c & 0x3F))); + doPut(range, cast(char)(0xF0 | (c >> 18))); + doPut(range, cast(char)(0x80 | ((c >> 12) & 0x3F))); + doPut(range, cast(char)(0x80 | ((c >> 6) & 0x3F))); + doPut(range, cast(char)(0x80 | (c & 0x3F))); return 4; } else @@ -1780,23 +1783,30 @@ size_t encode(E, R)(dchar c, R range) { if (c <= 0xFFFF) { - r.put(cast(wchar) c); + range.doPut(cast(wchar) c); return 1; } - r.put(cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800)); - r.put(cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00)); + range.doPut(cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800)); + range.doPut(cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00)); return 2; } else static if (is(Unqual!E == dchar)) { - r.put(c); + range.doPut(c); return 1; } else { - assert(0); + static assert(0); } } +unittest +{ + Appender!(char[]) r; + assert(encode!(char)('T', r) == 1); + assert(encode!(wchar)('T', r) == 1); + assert(encode!(dchar)('T', r) == 1); +} /** Encodes a single code point to a delegate. @@ -1817,7 +1827,8 @@ size_t encode(E, R)(dchar c, R range) Standards: Unicode 5.0, ASCII, ISO-8859-1, WINDOWS-1252 Params: - c = the code point to be encoded + c = the code point to be encoded + dg = the delegate to invoke for each code unit */ void encode(E)(dchar c, void delegate(E) dg) in @@ -1898,7 +1909,7 @@ unittest Standards: Unicode 5.0, ASCII, ISO-8859-1, WINDOWS-1252 Params: - d = the code point to be encoded + c = the code point to be encoded Examples: -------------------------------------------------------- @@ -1996,11 +2007,73 @@ body } else { + static if(is(Dst == wchar)) + { + immutable minReservePlace = 2; + } + else static if(is(Dst == dchar)) + { + immutable minReservePlace = 1; + } + else + { + immutable minReservePlace = 6; + } + + Dst[] buffer = new Dst[s.length]; + Dst[] tmpBuffer = buffer; const(Src)[] t = s; + while (t.length != 0) { - r ~= encode!(Dst)(decode(t)); + if(tmpBuffer.length < minReservePlace) + { + size_t prevLength = buffer.length; + buffer.length += t.length + minReservePlace; + tmpBuffer = buffer[prevLength - tmpBuffer.length .. $]; + } + EncoderInstance!(Dst).encode(decode(t), tmpBuffer); } + + r = cast(immutable)buffer[0 .. buffer.length - tmpBuffer.length]; + } +} + +unittest +{ + import std.typetuple; + { + import std.conv : to; + + string asciiCharString = to!string(iota(0, 128, 1)); + + alias Types = TypeTuple!(string, Latin1String, AsciiString, Windows1252String, dstring, wstring); + foreach(S; Types) + foreach(D; Types) + { + string str; + S sStr; + D dStr; + transcode(asciiCharString, sStr); + transcode(sStr, dStr); + transcode(dStr, str); + assert(asciiCharString == str); + } + } + { + string czechChars = "Příliš žluťoučký kůň úpěl ďábelské ódy."; + alias Types = TypeTuple!(string, dstring, wstring); + foreach(S; Types) + foreach(D; Types) + { + string str; + S sStr; + D dStr; + transcode(czechChars, sStr); + transcode(sStr, dStr); + transcode(dStr, str); + assert(czechChars == str); + } } } @@ -2145,7 +2218,8 @@ abstract class EncodingScheme * The input to this function MUST be a valid code point. * * Params: - * c = the code point to be encoded + * c = the code point to be encoded + * buffer = the destination array * * Returns: * the number of ubytes written. @@ -2333,6 +2407,7 @@ abstract class EncodingScheme * * Params: * s = the string to be counted + * n = the current code point index */ ptrdiff_t index(const(ubyte)[] s, size_t n) in diff --git a/std/exception.d b/std/exception.d index 6e96355c9..60c8e20c2 100644 --- a/std/exception.d +++ b/std/exception.d @@ -5,33 +5,33 @@ handling. It also defines functions intended to aid in unit testing. Synopsis of some of std.exception's functions: --------------------- -string synopsis() -{ - FILE* f = enforce(fopen("some/file")); - // f is not null from here on - FILE* g = enforceEx!WriteException(fopen("some/other/file", "w")); - // g is not null from here on + -------------------- + string synopsis() + { + FILE* f = enforce(fopen("some/file")); + // f is not null from here on + FILE* g = enforceEx!WriteException(fopen("some/other/file", "w")); + // g is not null from here on - Exception e = collectException(write(g, readln(f))); - if (e) - { - ... an exception occurred... - ... We have the exception to play around with... - } + Exception e = collectException(write(g, readln(f))); + if (e) + { + ... an exception occurred... + ... We have the exception to play around with... + } - string msg = collectExceptionMsg(write(g, readln(f))); - if (msg) - { - ... an exception occurred... - ... We have the message from the exception but not the exception... - } + string msg = collectExceptionMsg(write(g, readln(f))); + if (msg) + { + ... an exception occurred... + ... We have the message from the exception but not the exception... + } - char[] line; - enforce(readln(f, line)); - return assumeUnique(line); -} --------------------- + char[] line; + enforce(readln(f, line)); + return assumeUnique(line); + } + -------------------- Macros: WIKI = Phobos/StdException @@ -60,22 +60,14 @@ import core.exception, core.stdc.errno; If msg is empty, and the thrown exception has a non-empty msg field, the exception's msg field will be output on test failure. + file = The file where the error occurred. + Defaults to $(D __FILE__). + line = The line where the error occurred. + Defaults to $(D __LINE__). Throws: $(D AssertError) if the given $(D Throwable) is thrown. - - Examples: --------------------- -assertNotThrown!StringException(enforceEx!StringException(true, "Error!")); - -//Exception is the default. -assertNotThrown(enforceEx!StringException(true, "Error!")); - -assert(collectExceptionMsg!AssertError(assertNotThrown!StringException( - enforceEx!StringException(false, "Error!"))) == - `assertNotThrown failed: StringException was thrown: Error!`); --------------------- - +/ + +/ void assertNotThrown(T : Throwable = Exception, E) (lazy E expression, string msg = null, @@ -83,21 +75,19 @@ void assertNotThrown(T : Throwable = Exception, E) size_t line = __LINE__) { try + { expression(); - catch(T t) + } + catch (T t) { immutable message = msg.empty ? t.msg : msg; immutable tail = message.empty ? "." : ": " ~ message; throw new AssertError(format("assertNotThrown failed: %s was thrown%s", - T.stringof, - tail), - file, - line, - t); + T.stringof, tail), + file, line, t); } } - -//Verify Examples +/// unittest { assertNotThrown!StringException(enforceEx!StringException(true, "Error!")); @@ -108,7 +98,9 @@ unittest assert(collectExceptionMsg!AssertError(assertNotThrown!StringException( enforceEx!StringException(false, "Error!"))) == `assertNotThrown failed: StringException was thrown: Error!`); - +} +unittest +{ assert(collectExceptionMsg!AssertError(assertNotThrown!StringException( enforceEx!StringException(false, ""), "Error!")) == `assertNotThrown failed: StringException was thrown: Error!`); @@ -128,24 +120,28 @@ unittest void nothrowEx() { } try + { assertNotThrown!Exception(nothrowEx()); - catch(AssertError) - assert(0); + } + catch (AssertError) assert(0); try + { assertNotThrown!Exception(nothrowEx(), "It's a message"); - catch(AssertError) - assert(0); + } + catch (AssertError) assert(0); try + { assertNotThrown!AssertError(nothrowEx()); - catch(AssertError) - assert(0); + } + catch (AssertError) assert(0); try + { assertNotThrown!AssertError(nothrowEx(), "It's a message"); - catch(AssertError) - assert(0); + } + catch (AssertError) assert(0); { bool thrown = false; @@ -154,9 +150,7 @@ unittest assertNotThrown!Exception( throwEx(new Exception("It's an Exception"))); } - catch(AssertError) - thrown = true; - + catch (AssertError) thrown = true; assert(thrown); } @@ -167,9 +161,7 @@ unittest assertNotThrown!Exception( throwEx(new Exception("It's an Exception")), "It's a message"); } - catch(AssertError) - thrown = true; - + catch (AssertError) thrown = true; assert(thrown); } @@ -178,13 +170,9 @@ unittest try { assertNotThrown!AssertError( - throwEx(new AssertError("It's an AssertError", - __FILE__, - __LINE__))); + throwEx(new AssertError("It's an AssertError", __FILE__, __LINE__))); } - catch(AssertError) - thrown = true; - + catch (AssertError) thrown = true; assert(thrown); } @@ -193,14 +181,10 @@ unittest try { assertNotThrown!AssertError( - throwEx(new AssertError("It's an AssertError", - __FILE__, - __LINE__)), + throwEx(new AssertError("It's an AssertError", __FILE__, __LINE__)), "It's a message"); } - catch(AssertError) - thrown = true; - + catch (AssertError) thrown = true; assert(thrown); } } @@ -215,21 +199,13 @@ unittest T = The $(D Throwable) to test for. expression = The expression to test. msg = Optional message to output on test failure. + file = The file where the error occurred. + Defaults to $(D __FILE__). + line = The line where the error occurred. + Defaults to $(D __LINE__). Throws: $(D AssertError) if the given $(D Throwable) is not thrown. - - Examples: --------------------- -assertThrown!StringException(enforceEx!StringException(false, "Error!")); - -//Exception is the default. -assertThrown(enforceEx!StringException(false, "Error!")); - -assert(collectExceptionMsg!AssertError(assertThrown!StringException( - enforceEx!StringException(true, "Error!"))) == - `assertThrown failed: No StringException was thrown.`); --------------------- +/ void assertThrown(T : Throwable = Exception, E) (lazy E expression, @@ -237,26 +213,16 @@ void assertThrown(T : Throwable = Exception, E) string file = __FILE__, size_t line = __LINE__) { - bool thrown = false; - try expression(); - catch(T t) - thrown = true; + catch (T) + return; - if(!thrown) - { - immutable tail = msg.empty ? "." : ": " ~ msg; - - throw new AssertError(format("assertThrown failed: No %s was thrown%s", - T.stringof, - tail), - file, - line); - } + throw new AssertError(format("assertThrown failed: No %s was thrown%s%s", + T.stringof, msg.empty ? "." : ": ", msg), + file, line); } - -//Verify Examples +/// unittest { assertThrown!StringException(enforceEx!StringException(false, "Error!")); @@ -275,36 +241,32 @@ unittest void nothrowEx() { } try + { assertThrown!Exception(throwEx(new Exception("It's an Exception"))); - catch(AssertError) - assert(0); + } + catch (AssertError) assert(0); try { assertThrown!Exception(throwEx(new Exception("It's an Exception")), "It's a message"); } - catch(AssertError) - assert(0); + catch(AssertError) assert(0); try { assertThrown!AssertError(throwEx(new AssertError("It's an AssertError", - __FILE__, - __LINE__))); + __FILE__, __LINE__))); } - catch(AssertError) - assert(0); + catch (AssertError) assert(0); try { assertThrown!AssertError(throwEx(new AssertError("It's an AssertError", - __FILE__, - __LINE__)), + __FILE__, __LINE__)), "It's a message"); } - catch(AssertError) - assert(0); + catch (AssertError) assert(0); { @@ -361,14 +323,15 @@ unittest blocks and $(D invariant)s), because they will be compiled out when compiling with $(I -release). Use $(D assert) in contracts. - Example: --------------------- -auto f = enforce(fopen("data.txt")); -auto line = readln(f); -enforce(line.length, "Expected a non-empty line."); --------------------- + Example: + -------------------- + auto f = enforce(fopen("data.txt")); + auto line = readln(f); + enforce(line.length, "Expected a non-empty line."); + -------------------- +/ T enforce(T)(T value, lazy const(char)[] msg = null, string file = __FILE__, size_t line = __LINE__) + if (is(typeof({ if (!value) {} }))) { if (!value) bailOut(file, line, msg); return value; @@ -382,6 +345,7 @@ T enforce(T)(T value, lazy const(char)[] msg = null, string file = __FILE__, siz +/ T enforce(T, string file, size_t line = __LINE__) (T value, lazy const(char)[] msg = null) + if (is(typeof({ if (!value) {} }))) { if (!value) bailOut(file, line, msg); return value; @@ -395,7 +359,8 @@ T enforce(T, string file, size_t line = __LINE__) +/ T enforce(T, Dg, string file = __FILE__, size_t line = __LINE__) (T value, scope Dg dg) - if (is(Dg : void delegate()) || is(Dg : void function())) + if (isSomeFunction!Dg && is(typeof( dg() )) && + is(typeof({ if (!value) {} }))) { if (!value) dg(); return value; @@ -403,7 +368,7 @@ T enforce(T, Dg, string file = __FILE__, size_t line = __LINE__) private void bailOut(string file, size_t line, in char[] msg) @safe pure { - throw new Exception(msg ? msg.idup : "Enforcement failed", file, line); + throw new Exception(msg.ptr ? msg.idup : "Enforcement failed", file, line); } unittest @@ -423,6 +388,13 @@ unittest } } +unittest +{ + // Issue 10510 + extern(C) void cFoo() { } + enforce(false, &cFoo); +} + // purity and safety inference test unittest { @@ -497,12 +469,12 @@ unittest /++ If $(D !!value) is true, $(D value) is returned. Otherwise, $(D ex) is thrown. - Example: --------------------- -auto f = enforce(fopen("data.txt")); -auto line = readln(f); -enforce(line.length, new IOException); // expect a non-empty line --------------------- + Example: + -------------------- + auto f = enforce(fopen("data.txt")); + auto line = readln(f); + enforce(line.length, new IOException); // expect a non-empty line + -------------------- +/ T enforce(T)(T value, lazy Throwable ex) { @@ -521,12 +493,12 @@ unittest $(D new ErrnoException(msg)) is thrown. $(D ErrnoException) assumes that the last operation set $(D errno) to an error code. - Example: --------------------- -auto f = errnoEnforce(fopen("data.txt")); -auto line = readln(f); -enforce(line.length); // expect a non-empty line --------------------- + Example: + -------------------- + auto f = errnoEnforce(fopen("data.txt")); + auto line = readln(f); + enforce(line.length); // expect a non-empty line + -------------------- +/ T errnoEnforce(T, string file = __FILE__, size_t line = __LINE__) (T value, lazy string msg = null) @@ -542,12 +514,12 @@ T errnoEnforce(T, string file = __FILE__, size_t line = __LINE__) and can be constructed with $(D new E(file, line)), then $(D new E(file, line)) will be thrown. - Example: --------------------- - auto f = enforceEx!FileMissingException(fopen("data.txt")); - auto line = readln(f); - enforceEx!DataCorruptionException(line.length); --------------------- + Example: + -------------------- + auto f = enforceEx!FileMissingException(fopen("data.txt")); + auto line = readln(f); + enforceEx!DataCorruptionException(line.length); + -------------------- +/ template enforceEx(E) if (is(typeof(new E("", __FILE__, __LINE__)))) @@ -628,13 +600,6 @@ unittest T = The type of exception to catch. expression = The expression which may throw an exception. result = The result of the expression if no exception is thrown. - - Example: --------------------- -int[] a = new int[3]; -int b; -assert(collectException(a[4], b)); --------------------- +/ T collectException(T = Exception, E)(lazy E expression, ref E result) { @@ -648,13 +613,16 @@ T collectException(T = Exception, E)(lazy E expression, ref E result) } return null; } - +/// unittest { - int[] a = new int[3]; int b; int foo() { throw new Exception("blah"); } assert(collectException(foo(), b)); + + int[] a = new int[3]; + import core.exception : RangeError; + assert(collectException!RangeError(a[4], b)); } /++ @@ -710,18 +678,6 @@ unittest Params: T = The type of exception to catch. expression = The expression which may throw an exception. - - Examples: --------------------- -void throwFunc() {throw new Exception("My Message.");} -assert(collectExceptionMsg(throwFunc()) == "My Message."); - -void nothrowFunc() {} -assert(collectExceptionMsg(nothrowFunc()) is null); - -void throwEmptyFunc() {throw new Exception("");} -assert(collectExceptionMsg(throwEmptyFunc()) == emptyExceptionMsg); --------------------- +/ string collectExceptionMsg(T = Exception, E)(lazy E expression) { @@ -734,17 +690,16 @@ string collectExceptionMsg(T = Exception, E)(lazy E expression) catch(T e) return e.msg.empty ? emptyExceptionMsg : e.msg; } - -//Verify Examples. +/// unittest { - void throwFunc() {throw new Exception("My Message.");} + void throwFunc() { throw new Exception("My Message."); } assert(collectExceptionMsg(throwFunc()) == "My Message."); void nothrowFunc() {} assert(collectExceptionMsg(nothrowFunc()) is null); - void throwEmptyFunc() {throw new Exception("");} + void throwEmptyFunc() { throw new Exception(""); } assert(collectExceptionMsg(throwEmptyFunc()) == emptyExceptionMsg); } @@ -860,27 +815,110 @@ version(none) unittest assert(is(typeof(arr1) == immutable(int[string])) && arr == null); } +/** + * Wraps a possibly-throwing expression in a $(D nothrow) wrapper so that it + * can be called by a $(D nothrow) function. + * + * This wrapper function documents commitment on the part of the caller that + * the appropriate steps have been taken to avoid whatever conditions may + * trigger an exception during the evaluation of $(D expr). If it turns out + * that the expression $(I does) throw at runtime, the wrapper will throw an + * $(D AssertError). + * + * (Note that $(D Throwable) objects such as $(D AssertError) that do not + * subclass $(D Exception) may be thrown even from $(D nothrow) functions, + * since they are considered to be serious runtime problems that cannot be + * recovered from.) + */ +T assumeWontThrow(T)(lazy T expr, + string msg = null, + string file = __FILE__, + size_t line = __LINE__) nothrow +{ + try + { + return expr; + } + catch(Exception e) + { + immutable tail = msg.empty ? "." : ": " ~ msg; + throw new AssertError("assumeWontThrow failed: Expression did throw" ~ + tail, file, line); + } +} + +/// +unittest +{ + import std.math : sqrt; + + // This function may throw. + int squareRoot(int x) + { + if (x < 0) + throw new Exception("Tried to take root of negative number"); + return cast(int)sqrt(cast(double)x); + } + + // This function never throws. + int computeLength(int x, int y) nothrow + { + // Since x*x + y*y is always positive, we can safely assume squareRoot + // won't throw, and use it to implement this nothrow function. If it + // does throw (e.g., if x*x + y*y overflows a 32-bit value), then the + // program will terminate. + return assumeWontThrow(squareRoot(x*x + y*y)); + } + + assert(computeLength(3, 4) == 5); +} + +unittest +{ + void alwaysThrows() + { + throw new Exception("I threw up"); + } + void bad() nothrow + { + assumeWontThrow(alwaysThrows()); + } + assertThrown!AssertError(bad()); +} + /** Returns $(D true) if $(D source)'s representation embeds a pointer that points to $(D target)'s representation or somewhere inside it. -Note that evaluating $(D pointsTo(x, x)) checks whether $(D x) has +If $(D source) is or contains a dynamic array, then, then pointsTo will check +if there is overlap between the dynamic array and $(D target)'s representation. + +If $(D source) is or contains a union, then every member of the union is +checked for embedded pointers. This may lead to false positives, depending on +which should be considered the "active" member of the union. + +If $(D source) is a class, then pointsTo will handle it as a pointer. + +If $(D target) is a pointer, a dynamic array or a class, then pointsTo will only +check if $(D source) points to $(D target), $(I not) what $(D target) references. + +Note: Evaluating $(D pointsTo(x, x)) checks whether $(D x) has internal pointers. This should only be done as an assertive test, as the language is free to assume objects don't have internal pointers (TDPL 7.1.3.5). */ -bool pointsTo(S, T, Tdummy=void)(auto ref const S source, auto ref const T target) @trusted pure nothrow - if ((__traits(isRef, source) || isDynamicArray!S) && // lvalue or slice rvalue - (__traits(isRef, target) || isDynamicArray!T)) // lvalue or slice rvalue +bool pointsTo(S, T, Tdummy=void)(auto ref const S source, ref const T target) @trusted pure nothrow + if (__traits(isRef, source) || isDynamicArray!S || + isPointer!S || is(S == class)) { - static if (is(S P : U*, U)) + static if (isPointer!S || is(S == class)) { const m = cast(void*) source, b = cast(void*) &target, e = b + target.sizeof; return b <= m && m < e; } - else static if (is(S == struct)) + else static if (is(S == struct) || is(S == union)) { foreach (i, Subobj; typeof(source.tupleof)) if (pointsTo(source.tupleof[i], target)) return true; @@ -902,10 +940,101 @@ bool pointsTo(S, T, Tdummy=void)(auto ref const S source, auto ref const T targe } } // for shared objects -bool pointsTo(S, T)(ref const shared S source, ref const shared T target) @trusted pure nothrow +bool pointsTo(S, T)(auto ref const shared S source, ref const shared T target) @trusted pure nothrow { return pointsTo!(shared S, shared T, void)(source, target); } + +/// Pointers +unittest +{ + int i = 0; + int* p = null; + assert(!p.pointsTo(i)); + p = &i; + assert( p.pointsTo(i)); +} + +/// Structs and Unions +unittest +{ + struct S + { + int v; + int* p; + } + int i; + auto s = S(0, &i); + + //structs and unions "own" their members + //pointsTo will answer true if one of the members pointsTo. + assert(!s.pointsTo(s.v)); //s.v is just v member of s, so not pointed. + assert( s.p.pointsTo(i)); //i is pointed by s.p. + assert( s .pointsTo(i)); //which means i is pointed by s itself. + + //Unions will behave exactly the same. Points to will check each "member" + //individually, even if they share the same memory +} + +/// Arrays (dynamic and static) +unittest +{ + int i; + int[] slice = [0, 1, 2, 3, 4]; + int[5] arr = [0, 1, 2, 3, 4]; + int*[] slicep = [&i]; + int*[1] arrp = [&i]; + + //A slice points to all of its members: + assert( slice.pointsTo(slice[3])); + assert(!slice[0 .. 2].pointsTo(slice[3])); //Object 3 is outside of the slice [0 .. 2] + + //Note that a slice will not take into account what its members point to. + assert( slicep[0].pointsTo(i)); + assert(!slicep .pointsTo(i)); + + //static arrays are objects that own their members, just like structs: + assert(!arr.pointsTo(arr[0])); //arr[0] is just a member of arr, so not pointed. + assert( arrp[0].pointsTo(i)); //i is pointed by arrp[0]. + assert( arrp .pointsTo(i)); //which means i is pointed by arrp itslef. + + //Notice the difference between static and dynamic arrays: + assert(!arr .pointsTo(arr[0])); + assert( arr[].pointsTo(arr[0])); + assert( arrp .pointsTo(i)); + assert(!arrp[].pointsTo(i)); +} + +/// Classes +unittest +{ + class C + { + this(int* p){this.p = p;} + int* p; + } + int i; + C a = new C(&i); + C b = a; + //Classes are a bit particular, as they are treated like simple pointers + //to a class payload. + assert( a.p.pointsTo(i)); //a.p points to i. + assert(!a .pointsTo(i)); //Yet a itself does not point i. + + //To check the class payload itself, iterate on its members: + () + { + foreach (index, _; FieldTypeTuple!C) + if (pointsTo(a.tupleof[index], i)) + return; + assert(0); + }(); + + //To check if a class points a specific payload, a direct memmory check can be done: + auto aLoc = cast(ubyte[__traits(classInstanceSize, C)]*) a; + assert(b.pointsTo(*aLoc)); //b points to where a is pointing +} + unittest { struct S1 { int a; S1 * b; } @@ -947,7 +1076,6 @@ unittest //dynamic arrays don't point to each other, or slices of themselves assert(!pointsTo(darr, darr)); - assert(!pointsTo(darr, darr[0 .. 1])); assert(!pointsTo(darr[0 .. 1], darr)); //But they do point their elements @@ -1005,6 +1133,70 @@ unittest assert(!pointsTo(ss, ss)); //The array doesn't point itself. } + +unittest //Unions +{ + int i; + union U //Named union + { + size_t asInt = 0; + int* asPointer; + } + struct S + { + union //Anonymous union + { + size_t asInt = 0; + int* asPointer; + } + } + + U u; + S s; + assert(!pointsTo(u, i)); + assert(!pointsTo(s, i)); + + u.asPointer = &i; + s.asPointer = &i; + assert( pointsTo(u, i)); + assert( pointsTo(s, i)); + + u.asInt = cast(size_t)&i; + s.asInt = cast(size_t)&i; + assert( pointsTo(u, i)); //logical false positive + assert( pointsTo(s, i)); //logical false positive +} + +unittest //Classes +{ + int i; + static class A + { + int* p; + } + A a = new A, b = a; + assert(!pointsTo(a, b)); //a does not point to b + a.p = &i; + assert(!pointsTo(a, i)); //a does not point to i +} +unittest //alias this test +{ + static int i; + static int j; + struct S + { + int* p; + @property int* foo(){return &i;} + alias foo this; + } + assert(is(S : int*)); + S s = S(&j); + assert(!pointsTo(s, i)); + assert( pointsTo(s, j)); + assert( pointsTo(cast(int*)s, i)); + assert(!pointsTo(cast(int*)s, j)); +} + /********************* * Thrown if errors that set $(D errno) occur. */ @@ -1035,21 +1227,22 @@ class ErrnoException : Exception Params: E = The type of $(D Throwable)s to catch. Defaults to ${D Exception} - T = The return type of the expression and the error handler. + T1 = The type of the expression. + T2 = The return type of the error handler. expression = The expression to run and return its result. errorHandler = The handler to run if the expression throwed. Examples: --------------------- + -------------------- //Revert to a default value upon an error: assert("x".to!int().ifThrown(0) == 0); --------------------- + -------------------- You can also chain multiple calls to ifThrown, each capturing errors from the entire preceding expression. Example: --------------------- + -------------------- //Chaining multiple calls to ifThrown to attempt multiple things in a row: string s="true"; assert(s.to!int(). @@ -1062,14 +1255,14 @@ class ErrnoException : Exception .ifThrown!ConvException("not a number") .ifThrown!Exception("number too small") == "not a number"); --------------------- + -------------------- The expression and the errorHandler must have a common type they can both be implicitly casted to, and that type will be the type of the compound expression. Examples: --------------------- + -------------------- //null and new Object have a common type(Object). static assert(is(typeof(null.ifThrown(new Object())) == Object)); static assert(is(typeof((new Object()).ifThrown(null)) == Object)); @@ -1077,14 +1270,14 @@ class ErrnoException : Exception //1 and new Object do not have a common type. static assert(!__traits(compiles, 1.ifThrown(new Object()))); static assert(!__traits(compiles, (new Object()).ifThrown(1))); --------------------- + -------------------- If you need to use the actual thrown expection, you can use a delegate. Example: --------------------- + -------------------- //Use a lambda to get the thrown object. assert("%s".format().ifThrown!Exception(e => e.classinfo.name) == "std.format.FormatException"); --------------------- + -------------------- +/ //lazy version CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, T2)(lazy scope T1 expression, lazy scope T2 errorHandler) @@ -1187,9 +1380,9 @@ unittest } //Default does not include errors. - int[] a=[]; - assert(a[0].ifThrown(0).collectException!RangeError() !is null); - assert(a[0].ifThrown(e=>0).collectException!RangeError() !is null); + int throwRangeError() { throw new RangeError; } + assert(throwRangeError().ifThrown(0).collectException!RangeError() !is null); + assert(throwRangeError().ifThrown(e=>0).collectException!RangeError() !is null); //Incompatible types are not accepted. static assert(!__traits(compiles, 1.ifThrown(new Object()))); diff --git a/std/file.d b/std/file.d index 62615e4f5..8cbe5f0e7 100644 --- a/std/file.d +++ b/std/file.d @@ -42,18 +42,17 @@ version (unittest) { import core.thread; - private @property string deleteme() + private @property string deleteme() @safe { static _deleteme = "deleteme.dmd.unittest.pid"; static _first = true; if(_first) { - _deleteme = buildPath(tempDir(), _deleteme) ~ to!string(getpid()); + _deleteme = buildPath(tempDir(), _deleteme) ~ to!string(thisProcessID); _first = false; } - return _deleteme; } } @@ -100,7 +99,7 @@ class FileException : Exception file = The file where the error occurred. line = The line where the error occurred. +/ - this(in char[] name, in char[] msg, string file = __FILE__, size_t line = __LINE__) + this(in char[] name, in char[] msg, string file = __FILE__, size_t line = __LINE__) @safe pure { if(msg.empty) super(name.idup, file, line); @@ -115,15 +114,17 @@ class FileException : Exception in Windows, $(D_PARAM errno) in Posix). Params: - name = Name of file for which the error occurred. - msg = Message describing the error. - file = The file where the error occurred. - line = The line where the error occurred. + name = Name of file for which the error occurred. + errno = The error number. + file = The file where the error occurred. + Defaults to $(D __FILE__). + line = The line where the error occurred. + Defaults to $(D __LINE__). +/ version(Windows) this(in char[] name, uint errno = .GetLastError(), string file = __FILE__, - size_t line = __LINE__) + size_t line = __LINE__) @safe { this(name, sysErrorString(errno), file, line); this.errno = errno; @@ -131,7 +132,7 @@ class FileException : Exception else version(Posix) this(in char[] name, uint errno = .errno, string file = __FILE__, - size_t line = __LINE__) + size_t line = __LINE__) @trusted { auto s = strerror(errno); this(name, to!string(s), file, line); @@ -848,7 +849,7 @@ unittest /++ Returns whether the given file (or directory) exists. +/ -@property bool exists(in char[] name) +bool exists(in char[] name) @trusted { version(Windows) { @@ -1081,7 +1082,7 @@ unittest possible for both $(D isFile) and $(D isDir) to be $(D false) for a particular file (in which case, it's a special file). You can use $(D getAttributes) to get the attributes to figure out what type of special - it is, or you can use $(D dirEntry) to get at its $(D statBuf), which is the + it is, or you can use $(D DirEntry) to get at its $(D statBuf), which is the result from $(D stat). In either case, see the man page for $(D stat) for more information. @@ -1528,7 +1529,7 @@ else version(Posix) string readLink(C)(const(C)[] link) dynamicBuffer.length = dynamicBuffer.length * 3 / 2; } - throw new FileException(format("Path for %s is too long to read.", link)); + throw new FileException(to!string(link), "Path is too long to read."); } version(Posix) unittest @@ -1593,30 +1594,130 @@ unittest assert(s.length); } +version (OSX) + private extern (C) int _NSGetExecutablePath(char* buf, uint* bufsize); +else version (FreeBSD) + private extern (C) int sysctl (const int* name, uint namelen, void* oldp, + size_t* oldlenp, const void* newp, size_t newlen); + +/** + * Returns the full path of the current executable. + * + * Throws: + * $(XREF object, Exception) + */ +@trusted string thisExePath () +{ + version (OSX) + { + import core.sys.posix.stdlib : realpath; + + uint size; + + _NSGetExecutablePath(null, &size); // get the length of the path + auto buffer = new char[size]; + _NSGetExecutablePath(buffer.ptr, &size); + + auto absolutePath = realpath(buffer.ptr, null); // let the function allocate + + scope (exit) + { + if (absolutePath) + free(absolutePath); + } + + errnoEnforce(absolutePath); + return to!(string)(absolutePath); + } + else version (linux) + { + return readLink("/proc/self/exe"); + } + else version (Windows) + { + wchar[MAX_PATH] buf; + wchar[] buffer = buf[]; + + while (true) + { + auto len = GetModuleFileNameW(null, buffer.ptr, cast(DWORD) buffer.length); + enforce(len, sysErrorString(GetLastError())); + if (len != buffer.length) + return to!(string)(buffer[0 .. len]); + buffer.length *= 2; + } + } + else version (FreeBSD) + { + enum + { + CTL_KERN = 1, + KERN_PROC = 14, + KERN_PROC_PATHNAME = 12 + } + + int[4] mib = [CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1]; + size_t len; + + auto result = sysctl(mib.ptr, mib.length, null, &len, null, 0); // get the length of the path + errnoEnforce(result == 0); + + auto buffer = new char[len - 1]; + result = sysctl(mib.ptr, mib.length, buffer.ptr, &len, null, 0); + errnoEnforce(result == 0); + + return buffer.assumeUnique; + } + else + static assert(0, "thisExePath is not supported on this platform"); +} + +unittest +{ + auto path = thisExePath(); + + assert(path.exists); + assert(path.isAbsolute); + assert(path.isFile); +} version(StdDdoc) { /++ Info on a file, similar to what you'd get from stat on a Posix system. - - A $(D DirEntry) is obtained by using the functions $(D dirEntry) (to get - the $(D DirEntry) for a specific file) or $(D dirEntries) (to get a - $(D DirEntry) for each file/directory in a particular directory). +/ struct DirEntry { - void _init(T...)(T); - public: + /++ + Constructs a DirEntry for the given file (or directory). + + Params: + path = The file (or directory) to get a DirEntry for. + + Throws: + $(D FileException) if the file does not exist. + +/ + this(string path); + + version (Windows) + { + private this(string path, in WIN32_FIND_DATA* fd); + private this(string path, in WIN32_FIND_DATAW *fd); + } + else version (Posix) + { + private this(string path, core.sys.posix.dirent.dirent* fd); + } /++ Returns the path to the file represented by this $(D DirEntry). Examples: -------------------- -auto de1 = dirEntry("/etc/fonts/fonts.conf"); +auto de1 = DirEntry("/etc/fonts/fonts.conf"); assert(de1.name == "/etc/fonts/fonts.conf"); -auto de2 = dirEntry("/usr/share/include"); +auto de2 = DirEntry("/usr/share/include"); assert(de2.name == "/usr/share/include"); -------------------- +/ @@ -1629,10 +1730,10 @@ assert(de2.name == "/usr/share/include"); Examples: -------------------- -auto de1 = dirEntry("/etc/fonts/fonts.conf"); +auto de1 = DirEntry("/etc/fonts/fonts.conf"); assert(!de1.isDir); -auto de2 = dirEntry("/usr/share/include"); +auto de2 = DirEntry("/usr/share/include"); assert(de2.isDir); -------------------- +/ @@ -1655,10 +1756,10 @@ assert(de2.isDir); Examples: -------------------- -auto de1 = dirEntry("/etc/fonts/fonts.conf"); +auto de1 = DirEntry("/etc/fonts/fonts.conf"); assert(de1.isFile); -auto de2 = dirEntry("/usr/share/include"); +auto de2 = DirEntry("/usr/share/include"); assert(!de2.isFile); -------------------- +/ @@ -1750,6 +1851,52 @@ else version(Windows) public: alias name this; + this(string path) + { + if(!path.exists) + throw new FileException(path, "File does not exist"); + + _name = path; + + with (getFileAttributesWin(path)) + { + _size = makeUlong(nFileSizeLow, nFileSizeHigh); + _timeCreated = std.datetime.FILETIMEToSysTime(&ftCreationTime); + _timeLastAccessed = std.datetime.FILETIMEToSysTime(&ftLastAccessTime); + _timeLastModified = std.datetime.FILETIMEToSysTime(&ftLastWriteTime); + _attributes = dwFileAttributes; + } + } + + private this(string path, in WIN32_FIND_DATA* fd) + { + auto clength = to!int(core.stdc.string.strlen(fd.cFileName.ptr)); + + // Convert cFileName[] to unicode + const wlength = MultiByteToWideChar(0, 0, fd.cFileName.ptr, clength, null, 0); + auto wbuf = new wchar[wlength]; + const n = MultiByteToWideChar(0, 0, fd.cFileName.ptr, clength, wbuf.ptr, wlength); + assert(n == wlength); + // toUTF8() returns a new buffer + _name = buildPath(path, std.utf.toUTF8(wbuf[0 .. wlength])); + _size = (cast(ulong)fd.nFileSizeHigh << 32) | fd.nFileSizeLow; + _timeCreated = std.datetime.FILETIMEToSysTime(&fd.ftCreationTime); + _timeLastAccessed = std.datetime.FILETIMEToSysTime(&fd.ftLastAccessTime); + _timeLastModified = std.datetime.FILETIMEToSysTime(&fd.ftLastWriteTime); + _attributes = fd.dwFileAttributes; + } + private this(string path, in WIN32_FIND_DATAW *fd) + { + size_t clength = std.string.wcslen(fd.cFileName.ptr); + _name = std.utf.toUTF8(fd.cFileName[0 .. clength]); + _name = buildPath(path, std.utf.toUTF8(fd.cFileName[0 .. clength])); + _size = (cast(ulong)fd.nFileSizeHigh << 32) | fd.nFileSizeLow; + _timeCreated = std.datetime.FILETIMEToSysTime(&fd.ftCreationTime); + _timeLastAccessed = std.datetime.FILETIMEToSysTime(&fd.ftLastAccessTime); + _timeLastModified = std.datetime.FILETIMEToSysTime(&fd.ftLastWriteTime); + _attributes = fd.dwFileAttributes; + } + @property string name() const pure nothrow { return _name; @@ -1804,55 +1951,8 @@ else version(Windows) } private: - - void _init(in char[] path) - { - _name = path.idup; - - with (getFileAttributesWin(path)) - { - _size = makeUlong(nFileSizeLow, nFileSizeHigh); - _timeCreated = std.datetime.FILETIMEToSysTime(&ftCreationTime); - _timeLastAccessed = std.datetime.FILETIMEToSysTime(&ftLastAccessTime); - _timeLastModified = std.datetime.FILETIMEToSysTime(&ftLastWriteTime); - _attributes = dwFileAttributes; - } - } - - void _init(in char[] path, in WIN32_FIND_DATA* fd) - { - auto clength = to!int(std.c.string.strlen(fd.cFileName.ptr)); - - // Convert cFileName[] to unicode - const wlength = MultiByteToWideChar(0, 0, fd.cFileName.ptr, clength, null, 0); - auto wbuf = new wchar[wlength]; - const n = MultiByteToWideChar(0, 0, fd.cFileName.ptr, clength, wbuf.ptr, wlength); - assert(n == wlength); - // toUTF8() returns a new buffer - _name = buildPath(path, std.utf.toUTF8(wbuf[0 .. wlength])); - _size = (cast(ulong)fd.nFileSizeHigh << 32) | fd.nFileSizeLow; - _timeCreated = std.datetime.FILETIMEToSysTime(&fd.ftCreationTime); - _timeLastAccessed = std.datetime.FILETIMEToSysTime(&fd.ftLastAccessTime); - _timeLastModified = std.datetime.FILETIMEToSysTime(&fd.ftLastWriteTime); - _attributes = fd.dwFileAttributes; - } - - void _init(in char[] path, in WIN32_FIND_DATAW *fd) - { - size_t clength = std.string.wcslen(fd.cFileName.ptr); - _name = std.utf.toUTF8(fd.cFileName[0 .. clength]); - _name = buildPath(path, std.utf.toUTF8(fd.cFileName[0 .. clength])); - _size = (cast(ulong)fd.nFileSizeHigh << 32) | fd.nFileSizeLow; - _timeCreated = std.datetime.FILETIMEToSysTime(&fd.ftCreationTime); - _timeLastAccessed = std.datetime.FILETIMEToSysTime(&fd.ftLastAccessTime); - _timeLastModified = std.datetime.FILETIMEToSysTime(&fd.ftLastWriteTime); - _attributes = fd.dwFileAttributes; - } - - string _name; /// The file or directory represented by this DirEntry. - SysTime _timeCreated; /// The time when the file was created. SysTime _timeLastAccessed; /// The time when the file was last accessed. SysTime _timeLastModified; /// The time when the file was last modified. @@ -1868,6 +1968,43 @@ else version(Posix) public: alias name this; + this(string path) + { + if(!path.exists) + throw new FileException(path, "File does not exist"); + + _name = path; + + _didLStat = false; + _didStat = false; + _dTypeSet = false; + } + + private this(string path, core.sys.posix.dirent.dirent* fd) + { + immutable len = core.stdc.string.strlen(fd.d_name.ptr); + _name = buildPath(path, fd.d_name[0 .. len]); + + _didLStat = false; + _didStat = false; + + //fd_d_type doesn't work for all file systems, + //in which case the result is DT_UNKOWN. But we + //can determine the correct type from lstat, so + //we'll only set the dtype here if we could + //correctly determine it (not lstat in the case + //of DT_UNKNOWN in case we don't ever actually + //need the dtype, thus potentially avoiding the + //cost of calling lstat). + if(fd.d_type != DT_UNKNOWN) + { + _dType = fd.d_type; + _dTypeSet = true; + } + else + _dTypeSet = false; + } + @property string name() const pure nothrow { return _name; @@ -1943,41 +2080,6 @@ else version(Posix) } private: - - void _init(in char[] path) - { - _name = path.idup; - - _didLStat = false; - _didStat = false; - _dTypeSet = false; - } - - void _init(in char[] path, core.sys.posix.dirent.dirent* fd) - { - immutable len = std.c.string.strlen(fd.d_name.ptr); - _name = buildPath(path, fd.d_name[0 .. len]); - - _didLStat = false; - _didStat = false; - - //fd_d_type doesn't work for all file systems, - //in which case the result is DT_UNKOWN. But we - //can determine the correct type from lstat, so - //we'll only set the dtype here if we could - //correctly determine it (not lstat in the case - //of DT_UNKNOWN in case we don't ever actually - //need the dtype, thus potentially avoiding the - //cost of calling lstat). - if(fd.d_type != DT_UNKNOWN) - { - _dType = fd.d_type; - _dTypeSet = true; - } - else - _dTypeSet = false; - } - /++ This is to support lazy evaluation, because doing stat's is expensive and not always needed. @@ -2013,7 +2115,6 @@ else version(Posix) _didLStat = true; } - string _name; /// The file or directory represented by this DirEntry. stat_t _statBuf = void; /// The result of stat(). @@ -2032,7 +2133,7 @@ unittest { if("C:\\Program Files\\".exists) { - auto de = dirEntry("C:\\Program Files\\"); + auto de = DirEntry("C:\\Program Files\\"); assert(!de.isFile); assert(de.isDir); assert(!de.isSymlink); @@ -2040,13 +2141,13 @@ unittest if("C:\\Users\\".exists && "C:\\Documents and Settings\\".exists) { - auto de = dirEntry("C:\\Documents and Settings\\"); + auto de = DirEntry("C:\\Documents and Settings\\"); assert(de.isSymlink); } if("C:\\Windows\\system.ini".exists) { - auto de = dirEntry("C:\\Windows\\system.ini"); + auto de = DirEntry("C:\\Windows\\system.ini"); assert(de.isFile); assert(!de.isDir); assert(!de.isSymlink); @@ -2057,7 +2158,7 @@ unittest if("/usr/include".exists) { { - auto de = dirEntry("/usr/include"); + auto de = DirEntry("/usr/include"); assert(!de.isFile); assert(de.isDir); assert(!de.isSymlink); @@ -2069,7 +2170,7 @@ unittest core.sys.posix.unistd.symlink("/usr/include", symfile.ptr); { - auto de = dirEntry(symfile); + auto de = DirEntry(symfile); assert(!de.isFile); assert(de.isDir); assert(de.isSymlink); @@ -2078,7 +2179,7 @@ unittest if("/usr/include/assert.h".exists) { - auto de = dirEntry("/usr/include/assert.h"); + auto de = DirEntry("/usr/include/assert.h"); assert(de.isFile); assert(!de.isDir); assert(!de.isSymlink); @@ -2172,12 +2273,11 @@ unittest +/ void rmdirRecurse(in char[] pathname) { - DirEntry de = dirEntry(pathname); - - rmdirRecurse(de); + //No references to pathname will be kept after rmdirRecurse, + //so the cast is safe + rmdirRecurse(DirEntry(cast(string)pathname)); } - /++ Remove directory and all of its content and subdirectories, recursively. @@ -2189,7 +2289,7 @@ void rmdirRecurse(in char[] pathname) void rmdirRecurse(ref DirEntry de) { if(!de.isDir) - throw new FileException(text("File ", de.name, " is not a directory")); + throw new FileException(de.name, "Not a directory"); if(de.isSymlink) remove(de.name); @@ -2205,6 +2305,16 @@ void rmdirRecurse(ref DirEntry de) rmdir(de.name); } } +///ditto +//Note, without this overload, passing an RValue DirEntry still works, but +//actually fully reconstructs a DirEntry inside the +//"rmdirRecurse(in char[] pathname)" implementation. That is needlessly +//expensive. +//A DirEntry is a bit big (72B), so keeping the "by ref" signature is desirable. +void rmdirRecurse(DirEntry de) +{ + rmdirRecurse(de); +} version(Windows) unittest { @@ -2338,7 +2448,7 @@ private struct DirIteratorImpl popDirStack(); return false; } - _cur._init(_stack.data[$-1].dirpath, findinfo); + _cur = DirEntry(_stack.data[$-1].dirpath, findinfo); return true; } @@ -2359,7 +2469,7 @@ private struct DirIteratorImpl popDirStack(); return false; } - _cur._init(_stack.data[$-1].dirpath, findinfo); + _cur = DirEntry(_stack.data[$-1].dirpath, findinfo); return true; } @@ -2406,7 +2516,7 @@ private struct DirIteratorImpl if(core.stdc.string.strcmp(fdata.d_name.ptr, ".") && core.stdc.string.strcmp(fdata.d_name.ptr, "..") ) { - _cur._init(_stack.data[$-1].dirpath, fdata); + _cur = DirEntry(_stack.data[$-1].dirpath, fdata); return true; } } @@ -2581,8 +2691,8 @@ unittest auto len = enforce(walkLength(dirEntries(absolutePath(relpath), mode))); assert(walkLength(dirEntries(relpath, mode)) == len); assert(equal( - map!(q{std.path.absolutePath(a.name)})(dirEntries(relpath, mode)), - map!(q{a.name})(dirEntries(absolutePath(relpath), mode)))); + map!(a => std.path.absolutePath(a.name))(dirEntries(relpath, mode)), + map!(a => a.name)(dirEntries(absolutePath(relpath), mode)))); return len; } @@ -2601,21 +2711,22 @@ unittest //writeln(name); assert(e.isFile || e.isDir, e.name); } -} -unittest -{ //issue 7264 - foreach (string name; dirEntries(".", "*.d", SpanMode.breadth)) + foreach (string name; dirEntries(testdir, "*.d", SpanMode.breadth)) { } - foreach (entry; dirEntries(".", SpanMode.breadth)) + foreach (entry; dirEntries(testdir, SpanMode.breadth)) { static assert(is(typeof(entry) == DirEntry)); } //issue 7138 - auto a = array(dirEntries(".", SpanMode.shallow)); + auto a = array(dirEntries(testdir, SpanMode.shallow)); + + // issue 11392 + auto dFiles = dirEntries(testdir, SpanMode.shallow); + foreach(d; dFiles){} } /++ @@ -2653,6 +2764,9 @@ auto dirEntries(string path, string pattern, SpanMode mode, } /++ + $(RED Deprecated. It will be removed in July 2014. + Please use $(LREF DirEntry) constructor directly instead.) + Returns a DirEntry for the given file (or directory). Params: @@ -2661,16 +2775,10 @@ auto dirEntries(string path, string pattern, SpanMode mode, Throws: $(D FileException) if the file does not exist. +/ +deprecated("Please use DirEntry constructor directly instead.") DirEntry dirEntry(in char[] name) { - if(!name.exists) - throw new FileException(text("File ", name, " does not exist")); - - DirEntry dirEntry; - - dirEntry._init(name); - - return dirEntry; + return DirEntry(name.idup); } //Test dirEntry with a directory. @@ -2935,7 +3043,7 @@ meantime. The POSIX $(D tempDir) algorithm is inspired by Python's $(LINK2 http://docs.python.org/library/tempfile.html#tempfile.tempdir, $(D tempfile.tempdir)). */ -string tempDir() +string tempDir() @trusted { static string cache; if (cache is null) diff --git a/std/format.d b/std/format.d index bb7ddc203..c8e7b7121 100644 --- a/std/format.d +++ b/std/format.d @@ -7,11 +7,11 @@ Macros: WIKI = Phobos/StdFormat - Copyright: Copyright Digital Mars 2000-. + Copyright: Copyright Digital Mars 2000-2013. License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). - Authors: $(WEB digitalmars.com, Walter Bright), $(WEB erdani.com, + Authors: $(WEB walterbright.com, Walter Bright), $(WEB erdani.com, Andrei Alexandrescu), and Kenji Hara Source: $(PHOBOSSRC std/_format.d) @@ -21,13 +21,20 @@ module std.format; //debug=format; // uncomment to turn on debugging printf's import core.stdc.stdio, core.stdc.stdlib, core.stdc.string, core.vararg; -import std.algorithm, std.array, std.ascii, std.bitmanip, std.conv, - std.exception, std.functional, std.math, std.range, - std.string, std.system, std.traits, std.typecons, std.typetuple, +import std.algorithm, std.ascii, std.bitmanip, std.conv, + std.exception, std.range, + std.system, std.traits, std.typetuple, std.utf; +version (Win64) { + import std.math : isnan; +} version(unittest) { + import std.math; import std.stdio; + import std.string; + import std.typecons; import core.exception; + import std.string; } version (Win32) version (DigitalMars) @@ -51,11 +58,13 @@ version (DigitalMarsC) */ class FormatException : Exception { + @safe pure nothrow this() { super("format error"); } + @safe pure nothrow this(string msg, string fn = __FILE__, size_t ln = __LINE__, Throwable next = null) { super(msg, fn, ln, next); @@ -66,6 +75,9 @@ class FormatException : Exception deprecated("Please use FormatException instead.") alias FormatException FormatError; +private alias enforceFmt = enforceEx!FormatException; + + /********************************************************************** Interprets variadic argument list $(D args), formats them according to $(D fmt), and sends the resulting characters to $(D w). The @@ -149,7 +161,7 @@ $(I Integer): $(I Digit): $(B '0')|$(B '1')|$(B '2')|$(B '3')|$(B '4')|$(B '5')|$(B '6')|$(B '7')|$(B '8')|$(B '9') $(I FormatChar): - $(B 's')|$(B 'b')|$(B 'd')|$(B 'o')|$(B 'x')|$(B 'X')|$(B 'e')|$(B 'E')|$(B 'f')|$(B 'F')|$(B 'g')|$(B 'G')|$(B 'a')|$(B 'A') + $(B 's')|$(B 'c')|$(B 'b')|$(B 'd')|$(B 'o')|$(B 'x')|$(B 'X')|$(B 'e')|$(B 'E')|$(B 'f')|$(B 'F')|$(B 'g')|$(B 'G')|$(B 'a')|$(B 'A') ) $(BOOKTABLE Flags affect formatting depending on the specifier as @@ -179,7 +191,7 @@ $(I FormatChar): Precision).)) $(TR $(TD $(B ' ')) $(TD numeric) $(TD Prefix positive - numbers in a signed conversion with a space.)) + numbers in a signed conversion with a space.)))
$(I Width)
@@ -290,83 +302,82 @@ $(I FormatChar): $(I FormatChar) is lower case, or $(B INF) or $(B INFINITY) if upper. -Examples: + Examples: + ------------------------- + import std.c.stdio; + import std.format; -------------------------- -import std.c.stdio; -import std.format; + void main() + { + auto writer = appender!string(); + formattedWrite(writer, "%s is the ultimate %s.", 42, "answer"); + assert(writer.data == "42 is the ultimate answer."); + // Clear the writer + writer = appender!string(); + formattedWrite(writer, "Date: %2$s %1$s", "October", 5); + assert(writer.data == "Date: 5 October"); + } + ------------------------ -void main() -{ - auto writer = appender!string(); - formattedWrite(writer, "%s is the ultimate %s.", 42, "answer"); - assert(writer.data == "42 is the ultimate answer."); - // Clear the writer - writer = appender!string(); - formattedWrite(writer, "Date: %2$s %1$s", "October", 5); - assert(writer.data == "Date: 5 October"); -} ------------------------- + The positional and non-positional styles can be mixed in the same + format string. (POSIX leaves this behavior undefined.) The internal + counter for non-positional parameters tracks the next parameter after + the largest positional parameter already used. -The positional and non-positional styles can be mixed in the same -format string. (POSIX leaves this behavior undefined.) The internal -counter for non-positional parameters tracks the next parameter after -the largest positional parameter already used. + Example using array and nested array formatting: + ------------------------- + import std.stdio; -Example using array and nested array formatting: -------------------------- -import std.stdio; - -void main() -{ - writefln("My items are %(%s %).", [1,2,3]); - writefln("My items are %(%s, %).", [1,2,3]); -} -------------------------- - The output is: + void main() + { + writefln("My items are %(%s %).", [1,2,3]); + writefln("My items are %(%s, %).", [1,2,3]); + } + ------------------------- + The output is:
 My items are 1 2 3.
 My items are 1, 2, 3.
 
- The trailing end of the sub-format string following the specifier for each - item is interpreted as the array delimiter, and is therefore omitted - following the last array item. The $(B %|) delimiter specifier may be used - to indicate where the delimiter begins, so that the portion of the format - string prior to it will be retained in the last array element: -------------------------- -import std.stdio; + The trailing end of the sub-format string following the specifier for each + item is interpreted as the array delimiter, and is therefore omitted + following the last array item. The $(B %|) delimiter specifier may be used + to indicate where the delimiter begins, so that the portion of the format + string prior to it will be retained in the last array element: + ------------------------- + import std.stdio; -void main() -{ - writefln("My items are %(-%s-%|, %).", [1,2,3]); -} -------------------------- - which gives the output: + void main() + { + writefln("My items are %(-%s-%|, %).", [1,2,3]); + } + ------------------------- + which gives the output:
 My items are -1-, -2-, -3-.
 
- These compound format specifiers may be nested in the case of a nested - array argument: -------------------------- -import std.stdio; -void main() { - auto mat = [[1, 2, 3], - [4, 5, 6], - [7, 8, 9]]; + These compound format specifiers may be nested in the case of a nested + array argument: + ------------------------- + import std.stdio; + void main() { + auto mat = [[1, 2, 3], + [4, 5, 6], + [7, 8, 9]]; - writefln("%(%(%d %)\n%)", mat); - writeln(); + writefln("%(%(%d %)\n%)", mat); + writeln(); - writefln("[%(%(%d %)\n %)]", mat); - writeln(); + writefln("[%(%(%d %)\n %)]", mat); + writeln(); - writefln("[%([%(%d %)]%|\n %)]", mat); - writeln(); -} -------------------------- - The output is: + writefln("[%([%(%d %)]%|\n %)]", mat); + writeln(); + } + ------------------------- + The output is:
 1 2 3
 4 5 6
@@ -381,19 +392,19 @@ void main() {
  [7 8 9]]
 
- Inside a compound format specifier, strings and characters are escaped - automatically. To avoid this behavior, add $(B '-') flag to - $(D "%$(LPAREN)"). -------------------------- -import std.stdio; + Inside a compound format specifier, strings and characters are escaped + automatically. To avoid this behavior, add $(B '-') flag to + $(D "%$(LPAREN)"). + ------------------------- + import std.stdio; -void main() -{ - writefln("My friends are %s.", ["John", "Nancy"]); - writefln("My friends are %(%s, %).", ["John", "Nancy"]); - writefln("My friends are %-(%s, %).", ["John", "Nancy"]); -} -------------------------- + void main() + { + writefln("My friends are %s.", ["John", "Nancy"]); + writefln("My friends are %(%s, %).", ["John", "Nancy"]); + writefln("My friends are %-(%s, %).", ["John", "Nancy"]); + } + ------------------------- which gives the output:
 My friends are ["John", "Nancy"].
@@ -403,30 +414,35 @@ My friends are John, Nancy.
  */
 uint formattedWrite(Writer, Char, A...)(Writer w, in Char[] fmt, A args)
 {
-    enum len = args.length;
-    void function(Writer, const(void)*, ref FormatSpec!Char) funs[len] = void;
-    const(void)* argsAddresses[len] = void;
+    alias FPfmt = void function(Writer, const(void)*, ref FormatSpec!Char) @safe pure nothrow;
+
+    auto spec = FormatSpec!Char(fmt);
+
+    FPfmt[A.length] funs;
+    const(void)*[A.length] argsAddresses;
     if (!__ctfe)
     {
-        foreach (i, arg; args)
+        foreach (i, Arg; A)
         {
-            funs[i] = &formatGeneric!(Writer, typeof(arg), Char);
+            funs[i] = ()@trusted{ return cast(FPfmt)&formatGeneric!(Writer, Arg, Char); }();
             // We can safely cast away shared because all data is either
             // immutable or completely owned by this function.
-            argsAddresses[i] = cast(const(void*)) &args[ i ];
+            argsAddresses[i] = (ref arg)@trusted{ return cast(const void*) &arg; }(args[i]);
+
+            // Reflect formatting @safe/pure ability of each arguments to this function
+            if (0) formatValue(w, args[i], spec);
         }
     }
+
     // Are we already done with formats? Then just dump each parameter in turn
     uint currentArg = 0;
-    auto spec = FormatSpec!Char(fmt);
     while (spec.writeUpToNextSpec(w))
     {
         if (currentArg == funs.length && !spec.indexStart)
         {
             // leftover spec?
-            enforceEx!FormatException(
-                    fmt.length == 0,
-                    text("Orphan format specifier: %", fmt));
+            enforceFmt(fmt.length == 0,
+                text("Orphan format specifier: %", fmt));
             break;
         }
         if (spec.width == spec.DYNAMIC)
@@ -501,6 +517,13 @@ uint formattedWrite(Writer, Char, A...)(Writer w, in Char[] fmt, A args)
     return currentArg;
 }
 
+@safe pure unittest
+{
+    auto w = appender!string();
+    formattedWrite(w, "%s %d", "@safe/pure", 42);
+    assert(w.data == "@safe/pure 42");
+}
+
 /**
    Reads characters from input range $(D r), converts them according
    to $(D fmt), and writes them to $(D args).
@@ -523,6 +546,8 @@ assert(a == "hello" && b == 124 && c == 34.5);
  */
 uint formattedRead(R, Char, S...)(ref R r, const(Char)[] fmt, S args)
 {
+    import std.typecons : isTuple;
+
     auto spec = FormatSpec!Char(fmt);
     static if (!S.length)
     {
@@ -586,29 +611,29 @@ template FormatSpec(Char)
 }
 
 /**
-   A General handler for $(D printf) style format specifiers. Used for building more
-   specific formatting functions.
-
-   Example:
-----
-auto a = appender!(string)();
-auto fmt = "Number: %2.4e\nString: %s";
-auto f = FormatSpec!char(fmt);
-
-f.writeUpToNextSpec(a);
-
-assert(a.data == "Number: ");
-assert(f.trailing == "\nString: %s");
-assert(f.spec == 'e');
-assert(f.width == 2);
-assert(f.precision == 4);
-
-f.writeUpToNextSpec(a);
-
-assert(a.data == "Number: \nString: ");
-assert(f.trailing == "");
-assert(f.spec == 's');
-----
+ * A General handler for $(D printf) style format specifiers. Used for building more
+ * specific formatting functions.
+ *
+ * Example:
+ * ----
+ * auto a = appender!(string)();
+ * auto fmt = "Number: %2.4e\nString: %s";
+ * auto f = FormatSpec!char(fmt);
+ *
+ * f.writeUpToNextSpec(a);
+ *
+ * assert(a.data == "Number: ");
+ * assert(f.trailing == "\nString: %s");
+ * assert(f.spec == 'e');
+ * assert(f.width == 2);
+ * assert(f.precision == 4);
+ *
+ * f.writeUpToNextSpec(a);
+ *
+ * assert(a.data == "Number: \nString: ");
+ * assert(f.trailing == "");
+ * assert(f.spec == 's');
+ * ----
  */
 struct FormatSpec(Char)
     if (is(Unqual!Char == Char))
@@ -617,63 +642,76 @@ struct FormatSpec(Char)
        Minimum _width, default $(D 0).
      */
     int width = 0;
+
     /**
        Precision. Its semantics depends on the argument type. For
        floating point numbers, _precision dictates the number of
        decimals printed.
      */
     int precision = UNSPECIFIED;
+
     /**
        Special value for width and precision. $(D DYNAMIC) width or
        precision means that they were specified with $(D '*') in the
        format string and are passed at runtime through the varargs.
      */
     enum int DYNAMIC = int.max;
+
     /**
        Special value for precision, meaning the format specifier
        contained no explicit precision.
      */
     enum int UNSPECIFIED = DYNAMIC - 1;
+
     /**
        The actual format specifier, $(D 's') by default.
     */
     char spec = 's';
+
     /**
        Index of the argument for positional parameters, from $(D 1) to
        $(D ubyte.max). ($(D 0) means not used).
     */
     ubyte indexStart;
+
     /**
        Index of the last argument for positional parameter range, from
        $(D 1) to $(D ubyte.max). ($(D 0) means not used).
     */
     ubyte indexEnd;
-    version(StdDdoc) {
+
+    version(StdDdoc)
+    {
         /**
          The format specifier contained a $(D '-') ($(D printf)
          compatibility).
          */
         bool flDash;
+
         /**
          The format specifier contained a $(D '0') ($(D printf)
          compatibility).
          */
         bool flZero;
+
         /**
          The format specifier contained a $(D ' ') ($(D printf)
          compatibility).
          */
         bool flSpace;
+
         /**
          The format specifier contained a $(D '+') ($(D printf)
          compatibility).
          */
         bool flPlus;
+
         /**
          The format specifier contained a $(D '#') ($(D printf)
          compatibility).
          */
         bool flHash;
+
         // Fake field to allow compilation
         ubyte allFlags;
     }
@@ -738,14 +776,15 @@ struct FormatSpec(Char)
        Construct a new $(D FormatSpec) using the format string $(D fmt), no
        processing is done until needed.
      */
-    this(in Char[] fmt)
+    this(in Char[] fmt) @safe pure
     {
         trailing = fmt;
     }
 
     bool writeUpToNextSpec(OutputRange)(OutputRange writer)
     {
-        if (trailing.empty) return false;
+        if (trailing.empty)
+            return false;
         for (size_t i = 0; i < trailing.length; ++i)
         {
             if (trailing[i] != '%') continue;
@@ -824,16 +863,11 @@ struct FormatSpec(Char)
             case '(':
                 // Embedded format specifier.
                 auto j = i + 1;
-                void check(bool condition)
-                {
-                    enforce(
-                        condition,
-                        text("Incorrect format specifier: %", trailing[i .. $]));
-                }
                 // Get the matching balanced paren
                 for (uint innerParens;;)
                 {
-                    check(j < trailing.length);
+                    enforce(j < trailing.length,
+                        text("Incorrect format specifier: %", trailing[i .. $]));
                     if (trailing[j++] != '%')
                     {
                         // skip, we're waiting for %( and %)
@@ -896,9 +930,8 @@ struct FormatSpec(Char)
                     trailing = trailing[1 .. $];
                     width = -.parse!(typeof(width))(trailing);
                     i = 0;
-                    enforceEx!FormatException(
-                            trailing[i++] == '$',
-                            "$ expected");
+                    enforceFmt(trailing[i++] == '$',
+                        "$ expected");
                 }
                 else
                 {
@@ -908,10 +941,9 @@ struct FormatSpec(Char)
                 break;
             case '1': .. case '9':
                 auto tmp = trailing[i .. $];
-                const widthOrArgIndex = .parse!(uint)(tmp);
-                enforceEx!FormatException(
-                        tmp.length,
-                        text("Incorrect format specifier %", trailing[i .. $]));
+                const widthOrArgIndex = .parse!uint(tmp);
+                enforceFmt(tmp.length,
+                    text("Incorrect format specifier %", trailing[i .. $]));
                 i = tmp.ptr - trailing.ptr;
                 if (tmp.startsWith('$'))
                 {
@@ -933,9 +965,8 @@ struct FormatSpec(Char)
                         indexEnd = .parse!(typeof(indexEnd))(tmp);
                     }
                     i = tmp.ptr - trailing.ptr;
-                    enforceEx!FormatException(
-                            trailing[i++] == '$',
-                            "$ expected");
+                    enforceFmt(trailing[i++] == '$',
+                        "$ expected");
                 }
                 else
                 {
@@ -954,9 +985,8 @@ struct FormatSpec(Char)
                         trailing = trailing[i .. $];
                         i = 0;
                         precision = -.parse!int(trailing);
-                        enforceEx!FormatException(
-                                trailing[i++] == '$',
-                                "$ expected");
+                        enforceFmt(trailing[i++] == '$',
+                            "$ expected");
                     }
                     else
                     {
@@ -969,7 +999,7 @@ struct FormatSpec(Char)
                     // negative precision, as good as 0
                     precision = 0;
                     auto tmp = trailing[i .. $];
-                    .parse!(int)(tmp); // skip digits
+                    .parse!int(tmp); // skip digits
                     i = tmp.ptr - trailing.ptr;
                 }
                 else if (isDigit(trailing[i]))
@@ -1133,7 +1163,7 @@ struct FormatSpec(Char)
                 "\ntrailing = ", trailing, "\n");
     }
 }
-unittest
+@safe pure unittest
 {
     //Test the example
     auto a = appender!(string)();
@@ -1226,11 +1256,16 @@ if (is(BooleanTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
         formatValue(w, cast(int) val, f);
 }
 
+@safe pure unittest
+{
+    assertCTFEable!(
+    {
+        formatTest( false, "false" );
+        formatTest( true,  "true"  );
+    });
+}
 unittest
 {
-    formatTest( false, "false" );
-    formatTest( true,  "true"  );
-
     class C1 { bool val; alias val this; this(bool v){ val = v; } }
     class C2 { bool val; alias val this; this(bool v){ val = v; }
                override string toString() const { return "C"; } }
@@ -1261,16 +1296,21 @@ unittest
    $(D null) literal is formatted as $(D "null").
  */
 void formatValue(Writer, T, Char)(Writer w, T obj, ref FormatSpec!Char f)
-if (is(T == typeof(null)) && !is(T == enum) && !hasToString!(T, Char))
+if (is(Unqual!T == typeof(null)) &&
+!is(T == enum) && !hasToString!(T, Char))
 {
-    enforceEx!FormatException(f.spec == 's', "null");
+    enforceFmt(f.spec == 's',
+        "null");
 
     put(w, "null");
 }
 
-unittest
+@safe pure unittest
 {
-    formatTest( null, "null" );
+    assertCTFEable!(
+    {
+        formatTest( null, "null" );
+    });
 }
 
 /**
@@ -1280,51 +1320,51 @@ void formatValue(Writer, T, Char)(Writer w, T obj, ref FormatSpec!Char f)
 if (is(IntegralTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
 {
     alias U = IntegralTypeOf!T;
-    U val = obj;
+    U val = obj;    // Extracting alias this may be impure/system/may-throw
 
     if (f.spec == 'r')
     {
         // raw write, skip all else and write the thing
-        auto begin = cast(const char*) &val;
+        auto raw = (ref val)@trusted{
+            return (cast(const char*) &val)[0 .. val.sizeof];
+        }(val);
         if (std.system.endian == Endian.littleEndian && f.flPlus
             || std.system.endian == Endian.bigEndian && f.flDash)
         {
             // must swap bytes
-            foreach_reverse (i; 0 .. val.sizeof)
-                put(w, begin[i]);
+            foreach_reverse (c; raw)
+                put(w, c);
         }
         else
         {
-            foreach (i; 0 .. val.sizeof)
-                put(w, begin[i]);
+            foreach (c; raw)
+                put(w, c);
         }
         return;
     }
 
+    uint base =
+        f.spec == 'x' || f.spec == 'X' ? 16 :
+        f.spec == 'o' ? 8 :
+        f.spec == 'b' ? 2 :
+        f.spec == 's' || f.spec == 'd' || f.spec == 'u' ? 10 :
+        0;
+    enforceFmt(base > 0,
+        "integral");
+
     // Forward on to formatIntegral to handle both U and const(U)
     // Saves duplication of code for both versions.
     static if (isSigned!U)
-        formatIntegral(w, cast(long) val, f, Unsigned!U.max);
+        formatIntegral(w, cast( long) val, f, base, Unsigned!U.max);
     else
-        formatIntegral(w, cast(ulong) val, f, U.max);
+        formatIntegral(w, cast(ulong) val, f, base, U.max);
 }
 
-private void formatIntegral(Writer, T, Char)(Writer w, const(T) val, ref FormatSpec!Char f, ulong mask)
+private void formatIntegral(Writer, T, Char)(Writer w, const(T) val, ref FormatSpec!Char f, uint base, ulong mask)
 {
     FormatSpec!Char fs = f; // fs is copy for change its values.
-
     T arg = val;
 
-    uint base =
-        fs.spec == 'x' || fs.spec == 'X' ? 16 :
-        fs.spec == 'o' ? 8 :
-        fs.spec == 'b' ? 2 :
-        fs.spec == 's' || fs.spec == 'd' || fs.spec == 'u' ? 10 :
-        0;
-    enforceEx!FormatException(
-            base > 0,
-            "integral");
-
     bool negative = (base == 10 && arg < 0);
     if (negative)
     {
@@ -1372,9 +1412,9 @@ private void formatUnsigned(Writer, Char)(Writer w, ulong arg, ref FormatSpec!Ch
         forcedPrefix = '-';
     }
     // fill the digits
-    char[] digits = void;
+    char[64] buffer; // 64 bits in base 2 at most
+    char[] digits;
     {
-        char buffer[64]; // 64 bits in base 2 at most
         uint i = buffer.length;
         auto n = arg;
         do
@@ -1436,10 +1476,15 @@ private void formatUnsigned(Writer, Char)(Writer w, ulong arg, ref FormatSpec!Ch
     if (!leftPad) foreach (i ; 0 .. spacesToPrint) put(w, ' ');
 }
 
+@safe pure unittest
+{
+    assertCTFEable!(
+    {
+        formatTest( 10, "10" );
+    });
+}
 unittest
 {
-    formatTest( 10, "10" );
-
     class C1 { long val; alias val this; this(long v){ val = v; } }
     class C2 { long val; alias val this; this(long v){ val = v; }
                override string toString() const { return "C"; } }
@@ -1508,24 +1553,25 @@ if (is(FloatingPointTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
     if (fs.spec == 'r')
     {
         // raw write, skip all else and write the thing
-        auto begin = cast(const char*) &val;
+        auto raw = (ref val)@trusted{
+            return (cast(const char*) &val)[0 .. val.sizeof];
+        }(val);
         if (std.system.endian == Endian.littleEndian && f.flPlus
             || std.system.endian == Endian.bigEndian && f.flDash)
         {
             // must swap bytes
-            foreach_reverse (i; 0 .. val.sizeof)
-                put(w, begin[i]);
+            foreach_reverse (c; raw)
+                put(w, c);
         }
         else
         {
-            foreach (i; 0 .. val.sizeof)
-                put(w, begin[i]);
+            foreach (c; raw)
+                put(w, c);
         }
         return;
     }
-    enforceEx!FormatException(
-            std.algorithm.find("fgFGaAeEs", fs.spec).length,
-            "floating");
+    enforceFmt(std.algorithm.find("fgFGaAeEs", fs.spec).length,
+        "floating");
     version (Win64)
     {
         if (isnan(val)) // snprintf writes 1.#QNAN
@@ -1556,8 +1602,8 @@ if (is(FloatingPointTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
         }
     }
     if (fs.spec == 's') fs.spec = 'g';
-    char sprintfSpec[1 /*%*/ + 5 /*flags*/ + 3 /*width.prec*/ + 2 /*format*/
-                     + 1 /*\0*/] = void;
+    char[1 /*%*/ + 5 /*flags*/ + 3 /*width.prec*/ + 2 /*format*/
+                     + 1 /*\0*/] sprintfSpec = void;
     sprintfSpec[0] = '%';
     uint i = 1;
     if (fs.flDash) sprintfSpec[i++] = '-';
@@ -1578,19 +1624,20 @@ if (is(FloatingPointTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
             // negative precision is same as no precision specified
             fs.precision == fs.UNSPECIFIED ? -1 : fs.precision,
             val);
-    enforceEx!FormatException(
-            n >= 0,
-            "floating point formatting failure");
+    enforceFmt(n >= 0,
+        "floating point formatting failure");
     put(w, buf[0 .. strlen(buf.ptr)]);
 }
 
-unittest
+/*@safe pure */unittest
 {
     foreach (T; TypeTuple!(float, double, real))
     {
         formatTest( to!(          T)(5.5), "5.5" );
         formatTest( to!(    const T)(5.5), "5.5" );
         formatTest( to!(immutable T)(5.5), "5.5" );
+
+        formatTest( T.nan, "nan" );
     }
 }
 
@@ -1611,14 +1658,6 @@ unittest
     formatTest( S2(2.25), "S" );
 }
 
-unittest
-{
-    foreach (T; TypeTuple!(float, double, real))
-    {
-        formatTest( T.nan, "nan" );
-    }
-}
-
 /*
    Formatting a $(D creal) is deprecated but still kept around for a while.
  */
@@ -1628,12 +1667,15 @@ if (is(Unqual!T : creal) && !is(T == enum) && !hasToString!(T, Char))
     creal val = obj;
 
     formatValue(w, val.re, f);
-    put(w, '+');
+    if (val.im >= 0)
+    {
+        put(w, '+');
+    }
     formatValue(w, val.im, f);
     put(w, 'i');
 }
 
-unittest
+/*@safe pure */unittest
 {
     foreach (T; TypeTuple!(cfloat, cdouble, creal))
     {
@@ -1641,6 +1683,12 @@ unittest
         formatTest( to!(    const T)(1 + 1i), "1+1i" );
         formatTest( to!(immutable T)(1 + 1i), "1+1i" );
     }
+    foreach (T; TypeTuple!(cfloat, cdouble, creal))
+    {
+        formatTest( to!(          T)(0 - 3i), "0-3i" );
+        formatTest( to!(    const T)(0 - 3i), "0-3i" );
+        formatTest( to!(immutable T)(0 - 3i), "0-3i" );
+    }
 }
 
 unittest
@@ -1672,7 +1720,7 @@ if (is(Unqual!T : ireal) && !is(T == enum) && !hasToString!(T, Char))
     put(w, 'i');
 }
 
-unittest
+/*@safe pure */unittest
 {
     foreach (T; TypeTuple!(ifloat, idouble, ireal))
     {
@@ -1715,14 +1763,21 @@ if (is(CharTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
     }
     else
     {
-        formatValue(w, cast(uint) val, f);
+        alias U = TypeTuple!(ubyte, ushort, uint)[CharTypeOf!T.sizeof/2];
+        formatValue(w, cast(U) val, f);
     }
 }
 
+@safe pure unittest
+{
+    assertCTFEable!(
+    {
+        formatTest( 'c', "c" );
+    });
+}
+
 unittest
 {
-    formatTest( 'c', "c" );
-
     class C1 { char val; alias val this; this(char v){ val = v; } }
     class C2 { char val; alias val this; this(char v){ val = v; }
                override string toString() const { return "C"; } }
@@ -1736,6 +1791,21 @@ unittest
     formatTest( S2('c'), "S" );
 }
 
+@safe pure unittest
+{
+    //Little Endian
+    formatTest( "%-r", cast( char)'c', ['c'         ] );
+    formatTest( "%-r", cast(wchar)'c', ['c', 0      ] );
+    formatTest( "%-r", cast(dchar)'c', ['c', 0, 0, 0] );
+    formatTest( "%-r", '本', ['\x2c', '\x67'] );
+
+    //Big Endian
+    formatTest( "%+r", cast( char)'c', [         'c'] );
+    formatTest( "%+r", cast(wchar)'c', [0,       'c'] );
+    formatTest( "%+r", cast(dchar)'c', [0, 0, 0, 'c'] );
+    formatTest( "%+r", '本', ['\x67', '\x2c'] );
+}
+
 /**
    Strings are formatted like $(D printf) does.
  */
@@ -1777,6 +1847,25 @@ unittest
     formatTest( S3("s3"), "S" );
 }
 
+@safe pure unittest
+{
+    //Little Endian
+    formatTest( "%-r", "ab"c, ['a'         , 'b'         ] );
+    formatTest( "%-r", "ab"w, ['a', 0      , 'b', 0      ] );
+    formatTest( "%-r", "ab"d, ['a', 0, 0, 0, 'b', 0, 0, 0] );
+    formatTest( "%-r", "日本語"c, ['\xe6', '\x97', '\xa5', '\xe6', '\x9c', '\xac', '\xe8', '\xaa', '\x9e'] );
+    formatTest( "%-r", "日本語"w, ['\xe5', '\x65',                 '\x2c', '\x67',                 '\x9e', '\x8a'                ] );
+    formatTest( "%-r", "日本語"d, ['\xe5', '\x65', '\x00', '\x00', '\x2c', '\x67', '\x00', '\x00', '\x9e', '\x8a', '\x00', '\x00'] );
+
+    //Big Endian
+    formatTest( "%+r", "ab"c, [         'a',          'b'] );
+    formatTest( "%+r", "ab"w, [      0, 'a',       0, 'b'] );
+    formatTest( "%+r", "ab"d, [0, 0, 0, 'a', 0, 0, 0, 'b'] );
+    formatTest( "%+r", "日本語"c, ['\xe6', '\x97', '\xa5', '\xe6', '\x9c', '\xac', '\xe8', '\xaa', '\x9e'] );
+    formatTest( "%+r", "日本語"w, [                '\x65', '\xe5',                 '\x67', '\x2c',                 '\x8a', '\x9e'] );
+    formatTest( "%+r", "日本語"d, ['\x00', '\x00', '\x65', '\xe5', '\x00', '\x00', '\x67', '\x2c', '\x00', '\x00', '\x8a', '\x9e'] );
+}
+
 /**
    Static-size arrays are formatted as dynamic arrays.
  */
@@ -1844,7 +1933,7 @@ unittest
       static if (flags & 4)
         string toString() const { return "S"; }
     }
-    formatTest(S!0b000([0, 1, 2]), "S!(0)([0, 1, 2])");
+    formatTest(S!0b000([0, 1, 2]), "S!0([0, 1, 2])");
     formatTest(S!0b001([0, 1, 2]), "[0, 1, 2]");        // Test for bug 7628
     formatTest(S!0b010([0, 1, 2]), "[0, 2, 4]");
     formatTest(S!0b011([0, 1, 2]), "[0, 2, 4]");
@@ -1945,12 +2034,16 @@ unittest
                     `["hello"]` );
 
         // 1 character escape sequences (' is not escaped in strings)
-        formatTest( [cast(StrType)"\"'\\\a\b\f\n\r\t\v"],
-                    `["\"'\\\a\b\f\n\r\t\v"]` );
+        formatTest( [cast(StrType)"\"'\0\\\a\b\f\n\r\t\v"],
+                    `["\"'\0\\\a\b\f\n\r\t\v"]` );
+
+        // 1 character optional escape sequences
+        formatTest( [cast(StrType)"\'\?"],
+                    `["'?"]` );
 
         // Valid and non-printable code point (<= U+FF)
-        formatTest( [cast(StrType)"\x00\x10\x1F\x20test"],
-                    `["\x00\x10\x1F test"]` );
+        formatTest( [cast(StrType)"\x10\x1F\x20test"],
+                    `["\x10\x1F test"]` );
 
         // Valid and non-printable code point (<= U+FFFF)
         formatTest( [cast(StrType)"\u200B..\u200F"],
@@ -1992,13 +2085,13 @@ unittest
     formatTest( "%-(%s, %)", arr, `hello, world` );
 
     auto aa1 = [1:"hello", 2:"world"];
-    formatTest( "%(%s:%s, %)",  aa1, `1:"hello", 2:"world"` );
-    formatTest( "%-(%s:%s, %)", aa1, `1:hello, 2:world` );
+    formatTest( "%(%s:%s, %)",  aa1, [`1:"hello", 2:"world"`, `2:"world", 1:"hello"`] );
+    formatTest( "%-(%s:%s, %)", aa1, [`1:hello, 2:world`, `2:world, 1:hello`] );
 
     auto aa2 = [1:["ab", "cd"], 2:["ef", "gh"]];
-    formatTest( "%-(%s:%s, %)",        aa2, `1:["ab", "cd"], 2:["ef", "gh"]` );
-    formatTest( "%-(%s:%(%s%), %)",    aa2, `1:"ab""cd", 2:"ef""gh"` );
-    formatTest( "%-(%s:%-(%s%)%|, %)", aa2, `1:abcd, 2:efgh` );
+    formatTest( "%-(%s:%s, %)",        aa2, [`1:["ab", "cd"], 2:["ef", "gh"]`, `2:["ef", "gh"], 1:["ab", "cd"]`] );
+    formatTest( "%-(%s:%(%s%), %)",    aa2, [`1:"ab""cd", 2:"ef""gh"`, `2:"ef""gh", 1:"ab""cd"`] );
+    formatTest( "%-(%s:%-(%s%)%|, %)", aa2, [`1:abcd, 2:efgh`, `2:efgh, 1:abcd`] );
 }
 
 // input range formatting
@@ -2006,116 +2099,126 @@ private void formatRange(Writer, T, Char)(ref Writer w, ref T val, ref FormatSpe
 if (isInputRange!T)
 {
     // Formatting character ranges like string
-    static if (is(CharTypeOf!(ElementType!T)))
     if (f.spec == 's')
     {
-        static if (is(StringTypeOf!T))
+        static if (is(CharTypeOf!(ElementType!T)))
         {
-            auto s = val[0 .. f.precision < $ ? f.precision : $];
-            if (!f.flDash)
+            static if (is(StringTypeOf!T))
             {
-                // right align
-                if (f.width > s.length)
-                    foreach (i ; 0 .. f.width - s.length) put(w, ' ');
-                put(w, s);
-            }
-            else
-            {
-                // left align
-                put(w, s);
-                if (f.width > s.length)
-                    foreach (i ; 0 .. f.width - s.length) put(w, ' ');
-            }
-        }
-        else
-        {
-            if (!f.flDash)
-            {
-                static if (hasLength!T)
+                auto s = val[0 .. f.precision < $ ? f.precision : $];
+                if (!f.flDash)
                 {
                     // right align
-                    auto len = val.length;
-                }
-                else static if (isForwardRange!T && !isInfinite!T)
-                {
-                    auto len = walkLength(val.save);
+                    if (f.width > s.length)
+                        foreach (i ; 0 .. f.width - s.length) put(w, ' ');
+                    put(w, s);
                 }
                 else
                 {
-                    enforce(f.width == 0, "Cannot right-align a range without length");
-                    size_t len = 0;
-                }
-                if (f.precision != f.UNSPECIFIED && len > f.precision)
-                    len = f.precision;
-
-                if (f.width > len)
-                    foreach (i ; 0 .. f.width - len)
-                        put(w, ' ');
-                if (f.precision == f.UNSPECIFIED)
-                    put(w, val);
-                else
-                {
-                    size_t printed = 0;
-                    for (; !val.empty && printed < f.precision; val.popFront(), ++printed)
-                        put(w, val.front);
+                    // left align
+                    put(w, s);
+                    if (f.width > s.length)
+                        foreach (i ; 0 .. f.width - s.length) put(w, ' ');
                 }
             }
             else
             {
-                size_t printed = void;
-
-                // left align
-                if (f.precision == f.UNSPECIFIED)
+                if (!f.flDash)
                 {
                     static if (hasLength!T)
                     {
-                        printed = val.length;
-                        put(w, val);
+                        // right align
+                        auto len = val.length;
+                    }
+                    else static if (isForwardRange!T && !isInfinite!T)
+                    {
+                        auto len = walkLength(val.save);
                     }
                     else
                     {
-                        printed = 0;
-                        for (; !val.empty; val.popFront(), ++printed)
+                        enforce(f.width == 0, "Cannot right-align a range without length");
+                        size_t len = 0;
+                    }
+                    if (f.precision != f.UNSPECIFIED && len > f.precision)
+                        len = f.precision;
+
+                    if (f.width > len)
+                        foreach (i ; 0 .. f.width - len)
+                            put(w, ' ');
+                    if (f.precision == f.UNSPECIFIED)
+                        put(w, val);
+                    else
+                    {
+                        size_t printed = 0;
+                        for (; !val.empty && printed < f.precision; val.popFront(), ++printed)
                             put(w, val.front);
                     }
                 }
                 else
                 {
-                    printed = 0;
-                    for (; !val.empty && printed < f.precision; val.popFront(), ++printed)
-                        put(w, val.front);
-                }
+                    size_t printed = void;
 
-                if (f.width > printed)
-                    foreach (i ; 0 .. f.width - printed)
-                        put(w, ' ');
+                    // left align
+                    if (f.precision == f.UNSPECIFIED)
+                    {
+                        static if (hasLength!T)
+                        {
+                            printed = val.length;
+                            put(w, val);
+                        }
+                        else
+                        {
+                            printed = 0;
+                            for (; !val.empty; val.popFront(), ++printed)
+                                put(w, val.front);
+                        }
+                    }
+                    else
+                    {
+                        printed = 0;
+                        for (; !val.empty && printed < f.precision; val.popFront(), ++printed)
+                            put(w, val.front);
+                    }
+
+                    if (f.width > printed)
+                        foreach (i ; 0 .. f.width - printed)
+                            put(w, ' ');
+                }
             }
         }
-        return;
-    }
-
-    if (f.spec == 'r')
-    {
-        // raw writes
-        for (size_t i; !val.empty; val.popFront(), ++i)
+        else
         {
-            formatValue(w, val.front, f);
+            put(w, f.seqBefore);
+            if (!val.empty)
+            {
+                formatElement(w, val.front, f);
+                val.popFront();
+                for (size_t i; !val.empty; val.popFront(), ++i)
+                {
+                    put(w, f.seqSeparator);
+                    formatElement(w, val.front, f);
+                }
+            }
+            static if (!isInfinite!T) put(w, f.seqAfter);
         }
     }
-    else if (f.spec == 's')
+    else if (f.spec == 'r')
     {
-        put(w, f.seqBefore);
-        if (!val.empty)
+        static if (is(DynamicArrayTypeOf!T))
+        {
+            alias ARR = DynamicArrayTypeOf!T;
+            foreach (e ; cast(ARR)val)
+            {
+                formatValue(w, e, f);
+            }
+        }
+        else
         {
-            formatElement(w, val.front, f);
-            val.popFront();
             for (size_t i; !val.empty; val.popFront(), ++i)
             {
-                put(w, f.seqSeparator);
-                formatElement(w, val.front, f);
+                formatValue(w, val.front, f);
             }
         }
-        static if (!isInfinite!T) put(w, f.seqAfter);
     }
     else if (f.spec == '(')
     {
@@ -2130,7 +2233,7 @@ if (isInputRange!T)
                 formatValue(w, val.front, fmt);
             else
                 formatElement(w, val.front, fmt);
-            if (f.sep)
+            if (f.sep.ptr)
             {
                 put(w, fmt.trailing);
                 val.popFront();
@@ -2154,6 +2257,8 @@ if (isInputRange!T)
 // character formatting with ecaping
 private void formatChar(Writer)(Writer w, in dchar c, in char quote)
 {
+    import std.uni : isGraphical;
+
     if (std.uni.isGraphical(c))
     {
         if (c == quote || c == '\\')
@@ -2166,6 +2271,7 @@ private void formatChar(Writer)(Writer w, in dchar c, in char quote)
         put(w, '\\');
         switch (c)
         {
+        case '\0':  put(w, '0');  break;
         case '\a':  put(w, 'a');  break;
         case '\b':  put(w, 'b');  break;
         case '\f':  put(w, 'f');  break;
@@ -2285,9 +2391,8 @@ if (is(AssocArrayTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
 {
     AssocArrayTypeOf!T val = obj;
 
-    enforceEx!FormatException(
-            f.spec == 's' || f.spec == '(',
-            "associative");
+    enforceFmt(f.spec == 's' || f.spec == '(',
+        "associative");
 
     enum const(Char)[] defSpec = "%s" ~ f.keySeparator ~ "%s" ~ f.seqSeparator;
     auto fmtSpec = f.spec == '(' ? f.nested : defSpec;
@@ -2312,7 +2417,7 @@ if (is(AssocArrayTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
             fmt.writeUpToNextSpec(w);
             formatElement(w, v, fmt);
         }
-        if (f.sep)
+        if (f.sep.length)
         {
             fmt.writeUpToNextSpec(w);
             if (++i != end)
@@ -2334,21 +2439,21 @@ unittest
     formatTest( aa0, `[]` );
 
     // elements escaping
-    formatTest(  ["aaa":1, "bbb":2, "ccc":3],
-                `["aaa":1, "bbb":2, "ccc":3]` );
+    formatTest(  ["aaa":1, "bbb":2],
+               [`["aaa":1, "bbb":2]`, `["bbb":2, "aaa":1]`] );
     formatTest(  ['c':"str"],
                 `['c':"str"]` );
     formatTest(  ['"':"\"", '\'':"'"],
-                `['"':"\"", '\'':"'"]` );
+               [`['"':"\"", '\'':"'"]`, `['\'':"'", '"':"\""]`] );
 
     // range formatting for AA
     auto aa3 = [1:"hello", 2:"world"];
     // escape
     formatTest( "{%(%s:%s $ %)}", aa3,
-                `{1:"hello" $ 2:"world"}`);
+               [`{1:"hello" $ 2:"world"}`, `{2:"world" $ 1:"hello"}`]);
     // use range formatting for key and value, and use %|
     formatTest( "{%([%04d->%(%c.%)]%| $ %)}", aa3,
-                `{[0001->h.e.l.l.o] $ [0002->w.o.r.l.d]}` );
+               [`{[0001->h.e.l.l.o] $ [0002->w.o.r.l.d]}`, `{[0002->w.o.r.l.d] $ [0001->h.e.l.l.o]}`] );
 }
 
 unittest
@@ -2356,13 +2461,13 @@ unittest
     class C1 { int[char] val; alias val this; this(int[char] v){ val = v; } }
     class C2 { int[char] val; alias val this; this(int[char] v){ val = v; }
                override string toString() const { return "C"; } }
-    formatTest( new C1(['c':1, 'd':2]), `['c':1, 'd':2]` );
+    formatTest( new C1(['c':1, 'd':2]), [`['c':1, 'd':2]`, `['d':2, 'c':1]`] );
     formatTest( new C2(['c':1, 'd':2]), "C" );
 
     struct S1 { int[char] val; alias val this; }
     struct S2 { int[char] val; alias val this;
                 string toString() const { return "S"; } }
-    formatTest( S1(['c':1, 'd':2]), `['c':1, 'd':2]` );
+    formatTest( S1(['c':1, 'd':2]), [`['c':1, 'd':2]`, `['d':2, 'c':1]`] );
     formatTest( S2(['c':1, 'd':2]), "S" );
 }
 
@@ -2424,8 +2529,8 @@ void enforceValidFormatSpec(T, Char)(ref FormatSpec!Char f)
 {
     static if (!isInputRange!T && hasToString!(T, Char) != 4)
     {
-        enforceEx!FormatException(f.spec == 's',
-            format("Expected '%%s' format specifier for type '%s'", T.stringof));
+        enforceFmt(f.spec == 's',
+            "Expected '%s' format specifier for type '" ~ T.stringof ~ "'");
     }
 }
 
@@ -2840,33 +2945,34 @@ if (isPointer!T && !is(T == enum) && !hasToString!(T, Char))
         else
         {
             const p = val;
+            const pnum = ()@trusted{ return cast(ulong) p; }();
             if (f.spec == 's')
             {
                 FormatSpec!Char fs = f; // fs is copy for change its values.
                 fs.spec = 'X';
-                formatValue(w, cast(ulong) p, fs);
+                formatValue(w, pnum, fs);
             }
             else
             {
-                enforceEx!FormatException(f.spec == 'X' || f.spec == 'x',
+                enforceFmt(f.spec == 'X' || f.spec == 'x',
                    "Expected one of %s, %x or %X for pointer type.");
-                formatValue(w, cast(ulong) p, f);
+                formatValue(w, pnum, f);
             }
         }
     }
 }
 
-unittest
+@safe pure unittest
 {
     // pointer
     auto r = retro([1,2,3,4]);
-    auto p = &r;
+    auto p = ()@trusted{ auto p = &r; return p; }();
     formatTest( p, "[4, 3, 2, 1]" );
     assert(p.empty);
     p = null;
     formatTest( p, "null" );
 
-    auto q = cast(void*)0xFFEECCAA;
+    auto q = ()@trusted{ return cast(void*)0xFFEECCAA; }();
     formatTest( q, "FFEECCAA" );
 }
 
@@ -2909,16 +3015,16 @@ unittest
 void formatValue(Writer, T, Char)(Writer w, T val, ref FormatSpec!Char f)
 if (is(T == delegate) && !is(T == enum) && !hasToString!(T, Char))
 {
-    alias FunctionAttribute FA;
+    alias FA = FunctionAttribute;
     if (functionAttributes!T & FA.pure_)    formatValue(w, "pure ", f);
     if (functionAttributes!T & FA.nothrow_) formatValue(w, "nothrow ", f);
     if (functionAttributes!T & FA.ref_)     formatValue(w, "ref ", f);
     if (functionAttributes!T & FA.property) formatValue(w, "@property ", f);
     if (functionAttributes!T & FA.trusted)  formatValue(w, "@trusted ", f);
     if (functionAttributes!T & FA.safe)     formatValue(w, "@safe ", f);
-    formatValue(w, ReturnType!(T).stringof,f);
-    formatValue(w, " delegate",f);
-    formatValue(w, ParameterTypeTuple!(T).stringof,f);
+    formatValue(w, ReturnType!T.stringof, f);
+    formatValue(w, " delegate", f);
+    formatValue(w, ParameterTypeTuple!T.stringof, f);
 }
 
 unittest
@@ -3036,6 +3142,35 @@ void formatTest(T)(string fmt, T val, string expected, size_t ln = __LINE__, str
             text("expected = `", expected, "`, result = `", w.data, "`"), fn, ln);
 }
 
+version(unittest)
+void formatTest(T)(T val, string[] expected, size_t ln = __LINE__, string fn = __FILE__)
+{
+    FormatSpec!char f;
+    auto w = appender!string();
+    formatValue(w, val, f);
+    foreach(cur; expected)
+    {
+        if(w.data == cur) return;
+    }
+    enforceEx!AssertError(
+            false,
+            text("expected one of `", expected, "`, result = `", w.data, "`"), fn, ln);
+}
+
+version(unittest)
+void formatTest(T)(string fmt, T val, string[] expected, size_t ln = __LINE__, string fn = __FILE__)
+{
+    auto w = appender!string();
+    formattedWrite(w, fmt, val);
+    foreach(cur; expected)
+    {
+        if(w.data == cur) return;
+    }
+    enforceEx!AssertError(
+            false,
+            text("expected one of `", expected, "`, result = `", w.data, "`"), fn, ln);
+}
+
 unittest
 {
     auto stream = appender!string();
@@ -3121,6 +3256,11 @@ unittest
         assert(stream.data == "1.67 -0X1.47AE147AE147BP+0 nan",
                 stream.data);
     }
+    else version (MinGW)
+    {
+        assert(stream.data == "1.67 -0XA.3D70A3D70A3D8P-3 nan",
+                stream.data);
+    }
     else
     {
         assert(stream.data == "1.67 -0X1.47AE147AE147BP+0 nan",
@@ -3627,6 +3767,53 @@ void formatReflectTest(T)(ref T val, string fmt, string formatted, string fn = _
             input, fn, ln);
 }
 
+version(unittest)
+void formatReflectTest(T)(ref T val, string fmt, string[] formatted, string fn = __FILE__, size_t ln = __LINE__)
+{
+    auto w = appender!string();
+    formattedWrite(w, fmt, val);
+
+    auto input = w.data;
+
+    foreach(cur; formatted)
+    {
+        if(input == cur) return;
+    }
+    enforceEx!AssertError(
+            false,
+            input,
+            fn,
+            ln);
+
+    T val2;
+    formattedRead(input, fmt, &val2);
+    static if (isAssociativeArray!T)
+    if (__ctfe)
+    {
+        alias val aa1;
+        alias val2 aa2;
+        //assert(aa1 == aa2);
+
+        assert(aa1.length == aa2.length);
+
+        assert(aa1.keys == aa2.keys);
+
+        //assert(aa1.values == aa2.values);
+        assert(aa1.values.length == aa2.values.length);
+        foreach (i; 0 .. aa1.values.length)
+            assert(aa1.values[i] == aa2.values[i]);
+
+        //foreach (i, key; aa1.keys)
+        //    assert(aa1.values[i] == aa1[key]);
+        //foreach (i, key; aa2.keys)
+        //    assert(aa2.values[i] == aa2[key]);
+        return;
+    }
+    enforceEx!AssertError(
+            val == val2,
+            input, fn, ln);
+}
+
 unittest
 {
     void booleanTest()
@@ -3655,7 +3842,10 @@ unittest
     {
         auto f = 3.14;
         formatReflectTest(f, "%s",  `3.14`);
-        formatReflectTest(f, "%e",  `3.140000e+00`);
+        version (MinGW)
+            formatReflectTest(f, "%e",  `3.140000e+000`);
+        else
+            formatReflectTest(f, "%e",  `3.140000e+00`);
         formatReflectTest(f, "%f",  `3.140000`);
         formatReflectTest(f, "%g",  `3.14`);
     }
@@ -3700,9 +3890,9 @@ unittest
     void aaTest()
     {
         auto aa = [1:"hello", 2:"world"];
-        formatReflectTest(aa, "%s",                     `[1:"hello", 2:"world"]`);
-        formatReflectTest(aa, "[%(%s->%s, %)]",         `[1->"hello", 2->"world"]`);
-        formatReflectTest(aa, "{%([%s=%(%c%)]%|; %)}",  `{[1=hello]; [2=world]}`);
+        formatReflectTest(aa, "%s",                     [`[1:"hello", 2:"world"]`, `[2:"world", 1:"hello"]`]);
+        formatReflectTest(aa, "[%(%s->%s, %)]",         [`[1->"hello", 2->"world"]`, `[2->"world", 1->"hello"]`]);
+        formatReflectTest(aa, "{%([%s=%(%c%)]%|; %)}",  [`{[1=hello]; [2=world]}`, `{[2=world]; [1=hello]}`]);
     }
 
     import std.exception;
@@ -4205,10 +4395,10 @@ body
             }
             else static if (isAssociativeArray!T)
             {
-                auto key = unformatElement!(typeof(T.keys[0]))(input, fmt);
+                auto key = unformatElement!(typeof(T.init.keys[0]))(input, fmt);
                 fmt.readUpToNextSpec(input);        // eat key separator
 
-                result[key] = unformatElement!(typeof(T.values[0]))(input, fmt);
+                result[key] = unformatElement!(typeof(T.init.values[0]))(input, fmt);
             }
             debug (unformatRange) {
             if (input.empty) printf("-> front = [empty] ");
@@ -4640,11 +4830,11 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr)
     {
         for (;;)
         {
-            if (valti.classinfo.name.length == 18 &&
-                    valti.classinfo.name[9..18] == "Invariant")
+            if (typeid(valti).name.length == 18 &&
+                    typeid(valti).name[9..18] == "Invariant")
                 valti = (cast(TypeInfo_Invariant)valti).next;
-            else if (valti.classinfo.name.length == 14 &&
-                    valti.classinfo.name[9..14] == "Const")
+            else if (typeid(valti).name.length == 14 &&
+                    typeid(valti).name[9..14] == "Const")
                 valti = (cast(TypeInfo_Const)valti).next;
             else
                 break;
@@ -4801,9 +4991,9 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr)
 
         static Mangle getMan(TypeInfo ti)
         {
-          auto m = cast(Mangle)ti.classinfo.name[9];
-          if (ti.classinfo.name.length == 20 &&
-              ti.classinfo.name[9..20] == "StaticArray")
+          auto m = cast(Mangle)typeid(ti).name[9];
+          if (typeid(ti).name.length == 20 &&
+              typeid(ti).name[9..20] == "StaticArray")
                 m = cast(Mangle)'G';
           return m;
         }
@@ -4822,7 +5012,7 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr)
           auto tiSave = ti;
           auto mSave = m;
           ti = valti;
-          //printf("\n%.*s\n", valti.classinfo.name.length, valti.classinfo.name.ptr);
+          //printf("\n%.*s\n", typeid(valti).name.length, typeid(valti).name.ptr);
           m = getMan(valti);
           while (len--)
           {
@@ -4947,6 +5137,7 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr)
         }
 
         //printf("formatArg(fc = '%c', m = '%c')\n", fc, m);
+        int mi;
         switch (m)
         {
             case Mangle.Tbool:
@@ -5089,13 +5280,13 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr)
                 return;
 
             case Mangle.Tarray:
-                int mi = 10;
-                if (ti.classinfo.name.length == 14 &&
-                    ti.classinfo.name[9..14] == "Array")
+                mi = 10;
+                if (typeid(ti).name.length == 14 &&
+                    typeid(ti).name[9..14] == "Array")
                 { // array of non-primitive types
                   TypeInfo tn = (cast(TypeInfo_Array)ti).next;
                   tn = skipCI(tn);
-                  switch (cast(Mangle)tn.classinfo.name[9])
+                  switch (cast(Mangle)typeid(tn).name[9])
                   {
                     case Mangle.Tchar:  goto LarrayChar;
                     case Mangle.Twchar: goto LarrayWchar;
@@ -5107,8 +5298,8 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr)
                   putArray(va.ptr, va.length, tn);
                   return;
                 }
-                if (ti.classinfo.name.length == 25 &&
-                    ti.classinfo.name[9..25] == "AssociativeArray")
+                if (typeid(ti).name.length == 25 &&
+                    typeid(ti).name[9..25] == "AssociativeArray")
                 { // associative array
                   ubyte[long] vaa = va_arg!(ubyte[long])(argptr);
                   putAArray(vaa,
@@ -5119,7 +5310,7 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr)
 
                 while (1)
                 {
-                    m2 = cast(Mangle)ti.classinfo.name[mi];
+                    m2 = cast(Mangle)typeid(ti).name[mi];
                     switch (m2)
                     {
                         case Mangle.Tchar:
@@ -5135,8 +5326,7 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr)
 
                         case Mangle.Tdchar:
                         LarrayDchar:
-                            auto sd = va_arg!(dstring)(argptr);
-                            s = toUTF8(sd);
+                            s = toUTF8(va_arg!(dstring)(argptr));
                         Lputstr:
                             if (fc != 's')
                                 throw new FormatException("string");
@@ -5163,13 +5353,13 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr)
 
             case Mangle.Ttypedef:
                 ti = (cast(TypeInfo_Typedef)ti).base;
-                m = cast(Mangle)ti.classinfo.name[9];
+                m = cast(Mangle)typeid(ti).name[9];
                 formatArg(fc);
                 return;
 
             case Mangle.Tenum:
                 ti = (cast(TypeInfo_Enum)ti).base;
-                m = cast(Mangle)ti.classinfo.name[9];
+                m = cast(Mangle)typeid(ti).name[9];
                 formatArg(fc);
                 return;
 
@@ -5311,28 +5501,30 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr)
             }
         }
 
-        ptrdiff_t n = tmpbuf.length;
-        char c;
-        int hexoffset = uc ? ('A' - ('9' + 1)) : ('a' - ('9' + 1));
+        {
+            ptrdiff_t n = tmpbuf.length;
+            char c;
+            int hexoffset = uc ? ('A' - ('9' + 1)) : ('a' - ('9' + 1));
 
-        while (vnumber)
-        {
-            c = cast(char)((vnumber % base) + '0');
-            if (c > '9')
-                c += hexoffset;
-            vnumber /= base;
-            tmpbuf[--n] = c;
+            while (vnumber)
+            {
+                c = cast(char)((vnumber % base) + '0');
+                if (c > '9')
+                    c += hexoffset;
+                vnumber /= base;
+                tmpbuf[--n] = c;
+            }
+            if (tmpbuf.length - n < precision && precision < tmpbuf.length)
+            {
+                ptrdiff_t m = tmpbuf.length - precision;
+                tmpbuf[m .. n] = '0';
+                n = m;
+            }
+            else if (flags & FLhash && fc == 'o')
+                prefix = "0";
+            putstr(tmpbuf[n .. tmpbuf.length]);
+            return;
         }
-        if (tmpbuf.length - n < precision && precision < tmpbuf.length)
-        {
-            ptrdiff_t m = tmpbuf.length - precision;
-            tmpbuf[m .. n] = '0';
-            n = m;
-        }
-        else if (flags & FLhash && fc == 'o')
-            prefix = "0";
-        putstr(tmpbuf[n .. tmpbuf.length]);
-        return;
 
     Lreal:
         putreal(vreal);
@@ -5340,7 +5532,10 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr)
 
     Lcomplex:
         putreal(vcreal.re);
-        putc('+');
+        if (vcreal.im >= 0)
+        {
+            putc('+');
+        }
         putreal(vcreal.im);
         putc('i');
         return;
@@ -5352,7 +5547,7 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr)
     for (int j = 0; j < arguments.length; )
     {
         ti = arguments[j++];
-        //printf("arg[%d]: '%.*s' %d\n", j, ti.classinfo.name.length, ti.classinfo.name.ptr, ti.classinfo.name.length);
+        //printf("arg[%d]: '%.*s' %d\n", j, typeid(ti).name.length, typeid(ti).name.ptr, typeid(ti).name.length);
         //ti.print();
 
         flags = 0;
@@ -5363,19 +5558,19 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr)
         int mi = 9;
         do
         {
-            if (ti.classinfo.name.length <= mi)
+            if (typeid(ti).name.length <= mi)
                 goto Lerror;
-            m = cast(Mangle)ti.classinfo.name[mi++];
+            m = cast(Mangle)typeid(ti).name[mi++];
         } while (m == Mangle.Tconst || m == Mangle.Timmutable);
 
         if (m == Mangle.Tarray)
         {
-            if (ti.classinfo.name.length == 14 &&
-                    ti.classinfo.name[9..14] == "Array")
+            if (typeid(ti).name.length == 14 &&
+                    typeid(ti).name[9..14] == "Array")
             {
                 TypeInfo tn = (cast(TypeInfo_Array)ti).next;
                 tn = skipCI(tn);
-                switch (cast(Mangle)tn.classinfo.name[9])
+                switch (cast(Mangle)typeid(tn).name[9])
                 {
                 case Mangle.Tchar:
                 case Mangle.Twchar:
@@ -5388,7 +5583,7 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr)
                 }
             }
           L1:
-            Mangle m2 = cast(Mangle)ti.classinfo.name[mi];
+            Mangle m2 = cast(Mangle)typeid(ti).name[mi];
             string  fmt;                        // format string
             wstring wfmt;
             dstring dfmt;
@@ -5457,7 +5652,7 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr)
                     if (j == arguments.length)
                         throw new FormatException("too few arguments");
                     ti = arguments[j++];
-                    m = cast(Mangle)ti.classinfo.name[9];
+                    m = cast(Mangle)typeid(ti).name[9];
                     if (m != Mangle.Tint)
                         throw new FormatException("int argument expected");
                     return va_arg!(int)(argptr);
@@ -5545,7 +5740,7 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr)
                 mi = 9;
                 do
                 {
-                    m = cast(Mangle)ti.classinfo.name[mi++];
+                    m = cast(Mangle)typeid(ti).name[mi++];
                 } while (m == Mangle.Tconst || m == Mangle.Timmutable);
 
                 if (c > 0x7F)                // if UTF sequence
@@ -5586,6 +5781,9 @@ unittest
     //else version (OSX)
     //    assert(s == "1.67 -0XA.3D70A3D70A3D8P-3 nan", s);
     //else
+    version (MinGW)
+        assert(s == "1.67 -0XA.3D70A3D70A3D8P-3 nan", s);
+    else
         assert(s == "1.67 -0X1.47AE147AE147BP+0 nan", s);
 
     s = std.string.format("%x %X", 0x1234AF, 0xAFAFAFAF);
@@ -5841,9 +6039,9 @@ unittest
 
     immutable(char[5])[int] aa = ([3:"hello", 4:"betty"]);
     r = std.string.format("%s", aa.values);
-    assert(r == `["hello", "betty"]`);
+    assert(r == `["hello", "betty"]` || r == `["betty", "hello"]`);
     r = std.string.format("%s", aa);
-    assert(r == `[3:"hello", 4:"betty"]`);
+    assert(r == `[3:"hello", 4:"betty"]` || r == `[4:"betty", 3:"hello"]`);
 
     static const dchar[] ds = ['a','b'];
     for (int j = 0; j < ds.length; ++j)
@@ -5869,3 +6067,12 @@ unittest
     formattedWrite(stream, "%2$.*1$d", 12, 10);
     assert(stream.data == "000000000010", stream.data);
 }
+
+unittest
+{
+    // bug 6893
+    enum E : ulong { A, B, C }
+    auto stream = appender!(char[])();
+    formattedWrite(stream, "%s", E.C);
+    assert(stream.data == "C");
+}
diff --git a/std/getopt.d b/std/getopt.d
index a597aa4b3..be6a78e12 100644
--- a/std/getopt.d
+++ b/std/getopt.d
@@ -79,7 +79,7 @@ void main(string[] args)
  to their defaults and then invoke $(D getopt). If a
  command-line argument is recognized as an option with a parameter and
  the parameter cannot be parsed properly (e.g. a number is expected
- but not present), a $(D ConvException) exception is thrown.
+ but not present), a $(D Exception) exception is thrown.
 
  Depending on the type of the pointer being bound, $(D getopt)
  recognizes the following kinds of options:
@@ -178,15 +178,15 @@ Invoking the program with e.g. "--tune=alpha=0.5 --tune beta=0.6" will
 set $(D tuningParms) to [ "alpha" : 0.5, "beta" : 0.6 ]. In general,
 keys and values can be of any parsable types.)
 
-$(LI $(I Delegate options.) An option can be bound to a delegate with
-the signature $(D void delegate()), $(D void delegate(string option))
-or $(D void delegate(string option, string value)).
+$(LI $(I Callback options.) An option can be bound to a function or
+delegate with the signature $(D void function()), $(D void function(string option)),
+$(D void function(string option, string value)), or their delegate equivalents.
 
-$(UL $(LI In the $(D void delegate()) case, the delegate is invoked
-whenever the option is seen.) $(LI In the $(D void delegate(string
-option)) case, the option string (without the leading dash(es)) is
-passed to the delegate. After that, the option string is considered
-handled and removed from the options array.
+$(UL $(LI If the callback doesn't take any arguments, the callback is invoked
+whenever the option is seen.) $(LI If the callback takes one string argument,
+the option string (without the leading dash(es)) is passed to the callback.
+After that, the option string is considered handled and removed from the
+options array.
 
 ---------
 void main(string[] args)
@@ -208,10 +208,10 @@ void main(string[] args)
 }
 ---------
 
-)$(LI In the $(D void delegate(string option, string value)) case, the
+)$(LI If the callback takes two string arguments, the
 option string is handled as an option with one argument, and parsed
 accordingly. The option and its value are passed to the
-delegate. After that, whatever was passed to the delegate is
+callback. After that, whatever was passed to the callback is
 considered handled and removed from the list.
 
 ---------
@@ -372,7 +372,7 @@ enum config {
     noPassThrough,
     /// Stop at first argument that does not look like an option
     stopOnFirstNonOption,
-};
+}
 
 private void getoptImpl(T...)(ref string[] args,
     ref configuration cfg, T opts)
@@ -442,13 +442,21 @@ void handleOption(R)(string option, R receiver, ref string[] args,
                 a[1] != optionChar)
         {
             string[] expanded;
-            foreach (dchar c; a[1 .. $])
+            foreach (j, dchar c; a[1 .. $])
             {
+                // If the character is not alpha, stop right there. This allows
+                // e.g. -j100 to work as "pass argument 100 to option -j".
+                if (!isAlpha(c))
+                {
+                    expanded ~= a[j + 1 .. $];
+                    break;
+                }
                 expanded ~= text(optionChar, c);
             }
             args = args[0 .. i] ~ expanded ~ args[i + 1 .. $];
             continue;
         }
+
         string val;
         if (!optMatch(a, option, val, cfg))
         {
@@ -476,11 +484,11 @@ void handleOption(R)(string option, R receiver, ref string[] args,
         else
         {
             // non-boolean option, which might include an argument
-            //enum isDelegateWithOneParameter = is(typeof(receiver("")) : void);
-            enum isDelegateWithLessThanTwoParameters =
-                is(typeof(receiver) == delegate) &&
+            //enum isCallbackWithOneParameter = is(typeof(receiver("")) : void);
+            enum isCallbackWithLessThanTwoParameters =
+                (is(typeof(receiver) == delegate) || is(typeof(*receiver) == function)) &&
                 !is(typeof(receiver("", "")));
-            if (!isDelegateWithLessThanTwoParameters && !(val.length) && !incremental) {
+            if (!isCallbackWithLessThanTwoParameters && !(val.length) && !incremental) {
                 // Eat the next argument too.  Check to make sure there's one
                 // to be eaten first, though.
                 enforce(i < args.length,
@@ -504,7 +512,8 @@ void handleOption(R)(string option, R receiver, ref string[] args,
                 // string receiver
                 *receiver = to!(typeof(*receiver))(val);
             }
-            else static if (is(typeof(receiver) == delegate))
+            else static if (is(typeof(receiver) == delegate) ||
+                            is(typeof(*receiver) == function))
             {
                 static if (is(typeof(receiver("", "")) : void))
                 {
@@ -592,7 +601,7 @@ private bool optMatch(string arg, string optPattern, ref string value,
     // yank the second '-' if present
     if (isLong) arg = arg[1 .. $];
     immutable eqPos = std.string.indexOf(arg, assignChar);
-    if (eqPos >= 0)
+    if (isLong && eqPos >= 0)
     {
         // argument looks like --opt=value
         value = arg[eqPos + 1 .. $];
@@ -768,6 +777,33 @@ unittest
     bool tb1 = true;
     getopt(args, "fb1", &fb1, "fb2", &fb2, "tb1", &tb1);
     assert(fb1 && fb2 && !tb1);
+
+    // test function callbacks
+
+    static class MyEx : Exception
+    {
+        this() { super(""); }
+        this(string option) { this(); this.option = option; }
+        this(string option, string value) { this(option); this.value = value; }
+
+        string option;
+        string value;
+    }
+
+    static void myStaticHandler1() { throw new MyEx(); }
+    args = (["program.name", "--verbose"]).dup;
+    try { getopt(args, "verbose", &myStaticHandler1); assert(0); }
+    catch (MyEx ex) { assert(ex.option is null && ex.value is null); }
+
+    static void myStaticHandler2(string option) { throw new MyEx(option); }
+    args = (["program.name", "--verbose"]).dup;
+    try { getopt(args, "verbose", &myStaticHandler2); assert(0); }
+    catch (MyEx ex) { assert(ex.option == "verbose" && ex.value is null); }
+
+    static void myStaticHandler3(string option, string value) { throw new MyEx(option, value); }
+    args = (["program.name", "--verbose", "2"]).dup;
+    try { getopt(args, "verbose", &myStaticHandler3); assert(0); }
+    catch (MyEx ex) { assert(ex.option == "verbose" && ex.value == "2"); }
 }
 
 unittest
@@ -814,3 +850,25 @@ unittest
     getopt(args, "opt", &opt);
     assert(args == ["prog", "--a", "--b", "--c"]);
 }
+
+unittest
+{
+    string foo, bar;
+    auto args = ["prog", "-thello", "-dbar=baz"];
+    getopt(args, "t", &foo, "d", &bar);
+    assert(foo == "hello");
+    assert(bar == "bar=baz");
+    // From bugzilla 5762
+    string a;
+    args = ["prog", "-a-0x12"];
+    getopt(args, config.bundling, "a|addr", &a);
+    assert(a == "-0x12", a);
+    args = ["prog", "--addr=-0x12"];
+    getopt(args, config.bundling, "a|addr", &a);
+    assert(a == "-0x12");
+    // From https://d.puremagic.com/issues/show_bug.cgi?id=11764
+    args = ["main", "-test"];
+    bool opt;
+    args.getopt(config.passThrough, "opt", &opt);
+    assert(args == ["main", "-test"]);
+}
diff --git a/std/internal/digest/sha_SSSE3.d b/std/internal/digest/sha_SSSE3.d
index bfcd18c72..cd91081c2 100644
--- a/std/internal/digest/sha_SSSE3.d
+++ b/std/internal/digest/sha_SSSE3.d
@@ -214,6 +214,8 @@ version(USE_SSSE3)
      */
     private nothrow pure string[] weave(string[] seq1, string[] seq2, uint dist = 1)
     {
+        import std.algorithm : min;
+
         string[] res = [];
         auto i1 = 0, i2 = 0;
         while (i1 < seq1.length || i2 < seq2.length)
diff --git a/std/internal/math/biguintcore.d b/std/internal/math/biguintcore.d
index 10a8d0fa2..8fc4dee07 100644
--- a/std/internal/math/biguintcore.d
+++ b/std/internal/math/biguintcore.d
@@ -47,6 +47,7 @@ alias multibyteAddSub!('-') multibyteSub;
 
 
 private import core.cpuid;
+private import std.traits : Unqual;
 
 shared static this()
 {
@@ -73,6 +74,7 @@ else static if (BigDigit.sizeof == long.sizeof)
 }
 else static assert(0, "Unsupported BigDigit size");
 
+private import std.exception : assumeUnique;
 private import std.traits:isIntegral;
 enum BigDigitBits = BigDigit.sizeof*8;
 template maxBigDigits(T) if (isIntegral!T)
@@ -80,10 +82,10 @@ template maxBigDigits(T) if (isIntegral!T)
     enum maxBigDigits = (T.sizeof+BigDigit.sizeof-1)/BigDigit.sizeof;
 }
 
-enum BigDigit [] ZERO = [0];
-enum BigDigit [] ONE = [1];
-enum BigDigit [] TWO = [2];
-enum BigDigit [] TEN = [10];
+enum immutable(BigDigit) [] ZERO = [0];
+enum immutable(BigDigit) [] ONE = [1];
+enum immutable(BigDigit) [] TWO = [2];
+enum immutable(BigDigit) [] TEN = [10];
 
 
 public:
@@ -94,13 +96,17 @@ struct BigUint
 private:
     pure invariant() 
     {
-        assert( data.length == 1 || data[$-1] != 0 );
-    }
-    BigDigit [] data = ZERO;
-    this(BigDigit [] x) pure
+        assert( data.length >= 1 && (data.length == 1 || data[$-1] != 0 ));
+    }    
+    immutable(BigDigit) [] data = ZERO;
+    this(immutable(BigDigit) [] x) pure
     {
        data = x;
     }
+    this(T)(T x) pure if (isIntegral!T)
+    {
+        opAssign(x);
+    }
 public:
     // Length in uints
     size_t uintLength() pure const
@@ -168,20 +174,16 @@ public:
                 uint uhi = cast(uint)(u >> 32);
                 if (uhi == 0)
                 {
-                  data = new BigDigit[1];
-                  data[0] = ulo;
+                    data = [ulo];
                 }
                 else
                 {
-                  data = new BigDigit[2];
-                  data[0] = ulo;
-                  data[1] = uhi;
+                    data = [ulo, uhi];
                 }
             }
             else static if (BigDigit.sizeof == long.sizeof)
             {
-                data = new BigDigit[1];
-                data[0] = u;
+                data = [u];
             }
         }
     }
@@ -191,7 +193,7 @@ public:
     }
 
     ///
-    int opCmp(Tdummy = void)(BigUint y) pure
+    int opCmp(Tdummy = void)(const BigUint y) pure const
     {
         if (data.length != y.data.length)
             return (data.length > y.data.length) ?  1 : -1;
@@ -202,7 +204,7 @@ public:
     }
 
     ///
-    int opCmp(Tulong)(Tulong y) pure if(is (Tulong == ulong))
+    int opCmp(Tulong)(Tulong y) pure const if(is (Tulong == ulong))
     {
         if (data.length > maxBigDigits!Tulong)
             return 1;
@@ -212,7 +214,11 @@ public:
             BigDigit tmp = cast(BigDigit)(y>>(i*BigDigitBits));
             if (tmp == 0)
                 if (data.length >= i+1)
-                    return 1;
+                {
+                    // Since ZERO is [0], so we cannot simply return 1 here, as
+                    // data[i] would be 0 for i==0 in that case.
+                    return (data[i] > 0) ? 1 : 0;
+                }
                 else
                     continue;
             else
@@ -341,7 +347,7 @@ public:
                 ++firstNonZero;
         }
         auto len = (s.length - firstNonZero + 15)/4;
-        data = new BigDigit[len+1];
+        auto tmp = new BigDigit[len+1];
         uint part = 0;
         uint sofar = 0;
         uint partcount = 0;
@@ -361,7 +367,7 @@ public:
             ++partcount;
             if (partcount==8)
             {
-                data[sofar] = part;
+                tmp[sofar] = part;
                 ++sofar;
                 partcount = 0;
                 part = 0;
@@ -370,11 +376,11 @@ public:
         if (part)
         {
             for ( ; partcount != 8; ++partcount) part >>= 4;
-            data[sofar] = part;
+            tmp[sofar] = part;
             ++sofar;
         }
         if (sofar == 0) data = ZERO;
-        else data = data[0..sofar];
+        else data = assumeUnique(tmp[0..sofar]);
         return true;
     }
 
@@ -394,9 +400,10 @@ public:
             return true;
         }
         auto predictlength = (18*2 + 2*(s.length-firstNonZero)) / 19;
-        data = new BigDigit[predictlength];
-        uint hi = biguintFromDecimal(data, s[firstNonZero..$]);
-        data.length = hi;
+        auto tmp = new BigDigit[predictlength];
+        uint hi = biguintFromDecimal(tmp, s[firstNonZero..$]);
+        tmp.length = hi;
+        data = assumeUnique(tmp);
         return true;
     }
 
@@ -405,7 +412,7 @@ public:
     // All of these member functions create a new BigUint.
 
     // return x >> y
-    BigUint opShr(Tulong)(Tulong y) pure if (is (Tulong == ulong))
+    BigUint opShr(Tulong)(Tulong y) pure const if (is (Tulong == ulong))
     {
         assert(y>0);
         uint bits = cast(uint)y & BIGDIGITSHIFTMASK;
@@ -419,13 +426,13 @@ public:
         {
             uint [] result = new BigDigit[data.length - words];
             multibyteShr(result, data[words..$], bits);
-            if (result.length>1 && result[$-1]==0) return BigUint(result[0..$-1]);
-            else return BigUint(result);
+            if (result.length>1 && result[$-1]==0) return BigUint(assumeUnique(result[0..$-1]));
+            else return BigUint(assumeUnique(result));
         }
     }
 
     // return x << y
-    BigUint opShl(Tulong)(Tulong y) pure if (is (Tulong == ulong))
+    BigUint opShl(Tulong)(Tulong y) pure const if (is (Tulong == ulong))
     {
         assert(y>0);
         if (isZero()) return this;
@@ -437,14 +444,14 @@ public:
         if (bits==0)
         {
             result[words..words+data.length] = data[];
-            return BigUint(result[0..words+data.length]);
+            return BigUint(assumeUnique(result[0..words+data.length]));
         }
         else
         {
             uint c = multibyteShl(result[words..words+data.length], data, bits);
-            if (c==0) return BigUint(result[0..words+data.length]);
+            if (c==0) return BigUint(assumeUnique(result[0..words+data.length]));
             result[$-1] = c;
-            return BigUint(result);
+            return BigUint(assumeUnique(result));
         }
     }
 
@@ -481,10 +488,14 @@ public:
                     sign = false;
                     return r;
                 }
-                r.data = new BigDigit[ d > uint.max ? 2: 1];
-                r.data[0] = cast(uint)(d & 0xFFFF_FFFF);
                 if (d > uint.max)
-                    r.data[1] = cast(uint)(d>>32);
+                {
+                    r.data = [cast(uint)(d & 0xFFFF_FFFF), cast(uint)(d>>32)];
+                }
+                else
+                {
+                    r.data = [cast(uint)(d & 0xFFFF_FFFF)];
+                }
             }
         }
         else
@@ -532,7 +543,7 @@ public:
             result[x.data.length+1] = multibyteMulAdd!('+')(result[1..x.data.length+1],
                 x.data, hi, 0);
         }
-        return BigUint(removeLeadingZeros(result));
+        return BigUint(removeLeadingZeros(assumeUnique(result)));
     }
 
     /*  return x * y.
@@ -554,12 +565,13 @@ public:
         }
         // the highest element could be zero,
         // in which case we need to reduce the length
-        return BigUint(removeLeadingZeros(result));
+        return BigUint(removeLeadingZeros(assumeUnique(result)));
     }
 
     // return x / y
-    static BigUint divInt(T)(BigUint x, T y) pure if ( is(T == uint) )
+    static BigUint divInt(T)(BigUint x, T y_) pure if ( is(Unqual!T == uint) )
     {
+        uint y = y_;
         if (y == 1)
             return x;
         uint [] result = new BigDigit[x.data.length];
@@ -579,12 +591,13 @@ public:
             result[] = x.data[];
             uint rem = multibyteDivAssign(result, y, 0);
         }
-        return BigUint(removeLeadingZeros(result));
+        return BigUint(removeLeadingZeros(assumeUnique(result)));
     }
 
     // return x % y
-    static uint modInt(T)(BigUint x, T y) pure if ( is(T == uint) )
+    static uint modInt(T)(BigUint x, T y_) pure if ( is(Unqual!T == uint) )
     {
+        uint y = y_;
         assert(y!=0);
         if ((y&(-y)) == y)
         {   // perfect power of 2
@@ -610,7 +623,7 @@ public:
             return divInt(x, y.data[0]);
         BigDigit [] result = new BigDigit[x.data.length - y.data.length + 1];
         divModInternal(result, null, x.data, y.data);
-        return BigUint(removeLeadingZeros(result));
+        return BigUint(removeLeadingZeros(assumeUnique(result)));
     }
 
     // return x % y
@@ -619,14 +632,32 @@ public:
         if (y.data.length > x.data.length) return x;
         if (y.data.length == 1)
         {
-            BigDigit [] result = new BigDigit[1];
-            result[0] = modInt(x, y.data[0]);
-            return BigUint(result);
+            return BigUint([modInt(x, y.data[0])]);
         }
         BigDigit [] result = new BigDigit[x.data.length - y.data.length + 1];
         BigDigit [] rem = new BigDigit[y.data.length];
         divModInternal(result, rem, x.data, y.data);
-        return BigUint(removeLeadingZeros(rem));
+        return BigUint(removeLeadingZeros(assumeUnique(rem)));
+    }
+    
+    // return x op y
+    static BigUint bitwiseOp(string op)(BigUint x, BigUint y, bool xSign, bool ySign, ref bool resultSign) pure if (op == "|" || op == "^" || op == "&")
+    {
+        auto d1 = includeSign(x.data, y.uintLength, xSign);
+        auto d2 = includeSign(y.data, x.uintLength, ySign);
+        
+        foreach (i; 0..d1.length)
+        {
+            mixin("d1[i] " ~ op ~ "= d2[i];");
+        }
+        
+        mixin("resultSign = xSign " ~ op ~ " ySign;");
+        
+        if (resultSign) {
+            twosComplement(d1, d1);
+        }
+        
+        return BigUint(removeLeadingZeros(assumeUnique(d1)));
     }
 
     /**
@@ -840,8 +871,13 @@ public:
         {
             r1=r1[0 .. $ - 1];
         }
-        result.data = resultBuffer[0 .. result_start + r1.length];
-        return result;
+        return BigUint(assumeUnique(resultBuffer[0 .. result_start + r1.length]));
+    }
+
+    // Implement toHash so that BigUint works properly as an AA key.
+    size_t toHash() const @trusted nothrow
+    {
+        return typeid(data).getHash(&data);
     }
 
 } // end BigUint
@@ -855,7 +891,7 @@ unittest
 }
 
 // Remove leading zeros from x, to restore the BigUint invariant
-BigDigit[] removeLeadingZeros(BigDigit [] x) pure
+inout(BigDigit) [] removeLeadingZeros(inout(BigDigit) [] x) pure
 {
     size_t k = x.length;
     while(k>1 && x[k - 1]==0) --k;
@@ -931,6 +967,41 @@ unittest
 
 
 private:
+void twosComplement(const(BigDigit) [] x, BigDigit[] result) pure
+{
+    foreach (i; 0..x.length)
+    {
+        result[i] = ~x[i];
+    }
+    result[x.length..$] = BigDigit.max;
+    
+    bool sgn = false;
+    
+    foreach (i; 0..result.length) {
+        if (result[i] == BigDigit.max) {
+            result[i] = 0;
+        } else {
+            result[i] += 1;
+            break;
+        }
+    }
+}
+
+// Encode BigInt as BigDigit array (sign and 2's complement)
+BigDigit[] includeSign(const(BigDigit) [] x, size_t minSize, bool sign) pure
+{
+    size_t length = (x.length > minSize) ? x.length : minSize;
+    BigDigit [] result = new BigDigit[length];
+    if (sign)
+    {
+        twosComplement(x, result);
+    }
+    else
+    {
+        result[0..x.length] = x;
+    }
+    return result;
+}
 
 // works for any type
 T intpow(T)(T x, ulong n) pure
@@ -1026,7 +1097,7 @@ unittest
 /*  General unsigned subtraction routine for bigints.
  *  Sets result = x - y. If the result is negative, negative will be true.
  */
-BigDigit [] sub(BigDigit[] x, BigDigit[] y, bool *negative) pure
+BigDigit [] sub(const BigDigit [] x, const BigDigit [] y, bool *negative) pure
 {
     if (x.length == y.length)
     {
@@ -1051,7 +1122,7 @@ BigDigit [] sub(BigDigit[] x, BigDigit[] y, bool *negative) pure
         return result;
     }
     // Lengths are different
-    BigDigit [] large, small;
+    const(BigDigit) [] large, small;
     if (x.length < y.length)
     {
         *negative = true;
@@ -1081,9 +1152,9 @@ BigDigit [] sub(BigDigit[] x, BigDigit[] y, bool *negative) pure
 
 
 // return a + b
-BigDigit [] add(BigDigit[] a, BigDigit [] b) pure
+BigDigit [] add(const BigDigit [] a, const BigDigit [] b) pure
 {
-    BigDigit [] x, y;
+    const(BigDigit) [] x, y;
     if (a.length < b.length)
     {
         x = b; y = a;
@@ -1291,7 +1362,7 @@ void mulInternal(BigDigit[] result, const(BigDigit)[] x, const(BigDigit)[] y)
  *   NOTE: If the highest half-digit of x is zero, the highest digit of result will
  *   also be zero.
  */
-void squareInternal(BigDigit[] result, BigDigit[] x) pure
+void squareInternal(BigDigit[] result, const BigDigit[] x) pure
 {
   // Squaring is potentially half a multiply, plus add the squares of
   // the diagonal elements.
@@ -1314,8 +1385,8 @@ void squareInternal(BigDigit[] result, BigDigit[] x) pure
 import core.bitop : bsr;
 
 /// if remainder is null, only calculate quotient.
-void divModInternal(BigDigit [] quotient, BigDigit[] remainder, BigDigit [] u,
-		BigDigit [] v) pure
+void divModInternal(BigDigit [] quotient, BigDigit[] remainder, const BigDigit [] u,
+		const BigDigit [] v) pure
 {
     assert(quotient.length == u.length - v.length + 1);
     assert(remainder == null || remainder.length == v.length);
@@ -1362,8 +1433,8 @@ void divModInternal(BigDigit [] quotient, BigDigit[] remainder, BigDigit [] u,
 
 unittest
 {
-    uint [] u = [0, 0xFFFF_FFFE, 0x8000_0000];
-    uint [] v = [0xFFFF_FFFF, 0x8000_0000];
+    immutable(uint) [] u = [0, 0xFFFF_FFFE, 0x8000_0000];
+    immutable(uint) [] v = [0xFFFF_FFFF, 0x8000_0000];
     uint [] q = new uint[u.length - v.length + 1];
     uint [] r = new uint[2];
     divModInternal(q, r, u, v);
@@ -1455,6 +1526,8 @@ in
 }
 body
 {
+    import std.conv : ConvException;
+
     // Convert to base 1e19 = 10_000_000_000_000_000_000.
     // (this is the largest power of 10 that will fit into a long).
     // The length will be less than 1 + s.length/log2(10) = 1 + s.length/3.3219.
@@ -1476,6 +1549,8 @@ body
     {
         if (s[i] == '_')
             continue;
+        if (s[i] < '0' || s[i] > '9')
+            throw new ConvException("invalid digit");
         x *= 10;
         x += s[i] - '0';
         ++lo;
@@ -1610,7 +1685,7 @@ body
 // add two uints of possibly different lengths. Result must be as long
 // as the larger length.
 // Returns carry (0 or 1).
-uint addSimple(BigDigit [] result, BigDigit [] left, BigDigit [] right) pure
+uint addSimple(BigDigit[] result, const BigDigit [] left, const BigDigit [] right) pure
 in
 {
     assert(result.length == left.length);
@@ -1864,7 +1939,7 @@ void mulKaratsuba(BigDigit [] result, const(BigDigit) [] x,
     addOrSubAssignSimple(result[half..$], mid, !midNegative);
 }
 
-void squareKaratsuba(BigDigit [] result, BigDigit [] x, 
+void squareKaratsuba(BigDigit [] result, const BigDigit [] x, 
 		BigDigit [] scratchbuff) pure
 {
     // See mulKaratsuba for implementation comments.
@@ -1878,8 +1953,8 @@ void squareKaratsuba(BigDigit [] result, BigDigit [] x,
     // half length, round up.
     auto half = (x.length >> 1) + (x.length & 1);
 
-    BigDigit [] x0 = x[0 .. half];
-    BigDigit [] x1 = x[half .. $];
+    const(BigDigit)[] x0 = x[0 .. half];
+    const(BigDigit)[] x1 = x[half .. $];
     BigDigit [] mid = scratchbuff[0 .. half*2];
     BigDigit [] newscratchbuff = scratchbuff[half*2 .. $];
      // initially use result to store temporaries
@@ -2029,7 +2104,7 @@ private:
 
 // Returns the highest value of i for which left[i]!=right[i],
 // or 0 if left[] == right[]
-size_t highestDifferentDigit(BigDigit [] left, BigDigit [] right) pure
+size_t highestDifferentDigit(const BigDigit [] left, const BigDigit [] right) pure
 {
     assert(left.length == right.length);
     for (ptrdiff_t i = left.length - 1; i>0; --i)
@@ -2041,7 +2116,7 @@ size_t highestDifferentDigit(BigDigit [] left, BigDigit [] right) pure
 }
 
 // Returns the lowest value of i for which x[i]!=0.
-int firstNonZeroDigit(BigDigit[] x) pure
+int firstNonZeroDigit(const BigDigit [] x) pure
 {
     int k = 0;
     while (x[k]==0)
@@ -2224,16 +2299,16 @@ version(unittest)
 
 unittest
 {
-
-    void printBiguint(uint [] data)
+    void printBiguint(const uint [] data)
     {
-        char [] buff = new char[data.length*9];
-        printf("%.*s\n", biguintToHex(buff, data, '_'));
+        char [] buff = biguintToHex(new char[data.length*9], data, '_');
+        printf("%.*s\n", buff.length, buff.ptr);
     }
 
     void printDecimalBigUint(BigUint data)
     {
-        printf("%.*s\n", data.toDecimalString(0));
+        auto str = data.toDecimalString(0);
+        printf("%.*s\n", str.length, str.ptr);
     }
 
     uint [] a, b;
diff --git a/std/internal/math/gammafunction.d b/std/internal/math/gammafunction.d
index cc9c3e6e7..e9f9cd565 100644
--- a/std/internal/math/gammafunction.d
+++ b/std/internal/math/gammafunction.d
@@ -345,7 +345,7 @@ unittest {
     for (int i=1; fact real.mant_dig-15);
+        assert(feqrel(gamma(i*1.0L), fact) >= real.mant_dig-15);
         fact *= (i*1.0L);
     }
     assert(gamma(0.0) == real.infinity);
@@ -364,7 +364,7 @@ unittest {
     real SQRT_PI = 1.77245385090551602729816748334114518279754945612238L;
 
 
-    assert(feqrel(gamma(0.5L), SQRT_PI) == real.mant_dig);
+    assert(feqrel(gamma(0.5L), SQRT_PI) >= real.mant_dig-1);
     assert(feqrel(gamma(17.25L), 4.224986665692703551570937158682064589938e13L) >= real.mant_dig-4);
 
     assert(feqrel(gamma(1.0 / 3.0L),  2.67893853470774763365569294097467764412868937795730L) >= real.mant_dig-2);
@@ -892,12 +892,12 @@ unittest { // also tested by the normal distribution
 
     // Test against Mathematica   betaRegularized[z,a,b]
     // These arbitrary points are chosen to give good code coverage.
-    assert(feqrel(betaIncomplete(8, 10, 0.2), 0.010_934_315_234_099_2L) >=  real.mant_dig - 4);
+    assert(feqrel(betaIncomplete(8, 10, 0.2), 0.010_934_315_234_099_2L) >=  real.mant_dig - 5);
     assert(feqrel(betaIncomplete(2, 2.5, 0.9),0.989_722_597_604_452_767_171_003_59L) >= real.mant_dig - 1 );
-    assert(feqrel(betaIncomplete(1000, 800, 0.5), 1.179140859734704555102808541457164E-06L) >= real.mant_dig - 12 );
+    assert(feqrel(betaIncomplete(1000, 800, 0.5), 1.179140859734704555102808541457164E-06L) >= real.mant_dig - 13 );
     assert(feqrel(betaIncomplete(0.0001, 10000, 0.0001),0.999978059362107134278786L) >= real.mant_dig - 18 );
     assert(betaIncomplete(0.01, 327726.7, 0.545113) == 1.0);
-    assert(feqrel(betaIncompleteInv(8, 10, 0.010_934_315_234_099_2L), 0.2L) >= real.mant_dig - 1);
+    assert(feqrel(betaIncompleteInv(8, 10, 0.010_934_315_234_099_2L), 0.2L) >= real.mant_dig - 2);
     assert(feqrel(betaIncomplete(0.01, 498.437, 0.0121433),0.99999664562033077636065L) >= real.mant_dig - 1);
     assert(feqrel(betaIncompleteInv(5, 10, 0.2000002972865658842), 0.229121208190918L) >= real.mant_dig - 3);
     assert(feqrel(betaIncompleteInv(4, 7, 0.8000002209179505L), 0.483657360076904L) >= real.mant_dig - 3);
@@ -1504,7 +1504,7 @@ unittest {
     assert(digamma(1)== -EULERGAMMA);
     assert(feqrel(digamma(0.25), -PI/2 - 3* LN2 - EULERGAMMA) >= real.mant_dig-7);
     assert(feqrel(digamma(1.0L/6), -PI/2 *sqrt(3.0L) - 2* LN2 -1.5*log(3.0L) - EULERGAMMA) >= real.mant_dig-7);
-    assert(digamma(-5)!<>0);
+    assert(digamma(-5).isNaN);
     assert(feqrel(digamma(2.5), -EULERGAMMA - 2*LN2 + 2.0 + 2.0L/3) >= real.mant_dig-9);
     assert(isIdentical(digamma(NaN(0xABC)), NaN(0xABC)));
 
diff --git a/std/internal/processinit.d b/std/internal/processinit.d
index 9012704fe..79df0e767 100644
--- a/std/internal/processinit.d
+++ b/std/internal/processinit.d
@@ -13,10 +13,10 @@ module std.internal.processinit;
 
 version(OSX)
 {
-    extern(C) void std_process_static_this();
+    extern(C) void std_process_shared_static_this();
 
     shared static this()
     {
-        std_process_static_this();
+        std_process_shared_static_this();
     }
 }
diff --git a/std/internal/unicode_comp.d b/std/internal/unicode_comp.d
new file mode 100644
index 000000000..8b4cf344f
--- /dev/null
+++ b/std/internal/unicode_comp.d
@@ -0,0 +1,32 @@
+module std.internal.unicode_comp;
+import std.internal.unicode_tables;
+
+static if(size_t.sizeof == 8) {
+//6976 bytes
+enum combiningClassTrieEntries = TrieEntry!(ubyte, 8, 7, 6)([ 0x0,  0x20,  0x120], [ 0x100,  0x400,  0x1240], [ 0x402030202020100,  0x206020202020205,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x0,  0x0,  0x0,  0x20001,  0x300000000,  0x5000400000000,  0x8000000070006,  0xb0000000a0009,  0xe0000000d000c,  0x11000f0010000f,  0x11000f0011000f,  0x1100000011000f,  0x11000f00120000,  0x13000000110000,  0x17001600150014,  0x1b001a00190018,  0x1d0000001c,  0x0,  0x0,  0x1e0000,  0x0,  0x0,  0x0,  0x2000000000001f,  0x2100000000,  0x22,  0x240023,  0x28002700260025,  0x2a000000000029,  0x2b000000000000,  0x0,  0x0,  0x2c000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2d000000000000,  0x2f0000002e0000,  0x0,  0x0,  0x3100000030,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x34003300320000,  0x0,  0x36000000000035,  0x3a003900380037,  0x3c003b00000000,  0x3d000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3e,  0x0,  0x0,  0x3f,  0x0,  0x0,  0x40000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x41,  0x0,  0x0,  0x0,  0x0,  0x0,  0x4200350000,  0x3a000000000043,  0x0,  0x0,  0x0,  0x0,  0x4400000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x4600450000,  0x470000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6e6e6e6e6e6e6e6,  0xe6e6e6e6e6e6e6e6,  0xdcdce8e6e6e6e6e6,  0xdcdcdcdcd8e8dcdc,  0xcadcdcdcdccacadc,  0xdcdcdcdcdcdcdcca,  0x1010101dcdcdcdc,  0xe6e6e6dcdcdcdc01,  0xdce6f0e6e6e6e6e6,  0xdcdce6e6e6dcdc,  0xe6dcdcdcdce6e6e6,  0xe9eaeae9e6dcdce8,  0xe6e6e6e6e6e9eaea,  0xe6e6e6e6e6e6e6e6,  0x0,  0x0,  0xe6e6e6e6e6000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6dce6e6e6e6dc00,  0xe6e6e6e6dcdee6e6,  0xdcdcdcdcdcdce6e6,  0xe6e4dee6e6dce6e6,  0x11100f0e0d0c0b0a,  0x1700161514131312,  0x1200dce600191800,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6e6e6e6e6e6e6e6,  0x201f1e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1f1e1d1c1b000000,  0xe6dcdce6e6222120,  0xdce6e6dce6e6e6e6,  0x0,  0x0,  0x23,  0x0,  0x0,  0x0,  0xe6e6000000000000,  0xe60000e6e6e6e6e6,  0xe60000e6dce6e6e6,  0xdce6e6dc00e6,  0x0,  0x0,  0x0,  0x0,  0x2400,  0x0,  0x0,  0x0,  0xdce6e6dce6e6dce6,  0xe6dce6dcdce6dcdc,  0xe6dce6dce6dce6e6,  0xe6e6dc,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6e6e6e6e6000000,  0xe6dce6e6,  0x0,  0x0,  0x0,  0xe6e6000000000000,  0xe6e6e6e6e600e6e6,  0xe6e6e600e6e6e6e6,  0xe6e6e6e6e600,  0x0,  0x0,  0x0,  0x0,  0x0,  0xdcdcdc00,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6dce6e600000000,  0xdcdcdce6e6e6dce6,  0xe6dce6e6e61d1c1b,  0xe6e6e6e6dcdce6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x700000000,  0x0,  0x90000000000,  0xe6e6dce600,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x90000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x90000000000,  0x5b540000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x90000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x96767,  0x0,  0x6b6b6b6b,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7676,  0x0,  0x7a7a7a7a,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xdcdc,  0x0,  0x0,  0xdc00dc0000000000,  0xd800,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x8400828100,  0x828282820000,  0xe6e60009e6e60082,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xdc000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x700000000000000,  0x90900,  0x0,  0xdc0000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6e6e60000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x900000000,  0x0,  0x0,  0x0,  0x900000000,  0x0,  0x0,  0x0,  0x90000,  0xe60000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe400,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xdce6de00,  0x0,  0x0,  0xe600000000000000,  0xdc,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x9,  0x0,  0xe6e6e60000000000,  0xdc0000e6e6e6e6e6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x700000000,  0x0,  0x900000000,  0x0,  0x0,  0x0,  0x0,  0xe6e6e6dce6000000,  0xe6e6e6e6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x9090000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7000000000000,  0x0,  0x9090000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x700000000000000,  0x0,  0x0,  0x0,  0xdcdcdc0100e6e6e6,  0xdcdcdcdce6e6dcdc,  0x1010101010100e6,  0xdc0000000001,  0xe600000000,  0x0,  0xe6e6e6e6e6dce6e6,  0xdcd6eae6e6dce6e6,  0xe6e6e6e6e6e6e6ca,  0xe6e6e6e6e6e6e6e6,  0xe6e6e6e6e6e6e6,  0x0,  0x0,  0xdce6dce900000000,  0x0,  0x0,  0xe6e6e6e60101e6e6,  0xe6e6010101,  0xe60101000000e600,  0xdcdcdcdc0101e6dc,  0xe6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe600000000000000,  0xe6e6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x900000000000000,  0x0,  0x0,  0x0,  0x0,  0xe6e6e6e6e6e6e6e6,  0xe6e6e6e6e6e6e6e6,  0xe6e6e6e6e6e6e6e6,  0xe6e6e6e6e6e6e6e6,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe0e0dee8e4da0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x80800,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe600000000000000,  0xe6e6e6e600000000,  0xe6e6e6e6e6e6,  0x0,  0x0,  0x0,  0xe600000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6e6,  0x0,  0x9000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x900000000,  0x0,  0x0,  0x0,  0xe6e6e6e6e6e6e6e6,  0xe6e6e6e6e6e6e6e6,  0xe6e6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xdcdcdc000000,  0x0,  0x0,  0x0,  0x0,  0x9000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7000000,  0x0,  0x9,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe60000dce6e600e6,  0xe6e60000000000e6,  0xe600,  0x0,  0x0,  0x0,  0x0,  0x0,  0x9000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x90000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1a000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6e6e6e6e6e6e6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xdc0000000000,  0x0,  0xe600dc0000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x900000000dc01e6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x70900,  0xe6e6e6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x909000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x709000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1d8d80000000000,  0xd8d8e20000000101,  0xd8d8d8,  0xdcdcdcdcdc000000,  0xe6e6e60000dcdcdc,  0xdcdce6e6,  0x0,  0x0,  0x0,  0xe6e6e6e60000,  0x0,  0x0,  0xe6e6e60000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+enum composeIdxMask = (1<<11)-1, composeCntShift = 11;
+enum compositionJumpTrieEntries = TrieEntry!(ushort, 12, 9)([ 0x0,  0x400], [ 0x1000,  0x2000], [ 0x3000200010000,  0x7000600050004,  0x7000700070008,  0xa000700090007,  0x70007000c000b,  0x7000700070007,  0x700070007000d,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x700070007000e,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff080208010800,  0x281618138003ffff,  0x383308328821301b,  0x285108507841383a,  0x8068485f185c3056,  0x3882407affff1078,  0x30a510a398903889,  0xffff30b648ad10ab,  0xffffffffffffffff,  0x28cf18cc80bcffff,  0x38ec08eb88da30d4,  0x290b110970fb40f3,  0x8122491919163110,  0x393c4134ffff1132,  0x3960115e994b4143,  0xffff317351691167,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffff1979,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff217cffffffff,  0x984118209810980,  0xffff2185ffffffff,  0x989ffffffffffff,  0xffffffffffffffff,  0xffff0991198e218a,  0xffffffffffff0992,  0xffffffffffff2193,  0xffff2197ffffffff,  0x99f119d099c099b,  0xffff21a0ffffffff,  0x9a4ffffffffffff,  0xffffffffffffffff,  0xffff09ac19a921a5,  0xffffffffffff09ad,  0xffffffffffff21ae,  0x21b621b2ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x11bc11baffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff11c011be,  0xffffffffffffffff,  0xffffffffffffffff,  0x9c309c2ffffffff,  0xffffffffffffffff,  0xffffffff09c509c4,  0xffffffffffffffff,  0x9c909c809c709c6,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x9caffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff29d029cb,  0xffffffffffffffff,  0xffffffffffffffff,  0x29d5ffffffffffff,  0xffffffffffff29da,  0x9dfffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x9e109e0ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x9e309e2ffffffff,  0xffffffff09e509e4,  0x9e709e6ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff09e8ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff39e9ffff,  0x29f4ffff21f0ffff,  0xffffffff39f9ffff,  0x2200ffffffffffff,  0xffffffff0a04ffff,  0xffffffff3205ffff,  0xffffffff2a0bffff,  0xffff0a11ffff0a10,  0xffffffff4212ffff,  0x321effff221affff,  0xffffffff4224ffff,  0x222cffffffffffff,  0xffffffff1230ffff,  0xffffffff4232ffff,  0x1a431a40323affff,  0xffff0a46ffffffff,  0xffff1247ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff0a49ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xa4cffffffff124a,  0xa5212501a4dffff,  0xffff0a57ffff2253,  0xffff0a58ffffffff,  0x2259ffffffffffff,  0xa5dffffffffffff,  0xa5effffffffffff,  0xffffffff0a5fffff,  0xa62ffffffff1260,  0xa6812661a63ffff,  0xffff0a6dffff2269,  0xffff0a6effffffff,  0x226fffffffffffff,  0xa73ffffffffffff,  0xa74ffffffffffff,  0xffffffff0a75ffff,  0xffffffffffffffff,  0xffff0a76ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff0a780a77,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff0a7a0a79,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff0a7c0a7b,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x1a7dffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff0a81ffff0a80,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff0a82ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff0a83ffffffff,  0xffffffff0a84ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffff0a85,  0xffffffffffffffff,  0xa87ffffffff0a86,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x1288ffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x1a8affffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff0a8dffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xa90128effffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff0a91ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xa92ffffffffffff,  0xffffffffffffffff,  0xffff1a93ffffffff,  0xffff0a96ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xa991297ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff1a9affff,  0xffffffffffff0a9d,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff0a9effff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xaa0ffff0a9fffff,  0xaa2ffff0aa1ffff,  0xffffffff0aa3ffff,  0xffffffff0aa4ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff0aa5ffffffff,  0xaa80aa7ffff0aa6,  0xffff0aa9ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xaab0aaaffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xaad0aacffffffff,  0xffffffffffffffff,  0xaaf0aaeffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff12b212b0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff0ab50ab4,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff0ab70ab6,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xac10ac022bc22b8,  0xac50ac40ac30ac2,  0xacf0ace22ca22c6,  0xad30ad20ad10ad0,  0xffffffff12d612d4,  0xffffffffffffffff,  0xffffffff12da12d8,  0xffffffffffffffff,  0xae50ae422e022dc,  0xae90ae80ae70ae6,  0xaf30af222ee22ea,  0xaf70af60af50af4,  0xffffffff1afb1af8,  0xffffffffffffffff,  0xffffffff1b011afe,  0xffffffffffffffff,  0xffffffff13061304,  0xffffffffffffffff,  0xffffffff130a1308,  0xffffffffffffffff,  0xffffffff1b0f1b0c,  0xffffffffffffffff,  0xffffffff1b12ffff,  0xffffffffffffffff,  0xb1e0b1d23192315,  0xb220b210b200b1f,  0xb2c0b2b23272323,  0xb300b2f0b2e0b2d,  0xffffffffffff0b31,  0xffffffffffff0b32,  0xffffffffffffffff,  0xffffffffffff0b33,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff0b34ffffffff,  0xffffffffffffffff,  0x1b35ffffffffffff,  0xffffffffffffffff,  0xffff0b38ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff0b39ffffffff,  0xffffffffffffffff,  0xffff1b3affffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff0b3effff0b3d,  0xffffffffffff0b3f,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff0b41ffff0b40,  0xffffffffffff0b42,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xb43ffffffffffff,  0xffffffffffffffff,  0xb45ffffffff0b44,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xb46ffffffffffff,  0xffffffff0b47ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffff0b48,  0xb49ffffffffffff,  0xffffffff0b4affff,  0xffffffffffff0b4b,  0xffffffff0b4cffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff0b4dffff,  0xffffffff0b4f0b4e,  0xffffffffffffffff,  0xffffffffffffffff,  0xb510b50ffffffff,  0xb530b52ffffffff,  0xb550b54ffffffff,  0xffffffff0b570b56,  0xb590b58ffffffff,  0xb5b0b5affffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff0b5d0b5cffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff0b5effffffff,  0xffffffffffffffff,  0xb61ffff0b600b5f,  0xffffffffffffffff,  0xb630b62ffffffff,  0xffffffff0b650b64,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff0b66ffffffff,  0xb67ffffffffffff,  0xb69ffff0b68ffff,  0xb6bffff0b6affff,  0xb6dffff0b6cffff,  0xb6fffff0b6effff,  0xb71ffff0b70ffff,  0xffffffff0b72ffff,  0xffff0b74ffff0b73,  0xffffffffffff0b75,  0x1376ffffffffffff,  0xffff1378ffffffff,  0xffffffff137affff,  0x137effffffff137c,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff0b80ffff,  0xffffffffffffffff,  0xffff0b81ffffffff,  0xb82ffffffffffff,  0xb84ffff0b83ffff,  0xb86ffff0b85ffff,  0xb88ffff0b87ffff,  0xb8affff0b89ffff,  0xb8cffff0b8bffff,  0xffffffff0b8dffff,  0xffff0b8fffff0b8e,  0xffffffffffff0b90,  0x1391ffffffffffff,  0xffff1393ffffffff,  0xffffffff1395ffff,  0x1399ffffffff1397,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xb9bffffffffffff,  0xffff0b9e0b9d0b9c,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff0b9fffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xba1ffff0ba0ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff0ba2ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff0ba40ba3ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff]);
+@property immutable(CompEntry[]) compositionTable()
+{
+alias CE = CompEntry;
+static immutable CE[] t = [CE(0x00338, 0x0226e),CE(0x00338, 0x02260),CE(0x00338, 0x0226f),CE(0x00300, 0x000c0),CE(0x00301, 0x000c1),CE(0x00302, 0x000c2),CE(0x00303, 0x000c3),CE(0x00304, 0x00100),CE(0x00306, 0x00102),CE(0x00307, 0x00226),CE(0x00308, 0x000c4),CE(0x00309, 0x01ea2),CE(0x0030a, 0x000c5),CE(0x0030c, 0x001cd),CE(0x0030f, 0x00200),CE(0x00311, 0x00202),CE(0x00323, 0x01ea0),CE(0x00325, 0x01e00),CE(0x00328, 0x00104),CE(0x00307, 0x01e02),CE(0x00323, 0x01e04),CE(0x00331, 0x01e06),CE(0x00301, 0x00106),CE(0x00302, 0x00108),CE(0x00307, 0x0010a),CE(0x0030c, 0x0010c),CE(0x00327, 0x000c7),CE(0x00307, 0x01e0a),CE(0x0030c, 0x0010e),CE(0x00323, 0x01e0c),CE(0x00327, 0x01e10),CE(0x0032d, 0x01e12),CE(0x00331, 0x01e0e),CE(0x00300, 0x000c8),CE(0x00301, 0x000c9),CE(0x00302, 0x000ca),CE(0x00303, 0x01ebc),CE(0x00304, 0x00112),CE(0x00306, 0x00114),CE(0x00307, 0x00116),CE(0x00308, 0x000cb),CE(0x00309, 0x01eba),CE(0x0030c, 0x0011a),CE(0x0030f, 0x00204),CE(0x00311, 0x00206),CE(0x00323, 0x01eb8),CE(0x00327, 0x00228),CE(0x00328, 0x00118),CE(0x0032d, 0x01e18),CE(0x00330, 0x01e1a),CE(0x00307, 0x01e1e),CE(0x00301, 0x001f4),CE(0x00302, 0x0011c),CE(0x00304, 0x01e20),CE(0x00306, 0x0011e),CE(0x00307, 0x00120),CE(0x0030c, 0x001e6),CE(0x00327, 0x00122),CE(0x00302, 0x00124),CE(0x00307, 0x01e22),CE(0x00308, 0x01e26),CE(0x0030c, 0x0021e),CE(0x00323, 0x01e24),CE(0x00327, 0x01e28),CE(0x0032e, 0x01e2a),CE(0x00300, 0x000cc),CE(0x00301, 0x000cd),CE(0x00302, 0x000ce),CE(0x00303, 0x00128),CE(0x00304, 0x0012a),CE(0x00306, 0x0012c),CE(0x00307, 0x00130),CE(0x00308, 0x000cf),CE(0x00309, 0x01ec8),CE(0x0030c, 0x001cf),CE(0x0030f, 0x00208),CE(0x00311, 0x0020a),CE(0x00323, 0x01eca),CE(0x00328, 0x0012e),CE(0x00330, 0x01e2c),CE(0x00302, 0x00134),CE(0x00301, 0x01e30),CE(0x0030c, 0x001e8),CE(0x00323, 0x01e32),CE(0x00327, 0x00136),CE(0x00331, 0x01e34),CE(0x00301, 0x00139),CE(0x0030c, 0x0013d),CE(0x00323, 0x01e36),CE(0x00327, 0x0013b),CE(0x0032d, 0x01e3c),CE(0x00331, 0x01e3a),CE(0x00301, 0x01e3e),CE(0x00307, 0x01e40),CE(0x00323, 0x01e42),CE(0x00300, 0x001f8),CE(0x00301, 0x00143),CE(0x00303, 0x000d1),CE(0x00307, 0x01e44),CE(0x0030c, 0x00147),CE(0x00323, 0x01e46),CE(0x00327, 0x00145),CE(0x0032d, 0x01e4a),CE(0x00331, 0x01e48),CE(0x00300, 0x000d2),CE(0x00301, 0x000d3),CE(0x00302, 0x000d4),CE(0x00303, 0x000d5),CE(0x00304, 0x0014c),CE(0x00306, 0x0014e),CE(0x00307, 0x0022e),CE(0x00308, 0x000d6),CE(0x00309, 0x01ece),CE(0x0030b, 0x00150),CE(0x0030c, 0x001d1),CE(0x0030f, 0x0020c),CE(0x00311, 0x0020e),CE(0x0031b, 0x001a0),CE(0x00323, 0x01ecc),CE(0x00328, 0x001ea),CE(0x00301, 0x01e54),CE(0x00307, 0x01e56),CE(0x00301, 0x00154),CE(0x00307, 0x01e58),CE(0x0030c, 0x00158),CE(0x0030f, 0x00210),CE(0x00311, 0x00212),CE(0x00323, 0x01e5a),CE(0x00327, 0x00156),CE(0x00331, 0x01e5e),CE(0x00301, 0x0015a),CE(0x00302, 0x0015c),CE(0x00307, 0x01e60),CE(0x0030c, 0x00160),CE(0x00323, 0x01e62),CE(0x00326, 0x00218),CE(0x00327, 0x0015e),CE(0x00307, 0x01e6a),CE(0x0030c, 0x00164),CE(0x00323, 0x01e6c),CE(0x00326, 0x0021a),CE(0x00327, 0x00162),CE(0x0032d, 0x01e70),CE(0x00331, 0x01e6e),CE(0x00300, 0x000d9),CE(0x00301, 0x000da),CE(0x00302, 0x000db),CE(0x00303, 0x00168),CE(0x00304, 0x0016a),CE(0x00306, 0x0016c),CE(0x00308, 0x000dc),CE(0x00309, 0x01ee6),CE(0x0030a, 0x0016e),CE(0x0030b, 0x00170),CE(0x0030c, 0x001d3),CE(0x0030f, 0x00214),CE(0x00311, 0x00216),CE(0x0031b, 0x001af),CE(0x00323, 0x01ee4),CE(0x00324, 0x01e72),CE(0x00328, 0x00172),CE(0x0032d, 0x01e76),CE(0x00330, 0x01e74),CE(0x00303, 0x01e7c),CE(0x00323, 0x01e7e),CE(0x00300, 0x01e80),CE(0x00301, 0x01e82),CE(0x00302, 0x00174),CE(0x00307, 0x01e86),CE(0x00308, 0x01e84),CE(0x00323, 0x01e88),CE(0x00307, 0x01e8a),CE(0x00308, 0x01e8c),CE(0x00300, 0x01ef2),CE(0x00301, 0x000dd),CE(0x00302, 0x00176),CE(0x00303, 0x01ef8),CE(0x00304, 0x00232),CE(0x00307, 0x01e8e),CE(0x00308, 0x00178),CE(0x00309, 0x01ef6),CE(0x00323, 0x01ef4),CE(0x00301, 0x00179),CE(0x00302, 0x01e90),CE(0x00307, 0x0017b),CE(0x0030c, 0x0017d),CE(0x00323, 0x01e92),CE(0x00331, 0x01e94),CE(0x00300, 0x000e0),CE(0x00301, 0x000e1),CE(0x00302, 0x000e2),CE(0x00303, 0x000e3),CE(0x00304, 0x00101),CE(0x00306, 0x00103),CE(0x00307, 0x00227),CE(0x00308, 0x000e4),CE(0x00309, 0x01ea3),CE(0x0030a, 0x000e5),CE(0x0030c, 0x001ce),CE(0x0030f, 0x00201),CE(0x00311, 0x00203),CE(0x00323, 0x01ea1),CE(0x00325, 0x01e01),CE(0x00328, 0x00105),CE(0x00307, 0x01e03),CE(0x00323, 0x01e05),CE(0x00331, 0x01e07),CE(0x00301, 0x00107),CE(0x00302, 0x00109),CE(0x00307, 0x0010b),CE(0x0030c, 0x0010d),CE(0x00327, 0x000e7),CE(0x00307, 0x01e0b),CE(0x0030c, 0x0010f),CE(0x00323, 0x01e0d),CE(0x00327, 0x01e11),CE(0x0032d, 0x01e13),CE(0x00331, 0x01e0f),CE(0x00300, 0x000e8),CE(0x00301, 0x000e9),CE(0x00302, 0x000ea),CE(0x00303, 0x01ebd),CE(0x00304, 0x00113),CE(0x00306, 0x00115),CE(0x00307, 0x00117),CE(0x00308, 0x000eb),CE(0x00309, 0x01ebb),CE(0x0030c, 0x0011b),CE(0x0030f, 0x00205),CE(0x00311, 0x00207),CE(0x00323, 0x01eb9),CE(0x00327, 0x00229),CE(0x00328, 0x00119),CE(0x0032d, 0x01e19),CE(0x00330, 0x01e1b),CE(0x00307, 0x01e1f),CE(0x00301, 0x001f5),CE(0x00302, 0x0011d),CE(0x00304, 0x01e21),CE(0x00306, 0x0011f),CE(0x00307, 0x00121),CE(0x0030c, 0x001e7),CE(0x00327, 0x00123),CE(0x00302, 0x00125),CE(0x00307, 0x01e23),CE(0x00308, 0x01e27),CE(0x0030c, 0x0021f),CE(0x00323, 0x01e25),CE(0x00327, 0x01e29),CE(0x0032e, 0x01e2b),CE(0x00331, 0x01e96),CE(0x00300, 0x000ec),CE(0x00301, 0x000ed),CE(0x00302, 0x000ee),CE(0x00303, 0x00129),CE(0x00304, 0x0012b),CE(0x00306, 0x0012d),CE(0x00308, 0x000ef),CE(0x00309, 0x01ec9),CE(0x0030c, 0x001d0),CE(0x0030f, 0x00209),CE(0x00311, 0x0020b),CE(0x00323, 0x01ecb),CE(0x00328, 0x0012f),CE(0x00330, 0x01e2d),CE(0x00302, 0x00135),CE(0x0030c, 0x001f0),CE(0x00301, 0x01e31),CE(0x0030c, 0x001e9),CE(0x00323, 0x01e33),CE(0x00327, 0x00137),CE(0x00331, 0x01e35),CE(0x00301, 0x0013a),CE(0x0030c, 0x0013e),CE(0x00323, 0x01e37),CE(0x00327, 0x0013c),CE(0x0032d, 0x01e3d),CE(0x00331, 0x01e3b),CE(0x00301, 0x01e3f),CE(0x00307, 0x01e41),CE(0x00323, 0x01e43),CE(0x00300, 0x001f9),CE(0x00301, 0x00144),CE(0x00303, 0x000f1),CE(0x00307, 0x01e45),CE(0x0030c, 0x00148),CE(0x00323, 0x01e47),CE(0x00327, 0x00146),CE(0x0032d, 0x01e4b),CE(0x00331, 0x01e49),CE(0x00300, 0x000f2),CE(0x00301, 0x000f3),CE(0x00302, 0x000f4),CE(0x00303, 0x000f5),CE(0x00304, 0x0014d),CE(0x00306, 0x0014f),CE(0x00307, 0x0022f),CE(0x00308, 0x000f6),CE(0x00309, 0x01ecf),CE(0x0030b, 0x00151),CE(0x0030c, 0x001d2),CE(0x0030f, 0x0020d),CE(0x00311, 0x0020f),CE(0x0031b, 0x001a1),CE(0x00323, 0x01ecd),CE(0x00328, 0x001eb),CE(0x00301, 0x01e55),CE(0x00307, 0x01e57),CE(0x00301, 0x00155),CE(0x00307, 0x01e59),CE(0x0030c, 0x00159),CE(0x0030f, 0x00211),CE(0x00311, 0x00213),CE(0x00323, 0x01e5b),CE(0x00327, 0x00157),CE(0x00331, 0x01e5f),CE(0x00301, 0x0015b),CE(0x00302, 0x0015d),CE(0x00307, 0x01e61),CE(0x0030c, 0x00161),CE(0x00323, 0x01e63),CE(0x00326, 0x00219),CE(0x00327, 0x0015f),CE(0x00307, 0x01e6b),CE(0x00308, 0x01e97),CE(0x0030c, 0x00165),CE(0x00323, 0x01e6d),CE(0x00326, 0x0021b),CE(0x00327, 0x00163),CE(0x0032d, 0x01e71),CE(0x00331, 0x01e6f),CE(0x00300, 0x000f9),CE(0x00301, 0x000fa),CE(0x00302, 0x000fb),CE(0x00303, 0x00169),CE(0x00304, 0x0016b),CE(0x00306, 0x0016d),CE(0x00308, 0x000fc),CE(0x00309, 0x01ee7),CE(0x0030a, 0x0016f),CE(0x0030b, 0x00171),CE(0x0030c, 0x001d4),CE(0x0030f, 0x00215),CE(0x00311, 0x00217),CE(0x0031b, 0x001b0),CE(0x00323, 0x01ee5),CE(0x00324, 0x01e73),CE(0x00328, 0x00173),CE(0x0032d, 0x01e77),CE(0x00330, 0x01e75),CE(0x00303, 0x01e7d),CE(0x00323, 0x01e7f),CE(0x00300, 0x01e81),CE(0x00301, 0x01e83),CE(0x00302, 0x00175),CE(0x00307, 0x01e87),CE(0x00308, 0x01e85),CE(0x0030a, 0x01e98),CE(0x00323, 0x01e89),CE(0x00307, 0x01e8b),CE(0x00308, 0x01e8d),CE(0x00300, 0x01ef3),CE(0x00301, 0x000fd),CE(0x00302, 0x00177),CE(0x00303, 0x01ef9),CE(0x00304, 0x00233),CE(0x00307, 0x01e8f),CE(0x00308, 0x000ff),CE(0x00309, 0x01ef7),CE(0x0030a, 0x01e99),CE(0x00323, 0x01ef5),CE(0x00301, 0x0017a),CE(0x00302, 0x01e91),CE(0x00307, 0x0017c),CE(0x0030c, 0x0017e),CE(0x00323, 0x01e93),CE(0x00331, 0x01e95),CE(0x00300, 0x01fed),CE(0x00301, 0x00385),CE(0x00342, 0x01fc1),CE(0x00300, 0x01ea6),CE(0x00301, 0x01ea4),CE(0x00303, 0x01eaa),CE(0x00309, 0x01ea8),CE(0x00304, 0x001de),CE(0x00301, 0x001fa),CE(0x00301, 0x001fc),CE(0x00304, 0x001e2),CE(0x00301, 0x01e08),CE(0x00300, 0x01ec0),CE(0x00301, 0x01ebe),CE(0x00303, 0x01ec4),CE(0x00309, 0x01ec2),CE(0x00301, 0x01e2e),CE(0x00300, 0x01ed2),CE(0x00301, 0x01ed0),CE(0x00303, 0x01ed6),CE(0x00309, 0x01ed4),CE(0x00301, 0x01e4c),CE(0x00304, 0x0022c),CE(0x00308, 0x01e4e),CE(0x00304, 0x0022a),CE(0x00301, 0x001fe),CE(0x00300, 0x001db),CE(0x00301, 0x001d7),CE(0x00304, 0x001d5),CE(0x0030c, 0x001d9),CE(0x00300, 0x01ea7),CE(0x00301, 0x01ea5),CE(0x00303, 0x01eab),CE(0x00309, 0x01ea9),CE(0x00304, 0x001df),CE(0x00301, 0x001fb),CE(0x00301, 0x001fd),CE(0x00304, 0x001e3),CE(0x00301, 0x01e09),CE(0x00300, 0x01ec1),CE(0x00301, 0x01ebf),CE(0x00303, 0x01ec5),CE(0x00309, 0x01ec3),CE(0x00301, 0x01e2f),CE(0x00300, 0x01ed3),CE(0x00301, 0x01ed1),CE(0x00303, 0x01ed7),CE(0x00309, 0x01ed5),CE(0x00301, 0x01e4d),CE(0x00304, 0x0022d),CE(0x00308, 0x01e4f),CE(0x00304, 0x0022b),CE(0x00301, 0x001ff),CE(0x00300, 0x001dc),CE(0x00301, 0x001d8),CE(0x00304, 0x001d6),CE(0x0030c, 0x001da),CE(0x00300, 0x01eb0),CE(0x00301, 0x01eae),CE(0x00303, 0x01eb4),CE(0x00309, 0x01eb2),CE(0x00300, 0x01eb1),CE(0x00301, 0x01eaf),CE(0x00303, 0x01eb5),CE(0x00309, 0x01eb3),CE(0x00300, 0x01e14),CE(0x00301, 0x01e16),CE(0x00300, 0x01e15),CE(0x00301, 0x01e17),CE(0x00300, 0x01e50),CE(0x00301, 0x01e52),CE(0x00300, 0x01e51),CE(0x00301, 0x01e53),CE(0x00307, 0x01e64),CE(0x00307, 0x01e65),CE(0x00307, 0x01e66),CE(0x00307, 0x01e67),CE(0x00301, 0x01e78),CE(0x00301, 0x01e79),CE(0x00308, 0x01e7a),CE(0x00308, 0x01e7b),CE(0x00307, 0x01e9b),CE(0x00300, 0x01edc),CE(0x00301, 0x01eda),CE(0x00303, 0x01ee0),CE(0x00309, 0x01ede),CE(0x00323, 0x01ee2),CE(0x00300, 0x01edd),CE(0x00301, 0x01edb),CE(0x00303, 0x01ee1),CE(0x00309, 0x01edf),CE(0x00323, 0x01ee3),CE(0x00300, 0x01eea),CE(0x00301, 0x01ee8),CE(0x00303, 0x01eee),CE(0x00309, 0x01eec),CE(0x00323, 0x01ef0),CE(0x00300, 0x01eeb),CE(0x00301, 0x01ee9),CE(0x00303, 0x01eef),CE(0x00309, 0x01eed),CE(0x00323, 0x01ef1),CE(0x0030c, 0x001ee),CE(0x00304, 0x001ec),CE(0x00304, 0x001ed),CE(0x00304, 0x001e0),CE(0x00304, 0x001e1),CE(0x00306, 0x01e1c),CE(0x00306, 0x01e1d),CE(0x00304, 0x00230),CE(0x00304, 0x00231),CE(0x0030c, 0x001ef),CE(0x00300, 0x01fba),CE(0x00301, 0x00386),CE(0x00304, 0x01fb9),CE(0x00306, 0x01fb8),CE(0x00313, 0x01f08),CE(0x00314, 0x01f09),CE(0x00345, 0x01fbc),CE(0x00300, 0x01fc8),CE(0x00301, 0x00388),CE(0x00313, 0x01f18),CE(0x00314, 0x01f19),CE(0x00300, 0x01fca),CE(0x00301, 0x00389),CE(0x00313, 0x01f28),CE(0x00314, 0x01f29),CE(0x00345, 0x01fcc),CE(0x00300, 0x01fda),CE(0x00301, 0x0038a),CE(0x00304, 0x01fd9),CE(0x00306, 0x01fd8),CE(0x00308, 0x003aa),CE(0x00313, 0x01f38),CE(0x00314, 0x01f39),CE(0x00300, 0x01ff8),CE(0x00301, 0x0038c),CE(0x00313, 0x01f48),CE(0x00314, 0x01f49),CE(0x00314, 0x01fec),CE(0x00300, 0x01fea),CE(0x00301, 0x0038e),CE(0x00304, 0x01fe9),CE(0x00306, 0x01fe8),CE(0x00308, 0x003ab),CE(0x00314, 0x01f59),CE(0x00300, 0x01ffa),CE(0x00301, 0x0038f),CE(0x00313, 0x01f68),CE(0x00314, 0x01f69),CE(0x00345, 0x01ffc),CE(0x00345, 0x01fb4),CE(0x00345, 0x01fc4),CE(0x00300, 0x01f70),CE(0x00301, 0x003ac),CE(0x00304, 0x01fb1),CE(0x00306, 0x01fb0),CE(0x00313, 0x01f00),CE(0x00314, 0x01f01),CE(0x00342, 0x01fb6),CE(0x00345, 0x01fb3),CE(0x00300, 0x01f72),CE(0x00301, 0x003ad),CE(0x00313, 0x01f10),CE(0x00314, 0x01f11),CE(0x00300, 0x01f74),CE(0x00301, 0x003ae),CE(0x00313, 0x01f20),CE(0x00314, 0x01f21),CE(0x00342, 0x01fc6),CE(0x00345, 0x01fc3),CE(0x00300, 0x01f76),CE(0x00301, 0x003af),CE(0x00304, 0x01fd1),CE(0x00306, 0x01fd0),CE(0x00308, 0x003ca),CE(0x00313, 0x01f30),CE(0x00314, 0x01f31),CE(0x00342, 0x01fd6),CE(0x00300, 0x01f78),CE(0x00301, 0x003cc),CE(0x00313, 0x01f40),CE(0x00314, 0x01f41),CE(0x00313, 0x01fe4),CE(0x00314, 0x01fe5),CE(0x00300, 0x01f7a),CE(0x00301, 0x003cd),CE(0x00304, 0x01fe1),CE(0x00306, 0x01fe0),CE(0x00308, 0x003cb),CE(0x00313, 0x01f50),CE(0x00314, 0x01f51),CE(0x00342, 0x01fe6),CE(0x00300, 0x01f7c),CE(0x00301, 0x003ce),CE(0x00313, 0x01f60),CE(0x00314, 0x01f61),CE(0x00342, 0x01ff6),CE(0x00345, 0x01ff3),CE(0x00300, 0x01fd2),CE(0x00301, 0x00390),CE(0x00342, 0x01fd7),CE(0x00300, 0x01fe2),CE(0x00301, 0x003b0),CE(0x00342, 0x01fe7),CE(0x00345, 0x01ff4),CE(0x00301, 0x003d3),CE(0x00308, 0x003d4),CE(0x00308, 0x00407),CE(0x00306, 0x004d0),CE(0x00308, 0x004d2),CE(0x00301, 0x00403),CE(0x00300, 0x00400),CE(0x00306, 0x004d6),CE(0x00308, 0x00401),CE(0x00306, 0x004c1),CE(0x00308, 0x004dc),CE(0x00308, 0x004de),CE(0x00300, 0x0040d),CE(0x00304, 0x004e2),CE(0x00306, 0x00419),CE(0x00308, 0x004e4),CE(0x00301, 0x0040c),CE(0x00308, 0x004e6),CE(0x00304, 0x004ee),CE(0x00306, 0x0040e),CE(0x00308, 0x004f0),CE(0x0030b, 0x004f2),CE(0x00308, 0x004f4),CE(0x00308, 0x004f8),CE(0x00308, 0x004ec),CE(0x00306, 0x004d1),CE(0x00308, 0x004d3),CE(0x00301, 0x00453),CE(0x00300, 0x00450),CE(0x00306, 0x004d7),CE(0x00308, 0x00451),CE(0x00306, 0x004c2),CE(0x00308, 0x004dd),CE(0x00308, 0x004df),CE(0x00300, 0x0045d),CE(0x00304, 0x004e3),CE(0x00306, 0x00439),CE(0x00308, 0x004e5),CE(0x00301, 0x0045c),CE(0x00308, 0x004e7),CE(0x00304, 0x004ef),CE(0x00306, 0x0045e),CE(0x00308, 0x004f1),CE(0x0030b, 0x004f3),CE(0x00308, 0x004f5),CE(0x00308, 0x004f9),CE(0x00308, 0x004ed),CE(0x00308, 0x00457),CE(0x0030f, 0x00476),CE(0x0030f, 0x00477),CE(0x00308, 0x004da),CE(0x00308, 0x004db),CE(0x00308, 0x004ea),CE(0x00308, 0x004eb),CE(0x00653, 0x00622),CE(0x00654, 0x00623),CE(0x00655, 0x00625),CE(0x00654, 0x00624),CE(0x00654, 0x00626),CE(0x00654, 0x006c2),CE(0x00654, 0x006d3),CE(0x00654, 0x006c0),CE(0x0093c, 0x00929),CE(0x0093c, 0x00931),CE(0x0093c, 0x00934),CE(0x009be, 0x009cb),CE(0x009d7, 0x009cc),CE(0x00b3e, 0x00b4b),CE(0x00b56, 0x00b48),CE(0x00b57, 0x00b4c),CE(0x00bd7, 0x00b94),CE(0x00bbe, 0x00bca),CE(0x00bd7, 0x00bcc),CE(0x00bbe, 0x00bcb),CE(0x00c56, 0x00c48),CE(0x00cd5, 0x00cc0),CE(0x00cc2, 0x00cca),CE(0x00cd5, 0x00cc7),CE(0x00cd6, 0x00cc8),CE(0x00cd5, 0x00ccb),CE(0x00d3e, 0x00d4a),CE(0x00d57, 0x00d4c),CE(0x00d3e, 0x00d4b),CE(0x00dca, 0x00dda),CE(0x00dcf, 0x00ddc),CE(0x00ddf, 0x00dde),CE(0x00dca, 0x00ddd),CE(0x0102e, 0x01026),CE(0x01b35, 0x01b06),CE(0x01b35, 0x01b08),CE(0x01b35, 0x01b0a),CE(0x01b35, 0x01b0c),CE(0x01b35, 0x01b0e),CE(0x01b35, 0x01b12),CE(0x01b35, 0x01b3b),CE(0x01b35, 0x01b3d),CE(0x01b35, 0x01b40),CE(0x01b35, 0x01b41),CE(0x01b35, 0x01b43),CE(0x00304, 0x01e38),CE(0x00304, 0x01e39),CE(0x00304, 0x01e5c),CE(0x00304, 0x01e5d),CE(0x00307, 0x01e68),CE(0x00307, 0x01e69),CE(0x00302, 0x01eac),CE(0x00306, 0x01eb6),CE(0x00302, 0x01ead),CE(0x00306, 0x01eb7),CE(0x00302, 0x01ec6),CE(0x00302, 0x01ec7),CE(0x00302, 0x01ed8),CE(0x00302, 0x01ed9),CE(0x00300, 0x01f02),CE(0x00301, 0x01f04),CE(0x00342, 0x01f06),CE(0x00345, 0x01f80),CE(0x00300, 0x01f03),CE(0x00301, 0x01f05),CE(0x00342, 0x01f07),CE(0x00345, 0x01f81),CE(0x00345, 0x01f82),CE(0x00345, 0x01f83),CE(0x00345, 0x01f84),CE(0x00345, 0x01f85),CE(0x00345, 0x01f86),CE(0x00345, 0x01f87),CE(0x00300, 0x01f0a),CE(0x00301, 0x01f0c),CE(0x00342, 0x01f0e),CE(0x00345, 0x01f88),CE(0x00300, 0x01f0b),CE(0x00301, 0x01f0d),CE(0x00342, 0x01f0f),CE(0x00345, 0x01f89),CE(0x00345, 0x01f8a),CE(0x00345, 0x01f8b),CE(0x00345, 0x01f8c),CE(0x00345, 0x01f8d),CE(0x00345, 0x01f8e),CE(0x00345, 0x01f8f),CE(0x00300, 0x01f12),CE(0x00301, 0x01f14),CE(0x00300, 0x01f13),CE(0x00301, 0x01f15),CE(0x00300, 0x01f1a),CE(0x00301, 0x01f1c),CE(0x00300, 0x01f1b),CE(0x00301, 0x01f1d),CE(0x00300, 0x01f22),CE(0x00301, 0x01f24),CE(0x00342, 0x01f26),CE(0x00345, 0x01f90),CE(0x00300, 0x01f23),CE(0x00301, 0x01f25),CE(0x00342, 0x01f27),CE(0x00345, 0x01f91),CE(0x00345, 0x01f92),CE(0x00345, 0x01f93),CE(0x00345, 0x01f94),CE(0x00345, 0x01f95),CE(0x00345, 0x01f96),CE(0x00345, 0x01f97),CE(0x00300, 0x01f2a),CE(0x00301, 0x01f2c),CE(0x00342, 0x01f2e),CE(0x00345, 0x01f98),CE(0x00300, 0x01f2b),CE(0x00301, 0x01f2d),CE(0x00342, 0x01f2f),CE(0x00345, 0x01f99),CE(0x00345, 0x01f9a),CE(0x00345, 0x01f9b),CE(0x00345, 0x01f9c),CE(0x00345, 0x01f9d),CE(0x00345, 0x01f9e),CE(0x00345, 0x01f9f),CE(0x00300, 0x01f32),CE(0x00301, 0x01f34),CE(0x00342, 0x01f36),CE(0x00300, 0x01f33),CE(0x00301, 0x01f35),CE(0x00342, 0x01f37),CE(0x00300, 0x01f3a),CE(0x00301, 0x01f3c),CE(0x00342, 0x01f3e),CE(0x00300, 0x01f3b),CE(0x00301, 0x01f3d),CE(0x00342, 0x01f3f),CE(0x00300, 0x01f42),CE(0x00301, 0x01f44),CE(0x00300, 0x01f43),CE(0x00301, 0x01f45),CE(0x00300, 0x01f4a),CE(0x00301, 0x01f4c),CE(0x00300, 0x01f4b),CE(0x00301, 0x01f4d),CE(0x00300, 0x01f52),CE(0x00301, 0x01f54),CE(0x00342, 0x01f56),CE(0x00300, 0x01f53),CE(0x00301, 0x01f55),CE(0x00342, 0x01f57),CE(0x00300, 0x01f5b),CE(0x00301, 0x01f5d),CE(0x00342, 0x01f5f),CE(0x00300, 0x01f62),CE(0x00301, 0x01f64),CE(0x00342, 0x01f66),CE(0x00345, 0x01fa0),CE(0x00300, 0x01f63),CE(0x00301, 0x01f65),CE(0x00342, 0x01f67),CE(0x00345, 0x01fa1),CE(0x00345, 0x01fa2),CE(0x00345, 0x01fa3),CE(0x00345, 0x01fa4),CE(0x00345, 0x01fa5),CE(0x00345, 0x01fa6),CE(0x00345, 0x01fa7),CE(0x00300, 0x01f6a),CE(0x00301, 0x01f6c),CE(0x00342, 0x01f6e),CE(0x00345, 0x01fa8),CE(0x00300, 0x01f6b),CE(0x00301, 0x01f6d),CE(0x00342, 0x01f6f),CE(0x00345, 0x01fa9),CE(0x00345, 0x01faa),CE(0x00345, 0x01fab),CE(0x00345, 0x01fac),CE(0x00345, 0x01fad),CE(0x00345, 0x01fae),CE(0x00345, 0x01faf),CE(0x00345, 0x01fb2),CE(0x00345, 0x01fc2),CE(0x00345, 0x01ff2),CE(0x00345, 0x01fb7),CE(0x00300, 0x01fcd),CE(0x00301, 0x01fce),CE(0x00342, 0x01fcf),CE(0x00345, 0x01fc7),CE(0x00345, 0x01ff7),CE(0x00300, 0x01fdd),CE(0x00301, 0x01fde),CE(0x00342, 0x01fdf),CE(0x00338, 0x0219a),CE(0x00338, 0x0219b),CE(0x00338, 0x021ae),CE(0x00338, 0x021cd),CE(0x00338, 0x021cf),CE(0x00338, 0x021ce),CE(0x00338, 0x02204),CE(0x00338, 0x02209),CE(0x00338, 0x0220c),CE(0x00338, 0x02224),CE(0x00338, 0x02226),CE(0x00338, 0x02241),CE(0x00338, 0x02244),CE(0x00338, 0x02247),CE(0x00338, 0x02249),CE(0x00338, 0x0226d),CE(0x00338, 0x02262),CE(0x00338, 0x02270),CE(0x00338, 0x02271),CE(0x00338, 0x02274),CE(0x00338, 0x02275),CE(0x00338, 0x02278),CE(0x00338, 0x02279),CE(0x00338, 0x02280),CE(0x00338, 0x02281),CE(0x00338, 0x022e0),CE(0x00338, 0x022e1),CE(0x00338, 0x02284),CE(0x00338, 0x02285),CE(0x00338, 0x02288),CE(0x00338, 0x02289),CE(0x00338, 0x022e2),CE(0x00338, 0x022e3),CE(0x00338, 0x022ac),CE(0x00338, 0x022ad),CE(0x00338, 0x022ae),CE(0x00338, 0x022af),CE(0x00338, 0x022ea),CE(0x00338, 0x022eb),CE(0x00338, 0x022ec),CE(0x00338, 0x022ed),CE(0x03099, 0x03094),CE(0x03099, 0x0304c),CE(0x03099, 0x0304e),CE(0x03099, 0x03050),CE(0x03099, 0x03052),CE(0x03099, 0x03054),CE(0x03099, 0x03056),CE(0x03099, 0x03058),CE(0x03099, 0x0305a),CE(0x03099, 0x0305c),CE(0x03099, 0x0305e),CE(0x03099, 0x03060),CE(0x03099, 0x03062),CE(0x03099, 0x03065),CE(0x03099, 0x03067),CE(0x03099, 0x03069),CE(0x03099, 0x03070),CE(0x0309a, 0x03071),CE(0x03099, 0x03073),CE(0x0309a, 0x03074),CE(0x03099, 0x03076),CE(0x0309a, 0x03077),CE(0x03099, 0x03079),CE(0x0309a, 0x0307a),CE(0x03099, 0x0307c),CE(0x0309a, 0x0307d),CE(0x03099, 0x0309e),CE(0x03099, 0x030f4),CE(0x03099, 0x030ac),CE(0x03099, 0x030ae),CE(0x03099, 0x030b0),CE(0x03099, 0x030b2),CE(0x03099, 0x030b4),CE(0x03099, 0x030b6),CE(0x03099, 0x030b8),CE(0x03099, 0x030ba),CE(0x03099, 0x030bc),CE(0x03099, 0x030be),CE(0x03099, 0x030c0),CE(0x03099, 0x030c2),CE(0x03099, 0x030c5),CE(0x03099, 0x030c7),CE(0x03099, 0x030c9),CE(0x03099, 0x030d0),CE(0x0309a, 0x030d1),CE(0x03099, 0x030d3),CE(0x0309a, 0x030d4),CE(0x03099, 0x030d6),CE(0x0309a, 0x030d7),CE(0x03099, 0x030d9),CE(0x0309a, 0x030da),CE(0x03099, 0x030dc),CE(0x0309a, 0x030dd),CE(0x03099, 0x030f7),CE(0x03099, 0x030f8),CE(0x03099, 0x030f9),CE(0x03099, 0x030fa),CE(0x03099, 0x030fe),CE(0x110ba, 0x1109a),CE(0x110ba, 0x1109c),CE(0x110ba, 0x110ab),CE(0x11127, 0x1112e),CE(0x11127, 0x1112f),];
+return t;
+}
+
+}
+
+
+static if(size_t.sizeof == 4) {
+//6976 bytes
+enum combiningClassTrieEntries = TrieEntry!(ubyte, 8, 7, 6)([ 0x0,  0x40,  0x240], [ 0x100,  0x400,  0x1240], [ 0x2020100,  0x4020302,  0x2020205,  0x2060202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x20001,  0x0,  0x0,  0x3,  0x0,  0x50004,  0x70006,  0x80000,  0xa0009,  0xb0000,  0xd000c,  0xe0000,  0x10000f,  0x11000f,  0x11000f,  0x11000f,  0x11000f,  0x110000,  0x120000,  0x11000f,  0x110000,  0x130000,  0x150014,  0x170016,  0x190018,  0x1b001a,  0x1c,  0x1d,  0x0,  0x0,  0x0,  0x0,  0x1e0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1f,  0x200000,  0x0,  0x21,  0x22,  0x0,  0x240023,  0x0,  0x260025,  0x280027,  0x29,  0x2a0000,  0x0,  0x2b0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2c0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2d0000,  0x2e0000,  0x2f0000,  0x0,  0x0,  0x0,  0x0,  0x30,  0x31,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x320000,  0x340033,  0x0,  0x0,  0x35,  0x360000,  0x380037,  0x3a0039,  0x0,  0x3c003b,  0x0,  0x3d0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x400000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x41,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x350000,  0x42,  0x43,  0x3a0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x44,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x450000,  0x46,  0x470000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6e6e6e6,  0xe6e6e6e6,  0xe6e6e6e6,  0xe6e6e6e6,  0xe6e6e6e6,  0xdcdce8e6,  0xd8e8dcdc,  0xdcdcdcdc,  0xdccacadc,  0xcadcdcdc,  0xdcdcdcca,  0xdcdcdcdc,  0xdcdcdcdc,  0x1010101,  0xdcdcdc01,  0xe6e6e6dc,  0xe6e6e6e6,  0xdce6f0e6,  0xe6e6dcdc,  0xdcdce6,  0xdce6e6e6,  0xe6dcdcdc,  0xe6dcdce8,  0xe9eaeae9,  0xe6e9eaea,  0xe6e6e6e6,  0xe6e6e6e6,  0xe6e6e6e6,  0x0,  0x0,  0x0,  0x0,  0xe6000000,  0xe6e6e6e6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6e6dc00,  0xe6dce6e6,  0xdcdee6e6,  0xe6e6e6e6,  0xdcdce6e6,  0xdcdcdcdc,  0xe6dce6e6,  0xe6e4dee6,  0xd0c0b0a,  0x11100f0e,  0x14131312,  0x17001615,  0x191800,  0x1200dce6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6e6e6e6,  0xe6e6e6e6,  0x201f1e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1b000000,  0x1f1e1d1c,  0xe6222120,  0xe6dcdce6,  0xe6e6e6e6,  0xdce6e6dc,  0x0,  0x0,  0x0,  0x0,  0x23,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6e60000,  0xe6e6e6e6,  0xe60000e6,  0xdce6e6e6,  0xe60000e6,  0xe6dc00e6,  0xdce6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2400,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6e6dce6,  0xdce6e6dc,  0xdce6dcdc,  0xe6dce6dc,  0xe6dce6e6,  0xe6dce6dc,  0xe6e6dc,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6000000,  0xe6e6e6e6,  0xe6dce6e6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6e60000,  0xe600e6e6,  0xe6e6e6e6,  0xe6e6e6e6,  0xe6e6e600,  0xe6e6e600,  0xe6e6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xdcdcdc00,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6dce6e6,  0xe6e6dce6,  0xdcdcdce6,  0xe61d1c1b,  0xe6dce6e6,  0xe6dcdce6,  0xe6e6e6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7,  0x0,  0x0,  0x0,  0x900,  0xe6dce600,  0xe6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x900,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x900,  0x0,  0x5b5400,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x90000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x96767,  0x0,  0x0,  0x0,  0x6b6b6b6b,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7676,  0x0,  0x0,  0x0,  0x7a7a7a7a,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xdcdc,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xdc00dc00,  0xd800,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x828100,  0x84,  0x82820000,  0x8282,  0xe6e60082,  0xe6e60009,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xdc0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7000000,  0x90900,  0x0,  0x0,  0x0,  0x0,  0xdc00,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6e6e600,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x9,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x9,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x90000,  0x0,  0x0,  0xe600,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe400,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xdce6de00,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6000000,  0xdc,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x9,  0x0,  0x0,  0x0,  0x0,  0xe6e6e600,  0xe6e6e6e6,  0xdc0000e6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7,  0x0,  0x0,  0x0,  0x9,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6000000,  0xe6e6e6dc,  0xe6e6e6e6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x9090000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x70000,  0x0,  0x0,  0x9090000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6e6e6,  0xdcdcdc01,  0xe6e6dcdc,  0xdcdcdcdc,  0x10100e6,  0x1010101,  0x1,  0xdc00,  0x0,  0xe6,  0x0,  0x0,  0xe6dce6e6,  0xe6e6e6e6,  0xe6dce6e6,  0xdcd6eae6,  0xe6e6e6ca,  0xe6e6e6e6,  0xe6e6e6e6,  0xe6e6e6e6,  0xe6e6e6e6,  0xe6e6e6,  0x0,  0x0,  0x0,  0x0,  0x0,  0xdce6dce9,  0x0,  0x0,  0x0,  0x0,  0x101e6e6,  0xe6e6e6e6,  0xe6010101,  0xe6,  0xe600,  0xe6010100,  0x101e6dc,  0xdcdcdcdc,  0xe6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6000000,  0xe6e6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x9000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6e6e6e6,  0xe6e6e6e6,  0xe6e6e6e6,  0xe6e6e6e6,  0xe6e6e6e6,  0xe6e6e6e6,  0xe6e6e6e6,  0xe6e6e6e6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe4da0000,  0xe0e0dee8,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x80800,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6000000,  0x0,  0xe6e6e6e6,  0xe6e6e6e6,  0xe6e6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6e6,  0x0,  0x0,  0x0,  0x0,  0x90000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x9,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6e6e6e6,  0xe6e6e6e6,  0xe6e6e6e6,  0xe6e6e6e6,  0xe6e6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xdc000000,  0xdcdc,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x9000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7000000,  0x0,  0x0,  0x0,  0x9,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6e600e6,  0xe60000dc,  0xe6,  0xe6e60000,  0xe600,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x90000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x900,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1a0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6e6e6e6,  0xe6e6e6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xdc00,  0x0,  0x0,  0x0,  0xe600dc00,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xdc01e6,  0x9000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x70900,  0x0,  0xe6e6e6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x9000000,  0x9,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7090000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1d8d800,  0x101,  0xd8d8e200,  0xd8d8d8,  0x0,  0xdc000000,  0xdcdcdcdc,  0xdcdcdc,  0xe6e6e600,  0xdcdce6e6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe6e60000,  0xe6e6,  0x0,  0x0,  0x0,  0x0,  0xe6e60000,  0xe6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+enum composeIdxMask = (1<<11)-1, composeCntShift = 11;
+enum compositionJumpTrieEntries = TrieEntry!(ushort, 12, 9)([ 0x0,  0x800], [ 0x1000,  0x2000], [ 0x10000,  0x30002,  0x50004,  0x70006,  0x70008,  0x70007,  0x90007,  0xa0007,  0xc000b,  0x70007,  0x70007,  0x70007,  0x7000d,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x7000e,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x8010800,  0xffff0802,  0x8003ffff,  0x28161813,  0x8821301b,  0x38330832,  0x7841383a,  0x28510850,  0x185c3056,  0x8068485f,  0xffff1078,  0x3882407a,  0x98903889,  0x30a510a3,  0x48ad10ab,  0xffff30b6,  0xffffffff,  0xffffffff,  0x80bcffff,  0x28cf18cc,  0x88da30d4,  0x38ec08eb,  0x70fb40f3,  0x290b1109,  0x19163110,  0x81224919,  0xffff1132,  0x393c4134,  0x994b4143,  0x3960115e,  0x51691167,  0xffff3173,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff1979,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff217c,  0x9810980,  0x9841182,  0xffffffff,  0xffff2185,  0xffffffff,  0x989ffff,  0xffffffff,  0xffffffff,  0x198e218a,  0xffff0991,  0xffff0992,  0xffffffff,  0xffff2193,  0xffffffff,  0xffffffff,  0xffff2197,  0x99c099b,  0x99f119d,  0xffffffff,  0xffff21a0,  0xffffffff,  0x9a4ffff,  0xffffffff,  0xffffffff,  0x19a921a5,  0xffff09ac,  0xffff09ad,  0xffffffff,  0xffff21ae,  0xffffffff,  0xffffffff,  0x21b621b2,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x11bc11ba,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x11c011be,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x9c309c2,  0xffffffff,  0xffffffff,  0x9c509c4,  0xffffffff,  0xffffffff,  0xffffffff,  0x9c709c6,  0x9c909c8,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x9caffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x29d029cb,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x29d5ffff,  0xffff29da,  0xffffffff,  0xffffffff,  0x9dfffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x9e109e0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x9e309e2,  0x9e509e4,  0xffffffff,  0xffffffff,  0x9e709e6,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff09e8,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x39e9ffff,  0xffffffff,  0x21f0ffff,  0x29f4ffff,  0x39f9ffff,  0xffffffff,  0xffffffff,  0x2200ffff,  0xa04ffff,  0xffffffff,  0x3205ffff,  0xffffffff,  0x2a0bffff,  0xffffffff,  0xffff0a10,  0xffff0a11,  0x4212ffff,  0xffffffff,  0x221affff,  0x321effff,  0x4224ffff,  0xffffffff,  0xffffffff,  0x222cffff,  0x1230ffff,  0xffffffff,  0x4232ffff,  0xffffffff,  0x323affff,  0x1a431a40,  0xffffffff,  0xffff0a46,  0xffffffff,  0xffff1247,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0a49,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff124a,  0xa4cffff,  0x1a4dffff,  0xa521250,  0xffff2253,  0xffff0a57,  0xffffffff,  0xffff0a58,  0xffffffff,  0x2259ffff,  0xffffffff,  0xa5dffff,  0xffffffff,  0xa5effff,  0xa5fffff,  0xffffffff,  0xffff1260,  0xa62ffff,  0x1a63ffff,  0xa681266,  0xffff2269,  0xffff0a6d,  0xffffffff,  0xffff0a6e,  0xffffffff,  0x226fffff,  0xffffffff,  0xa73ffff,  0xffffffff,  0xa74ffff,  0xa75ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0a76,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xa780a77,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xa7a0a79,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xa7c0a7b,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x1a7dffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0a80,  0xffff0a81,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xa82ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0a83,  0xa84ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0a85,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0a86,  0xa87ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x1288ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x1a8affff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0a8d,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xa90128e,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0a91,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xa92ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff1a93,  0xffffffff,  0xffff0a96,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xa991297,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x1a9affff,  0xffffffff,  0xffff0a9d,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xa9effff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xa9fffff,  0xaa0ffff,  0xaa1ffff,  0xaa2ffff,  0xaa3ffff,  0xffffffff,  0xaa4ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0aa5,  0xffff0aa6,  0xaa80aa7,  0xffffffff,  0xffff0aa9,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xaab0aaa,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xaad0aac,  0xffffffff,  0xffffffff,  0xffffffff,  0xaaf0aae,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x12b212b0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xab50ab4,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xab70ab6,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x22bc22b8,  0xac10ac0,  0xac30ac2,  0xac50ac4,  0x22ca22c6,  0xacf0ace,  0xad10ad0,  0xad30ad2,  0x12d612d4,  0xffffffff,  0xffffffff,  0xffffffff,  0x12da12d8,  0xffffffff,  0xffffffff,  0xffffffff,  0x22e022dc,  0xae50ae4,  0xae70ae6,  0xae90ae8,  0x22ee22ea,  0xaf30af2,  0xaf50af4,  0xaf70af6,  0x1afb1af8,  0xffffffff,  0xffffffff,  0xffffffff,  0x1b011afe,  0xffffffff,  0xffffffff,  0xffffffff,  0x13061304,  0xffffffff,  0xffffffff,  0xffffffff,  0x130a1308,  0xffffffff,  0xffffffff,  0xffffffff,  0x1b0f1b0c,  0xffffffff,  0xffffffff,  0xffffffff,  0x1b12ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x23192315,  0xb1e0b1d,  0xb200b1f,  0xb220b21,  0x23272323,  0xb2c0b2b,  0xb2e0b2d,  0xb300b2f,  0xffff0b31,  0xffffffff,  0xffff0b32,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0b33,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0b34,  0xffffffff,  0xffffffff,  0xffffffff,  0x1b35ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0b38,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0b39,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff1b3a,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0b3d,  0xffff0b3e,  0xffff0b3f,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0b40,  0xffff0b41,  0xffff0b42,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xb43ffff,  0xffffffff,  0xffffffff,  0xffff0b44,  0xb45ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xb46ffff,  0xb47ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0b48,  0xffffffff,  0xffffffff,  0xb49ffff,  0xb4affff,  0xffffffff,  0xffff0b4b,  0xffffffff,  0xb4cffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xb4dffff,  0xffffffff,  0xb4f0b4e,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xb510b50,  0xffffffff,  0xb530b52,  0xffffffff,  0xb550b54,  0xb570b56,  0xffffffff,  0xffffffff,  0xb590b58,  0xffffffff,  0xb5b0b5a,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xb5cffff,  0xffff0b5d,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0b5e,  0xffffffff,  0xffffffff,  0xb600b5f,  0xb61ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xb630b62,  0xb650b64,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0b66,  0xffffffff,  0xb67ffff,  0xb68ffff,  0xb69ffff,  0xb6affff,  0xb6bffff,  0xb6cffff,  0xb6dffff,  0xb6effff,  0xb6fffff,  0xb70ffff,  0xb71ffff,  0xb72ffff,  0xffffffff,  0xffff0b73,  0xffff0b74,  0xffff0b75,  0xffffffff,  0xffffffff,  0x1376ffff,  0xffffffff,  0xffff1378,  0x137affff,  0xffffffff,  0xffff137c,  0x137effff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xb80ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0b81,  0xffffffff,  0xb82ffff,  0xb83ffff,  0xb84ffff,  0xb85ffff,  0xb86ffff,  0xb87ffff,  0xb88ffff,  0xb89ffff,  0xb8affff,  0xb8bffff,  0xb8cffff,  0xb8dffff,  0xffffffff,  0xffff0b8e,  0xffff0b8f,  0xffff0b90,  0xffffffff,  0xffffffff,  0x1391ffff,  0xffffffff,  0xffff1393,  0x1395ffff,  0xffffffff,  0xffff1397,  0x1399ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xb9bffff,  0xb9d0b9c,  0xffff0b9e,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xb9fffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xba0ffff,  0xba1ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xba2ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xba3ffff,  0xffff0ba4,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff]);
+@property immutable(CompEntry[]) compositionTable()
+{
+alias CE = CompEntry;
+static immutable CE[] t = [CE(0x00338, 0x0226e),CE(0x00338, 0x02260),CE(0x00338, 0x0226f),CE(0x00300, 0x000c0),CE(0x00301, 0x000c1),CE(0x00302, 0x000c2),CE(0x00303, 0x000c3),CE(0x00304, 0x00100),CE(0x00306, 0x00102),CE(0x00307, 0x00226),CE(0x00308, 0x000c4),CE(0x00309, 0x01ea2),CE(0x0030a, 0x000c5),CE(0x0030c, 0x001cd),CE(0x0030f, 0x00200),CE(0x00311, 0x00202),CE(0x00323, 0x01ea0),CE(0x00325, 0x01e00),CE(0x00328, 0x00104),CE(0x00307, 0x01e02),CE(0x00323, 0x01e04),CE(0x00331, 0x01e06),CE(0x00301, 0x00106),CE(0x00302, 0x00108),CE(0x00307, 0x0010a),CE(0x0030c, 0x0010c),CE(0x00327, 0x000c7),CE(0x00307, 0x01e0a),CE(0x0030c, 0x0010e),CE(0x00323, 0x01e0c),CE(0x00327, 0x01e10),CE(0x0032d, 0x01e12),CE(0x00331, 0x01e0e),CE(0x00300, 0x000c8),CE(0x00301, 0x000c9),CE(0x00302, 0x000ca),CE(0x00303, 0x01ebc),CE(0x00304, 0x00112),CE(0x00306, 0x00114),CE(0x00307, 0x00116),CE(0x00308, 0x000cb),CE(0x00309, 0x01eba),CE(0x0030c, 0x0011a),CE(0x0030f, 0x00204),CE(0x00311, 0x00206),CE(0x00323, 0x01eb8),CE(0x00327, 0x00228),CE(0x00328, 0x00118),CE(0x0032d, 0x01e18),CE(0x00330, 0x01e1a),CE(0x00307, 0x01e1e),CE(0x00301, 0x001f4),CE(0x00302, 0x0011c),CE(0x00304, 0x01e20),CE(0x00306, 0x0011e),CE(0x00307, 0x00120),CE(0x0030c, 0x001e6),CE(0x00327, 0x00122),CE(0x00302, 0x00124),CE(0x00307, 0x01e22),CE(0x00308, 0x01e26),CE(0x0030c, 0x0021e),CE(0x00323, 0x01e24),CE(0x00327, 0x01e28),CE(0x0032e, 0x01e2a),CE(0x00300, 0x000cc),CE(0x00301, 0x000cd),CE(0x00302, 0x000ce),CE(0x00303, 0x00128),CE(0x00304, 0x0012a),CE(0x00306, 0x0012c),CE(0x00307, 0x00130),CE(0x00308, 0x000cf),CE(0x00309, 0x01ec8),CE(0x0030c, 0x001cf),CE(0x0030f, 0x00208),CE(0x00311, 0x0020a),CE(0x00323, 0x01eca),CE(0x00328, 0x0012e),CE(0x00330, 0x01e2c),CE(0x00302, 0x00134),CE(0x00301, 0x01e30),CE(0x0030c, 0x001e8),CE(0x00323, 0x01e32),CE(0x00327, 0x00136),CE(0x00331, 0x01e34),CE(0x00301, 0x00139),CE(0x0030c, 0x0013d),CE(0x00323, 0x01e36),CE(0x00327, 0x0013b),CE(0x0032d, 0x01e3c),CE(0x00331, 0x01e3a),CE(0x00301, 0x01e3e),CE(0x00307, 0x01e40),CE(0x00323, 0x01e42),CE(0x00300, 0x001f8),CE(0x00301, 0x00143),CE(0x00303, 0x000d1),CE(0x00307, 0x01e44),CE(0x0030c, 0x00147),CE(0x00323, 0x01e46),CE(0x00327, 0x00145),CE(0x0032d, 0x01e4a),CE(0x00331, 0x01e48),CE(0x00300, 0x000d2),CE(0x00301, 0x000d3),CE(0x00302, 0x000d4),CE(0x00303, 0x000d5),CE(0x00304, 0x0014c),CE(0x00306, 0x0014e),CE(0x00307, 0x0022e),CE(0x00308, 0x000d6),CE(0x00309, 0x01ece),CE(0x0030b, 0x00150),CE(0x0030c, 0x001d1),CE(0x0030f, 0x0020c),CE(0x00311, 0x0020e),CE(0x0031b, 0x001a0),CE(0x00323, 0x01ecc),CE(0x00328, 0x001ea),CE(0x00301, 0x01e54),CE(0x00307, 0x01e56),CE(0x00301, 0x00154),CE(0x00307, 0x01e58),CE(0x0030c, 0x00158),CE(0x0030f, 0x00210),CE(0x00311, 0x00212),CE(0x00323, 0x01e5a),CE(0x00327, 0x00156),CE(0x00331, 0x01e5e),CE(0x00301, 0x0015a),CE(0x00302, 0x0015c),CE(0x00307, 0x01e60),CE(0x0030c, 0x00160),CE(0x00323, 0x01e62),CE(0x00326, 0x00218),CE(0x00327, 0x0015e),CE(0x00307, 0x01e6a),CE(0x0030c, 0x00164),CE(0x00323, 0x01e6c),CE(0x00326, 0x0021a),CE(0x00327, 0x00162),CE(0x0032d, 0x01e70),CE(0x00331, 0x01e6e),CE(0x00300, 0x000d9),CE(0x00301, 0x000da),CE(0x00302, 0x000db),CE(0x00303, 0x00168),CE(0x00304, 0x0016a),CE(0x00306, 0x0016c),CE(0x00308, 0x000dc),CE(0x00309, 0x01ee6),CE(0x0030a, 0x0016e),CE(0x0030b, 0x00170),CE(0x0030c, 0x001d3),CE(0x0030f, 0x00214),CE(0x00311, 0x00216),CE(0x0031b, 0x001af),CE(0x00323, 0x01ee4),CE(0x00324, 0x01e72),CE(0x00328, 0x00172),CE(0x0032d, 0x01e76),CE(0x00330, 0x01e74),CE(0x00303, 0x01e7c),CE(0x00323, 0x01e7e),CE(0x00300, 0x01e80),CE(0x00301, 0x01e82),CE(0x00302, 0x00174),CE(0x00307, 0x01e86),CE(0x00308, 0x01e84),CE(0x00323, 0x01e88),CE(0x00307, 0x01e8a),CE(0x00308, 0x01e8c),CE(0x00300, 0x01ef2),CE(0x00301, 0x000dd),CE(0x00302, 0x00176),CE(0x00303, 0x01ef8),CE(0x00304, 0x00232),CE(0x00307, 0x01e8e),CE(0x00308, 0x00178),CE(0x00309, 0x01ef6),CE(0x00323, 0x01ef4),CE(0x00301, 0x00179),CE(0x00302, 0x01e90),CE(0x00307, 0x0017b),CE(0x0030c, 0x0017d),CE(0x00323, 0x01e92),CE(0x00331, 0x01e94),CE(0x00300, 0x000e0),CE(0x00301, 0x000e1),CE(0x00302, 0x000e2),CE(0x00303, 0x000e3),CE(0x00304, 0x00101),CE(0x00306, 0x00103),CE(0x00307, 0x00227),CE(0x00308, 0x000e4),CE(0x00309, 0x01ea3),CE(0x0030a, 0x000e5),CE(0x0030c, 0x001ce),CE(0x0030f, 0x00201),CE(0x00311, 0x00203),CE(0x00323, 0x01ea1),CE(0x00325, 0x01e01),CE(0x00328, 0x00105),CE(0x00307, 0x01e03),CE(0x00323, 0x01e05),CE(0x00331, 0x01e07),CE(0x00301, 0x00107),CE(0x00302, 0x00109),CE(0x00307, 0x0010b),CE(0x0030c, 0x0010d),CE(0x00327, 0x000e7),CE(0x00307, 0x01e0b),CE(0x0030c, 0x0010f),CE(0x00323, 0x01e0d),CE(0x00327, 0x01e11),CE(0x0032d, 0x01e13),CE(0x00331, 0x01e0f),CE(0x00300, 0x000e8),CE(0x00301, 0x000e9),CE(0x00302, 0x000ea),CE(0x00303, 0x01ebd),CE(0x00304, 0x00113),CE(0x00306, 0x00115),CE(0x00307, 0x00117),CE(0x00308, 0x000eb),CE(0x00309, 0x01ebb),CE(0x0030c, 0x0011b),CE(0x0030f, 0x00205),CE(0x00311, 0x00207),CE(0x00323, 0x01eb9),CE(0x00327, 0x00229),CE(0x00328, 0x00119),CE(0x0032d, 0x01e19),CE(0x00330, 0x01e1b),CE(0x00307, 0x01e1f),CE(0x00301, 0x001f5),CE(0x00302, 0x0011d),CE(0x00304, 0x01e21),CE(0x00306, 0x0011f),CE(0x00307, 0x00121),CE(0x0030c, 0x001e7),CE(0x00327, 0x00123),CE(0x00302, 0x00125),CE(0x00307, 0x01e23),CE(0x00308, 0x01e27),CE(0x0030c, 0x0021f),CE(0x00323, 0x01e25),CE(0x00327, 0x01e29),CE(0x0032e, 0x01e2b),CE(0x00331, 0x01e96),CE(0x00300, 0x000ec),CE(0x00301, 0x000ed),CE(0x00302, 0x000ee),CE(0x00303, 0x00129),CE(0x00304, 0x0012b),CE(0x00306, 0x0012d),CE(0x00308, 0x000ef),CE(0x00309, 0x01ec9),CE(0x0030c, 0x001d0),CE(0x0030f, 0x00209),CE(0x00311, 0x0020b),CE(0x00323, 0x01ecb),CE(0x00328, 0x0012f),CE(0x00330, 0x01e2d),CE(0x00302, 0x00135),CE(0x0030c, 0x001f0),CE(0x00301, 0x01e31),CE(0x0030c, 0x001e9),CE(0x00323, 0x01e33),CE(0x00327, 0x00137),CE(0x00331, 0x01e35),CE(0x00301, 0x0013a),CE(0x0030c, 0x0013e),CE(0x00323, 0x01e37),CE(0x00327, 0x0013c),CE(0x0032d, 0x01e3d),CE(0x00331, 0x01e3b),CE(0x00301, 0x01e3f),CE(0x00307, 0x01e41),CE(0x00323, 0x01e43),CE(0x00300, 0x001f9),CE(0x00301, 0x00144),CE(0x00303, 0x000f1),CE(0x00307, 0x01e45),CE(0x0030c, 0x00148),CE(0x00323, 0x01e47),CE(0x00327, 0x00146),CE(0x0032d, 0x01e4b),CE(0x00331, 0x01e49),CE(0x00300, 0x000f2),CE(0x00301, 0x000f3),CE(0x00302, 0x000f4),CE(0x00303, 0x000f5),CE(0x00304, 0x0014d),CE(0x00306, 0x0014f),CE(0x00307, 0x0022f),CE(0x00308, 0x000f6),CE(0x00309, 0x01ecf),CE(0x0030b, 0x00151),CE(0x0030c, 0x001d2),CE(0x0030f, 0x0020d),CE(0x00311, 0x0020f),CE(0x0031b, 0x001a1),CE(0x00323, 0x01ecd),CE(0x00328, 0x001eb),CE(0x00301, 0x01e55),CE(0x00307, 0x01e57),CE(0x00301, 0x00155),CE(0x00307, 0x01e59),CE(0x0030c, 0x00159),CE(0x0030f, 0x00211),CE(0x00311, 0x00213),CE(0x00323, 0x01e5b),CE(0x00327, 0x00157),CE(0x00331, 0x01e5f),CE(0x00301, 0x0015b),CE(0x00302, 0x0015d),CE(0x00307, 0x01e61),CE(0x0030c, 0x00161),CE(0x00323, 0x01e63),CE(0x00326, 0x00219),CE(0x00327, 0x0015f),CE(0x00307, 0x01e6b),CE(0x00308, 0x01e97),CE(0x0030c, 0x00165),CE(0x00323, 0x01e6d),CE(0x00326, 0x0021b),CE(0x00327, 0x00163),CE(0x0032d, 0x01e71),CE(0x00331, 0x01e6f),CE(0x00300, 0x000f9),CE(0x00301, 0x000fa),CE(0x00302, 0x000fb),CE(0x00303, 0x00169),CE(0x00304, 0x0016b),CE(0x00306, 0x0016d),CE(0x00308, 0x000fc),CE(0x00309, 0x01ee7),CE(0x0030a, 0x0016f),CE(0x0030b, 0x00171),CE(0x0030c, 0x001d4),CE(0x0030f, 0x00215),CE(0x00311, 0x00217),CE(0x0031b, 0x001b0),CE(0x00323, 0x01ee5),CE(0x00324, 0x01e73),CE(0x00328, 0x00173),CE(0x0032d, 0x01e77),CE(0x00330, 0x01e75),CE(0x00303, 0x01e7d),CE(0x00323, 0x01e7f),CE(0x00300, 0x01e81),CE(0x00301, 0x01e83),CE(0x00302, 0x00175),CE(0x00307, 0x01e87),CE(0x00308, 0x01e85),CE(0x0030a, 0x01e98),CE(0x00323, 0x01e89),CE(0x00307, 0x01e8b),CE(0x00308, 0x01e8d),CE(0x00300, 0x01ef3),CE(0x00301, 0x000fd),CE(0x00302, 0x00177),CE(0x00303, 0x01ef9),CE(0x00304, 0x00233),CE(0x00307, 0x01e8f),CE(0x00308, 0x000ff),CE(0x00309, 0x01ef7),CE(0x0030a, 0x01e99),CE(0x00323, 0x01ef5),CE(0x00301, 0x0017a),CE(0x00302, 0x01e91),CE(0x00307, 0x0017c),CE(0x0030c, 0x0017e),CE(0x00323, 0x01e93),CE(0x00331, 0x01e95),CE(0x00300, 0x01fed),CE(0x00301, 0x00385),CE(0x00342, 0x01fc1),CE(0x00300, 0x01ea6),CE(0x00301, 0x01ea4),CE(0x00303, 0x01eaa),CE(0x00309, 0x01ea8),CE(0x00304, 0x001de),CE(0x00301, 0x001fa),CE(0x00301, 0x001fc),CE(0x00304, 0x001e2),CE(0x00301, 0x01e08),CE(0x00300, 0x01ec0),CE(0x00301, 0x01ebe),CE(0x00303, 0x01ec4),CE(0x00309, 0x01ec2),CE(0x00301, 0x01e2e),CE(0x00300, 0x01ed2),CE(0x00301, 0x01ed0),CE(0x00303, 0x01ed6),CE(0x00309, 0x01ed4),CE(0x00301, 0x01e4c),CE(0x00304, 0x0022c),CE(0x00308, 0x01e4e),CE(0x00304, 0x0022a),CE(0x00301, 0x001fe),CE(0x00300, 0x001db),CE(0x00301, 0x001d7),CE(0x00304, 0x001d5),CE(0x0030c, 0x001d9),CE(0x00300, 0x01ea7),CE(0x00301, 0x01ea5),CE(0x00303, 0x01eab),CE(0x00309, 0x01ea9),CE(0x00304, 0x001df),CE(0x00301, 0x001fb),CE(0x00301, 0x001fd),CE(0x00304, 0x001e3),CE(0x00301, 0x01e09),CE(0x00300, 0x01ec1),CE(0x00301, 0x01ebf),CE(0x00303, 0x01ec5),CE(0x00309, 0x01ec3),CE(0x00301, 0x01e2f),CE(0x00300, 0x01ed3),CE(0x00301, 0x01ed1),CE(0x00303, 0x01ed7),CE(0x00309, 0x01ed5),CE(0x00301, 0x01e4d),CE(0x00304, 0x0022d),CE(0x00308, 0x01e4f),CE(0x00304, 0x0022b),CE(0x00301, 0x001ff),CE(0x00300, 0x001dc),CE(0x00301, 0x001d8),CE(0x00304, 0x001d6),CE(0x0030c, 0x001da),CE(0x00300, 0x01eb0),CE(0x00301, 0x01eae),CE(0x00303, 0x01eb4),CE(0x00309, 0x01eb2),CE(0x00300, 0x01eb1),CE(0x00301, 0x01eaf),CE(0x00303, 0x01eb5),CE(0x00309, 0x01eb3),CE(0x00300, 0x01e14),CE(0x00301, 0x01e16),CE(0x00300, 0x01e15),CE(0x00301, 0x01e17),CE(0x00300, 0x01e50),CE(0x00301, 0x01e52),CE(0x00300, 0x01e51),CE(0x00301, 0x01e53),CE(0x00307, 0x01e64),CE(0x00307, 0x01e65),CE(0x00307, 0x01e66),CE(0x00307, 0x01e67),CE(0x00301, 0x01e78),CE(0x00301, 0x01e79),CE(0x00308, 0x01e7a),CE(0x00308, 0x01e7b),CE(0x00307, 0x01e9b),CE(0x00300, 0x01edc),CE(0x00301, 0x01eda),CE(0x00303, 0x01ee0),CE(0x00309, 0x01ede),CE(0x00323, 0x01ee2),CE(0x00300, 0x01edd),CE(0x00301, 0x01edb),CE(0x00303, 0x01ee1),CE(0x00309, 0x01edf),CE(0x00323, 0x01ee3),CE(0x00300, 0x01eea),CE(0x00301, 0x01ee8),CE(0x00303, 0x01eee),CE(0x00309, 0x01eec),CE(0x00323, 0x01ef0),CE(0x00300, 0x01eeb),CE(0x00301, 0x01ee9),CE(0x00303, 0x01eef),CE(0x00309, 0x01eed),CE(0x00323, 0x01ef1),CE(0x0030c, 0x001ee),CE(0x00304, 0x001ec),CE(0x00304, 0x001ed),CE(0x00304, 0x001e0),CE(0x00304, 0x001e1),CE(0x00306, 0x01e1c),CE(0x00306, 0x01e1d),CE(0x00304, 0x00230),CE(0x00304, 0x00231),CE(0x0030c, 0x001ef),CE(0x00300, 0x01fba),CE(0x00301, 0x00386),CE(0x00304, 0x01fb9),CE(0x00306, 0x01fb8),CE(0x00313, 0x01f08),CE(0x00314, 0x01f09),CE(0x00345, 0x01fbc),CE(0x00300, 0x01fc8),CE(0x00301, 0x00388),CE(0x00313, 0x01f18),CE(0x00314, 0x01f19),CE(0x00300, 0x01fca),CE(0x00301, 0x00389),CE(0x00313, 0x01f28),CE(0x00314, 0x01f29),CE(0x00345, 0x01fcc),CE(0x00300, 0x01fda),CE(0x00301, 0x0038a),CE(0x00304, 0x01fd9),CE(0x00306, 0x01fd8),CE(0x00308, 0x003aa),CE(0x00313, 0x01f38),CE(0x00314, 0x01f39),CE(0x00300, 0x01ff8),CE(0x00301, 0x0038c),CE(0x00313, 0x01f48),CE(0x00314, 0x01f49),CE(0x00314, 0x01fec),CE(0x00300, 0x01fea),CE(0x00301, 0x0038e),CE(0x00304, 0x01fe9),CE(0x00306, 0x01fe8),CE(0x00308, 0x003ab),CE(0x00314, 0x01f59),CE(0x00300, 0x01ffa),CE(0x00301, 0x0038f),CE(0x00313, 0x01f68),CE(0x00314, 0x01f69),CE(0x00345, 0x01ffc),CE(0x00345, 0x01fb4),CE(0x00345, 0x01fc4),CE(0x00300, 0x01f70),CE(0x00301, 0x003ac),CE(0x00304, 0x01fb1),CE(0x00306, 0x01fb0),CE(0x00313, 0x01f00),CE(0x00314, 0x01f01),CE(0x00342, 0x01fb6),CE(0x00345, 0x01fb3),CE(0x00300, 0x01f72),CE(0x00301, 0x003ad),CE(0x00313, 0x01f10),CE(0x00314, 0x01f11),CE(0x00300, 0x01f74),CE(0x00301, 0x003ae),CE(0x00313, 0x01f20),CE(0x00314, 0x01f21),CE(0x00342, 0x01fc6),CE(0x00345, 0x01fc3),CE(0x00300, 0x01f76),CE(0x00301, 0x003af),CE(0x00304, 0x01fd1),CE(0x00306, 0x01fd0),CE(0x00308, 0x003ca),CE(0x00313, 0x01f30),CE(0x00314, 0x01f31),CE(0x00342, 0x01fd6),CE(0x00300, 0x01f78),CE(0x00301, 0x003cc),CE(0x00313, 0x01f40),CE(0x00314, 0x01f41),CE(0x00313, 0x01fe4),CE(0x00314, 0x01fe5),CE(0x00300, 0x01f7a),CE(0x00301, 0x003cd),CE(0x00304, 0x01fe1),CE(0x00306, 0x01fe0),CE(0x00308, 0x003cb),CE(0x00313, 0x01f50),CE(0x00314, 0x01f51),CE(0x00342, 0x01fe6),CE(0x00300, 0x01f7c),CE(0x00301, 0x003ce),CE(0x00313, 0x01f60),CE(0x00314, 0x01f61),CE(0x00342, 0x01ff6),CE(0x00345, 0x01ff3),CE(0x00300, 0x01fd2),CE(0x00301, 0x00390),CE(0x00342, 0x01fd7),CE(0x00300, 0x01fe2),CE(0x00301, 0x003b0),CE(0x00342, 0x01fe7),CE(0x00345, 0x01ff4),CE(0x00301, 0x003d3),CE(0x00308, 0x003d4),CE(0x00308, 0x00407),CE(0x00306, 0x004d0),CE(0x00308, 0x004d2),CE(0x00301, 0x00403),CE(0x00300, 0x00400),CE(0x00306, 0x004d6),CE(0x00308, 0x00401),CE(0x00306, 0x004c1),CE(0x00308, 0x004dc),CE(0x00308, 0x004de),CE(0x00300, 0x0040d),CE(0x00304, 0x004e2),CE(0x00306, 0x00419),CE(0x00308, 0x004e4),CE(0x00301, 0x0040c),CE(0x00308, 0x004e6),CE(0x00304, 0x004ee),CE(0x00306, 0x0040e),CE(0x00308, 0x004f0),CE(0x0030b, 0x004f2),CE(0x00308, 0x004f4),CE(0x00308, 0x004f8),CE(0x00308, 0x004ec),CE(0x00306, 0x004d1),CE(0x00308, 0x004d3),CE(0x00301, 0x00453),CE(0x00300, 0x00450),CE(0x00306, 0x004d7),CE(0x00308, 0x00451),CE(0x00306, 0x004c2),CE(0x00308, 0x004dd),CE(0x00308, 0x004df),CE(0x00300, 0x0045d),CE(0x00304, 0x004e3),CE(0x00306, 0x00439),CE(0x00308, 0x004e5),CE(0x00301, 0x0045c),CE(0x00308, 0x004e7),CE(0x00304, 0x004ef),CE(0x00306, 0x0045e),CE(0x00308, 0x004f1),CE(0x0030b, 0x004f3),CE(0x00308, 0x004f5),CE(0x00308, 0x004f9),CE(0x00308, 0x004ed),CE(0x00308, 0x00457),CE(0x0030f, 0x00476),CE(0x0030f, 0x00477),CE(0x00308, 0x004da),CE(0x00308, 0x004db),CE(0x00308, 0x004ea),CE(0x00308, 0x004eb),CE(0x00653, 0x00622),CE(0x00654, 0x00623),CE(0x00655, 0x00625),CE(0x00654, 0x00624),CE(0x00654, 0x00626),CE(0x00654, 0x006c2),CE(0x00654, 0x006d3),CE(0x00654, 0x006c0),CE(0x0093c, 0x00929),CE(0x0093c, 0x00931),CE(0x0093c, 0x00934),CE(0x009be, 0x009cb),CE(0x009d7, 0x009cc),CE(0x00b3e, 0x00b4b),CE(0x00b56, 0x00b48),CE(0x00b57, 0x00b4c),CE(0x00bd7, 0x00b94),CE(0x00bbe, 0x00bca),CE(0x00bd7, 0x00bcc),CE(0x00bbe, 0x00bcb),CE(0x00c56, 0x00c48),CE(0x00cd5, 0x00cc0),CE(0x00cc2, 0x00cca),CE(0x00cd5, 0x00cc7),CE(0x00cd6, 0x00cc8),CE(0x00cd5, 0x00ccb),CE(0x00d3e, 0x00d4a),CE(0x00d57, 0x00d4c),CE(0x00d3e, 0x00d4b),CE(0x00dca, 0x00dda),CE(0x00dcf, 0x00ddc),CE(0x00ddf, 0x00dde),CE(0x00dca, 0x00ddd),CE(0x0102e, 0x01026),CE(0x01b35, 0x01b06),CE(0x01b35, 0x01b08),CE(0x01b35, 0x01b0a),CE(0x01b35, 0x01b0c),CE(0x01b35, 0x01b0e),CE(0x01b35, 0x01b12),CE(0x01b35, 0x01b3b),CE(0x01b35, 0x01b3d),CE(0x01b35, 0x01b40),CE(0x01b35, 0x01b41),CE(0x01b35, 0x01b43),CE(0x00304, 0x01e38),CE(0x00304, 0x01e39),CE(0x00304, 0x01e5c),CE(0x00304, 0x01e5d),CE(0x00307, 0x01e68),CE(0x00307, 0x01e69),CE(0x00302, 0x01eac),CE(0x00306, 0x01eb6),CE(0x00302, 0x01ead),CE(0x00306, 0x01eb7),CE(0x00302, 0x01ec6),CE(0x00302, 0x01ec7),CE(0x00302, 0x01ed8),CE(0x00302, 0x01ed9),CE(0x00300, 0x01f02),CE(0x00301, 0x01f04),CE(0x00342, 0x01f06),CE(0x00345, 0x01f80),CE(0x00300, 0x01f03),CE(0x00301, 0x01f05),CE(0x00342, 0x01f07),CE(0x00345, 0x01f81),CE(0x00345, 0x01f82),CE(0x00345, 0x01f83),CE(0x00345, 0x01f84),CE(0x00345, 0x01f85),CE(0x00345, 0x01f86),CE(0x00345, 0x01f87),CE(0x00300, 0x01f0a),CE(0x00301, 0x01f0c),CE(0x00342, 0x01f0e),CE(0x00345, 0x01f88),CE(0x00300, 0x01f0b),CE(0x00301, 0x01f0d),CE(0x00342, 0x01f0f),CE(0x00345, 0x01f89),CE(0x00345, 0x01f8a),CE(0x00345, 0x01f8b),CE(0x00345, 0x01f8c),CE(0x00345, 0x01f8d),CE(0x00345, 0x01f8e),CE(0x00345, 0x01f8f),CE(0x00300, 0x01f12),CE(0x00301, 0x01f14),CE(0x00300, 0x01f13),CE(0x00301, 0x01f15),CE(0x00300, 0x01f1a),CE(0x00301, 0x01f1c),CE(0x00300, 0x01f1b),CE(0x00301, 0x01f1d),CE(0x00300, 0x01f22),CE(0x00301, 0x01f24),CE(0x00342, 0x01f26),CE(0x00345, 0x01f90),CE(0x00300, 0x01f23),CE(0x00301, 0x01f25),CE(0x00342, 0x01f27),CE(0x00345, 0x01f91),CE(0x00345, 0x01f92),CE(0x00345, 0x01f93),CE(0x00345, 0x01f94),CE(0x00345, 0x01f95),CE(0x00345, 0x01f96),CE(0x00345, 0x01f97),CE(0x00300, 0x01f2a),CE(0x00301, 0x01f2c),CE(0x00342, 0x01f2e),CE(0x00345, 0x01f98),CE(0x00300, 0x01f2b),CE(0x00301, 0x01f2d),CE(0x00342, 0x01f2f),CE(0x00345, 0x01f99),CE(0x00345, 0x01f9a),CE(0x00345, 0x01f9b),CE(0x00345, 0x01f9c),CE(0x00345, 0x01f9d),CE(0x00345, 0x01f9e),CE(0x00345, 0x01f9f),CE(0x00300, 0x01f32),CE(0x00301, 0x01f34),CE(0x00342, 0x01f36),CE(0x00300, 0x01f33),CE(0x00301, 0x01f35),CE(0x00342, 0x01f37),CE(0x00300, 0x01f3a),CE(0x00301, 0x01f3c),CE(0x00342, 0x01f3e),CE(0x00300, 0x01f3b),CE(0x00301, 0x01f3d),CE(0x00342, 0x01f3f),CE(0x00300, 0x01f42),CE(0x00301, 0x01f44),CE(0x00300, 0x01f43),CE(0x00301, 0x01f45),CE(0x00300, 0x01f4a),CE(0x00301, 0x01f4c),CE(0x00300, 0x01f4b),CE(0x00301, 0x01f4d),CE(0x00300, 0x01f52),CE(0x00301, 0x01f54),CE(0x00342, 0x01f56),CE(0x00300, 0x01f53),CE(0x00301, 0x01f55),CE(0x00342, 0x01f57),CE(0x00300, 0x01f5b),CE(0x00301, 0x01f5d),CE(0x00342, 0x01f5f),CE(0x00300, 0x01f62),CE(0x00301, 0x01f64),CE(0x00342, 0x01f66),CE(0x00345, 0x01fa0),CE(0x00300, 0x01f63),CE(0x00301, 0x01f65),CE(0x00342, 0x01f67),CE(0x00345, 0x01fa1),CE(0x00345, 0x01fa2),CE(0x00345, 0x01fa3),CE(0x00345, 0x01fa4),CE(0x00345, 0x01fa5),CE(0x00345, 0x01fa6),CE(0x00345, 0x01fa7),CE(0x00300, 0x01f6a),CE(0x00301, 0x01f6c),CE(0x00342, 0x01f6e),CE(0x00345, 0x01fa8),CE(0x00300, 0x01f6b),CE(0x00301, 0x01f6d),CE(0x00342, 0x01f6f),CE(0x00345, 0x01fa9),CE(0x00345, 0x01faa),CE(0x00345, 0x01fab),CE(0x00345, 0x01fac),CE(0x00345, 0x01fad),CE(0x00345, 0x01fae),CE(0x00345, 0x01faf),CE(0x00345, 0x01fb2),CE(0x00345, 0x01fc2),CE(0x00345, 0x01ff2),CE(0x00345, 0x01fb7),CE(0x00300, 0x01fcd),CE(0x00301, 0x01fce),CE(0x00342, 0x01fcf),CE(0x00345, 0x01fc7),CE(0x00345, 0x01ff7),CE(0x00300, 0x01fdd),CE(0x00301, 0x01fde),CE(0x00342, 0x01fdf),CE(0x00338, 0x0219a),CE(0x00338, 0x0219b),CE(0x00338, 0x021ae),CE(0x00338, 0x021cd),CE(0x00338, 0x021cf),CE(0x00338, 0x021ce),CE(0x00338, 0x02204),CE(0x00338, 0x02209),CE(0x00338, 0x0220c),CE(0x00338, 0x02224),CE(0x00338, 0x02226),CE(0x00338, 0x02241),CE(0x00338, 0x02244),CE(0x00338, 0x02247),CE(0x00338, 0x02249),CE(0x00338, 0x0226d),CE(0x00338, 0x02262),CE(0x00338, 0x02270),CE(0x00338, 0x02271),CE(0x00338, 0x02274),CE(0x00338, 0x02275),CE(0x00338, 0x02278),CE(0x00338, 0x02279),CE(0x00338, 0x02280),CE(0x00338, 0x02281),CE(0x00338, 0x022e0),CE(0x00338, 0x022e1),CE(0x00338, 0x02284),CE(0x00338, 0x02285),CE(0x00338, 0x02288),CE(0x00338, 0x02289),CE(0x00338, 0x022e2),CE(0x00338, 0x022e3),CE(0x00338, 0x022ac),CE(0x00338, 0x022ad),CE(0x00338, 0x022ae),CE(0x00338, 0x022af),CE(0x00338, 0x022ea),CE(0x00338, 0x022eb),CE(0x00338, 0x022ec),CE(0x00338, 0x022ed),CE(0x03099, 0x03094),CE(0x03099, 0x0304c),CE(0x03099, 0x0304e),CE(0x03099, 0x03050),CE(0x03099, 0x03052),CE(0x03099, 0x03054),CE(0x03099, 0x03056),CE(0x03099, 0x03058),CE(0x03099, 0x0305a),CE(0x03099, 0x0305c),CE(0x03099, 0x0305e),CE(0x03099, 0x03060),CE(0x03099, 0x03062),CE(0x03099, 0x03065),CE(0x03099, 0x03067),CE(0x03099, 0x03069),CE(0x03099, 0x03070),CE(0x0309a, 0x03071),CE(0x03099, 0x03073),CE(0x0309a, 0x03074),CE(0x03099, 0x03076),CE(0x0309a, 0x03077),CE(0x03099, 0x03079),CE(0x0309a, 0x0307a),CE(0x03099, 0x0307c),CE(0x0309a, 0x0307d),CE(0x03099, 0x0309e),CE(0x03099, 0x030f4),CE(0x03099, 0x030ac),CE(0x03099, 0x030ae),CE(0x03099, 0x030b0),CE(0x03099, 0x030b2),CE(0x03099, 0x030b4),CE(0x03099, 0x030b6),CE(0x03099, 0x030b8),CE(0x03099, 0x030ba),CE(0x03099, 0x030bc),CE(0x03099, 0x030be),CE(0x03099, 0x030c0),CE(0x03099, 0x030c2),CE(0x03099, 0x030c5),CE(0x03099, 0x030c7),CE(0x03099, 0x030c9),CE(0x03099, 0x030d0),CE(0x0309a, 0x030d1),CE(0x03099, 0x030d3),CE(0x0309a, 0x030d4),CE(0x03099, 0x030d6),CE(0x0309a, 0x030d7),CE(0x03099, 0x030d9),CE(0x0309a, 0x030da),CE(0x03099, 0x030dc),CE(0x0309a, 0x030dd),CE(0x03099, 0x030f7),CE(0x03099, 0x030f8),CE(0x03099, 0x030f9),CE(0x03099, 0x030fa),CE(0x03099, 0x030fe),CE(0x110ba, 0x1109a),CE(0x110ba, 0x1109c),CE(0x110ba, 0x110ab),CE(0x11127, 0x1112e),CE(0x11127, 0x1112f),];
+return t;
+}
+
+}
+
diff --git a/std/internal/unicode_decomp.d b/std/internal/unicode_decomp.d
new file mode 100644
index 000000000..44c21fe5d
--- /dev/null
+++ b/std/internal/unicode_decomp.d
@@ -0,0 +1,32 @@
+module std.internal.unicode_decomp;
+import std.internal.unicode_tables;
+
+static if(size_t.sizeof == 8) {
+//22656 bytes
+enum compatMappingTrieEntries = TrieEntry!(ushort, 8, 8, 5)([ 0x0,  0x20,  0x2a0], [ 0x100,  0xa00,  0x21c0], [ 0x402030202020100,  0x706020202020205,  0x802020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x0,  0x3000200010000,  0x7000600050004,  0xa000900080000,  0xc000b,  0xf000e000d0000,  0x11001000000000,  0x15001400130012,  0x19001800170016,  0x1b001a00000000,  0x0,  0x1c,  0x1e0000001d0000,  0x1f00000000,  0x0,  0x0,  0x0,  0x0,  0x2100200000,  0x2200000000,  0x2400230000,  0x0,  0x2500000000,  0x2700000026,  0x2800000000,  0x2900000000,  0x2a00000000,  0x2b00000000,  0x2c0000,  0x2e002d0000,  0x3100300000002f,  0x330032,  0x340000,  0x35000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3800370036,  0x0,  0x0,  0x0,  0x3b003a00390000,  0x3d003c,  0x410040003f003e,  0x45004400430042,  0x49004800470046,  0x4d004c004b004a,  0x510050004f004e,  0x530052,  0x57005600550054,  0x5a00590058,  0x5e005d005c005b,  0x6100000060005f,  0x620000,  0x0,  0x63000000000000,  0x67006600650064,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x69000000000068,  0x6a00000000,  0x0,  0x0,  0x6b000000000000,  0x0,  0x6c000000000000,  0x0,  0x0,  0x6e00000000006d,  0x7200710070006f,  0x7500740073,  0x79007800770076,  0x7d007c007b007a,  0x80007f007e0000,  0x81,  0x85008400830082,  0x89008800870086,  0x8d008c008b008a,  0x910090008f008e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x92000000000000,  0x93000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x97009600950094,  0x9b009a00990098,  0x9f009e009d009c,  0xa200a100a0,  0xa600a500a400a3,  0xaa00a900a800a7,  0xae00ad00ac00ab,  0xb200b100b000af,  0xb600b500b400b3,  0xba00b900b800b7,  0xbe00bd00bc00bb,  0xc200c100c000bf,  0xc600c500c400c3,  0xca00c900c800c7,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xcc00cb,  0xcd0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xcf00ce00000000,  0xd100d00000,  0x0,  0x0,  0x0,  0x0,  0xd500d400d300d2,  0xd900d800d700d6,  0xdd00dc00db00da,  0xdf00d300d200de,  0xe200e100e000d5,  0xe500e400e300d9,  0xe900e800e700e6,  0xed00ec00eb00ea,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xf100f000ef00ee,  0xf300f2,  0x0,  0x0,  0x0,  0x0,  0xf700f600f500f4,  0xf8,  0xfb00fa00f9,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xff00fe00fd00fc,  0x103010201010100,  0x107010601050104,  0x10b010a01090108,  0x10c,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1,  0x0,  0x69200000015,  0x9000000000000,  0x30f034300000000,  0x11b20003,  0x78703140048,  0x49403c603ce,  0x58605730570056d,  0x5f8000005b005a6,  0x6580631062e062b,  0x6f906ea06e706e4,  0x7a907a6078f0000,  0x7e307bf07ac,  0x8b708b408b10000,  0x95f08cb,  0x9c209af09ac09a9,  0xa47000009ec09e2,  0xab30a8c0a890a86,  0xb550b490b460b43,  0xc5e0c5b0c410000,  0xc980c740c61,  0xd6e0d6b0d680000,  0xe1b00000e0c0d82,  0x9c8058c09c50589,  0xa3b05ec0a0a05ce,  0xa4105f20a3e05ef,  0xa6e061a0a4405f5,  0xaa2064700000000,  0xab006550aad0652,  0xab9065e0ad00675,  0xb0106a00afb069a,  0xb0a06a90b0406a3,  0xb1606ba,  0xb4f06f00b4c06ed,  0xb6b070f0b5206f3,  0xb3706d8000006f6,  0xbae072e0b730717,  0x7500bcc07430000,  0x7400bcf07460bd9,  0x78c000000000bc9,  0x7950c4d079b0c3e,  0xed70c47,  0xc8e07d90c8307ce,  0xca207ed,  0xd1d08580d070842,  0xd2b086c0d0d0848,  0xd49088a0d320873,  0xd5d08a60d380879,  0xd54089d,  0xd7808c10d7108ba,  0xd9808e10d7f08c8,  0xdc4090d0d9b08e4,  0xe0f09620de9093f,  0x97f0e290979096e,  0x8400614060d0e2f,  0xcae07f9,  0x0,  0x0,  0x8f0000000000000,  0xda7,  0x0,  0x0,  0x0,  0x0,  0x7360a670613060c,  0x78307800bb9073d,  0x70309f305b70c32,  0x8e70ca507f00b5f,  0x8d20d8d08d60d9e,  0x8ce0d9108da0d89,  0x9e505a900000d85,  0xe630e5a09de05a2,  0xb0706a600000000,  0xccc08170ba80728,  0xecc0e7b0ccf081a,  0xa64061006090b76,  0xaf80697,  0x9ef05b30c3b0789,  0xe680e5d0e600e57,  0x9f905bd09f605ba,  0xabf06640abc0661,  0xb6507090b620706,  0xcab07f60ca807f3,  0xd13084e0d10084b,  0xda408ed0da108ea,  0xd5a08a30d460887,  0xb1f06c300000000,  0x0,  0x9db059f00000000,  0xc9b07e60ac9066e,  0xc9107dc0c7b07c6,  0xe1509680c9407df,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xa11073e0e9a0b0d,  0xde10eb80eb60eb4,  0x695,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x4b00240012000f,  0x270006,  0xb4108400a280e96,  0xecf,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2b00000004001a,  0x1d,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xed5,  0x5400000000,  0x54600000000,  0x0,  0x7410ee8001c0003,  0xfb40f630f43,  0x103c101600000fed,  0x1185,  0x0,  0x0,  0x0,  0x0,  0x0,  0x101f0fbd00000000,  0x1175111910f5108f,  0x1213,  0x0,  0x0,  0x0,  0x0,  0x0,  0x120c117e00000000,  0x124b120311d5,  0x10161011116e10ea,  0x11ee123c101f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x11f811f011ae,  0x10f00fad,  0x100d0000,  0x0,  0x12ad000012b612b0,  0x12a4000000000000,  0x0,  0x12d712c212ce,  0x0,  0x0,  0x12c80000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x130a0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x12ef000012f812f2,  0x132d000000000000,  0x0,  0x131b13041310,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1333133000000000,  0x0,  0x0,  0x12fb12b90000,  0x0,  0x0,  0x0,  0x12ec12aa12e912a7,  0x12f512b300000000,  0x1339133600000000,  0x130112bf12fe12bc,  0x130712c500000000,  0x131512d1130d12cb,  0x133f133c00000000,  0x131812d4132a12e6,  0x132112dd131e12da,  0x132412e0,  0x132712e3,  0x0,  0x0,  0x1342000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x13e913e600000000,  0x17ca13ec178f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x185b179213ef0000,  0x1811,  0x0,  0x18520000186d,  0x0,  0x0,  0x0,  0x186a000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18820000,  0x0,  0x188b0000,  0x188e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1879187618731870,  0x18881885187f187c,  0x0,  0x0,  0x189a000000000000,  0x189d,  0x0,  0x0,  0x0,  0x1897000018941891,  0x0,  0x0,  0x0,  0x0,  0x18ac000000000000,  0x18af00000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18a618a318a00000,  0x18a900000000,  0x0,  0x0,  0x18b80000000018bb,  0x18be,  0x0,  0x0,  0x0,  0x18b518b2,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18c1,  0x0,  0x0,  0x0,  0x0,  0x18ca18c400000000,  0x18c7,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18cd,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18d0,  0x18da000000000000,  0x18d618d3000018dd,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18e618e000000000,  0x18e3,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18e900000000,  0x18f318ef18ec,  0x0,  0x0,  0x0,  0x0,  0x18f6000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18ff000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18fc18f9,  0x0,  0x0,  0x0,  0x1902,  0x0,  0x0,  0x0,  0x0,  0x1907000000000000,  0x0,  0x0,  0x190a0000,  0x190d00000000,  0x1910000000000000,  0x0,  0x1913,  0x0,  0x0,  0x19040000,  0x0,  0x1916000000000000,  0x1931193519190000,  0x1938193c,  0x0,  0x191c0000,  0x0,  0x0,  0x0,  0x1922000000000000,  0x0,  0x0,  0x19250000,  0x192800000000,  0x192b000000000000,  0x0,  0x192e,  0x0,  0x0,  0x191f0000,  0x0,  0x0,  0x193f00000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1942,  0x0,  0x1a3800000000,  0x1a3e00001a3b,  0x1a4400001a41,  0x1a4700000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1a4a000000000000,  0x1a4d0000,  0x1a5600001a531a50,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x5d50e550568,  0x6870e75062905e6,  0x71a060706cf06ac,  0x77e07230734,  0x82c06af0e7e07a4,  0x6920770056b088d,  0x9371a590e840e82,  0xe8e0e8c0a7d0a2e,  0xb79000006020e90,  0xe8807870e7105d3,  0xba30cd31a5d1a5b,  0x86a0ea41a610a24,  0x10ee10ec10ea1a63,  0xa110ae0123e123c,  0x10ec10ea086a0a24,  0x123e123c11f0,  0x0,  0x0,  0x0,  0x1313,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe86000000000000,  0xe900e660e8a09a0,  0xe980e940e920ad9,  0x1a650ea00e9e0e9c,  0xed31a670ea20ed1,  0xeac0eaa0ea60ea8,  0xeba0eb20eb00eae,  0xec00ebe0e790ebc,  0x6110ec40ec21a5f,  0x116e0eca0ec80ec6,  0xa1305da0a0705cb,  0xa1905e00a1605dd,  0xa6b06170a4a05fb,  0xa7a06260a71061d,  0xa7706230a740620,  0xaa9064e0aa5064a,  0xad6067b0ad30678,  0xaef06840acc0671,  0xb1906bd0afe069d,  0xb1c06c00b2206c6,  0xb2806cc0b2506c9,  0xb5806fc0b6e0712,  0xbab072b0ba50725,  0xbd207490bb10731,  0xbdf07560bd5074c,  0xc1207720bdc0753,  0xc1807780c150775,  0xc4a07980c440792,  0xc50079e0c5307a1,  0xc7f07ca0c7707c2,  0xc8a07d50c8607d1,  0xcef08380cec0835,  0xd1608510d0a0845,  0xd20085b0d190854,  0xd3f08800d350876,  0xd3b087c0d2e086f,  0xd4e089a0d420883,  0xd6308ac0d5708a0,  0xdc1090a0d6008a9,  0xdc709100dca0913,  0xd7b08c40d7408bd,  0xdde09270ddb0924,  0xde6093c0de30939,  0xdec09420def0945,  0xe0109540df50948,  0xe18096b0e040957,  0xe3509850e2c097c,  0xd510b2b0e380988,  0xd3509a60e210df2,  0x0,  0x9e905ad09fc05c0,  0x9b2057609b6057a,  0x9ba057e09be0582,  0x9cf059309ff05c3,  0x9d7059b09cb058f,  0xa0305c709d30597,  0xab6065b0ac20667,  0xa9306380a9f0644,  0xa9b06400a8f0634,  0xac5066a0a97063c,  0xb68070c0b5c0700,  0xc9f07ea0cc50810,  0xc6407af0c6807b3,  0xc6c07b70c7007bb,  0xcb508000cc80813,  0xcbd08080cb107fc,  0xcc1080c0cb90804,  0xd9508de0dbe0907,  0xdaa08f30dae08f7,  0xdb208fb0db608ff,  0xe09095c0dba0903,  0xe1e09710e240974,  0xe120965,  0x0,  0x10c1109f10be109c,  0x10d310b110ca10a8,  0xf160ef40f130ef1,  0xf280f060f1f0efd,  0x110610fb110310f8,  0x110a10ff,  0xf540f490f510f46,  0xf580f4d,  0x1145112311421120,  0x11571135114e112c,  0xf8b0f690f880f66,  0xf9d0f7b0f940f72,  0x119f1190119c118d,  0x11a7119811a31194,  0xfd20fc30fcf0fc0,  0xfda0fcb0fd60fc7,  0x11e611db11e311d8,  0x11ea11df,  0xffe0ff30ffb0ff0,  0x10020ff7,  0x122d121e122a121b,  0x1235122612311222,  0x1025000010220000,  0x102d000010290000,  0x1277125512741252,  0x128912671280125e,  0x106410421061103f,  0x10761054106d104b,  0x10f510f2108f1088,  0x1175117211191112,  0x1203120011d511d2,  0x124b1244,  0x10c510a310dc10ba,  0x10d710b510ce10ac,  0xf1a0ef80f310f0f,  0xf2c0f0a0f230f01,  0x114911271160113e,  0x115b113911521130,  0xf8f0f6d0fa60f84,  0xfa10f7f0f980f76,  0x127b125912921270,  0x128d126b12841262,  0x10681046107f105d,  0x107a10581071104f,  0x10e7108b10961099,  0x10e310e000001092,  0xee80ee50eeb0eee,  0x2a1170002a0f35,  0x116b111500200051,  0x116711640000111c,  0xf630f600f430f40,  0x350031002d0faa,  0x118511811178117b,  0x118911ab00000000,  0xfb40fb10fb70fba,  0x440040003c0000,  0x1213120f12061209,  0x1217123911f511f2,  0x101610131019101c,  0x995001c0018100a,  0x129d124700000000,  0x129912960000124e,  0x103c10390fed0fea,  0x3900031083,  0x1000100010001,  0x1000100010001,  0x100010001,  0x0,  0x1a690000,  0x4e000000000000,  0x0,  0x0,  0x0,  0x2ff02fc02fa,  0x0,  0x1000000000000,  0x1a6f000000000000,  0x1a7e1a7b00001a72,  0x0,  0xc0000008f,  0x0,  0x563000000000000,  0x920560,  0x0,  0x0,  0x1a76000000000000,  0x0,  0x1000000000000,  0x0,  0x0,  0x0,  0x0,  0xae00305,  0x392038303740365,  0x1aad02f403b003a1,  0xb3b00a500a10544,  0x30f034303140305,  0x392038303740365,  0x1aad02f403b003a1,  0xa500a10544,  0xb4107870a7d0692,  0xa280b790b0d0e8c,  0x8400cd30b3b05d3,  0xba3,  0x0,  0x0,  0x83f,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe4d05e309a2099e,  0xe770a220a1e0000,  0x6ac06020e500000,  0xe6d0b0d06ac06ac,  0xa28073406cf06cf,  0x786077e0000,  0x82c083b06af0000,  0x82c082c,  0x897088f0863,  0x77c0000060a,  0x5b0071a0000060a,  0xa7d000005e305d5,  0x7230000067e0629,  0x136a136213540787,  0x68000000ae0136f,  0x10060f3a10ec11ee,  0x1aab,  0xa7d0a2e05e60000,  0x73e0ae0,  0x0,  0x3ca03c103e203da,  0x498045903d20455,  0x3de04e703d604cf,  0x3be051104eb049c,  0x6de06d406d106cf,  0x91f091b091806b2,  0x950094d068206e1,  0x72305e605e30734,  0xb3d0b330b300ae0,  0xdd60dd20dcf086a,  0xdfd0dfa0b410b40,  0x5d30a2e09a00a28,  0x0,  0x0,  0x30d0000,  0x0,  0x0,  0x0,  0x1a8d1a8600000000,  0x0,  0x0,  0x0,  0x0,  0x1a9200000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1a981a9b1a950000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1aa0,  0x1aa50000,  0x1aa8,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1ab200001aaf,  0x0,  0x1ac100001ab81ab5,  0x1ac4,  0x0,  0x0,  0x0,  0x1ac80000,  0x1ace000000001acb,  0x1ad10000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1ad700000556,  0x0,  0x0,  0x55b054a1ad40000,  0x1add1ada,  0x1ae31ae0,  0x1ae91ae6,  0x0,  0x1aef1aec,  0x1afb1af8,  0x1b011afe,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1b131b101b0d1b0a,  0x0,  0x0,  0x0,  0x0,  0x1b071b041af51af2,  0x0,  0x1b191b1600000000,  0x1b1f1b1c,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1b371b350000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x365030f03430314,  0x3a1039203830374,  0x342032f031c03b0,  0x382037303640355,  0x3f703af03a00391,  0xe600e200d900a3,  0xf600f200ee00ea,  0xb100ac00a700fa,  0xc500c000bb00b6,  0xdd00d400cf00ca,  0x368035903460319,  0x3a4039503860377,  0x3450332031f03b3,  0x385037603670358,  0x3fa03b203a30394,  0x172016e016a0166,  0x182017e017a0176,  0x192018e018a0186,  0x1a2019e019a0196,  0x1b201ae01aa01a6,  0x1c201be01ba01b6,  0x5d5056801ca01c6,  0x67e062905e605e3,  0x60706cf06ac0687,  0x77e07230734071a,  0x82c083b06af07a4,  0x6b2056b088d085e,  0x60a095a06820770,  0xa2e09a009370692,  0xb0d06020ad90a7d,  0xa280b79073e0ae0,  0xcd307870b3b05d3,  0xba308400a1105d8,  0xb410de1086a0a24,  0x30506110695,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1abc,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x552054f0542,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1b2c,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x6b2073e,  0x0,  0x0,  0x0,  0x1b2f000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x227c000000000000,  0x0,  0x0,  0x0,  0x0,  0x26b0000000000000,  0x0,  0x0,  0x0,  0x1f091f011efb1ee9,  0x1f1b1f171f131f0d,  0x1f5f1f571f4b1f21,  0x1f871f771f6f1f67,  0x1fb91fa51f8b1f89,  0x1fcd1fc71fc51fc1,  0x1feb1fe91fdd1fdb,  0x204f20451ff71fef,  0x207f207d2079206f,  0x20b420ae20982087,  0x20ce20cc20ca20c4,  0x20f820f220dc20da,  0x210f2108210020fc,  0x212f212b21292113,  0x2141213921352131,  0x21972195218b214f,  0x21e521e321d921d7,  0x32521f121ed21e9,  0x2260222303292211,  0x227a2274226e2266,  0x228422822280227e,  0x230c230622e22286,  0x231623122310230e,  0x2334233023222318,  0x235c235a23562354,  0x2376237423622360,  0x238a238823862384,  0x23aa23a823a62394,  0x23ee23de23dc23bc,  0x241c240a23fa23f6,  0x2452244c2442243e,  0x245e245c245a2456,  0x247e247a246c246a,  0x248e248a24842482,  0x2498249624922490,  0x250e250c24f224e8,  0x2530252c25282512,  0x2558255425522534,  0x25742572255c255a,  0x2592258425822578,  0x25ba25aa25982596,  0x25de25c825c425c2,  0x260025fa25e825e0,  0x261a261826142608,  0x26262624261e261c,  0x263c263a2638262a,  0x2658264e264a2648,  0x26622660265c265a,  0x2670266826662664,  0x26862684267e267c,  0x2690268e268a2688,  0x26a0269c26982692,  0x26aa26a826a626a2,  0x26b226ae,  0x0,  0x0,  0x1,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1b4900000000,  0x1fd11fcf1fcd,  0x0,  0x0,  0x0,  0x0,  0x1b8100001b7e,  0x1b8700001b84,  0x1b8d00001b8a,  0x1b9300001b90,  0x1b9900001b96,  0x1b9f00001b9c,  0x1ba500001ba20000,  0x1ba80000,  0x0,  0x1bb100001bae1bab,  0x1bba1bb700001bb4,  0x1bc01bbd0000,  0x1bc91bc6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1b7b,  0x87000000000000,  0x1bcc1bd30000008a,  0x0,  0x0,  0x0,  0x1c4300001c26,  0x1c9200001bf6,  0x1caf00001c9b,  0x1cca00001cbf,  0x1cdc00001ccf,  0x1ceb00001ce1,  0x1cf700001cf20000,  0x1c100000,  0x0,  0x1d3b00001d261d1d,  0x1d611d5700001d42,  0x1d7e1d760000,  0x1caa1da1,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1e44000000001c01,  0x1e571e521e4d,  0x1ca11e6000000000,  0x0,  0x0,  0x0,  0x0,  0x1a10194919440000,  0x19501a141a12194b,  0x1a181a1619571955,  0x1a201a1e1a1c1a1a,  0x19661961195c19a6,  0x196f196d196819b0,  0x198e198319811977,  0x1947199d19981993,  0x19de19dc19da19d8,  0x198c19e419e219e0,  0x19ee19ec19ea19e8,  0x19f619f419f21975,  0x19fe197f19fa19f8,  0x1a2219a419a219d4,  0x1a2a1a281a261a24,  0x1a3019a81a2e1a2c,  0x19ae19ac19aa1a32,  0x19b819b619b419b2,  0x19c019be19bc19ba,  0x19c819c619c419c2,  0x1a361a3419cc19ca,  0x1a0019d219d019ce,  0x1a081a061a041a02,  0x1a0e1a0c1a0a,  0x1f171ee900000000,  0x1efd1ef120471eef,  0x1ef71f0d23641ef3,  0x1f212051208c1eeb,  0x1e901e001d701ce,  0x20d020401fb01f2,  0x245023c02330225,  0x1db01d20257024e,  0x1ff01f601ed01e4,  0x237022902110208,  0x25b025202490240,  0x21e0216022e,  0x2a0026802700260,  0x284026402880274,  0x2c402b00290026c,  0x2a402ec02b802c0,  0x2d002b402bc02ac,  0x2d402e402c80298,  0x2a8029c0278028c,  0x29402e8027c02cc,  0x2e002dc028002d8,  0x23fe21e321112021,  0x0,  0x0,  0x41c04110406082e,  0x440043904320427,  0x475046e044e0447,  0x4850482047f047c,  0x19571950194b1944,  0x196f19681961195c,  0x1993198e19831977,  0x194d1946199d1998,  0x1963195e19591952,  0x198519791971196a,  0x199f199a19951990,  0x1974197c1988,  0x20471eef1f171ee9,  0x1f5f1eed1f611f19,  0x22e203291fcd1f0f,  0x204f25c822232286,  0x2240221b223b0325,  0x23ca255e231c2007,  0x2098236823e21fab,  0x22961fdf1f4925a2,  0x208a1f731f2b262c,  0x20fa1ef31efd1ef1,  0x20b220b81fc92001,  0x1fd725681f292390,  0x48e048b04882083,  0x4b704b404b10491,  0x4c304c004bd04ba,  0x4e404cc04c904c6,  0x4d604a3034e033b,  0x5290518050304f2,  0x34d033a0327053a,  0x7390a7f0a8206b4,  0x1c0a1bff1bf11bd8,  0x1c731c411c241c1a,  0x1cbd1cad1c991c90,  0x1cdf1cda1ccd1c1e,  0x1bde1cf51cf01bfb,  0x1c8e1d111d0f1ca6,  0x1d551d391d1b1d0d,  0x1ddc1c311d9f1d74,  0x1e041e001def1c22,  0x1c351e1b1e191e11,  0x1e421c5d1e341bed,  0x1e551e501e4b,  0x1beb1be51be01bda,  0x1c0c1c041bf91bf3,  0x1c331c201c1c1c13,  0x1c2e1c291c3c1c37,  0x1c501c571c4b1c46,  0x1c6d1c661c5f1c5c,  0x1c8b1c841c7d1c61,  0x1cb21ca81ca41c95,  0x1cd61cd21cc21cb7,  0x1c811d031cfa1ce4,  0x1d291d351d171d0c,  0x1d4c1d451d201d30,  0x1d6b1d641d3e1d51,  0x1d811d951d701d5a,  0x1d8f1d8a1d9b1d85,  0x1db81da41dac1d79,  0x1dc51dbf1dbb1db2,  0x1dd61dd21dce1dca,  0x1df11de61de31dde,  0x1e0b1e061c681df5,  0x1e291e241e1f1e13,  0x1c6f1e391e361e2e,  0x3610352033f0311,  0x39d038e037f0370,  0x33e032b03bb03ac,  0x37e036f03600351,  0x3ba03ab039c038d,  0x4230418040d0402,  0x56a0a530b0f042e,  0xa590ce60c580a0f,  0x210a06db0a600a5c,  0x223d21f920892200,  0xbea11b40c260cda,  0x689075b071c0b7b,  0xc290cdd0b8c0a26,  0x6010bf611c011b7,  0x68c07640b7e068d,  0xa560bfd11c30893,  0x11c60c350aec0b94,  0xc030b970a300c00,  0xc070b9a0a340a33,  0xc1b0b9e0a380a37,  0x7680b8206910c1f,  0xd000cfa0cf60690,  0xc0f11c90c380ce9,  0xbed11ba0c2c0ce0,  0xc2f0ce3076c0b86,  0x76f0b890bf011bd,  0x5d70999077b0bb4,  0x5e805ff0a2d0a2a,  0x6ae0b1306940a50,  0xba20722071f0b3a,  0xbc60bc20bbf0bbc,  0x8200c0b0bf90bf3,  0xd25082b08230cd5,  0x5d1092a09360869,  0x36c035d034a0337,  0x3a80399038a037b,  0x3490336032303b7,  0x389037a036b035c,  0x3fe03b603a70398,  0x42a041f04140409,  0x44a0443043c0435,  0xaf4047804710451,  0x0,  0x0,  0x0,  0x0,  0x26b4,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe730e6b,  0x0,  0x256a258422132556,  0x26ae1ff91eff22c6,  0x202b25c8209226ae,  0x244a238221872090,  0x25a8251e250424e6,  0x233c22f0229a2254,  0x1f11265225bc24ca,  0x24e42302225e1fe3,  0x24dc22d620e6267a,  0x250a247821a12526,  0x232822a6221d211f,  0x1fb31f7d1f3125ae,  0x23922300225a21d5,  0x257e24ec24e02456,  0x23b02678266a2610,  0x25d624bc242c23d0,  0x212d206d2540267e,  0x23b4231a24682408,  0x20d4206b260c2566,  0x242422ca22b02256,  0x246e1fb125ec2438,  0x242e23e61f811f83,  0x21a3254e25f024c8,  0x20be1f0525462254,  0x1fc3237223322159,  0x1ef5214b1f3923b8,  0x1fed242221e12290,  0x253824cc23982063,  0x21ab228c25962276,  0x1f1f237021bb24a8,  0x241822441f7f1f5d,  0x1fb725c6253e2494,  0x21ef212720982011,  0x265625e423ba22d8,  0x220f1fa5268c2680,  0x217b210d2590226c,  0x22f622d021d12189,  0x2464243223e0234e,  0x25d8259c24d02588,  0x22ee201b1fa71f91,  0x2155211d25382514,  0x232c2406227221b7,  0x20f020be20491f27,  0x24502348233a215b,  0x2612260a25ca2460,  0x25c023da1f332630,  0x1f451f15216725fe,  0x225421e720d020c0,  0x25a624d6238022fc,  0x1fa325ea220726aa,  0x22be22a22233222d,  0x242023ae236e2340,  0x25f221911f612636,  0x258a22b220e21f3d,  0x23322237216b2143,  0x20d820091f9525f6,  0x2294224a222521fc,  0x251624462378233e,  0x1fcb260425c4251c,  0x235022fe200b22c0,  0x2682266e25f824de,  0x23f6247c22ae2231,  0x22ea2326240e23fc,  0x1f9724b01f23254c,  0x241421a521151f8f,  0x258e220d229c20b6,  0x2123252c25ee250e,  0x20371f4d,  0x220500002061,  0x238c232a1f850000,  0x23d823ce23cc23be,  0x245224102616,  0x2544000024e2,  0x25b4259e0000,  0x2642264000000000,  0x25fc25b026762644,  0x1faf1f511f471f35,  0x203d202f1fd51fb5,  0x20d62065205f2041,  0x21792175216120da,  0x220921f321db2185,  0x22ce22b622a82246,  0x23b22342230822f8,  0x23c623c223c42240,  0x23d623d423ca23c8,  0x2432240023f223e8,  0x24582444243a2436,  0x24ce249a249a2480,  0x254a2548252e2522,  0x259e259a256e256c,  0x215d263426282606,  0x248c274b,  0x1f2f1f5b1f7b1ef9,  0x1fbb1fad1f651f4f,  0x203b202d2025202f,  0x2094208e20692061,  0x2125212120aa20a2,  0x21712165214d213d,  0x2185217321792169,  0x21c921c521bf2193,  0x221f221d220521dd,  0x22a22276226e2229,  0x22dc22ce22c422c8,  0x2324230a23a422f8,  0x236a2358234a232a,  0x238e238c237e237c,  0x23b6239e23a02396,  0x2428240c240023f4,  0x24b2245824402432,  0x252a2524250024c6,  0x253c2544253a252e,  0x254a254225462548,  0x25a4258c256e2550,  0x260625f425ce25be,  0x262e262826202616,  0x272126ae265e2634,  0x1ea11e8d2733271f,  0x27a9277927671ea3,  0x26ac26a4,  0x0,  0xade0ae30adf0adb,  0xd280d280ae2,  0x0,  0x0,  0x134e000000000000,  0x134b135113481345,  0x0,  0x13d2000013850000,  0x1374136f135413a6,  0x13b7139b1360138e,  0x13ca13c702f413cd,  0x1359135613c313bf,  0x1371136c1364135c,  0x137f137c1376,  0x1390138b13881382,  0x139d00001398,  0x13a8000013a313a0,  0x13b413b1000013ab,  0x137913cf13bc13b9,  0x135f13ae13931367,  0x181e181e18181818,  0x18201820181e181e,  0x1824182418201820,  0x181c181c18241824,  0x18221822181c181c,  0x181a181a18221822,  0x183c183c181a181a,  0x183e183e183c183c,  0x18281828183e183e,  0x1826182618281828,  0x182a182a18261826,  0x182c182c182a182a,  0x18321832182c182c,  0x1834183418301830,  0x18381838182e182e,  0x1840184018361836,  0x1844184418401840,  0x1848184818441844,  0x1846184618481848,  0x184a184a18461846,  0x184c184c184c184c,  0x18501850186d186d,  0x184e184e18501850,  0x15911591184e184e,  0x186a186a,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1842000000000000,  0x1803184218421842,  0x180717ff17ff1803,  0x18621862185b1807,  0x1860186018551855,  0x180b180b180b180b,  0x17cd17cd14151415,  0x17f117f1180d180d,  0x17fd17fd18011801,  0x1809180918051805,  0x17f517f517f51809,  0x1864186418641864,  0x17f517e517d517d1,  0x13fe13f713f417f9,  0x141e14171414140b,  0x146a144d1438142d,  0x1484147b1472146d,  0x14311422148c1487,  0x143c14d414d11435,  0x151a150c150514fa,  0x15a515a215931562,  0x15c815c515ba15b0,  0x1607157515e415df,  0x16451642163f160a,  0x165b16561653164c,  0x1679167416711662,  0x16851682167f167c,  0x16aa169616931688,  0x1579158c16c816b9,  0x14591455145116e0,  0x172d1461145d1526,  0x17691758174f1740,  0x177f17741771176c,  0x17aa17a3179c1782,  0x14e417c717c417b3,  0x64005d179714ee,  0x8000790072006b,  0x17e917e517e117dd,  0x140813db17f917f5,  0x14171414140e140b,  0x1464144d144a1447,  0x14781475146d146a,  0x14871484147e147b,  0x1674167116561653,  0x1693168816851679,  0x16e01579158c1696,  0x17551752152616e5,  0x176c176917631758,  0x17b317b017ad1797,  0x17d117c717c417be,  0x17ed17e517d917d5,  0x140b13fe13f713f4,  0x1438142d141e1411,  0x148c147b1467144d,  0x14d1143514311422,  0x150c150514fa143c,  0x1593156d1562151a,  0x15ba15b015a515a2,  0x157515e415df15c5,  0x1642163f160a1607,  0x1662165b164c1645,  0x16851682167f167c,  0x16c816b916aa1688,  0x1455145113e0158c,  0x1740172d15261459,  0x177117661758174f,  0x17a3179c17851774,  0x17e515ed17b317aa,  0x144d1411140b17ed,  0x151a1481147b1467,  0x16851557154c1529,  0x17661758158c1688,  0x162c162515ed17b3,  0x15ff15da15d71633,  0x152c161c16191602,  0x1490155d155a152f,  0x1440142a142613fb,  0x15bd159d159a1402,  0x1546153b153415c0,  0x157015171549154c,  0x15ff15da15d715b7,  0x152c161c16191602,  0x1490155d155a152f,  0x1440142a142613fb,  0x15bd159d159a1402,  0x1546153b153415c0,  0x157015171549154c,  0x1546153b153415b7,  0x15c815571529154c,  0x1534150c150514fa,  0x15df15c81546153b,  0x13e313e3,  0x0,  0x0,  0x0,  0x0,  0x1434143014301421,  0x145814541450143b,  0x14c114c514a314a3,  0x1521150114fd1508,  0x15251525151d1521,  0x153e159615651565,  0x154f154f1537153e,  0x15b315a815531553,  0x15cf15cb15cb15b3,  0x15f315f315e715d3,  0x16111615160d15f7,  0x1669166516481648,  0x16ad16c016c416bc,  0x16d216cb16cb16ad,  0x170b170216fe16d2,  0x1716171216f316eb,  0x177716ef00000000,  0x173417471743177b,  0x175b175f17381734,  0x1429140117b617b6,  0x1460143f14431425,  0x14a7148f14ab145c,  0x15ac15421569150f,  0x179f17a616d616b5,  0x174b166d172117ba,  0x168f15fb16bc1665,  0x168b16b1171a1730,  0x14ba1493173016b1,  0x168b13fa164f16f7,  0x173c1513159615e7,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x13d913de165e158f,  0x15eb14e915731706,  0x1497157c1578158a,  0x14f1,  0x0,  0x0,  0x0,  0x0,  0x5401b331b3102f6,  0x1b770093008d0546,  0x2ff1b79,  0x0,  0x0,  0x0,  0x0,  0x0,  0x9931a6b1a6d02fc,  0xe3b00a500a10993,  0x1b451b4f1b4b0e3f,  0x1b351b3b1b391b47,  0x1b411b3f1b3d1b37,  0x98b000000001b43,  0xc000c000c098f,  0x99309930993000c,  0x2fa1b3102f6,  0x8d009305400546,  0xe3b00a500a11a6d,  0x971b4f1b4b0e3f,  0x2f802f402f2009d,  0x54405590548,  0x566009b0099098d,  0x0,  0x5a161f0057,  0x1622006800000061,  0x163000761629006f,  0x163a00841637007d,  0x13e913e613e613d5,  0x13ec178f178f13e9,  0x17ca17ca17ca13ec,  0x13f213d713d717ca,  0x141a13f213f213f2,  0x141c141c141c141a,  0x147014701470141c,  0x13f513f513f51470,  0x13f813f813f813f5,  0x13ff13ff13ff13f8,  0x14e214e014e013ff,  0x140913dc13dc14e2,  0x14f814f814f81409,  0x15321532153214f8,  0x1560156015601532,  0x15a015a015a01560,  0x15c315c315c315a0,  0x15dd15dd15dd15c3,  0x15e215e215e215dd,  0x16051605160515e2,  0x163d163d163d1605,  0x165916591659163d,  0x1677167716771659,  0x14ec14ec14ec1677,  0x140c140c140c14ec,  0x140f140f140f140c,  0x13e113e113e1140f,  0x14151788178813e1,  0x13fc13fc13fc1415,  0x16a2169e169e13fc,  0x169b16a616a616a2,  0x169b,  0x970095008d0000,  0x9f009d009b0099,  0x2f402f200a500a1,  0x30302fa02f802f6,  0x30f034303140305,  0x392038303740365,  0x546054003b003a1,  0x93055905440548,  0x5e305d505680566,  0x687067e062905e6,  0x71a060706cf06ac,  0x7a4077e07230734,  0x85e082c083b06af,  0x77006b2056b088d,  0x98b060a095a0682,  0x9930991098f098d,  0x9a0093706920995,  0x6020ad90a7d0a2e,  0xb79073e0ae00b0d,  0x7870b3b05d30a28,  0x8400a1105d80cd3,  0xde1086a0a240ba3,  0xe3b061106950b41,  0x1b280e410e3f0e3d,  0x1b3f1b3d1b331b2a,  0x1bd61e551e5c1b31,  0x1c181c081bfd1bef,  0x1cee1e171e0f1e02,  0x1bff1bf11bd81c16,  0x1c411c241c1a1c0a,  0x1cad1c991c901c73,  0x1cda1ccd1c1e1cbd,  0x1cf51cf01bfb1cdf,  0x1d111d0f1ca61bde,  0x1d391d1b1d0d1c8e,  0x1c311d9f1d741d55,  0x1e001def1c221ddc,  0x1e1b1e191e111e04,  0x1c5d1e341bed1c35,  0x8b00881c061e42,  0x1a101949194419d4,  0x19501a141a12194b,  0x1a181a1619571955,  0x1a201a1e1a1c1a1a,  0x19661961195c19a6,  0x196f196d196819b0,  0x198e198319811977,  0x199d19981993,  0x19d8194700000000,  0x19e019de19dc19da,  0x19e419e200000000,  0x19ec19ea19e8198c,  0x197519ee00000000,  0x19f819f619f419f2,  0x197f19fa00000000,  0x19fe,  0x90e4b0e450e43,  0x1a820e470e49,  0x1a8b1a891a841b22,  0x1b261b241a90,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x26b600000000,  0x26b9,  0x0,  0x0,  0x26bc000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x26c226bf00000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x26c826c500000000,  0x26d726d326cf26cb,  0x26db,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x26df000000000000,  0x26e626ed26e226ea,  0x26f1,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x5e605e305d50568,  0x6ac0687067e0629,  0x734071a060706cf,  0x6af07a4077e0723,  0x88d085e082c083b,  0x682077006b2056b,  0x9370692060a095a,  0xad90a7d0a2e09a0,  0x73e0ae00b0d0602,  0xb3b05d30a280b79,  0xa1105d80cd30787,  0x86a0a240ba30840,  0x61106950b410de1,  0x5e605e305d50568,  0x6ac0687067e0629,  0x734071a060706cf,  0x6af07a4077e0723,  0x88d085e082c083b,  0x682077006b2056b,  0x9370692060a095a,  0xad90a7d0a2e09a0,  0x73e0ae000000602,  0xb3b05d30a280b79,  0xa1105d80cd30787,  0x86a0a240ba30840,  0x61106950b410de1,  0x5e605e305d50568,  0x6ac0687067e0629,  0x734071a060706cf,  0x6af07a4077e0723,  0x88d085e082c083b,  0x682077006b2056b,  0x9370692060a095a,  0xad90a7d0a2e09a0,  0x73e0ae00b0d0602,  0xb3b05d30a280b79,  0xa1105d80cd30787,  0x86a0a240ba30840,  0x61106950b410de1,  0x5e605e300000568,  0x68700000000,  0x71a06070000,  0x6af07a4077e0000,  0x88d085e0000083b,  0x682077006b2056b,  0x9370692060a095a,  0xad900000a2e09a0,  0x73e0ae00b0d0000,  0xb3b05d30a280b79,  0xa1105d80cd30000,  0x86a0a240ba30840,  0x61106950b410de1,  0x5e605e305d50568,  0x6ac0687067e0629,  0x734071a060706cf,  0x6af07a4077e0723,  0x88d085e082c083b,  0x682077006b2056b,  0x9370692060a095a,  0xad90a7d0a2e09a0,  0x73e0ae00b0d0602,  0xb3b05d30a280b79,  0xa1105d80cd30787,  0x86a0a240ba30840,  0x61106950b410de1,  0x5e6000005d50568,  0x687067e0629,  0x734071a06070000,  0x6af07a4077e0723,  0x88d085e0000083b,  0x682077006b2056b,  0x93706920000095a,  0xad90a7d0a2e09a0,  0x73e0ae00b0d0602,  0xb3b05d30a280b79,  0xa1105d80cd30787,  0x86a0a240ba30840,  0x61106950b410de1,  0x5e6000005d50568,  0x687067e0629,  0x734071a060706cf,  0x7a400000723,  0x88d085e00000000,  0x682077006b2056b,  0x93706920000095a,  0xad90a7d0a2e09a0,  0x73e0ae00b0d0602,  0xb3b05d30a280b79,  0xa1105d80cd30787,  0x86a0a240ba30840,  0x61106950b410de1,  0x5e605e305d50568,  0x6ac0687067e0629,  0x734071a060706cf,  0x6af07a4077e0723,  0x88d085e082c083b,  0x682077006b2056b,  0x9370692060a095a,  0xad90a7d0a2e09a0,  0x73e0ae00b0d0602,  0xb3b05d30a280b79,  0xa1105d80cd30787,  0x86a0a240ba30840,  0x61106950b410de1,  0x6af07a4077e0723,  0x88d085e082c083b,  0x682077006b2056b,  0x9370692060a095a,  0xad90a7d0a2e09a0,  0x73e0ae00b0d0602,  0xb3b05d30a280b79,  0xa1105d80cd30787,  0x9370692060a095a,  0xad90a7d0a2e09a0,  0x73e0ae00b0d0602,  0xb3b05d30a280b79,  0xa1105d80cd30787,  0x86a0a240ba30840,  0x61106950b410de1,  0x5e605e305d50568,  0x6ac0687067e0629,  0x734071a060706cf,  0x6af07a4077e0723,  0x88d085e082c083b,  0x682077006b2056b,  0x9370692060a095a,  0xad90a7d0a2e09a0,  0x73e0ae00b0d0602,  0xb3b05d30a280b79,  0xa1105d80cd30787,  0x86a0a240ba30840,  0x61106950b410de1,  0x5e605e305d50568,  0x6ac0687067e0629,  0x734071a060706cf,  0x6af07a4077e0723,  0x61106950b410de1,  0xe800e6f,  0xf3c0f3a0f380ee3,  0xfad0f5e0f5c0f3e,  0xfe20fe00fde0faf,  0x10060fe80fe60fe4,  0x100f100d0fad1008,  0x1035103310311011,  0x10ea10861aa3077c,  0x110e10f010ee10ec,  0x11ae1170116e1110,  0x11ce11cc11b211b0,  0x11f811f011ee11d0,  0x123c11fe11fc11fa,  0x1a9e12421240123e,  0x123c11ae116e10f0,  0xf380ee311ee11f0,  0xf5c0f3e0f3c0f3a,  0xfde0faf0fad0f5e,  0xfe60fe40fe20fe0,  0xfad100810060fe8,  0x10311011100f100d,  0x1aa3077c10351033,  0x10ee10ec10ea1086,  0x116e1110110e10f0,  0x11b211b011ae1170,  0x11ee11d011ce11cc,  0x11fc11fa11f811f0,  0x1240123e123c11fe,  0x116e10f01a9e1242,  0x11ee11f0123c11ae,  0xf3c0f3a0f380ee3,  0xfad0f5e0f5c0f3e,  0xfe20fe00fde0faf,  0x10060fe80fe60fe4,  0x100f100d0fad1008,  0x1035103310311011,  0x10ea10861aa3077c,  0x110e10f010ee10ec,  0x11ae1170116e1110,  0x11ce11cc11b211b0,  0x11f811f011ee11d0,  0x123c11fe11fc11fa,  0x1a9e12421240123e,  0x123c11ae116e10f0,  0xf380ee311ee11f0,  0xf5c0f3e0f3c0f3a,  0xfde0faf0fad0f5e,  0xfe60fe40fe20fe0,  0xfad100810060fe8,  0x10311011100f100d,  0x1aa3077c10351033,  0x10ee10ec10ea1086,  0x116e1110110e10f0,  0x11b211b011ae1170,  0x11ee11d011ce11cc,  0x11fc11fa11f811f0,  0x1240123e123c11fe,  0x116e10f01a9e1242,  0x11ee11f0123c11ae,  0xf3c0f3a0f380ee3,  0xfad0f5e0f5c0f3e,  0xfe20fe00fde0faf,  0x10060fe80fe60fe4,  0x100f100d0fad1008,  0x1035103310311011,  0x10ea10861aa3077c,  0x110e10f010ee10ec,  0x11ae1170116e1110,  0x11ce11cc11b211b0,  0x11f811f011ee11d0,  0x123c11fe11fc11fa,  0x1a9e12421240123e,  0x123c11ae116e10f0,  0x12a212a011ee11f0,  0x314030500000000,  0x3740365030f0343,  0x3b003a103920383,  0x30f034303140305,  0x392038303740365,  0x314030503b003a1,  0x3740365030f0343,  0x3b003a103920383,  0x30f034303140305,  0x392038303740365,  0x314030503b003a1,  0x3740365030f0343,  0x3b003a103920383,  0x14e013f513f213d7,  0x13f8140917880000,  0x14ec167713fc15c3,  0x15e214f8140f140c,  0x13dc16591560163d,  0x13ff1470141c1532,  0x160515dd15a014e2,  0x1816183a184a1814,  0x13f513f20000,  0x13f80000000013e1,  0x14ec167713fc0000,  0x15e214f8140f140c,  0x16591560163d,  0x13ff1470141c1532,  0x1605000015a00000,  0x0,  0x13f500000000,  0x13f8000000000000,  0x14ec000013fc0000,  0x15e214f8140f0000,  0x165915600000,  0x13ff000000001532,  0x1605000015a00000,  0x18160000184a0000,  0x13f513f20000,  0x13f80000000013e1,  0x167713fc15c3,  0x15e214f8140f140c,  0x16591560163d,  0x13ff1470141c1532,  0x160515dd15a00000,  0x183a00001814,  0x14e013f513f213d7,  0x13f81409178813e1,  0x14ec000013fc15c3,  0x15e214f8140f140c,  0x13dc16591560163d,  0x13ff1470141c1532,  0x160515dd15a014e2,  0x0,  0x14e013f513f20000,  0x13f8140917880000,  0x14ec000013fc15c3,  0x15e214f8140f140c,  0x13dc16591560163d,  0x13ff1470141c1532,  0x160515dd15a014e2,  0x0,  0x3f103160307030a,  0x4fa04de04ab0468,  0x5310520050b,  0x0,  0x10a0106010200fe,  0x11a01160112010e,  0x12a01260122011e,  0x13a01360132012e,  0x14a01460142013e,  0x15a01560152014e,  0x5e31b4d0162015e,  0x93305e5082c,  0x5e605e305d50568,  0x6ac0687067e0629,  0x734071a060706cf,  0x6af07a4077e0723,  0x88d085e082c083b,  0x682077006b2056b,  0x76c06b1060a095a,  0x930082708660860,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x761075e00000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x606,  0x0,  0x0,  0x0,  0x1cad1c9e1bc3,  0x0,  0x0,  0x0,  0x1cf71ff320b02197,  0x208c253220811f17,  0x21e722f221fe1f1d,  0x21eb1f6921451f9d,  0x2560235c24261f93,  0x219d22cc200f2073,  0x25a01eef1ee921b3,  0x21ad20011efd20fa,  0x23f023d221992574,  0x329221b22bc2005,  0x20351f9f2366,  0x0,  0x1b5d1b551b511b69,  0x1b591b711b611b6d,  0x1b65,  0x0,  0x1ffd2147,  0x0,  0x0,  0x0,  0x26f51f0b1f031f07,  0x1f3b1f371f351f2d,  0x1f431f471f411f3f,  0x1f531f5126fd1e63,  0x1e6526f71f631f55,  0x1f7126fb1f691f59,  0x1f7b1f791f251f75,  0x1e691f8d1f8927b9,  0x1fa11f9f1f9b1f99,  0x1fb51faf1fad1e6b,  0x1fc31fbf1fbd1fbb,  0x1fe11fd91fd51fd3,  0x1fe71fe71fe71fe5,  0x1ff51ff122e42703,  0x20031fff1ffb2705,  0x20152013200d2017,  0x2023201f201d2019,  0x202d202920292027,  0x204b203920332031,  0x2043203f204d203d,  0x2057205520711f8f,  0x205b205d20532059,  0x2077207527072067,  0x209620852081207b,  0x209e209c270b2709,  0x1e6d20a4209a20a0,  0x20ac20ac20a81e6f,  0x20be20bc20ba270d,  0x20c820c6270f20c2,  0x20d21e7120cc2137,  0x271320de20e020da,  0x20e820ea271520e4,  0x1e7320f620f420ec,  0x21062104210220fe,  0x21171e7727171e75,  0x27cd211f211b2119,  0x2486271b271b212b,  0x27291e7921332133,  0x1e7b213f213b277d,  0x2157215321512149,  0x21611e7d1e7f215f,  0x216f216d2163271d,  0x21792177216f2171,  0x2183217f217d2181,  0x218f210b21872185,  0x21b121a7219f219b,  0x21b521a921af2723,  0x21c7272521c321b9,  0x21cb1e8121bd21c1,  0x1e8321cd21d321cf,  0x21f5272721df21db,  0x22091e8922032215,  0x1f6d1f6b1e851e87,  0x1ebb2470220b2217,  0x222b2221221f221d,  0x22351e8b27312227,  0x273522462242222f,  0x1e8d224c22392248,  0x225822522250224e,  0x22621e8f225c2737,  0x226a1e9122642739,  0x273b227822762270,  0x273f2288273d2711,  0x2298228a2292228e,  0x22a422a222a822a0,  0x229e274122ac22aa,  0x22c41e9322ba22b8,  0x22d222b4274322c2,  0x22de22d427472745,  0x22e01e9522da22dc,  0x26f922ec22e622e8,  0x274d22fa274922f4,  0x274f2314230a2304,  0x275327512320231e,  0x23381e972336232e,  0x234623441e991e99,  0x1e9b2352234c234a,  0x2757236c2755235e,  0x2759237a27192372,  0x1e9f1e9d275d275b,  0x2763275f27612396,  0x239c239c239a2765,  0x1ea523a21ea323a0,  0x23b023ac27691ea7,  0x23c8276b1ea923b6,  0x23e423d8276f276d,  0x23ec23ea23e81eab,  0x23f8277327732771,  0x2404240227751ead,  0x1eb1241227771eaf,  0x277b241e2416241a,  0x243424301eb3242a,  0x2781277f1eb5243c,  0x2785244827831eb7,  0x278724582454244e,  0x2466278b24622789,  0x247424721eb9272b,  0x278d20a624761ebd,  0x2486272f272d278f,  0x249e1ebf25942488,  0x24a21fa924a0249c,  0x279124aa24a624a4,  0x24b824b624ac24a8,  0x24ce24c424ba24ae,  0x24c224c024be24b4,  0x1ec1279527972793,  0x279f24d824d424d2,  0x1ec51ec3279924da,  0x24ea1ec7279d279b,  0x24f624f024ee24ec,  0x250024f824fa24f4,  0x1ec9250224fe24fc,  0x25101ecb25082506,  0x251a251827a12512,  0x27a31e6725201ecd,  0x25361ed11ecf27a5,  0x27a7255825502542,  0x2576257025642562,  0x257a257c26ff27ab,  0x258c258627012580,  0x25b225ac27af27ad,  0x25cc25b827b125b6,  0x25da25d025d425d2,  0x1ed325e227b325dc,  0x26021ed527b525e6,  0x27bb27b7260e20ee,  0x27bd26221ed91ed7,  0x262e262e27bf1edb,  0x1edd263e27c12632,  0x26542650264c2646,  0x266c265e27c31edf,  0x26741ee31ee12672,  0x27c927c71ee527c5,  0x26901ee7268627cb,  0x269e269a26962694,  0x27cf26a2,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//12288 bytes
+enum canonMappingTrieEntries = TrieEntry!(ushort, 8, 7, 6)([ 0x0,  0x20,  0x120], [ 0x100,  0x400,  0x1380], [ 0x302020202020100,  0x205020202020204,  0x602020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x1000000000000,  0x5000400030002,  0x6,  0x9000800070000,  0xc0000000b000a,  0x0,  0xe00000000000d,  0x0,  0x0,  0x1100000010000f,  0x130012,  0x16001500140000,  0x18000000170000,  0x1a000000190000,  0x0,  0x1c001b0000,  0x1d,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1f001e,  0x0,  0x0,  0x23002200210020,  0x27002600250024,  0x28,  0x2b002a00000029,  0x2f002e002d002c,  0x30,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x31000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x34003300320000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x38003700360035,  0x3c003b003a0039,  0x3e003d,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3f00000000,  0x40,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x43004200410000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x47004600450044,  0x4b004a00490048,  0x4c,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x250012000f000c,  0x850000004f0045,  0xcb00a400a1009e,  0x13301240121011e,  0x1a0019d01880000,  0x1da01b601a3,  0x2730270026d0000,  0x2f30287,  0x33803250322031f,  0x398000003620358,  0x3de03b703b403b1,  0x446043a04370434,  0x4b404b1049c0000,  0x4ee04ca04b7,  0x58a058705840000,  0x61c0000060d059e,  0x33e002b033b0028,  0x38c00790380006d,  0x392007f038f007c,  0x3a2008f03950082,  0x3cd00ba00000000,  0x3db00c803d800c5,  0x3e400d103fb00e8,  0x41000fd040a00f7,  0x419010604130100,  0x41c0109,  0x440012a043d0127,  0x45c01490443012d,  0x130,  0x471015d0462014f,  0x170047701630000,  0x47a01660484,  0x185000000000000,  0x18e04a801940499,  0x4a2,  0x4e401d004d901c5,  0x4f801e4,  0x5450231052f021b,  0x54b023705350221,  0x56902550552023e,  0x57b026405580244,  0x572025b,  0x594027d058d0276,  0x5b4029d059b0284,  0x5e002c905b702a0,  0x61002f605f502de,  0x3110628030b0302,  0x6310314062e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x50401f0,  0x0,  0x0,  0x2ac000000000000,  0x5c3,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x13d036900560000,  0x2a304fb01e70450,  0x28e05a9029205ba,  0x28a05ad029605a5,  0x35b0048000005a1,  0x653064a03540041,  0x416010300000000,  0x522020e046b0157,  0x65f065c05250211,  0x465,  0x40700f4,  0x365005204960182,  0x656064d06500647,  0x36f005c036c0059,  0x3ea00d703e700d4,  0x456014304530140,  0x50101ed04fe01ea,  0x53b022705380224,  0x5c002a905bd02a6,  0x578026105660252,  0x425011200000000,  0x0,  0x351003e00000000,  0x4f101dd03f400e1,  0x4e701d304d101bd,  0x61602fc04ea01d6,  0x0,  0x0,  0x0,  0x66b00000010000d,  0x137,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x662,  0x0,  0x100000000,  0x0,  0x6450670063d0000,  0x72c06df06c3,  0x798077800000759,  0x8d1,  0x0,  0x0,  0x0,  0x0,  0x0,  0x781073500000000,  0x8c10867084707e9,  0x92f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x92808ca00000000,  0x95f091f08fd,  0x9b4000000000000,  0x9b7,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x9c3000009cc09c6,  0x9ba000000000000,  0x0,  0x9ed09d809e4,  0x0,  0x0,  0x9de0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xa200000,  0x0,  0x0,  0x0,  0x0,  0x0,  0xa0500000a0e0a08,  0xa41000000000000,  0x0,  0xa2f0a1a0a26,  0x0,  0x0,  0x0,  0x0,  0x0,  0xa470a4400000000,  0x0,  0x0,  0xa1109cf0000,  0x0,  0x0,  0x0,  0xa0209c009ff09bd,  0xa0b09c900000000,  0xa4d0a4a00000000,  0xa1709d50a1409d2,  0xa1d09db00000000,  0xa2909e70a2309e1,  0xa530a5000000000,  0xa2c09ea0a3e09fc,  0xa3509f30a3209f0,  0xa3809f6,  0xa3b09f9,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xac10abe00000000,  0xaca0ac40ac7,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xacd00000ad3,  0x0,  0x0,  0x0,  0xad0000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xae80000,  0x0,  0xaf10000,  0xaf4,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xadf0adc0ad90ad6,  0xaee0aeb0ae50ae2,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb00000000000000,  0xb03,  0x0,  0x0,  0x0,  0xafd00000afa0af7,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb12000000000000,  0xb1500000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb0c0b090b060000,  0xb0f00000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb1e000000000b21,  0xb24,  0x0,  0x0,  0x0,  0xb1b0b18,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb27,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb300b2a00000000,  0xb2d,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb33,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb36,  0xb40000000000000,  0xb3c0b3900000b43,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb4c0b4600000000,  0xb49,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb4f00000000,  0xb590b550b52,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb5f000000000000,  0x0,  0x0,  0xb620000,  0xb6500000000,  0xb68000000000000,  0x0,  0xb6b,  0x0,  0x0,  0xb5c0000,  0x0,  0xb6e000000000000,  0xb890b710000,  0xb8c,  0x0,  0xb740000,  0x0,  0x0,  0x0,  0xb7a000000000000,  0x0,  0x0,  0xb7d0000,  0xb8000000000,  0xb83000000000000,  0x0,  0xb86,  0x0,  0x0,  0xb770000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb8f00000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb9200000000,  0xb9800000b95,  0xb9e00000b9b,  0xba100000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xba4000000000000,  0xba70000,  0xbb000000bad0baa,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3830070037d006a,  0x389007603860073,  0x39f008c039b0088,  0x3ae009b03a50092,  0x3ab009803a80095,  0x3d400c103d000bd,  0x40100ee03fe00eb,  0x40400f103f700e4,  0x41f010c040d00fa,  0x422010f04280115,  0x42e011b042b0118,  0x4490136045f014c,  0x46e015a04680154,  0x47d016904740160,  0x48a01760480016c,  0x48d017904870173,  0x493017f0490017c,  0x4a50191049f018b,  0x4ab019704ae019a,  0x4d501c104cd01b9,  0x4e001cc04dc01c8,  0x52c021805290215,  0x53e022a0532021e,  0x54802340541022d,  0x55f024b05550241,  0x55b0247054e023a,  0x56c02580562024e,  0x581026a0575025e,  0x5dd02c6057e0267,  0x5e302cc05e602cf,  0x597028005900279,  0x5ec02d505e902d2,  0x5f202db05ef02d8,  0x5f802e105fb02e4,  0x60402ea060102e7,  0x61902ff060702ed,  0x6340317062b030e,  0x56f04310637031a,  0x6590000062205fe,  0x0,  0x35f004c0372005f,  0x3280015032c0019,  0x330001d03340021,  0x345003203750062,  0x34d003a0341002e,  0x379006603490036,  0x3e100ce03ed00da,  0x3be00ab03ca00b7,  0x3c600b303ba00a7,  0x3f000dd03c200af,  0x4590146044d013a,  0x4f501e1051b0207,  0x4ba01a604be01aa,  0x4c201ae04c601b2,  0x50b01f7051e020a,  0x51301ff050701f3,  0x5170203050f01fb,  0x5b1029a05da02c3,  0x5c602af05ca02b3,  0x5ce02b705d202bb,  0x60a02f005d602bf,  0x61f030506250308,  0x61302f9,  0x0,  0x81b07f9081807f6,  0x82d080b08240802,  0x69e067c069b0679,  0x6b0068e06a70685,  0x858084d0855084a,  0x85c0851,  0x6d406c906d106c6,  0x6d806cd,  0x89308710890086e,  0x8a50883089c087a,  0x70706e5070406e2,  0x71906f7071006ee,  0x8eb08dc08e808d9,  0x8f308e408ef08e0,  0x74a073b07470738,  0x7520743074e073f,  0x90e0903090b0900,  0x9120907,  0x76a075f0767075c,  0x76e0763,  0x949093a09460937,  0x9510942094d093e,  0x787000007840000,  0x78f0000078b0000,  0x98b096909880966,  0x99d097b09940972,  0x7c0079e07bd079b,  0x7d207b007c907a7,  0x847084407e907e2,  0x8c108be08670860,  0x91f091c08fd08fa,  0x95f0958,  0x81f07fd08360814,  0x831080f08280806,  0x6a2068006b90697,  0x6b4069206ab0689,  0x897087508ae088c,  0x8a9088708a0087e,  0x70b06e907220700,  0x71d06fb071406f2,  0x98f096d09a60984,  0x9a1097f09980976,  0x7c407a207db07b9,  0x7d607b407cd07ab,  0x84107e507f007f3,  0x83d083a000007ec,  0x670066d06730676,  0x8bc000006bd,  0x8b9086306400000,  0x8b508b20000086a,  0x6df06dc06c306c0,  0xbb90bb60bb30726,  0x8d108cd08c408c7,  0x8d508f700000000,  0x72c0729072f0732,  0xbc20bbf0bbc0000,  0x92f092b09220925,  0x933095509190916,  0x7780775077b077e,  0x31d063d063a0772,  0x9b1095b00000000,  0x9ad09aa00000962,  0x798079507590756,  0x64307df,  0xbc70bc5,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x79300000000,  0x4f015200000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xbcc0bc900000000,  0x0,  0x0,  0x0,  0x0,  0xbcf00000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xbd50bd80bd20000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xbdb,  0xbde0000,  0xbe1,  0x0,  0x0,  0x0,  0x0,  0x0,  0xbe700000be4,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xbea0000,  0xbf0000000000bed,  0xbf30000,  0x0,  0x0,  0x0,  0x0,  0x0,  0xbf900000006,  0x0,  0x0,  0x900030bf60000,  0xbff0bfc,  0xc050c02,  0xc0b0c08,  0x0,  0xc110c0e,  0xc1d0c1a,  0xc230c20,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc350c320c2f0c2c,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc290c260c170c14,  0x0,  0xc3b0c3800000000,  0xc410c3e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc490c470000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc44,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc5100000c4e,  0xc5700000c54,  0xc5d00000c5a,  0xc6300000c60,  0xc6900000c66,  0xc6f00000c6c,  0xc7500000c720000,  0xc780000,  0x0,  0xc8100000c7e0c7b,  0xc8a0c8700000c84,  0xc900c8d0000,  0xc960c93,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc4b,  0x0,  0xc9900000000,  0x0,  0x0,  0x0,  0xca200000c9f,  0xca800000ca5,  0xcae00000cab,  0xcb400000cb1,  0xcba00000cb7,  0xcc000000cbd,  0xcc600000cc30000,  0xcc90000,  0x0,  0xcd200000ccf0ccc,  0xcdb0cd800000cd5,  0xce10cde0000,  0xce70ce4,  0x0,  0x0,  0x0,  0x0,  0x0,  0xcea000000000c9c,  0xcf30cf00ced,  0xcf600000000,  0x124b125d0fb71241,  0x13270e290d831043,  0xe4f12930e991327,  0x116710cd0f550e97,  0x1279121511fd11e3,  0x109d106910190feb,  0xd8d12f3128911c7,  0x11e110790ff50e1d,  0x11d910510edb1309,  0x120311890f65121d,  0x108d10250fbd0eff,  0xe050dd90d9d127d,  0x10d310770ff10f95,  0x125911e711dd1171,  0x10e9130712fb12cf,  0x12a111b9114d1107,  0xf0b0e87122f130b,  0x10ed1083117d112f,  0xecb0e8512cb1249,  0x11471047102f0fed,  0x117f0e0312b11159,  0x114f11150ddd0ddf,  0xf67123d12b511c5,  0xebb0d8712350feb,  0xe1110c110950f27,  0xd7f0f1b0da510f1,  0xe2311450f9d1011,  0x122711c910d70e7d,  0xf6f100d126d1005,  0xd9110bf0f7b11a5,  0x113d0fdb0ddb0dc3,  0xe091291122d1195,  0xfa10f070e9f0e37,  0x12f712ab10f31053,  0xfb50df91313130d,  0xf490ef312690ffd,  0x106d104b0f910f57,  0x11791153111110af,  0x12a3127111cd1261,  0x10670e410dfb0de9,  0xf230efd1227120b,  0x1091112d10030f77,  0xee50ebb0e670d97,  0x116b10a9109b0f29,  0x12d112c912951175,  0x128d110f0d9f12dd,  0xdb10d8f0f3512c1,  0xfeb0f9f0ec70ebd,  0x127711d310cb1073,  0xdf712af0fad1323,  0x103b10210fd10fcb,  0x114310e710bd10a1,  0x12b70f5d0dc512e3,  0x126310310ed70da9,  0x10950fd50f390f17,  0xecf0e310deb12bb,  0x10150fe10fc30fa7,  0x120d116310c3109f,  0xe1312c5128f1213,  0x10b110750e33103d,  0x130f12ff12bd11db,  0x1121118b102d0fcf,  0x1063108b11331125,  0xded11ad0d93123b,  0x11390f690ef50de7,  0x12670fb3101b0eb5,  0xf03122112b31205,  0xe590db5,  0xfab00000e7b,  0x10cf108f0de10000,  0x110d1105110310f5,  0x116d113512d3,  0x1233000011df,  0x128312730000,  0x12e912e700000000,  0x12bf127f130512eb,  0xe010db90db30da1,  0xe5f0e530e170e07,  0xecd0e7f0e790e63,  0xf470f430f2f0ed1,  0xfaf0fa30f970f53,  0x1049103510270fdd,  0x10eb10a3107d106f,  0x10fd10f910fb10f7,  0x110b1109110110ff,  0x11531127111d1117,  0x11731161115b1157,  0x11cb11971197118d,  0x1239123712231219,  0x1273126f124f124d,  0xf2b12e112d912c7,  0x119313be,  0xd9b0dc10dd70d81,  0xe0b0dff0dc90db7,  0xe5d0e510e490e53,  0xe9b0e950e830e7b,  0xf050f010eb10ea9,  0xf3f0f330f1d0f13,  0xf530f410f470f37,  0xf890f850f7f0f5f,  0xfbf0fbd0fab0f99,  0x102110050fff0fc7,  0x1057104910411045,  0x1089107f10e3106f,  0x10b910b510ab108f,  0x10d110cf10c910c7,  0x10ef10dd10df10d5,  0x114911311127111f,  0x11af1173115f1153,  0x121f121b11f911c3,  0x122b123312291223,  0x1239123112351237,  0x12751265124f123f,  0x12c712b91299128b,  0x12db12d912d512d3,  0x1394132712f912e1,  0xd370d2313a61392,  0x141c13ec13da0d39,  0x13251321,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xabb00000a7a0000,  0x0,  0x0,  0xab50ab200000000,  0xa590a560aae0aaa,  0xa680a650a5f0a5c,  0xa740a710a6b,  0xa830a800a7d0a77,  0xa8c00000a89,  0xa9500000a920a8f,  0xaa10a9e00000a98,  0xa6e0ab80aa70aa4,  0xa9b0a860a62,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x132900000000,  0x132c,  0x0,  0x0,  0x132f000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1335133200000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x133b133800000000,  0x134a13461342133e,  0x134e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1352000000000000,  0x135913601355135d,  0x1364,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x13680d8b0d850d89,  0xda70da30da10d99,  0xdaf0db30dad0dab,  0xdbb0db913700cf9,  0xcfb136a0dc70dbd,  0xdd1136e0dcb0dbf,  0xdd70dd50d950dd3,  0xcff0de50de3142c,  0xdf50df30df10def,  0xe070e010dff0d01,  0xe110e0f0e0d0e0b,  0xe1b0e190e170e15,  0xe210e210e210e1f,  0xe270e25105d1376,  0xe2f0e2d0e2b1378,  0xe3b0e390e350e3d,  0xe470e450e430e3f,  0xe510e4d0e4d0e4b,  0xe690e5b0e570e55,  0xe650e610e6b0e5f,  0xe710e6f0e890de7,  0xe750e770e6d0e73,  0xe8d0e8b137a0e81,  0xe9d0e930e910e8f,  0xea50ea3137e137c,  0xd030eab0ea10ea7,  0xeb30eb30eaf0d05,  0xebb0eb90eb71380,  0xec30ec113820ebf,  0xec90d070ec50f0f,  0x13860ed30ed50ed1,  0xedd0edf13880ed9,  0xd090ee90ee70ee1,  0xef10eef0eed0eeb,  0xef70d0d138a0d0b,  0x14400eff0efb0ef9,  0x118f138e138e0f09,  0x139c0d0f0f0d0f0d,  0xd110f150f1113f0,  0xf250f210f1f0f19,  0xf2f0d130d150f2d,  0xf3d0f3b0f311390,  0xf470f450f3d0f3f,  0xf510f4d0f4b0f4f,  0xf5b0f590f550f53,  0xf730f6b0f630f61,  0xf750f6d0f711396,  0xf8713980f830f79,  0xf8b0d170f7d0f81,  0xd190f8d0f930f8f,  0xfa5139a0f9b0f97,  0xfaf0d1f0fa90fb9,  0xdcf0dcd0d1b0d1d,  0xd5111810fb10fbb,  0xfc90fc10fbf0fbd,  0xfd30d2113a40fc5,  0x13a80fdd0fd90fcd,  0xd230fe30fd70fdf,  0xfef0fe90fe70fe5,  0xff70d250ff313aa,  0xffb0d270ff913ac,  0x13ae100710051001,  0x13b2100913b01384,  0x1017100b1013100f,  0x102310211027101f,  0x101d13b4102b1029,  0x10410d2910391037,  0x104d103313b6103f,  0x1059104f13ba13b8,  0x105b0d2b10551057,  0x136c1065105f1061,  0x13c0107113bc106b,  0x13c21081107f107b,  0x13c613c410871085,  0x10990d2d10971093,  0x10a710a50d2f0d2f,  0xd3110b310ad10ab,  0x13ca10bb13c810b7,  0x13cc10c5138c10c1,  0xd350d3313d013ce,  0x13d613d213d410d5,  0x10db10db10d913d8,  0xd3b10e10d3910df,  0x10e910e513dc0d3d,  0x10ff13de0d3f10ef,  0x1113110d13e213e0,  0x111b111911170d41,  0x112313e613e613e4,  0x112b112913e80d43,  0xd47113713ea0d45,  0x13ee1141113b113f,  0x115511510d49114b,  0x13f413f20d4b115d,  0x13f8116513f60d4d,  0x13fa1173116f1169,  0x117b13fe117713fc,  0x118511830d4f139e,  0x14000ead11870d53,  0x118f13a213a01402,  0x119b0d55126b1191,  0x119f0dfd119d1199,  0x140411a711a311a1,  0x11b511b311a911a5,  0x11cb11c111b711ab,  0x11bf11bd11bb11b1,  0xd571408140a1406,  0x141211d511d111cf,  0xd5b0d59140c11d7,  0x11e50d5d1410140e,  0x11ef11eb11e911e7,  0x11f911f111f311ed,  0xd5f11fb11f711f5,  0x12070d61120111ff,  0x1211120f14141209,  0x14160cfd12170d63,  0x12250d670d651418,  0x141a1243123f1231,  0x1253125112471245,  0x125512571372141e,  0x1265125f1374125b,  0x1281127b14221420,  0x1297128714241285,  0x12a5129b129f129d,  0xd6912a9142612a7,  0x12c30d6b142812ad,  0x142e142a12cd0ee3,  0x143012d70d6f0d6d,  0x12db12db14320d71,  0xd7312e5143412df,  0x12f512f112ef12ed,  0x12fd12f914360d75,  0x13030d790d771301,  0x143c143a0d7b1438,  0x13150d7d1311143e,  0x131d131b13191317,  0x1442131f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+@property
+{
+private alias _IDCA = immutable(dchar[]);
+_IDCA decompCanonTable() { static _IDCA t = [ 0x0,  0x3b,  0x0,  0x3c,  0x338,  0x0,  0x3d,  0x338,  0x0,  0x3e,  0x338,  0x0,  0x41,  0x300,  0x0,  0x41,  0x301,  0x0,  0x41,  0x302,  0x0,  0x41,  0x302,  0x300,  0x0,  0x41,  0x302,  0x301,  0x0,  0x41,  0x302,  0x303,  0x0,  0x41,  0x302,  0x309,  0x0,  0x41,  0x303,  0x0,  0x41,  0x304,  0x0,  0x41,  0x306,  0x0,  0x41,  0x306,  0x300,  0x0,  0x41,  0x306,  0x301,  0x0,  0x41,  0x306,  0x303,  0x0,  0x41,  0x306,  0x309,  0x0,  0x41,  0x307,  0x0,  0x41,  0x307,  0x304,  0x0,  0x41,  0x308,  0x0,  0x41,  0x308,  0x304,  0x0,  0x41,  0x309,  0x0,  0x41,  0x30a,  0x0,  0x41,  0x30a,  0x301,  0x0,  0x41,  0x30c,  0x0,  0x41,  0x30f,  0x0,  0x41,  0x311,  0x0,  0x41,  0x323,  0x0,  0x41,  0x323,  0x302,  0x0,  0x41,  0x323,  0x306,  0x0,  0x41,  0x325,  0x0,  0x41,  0x328,  0x0,  0x42,  0x307,  0x0,  0x42,  0x323,  0x0,  0x42,  0x331,  0x0,  0x43,  0x301,  0x0,  0x43,  0x302,  0x0,  0x43,  0x307,  0x0,  0x43,  0x30c,  0x0,  0x43,  0x327,  0x0,  0x43,  0x327,  0x301,  0x0,  0x44,  0x307,  0x0,  0x44,  0x30c,  0x0,  0x44,  0x323,  0x0,  0x44,  0x327,  0x0,  0x44,  0x32d,  0x0,  0x44,  0x331,  0x0,  0x45,  0x300,  0x0,  0x45,  0x301,  0x0,  0x45,  0x302,  0x0,  0x45,  0x302,  0x300,  0x0,  0x45,  0x302,  0x301,  0x0,  0x45,  0x302,  0x303,  0x0,  0x45,  0x302,  0x309,  0x0,  0x45,  0x303,  0x0,  0x45,  0x304,  0x0,  0x45,  0x304,  0x300,  0x0,  0x45,  0x304,  0x301,  0x0,  0x45,  0x306,  0x0,  0x45,  0x307,  0x0,  0x45,  0x308,  0x0,  0x45,  0x309,  0x0,  0x45,  0x30c,  0x0,  0x45,  0x30f,  0x0,  0x45,  0x311,  0x0,  0x45,  0x323,  0x0,  0x45,  0x323,  0x302,  0x0,  0x45,  0x327,  0x0,  0x45,  0x327,  0x306,  0x0,  0x45,  0x328,  0x0,  0x45,  0x32d,  0x0,  0x45,  0x330,  0x0,  0x46,  0x307,  0x0,  0x47,  0x301,  0x0,  0x47,  0x302,  0x0,  0x47,  0x304,  0x0,  0x47,  0x306,  0x0,  0x47,  0x307,  0x0,  0x47,  0x30c,  0x0,  0x47,  0x327,  0x0,  0x48,  0x302,  0x0,  0x48,  0x307,  0x0,  0x48,  0x308,  0x0,  0x48,  0x30c,  0x0,  0x48,  0x323,  0x0,  0x48,  0x327,  0x0,  0x48,  0x32e,  0x0,  0x49,  0x300,  0x0,  0x49,  0x301,  0x0,  0x49,  0x302,  0x0,  0x49,  0x303,  0x0,  0x49,  0x304,  0x0,  0x49,  0x306,  0x0,  0x49,  0x307,  0x0,  0x49,  0x308,  0x0,  0x49,  0x308,  0x301,  0x0,  0x49,  0x309,  0x0,  0x49,  0x30c,  0x0,  0x49,  0x30f,  0x0,  0x49,  0x311,  0x0,  0x49,  0x323,  0x0,  0x49,  0x328,  0x0,  0x49,  0x330,  0x0,  0x4a,  0x302,  0x0,  0x4b,  0x0,  0x4b,  0x301,  0x0,  0x4b,  0x30c,  0x0,  0x4b,  0x323,  0x0,  0x4b,  0x327,  0x0,  0x4b,  0x331,  0x0,  0x4c,  0x301,  0x0,  0x4c,  0x30c,  0x0,  0x4c,  0x323,  0x0,  0x4c,  0x323,  0x304,  0x0,  0x4c,  0x327,  0x0,  0x4c,  0x32d,  0x0,  0x4c,  0x331,  0x0,  0x4d,  0x301,  0x0,  0x4d,  0x307,  0x0,  0x4d,  0x323,  0x0,  0x4e,  0x300,  0x0,  0x4e,  0x301,  0x0,  0x4e,  0x303,  0x0,  0x4e,  0x307,  0x0,  0x4e,  0x30c,  0x0,  0x4e,  0x323,  0x0,  0x4e,  0x327,  0x0,  0x4e,  0x32d,  0x0,  0x4e,  0x331,  0x0,  0x4f,  0x300,  0x0,  0x4f,  0x301,  0x0,  0x4f,  0x302,  0x0,  0x4f,  0x302,  0x300,  0x0,  0x4f,  0x302,  0x301,  0x0,  0x4f,  0x302,  0x303,  0x0,  0x4f,  0x302,  0x309,  0x0,  0x4f,  0x303,  0x0,  0x4f,  0x303,  0x301,  0x0,  0x4f,  0x303,  0x304,  0x0,  0x4f,  0x303,  0x308,  0x0,  0x4f,  0x304,  0x0,  0x4f,  0x304,  0x300,  0x0,  0x4f,  0x304,  0x301,  0x0,  0x4f,  0x306,  0x0,  0x4f,  0x307,  0x0,  0x4f,  0x307,  0x304,  0x0,  0x4f,  0x308,  0x0,  0x4f,  0x308,  0x304,  0x0,  0x4f,  0x309,  0x0,  0x4f,  0x30b,  0x0,  0x4f,  0x30c,  0x0,  0x4f,  0x30f,  0x0,  0x4f,  0x311,  0x0,  0x4f,  0x31b,  0x0,  0x4f,  0x31b,  0x300,  0x0,  0x4f,  0x31b,  0x301,  0x0,  0x4f,  0x31b,  0x303,  0x0,  0x4f,  0x31b,  0x309,  0x0,  0x4f,  0x31b,  0x323,  0x0,  0x4f,  0x323,  0x0,  0x4f,  0x323,  0x302,  0x0,  0x4f,  0x328,  0x0,  0x4f,  0x328,  0x304,  0x0,  0x50,  0x301,  0x0,  0x50,  0x307,  0x0,  0x52,  0x301,  0x0,  0x52,  0x307,  0x0,  0x52,  0x30c,  0x0,  0x52,  0x30f,  0x0,  0x52,  0x311,  0x0,  0x52,  0x323,  0x0,  0x52,  0x323,  0x304,  0x0,  0x52,  0x327,  0x0,  0x52,  0x331,  0x0,  0x53,  0x301,  0x0,  0x53,  0x301,  0x307,  0x0,  0x53,  0x302,  0x0,  0x53,  0x307,  0x0,  0x53,  0x30c,  0x0,  0x53,  0x30c,  0x307,  0x0,  0x53,  0x323,  0x0,  0x53,  0x323,  0x307,  0x0,  0x53,  0x326,  0x0,  0x53,  0x327,  0x0,  0x54,  0x307,  0x0,  0x54,  0x30c,  0x0,  0x54,  0x323,  0x0,  0x54,  0x326,  0x0,  0x54,  0x327,  0x0,  0x54,  0x32d,  0x0,  0x54,  0x331,  0x0,  0x55,  0x300,  0x0,  0x55,  0x301,  0x0,  0x55,  0x302,  0x0,  0x55,  0x303,  0x0,  0x55,  0x303,  0x301,  0x0,  0x55,  0x304,  0x0,  0x55,  0x304,  0x308,  0x0,  0x55,  0x306,  0x0,  0x55,  0x308,  0x0,  0x55,  0x308,  0x300,  0x0,  0x55,  0x308,  0x301,  0x0,  0x55,  0x308,  0x304,  0x0,  0x55,  0x308,  0x30c,  0x0,  0x55,  0x309,  0x0,  0x55,  0x30a,  0x0,  0x55,  0x30b,  0x0,  0x55,  0x30c,  0x0,  0x55,  0x30f,  0x0,  0x55,  0x311,  0x0,  0x55,  0x31b,  0x0,  0x55,  0x31b,  0x300,  0x0,  0x55,  0x31b,  0x301,  0x0,  0x55,  0x31b,  0x303,  0x0,  0x55,  0x31b,  0x309,  0x0,  0x55,  0x31b,  0x323,  0x0,  0x55,  0x323,  0x0,  0x55,  0x324,  0x0,  0x55,  0x328,  0x0,  0x55,  0x32d,  0x0,  0x55,  0x330,  0x0,  0x56,  0x303,  0x0,  0x56,  0x323,  0x0,  0x57,  0x300,  0x0,  0x57,  0x301,  0x0,  0x57,  0x302,  0x0,  0x57,  0x307,  0x0,  0x57,  0x308,  0x0,  0x57,  0x323,  0x0,  0x58,  0x307,  0x0,  0x58,  0x308,  0x0,  0x59,  0x300,  0x0,  0x59,  0x301,  0x0,  0x59,  0x302,  0x0,  0x59,  0x303,  0x0,  0x59,  0x304,  0x0,  0x59,  0x307,  0x0,  0x59,  0x308,  0x0,  0x59,  0x309,  0x0,  0x59,  0x323,  0x0,  0x5a,  0x301,  0x0,  0x5a,  0x302,  0x0,  0x5a,  0x307,  0x0,  0x5a,  0x30c,  0x0,  0x5a,  0x323,  0x0,  0x5a,  0x331,  0x0,  0x60,  0x0,  0x61,  0x300,  0x0,  0x61,  0x301,  0x0,  0x61,  0x302,  0x0,  0x61,  0x302,  0x300,  0x0,  0x61,  0x302,  0x301,  0x0,  0x61,  0x302,  0x303,  0x0,  0x61,  0x302,  0x309,  0x0,  0x61,  0x303,  0x0,  0x61,  0x304,  0x0,  0x61,  0x306,  0x0,  0x61,  0x306,  0x300,  0x0,  0x61,  0x306,  0x301,  0x0,  0x61,  0x306,  0x303,  0x0,  0x61,  0x306,  0x309,  0x0,  0x61,  0x307,  0x0,  0x61,  0x307,  0x304,  0x0,  0x61,  0x308,  0x0,  0x61,  0x308,  0x304,  0x0,  0x61,  0x309,  0x0,  0x61,  0x30a,  0x0,  0x61,  0x30a,  0x301,  0x0,  0x61,  0x30c,  0x0,  0x61,  0x30f,  0x0,  0x61,  0x311,  0x0,  0x61,  0x323,  0x0,  0x61,  0x323,  0x302,  0x0,  0x61,  0x323,  0x306,  0x0,  0x61,  0x325,  0x0,  0x61,  0x328,  0x0,  0x62,  0x307,  0x0,  0x62,  0x323,  0x0,  0x62,  0x331,  0x0,  0x63,  0x301,  0x0,  0x63,  0x302,  0x0,  0x63,  0x307,  0x0,  0x63,  0x30c,  0x0,  0x63,  0x327,  0x0,  0x63,  0x327,  0x301,  0x0,  0x64,  0x307,  0x0,  0x64,  0x30c,  0x0,  0x64,  0x323,  0x0,  0x64,  0x327,  0x0,  0x64,  0x32d,  0x0,  0x64,  0x331,  0x0,  0x65,  0x300,  0x0,  0x65,  0x301,  0x0,  0x65,  0x302,  0x0,  0x65,  0x302,  0x300,  0x0,  0x65,  0x302,  0x301,  0x0,  0x65,  0x302,  0x303,  0x0,  0x65,  0x302,  0x309,  0x0,  0x65,  0x303,  0x0,  0x65,  0x304,  0x0,  0x65,  0x304,  0x300,  0x0,  0x65,  0x304,  0x301,  0x0,  0x65,  0x306,  0x0,  0x65,  0x307,  0x0,  0x65,  0x308,  0x0,  0x65,  0x309,  0x0,  0x65,  0x30c,  0x0,  0x65,  0x30f,  0x0,  0x65,  0x311,  0x0,  0x65,  0x323,  0x0,  0x65,  0x323,  0x302,  0x0,  0x65,  0x327,  0x0,  0x65,  0x327,  0x306,  0x0,  0x65,  0x328,  0x0,  0x65,  0x32d,  0x0,  0x65,  0x330,  0x0,  0x66,  0x307,  0x0,  0x67,  0x301,  0x0,  0x67,  0x302,  0x0,  0x67,  0x304,  0x0,  0x67,  0x306,  0x0,  0x67,  0x307,  0x0,  0x67,  0x30c,  0x0,  0x67,  0x327,  0x0,  0x68,  0x302,  0x0,  0x68,  0x307,  0x0,  0x68,  0x308,  0x0,  0x68,  0x30c,  0x0,  0x68,  0x323,  0x0,  0x68,  0x327,  0x0,  0x68,  0x32e,  0x0,  0x68,  0x331,  0x0,  0x69,  0x300,  0x0,  0x69,  0x301,  0x0,  0x69,  0x302,  0x0,  0x69,  0x303,  0x0,  0x69,  0x304,  0x0,  0x69,  0x306,  0x0,  0x69,  0x308,  0x0,  0x69,  0x308,  0x301,  0x0,  0x69,  0x309,  0x0,  0x69,  0x30c,  0x0,  0x69,  0x30f,  0x0,  0x69,  0x311,  0x0,  0x69,  0x323,  0x0,  0x69,  0x328,  0x0,  0x69,  0x330,  0x0,  0x6a,  0x302,  0x0,  0x6a,  0x30c,  0x0,  0x6b,  0x301,  0x0,  0x6b,  0x30c,  0x0,  0x6b,  0x323,  0x0,  0x6b,  0x327,  0x0,  0x6b,  0x331,  0x0,  0x6c,  0x301,  0x0,  0x6c,  0x30c,  0x0,  0x6c,  0x323,  0x0,  0x6c,  0x323,  0x304,  0x0,  0x6c,  0x327,  0x0,  0x6c,  0x32d,  0x0,  0x6c,  0x331,  0x0,  0x6d,  0x301,  0x0,  0x6d,  0x307,  0x0,  0x6d,  0x323,  0x0,  0x6e,  0x300,  0x0,  0x6e,  0x301,  0x0,  0x6e,  0x303,  0x0,  0x6e,  0x307,  0x0,  0x6e,  0x30c,  0x0,  0x6e,  0x323,  0x0,  0x6e,  0x327,  0x0,  0x6e,  0x32d,  0x0,  0x6e,  0x331,  0x0,  0x6f,  0x300,  0x0,  0x6f,  0x301,  0x0,  0x6f,  0x302,  0x0,  0x6f,  0x302,  0x300,  0x0,  0x6f,  0x302,  0x301,  0x0,  0x6f,  0x302,  0x303,  0x0,  0x6f,  0x302,  0x309,  0x0,  0x6f,  0x303,  0x0,  0x6f,  0x303,  0x301,  0x0,  0x6f,  0x303,  0x304,  0x0,  0x6f,  0x303,  0x308,  0x0,  0x6f,  0x304,  0x0,  0x6f,  0x304,  0x300,  0x0,  0x6f,  0x304,  0x301,  0x0,  0x6f,  0x306,  0x0,  0x6f,  0x307,  0x0,  0x6f,  0x307,  0x304,  0x0,  0x6f,  0x308,  0x0,  0x6f,  0x308,  0x304,  0x0,  0x6f,  0x309,  0x0,  0x6f,  0x30b,  0x0,  0x6f,  0x30c,  0x0,  0x6f,  0x30f,  0x0,  0x6f,  0x311,  0x0,  0x6f,  0x31b,  0x0,  0x6f,  0x31b,  0x300,  0x0,  0x6f,  0x31b,  0x301,  0x0,  0x6f,  0x31b,  0x303,  0x0,  0x6f,  0x31b,  0x309,  0x0,  0x6f,  0x31b,  0x323,  0x0,  0x6f,  0x323,  0x0,  0x6f,  0x323,  0x302,  0x0,  0x6f,  0x328,  0x0,  0x6f,  0x328,  0x304,  0x0,  0x70,  0x301,  0x0,  0x70,  0x307,  0x0,  0x72,  0x301,  0x0,  0x72,  0x307,  0x0,  0x72,  0x30c,  0x0,  0x72,  0x30f,  0x0,  0x72,  0x311,  0x0,  0x72,  0x323,  0x0,  0x72,  0x323,  0x304,  0x0,  0x72,  0x327,  0x0,  0x72,  0x331,  0x0,  0x73,  0x301,  0x0,  0x73,  0x301,  0x307,  0x0,  0x73,  0x302,  0x0,  0x73,  0x307,  0x0,  0x73,  0x30c,  0x0,  0x73,  0x30c,  0x307,  0x0,  0x73,  0x323,  0x0,  0x73,  0x323,  0x307,  0x0,  0x73,  0x326,  0x0,  0x73,  0x327,  0x0,  0x74,  0x307,  0x0,  0x74,  0x308,  0x0,  0x74,  0x30c,  0x0,  0x74,  0x323,  0x0,  0x74,  0x326,  0x0,  0x74,  0x327,  0x0,  0x74,  0x32d,  0x0,  0x74,  0x331,  0x0,  0x75,  0x300,  0x0,  0x75,  0x301,  0x0,  0x75,  0x302,  0x0,  0x75,  0x303,  0x0,  0x75,  0x303,  0x301,  0x0,  0x75,  0x304,  0x0,  0x75,  0x304,  0x308,  0x0,  0x75,  0x306,  0x0,  0x75,  0x308,  0x0,  0x75,  0x308,  0x300,  0x0,  0x75,  0x308,  0x301,  0x0,  0x75,  0x308,  0x304,  0x0,  0x75,  0x308,  0x30c,  0x0,  0x75,  0x309,  0x0,  0x75,  0x30a,  0x0,  0x75,  0x30b,  0x0,  0x75,  0x30c,  0x0,  0x75,  0x30f,  0x0,  0x75,  0x311,  0x0,  0x75,  0x31b,  0x0,  0x75,  0x31b,  0x300,  0x0,  0x75,  0x31b,  0x301,  0x0,  0x75,  0x31b,  0x303,  0x0,  0x75,  0x31b,  0x309,  0x0,  0x75,  0x31b,  0x323,  0x0,  0x75,  0x323,  0x0,  0x75,  0x324,  0x0,  0x75,  0x328,  0x0,  0x75,  0x32d,  0x0,  0x75,  0x330,  0x0,  0x76,  0x303,  0x0,  0x76,  0x323,  0x0,  0x77,  0x300,  0x0,  0x77,  0x301,  0x0,  0x77,  0x302,  0x0,  0x77,  0x307,  0x0,  0x77,  0x308,  0x0,  0x77,  0x30a,  0x0,  0x77,  0x323,  0x0,  0x78,  0x307,  0x0,  0x78,  0x308,  0x0,  0x79,  0x300,  0x0,  0x79,  0x301,  0x0,  0x79,  0x302,  0x0,  0x79,  0x303,  0x0,  0x79,  0x304,  0x0,  0x79,  0x307,  0x0,  0x79,  0x308,  0x0,  0x79,  0x309,  0x0,  0x79,  0x30a,  0x0,  0x79,  0x323,  0x0,  0x7a,  0x301,  0x0,  0x7a,  0x302,  0x0,  0x7a,  0x307,  0x0,  0x7a,  0x30c,  0x0,  0x7a,  0x323,  0x0,  0x7a,  0x331,  0x0,  0xa8,  0x300,  0x0,  0xa8,  0x301,  0x0,  0xa8,  0x342,  0x0,  0xb4,  0x0,  0xb7,  0x0,  0xc6,  0x301,  0x0,  0xc6,  0x304,  0x0,  0xd8,  0x301,  0x0,  0xe6,  0x301,  0x0,  0xe6,  0x304,  0x0,  0xf8,  0x301,  0x0,  0x17f,  0x307,  0x0,  0x1b7,  0x30c,  0x0,  0x292,  0x30c,  0x0,  0x2b9,  0x0,  0x300,  0x0,  0x301,  0x0,  0x308,  0x301,  0x0,  0x313,  0x0,  0x391,  0x300,  0x0,  0x391,  0x301,  0x0,  0x391,  0x304,  0x0,  0x391,  0x306,  0x0,  0x391,  0x313,  0x0,  0x391,  0x313,  0x300,  0x0,  0x391,  0x313,  0x300,  0x345,  0x0,  0x391,  0x313,  0x301,  0x0,  0x391,  0x313,  0x301,  0x345,  0x0,  0x391,  0x313,  0x342,  0x0,  0x391,  0x313,  0x342,  0x345,  0x0,  0x391,  0x313,  0x345,  0x0,  0x391,  0x314,  0x0,  0x391,  0x314,  0x300,  0x0,  0x391,  0x314,  0x300,  0x345,  0x0,  0x391,  0x314,  0x301,  0x0,  0x391,  0x314,  0x301,  0x345,  0x0,  0x391,  0x314,  0x342,  0x0,  0x391,  0x314,  0x342,  0x345,  0x0,  0x391,  0x314,  0x345,  0x0,  0x391,  0x345,  0x0,  0x395,  0x300,  0x0,  0x395,  0x301,  0x0,  0x395,  0x313,  0x0,  0x395,  0x313,  0x300,  0x0,  0x395,  0x313,  0x301,  0x0,  0x395,  0x314,  0x0,  0x395,  0x314,  0x300,  0x0,  0x395,  0x314,  0x301,  0x0,  0x397,  0x300,  0x0,  0x397,  0x301,  0x0,  0x397,  0x313,  0x0,  0x397,  0x313,  0x300,  0x0,  0x397,  0x313,  0x300,  0x345,  0x0,  0x397,  0x313,  0x301,  0x0,  0x397,  0x313,  0x301,  0x345,  0x0,  0x397,  0x313,  0x342,  0x0,  0x397,  0x313,  0x342,  0x345,  0x0,  0x397,  0x313,  0x345,  0x0,  0x397,  0x314,  0x0,  0x397,  0x314,  0x300,  0x0,  0x397,  0x314,  0x300,  0x345,  0x0,  0x397,  0x314,  0x301,  0x0,  0x397,  0x314,  0x301,  0x345,  0x0,  0x397,  0x314,  0x342,  0x0,  0x397,  0x314,  0x342,  0x345,  0x0,  0x397,  0x314,  0x345,  0x0,  0x397,  0x345,  0x0,  0x399,  0x300,  0x0,  0x399,  0x301,  0x0,  0x399,  0x304,  0x0,  0x399,  0x306,  0x0,  0x399,  0x308,  0x0,  0x399,  0x313,  0x0,  0x399,  0x313,  0x300,  0x0,  0x399,  0x313,  0x301,  0x0,  0x399,  0x313,  0x342,  0x0,  0x399,  0x314,  0x0,  0x399,  0x314,  0x300,  0x0,  0x399,  0x314,  0x301,  0x0,  0x399,  0x314,  0x342,  0x0,  0x39f,  0x300,  0x0,  0x39f,  0x301,  0x0,  0x39f,  0x313,  0x0,  0x39f,  0x313,  0x300,  0x0,  0x39f,  0x313,  0x301,  0x0,  0x39f,  0x314,  0x0,  0x39f,  0x314,  0x300,  0x0,  0x39f,  0x314,  0x301,  0x0,  0x3a1,  0x314,  0x0,  0x3a5,  0x300,  0x0,  0x3a5,  0x301,  0x0,  0x3a5,  0x304,  0x0,  0x3a5,  0x306,  0x0,  0x3a5,  0x308,  0x0,  0x3a5,  0x314,  0x0,  0x3a5,  0x314,  0x300,  0x0,  0x3a5,  0x314,  0x301,  0x0,  0x3a5,  0x314,  0x342,  0x0,  0x3a9,  0x0,  0x3a9,  0x300,  0x0,  0x3a9,  0x301,  0x0,  0x3a9,  0x313,  0x0,  0x3a9,  0x313,  0x300,  0x0,  0x3a9,  0x313,  0x300,  0x345,  0x0,  0x3a9,  0x313,  0x301,  0x0,  0x3a9,  0x313,  0x301,  0x345,  0x0,  0x3a9,  0x313,  0x342,  0x0,  0x3a9,  0x313,  0x342,  0x345,  0x0,  0x3a9,  0x313,  0x345,  0x0,  0x3a9,  0x314,  0x0,  0x3a9,  0x314,  0x300,  0x0,  0x3a9,  0x314,  0x300,  0x345,  0x0,  0x3a9,  0x314,  0x301,  0x0,  0x3a9,  0x314,  0x301,  0x345,  0x0,  0x3a9,  0x314,  0x342,  0x0,  0x3a9,  0x314,  0x342,  0x345,  0x0,  0x3a9,  0x314,  0x345,  0x0,  0x3a9,  0x345,  0x0,  0x3b1,  0x300,  0x0,  0x3b1,  0x300,  0x345,  0x0,  0x3b1,  0x301,  0x0,  0x3b1,  0x301,  0x345,  0x0,  0x3b1,  0x304,  0x0,  0x3b1,  0x306,  0x0,  0x3b1,  0x313,  0x0,  0x3b1,  0x313,  0x300,  0x0,  0x3b1,  0x313,  0x300,  0x345,  0x0,  0x3b1,  0x313,  0x301,  0x0,  0x3b1,  0x313,  0x301,  0x345,  0x0,  0x3b1,  0x313,  0x342,  0x0,  0x3b1,  0x313,  0x342,  0x345,  0x0,  0x3b1,  0x313,  0x345,  0x0,  0x3b1,  0x314,  0x0,  0x3b1,  0x314,  0x300,  0x0,  0x3b1,  0x314,  0x300,  0x345,  0x0,  0x3b1,  0x314,  0x301,  0x0,  0x3b1,  0x314,  0x301,  0x345,  0x0,  0x3b1,  0x314,  0x342,  0x0,  0x3b1,  0x314,  0x342,  0x345,  0x0,  0x3b1,  0x314,  0x345,  0x0,  0x3b1,  0x342,  0x0,  0x3b1,  0x342,  0x345,  0x0,  0x3b1,  0x345,  0x0,  0x3b5,  0x300,  0x0,  0x3b5,  0x301,  0x0,  0x3b5,  0x313,  0x0,  0x3b5,  0x313,  0x300,  0x0,  0x3b5,  0x313,  0x301,  0x0,  0x3b5,  0x314,  0x0,  0x3b5,  0x314,  0x300,  0x0,  0x3b5,  0x314,  0x301,  0x0,  0x3b7,  0x300,  0x0,  0x3b7,  0x300,  0x345,  0x0,  0x3b7,  0x301,  0x0,  0x3b7,  0x301,  0x345,  0x0,  0x3b7,  0x313,  0x0,  0x3b7,  0x313,  0x300,  0x0,  0x3b7,  0x313,  0x300,  0x345,  0x0,  0x3b7,  0x313,  0x301,  0x0,  0x3b7,  0x313,  0x301,  0x345,  0x0,  0x3b7,  0x313,  0x342,  0x0,  0x3b7,  0x313,  0x342,  0x345,  0x0,  0x3b7,  0x313,  0x345,  0x0,  0x3b7,  0x314,  0x0,  0x3b7,  0x314,  0x300,  0x0,  0x3b7,  0x314,  0x300,  0x345,  0x0,  0x3b7,  0x314,  0x301,  0x0,  0x3b7,  0x314,  0x301,  0x345,  0x0,  0x3b7,  0x314,  0x342,  0x0,  0x3b7,  0x314,  0x342,  0x345,  0x0,  0x3b7,  0x314,  0x345,  0x0,  0x3b7,  0x342,  0x0,  0x3b7,  0x342,  0x345,  0x0,  0x3b7,  0x345,  0x0,  0x3b9,  0x0,  0x3b9,  0x300,  0x0,  0x3b9,  0x301,  0x0,  0x3b9,  0x304,  0x0,  0x3b9,  0x306,  0x0,  0x3b9,  0x308,  0x0,  0x3b9,  0x308,  0x300,  0x0,  0x3b9,  0x308,  0x301,  0x0,  0x3b9,  0x308,  0x342,  0x0,  0x3b9,  0x313,  0x0,  0x3b9,  0x313,  0x300,  0x0,  0x3b9,  0x313,  0x301,  0x0,  0x3b9,  0x313,  0x342,  0x0,  0x3b9,  0x314,  0x0,  0x3b9,  0x314,  0x300,  0x0,  0x3b9,  0x314,  0x301,  0x0,  0x3b9,  0x314,  0x342,  0x0,  0x3b9,  0x342,  0x0,  0x3bf,  0x300,  0x0,  0x3bf,  0x301,  0x0,  0x3bf,  0x313,  0x0,  0x3bf,  0x313,  0x300,  0x0,  0x3bf,  0x313,  0x301,  0x0,  0x3bf,  0x314,  0x0,  0x3bf,  0x314,  0x300,  0x0,  0x3bf,  0x314,  0x301,  0x0,  0x3c1,  0x313,  0x0,  0x3c1,  0x314,  0x0,  0x3c5,  0x300,  0x0,  0x3c5,  0x301,  0x0,  0x3c5,  0x304,  0x0,  0x3c5,  0x306,  0x0,  0x3c5,  0x308,  0x0,  0x3c5,  0x308,  0x300,  0x0,  0x3c5,  0x308,  0x301,  0x0,  0x3c5,  0x308,  0x342,  0x0,  0x3c5,  0x313,  0x0,  0x3c5,  0x313,  0x300,  0x0,  0x3c5,  0x313,  0x301,  0x0,  0x3c5,  0x313,  0x342,  0x0,  0x3c5,  0x314,  0x0,  0x3c5,  0x314,  0x300,  0x0,  0x3c5,  0x314,  0x301,  0x0,  0x3c5,  0x314,  0x342,  0x0,  0x3c5,  0x342,  0x0,  0x3c9,  0x300,  0x0,  0x3c9,  0x300,  0x345,  0x0,  0x3c9,  0x301,  0x0,  0x3c9,  0x301,  0x345,  0x0,  0x3c9,  0x313,  0x0,  0x3c9,  0x313,  0x300,  0x0,  0x3c9,  0x313,  0x300,  0x345,  0x0,  0x3c9,  0x313,  0x301,  0x0,  0x3c9,  0x313,  0x301,  0x345,  0x0,  0x3c9,  0x313,  0x342,  0x0,  0x3c9,  0x313,  0x342,  0x345,  0x0,  0x3c9,  0x313,  0x345,  0x0,  0x3c9,  0x314,  0x0,  0x3c9,  0x314,  0x300,  0x0,  0x3c9,  0x314,  0x300,  0x345,  0x0,  0x3c9,  0x314,  0x301,  0x0,  0x3c9,  0x314,  0x301,  0x345,  0x0,  0x3c9,  0x314,  0x342,  0x0,  0x3c9,  0x314,  0x342,  0x345,  0x0,  0x3c9,  0x314,  0x345,  0x0,  0x3c9,  0x342,  0x0,  0x3c9,  0x342,  0x345,  0x0,  0x3c9,  0x345,  0x0,  0x3d2,  0x301,  0x0,  0x3d2,  0x308,  0x0,  0x406,  0x308,  0x0,  0x410,  0x306,  0x0,  0x410,  0x308,  0x0,  0x413,  0x301,  0x0,  0x415,  0x300,  0x0,  0x415,  0x306,  0x0,  0x415,  0x308,  0x0,  0x416,  0x306,  0x0,  0x416,  0x308,  0x0,  0x417,  0x308,  0x0,  0x418,  0x300,  0x0,  0x418,  0x304,  0x0,  0x418,  0x306,  0x0,  0x418,  0x308,  0x0,  0x41a,  0x301,  0x0,  0x41e,  0x308,  0x0,  0x423,  0x304,  0x0,  0x423,  0x306,  0x0,  0x423,  0x308,  0x0,  0x423,  0x30b,  0x0,  0x427,  0x308,  0x0,  0x42b,  0x308,  0x0,  0x42d,  0x308,  0x0,  0x430,  0x306,  0x0,  0x430,  0x308,  0x0,  0x433,  0x301,  0x0,  0x435,  0x300,  0x0,  0x435,  0x306,  0x0,  0x435,  0x308,  0x0,  0x436,  0x306,  0x0,  0x436,  0x308,  0x0,  0x437,  0x308,  0x0,  0x438,  0x300,  0x0,  0x438,  0x304,  0x0,  0x438,  0x306,  0x0,  0x438,  0x308,  0x0,  0x43a,  0x301,  0x0,  0x43e,  0x308,  0x0,  0x443,  0x304,  0x0,  0x443,  0x306,  0x0,  0x443,  0x308,  0x0,  0x443,  0x30b,  0x0,  0x447,  0x308,  0x0,  0x44b,  0x308,  0x0,  0x44d,  0x308,  0x0,  0x456,  0x308,  0x0,  0x474,  0x30f,  0x0,  0x475,  0x30f,  0x0,  0x4d8,  0x308,  0x0,  0x4d9,  0x308,  0x0,  0x4e8,  0x308,  0x0,  0x4e9,  0x308,  0x0,  0x5d0,  0x5b7,  0x0,  0x5d0,  0x5b8,  0x0,  0x5d0,  0x5bc,  0x0,  0x5d1,  0x5bc,  0x0,  0x5d1,  0x5bf,  0x0,  0x5d2,  0x5bc,  0x0,  0x5d3,  0x5bc,  0x0,  0x5d4,  0x5bc,  0x0,  0x5d5,  0x5b9,  0x0,  0x5d5,  0x5bc,  0x0,  0x5d6,  0x5bc,  0x0,  0x5d8,  0x5bc,  0x0,  0x5d9,  0x5b4,  0x0,  0x5d9,  0x5bc,  0x0,  0x5da,  0x5bc,  0x0,  0x5db,  0x5bc,  0x0,  0x5db,  0x5bf,  0x0,  0x5dc,  0x5bc,  0x0,  0x5de,  0x5bc,  0x0,  0x5e0,  0x5bc,  0x0,  0x5e1,  0x5bc,  0x0,  0x5e3,  0x5bc,  0x0,  0x5e4,  0x5bc,  0x0,  0x5e4,  0x5bf,  0x0,  0x5e6,  0x5bc,  0x0,  0x5e7,  0x5bc,  0x0,  0x5e8,  0x5bc,  0x0,  0x5e9,  0x5bc,  0x0,  0x5e9,  0x5bc,  0x5c1,  0x0,  0x5e9,  0x5bc,  0x5c2,  0x0,  0x5e9,  0x5c1,  0x0,  0x5e9,  0x5c2,  0x0,  0x5ea,  0x5bc,  0x0,  0x5f2,  0x5b7,  0x0,  0x627,  0x653,  0x0,  0x627,  0x654,  0x0,  0x627,  0x655,  0x0,  0x648,  0x654,  0x0,  0x64a,  0x654,  0x0,  0x6c1,  0x654,  0x0,  0x6d2,  0x654,  0x0,  0x6d5,  0x654,  0x0,  0x915,  0x93c,  0x0,  0x916,  0x93c,  0x0,  0x917,  0x93c,  0x0,  0x91c,  0x93c,  0x0,  0x921,  0x93c,  0x0,  0x922,  0x93c,  0x0,  0x928,  0x93c,  0x0,  0x92b,  0x93c,  0x0,  0x92f,  0x93c,  0x0,  0x930,  0x93c,  0x0,  0x933,  0x93c,  0x0,  0x9a1,  0x9bc,  0x0,  0x9a2,  0x9bc,  0x0,  0x9af,  0x9bc,  0x0,  0x9c7,  0x9be,  0x0,  0x9c7,  0x9d7,  0x0,  0xa16,  0xa3c,  0x0,  0xa17,  0xa3c,  0x0,  0xa1c,  0xa3c,  0x0,  0xa2b,  0xa3c,  0x0,  0xa32,  0xa3c,  0x0,  0xa38,  0xa3c,  0x0,  0xb21,  0xb3c,  0x0,  0xb22,  0xb3c,  0x0,  0xb47,  0xb3e,  0x0,  0xb47,  0xb56,  0x0,  0xb47,  0xb57,  0x0,  0xb92,  0xbd7,  0x0,  0xbc6,  0xbbe,  0x0,  0xbc6,  0xbd7,  0x0,  0xbc7,  0xbbe,  0x0,  0xc46,  0xc56,  0x0,  0xcbf,  0xcd5,  0x0,  0xcc6,  0xcc2,  0x0,  0xcc6,  0xcc2,  0xcd5,  0x0,  0xcc6,  0xcd5,  0x0,  0xcc6,  0xcd6,  0x0,  0xd46,  0xd3e,  0x0,  0xd46,  0xd57,  0x0,  0xd47,  0xd3e,  0x0,  0xdd9,  0xdca,  0x0,  0xdd9,  0xdcf,  0x0,  0xdd9,  0xdcf,  0xdca,  0x0,  0xdd9,  0xddf,  0x0,  0xf40,  0xfb5,  0x0,  0xf42,  0xfb7,  0x0,  0xf4c,  0xfb7,  0x0,  0xf51,  0xfb7,  0x0,  0xf56,  0xfb7,  0x0,  0xf5b,  0xfb7,  0x0,  0xf71,  0xf72,  0x0,  0xf71,  0xf74,  0x0,  0xf71,  0xf80,  0x0,  0xf90,  0xfb5,  0x0,  0xf92,  0xfb7,  0x0,  0xf9c,  0xfb7,  0x0,  0xfa1,  0xfb7,  0x0,  0xfa6,  0xfb7,  0x0,  0xfab,  0xfb7,  0x0,  0xfb2,  0xf80,  0x0,  0xfb3,  0xf80,  0x0,  0x1025,  0x102e,  0x0,  0x1b05,  0x1b35,  0x0,  0x1b07,  0x1b35,  0x0,  0x1b09,  0x1b35,  0x0,  0x1b0b,  0x1b35,  0x0,  0x1b0d,  0x1b35,  0x0,  0x1b11,  0x1b35,  0x0,  0x1b3a,  0x1b35,  0x0,  0x1b3c,  0x1b35,  0x0,  0x1b3e,  0x1b35,  0x0,  0x1b3f,  0x1b35,  0x0,  0x1b42,  0x1b35,  0x0,  0x1fbf,  0x300,  0x0,  0x1fbf,  0x301,  0x0,  0x1fbf,  0x342,  0x0,  0x1ffe,  0x300,  0x0,  0x1ffe,  0x301,  0x0,  0x1ffe,  0x342,  0x0,  0x2002,  0x0,  0x2003,  0x0,  0x2190,  0x338,  0x0,  0x2192,  0x338,  0x0,  0x2194,  0x338,  0x0,  0x21d0,  0x338,  0x0,  0x21d2,  0x338,  0x0,  0x21d4,  0x338,  0x0,  0x2203,  0x338,  0x0,  0x2208,  0x338,  0x0,  0x220b,  0x338,  0x0,  0x2223,  0x338,  0x0,  0x2225,  0x338,  0x0,  0x223c,  0x338,  0x0,  0x2243,  0x338,  0x0,  0x2245,  0x338,  0x0,  0x2248,  0x338,  0x0,  0x224d,  0x338,  0x0,  0x2261,  0x338,  0x0,  0x2264,  0x338,  0x0,  0x2265,  0x338,  0x0,  0x2272,  0x338,  0x0,  0x2273,  0x338,  0x0,  0x2276,  0x338,  0x0,  0x2277,  0x338,  0x0,  0x227a,  0x338,  0x0,  0x227b,  0x338,  0x0,  0x227c,  0x338,  0x0,  0x227d,  0x338,  0x0,  0x2282,  0x338,  0x0,  0x2283,  0x338,  0x0,  0x2286,  0x338,  0x0,  0x2287,  0x338,  0x0,  0x2291,  0x338,  0x0,  0x2292,  0x338,  0x0,  0x22a2,  0x338,  0x0,  0x22a8,  0x338,  0x0,  0x22a9,  0x338,  0x0,  0x22ab,  0x338,  0x0,  0x22b2,  0x338,  0x0,  0x22b3,  0x338,  0x0,  0x22b4,  0x338,  0x0,  0x22b5,  0x338,  0x0,  0x2add,  0x338,  0x0,  0x3008,  0x0,  0x3009,  0x0,  0x3046,  0x3099,  0x0,  0x304b,  0x3099,  0x0,  0x304d,  0x3099,  0x0,  0x304f,  0x3099,  0x0,  0x3051,  0x3099,  0x0,  0x3053,  0x3099,  0x0,  0x3055,  0x3099,  0x0,  0x3057,  0x3099,  0x0,  0x3059,  0x3099,  0x0,  0x305b,  0x3099,  0x0,  0x305d,  0x3099,  0x0,  0x305f,  0x3099,  0x0,  0x3061,  0x3099,  0x0,  0x3064,  0x3099,  0x0,  0x3066,  0x3099,  0x0,  0x3068,  0x3099,  0x0,  0x306f,  0x3099,  0x0,  0x306f,  0x309a,  0x0,  0x3072,  0x3099,  0x0,  0x3072,  0x309a,  0x0,  0x3075,  0x3099,  0x0,  0x3075,  0x309a,  0x0,  0x3078,  0x3099,  0x0,  0x3078,  0x309a,  0x0,  0x307b,  0x3099,  0x0,  0x307b,  0x309a,  0x0,  0x309d,  0x3099,  0x0,  0x30a6,  0x3099,  0x0,  0x30ab,  0x3099,  0x0,  0x30ad,  0x3099,  0x0,  0x30af,  0x3099,  0x0,  0x30b1,  0x3099,  0x0,  0x30b3,  0x3099,  0x0,  0x30b5,  0x3099,  0x0,  0x30b7,  0x3099,  0x0,  0x30b9,  0x3099,  0x0,  0x30bb,  0x3099,  0x0,  0x30bd,  0x3099,  0x0,  0x30bf,  0x3099,  0x0,  0x30c1,  0x3099,  0x0,  0x30c4,  0x3099,  0x0,  0x30c6,  0x3099,  0x0,  0x30c8,  0x3099,  0x0,  0x30cf,  0x3099,  0x0,  0x30cf,  0x309a,  0x0,  0x30d2,  0x3099,  0x0,  0x30d2,  0x309a,  0x0,  0x30d5,  0x3099,  0x0,  0x30d5,  0x309a,  0x0,  0x30d8,  0x3099,  0x0,  0x30d8,  0x309a,  0x0,  0x30db,  0x3099,  0x0,  0x30db,  0x309a,  0x0,  0x30ef,  0x3099,  0x0,  0x30f0,  0x3099,  0x0,  0x30f1,  0x3099,  0x0,  0x30f2,  0x3099,  0x0,  0x30fd,  0x3099,  0x0,  0x349e,  0x0,  0x34b9,  0x0,  0x34bb,  0x0,  0x34df,  0x0,  0x3515,  0x0,  0x36ee,  0x0,  0x36fc,  0x0,  0x3781,  0x0,  0x382f,  0x0,  0x3862,  0x0,  0x387c,  0x0,  0x38c7,  0x0,  0x38e3,  0x0,  0x391c,  0x0,  0x393a,  0x0,  0x3a2e,  0x0,  0x3a6c,  0x0,  0x3ae4,  0x0,  0x3b08,  0x0,  0x3b19,  0x0,  0x3b49,  0x0,  0x3b9d,  0x0,  0x3c18,  0x0,  0x3c4e,  0x0,  0x3d33,  0x0,  0x3d96,  0x0,  0x3eac,  0x0,  0x3eb8,  0x0,  0x3f1b,  0x0,  0x3ffc,  0x0,  0x4008,  0x0,  0x4018,  0x0,  0x4039,  0x0,  0x4046,  0x0,  0x4096,  0x0,  0x40e3,  0x0,  0x412f,  0x0,  0x4202,  0x0,  0x4227,  0x0,  0x42a0,  0x0,  0x4301,  0x0,  0x4334,  0x0,  0x4359,  0x0,  0x43d5,  0x0,  0x43d9,  0x0,  0x440b,  0x0,  0x446b,  0x0,  0x452b,  0x0,  0x455d,  0x0,  0x4561,  0x0,  0x456b,  0x0,  0x45d7,  0x0,  0x45f9,  0x0,  0x4635,  0x0,  0x46be,  0x0,  0x46c7,  0x0,  0x4995,  0x0,  0x49e6,  0x0,  0x4a6e,  0x0,  0x4a76,  0x0,  0x4ab2,  0x0,  0x4b33,  0x0,  0x4bce,  0x0,  0x4cce,  0x0,  0x4ced,  0x0,  0x4cf8,  0x0,  0x4d56,  0x0,  0x4e0d,  0x0,  0x4e26,  0x0,  0x4e32,  0x0,  0x4e38,  0x0,  0x4e39,  0x0,  0x4e3d,  0x0,  0x4e41,  0x0,  0x4e82,  0x0,  0x4e86,  0x0,  0x4eae,  0x0,  0x4ec0,  0x0,  0x4ecc,  0x0,  0x4ee4,  0x0,  0x4f60,  0x0,  0x4f80,  0x0,  0x4f86,  0x0,  0x4f8b,  0x0,  0x4fae,  0x0,  0x4fbb,  0x0,  0x4fbf,  0x0,  0x5002,  0x0,  0x502b,  0x0,  0x507a,  0x0,  0x5099,  0x0,  0x50cf,  0x0,  0x50da,  0x0,  0x50e7,  0x0,  0x5140,  0x0,  0x5145,  0x0,  0x514d,  0x0,  0x5154,  0x0,  0x5164,  0x0,  0x5167,  0x0,  0x5168,  0x0,  0x5169,  0x0,  0x516d,  0x0,  0x5177,  0x0,  0x5180,  0x0,  0x518d,  0x0,  0x5192,  0x0,  0x5195,  0x0,  0x5197,  0x0,  0x51a4,  0x0,  0x51ac,  0x0,  0x51b5,  0x0,  0x51b7,  0x0,  0x51c9,  0x0,  0x51cc,  0x0,  0x51dc,  0x0,  0x51de,  0x0,  0x51f5,  0x0,  0x5203,  0x0,  0x5207,  0x0,  0x5217,  0x0,  0x5229,  0x0,  0x523a,  0x0,  0x523b,  0x0,  0x5246,  0x0,  0x5272,  0x0,  0x5277,  0x0,  0x5289,  0x0,  0x529b,  0x0,  0x52a3,  0x0,  0x52b3,  0x0,  0x52c7,  0x0,  0x52c9,  0x0,  0x52d2,  0x0,  0x52de,  0x0,  0x52e4,  0x0,  0x52f5,  0x0,  0x52fa,  0x0,  0x5305,  0x0,  0x5306,  0x0,  0x5317,  0x0,  0x533f,  0x0,  0x5349,  0x0,  0x5351,  0x0,  0x535a,  0x0,  0x5373,  0x0,  0x5375,  0x0,  0x537d,  0x0,  0x537f,  0x0,  0x53c3,  0x0,  0x53ca,  0x0,  0x53df,  0x0,  0x53e5,  0x0,  0x53eb,  0x0,  0x53f1,  0x0,  0x5406,  0x0,  0x540f,  0x0,  0x541d,  0x0,  0x5438,  0x0,  0x5442,  0x0,  0x5448,  0x0,  0x5468,  0x0,  0x549e,  0x0,  0x54a2,  0x0,  0x54bd,  0x0,  0x54f6,  0x0,  0x5510,  0x0,  0x5553,  0x0,  0x5555,  0x0,  0x5563,  0x0,  0x5584,  0x0,  0x5587,  0x0,  0x5599,  0x0,  0x559d,  0x0,  0x55ab,  0x0,  0x55b3,  0x0,  0x55c0,  0x0,  0x55c2,  0x0,  0x55e2,  0x0,  0x5606,  0x0,  0x5651,  0x0,  0x5668,  0x0,  0x5674,  0x0,  0x56f9,  0x0,  0x5716,  0x0,  0x5717,  0x0,  0x578b,  0x0,  0x57ce,  0x0,  0x57f4,  0x0,  0x580d,  0x0,  0x5831,  0x0,  0x5832,  0x0,  0x5840,  0x0,  0x585a,  0x0,  0x585e,  0x0,  0x58a8,  0x0,  0x58ac,  0x0,  0x58b3,  0x0,  0x58d8,  0x0,  0x58df,  0x0,  0x58ee,  0x0,  0x58f2,  0x0,  0x58f7,  0x0,  0x5906,  0x0,  0x591a,  0x0,  0x5922,  0x0,  0x5944,  0x0,  0x5948,  0x0,  0x5951,  0x0,  0x5954,  0x0,  0x5962,  0x0,  0x5973,  0x0,  0x59d8,  0x0,  0x59ec,  0x0,  0x5a1b,  0x0,  0x5a27,  0x0,  0x5a62,  0x0,  0x5a66,  0x0,  0x5ab5,  0x0,  0x5b08,  0x0,  0x5b28,  0x0,  0x5b3e,  0x0,  0x5b85,  0x0,  0x5bc3,  0x0,  0x5bd8,  0x0,  0x5be7,  0x0,  0x5bee,  0x0,  0x5bf3,  0x0,  0x5bff,  0x0,  0x5c06,  0x0,  0x5c22,  0x0,  0x5c3f,  0x0,  0x5c60,  0x0,  0x5c62,  0x0,  0x5c64,  0x0,  0x5c65,  0x0,  0x5c6e,  0x0,  0x5c8d,  0x0,  0x5cc0,  0x0,  0x5d19,  0x0,  0x5d43,  0x0,  0x5d50,  0x0,  0x5d6b,  0x0,  0x5d6e,  0x0,  0x5d7c,  0x0,  0x5db2,  0x0,  0x5dba,  0x0,  0x5de1,  0x0,  0x5de2,  0x0,  0x5dfd,  0x0,  0x5e28,  0x0,  0x5e3d,  0x0,  0x5e69,  0x0,  0x5e74,  0x0,  0x5ea6,  0x0,  0x5eb0,  0x0,  0x5eb3,  0x0,  0x5eb6,  0x0,  0x5ec9,  0x0,  0x5eca,  0x0,  0x5ed2,  0x0,  0x5ed3,  0x0,  0x5ed9,  0x0,  0x5eec,  0x0,  0x5efe,  0x0,  0x5f04,  0x0,  0x5f22,  0x0,  0x5f53,  0x0,  0x5f62,  0x0,  0x5f69,  0x0,  0x5f6b,  0x0,  0x5f8b,  0x0,  0x5f9a,  0x0,  0x5fa9,  0x0,  0x5fad,  0x0,  0x5fcd,  0x0,  0x5fd7,  0x0,  0x5ff5,  0x0,  0x5ff9,  0x0,  0x6012,  0x0,  0x601c,  0x0,  0x6075,  0x0,  0x6081,  0x0,  0x6094,  0x0,  0x60c7,  0x0,  0x60d8,  0x0,  0x60e1,  0x0,  0x6108,  0x0,  0x6144,  0x0,  0x6148,  0x0,  0x614c,  0x0,  0x614e,  0x0,  0x6160,  0x0,  0x6168,  0x0,  0x617a,  0x0,  0x618e,  0x0,  0x6190,  0x0,  0x61a4,  0x0,  0x61af,  0x0,  0x61b2,  0x0,  0x61de,  0x0,  0x61f2,  0x0,  0x61f6,  0x0,  0x6200,  0x0,  0x6210,  0x0,  0x621b,  0x0,  0x622e,  0x0,  0x6234,  0x0,  0x625d,  0x0,  0x62b1,  0x0,  0x62c9,  0x0,  0x62cf,  0x0,  0x62d3,  0x0,  0x62d4,  0x0,  0x62fc,  0x0,  0x62fe,  0x0,  0x633d,  0x0,  0x6350,  0x0,  0x6368,  0x0,  0x637b,  0x0,  0x6383,  0x0,  0x63a0,  0x0,  0x63a9,  0x0,  0x63c4,  0x0,  0x63c5,  0x0,  0x63e4,  0x0,  0x641c,  0x0,  0x6422,  0x0,  0x6452,  0x0,  0x6469,  0x0,  0x6477,  0x0,  0x647e,  0x0,  0x649a,  0x0,  0x649d,  0x0,  0x64c4,  0x0,  0x654f,  0x0,  0x6556,  0x0,  0x656c,  0x0,  0x6578,  0x0,  0x6599,  0x0,  0x65c5,  0x0,  0x65e2,  0x0,  0x65e3,  0x0,  0x6613,  0x0,  0x6649,  0x0,  0x6674,  0x0,  0x6688,  0x0,  0x6691,  0x0,  0x669c,  0x0,  0x66b4,  0x0,  0x66c6,  0x0,  0x66f4,  0x0,  0x66f8,  0x0,  0x6700,  0x0,  0x6717,  0x0,  0x671b,  0x0,  0x6721,  0x0,  0x674e,  0x0,  0x6753,  0x0,  0x6756,  0x0,  0x675e,  0x0,  0x677b,  0x0,  0x6785,  0x0,  0x6797,  0x0,  0x67f3,  0x0,  0x67fa,  0x0,  0x6817,  0x0,  0x681f,  0x0,  0x6852,  0x0,  0x6881,  0x0,  0x6885,  0x0,  0x688e,  0x0,  0x68a8,  0x0,  0x6914,  0x0,  0x6942,  0x0,  0x69a3,  0x0,  0x69ea,  0x0,  0x6a02,  0x0,  0x6a13,  0x0,  0x6aa8,  0x0,  0x6ad3,  0x0,  0x6adb,  0x0,  0x6b04,  0x0,  0x6b21,  0x0,  0x6b54,  0x0,  0x6b72,  0x0,  0x6b77,  0x0,  0x6b79,  0x0,  0x6b9f,  0x0,  0x6bae,  0x0,  0x6bba,  0x0,  0x6bbb,  0x0,  0x6c4e,  0x0,  0x6c67,  0x0,  0x6c88,  0x0,  0x6cbf,  0x0,  0x6ccc,  0x0,  0x6ccd,  0x0,  0x6ce5,  0x0,  0x6d16,  0x0,  0x6d1b,  0x0,  0x6d1e,  0x0,  0x6d34,  0x0,  0x6d3e,  0x0,  0x6d41,  0x0,  0x6d69,  0x0,  0x6d6a,  0x0,  0x6d77,  0x0,  0x6d78,  0x0,  0x6d85,  0x0,  0x6dcb,  0x0,  0x6dda,  0x0,  0x6dea,  0x0,  0x6df9,  0x0,  0x6e1a,  0x0,  0x6e2f,  0x0,  0x6e6e,  0x0,  0x6e9c,  0x0,  0x6eba,  0x0,  0x6ec7,  0x0,  0x6ecb,  0x0,  0x6ed1,  0x0,  0x6edb,  0x0,  0x6f0f,  0x0,  0x6f22,  0x0,  0x6f23,  0x0,  0x6f6e,  0x0,  0x6fc6,  0x0,  0x6feb,  0x0,  0x6ffe,  0x0,  0x701b,  0x0,  0x701e,  0x0,  0x7039,  0x0,  0x704a,  0x0,  0x7070,  0x0,  0x7077,  0x0,  0x707d,  0x0,  0x7099,  0x0,  0x70ad,  0x0,  0x70c8,  0x0,  0x70d9,  0x0,  0x7145,  0x0,  0x7149,  0x0,  0x716e,  0x0,  0x719c,  0x0,  0x71ce,  0x0,  0x71d0,  0x0,  0x7210,  0x0,  0x721b,  0x0,  0x7228,  0x0,  0x722b,  0x0,  0x7235,  0x0,  0x7250,  0x0,  0x7262,  0x0,  0x7280,  0x0,  0x7295,  0x0,  0x72af,  0x0,  0x72c0,  0x0,  0x72fc,  0x0,  0x732a,  0x0,  0x7375,  0x0,  0x737a,  0x0,  0x7387,  0x0,  0x738b,  0x0,  0x73a5,  0x0,  0x73b2,  0x0,  0x73de,  0x0,  0x7406,  0x0,  0x7409,  0x0,  0x7422,  0x0,  0x7447,  0x0,  0x745c,  0x0,  0x7469,  0x0,  0x7471,  0x0,  0x7485,  0x0,  0x7489,  0x0,  0x7498,  0x0,  0x74ca,  0x0,  0x7506,  0x0,  0x7524,  0x0,  0x753b,  0x0,  0x753e,  0x0,  0x7559,  0x0,  0x7565,  0x0,  0x7570,  0x0,  0x75e2,  0x0,  0x7610,  0x0,  0x761d,  0x0,  0x761f,  0x0,  0x7642,  0x0,  0x7669,  0x0,  0x76ca,  0x0,  0x76db,  0x0,  0x76e7,  0x0,  0x76f4,  0x0,  0x7701,  0x0,  0x771e,  0x0,  0x771f,  0x0,  0x7740,  0x0,  0x774a,  0x0,  0x778b,  0x0,  0x77a7,  0x0,  0x784e,  0x0,  0x786b,  0x0,  0x788c,  0x0,  0x7891,  0x0,  0x78ca,  0x0,  0x78cc,  0x0,  0x78fb,  0x0,  0x792a,  0x0,  0x793c,  0x0,  0x793e,  0x0,  0x7948,  0x0,  0x7949,  0x0,  0x7950,  0x0,  0x7956,  0x0,  0x795d,  0x0,  0x795e,  0x0,  0x7965,  0x0,  0x797f,  0x0,  0x798d,  0x0,  0x798e,  0x0,  0x798f,  0x0,  0x79ae,  0x0,  0x79ca,  0x0,  0x79eb,  0x0,  0x7a1c,  0x0,  0x7a40,  0x0,  0x7a4a,  0x0,  0x7a4f,  0x0,  0x7a81,  0x0,  0x7ab1,  0x0,  0x7acb,  0x0,  0x7aee,  0x0,  0x7b20,  0x0,  0x7bc0,  0x0,  0x7bc6,  0x0,  0x7bc9,  0x0,  0x7c3e,  0x0,  0x7c60,  0x0,  0x7c7b,  0x0,  0x7c92,  0x0,  0x7cbe,  0x0,  0x7cd2,  0x0,  0x7cd6,  0x0,  0x7ce3,  0x0,  0x7ce7,  0x0,  0x7ce8,  0x0,  0x7d00,  0x0,  0x7d10,  0x0,  0x7d22,  0x0,  0x7d2f,  0x0,  0x7d5b,  0x0,  0x7d63,  0x0,  0x7da0,  0x0,  0x7dbe,  0x0,  0x7dc7,  0x0,  0x7df4,  0x0,  0x7e02,  0x0,  0x7e09,  0x0,  0x7e37,  0x0,  0x7e41,  0x0,  0x7e45,  0x0,  0x7f3e,  0x0,  0x7f72,  0x0,  0x7f79,  0x0,  0x7f7a,  0x0,  0x7f85,  0x0,  0x7f95,  0x0,  0x7f9a,  0x0,  0x7fbd,  0x0,  0x7ffa,  0x0,  0x8001,  0x0,  0x8005,  0x0,  0x8046,  0x0,  0x8060,  0x0,  0x806f,  0x0,  0x8070,  0x0,  0x807e,  0x0,  0x808b,  0x0,  0x80ad,  0x0,  0x80b2,  0x0,  0x8103,  0x0,  0x813e,  0x0,  0x81d8,  0x0,  0x81e8,  0x0,  0x81ed,  0x0,  0x8201,  0x0,  0x8204,  0x0,  0x8218,  0x0,  0x826f,  0x0,  0x8279,  0x0,  0x828b,  0x0,  0x8291,  0x0,  0x829d,  0x0,  0x82b1,  0x0,  0x82b3,  0x0,  0x82bd,  0x0,  0x82e5,  0x0,  0x82e6,  0x0,  0x831d,  0x0,  0x8323,  0x0,  0x8336,  0x0,  0x8352,  0x0,  0x8353,  0x0,  0x8363,  0x0,  0x83ad,  0x0,  0x83bd,  0x0,  0x83c9,  0x0,  0x83ca,  0x0,  0x83cc,  0x0,  0x83dc,  0x0,  0x83e7,  0x0,  0x83ef,  0x0,  0x83f1,  0x0,  0x843d,  0x0,  0x8449,  0x0,  0x8457,  0x0,  0x84ee,  0x0,  0x84f1,  0x0,  0x84f3,  0x0,  0x84fc,  0x0,  0x8516,  0x0,  0x8564,  0x0,  0x85cd,  0x0,  0x85fa,  0x0,  0x8606,  0x0,  0x8612,  0x0,  0x862d,  0x0,  0x863f,  0x0,  0x8650,  0x0,  0x865c,  0x0,  0x8667,  0x0,  0x8669,  0x0,  0x8688,  0x0,  0x86a9,  0x0,  0x86e2,  0x0,  0x870e,  0x0,  0x8728,  0x0,  0x876b,  0x0,  0x8779,  0x0,  0x8786,  0x0,  0x87ba,  0x0,  0x87e1,  0x0,  0x8801,  0x0,  0x881f,  0x0,  0x884c,  0x0,  0x8860,  0x0,  0x8863,  0x0,  0x88c2,  0x0,  0x88cf,  0x0,  0x88d7,  0x0,  0x88de,  0x0,  0x88e1,  0x0,  0x88f8,  0x0,  0x88fa,  0x0,  0x8910,  0x0,  0x8941,  0x0,  0x8964,  0x0,  0x8986,  0x0,  0x898b,  0x0,  0x8996,  0x0,  0x8aa0,  0x0,  0x8aaa,  0x0,  0x8abf,  0x0,  0x8acb,  0x0,  0x8ad2,  0x0,  0x8ad6,  0x0,  0x8aed,  0x0,  0x8af8,  0x0,  0x8afe,  0x0,  0x8b01,  0x0,  0x8b39,  0x0,  0x8b58,  0x0,  0x8b80,  0x0,  0x8b8a,  0x0,  0x8c48,  0x0,  0x8c55,  0x0,  0x8cab,  0x0,  0x8cc1,  0x0,  0x8cc2,  0x0,  0x8cc8,  0x0,  0x8cd3,  0x0,  0x8d08,  0x0,  0x8d1b,  0x0,  0x8d77,  0x0,  0x8dbc,  0x0,  0x8dcb,  0x0,  0x8def,  0x0,  0x8df0,  0x0,  0x8eca,  0x0,  0x8ed4,  0x0,  0x8f26,  0x0,  0x8f2a,  0x0,  0x8f38,  0x0,  0x8f3b,  0x0,  0x8f62,  0x0,  0x8f9e,  0x0,  0x8fb0,  0x0,  0x8fb6,  0x0,  0x9023,  0x0,  0x9038,  0x0,  0x9072,  0x0,  0x907c,  0x0,  0x908f,  0x0,  0x9094,  0x0,  0x90ce,  0x0,  0x90de,  0x0,  0x90f1,  0x0,  0x90fd,  0x0,  0x9111,  0x0,  0x911b,  0x0,  0x916a,  0x0,  0x9199,  0x0,  0x91b4,  0x0,  0x91cc,  0x0,  0x91cf,  0x0,  0x91d1,  0x0,  0x9234,  0x0,  0x9238,  0x0,  0x9276,  0x0,  0x927c,  0x0,  0x92d7,  0x0,  0x92d8,  0x0,  0x9304,  0x0,  0x934a,  0x0,  0x93f9,  0x0,  0x9415,  0x0,  0x958b,  0x0,  0x95ad,  0x0,  0x95b7,  0x0,  0x962e,  0x0,  0x964b,  0x0,  0x964d,  0x0,  0x9675,  0x0,  0x9678,  0x0,  0x967c,  0x0,  0x9686,  0x0,  0x96a3,  0x0,  0x96b7,  0x0,  0x96b8,  0x0,  0x96c3,  0x0,  0x96e2,  0x0,  0x96e3,  0x0,  0x96f6,  0x0,  0x96f7,  0x0,  0x9723,  0x0,  0x9732,  0x0,  0x9748,  0x0,  0x9756,  0x0,  0x97db,  0x0,  0x97e0,  0x0,  0x97ff,  0x0,  0x980b,  0x0,  0x9818,  0x0,  0x9829,  0x0,  0x983b,  0x0,  0x985e,  0x0,  0x98e2,  0x0,  0x98ef,  0x0,  0x98fc,  0x0,  0x9928,  0x0,  0x9929,  0x0,  0x99a7,  0x0,  0x99c2,  0x0,  0x99f1,  0x0,  0x99fe,  0x0,  0x9a6a,  0x0,  0x9b12,  0x0,  0x9b6f,  0x0,  0x9c40,  0x0,  0x9c57,  0x0,  0x9cfd,  0x0,  0x9d67,  0x0,  0x9db4,  0x0,  0x9dfa,  0x0,  0x9e1e,  0x0,  0x9e7f,  0x0,  0x9e97,  0x0,  0x9e9f,  0x0,  0x9ebb,  0x0,  0x9ece,  0x0,  0x9ef9,  0x0,  0x9efe,  0x0,  0x9f05,  0x0,  0x9f0f,  0x0,  0x9f16,  0x0,  0x9f3b,  0x0,  0x9f43,  0x0,  0x9f8d,  0x0,  0x9f8e,  0x0,  0x9f9c,  0x0,  0x11099,  0x110ba,  0x0,  0x1109b,  0x110ba,  0x0,  0x110a5,  0x110ba,  0x0,  0x11131,  0x11127,  0x0,  0x11132,  0x11127,  0x0,  0x1d157,  0x1d165,  0x0,  0x1d158,  0x1d165,  0x0,  0x1d158,  0x1d165,  0x1d16e,  0x0,  0x1d158,  0x1d165,  0x1d16f,  0x0,  0x1d158,  0x1d165,  0x1d170,  0x0,  0x1d158,  0x1d165,  0x1d171,  0x0,  0x1d158,  0x1d165,  0x1d172,  0x0,  0x1d1b9,  0x1d165,  0x0,  0x1d1b9,  0x1d165,  0x1d16e,  0x0,  0x1d1b9,  0x1d165,  0x1d16f,  0x0,  0x1d1ba,  0x1d165,  0x0,  0x1d1ba,  0x1d165,  0x1d16e,  0x0,  0x1d1ba,  0x1d165,  0x1d16f,  0x0,  0x20122,  0x0,  0x2051c,  0x0,  0x20525,  0x0,  0x2054b,  0x0,  0x2063a,  0x0,  0x20804,  0x0,  0x208de,  0x0,  0x20a2c,  0x0,  0x20b63,  0x0,  0x214e4,  0x0,  0x216a8,  0x0,  0x216ea,  0x0,  0x219c8,  0x0,  0x21b18,  0x0,  0x21d0b,  0x0,  0x21de4,  0x0,  0x21de6,  0x0,  0x22183,  0x0,  0x2219f,  0x0,  0x22331,  0x0,  0x226d4,  0x0,  0x22844,  0x0,  0x2284a,  0x0,  0x22b0c,  0x0,  0x22bf1,  0x0,  0x2300a,  0x0,  0x232b8,  0x0,  0x2335f,  0x0,  0x23393,  0x0,  0x2339c,  0x0,  0x233c3,  0x0,  0x233d5,  0x0,  0x2346d,  0x0,  0x236a3,  0x0,  0x238a7,  0x0,  0x23a8d,  0x0,  0x23afa,  0x0,  0x23cbc,  0x0,  0x23d1e,  0x0,  0x23ed1,  0x0,  0x23f5e,  0x0,  0x23f8e,  0x0,  0x24263,  0x0,  0x242ee,  0x0,  0x243ab,  0x0,  0x24608,  0x0,  0x24735,  0x0,  0x24814,  0x0,  0x24c36,  0x0,  0x24c92,  0x0,  0x24fa1,  0x0,  0x24fb8,  0x0,  0x25044,  0x0,  0x250f2,  0x0,  0x250f3,  0x0,  0x25119,  0x0,  0x25133,  0x0,  0x25249,  0x0,  0x2541d,  0x0,  0x25626,  0x0,  0x2569a,  0x0,  0x256c5,  0x0,  0x2597c,  0x0,  0x25aa7,  0x0,  0x25bab,  0x0,  0x25c80,  0x0,  0x25cd0,  0x0,  0x25f86,  0x0,  0x261da,  0x0,  0x26228,  0x0,  0x26247,  0x0,  0x262d9,  0x0,  0x2633e,  0x0,  0x264da,  0x0,  0x26523,  0x0,  0x265a8,  0x0,  0x267a7,  0x0,  0x267b5,  0x0,  0x26b3c,  0x0,  0x26c36,  0x0,  0x26cd5,  0x0,  0x26d6b,  0x0,  0x26f2c,  0x0,  0x26fb1,  0x0,  0x270d2,  0x0,  0x273ca,  0x0,  0x27667,  0x0,  0x278ae,  0x0,  0x27966,  0x0,  0x27ca8,  0x0,  0x27ed3,  0x0,  0x27f2f,  0x0,  0x285d2,  0x0,  0x285ed,  0x0,  0x2872e,  0x0,  0x28bfa,  0x0,  0x28d77,  0x0,  0x29145,  0x0,  0x291df,  0x0,  0x2921a,  0x0,  0x2940a,  0x0,  0x29496,  0x0,  0x295b6,  0x0,  0x29b30,  0x0,  0x2a0ce,  0x0,  0x2a105,  0x0,  0x2a20e,  0x0,  0x2a291,  0x0,  0x2a392,  0x0,  0x2a600,  0x0]; return t; }
+_IDCA decompCompatTable() { static _IDCA t = [ 0x0,  0x20,  0x0,  0x20,  0x301,  0x0,  0x20,  0x303,  0x0,  0x20,  0x304,  0x0,  0x20,  0x305,  0x0,  0x20,  0x306,  0x0,  0x20,  0x307,  0x0,  0x20,  0x308,  0x0,  0x20,  0x308,  0x300,  0x0,  0x20,  0x308,  0x301,  0x0,  0x20,  0x308,  0x342,  0x0,  0x20,  0x30a,  0x0,  0x20,  0x30b,  0x0,  0x20,  0x313,  0x0,  0x20,  0x313,  0x300,  0x0,  0x20,  0x313,  0x301,  0x0,  0x20,  0x313,  0x342,  0x0,  0x20,  0x314,  0x0,  0x20,  0x314,  0x300,  0x0,  0x20,  0x314,  0x301,  0x0,  0x20,  0x314,  0x342,  0x0,  0x20,  0x327,  0x0,  0x20,  0x328,  0x0,  0x20,  0x333,  0x0,  0x20,  0x342,  0x0,  0x20,  0x345,  0x0,  0x20,  0x64b,  0x0,  0x20,  0x64c,  0x0,  0x20,  0x64c,  0x651,  0x0,  0x20,  0x64d,  0x0,  0x20,  0x64d,  0x651,  0x0,  0x20,  0x64e,  0x0,  0x20,  0x64e,  0x651,  0x0,  0x20,  0x64f,  0x0,  0x20,  0x64f,  0x651,  0x0,  0x20,  0x650,  0x0,  0x20,  0x650,  0x651,  0x0,  0x20,  0x651,  0x0,  0x20,  0x651,  0x670,  0x0,  0x20,  0x652,  0x0,  0x20,  0x3099,  0x0,  0x20,  0x309a,  0x0,  0x21,  0x0,  0x21,  0x21,  0x0,  0x21,  0x3f,  0x0,  0x22,  0x0,  0x23,  0x0,  0x24,  0x0,  0x25,  0x0,  0x26,  0x0,  0x27,  0x0,  0x28,  0x0,  0x28,  0x31,  0x29,  0x0,  0x28,  0x31,  0x30,  0x29,  0x0,  0x28,  0x31,  0x31,  0x29,  0x0,  0x28,  0x31,  0x32,  0x29,  0x0,  0x28,  0x31,  0x33,  0x29,  0x0,  0x28,  0x31,  0x34,  0x29,  0x0,  0x28,  0x31,  0x35,  0x29,  0x0,  0x28,  0x31,  0x36,  0x29,  0x0,  0x28,  0x31,  0x37,  0x29,  0x0,  0x28,  0x31,  0x38,  0x29,  0x0,  0x28,  0x31,  0x39,  0x29,  0x0,  0x28,  0x32,  0x29,  0x0,  0x28,  0x32,  0x30,  0x29,  0x0,  0x28,  0x33,  0x29,  0x0,  0x28,  0x34,  0x29,  0x0,  0x28,  0x35,  0x29,  0x0,  0x28,  0x36,  0x29,  0x0,  0x28,  0x37,  0x29,  0x0,  0x28,  0x38,  0x29,  0x0,  0x28,  0x39,  0x29,  0x0,  0x28,  0x41,  0x29,  0x0,  0x28,  0x42,  0x29,  0x0,  0x28,  0x43,  0x29,  0x0,  0x28,  0x44,  0x29,  0x0,  0x28,  0x45,  0x29,  0x0,  0x28,  0x46,  0x29,  0x0,  0x28,  0x47,  0x29,  0x0,  0x28,  0x48,  0x29,  0x0,  0x28,  0x49,  0x29,  0x0,  0x28,  0x4a,  0x29,  0x0,  0x28,  0x4b,  0x29,  0x0,  0x28,  0x4c,  0x29,  0x0,  0x28,  0x4d,  0x29,  0x0,  0x28,  0x4e,  0x29,  0x0,  0x28,  0x4f,  0x29,  0x0,  0x28,  0x50,  0x29,  0x0,  0x28,  0x51,  0x29,  0x0,  0x28,  0x52,  0x29,  0x0,  0x28,  0x53,  0x29,  0x0,  0x28,  0x54,  0x29,  0x0,  0x28,  0x55,  0x29,  0x0,  0x28,  0x56,  0x29,  0x0,  0x28,  0x57,  0x29,  0x0,  0x28,  0x58,  0x29,  0x0,  0x28,  0x59,  0x29,  0x0,  0x28,  0x5a,  0x29,  0x0,  0x28,  0x61,  0x29,  0x0,  0x28,  0x62,  0x29,  0x0,  0x28,  0x63,  0x29,  0x0,  0x28,  0x64,  0x29,  0x0,  0x28,  0x65,  0x29,  0x0,  0x28,  0x66,  0x29,  0x0,  0x28,  0x67,  0x29,  0x0,  0x28,  0x68,  0x29,  0x0,  0x28,  0x69,  0x29,  0x0,  0x28,  0x6a,  0x29,  0x0,  0x28,  0x6b,  0x29,  0x0,  0x28,  0x6c,  0x29,  0x0,  0x28,  0x6d,  0x29,  0x0,  0x28,  0x6e,  0x29,  0x0,  0x28,  0x6f,  0x29,  0x0,  0x28,  0x70,  0x29,  0x0,  0x28,  0x71,  0x29,  0x0,  0x28,  0x72,  0x29,  0x0,  0x28,  0x73,  0x29,  0x0,  0x28,  0x74,  0x29,  0x0,  0x28,  0x75,  0x29,  0x0,  0x28,  0x76,  0x29,  0x0,  0x28,  0x77,  0x29,  0x0,  0x28,  0x78,  0x29,  0x0,  0x28,  0x79,  0x29,  0x0,  0x28,  0x7a,  0x29,  0x0,  0x28,  0x1100,  0x29,  0x0,  0x28,  0x1100,  0x1161,  0x29,  0x0,  0x28,  0x1102,  0x29,  0x0,  0x28,  0x1102,  0x1161,  0x29,  0x0,  0x28,  0x1103,  0x29,  0x0,  0x28,  0x1103,  0x1161,  0x29,  0x0,  0x28,  0x1105,  0x29,  0x0,  0x28,  0x1105,  0x1161,  0x29,  0x0,  0x28,  0x1106,  0x29,  0x0,  0x28,  0x1106,  0x1161,  0x29,  0x0,  0x28,  0x1107,  0x29,  0x0,  0x28,  0x1107,  0x1161,  0x29,  0x0,  0x28,  0x1109,  0x29,  0x0,  0x28,  0x1109,  0x1161,  0x29,  0x0,  0x28,  0x110b,  0x29,  0x0,  0x28,  0x110b,  0x1161,  0x29,  0x0,  0x28,  0x110b,  0x1169,  0x110c,  0x1165,  0x11ab,  0x29,  0x0,  0x28,  0x110b,  0x1169,  0x1112,  0x116e,  0x29,  0x0,  0x28,  0x110c,  0x29,  0x0,  0x28,  0x110c,  0x1161,  0x29,  0x0,  0x28,  0x110c,  0x116e,  0x29,  0x0,  0x28,  0x110e,  0x29,  0x0,  0x28,  0x110e,  0x1161,  0x29,  0x0,  0x28,  0x110f,  0x29,  0x0,  0x28,  0x110f,  0x1161,  0x29,  0x0,  0x28,  0x1110,  0x29,  0x0,  0x28,  0x1110,  0x1161,  0x29,  0x0,  0x28,  0x1111,  0x29,  0x0,  0x28,  0x1111,  0x1161,  0x29,  0x0,  0x28,  0x1112,  0x29,  0x0,  0x28,  0x1112,  0x1161,  0x29,  0x0,  0x28,  0x4e00,  0x29,  0x0,  0x28,  0x4e03,  0x29,  0x0,  0x28,  0x4e09,  0x29,  0x0,  0x28,  0x4e5d,  0x29,  0x0,  0x28,  0x4e8c,  0x29,  0x0,  0x28,  0x4e94,  0x29,  0x0,  0x28,  0x4ee3,  0x29,  0x0,  0x28,  0x4f01,  0x29,  0x0,  0x28,  0x4f11,  0x29,  0x0,  0x28,  0x516b,  0x29,  0x0,  0x28,  0x516d,  0x29,  0x0,  0x28,  0x52b4,  0x29,  0x0,  0x28,  0x5341,  0x29,  0x0,  0x28,  0x5354,  0x29,  0x0,  0x28,  0x540d,  0x29,  0x0,  0x28,  0x547c,  0x29,  0x0,  0x28,  0x56db,  0x29,  0x0,  0x28,  0x571f,  0x29,  0x0,  0x28,  0x5b66,  0x29,  0x0,  0x28,  0x65e5,  0x29,  0x0,  0x28,  0x6708,  0x29,  0x0,  0x28,  0x6709,  0x29,  0x0,  0x28,  0x6728,  0x29,  0x0,  0x28,  0x682a,  0x29,  0x0,  0x28,  0x6c34,  0x29,  0x0,  0x28,  0x706b,  0x29,  0x0,  0x28,  0x7279,  0x29,  0x0,  0x28,  0x76e3,  0x29,  0x0,  0x28,  0x793e,  0x29,  0x0,  0x28,  0x795d,  0x29,  0x0,  0x28,  0x796d,  0x29,  0x0,  0x28,  0x81ea,  0x29,  0x0,  0x28,  0x81f3,  0x29,  0x0,  0x28,  0x8ca1,  0x29,  0x0,  0x28,  0x8cc7,  0x29,  0x0,  0x28,  0x91d1,  0x29,  0x0,  0x29,  0x0,  0x2a,  0x0,  0x2b,  0x0,  0x2c,  0x0,  0x2d,  0x0,  0x2e,  0x0,  0x2e,  0x2e,  0x0,  0x2e,  0x2e,  0x2e,  0x0,  0x2f,  0x0,  0x30,  0x0,  0x30,  0x2c,  0x0,  0x30,  0x2e,  0x0,  0x30,  0x2044,  0x33,  0x0,  0x30,  0x70b9,  0x0,  0x31,  0x0,  0x31,  0x2c,  0x0,  0x31,  0x2e,  0x0,  0x31,  0x30,  0x0,  0x31,  0x30,  0x2e,  0x0,  0x31,  0x30,  0x65e5,  0x0,  0x31,  0x30,  0x6708,  0x0,  0x31,  0x30,  0x70b9,  0x0,  0x31,  0x31,  0x0,  0x31,  0x31,  0x2e,  0x0,  0x31,  0x31,  0x65e5,  0x0,  0x31,  0x31,  0x6708,  0x0,  0x31,  0x31,  0x70b9,  0x0,  0x31,  0x32,  0x0,  0x31,  0x32,  0x2e,  0x0,  0x31,  0x32,  0x65e5,  0x0,  0x31,  0x32,  0x6708,  0x0,  0x31,  0x32,  0x70b9,  0x0,  0x31,  0x33,  0x0,  0x31,  0x33,  0x2e,  0x0,  0x31,  0x33,  0x65e5,  0x0,  0x31,  0x33,  0x70b9,  0x0,  0x31,  0x34,  0x0,  0x31,  0x34,  0x2e,  0x0,  0x31,  0x34,  0x65e5,  0x0,  0x31,  0x34,  0x70b9,  0x0,  0x31,  0x35,  0x0,  0x31,  0x35,  0x2e,  0x0,  0x31,  0x35,  0x65e5,  0x0,  0x31,  0x35,  0x70b9,  0x0,  0x31,  0x36,  0x0,  0x31,  0x36,  0x2e,  0x0,  0x31,  0x36,  0x65e5,  0x0,  0x31,  0x36,  0x70b9,  0x0,  0x31,  0x37,  0x0,  0x31,  0x37,  0x2e,  0x0,  0x31,  0x37,  0x65e5,  0x0,  0x31,  0x37,  0x70b9,  0x0,  0x31,  0x38,  0x0,  0x31,  0x38,  0x2e,  0x0,  0x31,  0x38,  0x65e5,  0x0,  0x31,  0x38,  0x70b9,  0x0,  0x31,  0x39,  0x0,  0x31,  0x39,  0x2e,  0x0,  0x31,  0x39,  0x65e5,  0x0,  0x31,  0x39,  0x70b9,  0x0,  0x31,  0x2044,  0x0,  0x31,  0x2044,  0x31,  0x30,  0x0,  0x31,  0x2044,  0x32,  0x0,  0x31,  0x2044,  0x33,  0x0,  0x31,  0x2044,  0x34,  0x0,  0x31,  0x2044,  0x35,  0x0,  0x31,  0x2044,  0x36,  0x0,  0x31,  0x2044,  0x37,  0x0,  0x31,  0x2044,  0x38,  0x0,  0x31,  0x2044,  0x39,  0x0,  0x31,  0x65e5,  0x0,  0x31,  0x6708,  0x0,  0x31,  0x70b9,  0x0,  0x32,  0x0,  0x32,  0x2c,  0x0,  0x32,  0x2e,  0x0,  0x32,  0x30,  0x0,  0x32,  0x30,  0x2e,  0x0,  0x32,  0x30,  0x65e5,  0x0,  0x32,  0x30,  0x70b9,  0x0,  0x32,  0x31,  0x0,  0x32,  0x31,  0x65e5,  0x0,  0x32,  0x31,  0x70b9,  0x0,  0x32,  0x32,  0x0,  0x32,  0x32,  0x65e5,  0x0,  0x32,  0x32,  0x70b9,  0x0,  0x32,  0x33,  0x0,  0x32,  0x33,  0x65e5,  0x0,  0x32,  0x33,  0x70b9,  0x0,  0x32,  0x34,  0x0,  0x32,  0x34,  0x65e5,  0x0,  0x32,  0x34,  0x70b9,  0x0,  0x32,  0x35,  0x0,  0x32,  0x35,  0x65e5,  0x0,  0x32,  0x36,  0x0,  0x32,  0x36,  0x65e5,  0x0,  0x32,  0x37,  0x0,  0x32,  0x37,  0x65e5,  0x0,  0x32,  0x38,  0x0,  0x32,  0x38,  0x65e5,  0x0,  0x32,  0x39,  0x0,  0x32,  0x39,  0x65e5,  0x0,  0x32,  0x2044,  0x33,  0x0,  0x32,  0x2044,  0x35,  0x0,  0x32,  0x65e5,  0x0,  0x32,  0x6708,  0x0,  0x32,  0x70b9,  0x0,  0x33,  0x0,  0x33,  0x2c,  0x0,  0x33,  0x2e,  0x0,  0x33,  0x30,  0x0,  0x33,  0x30,  0x65e5,  0x0,  0x33,  0x31,  0x0,  0x33,  0x31,  0x65e5,  0x0,  0x33,  0x32,  0x0,  0x33,  0x33,  0x0,  0x33,  0x34,  0x0,  0x33,  0x35,  0x0,  0x33,  0x36,  0x0,  0x33,  0x37,  0x0,  0x33,  0x38,  0x0,  0x33,  0x39,  0x0,  0x33,  0x2044,  0x34,  0x0,  0x33,  0x2044,  0x35,  0x0,  0x33,  0x2044,  0x38,  0x0,  0x33,  0x65e5,  0x0,  0x33,  0x6708,  0x0,  0x33,  0x70b9,  0x0,  0x34,  0x0,  0x34,  0x2c,  0x0,  0x34,  0x2e,  0x0,  0x34,  0x30,  0x0,  0x34,  0x31,  0x0,  0x34,  0x32,  0x0,  0x34,  0x33,  0x0,  0x34,  0x34,  0x0,  0x34,  0x35,  0x0,  0x34,  0x36,  0x0,  0x34,  0x37,  0x0,  0x34,  0x38,  0x0,  0x34,  0x39,  0x0,  0x34,  0x2044,  0x35,  0x0,  0x34,  0x65e5,  0x0,  0x34,  0x6708,  0x0,  0x34,  0x70b9,  0x0,  0x35,  0x0,  0x35,  0x2c,  0x0,  0x35,  0x2e,  0x0,  0x35,  0x30,  0x0,  0x35,  0x2044,  0x36,  0x0,  0x35,  0x2044,  0x38,  0x0,  0x35,  0x65e5,  0x0,  0x35,  0x6708,  0x0,  0x35,  0x70b9,  0x0,  0x36,  0x0,  0x36,  0x2c,  0x0,  0x36,  0x2e,  0x0,  0x36,  0x65e5,  0x0,  0x36,  0x6708,  0x0,  0x36,  0x70b9,  0x0,  0x37,  0x0,  0x37,  0x2c,  0x0,  0x37,  0x2e,  0x0,  0x37,  0x2044,  0x38,  0x0,  0x37,  0x65e5,  0x0,  0x37,  0x6708,  0x0,  0x37,  0x70b9,  0x0,  0x38,  0x0,  0x38,  0x2c,  0x0,  0x38,  0x2e,  0x0,  0x38,  0x65e5,  0x0,  0x38,  0x6708,  0x0,  0x38,  0x70b9,  0x0,  0x39,  0x0,  0x39,  0x2c,  0x0,  0x39,  0x2e,  0x0,  0x39,  0x65e5,  0x0,  0x39,  0x6708,  0x0,  0x39,  0x70b9,  0x0,  0x3a,  0x0,  0x3a,  0x3a,  0x3d,  0x0,  0x3b,  0x0,  0x3c,  0x0,  0x3c,  0x338,  0x0,  0x3d,  0x0,  0x3d,  0x3d,  0x0,  0x3d,  0x3d,  0x3d,  0x0,  0x3d,  0x338,  0x0,  0x3e,  0x0,  0x3e,  0x338,  0x0,  0x3f,  0x0,  0x3f,  0x21,  0x0,  0x3f,  0x3f,  0x0,  0x40,  0x0,  0x41,  0x0,  0x41,  0x55,  0x0,  0x41,  0x300,  0x0,  0x41,  0x301,  0x0,  0x41,  0x302,  0x0,  0x41,  0x302,  0x300,  0x0,  0x41,  0x302,  0x301,  0x0,  0x41,  0x302,  0x303,  0x0,  0x41,  0x302,  0x309,  0x0,  0x41,  0x303,  0x0,  0x41,  0x304,  0x0,  0x41,  0x306,  0x0,  0x41,  0x306,  0x300,  0x0,  0x41,  0x306,  0x301,  0x0,  0x41,  0x306,  0x303,  0x0,  0x41,  0x306,  0x309,  0x0,  0x41,  0x307,  0x0,  0x41,  0x307,  0x304,  0x0,  0x41,  0x308,  0x0,  0x41,  0x308,  0x304,  0x0,  0x41,  0x309,  0x0,  0x41,  0x30a,  0x0,  0x41,  0x30a,  0x301,  0x0,  0x41,  0x30c,  0x0,  0x41,  0x30f,  0x0,  0x41,  0x311,  0x0,  0x41,  0x323,  0x0,  0x41,  0x323,  0x302,  0x0,  0x41,  0x323,  0x306,  0x0,  0x41,  0x325,  0x0,  0x41,  0x328,  0x0,  0x41,  0x2215,  0x6d,  0x0,  0x42,  0x0,  0x42,  0x71,  0x0,  0x42,  0x307,  0x0,  0x42,  0x323,  0x0,  0x42,  0x331,  0x0,  0x43,  0x0,  0x43,  0x44,  0x0,  0x43,  0x6f,  0x2e,  0x0,  0x43,  0x301,  0x0,  0x43,  0x302,  0x0,  0x43,  0x307,  0x0,  0x43,  0x30c,  0x0,  0x43,  0x327,  0x0,  0x43,  0x327,  0x301,  0x0,  0x43,  0x2215,  0x6b,  0x67,  0x0,  0x44,  0x0,  0x44,  0x4a,  0x0,  0x44,  0x5a,  0x0,  0x44,  0x5a,  0x30c,  0x0,  0x44,  0x7a,  0x0,  0x44,  0x7a,  0x30c,  0x0,  0x44,  0x307,  0x0,  0x44,  0x30c,  0x0,  0x44,  0x323,  0x0,  0x44,  0x327,  0x0,  0x44,  0x32d,  0x0,  0x44,  0x331,  0x0,  0x45,  0x0,  0x45,  0x300,  0x0,  0x45,  0x301,  0x0,  0x45,  0x302,  0x0,  0x45,  0x302,  0x300,  0x0,  0x45,  0x302,  0x301,  0x0,  0x45,  0x302,  0x303,  0x0,  0x45,  0x302,  0x309,  0x0,  0x45,  0x303,  0x0,  0x45,  0x304,  0x0,  0x45,  0x304,  0x300,  0x0,  0x45,  0x304,  0x301,  0x0,  0x45,  0x306,  0x0,  0x45,  0x307,  0x0,  0x45,  0x308,  0x0,  0x45,  0x309,  0x0,  0x45,  0x30c,  0x0,  0x45,  0x30f,  0x0,  0x45,  0x311,  0x0,  0x45,  0x323,  0x0,  0x45,  0x323,  0x302,  0x0,  0x45,  0x327,  0x0,  0x45,  0x327,  0x306,  0x0,  0x45,  0x328,  0x0,  0x45,  0x32d,  0x0,  0x45,  0x330,  0x0,  0x46,  0x0,  0x46,  0x41,  0x58,  0x0,  0x46,  0x307,  0x0,  0x47,  0x0,  0x47,  0x42,  0x0,  0x47,  0x48,  0x7a,  0x0,  0x47,  0x50,  0x61,  0x0,  0x47,  0x79,  0x0,  0x47,  0x301,  0x0,  0x47,  0x302,  0x0,  0x47,  0x304,  0x0,  0x47,  0x306,  0x0,  0x47,  0x307,  0x0,  0x47,  0x30c,  0x0,  0x47,  0x327,  0x0,  0x48,  0x0,  0x48,  0x50,  0x0,  0x48,  0x56,  0x0,  0x48,  0x67,  0x0,  0x48,  0x7a,  0x0,  0x48,  0x302,  0x0,  0x48,  0x307,  0x0,  0x48,  0x308,  0x0,  0x48,  0x30c,  0x0,  0x48,  0x323,  0x0,  0x48,  0x327,  0x0,  0x48,  0x32e,  0x0,  0x49,  0x0,  0x49,  0x49,  0x0,  0x49,  0x49,  0x49,  0x0,  0x49,  0x4a,  0x0,  0x49,  0x55,  0x0,  0x49,  0x56,  0x0,  0x49,  0x58,  0x0,  0x49,  0x300,  0x0,  0x49,  0x301,  0x0,  0x49,  0x302,  0x0,  0x49,  0x303,  0x0,  0x49,  0x304,  0x0,  0x49,  0x306,  0x0,  0x49,  0x307,  0x0,  0x49,  0x308,  0x0,  0x49,  0x308,  0x301,  0x0,  0x49,  0x309,  0x0,  0x49,  0x30c,  0x0,  0x49,  0x30f,  0x0,  0x49,  0x311,  0x0,  0x49,  0x323,  0x0,  0x49,  0x328,  0x0,  0x49,  0x330,  0x0,  0x4a,  0x0,  0x4a,  0x302,  0x0,  0x4b,  0x0,  0x4b,  0x42,  0x0,  0x4b,  0x4b,  0x0,  0x4b,  0x4d,  0x0,  0x4b,  0x301,  0x0,  0x4b,  0x30c,  0x0,  0x4b,  0x323,  0x0,  0x4b,  0x327,  0x0,  0x4b,  0x331,  0x0,  0x4c,  0x0,  0x4c,  0x4a,  0x0,  0x4c,  0x54,  0x44,  0x0,  0x4c,  0x6a,  0x0,  0x4c,  0xb7,  0x0,  0x4c,  0x301,  0x0,  0x4c,  0x30c,  0x0,  0x4c,  0x323,  0x0,  0x4c,  0x323,  0x304,  0x0,  0x4c,  0x327,  0x0,  0x4c,  0x32d,  0x0,  0x4c,  0x331,  0x0,  0x4d,  0x0,  0x4d,  0x42,  0x0,  0x4d,  0x43,  0x0,  0x4d,  0x44,  0x0,  0x4d,  0x48,  0x7a,  0x0,  0x4d,  0x50,  0x61,  0x0,  0x4d,  0x56,  0x0,  0x4d,  0x57,  0x0,  0x4d,  0x301,  0x0,  0x4d,  0x307,  0x0,  0x4d,  0x323,  0x0,  0x4d,  0x3a9,  0x0,  0x4e,  0x0,  0x4e,  0x4a,  0x0,  0x4e,  0x6a,  0x0,  0x4e,  0x6f,  0x0,  0x4e,  0x300,  0x0,  0x4e,  0x301,  0x0,  0x4e,  0x303,  0x0,  0x4e,  0x307,  0x0,  0x4e,  0x30c,  0x0,  0x4e,  0x323,  0x0,  0x4e,  0x327,  0x0,  0x4e,  0x32d,  0x0,  0x4e,  0x331,  0x0,  0x4f,  0x0,  0x4f,  0x300,  0x0,  0x4f,  0x301,  0x0,  0x4f,  0x302,  0x0,  0x4f,  0x302,  0x300,  0x0,  0x4f,  0x302,  0x301,  0x0,  0x4f,  0x302,  0x303,  0x0,  0x4f,  0x302,  0x309,  0x0,  0x4f,  0x303,  0x0,  0x4f,  0x303,  0x301,  0x0,  0x4f,  0x303,  0x304,  0x0,  0x4f,  0x303,  0x308,  0x0,  0x4f,  0x304,  0x0,  0x4f,  0x304,  0x300,  0x0,  0x4f,  0x304,  0x301,  0x0,  0x4f,  0x306,  0x0,  0x4f,  0x307,  0x0,  0x4f,  0x307,  0x304,  0x0,  0x4f,  0x308,  0x0,  0x4f,  0x308,  0x304,  0x0,  0x4f,  0x309,  0x0,  0x4f,  0x30b,  0x0,  0x4f,  0x30c,  0x0,  0x4f,  0x30f,  0x0,  0x4f,  0x311,  0x0,  0x4f,  0x31b,  0x0,  0x4f,  0x31b,  0x300,  0x0,  0x4f,  0x31b,  0x301,  0x0,  0x4f,  0x31b,  0x303,  0x0,  0x4f,  0x31b,  0x309,  0x0,  0x4f,  0x31b,  0x323,  0x0,  0x4f,  0x323,  0x0,  0x4f,  0x323,  0x302,  0x0,  0x4f,  0x328,  0x0,  0x4f,  0x328,  0x304,  0x0,  0x50,  0x0,  0x50,  0x48,  0x0,  0x50,  0x50,  0x4d,  0x0,  0x50,  0x50,  0x56,  0x0,  0x50,  0x52,  0x0,  0x50,  0x54,  0x45,  0x0,  0x50,  0x61,  0x0,  0x50,  0x301,  0x0,  0x50,  0x307,  0x0,  0x51,  0x0,  0x52,  0x0,  0x52,  0x73,  0x0,  0x52,  0x301,  0x0,  0x52,  0x307,  0x0,  0x52,  0x30c,  0x0,  0x52,  0x30f,  0x0,  0x52,  0x311,  0x0,  0x52,  0x323,  0x0,  0x52,  0x323,  0x304,  0x0,  0x52,  0x327,  0x0,  0x52,  0x331,  0x0,  0x53,  0x0,  0x53,  0x44,  0x0,  0x53,  0x4d,  0x0,  0x53,  0x53,  0x0,  0x53,  0x76,  0x0,  0x53,  0x301,  0x0,  0x53,  0x301,  0x307,  0x0,  0x53,  0x302,  0x0,  0x53,  0x307,  0x0,  0x53,  0x30c,  0x0,  0x53,  0x30c,  0x307,  0x0,  0x53,  0x323,  0x0,  0x53,  0x323,  0x307,  0x0,  0x53,  0x326,  0x0,  0x53,  0x327,  0x0,  0x54,  0x0,  0x54,  0x45,  0x4c,  0x0,  0x54,  0x48,  0x7a,  0x0,  0x54,  0x4d,  0x0,  0x54,  0x307,  0x0,  0x54,  0x30c,  0x0,  0x54,  0x323,  0x0,  0x54,  0x326,  0x0,  0x54,  0x327,  0x0,  0x54,  0x32d,  0x0,  0x54,  0x331,  0x0,  0x55,  0x0,  0x55,  0x300,  0x0,  0x55,  0x301,  0x0,  0x55,  0x302,  0x0,  0x55,  0x303,  0x0,  0x55,  0x303,  0x301,  0x0,  0x55,  0x304,  0x0,  0x55,  0x304,  0x308,  0x0,  0x55,  0x306,  0x0,  0x55,  0x308,  0x0,  0x55,  0x308,  0x300,  0x0,  0x55,  0x308,  0x301,  0x0,  0x55,  0x308,  0x304,  0x0,  0x55,  0x308,  0x30c,  0x0,  0x55,  0x309,  0x0,  0x55,  0x30a,  0x0,  0x55,  0x30b,  0x0,  0x55,  0x30c,  0x0,  0x55,  0x30f,  0x0,  0x55,  0x311,  0x0,  0x55,  0x31b,  0x0,  0x55,  0x31b,  0x300,  0x0,  0x55,  0x31b,  0x301,  0x0,  0x55,  0x31b,  0x303,  0x0,  0x55,  0x31b,  0x309,  0x0,  0x55,  0x31b,  0x323,  0x0,  0x55,  0x323,  0x0,  0x55,  0x324,  0x0,  0x55,  0x328,  0x0,  0x55,  0x32d,  0x0,  0x55,  0x330,  0x0,  0x56,  0x0,  0x56,  0x49,  0x0,  0x56,  0x49,  0x49,  0x0,  0x56,  0x49,  0x49,  0x49,  0x0,  0x56,  0x303,  0x0,  0x56,  0x323,  0x0,  0x56,  0x2215,  0x6d,  0x0,  0x57,  0x0,  0x57,  0x43,  0x0,  0x57,  0x5a,  0x0,  0x57,  0x62,  0x0,  0x57,  0x300,  0x0,  0x57,  0x301,  0x0,  0x57,  0x302,  0x0,  0x57,  0x307,  0x0,  0x57,  0x308,  0x0,  0x57,  0x323,  0x0,  0x58,  0x0,  0x58,  0x49,  0x0,  0x58,  0x49,  0x49,  0x0,  0x58,  0x307,  0x0,  0x58,  0x308,  0x0,  0x59,  0x0,  0x59,  0x300,  0x0,  0x59,  0x301,  0x0,  0x59,  0x302,  0x0,  0x59,  0x303,  0x0,  0x59,  0x304,  0x0,  0x59,  0x307,  0x0,  0x59,  0x308,  0x0,  0x59,  0x309,  0x0,  0x59,  0x323,  0x0,  0x5a,  0x0,  0x5a,  0x301,  0x0,  0x5a,  0x302,  0x0,  0x5a,  0x307,  0x0,  0x5a,  0x30c,  0x0,  0x5a,  0x323,  0x0,  0x5a,  0x331,  0x0,  0x5b,  0x0,  0x5c,  0x0,  0x5d,  0x0,  0x5e,  0x0,  0x5f,  0x0,  0x60,  0x0,  0x61,  0x0,  0x61,  0x2e,  0x6d,  0x2e,  0x0,  0x61,  0x2f,  0x63,  0x0,  0x61,  0x2f,  0x73,  0x0,  0x61,  0x2be,  0x0,  0x61,  0x300,  0x0,  0x61,  0x301,  0x0,  0x61,  0x302,  0x0,  0x61,  0x302,  0x300,  0x0,  0x61,  0x302,  0x301,  0x0,  0x61,  0x302,  0x303,  0x0,  0x61,  0x302,  0x309,  0x0,  0x61,  0x303,  0x0,  0x61,  0x304,  0x0,  0x61,  0x306,  0x0,  0x61,  0x306,  0x300,  0x0,  0x61,  0x306,  0x301,  0x0,  0x61,  0x306,  0x303,  0x0,  0x61,  0x306,  0x309,  0x0,  0x61,  0x307,  0x0,  0x61,  0x307,  0x304,  0x0,  0x61,  0x308,  0x0,  0x61,  0x308,  0x304,  0x0,  0x61,  0x309,  0x0,  0x61,  0x30a,  0x0,  0x61,  0x30a,  0x301,  0x0,  0x61,  0x30c,  0x0,  0x61,  0x30f,  0x0,  0x61,  0x311,  0x0,  0x61,  0x323,  0x0,  0x61,  0x323,  0x302,  0x0,  0x61,  0x323,  0x306,  0x0,  0x61,  0x325,  0x0,  0x61,  0x328,  0x0,  0x62,  0x0,  0x62,  0x61,  0x72,  0x0,  0x62,  0x307,  0x0,  0x62,  0x323,  0x0,  0x62,  0x331,  0x0,  0x63,  0x0,  0x63,  0x2f,  0x6f,  0x0,  0x63,  0x2f,  0x75,  0x0,  0x63,  0x61,  0x6c,  0x0,  0x63,  0x63,  0x0,  0x63,  0x64,  0x0,  0x63,  0x6d,  0x0,  0x63,  0x6d,  0x32,  0x0,  0x63,  0x6d,  0x33,  0x0,  0x63,  0x301,  0x0,  0x63,  0x302,  0x0,  0x63,  0x307,  0x0,  0x63,  0x30c,  0x0,  0x63,  0x327,  0x0,  0x63,  0x327,  0x301,  0x0,  0x64,  0x0,  0x64,  0x42,  0x0,  0x64,  0x61,  0x0,  0x64,  0x6c,  0x0,  0x64,  0x6d,  0x0,  0x64,  0x6d,  0x32,  0x0,  0x64,  0x6d,  0x33,  0x0,  0x64,  0x7a,  0x0,  0x64,  0x7a,  0x30c,  0x0,  0x64,  0x307,  0x0,  0x64,  0x30c,  0x0,  0x64,  0x323,  0x0,  0x64,  0x327,  0x0,  0x64,  0x32d,  0x0,  0x64,  0x331,  0x0,  0x65,  0x0,  0x65,  0x56,  0x0,  0x65,  0x72,  0x67,  0x0,  0x65,  0x300,  0x0,  0x65,  0x301,  0x0,  0x65,  0x302,  0x0,  0x65,  0x302,  0x300,  0x0,  0x65,  0x302,  0x301,  0x0,  0x65,  0x302,  0x303,  0x0,  0x65,  0x302,  0x309,  0x0,  0x65,  0x303,  0x0,  0x65,  0x304,  0x0,  0x65,  0x304,  0x300,  0x0,  0x65,  0x304,  0x301,  0x0,  0x65,  0x306,  0x0,  0x65,  0x307,  0x0,  0x65,  0x308,  0x0,  0x65,  0x309,  0x0,  0x65,  0x30c,  0x0,  0x65,  0x30f,  0x0,  0x65,  0x311,  0x0,  0x65,  0x323,  0x0,  0x65,  0x323,  0x302,  0x0,  0x65,  0x327,  0x0,  0x65,  0x327,  0x306,  0x0,  0x65,  0x328,  0x0,  0x65,  0x32d,  0x0,  0x65,  0x330,  0x0,  0x66,  0x0,  0x66,  0x66,  0x0,  0x66,  0x66,  0x69,  0x0,  0x66,  0x66,  0x6c,  0x0,  0x66,  0x69,  0x0,  0x66,  0x6c,  0x0,  0x66,  0x6d,  0x0,  0x66,  0x307,  0x0,  0x67,  0x0,  0x67,  0x61,  0x6c,  0x0,  0x67,  0x301,  0x0,  0x67,  0x302,  0x0,  0x67,  0x304,  0x0,  0x67,  0x306,  0x0,  0x67,  0x307,  0x0,  0x67,  0x30c,  0x0,  0x67,  0x327,  0x0,  0x68,  0x0,  0x68,  0x50,  0x61,  0x0,  0x68,  0x61,  0x0,  0x68,  0x302,  0x0,  0x68,  0x307,  0x0,  0x68,  0x308,  0x0,  0x68,  0x30c,  0x0,  0x68,  0x323,  0x0,  0x68,  0x327,  0x0,  0x68,  0x32e,  0x0,  0x68,  0x331,  0x0,  0x69,  0x0,  0x69,  0x69,  0x0,  0x69,  0x69,  0x69,  0x0,  0x69,  0x6a,  0x0,  0x69,  0x6e,  0x0,  0x69,  0x76,  0x0,  0x69,  0x78,  0x0,  0x69,  0x300,  0x0,  0x69,  0x301,  0x0,  0x69,  0x302,  0x0,  0x69,  0x303,  0x0,  0x69,  0x304,  0x0,  0x69,  0x306,  0x0,  0x69,  0x308,  0x0,  0x69,  0x308,  0x301,  0x0,  0x69,  0x309,  0x0,  0x69,  0x30c,  0x0,  0x69,  0x30f,  0x0,  0x69,  0x311,  0x0,  0x69,  0x323,  0x0,  0x69,  0x328,  0x0,  0x69,  0x330,  0x0,  0x6a,  0x0,  0x6a,  0x302,  0x0,  0x6a,  0x30c,  0x0,  0x6b,  0x0,  0x6b,  0x41,  0x0,  0x6b,  0x48,  0x7a,  0x0,  0x6b,  0x50,  0x61,  0x0,  0x6b,  0x56,  0x0,  0x6b,  0x57,  0x0,  0x6b,  0x63,  0x61,  0x6c,  0x0,  0x6b,  0x67,  0x0,  0x6b,  0x6c,  0x0,  0x6b,  0x6d,  0x0,  0x6b,  0x6d,  0x32,  0x0,  0x6b,  0x6d,  0x33,  0x0,  0x6b,  0x74,  0x0,  0x6b,  0x301,  0x0,  0x6b,  0x30c,  0x0,  0x6b,  0x323,  0x0,  0x6b,  0x327,  0x0,  0x6b,  0x331,  0x0,  0x6b,  0x3a9,  0x0,  0x6c,  0x0,  0x6c,  0x6a,  0x0,  0x6c,  0x6d,  0x0,  0x6c,  0x6e,  0x0,  0x6c,  0x6f,  0x67,  0x0,  0x6c,  0x78,  0x0,  0x6c,  0xb7,  0x0,  0x6c,  0x301,  0x0,  0x6c,  0x30c,  0x0,  0x6c,  0x323,  0x0,  0x6c,  0x323,  0x304,  0x0,  0x6c,  0x327,  0x0,  0x6c,  0x32d,  0x0,  0x6c,  0x331,  0x0,  0x6d,  0x0,  0x6d,  0x32,  0x0,  0x6d,  0x33,  0x0,  0x6d,  0x41,  0x0,  0x6d,  0x56,  0x0,  0x6d,  0x57,  0x0,  0x6d,  0x62,  0x0,  0x6d,  0x67,  0x0,  0x6d,  0x69,  0x6c,  0x0,  0x6d,  0x6c,  0x0,  0x6d,  0x6d,  0x0,  0x6d,  0x6d,  0x32,  0x0,  0x6d,  0x6d,  0x33,  0x0,  0x6d,  0x6f,  0x6c,  0x0,  0x6d,  0x73,  0x0,  0x6d,  0x301,  0x0,  0x6d,  0x307,  0x0,  0x6d,  0x323,  0x0,  0x6d,  0x2215,  0x73,  0x0,  0x6d,  0x2215,  0x73,  0x32,  0x0,  0x6e,  0x0,  0x6e,  0x41,  0x0,  0x6e,  0x46,  0x0,  0x6e,  0x56,  0x0,  0x6e,  0x57,  0x0,  0x6e,  0x6a,  0x0,  0x6e,  0x6d,  0x0,  0x6e,  0x73,  0x0,  0x6e,  0x300,  0x0,  0x6e,  0x301,  0x0,  0x6e,  0x303,  0x0,  0x6e,  0x307,  0x0,  0x6e,  0x30c,  0x0,  0x6e,  0x323,  0x0,  0x6e,  0x327,  0x0,  0x6e,  0x32d,  0x0,  0x6e,  0x331,  0x0,  0x6f,  0x0,  0x6f,  0x56,  0x0,  0x6f,  0x300,  0x0,  0x6f,  0x301,  0x0,  0x6f,  0x302,  0x0,  0x6f,  0x302,  0x300,  0x0,  0x6f,  0x302,  0x301,  0x0,  0x6f,  0x302,  0x303,  0x0,  0x6f,  0x302,  0x309,  0x0,  0x6f,  0x303,  0x0,  0x6f,  0x303,  0x301,  0x0,  0x6f,  0x303,  0x304,  0x0,  0x6f,  0x303,  0x308,  0x0,  0x6f,  0x304,  0x0,  0x6f,  0x304,  0x300,  0x0,  0x6f,  0x304,  0x301,  0x0,  0x6f,  0x306,  0x0,  0x6f,  0x307,  0x0,  0x6f,  0x307,  0x304,  0x0,  0x6f,  0x308,  0x0,  0x6f,  0x308,  0x304,  0x0,  0x6f,  0x309,  0x0,  0x6f,  0x30b,  0x0,  0x6f,  0x30c,  0x0,  0x6f,  0x30f,  0x0,  0x6f,  0x311,  0x0,  0x6f,  0x31b,  0x0,  0x6f,  0x31b,  0x300,  0x0,  0x6f,  0x31b,  0x301,  0x0,  0x6f,  0x31b,  0x303,  0x0,  0x6f,  0x31b,  0x309,  0x0,  0x6f,  0x31b,  0x323,  0x0,  0x6f,  0x323,  0x0,  0x6f,  0x323,  0x302,  0x0,  0x6f,  0x328,  0x0,  0x6f,  0x328,  0x304,  0x0,  0x70,  0x0,  0x70,  0x2e,  0x6d,  0x2e,  0x0,  0x70,  0x41,  0x0,  0x70,  0x46,  0x0,  0x70,  0x56,  0x0,  0x70,  0x57,  0x0,  0x70,  0x63,  0x0,  0x70,  0x73,  0x0,  0x70,  0x301,  0x0,  0x70,  0x307,  0x0,  0x71,  0x0,  0x72,  0x0,  0x72,  0x61,  0x64,  0x0,  0x72,  0x61,  0x64,  0x2215,  0x73,  0x0,  0x72,  0x61,  0x64,  0x2215,  0x73,  0x32,  0x0,  0x72,  0x301,  0x0,  0x72,  0x307,  0x0,  0x72,  0x30c,  0x0,  0x72,  0x30f,  0x0,  0x72,  0x311,  0x0,  0x72,  0x323,  0x0,  0x72,  0x323,  0x304,  0x0,  0x72,  0x327,  0x0,  0x72,  0x331,  0x0,  0x73,  0x0,  0x73,  0x72,  0x0,  0x73,  0x74,  0x0,  0x73,  0x301,  0x0,  0x73,  0x301,  0x307,  0x0,  0x73,  0x302,  0x0,  0x73,  0x307,  0x0,  0x73,  0x30c,  0x0,  0x73,  0x30c,  0x307,  0x0,  0x73,  0x323,  0x0,  0x73,  0x323,  0x307,  0x0,  0x73,  0x326,  0x0,  0x73,  0x327,  0x0,  0x74,  0x0,  0x74,  0x307,  0x0,  0x74,  0x308,  0x0,  0x74,  0x30c,  0x0,  0x74,  0x323,  0x0,  0x74,  0x326,  0x0,  0x74,  0x327,  0x0,  0x74,  0x32d,  0x0,  0x74,  0x331,  0x0,  0x75,  0x0,  0x75,  0x300,  0x0,  0x75,  0x301,  0x0,  0x75,  0x302,  0x0,  0x75,  0x303,  0x0,  0x75,  0x303,  0x301,  0x0,  0x75,  0x304,  0x0,  0x75,  0x304,  0x308,  0x0,  0x75,  0x306,  0x0,  0x75,  0x308,  0x0,  0x75,  0x308,  0x300,  0x0,  0x75,  0x308,  0x301,  0x0,  0x75,  0x308,  0x304,  0x0,  0x75,  0x308,  0x30c,  0x0,  0x75,  0x309,  0x0,  0x75,  0x30a,  0x0,  0x75,  0x30b,  0x0,  0x75,  0x30c,  0x0,  0x75,  0x30f,  0x0,  0x75,  0x311,  0x0,  0x75,  0x31b,  0x0,  0x75,  0x31b,  0x300,  0x0,  0x75,  0x31b,  0x301,  0x0,  0x75,  0x31b,  0x303,  0x0,  0x75,  0x31b,  0x309,  0x0,  0x75,  0x31b,  0x323,  0x0,  0x75,  0x323,  0x0,  0x75,  0x324,  0x0,  0x75,  0x328,  0x0,  0x75,  0x32d,  0x0,  0x75,  0x330,  0x0,  0x76,  0x0,  0x76,  0x69,  0x0,  0x76,  0x69,  0x69,  0x0,  0x76,  0x69,  0x69,  0x69,  0x0,  0x76,  0x303,  0x0,  0x76,  0x323,  0x0,  0x77,  0x0,  0x77,  0x300,  0x0,  0x77,  0x301,  0x0,  0x77,  0x302,  0x0,  0x77,  0x307,  0x0,  0x77,  0x308,  0x0,  0x77,  0x30a,  0x0,  0x77,  0x323,  0x0,  0x78,  0x0,  0x78,  0x69,  0x0,  0x78,  0x69,  0x69,  0x0,  0x78,  0x307,  0x0,  0x78,  0x308,  0x0,  0x79,  0x0,  0x79,  0x300,  0x0,  0x79,  0x301,  0x0,  0x79,  0x302,  0x0,  0x79,  0x303,  0x0,  0x79,  0x304,  0x0,  0x79,  0x307,  0x0,  0x79,  0x308,  0x0,  0x79,  0x309,  0x0,  0x79,  0x30a,  0x0,  0x79,  0x323,  0x0,  0x7a,  0x0,  0x7a,  0x301,  0x0,  0x7a,  0x302,  0x0,  0x7a,  0x307,  0x0,  0x7a,  0x30c,  0x0,  0x7a,  0x323,  0x0,  0x7a,  0x331,  0x0,  0x7b,  0x0,  0x7c,  0x0,  0x7d,  0x0,  0x7e,  0x0,  0xa2,  0x0,  0xa3,  0x0,  0xa5,  0x0,  0xa6,  0x0,  0xac,  0x0,  0xb0,  0x43,  0x0,  0xb0,  0x46,  0x0,  0xb7,  0x0,  0xc6,  0x0,  0xc6,  0x301,  0x0,  0xc6,  0x304,  0x0,  0xd8,  0x301,  0x0,  0xe6,  0x301,  0x0,  0xe6,  0x304,  0x0,  0xf0,  0x0,  0xf8,  0x301,  0x0,  0x126,  0x0,  0x127,  0x0,  0x131,  0x0,  0x14b,  0x0,  0x153,  0x0,  0x18e,  0x0,  0x190,  0x0,  0x1ab,  0x0,  0x1b7,  0x30c,  0x0,  0x222,  0x0,  0x237,  0x0,  0x250,  0x0,  0x251,  0x0,  0x252,  0x0,  0x254,  0x0,  0x255,  0x0,  0x259,  0x0,  0x25b,  0x0,  0x25c,  0x0,  0x25f,  0x0,  0x261,  0x0,  0x263,  0x0,  0x265,  0x0,  0x266,  0x0,  0x268,  0x0,  0x269,  0x0,  0x26a,  0x0,  0x26d,  0x0,  0x26f,  0x0,  0x270,  0x0,  0x271,  0x0,  0x272,  0x0,  0x273,  0x0,  0x274,  0x0,  0x275,  0x0,  0x278,  0x0,  0x279,  0x0,  0x27b,  0x0,  0x281,  0x0,  0x282,  0x0,  0x283,  0x0,  0x289,  0x0,  0x28a,  0x0,  0x28b,  0x0,  0x28c,  0x0,  0x290,  0x0,  0x291,  0x0,  0x292,  0x0,  0x292,  0x30c,  0x0,  0x295,  0x0,  0x29d,  0x0,  0x29f,  0x0,  0x2b9,  0x0,  0x2bc,  0x6e,  0x0,  0x300,  0x0,  0x301,  0x0,  0x308,  0x301,  0x0,  0x313,  0x0,  0x391,  0x0,  0x391,  0x300,  0x0,  0x391,  0x301,  0x0,  0x391,  0x304,  0x0,  0x391,  0x306,  0x0,  0x391,  0x313,  0x0,  0x391,  0x313,  0x300,  0x0,  0x391,  0x313,  0x300,  0x345,  0x0,  0x391,  0x313,  0x301,  0x0,  0x391,  0x313,  0x301,  0x345,  0x0,  0x391,  0x313,  0x342,  0x0,  0x391,  0x313,  0x342,  0x345,  0x0,  0x391,  0x313,  0x345,  0x0,  0x391,  0x314,  0x0,  0x391,  0x314,  0x300,  0x0,  0x391,  0x314,  0x300,  0x345,  0x0,  0x391,  0x314,  0x301,  0x0,  0x391,  0x314,  0x301,  0x345,  0x0,  0x391,  0x314,  0x342,  0x0,  0x391,  0x314,  0x342,  0x345,  0x0,  0x391,  0x314,  0x345,  0x0,  0x391,  0x345,  0x0,  0x392,  0x0,  0x393,  0x0,  0x394,  0x0,  0x395,  0x0,  0x395,  0x300,  0x0,  0x395,  0x301,  0x0,  0x395,  0x313,  0x0,  0x395,  0x313,  0x300,  0x0,  0x395,  0x313,  0x301,  0x0,  0x395,  0x314,  0x0,  0x395,  0x314,  0x300,  0x0,  0x395,  0x314,  0x301,  0x0,  0x396,  0x0,  0x397,  0x0,  0x397,  0x300,  0x0,  0x397,  0x301,  0x0,  0x397,  0x313,  0x0,  0x397,  0x313,  0x300,  0x0,  0x397,  0x313,  0x300,  0x345,  0x0,  0x397,  0x313,  0x301,  0x0,  0x397,  0x313,  0x301,  0x345,  0x0,  0x397,  0x313,  0x342,  0x0,  0x397,  0x313,  0x342,  0x345,  0x0,  0x397,  0x313,  0x345,  0x0,  0x397,  0x314,  0x0,  0x397,  0x314,  0x300,  0x0,  0x397,  0x314,  0x300,  0x345,  0x0,  0x397,  0x314,  0x301,  0x0,  0x397,  0x314,  0x301,  0x345,  0x0,  0x397,  0x314,  0x342,  0x0,  0x397,  0x314,  0x342,  0x345,  0x0,  0x397,  0x314,  0x345,  0x0,  0x397,  0x345,  0x0,  0x398,  0x0,  0x399,  0x0,  0x399,  0x300,  0x0,  0x399,  0x301,  0x0,  0x399,  0x304,  0x0,  0x399,  0x306,  0x0,  0x399,  0x308,  0x0,  0x399,  0x313,  0x0,  0x399,  0x313,  0x300,  0x0,  0x399,  0x313,  0x301,  0x0,  0x399,  0x313,  0x342,  0x0,  0x399,  0x314,  0x0,  0x399,  0x314,  0x300,  0x0,  0x399,  0x314,  0x301,  0x0,  0x399,  0x314,  0x342,  0x0,  0x39a,  0x0,  0x39b,  0x0,  0x39c,  0x0,  0x39d,  0x0,  0x39e,  0x0,  0x39f,  0x0,  0x39f,  0x300,  0x0,  0x39f,  0x301,  0x0,  0x39f,  0x313,  0x0,  0x39f,  0x313,  0x300,  0x0,  0x39f,  0x313,  0x301,  0x0,  0x39f,  0x314,  0x0,  0x39f,  0x314,  0x300,  0x0,  0x39f,  0x314,  0x301,  0x0,  0x3a0,  0x0,  0x3a1,  0x0,  0x3a1,  0x314,  0x0,  0x3a3,  0x0,  0x3a4,  0x0,  0x3a5,  0x0,  0x3a5,  0x300,  0x0,  0x3a5,  0x301,  0x0,  0x3a5,  0x304,  0x0,  0x3a5,  0x306,  0x0,  0x3a5,  0x308,  0x0,  0x3a5,  0x314,  0x0,  0x3a5,  0x314,  0x300,  0x0,  0x3a5,  0x314,  0x301,  0x0,  0x3a5,  0x314,  0x342,  0x0,  0x3a6,  0x0,  0x3a7,  0x0,  0x3a8,  0x0,  0x3a9,  0x0,  0x3a9,  0x300,  0x0,  0x3a9,  0x301,  0x0,  0x3a9,  0x313,  0x0,  0x3a9,  0x313,  0x300,  0x0,  0x3a9,  0x313,  0x300,  0x345,  0x0,  0x3a9,  0x313,  0x301,  0x0,  0x3a9,  0x313,  0x301,  0x345,  0x0,  0x3a9,  0x313,  0x342,  0x0,  0x3a9,  0x313,  0x342,  0x345,  0x0,  0x3a9,  0x313,  0x345,  0x0,  0x3a9,  0x314,  0x0,  0x3a9,  0x314,  0x300,  0x0,  0x3a9,  0x314,  0x300,  0x345,  0x0,  0x3a9,  0x314,  0x301,  0x0,  0x3a9,  0x314,  0x301,  0x345,  0x0,  0x3a9,  0x314,  0x342,  0x0,  0x3a9,  0x314,  0x342,  0x345,  0x0,  0x3a9,  0x314,  0x345,  0x0,  0x3a9,  0x345,  0x0,  0x3b1,  0x0,  0x3b1,  0x300,  0x0,  0x3b1,  0x300,  0x345,  0x0,  0x3b1,  0x301,  0x0,  0x3b1,  0x301,  0x345,  0x0,  0x3b1,  0x304,  0x0,  0x3b1,  0x306,  0x0,  0x3b1,  0x313,  0x0,  0x3b1,  0x313,  0x300,  0x0,  0x3b1,  0x313,  0x300,  0x345,  0x0,  0x3b1,  0x313,  0x301,  0x0,  0x3b1,  0x313,  0x301,  0x345,  0x0,  0x3b1,  0x313,  0x342,  0x0,  0x3b1,  0x313,  0x342,  0x345,  0x0,  0x3b1,  0x313,  0x345,  0x0,  0x3b1,  0x314,  0x0,  0x3b1,  0x314,  0x300,  0x0,  0x3b1,  0x314,  0x300,  0x345,  0x0,  0x3b1,  0x314,  0x301,  0x0,  0x3b1,  0x314,  0x301,  0x345,  0x0,  0x3b1,  0x314,  0x342,  0x0,  0x3b1,  0x314,  0x342,  0x345,  0x0,  0x3b1,  0x314,  0x345,  0x0,  0x3b1,  0x342,  0x0,  0x3b1,  0x342,  0x345,  0x0,  0x3b1,  0x345,  0x0,  0x3b2,  0x0,  0x3b3,  0x0,  0x3b4,  0x0,  0x3b5,  0x0,  0x3b5,  0x300,  0x0,  0x3b5,  0x301,  0x0,  0x3b5,  0x313,  0x0,  0x3b5,  0x313,  0x300,  0x0,  0x3b5,  0x313,  0x301,  0x0,  0x3b5,  0x314,  0x0,  0x3b5,  0x314,  0x300,  0x0,  0x3b5,  0x314,  0x301,  0x0,  0x3b6,  0x0,  0x3b7,  0x0,  0x3b7,  0x300,  0x0,  0x3b7,  0x300,  0x345,  0x0,  0x3b7,  0x301,  0x0,  0x3b7,  0x301,  0x345,  0x0,  0x3b7,  0x313,  0x0,  0x3b7,  0x313,  0x300,  0x0,  0x3b7,  0x313,  0x300,  0x345,  0x0,  0x3b7,  0x313,  0x301,  0x0,  0x3b7,  0x313,  0x301,  0x345,  0x0,  0x3b7,  0x313,  0x342,  0x0,  0x3b7,  0x313,  0x342,  0x345,  0x0,  0x3b7,  0x313,  0x345,  0x0,  0x3b7,  0x314,  0x0,  0x3b7,  0x314,  0x300,  0x0,  0x3b7,  0x314,  0x300,  0x345,  0x0,  0x3b7,  0x314,  0x301,  0x0,  0x3b7,  0x314,  0x301,  0x345,  0x0,  0x3b7,  0x314,  0x342,  0x0,  0x3b7,  0x314,  0x342,  0x345,  0x0,  0x3b7,  0x314,  0x345,  0x0,  0x3b7,  0x342,  0x0,  0x3b7,  0x342,  0x345,  0x0,  0x3b7,  0x345,  0x0,  0x3b8,  0x0,  0x3b9,  0x0,  0x3b9,  0x300,  0x0,  0x3b9,  0x301,  0x0,  0x3b9,  0x304,  0x0,  0x3b9,  0x306,  0x0,  0x3b9,  0x308,  0x0,  0x3b9,  0x308,  0x300,  0x0,  0x3b9,  0x308,  0x301,  0x0,  0x3b9,  0x308,  0x342,  0x0,  0x3b9,  0x313,  0x0,  0x3b9,  0x313,  0x300,  0x0,  0x3b9,  0x313,  0x301,  0x0,  0x3b9,  0x313,  0x342,  0x0,  0x3b9,  0x314,  0x0,  0x3b9,  0x314,  0x300,  0x0,  0x3b9,  0x314,  0x301,  0x0,  0x3b9,  0x314,  0x342,  0x0,  0x3b9,  0x342,  0x0,  0x3ba,  0x0,  0x3bb,  0x0,  0x3bc,  0x0,  0x3bc,  0x41,  0x0,  0x3bc,  0x46,  0x0,  0x3bc,  0x56,  0x0,  0x3bc,  0x57,  0x0,  0x3bc,  0x67,  0x0,  0x3bc,  0x6c,  0x0,  0x3bc,  0x6d,  0x0,  0x3bc,  0x73,  0x0,  0x3bd,  0x0,  0x3be,  0x0,  0x3bf,  0x0,  0x3bf,  0x300,  0x0,  0x3bf,  0x301,  0x0,  0x3bf,  0x313,  0x0,  0x3bf,  0x313,  0x300,  0x0,  0x3bf,  0x313,  0x301,  0x0,  0x3bf,  0x314,  0x0,  0x3bf,  0x314,  0x300,  0x0,  0x3bf,  0x314,  0x301,  0x0,  0x3c0,  0x0,  0x3c1,  0x0,  0x3c1,  0x313,  0x0,  0x3c1,  0x314,  0x0,  0x3c2,  0x0,  0x3c3,  0x0,  0x3c4,  0x0,  0x3c5,  0x0,  0x3c5,  0x300,  0x0,  0x3c5,  0x301,  0x0,  0x3c5,  0x304,  0x0,  0x3c5,  0x306,  0x0,  0x3c5,  0x308,  0x0,  0x3c5,  0x308,  0x300,  0x0,  0x3c5,  0x308,  0x301,  0x0,  0x3c5,  0x308,  0x342,  0x0,  0x3c5,  0x313,  0x0,  0x3c5,  0x313,  0x300,  0x0,  0x3c5,  0x313,  0x301,  0x0,  0x3c5,  0x313,  0x342,  0x0,  0x3c5,  0x314,  0x0,  0x3c5,  0x314,  0x300,  0x0,  0x3c5,  0x314,  0x301,  0x0,  0x3c5,  0x314,  0x342,  0x0,  0x3c5,  0x342,  0x0,  0x3c6,  0x0,  0x3c7,  0x0,  0x3c8,  0x0,  0x3c9,  0x0,  0x3c9,  0x300,  0x0,  0x3c9,  0x300,  0x345,  0x0,  0x3c9,  0x301,  0x0,  0x3c9,  0x301,  0x345,  0x0,  0x3c9,  0x313,  0x0,  0x3c9,  0x313,  0x300,  0x0,  0x3c9,  0x313,  0x300,  0x345,  0x0,  0x3c9,  0x313,  0x301,  0x0,  0x3c9,  0x313,  0x301,  0x345,  0x0,  0x3c9,  0x313,  0x342,  0x0,  0x3c9,  0x313,  0x342,  0x345,  0x0,  0x3c9,  0x313,  0x345,  0x0,  0x3c9,  0x314,  0x0,  0x3c9,  0x314,  0x300,  0x0,  0x3c9,  0x314,  0x300,  0x345,  0x0,  0x3c9,  0x314,  0x301,  0x0,  0x3c9,  0x314,  0x301,  0x345,  0x0,  0x3c9,  0x314,  0x342,  0x0,  0x3c9,  0x314,  0x342,  0x345,  0x0,  0x3c9,  0x314,  0x345,  0x0,  0x3c9,  0x342,  0x0,  0x3c9,  0x342,  0x345,  0x0,  0x3c9,  0x345,  0x0,  0x3dc,  0x0,  0x3dd,  0x0,  0x406,  0x308,  0x0,  0x410,  0x306,  0x0,  0x410,  0x308,  0x0,  0x413,  0x301,  0x0,  0x415,  0x300,  0x0,  0x415,  0x306,  0x0,  0x415,  0x308,  0x0,  0x416,  0x306,  0x0,  0x416,  0x308,  0x0,  0x417,  0x308,  0x0,  0x418,  0x300,  0x0,  0x418,  0x304,  0x0,  0x418,  0x306,  0x0,  0x418,  0x308,  0x0,  0x41a,  0x301,  0x0,  0x41e,  0x308,  0x0,  0x423,  0x304,  0x0,  0x423,  0x306,  0x0,  0x423,  0x308,  0x0,  0x423,  0x30b,  0x0,  0x427,  0x308,  0x0,  0x42b,  0x308,  0x0,  0x42d,  0x308,  0x0,  0x430,  0x306,  0x0,  0x430,  0x308,  0x0,  0x433,  0x301,  0x0,  0x435,  0x300,  0x0,  0x435,  0x306,  0x0,  0x435,  0x308,  0x0,  0x436,  0x306,  0x0,  0x436,  0x308,  0x0,  0x437,  0x308,  0x0,  0x438,  0x300,  0x0,  0x438,  0x304,  0x0,  0x438,  0x306,  0x0,  0x438,  0x308,  0x0,  0x43a,  0x301,  0x0,  0x43d,  0x0,  0x43e,  0x308,  0x0,  0x443,  0x304,  0x0,  0x443,  0x306,  0x0,  0x443,  0x308,  0x0,  0x443,  0x30b,  0x0,  0x447,  0x308,  0x0,  0x44b,  0x308,  0x0,  0x44d,  0x308,  0x0,  0x456,  0x308,  0x0,  0x474,  0x30f,  0x0,  0x475,  0x30f,  0x0,  0x4d8,  0x308,  0x0,  0x4d9,  0x308,  0x0,  0x4e8,  0x308,  0x0,  0x4e9,  0x308,  0x0,  0x565,  0x582,  0x0,  0x574,  0x565,  0x0,  0x574,  0x56b,  0x0,  0x574,  0x56d,  0x0,  0x574,  0x576,  0x0,  0x57e,  0x576,  0x0,  0x5d0,  0x0,  0x5d0,  0x5b7,  0x0,  0x5d0,  0x5b8,  0x0,  0x5d0,  0x5bc,  0x0,  0x5d0,  0x5dc,  0x0,  0x5d1,  0x0,  0x5d1,  0x5bc,  0x0,  0x5d1,  0x5bf,  0x0,  0x5d2,  0x0,  0x5d2,  0x5bc,  0x0,  0x5d3,  0x0,  0x5d3,  0x5bc,  0x0,  0x5d4,  0x0,  0x5d4,  0x5bc,  0x0,  0x5d5,  0x5b9,  0x0,  0x5d5,  0x5bc,  0x0,  0x5d6,  0x5bc,  0x0,  0x5d8,  0x5bc,  0x0,  0x5d9,  0x5b4,  0x0,  0x5d9,  0x5bc,  0x0,  0x5da,  0x5bc,  0x0,  0x5db,  0x0,  0x5db,  0x5bc,  0x0,  0x5db,  0x5bf,  0x0,  0x5dc,  0x0,  0x5dc,  0x5bc,  0x0,  0x5dd,  0x0,  0x5de,  0x5bc,  0x0,  0x5e0,  0x5bc,  0x0,  0x5e1,  0x5bc,  0x0,  0x5e2,  0x0,  0x5e3,  0x5bc,  0x0,  0x5e4,  0x5bc,  0x0,  0x5e4,  0x5bf,  0x0,  0x5e6,  0x5bc,  0x0,  0x5e7,  0x5bc,  0x0,  0x5e8,  0x0,  0x5e8,  0x5bc,  0x0,  0x5e9,  0x5bc,  0x0,  0x5e9,  0x5bc,  0x5c1,  0x0,  0x5e9,  0x5bc,  0x5c2,  0x0,  0x5e9,  0x5c1,  0x0,  0x5e9,  0x5c2,  0x0,  0x5ea,  0x0,  0x5ea,  0x5bc,  0x0,  0x5f2,  0x5b7,  0x0,  0x621,  0x0,  0x627,  0x0,  0x627,  0x643,  0x628,  0x631,  0x0,  0x627,  0x644,  0x644,  0x647,  0x0,  0x627,  0x64b,  0x0,  0x627,  0x653,  0x0,  0x627,  0x654,  0x0,  0x627,  0x655,  0x0,  0x627,  0x674,  0x0,  0x628,  0x0,  0x628,  0x62c,  0x0,  0x628,  0x62d,  0x0,  0x628,  0x62d,  0x64a,  0x0,  0x628,  0x62e,  0x0,  0x628,  0x62e,  0x64a,  0x0,  0x628,  0x631,  0x0,  0x628,  0x632,  0x0,  0x628,  0x645,  0x0,  0x628,  0x646,  0x0,  0x628,  0x647,  0x0,  0x628,  0x649,  0x0,  0x628,  0x64a,  0x0,  0x629,  0x0,  0x62a,  0x0,  0x62a,  0x62c,  0x0,  0x62a,  0x62c,  0x645,  0x0,  0x62a,  0x62c,  0x649,  0x0,  0x62a,  0x62c,  0x64a,  0x0,  0x62a,  0x62d,  0x0,  0x62a,  0x62d,  0x62c,  0x0,  0x62a,  0x62d,  0x645,  0x0,  0x62a,  0x62e,  0x0,  0x62a,  0x62e,  0x645,  0x0,  0x62a,  0x62e,  0x649,  0x0,  0x62a,  0x62e,  0x64a,  0x0,  0x62a,  0x631,  0x0,  0x62a,  0x632,  0x0,  0x62a,  0x645,  0x0,  0x62a,  0x645,  0x62c,  0x0,  0x62a,  0x645,  0x62d,  0x0,  0x62a,  0x645,  0x62e,  0x0,  0x62a,  0x645,  0x649,  0x0,  0x62a,  0x645,  0x64a,  0x0,  0x62a,  0x646,  0x0,  0x62a,  0x647,  0x0,  0x62a,  0x649,  0x0,  0x62a,  0x64a,  0x0,  0x62b,  0x0,  0x62b,  0x62c,  0x0,  0x62b,  0x631,  0x0,  0x62b,  0x632,  0x0,  0x62b,  0x645,  0x0,  0x62b,  0x646,  0x0,  0x62b,  0x647,  0x0,  0x62b,  0x649,  0x0,  0x62b,  0x64a,  0x0,  0x62c,  0x0,  0x62c,  0x62d,  0x0,  0x62c,  0x62d,  0x649,  0x0,  0x62c,  0x62d,  0x64a,  0x0,  0x62c,  0x644,  0x20,  0x62c,  0x644,  0x627,  0x644,  0x647,  0x0,  0x62c,  0x645,  0x0,  0x62c,  0x645,  0x62d,  0x0,  0x62c,  0x645,  0x649,  0x0,  0x62c,  0x645,  0x64a,  0x0,  0x62c,  0x649,  0x0,  0x62c,  0x64a,  0x0,  0x62d,  0x0,  0x62d,  0x62c,  0x0,  0x62d,  0x62c,  0x64a,  0x0,  0x62d,  0x645,  0x0,  0x62d,  0x645,  0x649,  0x0,  0x62d,  0x645,  0x64a,  0x0,  0x62d,  0x649,  0x0,  0x62d,  0x64a,  0x0,  0x62e,  0x0,  0x62e,  0x62c,  0x0,  0x62e,  0x62d,  0x0,  0x62e,  0x645,  0x0,  0x62e,  0x649,  0x0,  0x62e,  0x64a,  0x0,  0x62f,  0x0,  0x630,  0x0,  0x630,  0x670,  0x0,  0x631,  0x0,  0x631,  0x633,  0x648,  0x644,  0x0,  0x631,  0x670,  0x0,  0x631,  0x6cc,  0x627,  0x644,  0x0,  0x632,  0x0,  0x633,  0x0,  0x633,  0x62c,  0x0,  0x633,  0x62c,  0x62d,  0x0,  0x633,  0x62c,  0x649,  0x0,  0x633,  0x62d,  0x0,  0x633,  0x62d,  0x62c,  0x0,  0x633,  0x62e,  0x0,  0x633,  0x62e,  0x649,  0x0,  0x633,  0x62e,  0x64a,  0x0,  0x633,  0x631,  0x0,  0x633,  0x645,  0x0,  0x633,  0x645,  0x62c,  0x0,  0x633,  0x645,  0x62d,  0x0,  0x633,  0x645,  0x645,  0x0,  0x633,  0x647,  0x0,  0x633,  0x649,  0x0,  0x633,  0x64a,  0x0,  0x634,  0x0,  0x634,  0x62c,  0x0,  0x634,  0x62c,  0x64a,  0x0,  0x634,  0x62d,  0x0,  0x634,  0x62d,  0x645,  0x0,  0x634,  0x62d,  0x64a,  0x0,  0x634,  0x62e,  0x0,  0x634,  0x631,  0x0,  0x634,  0x645,  0x0,  0x634,  0x645,  0x62e,  0x0,  0x634,  0x645,  0x645,  0x0,  0x634,  0x647,  0x0,  0x634,  0x649,  0x0,  0x634,  0x64a,  0x0,  0x635,  0x0,  0x635,  0x62d,  0x0,  0x635,  0x62d,  0x62d,  0x0,  0x635,  0x62d,  0x64a,  0x0,  0x635,  0x62e,  0x0,  0x635,  0x631,  0x0,  0x635,  0x644,  0x639,  0x645,  0x0,  0x635,  0x644,  0x649,  0x0,  0x635,  0x644,  0x649,  0x20,  0x627,  0x644,  0x644,  0x647,  0x20,  0x639,  0x644,  0x64a,  0x647,  0x20,  0x648,  0x633,  0x644,  0x645,  0x0,  0x635,  0x644,  0x6d2,  0x0,  0x635,  0x645,  0x0,  0x635,  0x645,  0x645,  0x0,  0x635,  0x649,  0x0,  0x635,  0x64a,  0x0,  0x636,  0x0,  0x636,  0x62c,  0x0,  0x636,  0x62d,  0x0,  0x636,  0x62d,  0x649,  0x0,  0x636,  0x62d,  0x64a,  0x0,  0x636,  0x62e,  0x0,  0x636,  0x62e,  0x645,  0x0,  0x636,  0x631,  0x0,  0x636,  0x645,  0x0,  0x636,  0x649,  0x0,  0x636,  0x64a,  0x0,  0x637,  0x0,  0x637,  0x62d,  0x0,  0x637,  0x645,  0x0,  0x637,  0x645,  0x62d,  0x0,  0x637,  0x645,  0x645,  0x0,  0x637,  0x645,  0x64a,  0x0,  0x637,  0x649,  0x0,  0x637,  0x64a,  0x0,  0x638,  0x0,  0x638,  0x645,  0x0,  0x639,  0x0,  0x639,  0x62c,  0x0,  0x639,  0x62c,  0x645,  0x0,  0x639,  0x644,  0x64a,  0x647,  0x0,  0x639,  0x645,  0x0,  0x639,  0x645,  0x645,  0x0,  0x639,  0x645,  0x649,  0x0,  0x639,  0x645,  0x64a,  0x0,  0x639,  0x649,  0x0,  0x639,  0x64a,  0x0,  0x63a,  0x0,  0x63a,  0x62c,  0x0,  0x63a,  0x645,  0x0,  0x63a,  0x645,  0x645,  0x0,  0x63a,  0x645,  0x649,  0x0,  0x63a,  0x645,  0x64a,  0x0,  0x63a,  0x649,  0x0,  0x63a,  0x64a,  0x0,  0x640,  0x64b,  0x0,  0x640,  0x64e,  0x0,  0x640,  0x64e,  0x651,  0x0,  0x640,  0x64f,  0x0,  0x640,  0x64f,  0x651,  0x0,  0x640,  0x650,  0x0,  0x640,  0x650,  0x651,  0x0,  0x640,  0x651,  0x0,  0x640,  0x652,  0x0,  0x641,  0x0,  0x641,  0x62c,  0x0,  0x641,  0x62d,  0x0,  0x641,  0x62e,  0x0,  0x641,  0x62e,  0x645,  0x0,  0x641,  0x645,  0x0,  0x641,  0x645,  0x64a,  0x0,  0x641,  0x649,  0x0,  0x641,  0x64a,  0x0,  0x642,  0x0,  0x642,  0x62d,  0x0,  0x642,  0x644,  0x6d2,  0x0,  0x642,  0x645,  0x0,  0x642,  0x645,  0x62d,  0x0,  0x642,  0x645,  0x645,  0x0,  0x642,  0x645,  0x64a,  0x0,  0x642,  0x649,  0x0,  0x642,  0x64a,  0x0,  0x643,  0x0,  0x643,  0x627,  0x0,  0x643,  0x62c,  0x0,  0x643,  0x62d,  0x0,  0x643,  0x62e,  0x0,  0x643,  0x644,  0x0,  0x643,  0x645,  0x0,  0x643,  0x645,  0x645,  0x0,  0x643,  0x645,  0x64a,  0x0,  0x643,  0x649,  0x0,  0x643,  0x64a,  0x0,  0x644,  0x0,  0x644,  0x627,  0x0,  0x644,  0x627,  0x653,  0x0,  0x644,  0x627,  0x654,  0x0,  0x644,  0x627,  0x655,  0x0,  0x644,  0x62c,  0x0,  0x644,  0x62c,  0x62c,  0x0,  0x644,  0x62c,  0x645,  0x0,  0x644,  0x62c,  0x64a,  0x0,  0x644,  0x62d,  0x0,  0x644,  0x62d,  0x645,  0x0,  0x644,  0x62d,  0x649,  0x0,  0x644,  0x62d,  0x64a,  0x0,  0x644,  0x62e,  0x0,  0x644,  0x62e,  0x645,  0x0,  0x644,  0x645,  0x0,  0x644,  0x645,  0x62d,  0x0,  0x644,  0x645,  0x64a,  0x0,  0x644,  0x647,  0x0,  0x644,  0x649,  0x0,  0x644,  0x64a,  0x0,  0x645,  0x0,  0x645,  0x627,  0x0,  0x645,  0x62c,  0x0,  0x645,  0x62c,  0x62d,  0x0,  0x645,  0x62c,  0x62e,  0x0,  0x645,  0x62c,  0x645,  0x0,  0x645,  0x62c,  0x64a,  0x0,  0x645,  0x62d,  0x0,  0x645,  0x62d,  0x62c,  0x0,  0x645,  0x62d,  0x645,  0x0,  0x645,  0x62d,  0x645,  0x62f,  0x0,  0x645,  0x62d,  0x64a,  0x0,  0x645,  0x62e,  0x0,  0x645,  0x62e,  0x62c,  0x0,  0x645,  0x62e,  0x645,  0x0,  0x645,  0x62e,  0x64a,  0x0,  0x645,  0x645,  0x0,  0x645,  0x645,  0x64a,  0x0,  0x645,  0x649,  0x0,  0x645,  0x64a,  0x0,  0x646,  0x0,  0x646,  0x62c,  0x0,  0x646,  0x62c,  0x62d,  0x0,  0x646,  0x62c,  0x645,  0x0,  0x646,  0x62c,  0x649,  0x0,  0x646,  0x62c,  0x64a,  0x0,  0x646,  0x62d,  0x0,  0x646,  0x62d,  0x645,  0x0,  0x646,  0x62d,  0x649,  0x0,  0x646,  0x62d,  0x64a,  0x0,  0x646,  0x62e,  0x0,  0x646,  0x631,  0x0,  0x646,  0x632,  0x0,  0x646,  0x645,  0x0,  0x646,  0x645,  0x649,  0x0,  0x646,  0x645,  0x64a,  0x0,  0x646,  0x646,  0x0,  0x646,  0x647,  0x0,  0x646,  0x649,  0x0,  0x646,  0x64a,  0x0,  0x647,  0x0,  0x647,  0x62c,  0x0,  0x647,  0x645,  0x0,  0x647,  0x645,  0x62c,  0x0,  0x647,  0x645,  0x645,  0x0,  0x647,  0x649,  0x0,  0x647,  0x64a,  0x0,  0x647,  0x670,  0x0,  0x648,  0x0,  0x648,  0x633,  0x644,  0x645,  0x0,  0x648,  0x654,  0x0,  0x648,  0x674,  0x0,  0x649,  0x0,  0x649,  0x670,  0x0,  0x64a,  0x0,  0x64a,  0x62c,  0x0,  0x64a,  0x62c,  0x64a,  0x0,  0x64a,  0x62d,  0x0,  0x64a,  0x62d,  0x64a,  0x0,  0x64a,  0x62e,  0x0,  0x64a,  0x631,  0x0,  0x64a,  0x632,  0x0,  0x64a,  0x645,  0x0,  0x64a,  0x645,  0x645,  0x0,  0x64a,  0x645,  0x64a,  0x0,  0x64a,  0x646,  0x0,  0x64a,  0x647,  0x0,  0x64a,  0x649,  0x0,  0x64a,  0x64a,  0x0,  0x64a,  0x654,  0x0,  0x64a,  0x654,  0x627,  0x0,  0x64a,  0x654,  0x62c,  0x0,  0x64a,  0x654,  0x62d,  0x0,  0x64a,  0x654,  0x62e,  0x0,  0x64a,  0x654,  0x631,  0x0,  0x64a,  0x654,  0x632,  0x0,  0x64a,  0x654,  0x645,  0x0,  0x64a,  0x654,  0x646,  0x0,  0x64a,  0x654,  0x647,  0x0,  0x64a,  0x654,  0x648,  0x0,  0x64a,  0x654,  0x649,  0x0,  0x64a,  0x654,  0x64a,  0x0,  0x64a,  0x654,  0x6c6,  0x0,  0x64a,  0x654,  0x6c7,  0x0,  0x64a,  0x654,  0x6c8,  0x0,  0x64a,  0x654,  0x6d0,  0x0,  0x64a,  0x654,  0x6d5,  0x0,  0x64a,  0x674,  0x0,  0x66e,  0x0,  0x66f,  0x0,  0x671,  0x0,  0x679,  0x0,  0x67a,  0x0,  0x67b,  0x0,  0x67e,  0x0,  0x67f,  0x0,  0x680,  0x0,  0x683,  0x0,  0x684,  0x0,  0x686,  0x0,  0x687,  0x0,  0x688,  0x0,  0x68c,  0x0,  0x68d,  0x0,  0x68e,  0x0,  0x691,  0x0,  0x698,  0x0,  0x6a1,  0x0,  0x6a4,  0x0,  0x6a6,  0x0,  0x6a9,  0x0,  0x6ad,  0x0,  0x6af,  0x0,  0x6b1,  0x0,  0x6b3,  0x0,  0x6ba,  0x0,  0x6bb,  0x0,  0x6be,  0x0,  0x6c1,  0x0,  0x6c1,  0x654,  0x0,  0x6c5,  0x0,  0x6c6,  0x0,  0x6c7,  0x0,  0x6c7,  0x674,  0x0,  0x6c8,  0x0,  0x6c9,  0x0,  0x6cb,  0x0,  0x6cc,  0x0,  0x6d0,  0x0,  0x6d2,  0x0,  0x6d2,  0x654,  0x0,  0x6d5,  0x654,  0x0,  0x915,  0x93c,  0x0,  0x916,  0x93c,  0x0,  0x917,  0x93c,  0x0,  0x91c,  0x93c,  0x0,  0x921,  0x93c,  0x0,  0x922,  0x93c,  0x0,  0x928,  0x93c,  0x0,  0x92b,  0x93c,  0x0,  0x92f,  0x93c,  0x0,  0x930,  0x93c,  0x0,  0x933,  0x93c,  0x0,  0x9a1,  0x9bc,  0x0,  0x9a2,  0x9bc,  0x0,  0x9af,  0x9bc,  0x0,  0x9c7,  0x9be,  0x0,  0x9c7,  0x9d7,  0x0,  0xa16,  0xa3c,  0x0,  0xa17,  0xa3c,  0x0,  0xa1c,  0xa3c,  0x0,  0xa2b,  0xa3c,  0x0,  0xa32,  0xa3c,  0x0,  0xa38,  0xa3c,  0x0,  0xb21,  0xb3c,  0x0,  0xb22,  0xb3c,  0x0,  0xb47,  0xb3e,  0x0,  0xb47,  0xb56,  0x0,  0xb47,  0xb57,  0x0,  0xb92,  0xbd7,  0x0,  0xbc6,  0xbbe,  0x0,  0xbc6,  0xbd7,  0x0,  0xbc7,  0xbbe,  0x0,  0xc46,  0xc56,  0x0,  0xcbf,  0xcd5,  0x0,  0xcc6,  0xcc2,  0x0,  0xcc6,  0xcc2,  0xcd5,  0x0,  0xcc6,  0xcd5,  0x0,  0xcc6,  0xcd6,  0x0,  0xd46,  0xd3e,  0x0,  0xd46,  0xd57,  0x0,  0xd47,  0xd3e,  0x0,  0xdd9,  0xdca,  0x0,  0xdd9,  0xdcf,  0x0,  0xdd9,  0xdcf,  0xdca,  0x0,  0xdd9,  0xddf,  0x0,  0xe4d,  0xe32,  0x0,  0xeab,  0xe99,  0x0,  0xeab,  0xea1,  0x0,  0xecd,  0xeb2,  0x0,  0xf0b,  0x0,  0xf40,  0xfb5,  0x0,  0xf42,  0xfb7,  0x0,  0xf4c,  0xfb7,  0x0,  0xf51,  0xfb7,  0x0,  0xf56,  0xfb7,  0x0,  0xf5b,  0xfb7,  0x0,  0xf71,  0xf72,  0x0,  0xf71,  0xf74,  0x0,  0xf71,  0xf80,  0x0,  0xf90,  0xfb5,  0x0,  0xf92,  0xfb7,  0x0,  0xf9c,  0xfb7,  0x0,  0xfa1,  0xfb7,  0x0,  0xfa6,  0xfb7,  0x0,  0xfab,  0xfb7,  0x0,  0xfb2,  0xf71,  0xf80,  0x0,  0xfb2,  0xf80,  0x0,  0xfb3,  0xf71,  0xf80,  0x0,  0xfb3,  0xf80,  0x0,  0x1025,  0x102e,  0x0,  0x10dc,  0x0,  0x1100,  0x0,  0x1100,  0x1161,  0x0,  0x1101,  0x0,  0x1102,  0x0,  0x1102,  0x1161,  0x0,  0x1103,  0x0,  0x1103,  0x1161,  0x0,  0x1104,  0x0,  0x1105,  0x0,  0x1105,  0x1161,  0x0,  0x1106,  0x0,  0x1106,  0x1161,  0x0,  0x1107,  0x0,  0x1107,  0x1161,  0x0,  0x1108,  0x0,  0x1109,  0x0,  0x1109,  0x1161,  0x0,  0x110a,  0x0,  0x110b,  0x0,  0x110b,  0x1161,  0x0,  0x110b,  0x116e,  0x0,  0x110c,  0x0,  0x110c,  0x1161,  0x0,  0x110c,  0x116e,  0x110b,  0x1174,  0x0,  0x110d,  0x0,  0x110e,  0x0,  0x110e,  0x1161,  0x0,  0x110e,  0x1161,  0x11b7,  0x1100,  0x1169,  0x0,  0x110f,  0x0,  0x110f,  0x1161,  0x0,  0x1110,  0x0,  0x1110,  0x1161,  0x0,  0x1111,  0x0,  0x1111,  0x1161,  0x0,  0x1112,  0x0,  0x1112,  0x1161,  0x0,  0x1114,  0x0,  0x1115,  0x0,  0x111a,  0x0,  0x111c,  0x0,  0x111d,  0x0,  0x111e,  0x0,  0x1120,  0x0,  0x1121,  0x0,  0x1122,  0x0,  0x1123,  0x0,  0x1127,  0x0,  0x1129,  0x0,  0x112b,  0x0,  0x112c,  0x0,  0x112d,  0x0,  0x112e,  0x0,  0x112f,  0x0,  0x1132,  0x0,  0x1136,  0x0,  0x1140,  0x0,  0x1147,  0x0,  0x114c,  0x0,  0x1157,  0x0,  0x1158,  0x0,  0x1159,  0x0,  0x1160,  0x0,  0x1161,  0x0,  0x1162,  0x0,  0x1163,  0x0,  0x1164,  0x0,  0x1165,  0x0,  0x1166,  0x0,  0x1167,  0x0,  0x1168,  0x0,  0x1169,  0x0,  0x116a,  0x0,  0x116b,  0x0,  0x116c,  0x0,  0x116d,  0x0,  0x116e,  0x0,  0x116f,  0x0,  0x1170,  0x0,  0x1171,  0x0,  0x1172,  0x0,  0x1173,  0x0,  0x1174,  0x0,  0x1175,  0x0,  0x1184,  0x0,  0x1185,  0x0,  0x1188,  0x0,  0x1191,  0x0,  0x1192,  0x0,  0x1194,  0x0,  0x119e,  0x0,  0x11a1,  0x0,  0x11aa,  0x0,  0x11ac,  0x0,  0x11ad,  0x0,  0x11b0,  0x0,  0x11b1,  0x0,  0x11b2,  0x0,  0x11b3,  0x0,  0x11b4,  0x0,  0x11b5,  0x0,  0x11c7,  0x0,  0x11c8,  0x0,  0x11cc,  0x0,  0x11ce,  0x0,  0x11d3,  0x0,  0x11d7,  0x0,  0x11d9,  0x0,  0x11dd,  0x0,  0x11df,  0x0,  0x11f1,  0x0,  0x11f2,  0x0,  0x1b05,  0x1b35,  0x0,  0x1b07,  0x1b35,  0x0,  0x1b09,  0x1b35,  0x0,  0x1b0b,  0x1b35,  0x0,  0x1b0d,  0x1b35,  0x0,  0x1b11,  0x1b35,  0x0,  0x1b3a,  0x1b35,  0x0,  0x1b3c,  0x1b35,  0x0,  0x1b3e,  0x1b35,  0x0,  0x1b3f,  0x1b35,  0x0,  0x1b42,  0x1b35,  0x0,  0x1d02,  0x0,  0x1d16,  0x0,  0x1d17,  0x0,  0x1d1c,  0x0,  0x1d1d,  0x0,  0x1d25,  0x0,  0x1d7b,  0x0,  0x1d85,  0x0,  0x2010,  0x0,  0x2013,  0x0,  0x2014,  0x0,  0x2032,  0x2032,  0x0,  0x2032,  0x2032,  0x2032,  0x0,  0x2032,  0x2032,  0x2032,  0x2032,  0x0,  0x2035,  0x2035,  0x0,  0x2035,  0x2035,  0x2035,  0x0,  0x20a9,  0x0,  0x2190,  0x0,  0x2190,  0x338,  0x0,  0x2191,  0x0,  0x2192,  0x0,  0x2192,  0x338,  0x0,  0x2193,  0x0,  0x2194,  0x338,  0x0,  0x21d0,  0x338,  0x0,  0x21d2,  0x338,  0x0,  0x21d4,  0x338,  0x0,  0x2202,  0x0,  0x2203,  0x338,  0x0,  0x2207,  0x0,  0x2208,  0x338,  0x0,  0x220b,  0x338,  0x0,  0x2211,  0x0,  0x2212,  0x0,  0x2223,  0x338,  0x0,  0x2225,  0x338,  0x0,  0x222b,  0x222b,  0x0,  0x222b,  0x222b,  0x222b,  0x0,  0x222b,  0x222b,  0x222b,  0x222b,  0x0,  0x222e,  0x222e,  0x0,  0x222e,  0x222e,  0x222e,  0x0,  0x223c,  0x338,  0x0,  0x2243,  0x338,  0x0,  0x2245,  0x338,  0x0,  0x2248,  0x338,  0x0,  0x224d,  0x338,  0x0,  0x2261,  0x338,  0x0,  0x2264,  0x338,  0x0,  0x2265,  0x338,  0x0,  0x2272,  0x338,  0x0,  0x2273,  0x338,  0x0,  0x2276,  0x338,  0x0,  0x2277,  0x338,  0x0,  0x227a,  0x338,  0x0,  0x227b,  0x338,  0x0,  0x227c,  0x338,  0x0,  0x227d,  0x338,  0x0,  0x2282,  0x338,  0x0,  0x2283,  0x338,  0x0,  0x2286,  0x338,  0x0,  0x2287,  0x338,  0x0,  0x2291,  0x338,  0x0,  0x2292,  0x338,  0x0,  0x22a2,  0x338,  0x0,  0x22a8,  0x338,  0x0,  0x22a9,  0x338,  0x0,  0x22ab,  0x338,  0x0,  0x22b2,  0x338,  0x0,  0x22b3,  0x338,  0x0,  0x22b4,  0x338,  0x0,  0x22b5,  0x338,  0x0,  0x2502,  0x0,  0x25a0,  0x0,  0x25cb,  0x0,  0x2985,  0x0,  0x2986,  0x0,  0x2add,  0x338,  0x0,  0x2d61,  0x0,  0x3001,  0x0,  0x3002,  0x0,  0x3008,  0x0,  0x3009,  0x0,  0x300a,  0x0,  0x300b,  0x0,  0x300c,  0x0,  0x300d,  0x0,  0x300e,  0x0,  0x300f,  0x0,  0x3010,  0x0,  0x3011,  0x0,  0x3012,  0x0,  0x3014,  0x0,  0x3014,  0x53,  0x3015,  0x0,  0x3014,  0x4e09,  0x3015,  0x0,  0x3014,  0x4e8c,  0x3015,  0x0,  0x3014,  0x52dd,  0x3015,  0x0,  0x3014,  0x5b89,  0x3015,  0x0,  0x3014,  0x6253,  0x3015,  0x0,  0x3014,  0x6557,  0x3015,  0x0,  0x3014,  0x672c,  0x3015,  0x0,  0x3014,  0x70b9,  0x3015,  0x0,  0x3014,  0x76d7,  0x3015,  0x0,  0x3015,  0x0,  0x3016,  0x0,  0x3017,  0x0,  0x3046,  0x3099,  0x0,  0x304b,  0x3099,  0x0,  0x304d,  0x3099,  0x0,  0x304f,  0x3099,  0x0,  0x3051,  0x3099,  0x0,  0x3053,  0x3099,  0x0,  0x3055,  0x3099,  0x0,  0x3057,  0x3099,  0x0,  0x3059,  0x3099,  0x0,  0x305b,  0x3099,  0x0,  0x305d,  0x3099,  0x0,  0x305f,  0x3099,  0x0,  0x3061,  0x3099,  0x0,  0x3064,  0x3099,  0x0,  0x3066,  0x3099,  0x0,  0x3068,  0x3099,  0x0,  0x306f,  0x3099,  0x0,  0x306f,  0x309a,  0x0,  0x3072,  0x3099,  0x0,  0x3072,  0x309a,  0x0,  0x3075,  0x3099,  0x0,  0x3075,  0x309a,  0x0,  0x3078,  0x3099,  0x0,  0x3078,  0x309a,  0x0,  0x307b,  0x304b,  0x0,  0x307b,  0x3099,  0x0,  0x307b,  0x309a,  0x0,  0x3088,  0x308a,  0x0,  0x3099,  0x0,  0x309a,  0x0,  0x309d,  0x3099,  0x0,  0x30a1,  0x0,  0x30a2,  0x0,  0x30a2,  0x30cf,  0x309a,  0x30fc,  0x30c8,  0x0,  0x30a2,  0x30eb,  0x30d5,  0x30a1,  0x0,  0x30a2,  0x30f3,  0x30d8,  0x309a,  0x30a2,  0x0,  0x30a2,  0x30fc,  0x30eb,  0x0,  0x30a3,  0x0,  0x30a4,  0x0,  0x30a4,  0x30cb,  0x30f3,  0x30af,  0x3099,  0x0,  0x30a4,  0x30f3,  0x30c1,  0x0,  0x30a5,  0x0,  0x30a6,  0x0,  0x30a6,  0x3099,  0x0,  0x30a6,  0x30a9,  0x30f3,  0x0,  0x30a7,  0x0,  0x30a8,  0x0,  0x30a8,  0x30b9,  0x30af,  0x30fc,  0x30c8,  0x3099,  0x0,  0x30a8,  0x30fc,  0x30ab,  0x30fc,  0x0,  0x30a9,  0x0,  0x30aa,  0x0,  0x30aa,  0x30f3,  0x30b9,  0x0,  0x30aa,  0x30fc,  0x30e0,  0x0,  0x30ab,  0x0,  0x30ab,  0x3099,  0x0,  0x30ab,  0x3099,  0x30ed,  0x30f3,  0x0,  0x30ab,  0x3099,  0x30f3,  0x30de,  0x0,  0x30ab,  0x30a4,  0x30ea,  0x0,  0x30ab,  0x30e9,  0x30c3,  0x30c8,  0x0,  0x30ab,  0x30ed,  0x30ea,  0x30fc,  0x0,  0x30ad,  0x0,  0x30ad,  0x3099,  0x0,  0x30ad,  0x3099,  0x30ab,  0x3099,  0x0,  0x30ad,  0x3099,  0x30cb,  0x30fc,  0x0,  0x30ad,  0x3099,  0x30eb,  0x30bf,  0x3099,  0x30fc,  0x0,  0x30ad,  0x30e5,  0x30ea,  0x30fc,  0x0,  0x30ad,  0x30ed,  0x0,  0x30ad,  0x30ed,  0x30af,  0x3099,  0x30e9,  0x30e0,  0x0,  0x30ad,  0x30ed,  0x30e1,  0x30fc,  0x30c8,  0x30eb,  0x0,  0x30ad,  0x30ed,  0x30ef,  0x30c3,  0x30c8,  0x0,  0x30af,  0x0,  0x30af,  0x3099,  0x0,  0x30af,  0x3099,  0x30e9,  0x30e0,  0x0,  0x30af,  0x3099,  0x30e9,  0x30e0,  0x30c8,  0x30f3,  0x0,  0x30af,  0x30eb,  0x30bb,  0x3099,  0x30a4,  0x30ed,  0x0,  0x30af,  0x30ed,  0x30fc,  0x30cd,  0x0,  0x30b1,  0x0,  0x30b1,  0x3099,  0x0,  0x30b1,  0x30fc,  0x30b9,  0x0,  0x30b3,  0x0,  0x30b3,  0x3099,  0x0,  0x30b3,  0x30b3,  0x0,  0x30b3,  0x30c8,  0x0,  0x30b3,  0x30eb,  0x30ca,  0x0,  0x30b3,  0x30fc,  0x30db,  0x309a,  0x0,  0x30b5,  0x0,  0x30b5,  0x3099,  0x0,  0x30b5,  0x30a4,  0x30af,  0x30eb,  0x0,  0x30b5,  0x30f3,  0x30c1,  0x30fc,  0x30e0,  0x0,  0x30b7,  0x0,  0x30b7,  0x3099,  0x0,  0x30b7,  0x30ea,  0x30f3,  0x30af,  0x3099,  0x0,  0x30b9,  0x0,  0x30b9,  0x3099,  0x0,  0x30bb,  0x0,  0x30bb,  0x3099,  0x0,  0x30bb,  0x30f3,  0x30c1,  0x0,  0x30bb,  0x30f3,  0x30c8,  0x0,  0x30bd,  0x0,  0x30bd,  0x3099,  0x0,  0x30bf,  0x0,  0x30bf,  0x3099,  0x0,  0x30bf,  0x3099,  0x30fc,  0x30b9,  0x0,  0x30c1,  0x0,  0x30c1,  0x3099,  0x0,  0x30c3,  0x0,  0x30c4,  0x0,  0x30c4,  0x3099,  0x0,  0x30c6,  0x0,  0x30c6,  0x3099,  0x0,  0x30c6,  0x3099,  0x30b7,  0x0,  0x30c8,  0x0,  0x30c8,  0x3099,  0x0,  0x30c8,  0x3099,  0x30eb,  0x0,  0x30c8,  0x30f3,  0x0,  0x30ca,  0x0,  0x30ca,  0x30ce,  0x0,  0x30cb,  0x0,  0x30cc,  0x0,  0x30cd,  0x0,  0x30ce,  0x0,  0x30ce,  0x30c3,  0x30c8,  0x0,  0x30cf,  0x0,  0x30cf,  0x3099,  0x0,  0x30cf,  0x3099,  0x30fc,  0x30ec,  0x30eb,  0x0,  0x30cf,  0x309a,  0x0,  0x30cf,  0x309a,  0x30fc,  0x30bb,  0x30f3,  0x30c8,  0x0,  0x30cf,  0x309a,  0x30fc,  0x30c4,  0x0,  0x30cf,  0x30a4,  0x30c4,  0x0,  0x30d2,  0x0,  0x30d2,  0x3099,  0x0,  0x30d2,  0x3099,  0x30eb,  0x0,  0x30d2,  0x309a,  0x0,  0x30d2,  0x309a,  0x30a2,  0x30b9,  0x30c8,  0x30eb,  0x0,  0x30d2,  0x309a,  0x30af,  0x30eb,  0x0,  0x30d2,  0x309a,  0x30b3,  0x0,  0x30d5,  0x0,  0x30d5,  0x3099,  0x0,  0x30d5,  0x3099,  0x30c3,  0x30b7,  0x30a7,  0x30eb,  0x0,  0x30d5,  0x309a,  0x0,  0x30d5,  0x30a1,  0x30e9,  0x30c3,  0x30c8,  0x3099,  0x0,  0x30d5,  0x30a3,  0x30fc,  0x30c8,  0x0,  0x30d5,  0x30e9,  0x30f3,  0x0,  0x30d8,  0x0,  0x30d8,  0x3099,  0x0,  0x30d8,  0x3099,  0x30fc,  0x30bf,  0x0,  0x30d8,  0x309a,  0x0,  0x30d8,  0x309a,  0x30bd,  0x0,  0x30d8,  0x309a,  0x30cb,  0x30d2,  0x0,  0x30d8,  0x309a,  0x30f3,  0x30b9,  0x0,  0x30d8,  0x309a,  0x30fc,  0x30b7,  0x3099,  0x0,  0x30d8,  0x30af,  0x30bf,  0x30fc,  0x30eb,  0x0,  0x30d8,  0x30eb,  0x30c4,  0x0,  0x30db,  0x0,  0x30db,  0x3099,  0x0,  0x30db,  0x3099,  0x30eb,  0x30c8,  0x0,  0x30db,  0x309a,  0x0,  0x30db,  0x309a,  0x30a4,  0x30f3,  0x30c8,  0x0,  0x30db,  0x309a,  0x30f3,  0x30c8,  0x3099,  0x0,  0x30db,  0x30f3,  0x0,  0x30db,  0x30fc,  0x30eb,  0x0,  0x30db,  0x30fc,  0x30f3,  0x0,  0x30de,  0x0,  0x30de,  0x30a4,  0x30af,  0x30ed,  0x0,  0x30de,  0x30a4,  0x30eb,  0x0,  0x30de,  0x30c3,  0x30cf,  0x0,  0x30de,  0x30eb,  0x30af,  0x0,  0x30de,  0x30f3,  0x30b7,  0x30e7,  0x30f3,  0x0,  0x30df,  0x0,  0x30df,  0x30af,  0x30ed,  0x30f3,  0x0,  0x30df,  0x30ea,  0x0,  0x30df,  0x30ea,  0x30cf,  0x3099,  0x30fc,  0x30eb,  0x0,  0x30e0,  0x0,  0x30e1,  0x0,  0x30e1,  0x30ab,  0x3099,  0x0,  0x30e1,  0x30ab,  0x3099,  0x30c8,  0x30f3,  0x0,  0x30e1,  0x30fc,  0x30c8,  0x30eb,  0x0,  0x30e2,  0x0,  0x30e3,  0x0,  0x30e4,  0x0,  0x30e4,  0x30fc,  0x30c8,  0x3099,  0x0,  0x30e4,  0x30fc,  0x30eb,  0x0,  0x30e5,  0x0,  0x30e6,  0x0,  0x30e6,  0x30a2,  0x30f3,  0x0,  0x30e7,  0x0,  0x30e8,  0x0,  0x30e9,  0x0,  0x30ea,  0x0,  0x30ea,  0x30c3,  0x30c8,  0x30eb,  0x0,  0x30ea,  0x30e9,  0x0,  0x30eb,  0x0,  0x30eb,  0x30d2,  0x309a,  0x30fc,  0x0,  0x30eb,  0x30fc,  0x30d5,  0x3099,  0x30eb,  0x0,  0x30ec,  0x0,  0x30ec,  0x30e0,  0x0,  0x30ec,  0x30f3,  0x30c8,  0x30b1,  0x3099,  0x30f3,  0x0,  0x30ed,  0x0,  0x30ef,  0x0,  0x30ef,  0x3099,  0x0,  0x30ef,  0x30c3,  0x30c8,  0x0,  0x30f0,  0x0,  0x30f0,  0x3099,  0x0,  0x30f1,  0x0,  0x30f1,  0x3099,  0x0,  0x30f2,  0x0,  0x30f2,  0x3099,  0x0,  0x30f3,  0x0,  0x30fb,  0x0,  0x30fc,  0x0,  0x30fd,  0x3099,  0x0,  0x349e,  0x0,  0x34b9,  0x0,  0x34bb,  0x0,  0x34df,  0x0,  0x3515,  0x0,  0x36ee,  0x0,  0x36fc,  0x0,  0x3781,  0x0,  0x382f,  0x0,  0x3862,  0x0,  0x387c,  0x0,  0x38c7,  0x0,  0x38e3,  0x0,  0x391c,  0x0,  0x393a,  0x0,  0x3a2e,  0x0,  0x3a6c,  0x0,  0x3ae4,  0x0,  0x3b08,  0x0,  0x3b19,  0x0,  0x3b49,  0x0,  0x3b9d,  0x0,  0x3c18,  0x0,  0x3c4e,  0x0,  0x3d33,  0x0,  0x3d96,  0x0,  0x3eac,  0x0,  0x3eb8,  0x0,  0x3f1b,  0x0,  0x3ffc,  0x0,  0x4008,  0x0,  0x4018,  0x0,  0x4039,  0x0,  0x4046,  0x0,  0x4096,  0x0,  0x40e3,  0x0,  0x412f,  0x0,  0x4202,  0x0,  0x4227,  0x0,  0x42a0,  0x0,  0x4301,  0x0,  0x4334,  0x0,  0x4359,  0x0,  0x43d5,  0x0,  0x43d9,  0x0,  0x440b,  0x0,  0x446b,  0x0,  0x452b,  0x0,  0x455d,  0x0,  0x4561,  0x0,  0x456b,  0x0,  0x45d7,  0x0,  0x45f9,  0x0,  0x4635,  0x0,  0x46be,  0x0,  0x46c7,  0x0,  0x4995,  0x0,  0x49e6,  0x0,  0x4a6e,  0x0,  0x4a76,  0x0,  0x4ab2,  0x0,  0x4b33,  0x0,  0x4bce,  0x0,  0x4cce,  0x0,  0x4ced,  0x0,  0x4cf8,  0x0,  0x4d56,  0x0,  0x4e00,  0x0,  0x4e01,  0x0,  0x4e03,  0x0,  0x4e09,  0x0,  0x4e0a,  0x0,  0x4e0b,  0x0,  0x4e0d,  0x0,  0x4e19,  0x0,  0x4e26,  0x0,  0x4e28,  0x0,  0x4e2d,  0x0,  0x4e32,  0x0,  0x4e36,  0x0,  0x4e38,  0x0,  0x4e39,  0x0,  0x4e3d,  0x0,  0x4e3f,  0x0,  0x4e41,  0x0,  0x4e59,  0x0,  0x4e5d,  0x0,  0x4e82,  0x0,  0x4e85,  0x0,  0x4e86,  0x0,  0x4e8c,  0x0,  0x4e94,  0x0,  0x4ea0,  0x0,  0x4ea4,  0x0,  0x4eae,  0x0,  0x4eba,  0x0,  0x4ec0,  0x0,  0x4ecc,  0x0,  0x4ee4,  0x0,  0x4f01,  0x0,  0x4f11,  0x0,  0x4f60,  0x0,  0x4f80,  0x0,  0x4f86,  0x0,  0x4f8b,  0x0,  0x4fae,  0x0,  0x4fbb,  0x0,  0x4fbf,  0x0,  0x5002,  0x0,  0x502b,  0x0,  0x507a,  0x0,  0x5099,  0x0,  0x50cf,  0x0,  0x50da,  0x0,  0x50e7,  0x0,  0x512a,  0x0,  0x513f,  0x0,  0x5140,  0x0,  0x5145,  0x0,  0x514d,  0x0,  0x5154,  0x0,  0x5164,  0x0,  0x5165,  0x0,  0x5167,  0x0,  0x5168,  0x0,  0x5169,  0x0,  0x516b,  0x0,  0x516d,  0x0,  0x5177,  0x0,  0x5180,  0x0,  0x5182,  0x0,  0x518d,  0x0,  0x5192,  0x0,  0x5195,  0x0,  0x5196,  0x0,  0x5197,  0x0,  0x5199,  0x0,  0x51a4,  0x0,  0x51ab,  0x0,  0x51ac,  0x0,  0x51b5,  0x0,  0x51b7,  0x0,  0x51c9,  0x0,  0x51cc,  0x0,  0x51dc,  0x0,  0x51de,  0x0,  0x51e0,  0x0,  0x51f5,  0x0,  0x5200,  0x0,  0x5203,  0x0,  0x5207,  0x0,  0x5217,  0x0,  0x521d,  0x0,  0x5229,  0x0,  0x523a,  0x0,  0x523b,  0x0,  0x5246,  0x0,  0x524d,  0x0,  0x5272,  0x0,  0x5277,  0x0,  0x5289,  0x0,  0x529b,  0x0,  0x52a3,  0x0,  0x52b3,  0x0,  0x52b4,  0x0,  0x52c7,  0x0,  0x52c9,  0x0,  0x52d2,  0x0,  0x52de,  0x0,  0x52e4,  0x0,  0x52f5,  0x0,  0x52f9,  0x0,  0x52fa,  0x0,  0x5305,  0x0,  0x5306,  0x0,  0x5315,  0x0,  0x5317,  0x0,  0x531a,  0x0,  0x5338,  0x0,  0x533b,  0x0,  0x533f,  0x0,  0x5341,  0x0,  0x5344,  0x0,  0x5345,  0x0,  0x5349,  0x0,  0x5351,  0x0,  0x5354,  0x0,  0x535a,  0x0,  0x535c,  0x0,  0x5369,  0x0,  0x5370,  0x0,  0x5373,  0x0,  0x5375,  0x0,  0x537d,  0x0,  0x537f,  0x0,  0x5382,  0x0,  0x53b6,  0x0,  0x53c3,  0x0,  0x53c8,  0x0,  0x53ca,  0x0,  0x53cc,  0x0,  0x53df,  0x0,  0x53e3,  0x0,  0x53e5,  0x0,  0x53eb,  0x0,  0x53ef,  0x0,  0x53f1,  0x0,  0x53f3,  0x0,  0x5406,  0x0,  0x5408,  0x0,  0x540d,  0x0,  0x540f,  0x0,  0x541d,  0x0,  0x5438,  0x0,  0x5439,  0x0,  0x5442,  0x0,  0x5448,  0x0,  0x5468,  0x0,  0x549e,  0x0,  0x54a2,  0x0,  0x54bd,  0x0,  0x54f6,  0x0,  0x5510,  0x0,  0x554f,  0x0,  0x5553,  0x0,  0x5555,  0x0,  0x5563,  0x0,  0x5584,  0x0,  0x5587,  0x0,  0x5599,  0x0,  0x559d,  0x0,  0x55ab,  0x0,  0x55b3,  0x0,  0x55b6,  0x0,  0x55c0,  0x0,  0x55c2,  0x0,  0x55e2,  0x0,  0x5606,  0x0,  0x5651,  0x0,  0x5668,  0x0,  0x5674,  0x0,  0x56d7,  0x0,  0x56db,  0x0,  0x56f9,  0x0,  0x5716,  0x0,  0x5717,  0x0,  0x571f,  0x0,  0x5730,  0x0,  0x578b,  0x0,  0x57ce,  0x0,  0x57f4,  0x0,  0x580d,  0x0,  0x5831,  0x0,  0x5832,  0x0,  0x5840,  0x0,  0x585a,  0x0,  0x585e,  0x0,  0x58a8,  0x0,  0x58ac,  0x0,  0x58b3,  0x0,  0x58d8,  0x0,  0x58df,  0x0,  0x58eb,  0x0,  0x58ee,  0x0,  0x58f0,  0x0,  0x58f2,  0x0,  0x58f7,  0x0,  0x5902,  0x0,  0x5906,  0x0,  0x590a,  0x0,  0x5915,  0x0,  0x591a,  0x0,  0x591c,  0x0,  0x5922,  0x0,  0x5927,  0x0,  0x5927,  0x6b63,  0x0,  0x5929,  0x0,  0x5944,  0x0,  0x5948,  0x0,  0x5951,  0x0,  0x5954,  0x0,  0x5962,  0x0,  0x5973,  0x0,  0x59d8,  0x0,  0x59ec,  0x0,  0x5a1b,  0x0,  0x5a27,  0x0,  0x5a62,  0x0,  0x5a66,  0x0,  0x5ab5,  0x0,  0x5b08,  0x0,  0x5b28,  0x0,  0x5b3e,  0x0,  0x5b50,  0x0,  0x5b57,  0x0,  0x5b66,  0x0,  0x5b80,  0x0,  0x5b85,  0x0,  0x5b97,  0x0,  0x5bc3,  0x0,  0x5bd8,  0x0,  0x5be7,  0x0,  0x5bee,  0x0,  0x5bf3,  0x0,  0x5bf8,  0x0,  0x5bff,  0x0,  0x5c06,  0x0,  0x5c0f,  0x0,  0x5c22,  0x0,  0x5c38,  0x0,  0x5c3f,  0x0,  0x5c60,  0x0,  0x5c62,  0x0,  0x5c64,  0x0,  0x5c65,  0x0,  0x5c6e,  0x0,  0x5c71,  0x0,  0x5c8d,  0x0,  0x5cc0,  0x0,  0x5d19,  0x0,  0x5d43,  0x0,  0x5d50,  0x0,  0x5d6b,  0x0,  0x5d6e,  0x0,  0x5d7c,  0x0,  0x5db2,  0x0,  0x5dba,  0x0,  0x5ddb,  0x0,  0x5de1,  0x0,  0x5de2,  0x0,  0x5de5,  0x0,  0x5de6,  0x0,  0x5df1,  0x0,  0x5dfd,  0x0,  0x5dfe,  0x0,  0x5e28,  0x0,  0x5e3d,  0x0,  0x5e69,  0x0,  0x5e72,  0x0,  0x5e73,  0x6210,  0x0,  0x5e74,  0x0,  0x5e7a,  0x0,  0x5e7c,  0x0,  0x5e7f,  0x0,  0x5ea6,  0x0,  0x5eb0,  0x0,  0x5eb3,  0x0,  0x5eb6,  0x0,  0x5ec9,  0x0,  0x5eca,  0x0,  0x5ed2,  0x0,  0x5ed3,  0x0,  0x5ed9,  0x0,  0x5eec,  0x0,  0x5ef4,  0x0,  0x5efe,  0x0,  0x5f04,  0x0,  0x5f0b,  0x0,  0x5f13,  0x0,  0x5f22,  0x0,  0x5f50,  0x0,  0x5f53,  0x0,  0x5f61,  0x0,  0x5f62,  0x0,  0x5f69,  0x0,  0x5f6b,  0x0,  0x5f73,  0x0,  0x5f8b,  0x0,  0x5f8c,  0x0,  0x5f97,  0x0,  0x5f9a,  0x0,  0x5fa9,  0x0,  0x5fad,  0x0,  0x5fc3,  0x0,  0x5fcd,  0x0,  0x5fd7,  0x0,  0x5ff5,  0x0,  0x5ff9,  0x0,  0x6012,  0x0,  0x601c,  0x0,  0x6075,  0x0,  0x6081,  0x0,  0x6094,  0x0,  0x60c7,  0x0,  0x60d8,  0x0,  0x60e1,  0x0,  0x6108,  0x0,  0x6144,  0x0,  0x6148,  0x0,  0x614c,  0x0,  0x614e,  0x0,  0x6160,  0x0,  0x6168,  0x0,  0x617a,  0x0,  0x618e,  0x0,  0x6190,  0x0,  0x61a4,  0x0,  0x61af,  0x0,  0x61b2,  0x0,  0x61de,  0x0,  0x61f2,  0x0,  0x61f6,  0x0,  0x6200,  0x0,  0x6208,  0x0,  0x6210,  0x0,  0x621b,  0x0,  0x622e,  0x0,  0x6234,  0x0,  0x6236,  0x0,  0x624b,  0x0,  0x6253,  0x0,  0x625d,  0x0,  0x6295,  0x0,  0x62b1,  0x0,  0x62c9,  0x0,  0x62cf,  0x0,  0x62d3,  0x0,  0x62d4,  0x0,  0x62fc,  0x0,  0x62fe,  0x0,  0x6307,  0x0,  0x633d,  0x0,  0x6350,  0x0,  0x6355,  0x0,  0x6368,  0x0,  0x637b,  0x0,  0x6383,  0x0,  0x63a0,  0x0,  0x63a9,  0x0,  0x63c4,  0x0,  0x63c5,  0x0,  0x63e4,  0x0,  0x641c,  0x0,  0x6422,  0x0,  0x6452,  0x0,  0x6469,  0x0,  0x6477,  0x0,  0x647e,  0x0,  0x649a,  0x0,  0x649d,  0x0,  0x64c4,  0x0,  0x652f,  0x0,  0x6534,  0x0,  0x654f,  0x0,  0x6556,  0x0,  0x656c,  0x0,  0x6578,  0x0,  0x6587,  0x0,  0x6597,  0x0,  0x6599,  0x0,  0x65a4,  0x0,  0x65b0,  0x0,  0x65b9,  0x0,  0x65c5,  0x0,  0x65e0,  0x0,  0x65e2,  0x0,  0x65e3,  0x0,  0x65e5,  0x0,  0x660e,  0x6cbb,  0x0,  0x6613,  0x0,  0x6620,  0x0,  0x662d,  0x548c,  0x0,  0x6649,  0x0,  0x6674,  0x0,  0x6688,  0x0,  0x6691,  0x0,  0x669c,  0x0,  0x66b4,  0x0,  0x66c6,  0x0,  0x66f0,  0x0,  0x66f4,  0x0,  0x66f8,  0x0,  0x6700,  0x0,  0x6708,  0x0,  0x6709,  0x0,  0x6717,  0x0,  0x671b,  0x0,  0x6721,  0x0,  0x6728,  0x0,  0x674e,  0x0,  0x6753,  0x0,  0x6756,  0x0,  0x675e,  0x0,  0x677b,  0x0,  0x6785,  0x0,  0x6797,  0x0,  0x67f3,  0x0,  0x67fa,  0x0,  0x6817,  0x0,  0x681f,  0x0,  0x682a,  0x0,  0x682a,  0x5f0f,  0x4f1a,  0x793e,  0x0,  0x6852,  0x0,  0x6881,  0x0,  0x6885,  0x0,  0x688e,  0x0,  0x68a8,  0x0,  0x6914,  0x0,  0x6942,  0x0,  0x69a3,  0x0,  0x69ea,  0x0,  0x6a02,  0x0,  0x6a13,  0x0,  0x6aa8,  0x0,  0x6ad3,  0x0,  0x6adb,  0x0,  0x6b04,  0x0,  0x6b20,  0x0,  0x6b21,  0x0,  0x6b54,  0x0,  0x6b62,  0x0,  0x6b63,  0x0,  0x6b72,  0x0,  0x6b77,  0x0,  0x6b79,  0x0,  0x6b9f,  0x0,  0x6bae,  0x0,  0x6bb3,  0x0,  0x6bba,  0x0,  0x6bbb,  0x0,  0x6bcb,  0x0,  0x6bcd,  0x0,  0x6bd4,  0x0,  0x6bdb,  0x0,  0x6c0f,  0x0,  0x6c14,  0x0,  0x6c34,  0x0,  0x6c4e,  0x0,  0x6c67,  0x0,  0x6c88,  0x0,  0x6cbf,  0x0,  0x6ccc,  0x0,  0x6ccd,  0x0,  0x6ce5,  0x0,  0x6ce8,  0x0,  0x6d16,  0x0,  0x6d1b,  0x0,  0x6d1e,  0x0,  0x6d34,  0x0,  0x6d3e,  0x0,  0x6d41,  0x0,  0x6d69,  0x0,  0x6d6a,  0x0,  0x6d77,  0x0,  0x6d78,  0x0,  0x6d85,  0x0,  0x6dcb,  0x0,  0x6dda,  0x0,  0x6dea,  0x0,  0x6df9,  0x0,  0x6e1a,  0x0,  0x6e2f,  0x0,  0x6e6e,  0x0,  0x6e80,  0x0,  0x6e9c,  0x0,  0x6eba,  0x0,  0x6ec7,  0x0,  0x6ecb,  0x0,  0x6ed1,  0x0,  0x6edb,  0x0,  0x6f0f,  0x0,  0x6f14,  0x0,  0x6f22,  0x0,  0x6f23,  0x0,  0x6f6e,  0x0,  0x6fc6,  0x0,  0x6feb,  0x0,  0x6ffe,  0x0,  0x701b,  0x0,  0x701e,  0x0,  0x7039,  0x0,  0x704a,  0x0,  0x706b,  0x0,  0x7070,  0x0,  0x7077,  0x0,  0x707d,  0x0,  0x7099,  0x0,  0x70ad,  0x0,  0x70c8,  0x0,  0x70d9,  0x0,  0x7121,  0x0,  0x7145,  0x0,  0x7149,  0x0,  0x716e,  0x0,  0x719c,  0x0,  0x71ce,  0x0,  0x71d0,  0x0,  0x7210,  0x0,  0x721b,  0x0,  0x7228,  0x0,  0x722a,  0x0,  0x722b,  0x0,  0x7235,  0x0,  0x7236,  0x0,  0x723b,  0x0,  0x723f,  0x0,  0x7247,  0x0,  0x7250,  0x0,  0x7259,  0x0,  0x725b,  0x0,  0x7262,  0x0,  0x7279,  0x0,  0x7280,  0x0,  0x7295,  0x0,  0x72ac,  0x0,  0x72af,  0x0,  0x72c0,  0x0,  0x72fc,  0x0,  0x732a,  0x0,  0x7375,  0x0,  0x737a,  0x0,  0x7384,  0x0,  0x7387,  0x0,  0x7389,  0x0,  0x738b,  0x0,  0x73a5,  0x0,  0x73b2,  0x0,  0x73de,  0x0,  0x7406,  0x0,  0x7409,  0x0,  0x7422,  0x0,  0x7447,  0x0,  0x745c,  0x0,  0x7469,  0x0,  0x7471,  0x0,  0x7485,  0x0,  0x7489,  0x0,  0x7498,  0x0,  0x74ca,  0x0,  0x74dc,  0x0,  0x74e6,  0x0,  0x7506,  0x0,  0x7518,  0x0,  0x751f,  0x0,  0x7524,  0x0,  0x7528,  0x0,  0x7530,  0x0,  0x7532,  0x0,  0x7533,  0x0,  0x7537,  0x0,  0x753b,  0x0,  0x753e,  0x0,  0x7559,  0x0,  0x7565,  0x0,  0x7570,  0x0,  0x758b,  0x0,  0x7592,  0x0,  0x75e2,  0x0,  0x7610,  0x0,  0x761d,  0x0,  0x761f,  0x0,  0x7642,  0x0,  0x7669,  0x0,  0x7676,  0x0,  0x767d,  0x0,  0x76ae,  0x0,  0x76bf,  0x0,  0x76ca,  0x0,  0x76db,  0x0,  0x76e3,  0x0,  0x76e7,  0x0,  0x76ee,  0x0,  0x76f4,  0x0,  0x7701,  0x0,  0x771e,  0x0,  0x771f,  0x0,  0x7740,  0x0,  0x774a,  0x0,  0x778b,  0x0,  0x77a7,  0x0,  0x77db,  0x0,  0x77e2,  0x0,  0x77f3,  0x0,  0x784e,  0x0,  0x786b,  0x0,  0x788c,  0x0,  0x7891,  0x0,  0x78ca,  0x0,  0x78cc,  0x0,  0x78fb,  0x0,  0x792a,  0x0,  0x793a,  0x0,  0x793c,  0x0,  0x793e,  0x0,  0x7948,  0x0,  0x7949,  0x0,  0x7950,  0x0,  0x7956,  0x0,  0x795d,  0x0,  0x795e,  0x0,  0x7965,  0x0,  0x797f,  0x0,  0x7981,  0x0,  0x798d,  0x0,  0x798e,  0x0,  0x798f,  0x0,  0x79ae,  0x0,  0x79b8,  0x0,  0x79be,  0x0,  0x79ca,  0x0,  0x79d8,  0x0,  0x79eb,  0x0,  0x7a1c,  0x0,  0x7a40,  0x0,  0x7a4a,  0x0,  0x7a4f,  0x0,  0x7a74,  0x0,  0x7a7a,  0x0,  0x7a81,  0x0,  0x7ab1,  0x0,  0x7acb,  0x0,  0x7aee,  0x0,  0x7af9,  0x0,  0x7b20,  0x0,  0x7b8f,  0x0,  0x7bc0,  0x0,  0x7bc6,  0x0,  0x7bc9,  0x0,  0x7c3e,  0x0,  0x7c60,  0x0,  0x7c73,  0x0,  0x7c7b,  0x0,  0x7c92,  0x0,  0x7cbe,  0x0,  0x7cd2,  0x0,  0x7cd6,  0x0,  0x7ce3,  0x0,  0x7ce7,  0x0,  0x7ce8,  0x0,  0x7cf8,  0x0,  0x7d00,  0x0,  0x7d10,  0x0,  0x7d22,  0x0,  0x7d2f,  0x0,  0x7d42,  0x0,  0x7d5b,  0x0,  0x7d63,  0x0,  0x7da0,  0x0,  0x7dbe,  0x0,  0x7dc7,  0x0,  0x7df4,  0x0,  0x7e02,  0x0,  0x7e09,  0x0,  0x7e37,  0x0,  0x7e41,  0x0,  0x7e45,  0x0,  0x7f36,  0x0,  0x7f3e,  0x0,  0x7f51,  0x0,  0x7f72,  0x0,  0x7f79,  0x0,  0x7f7a,  0x0,  0x7f85,  0x0,  0x7f8a,  0x0,  0x7f95,  0x0,  0x7f9a,  0x0,  0x7fbd,  0x0,  0x7ffa,  0x0,  0x8001,  0x0,  0x8005,  0x0,  0x800c,  0x0,  0x8012,  0x0,  0x8033,  0x0,  0x8046,  0x0,  0x8060,  0x0,  0x806f,  0x0,  0x8070,  0x0,  0x807e,  0x0,  0x807f,  0x0,  0x8089,  0x0,  0x808b,  0x0,  0x80ad,  0x0,  0x80b2,  0x0,  0x8103,  0x0,  0x813e,  0x0,  0x81d8,  0x0,  0x81e3,  0x0,  0x81e8,  0x0,  0x81ea,  0x0,  0x81ed,  0x0,  0x81f3,  0x0,  0x81fc,  0x0,  0x8201,  0x0,  0x8204,  0x0,  0x820c,  0x0,  0x8218,  0x0,  0x821b,  0x0,  0x821f,  0x0,  0x826e,  0x0,  0x826f,  0x0,  0x8272,  0x0,  0x8278,  0x0,  0x8279,  0x0,  0x828b,  0x0,  0x8291,  0x0,  0x829d,  0x0,  0x82b1,  0x0,  0x82b3,  0x0,  0x82bd,  0x0,  0x82e5,  0x0,  0x82e6,  0x0,  0x831d,  0x0,  0x8323,  0x0,  0x8336,  0x0,  0x8352,  0x0,  0x8353,  0x0,  0x8363,  0x0,  0x83ad,  0x0,  0x83bd,  0x0,  0x83c9,  0x0,  0x83ca,  0x0,  0x83cc,  0x0,  0x83dc,  0x0,  0x83e7,  0x0,  0x83ef,  0x0,  0x83f1,  0x0,  0x843d,  0x0,  0x8449,  0x0,  0x8457,  0x0,  0x84ee,  0x0,  0x84f1,  0x0,  0x84f3,  0x0,  0x84fc,  0x0,  0x8516,  0x0,  0x8564,  0x0,  0x85cd,  0x0,  0x85fa,  0x0,  0x8606,  0x0,  0x8612,  0x0,  0x862d,  0x0,  0x863f,  0x0,  0x864d,  0x0,  0x8650,  0x0,  0x865c,  0x0,  0x8667,  0x0,  0x8669,  0x0,  0x866b,  0x0,  0x8688,  0x0,  0x86a9,  0x0,  0x86e2,  0x0,  0x870e,  0x0,  0x8728,  0x0,  0x876b,  0x0,  0x8779,  0x0,  0x8786,  0x0,  0x87ba,  0x0,  0x87e1,  0x0,  0x8801,  0x0,  0x881f,  0x0,  0x8840,  0x0,  0x884c,  0x0,  0x8860,  0x0,  0x8863,  0x0,  0x88c2,  0x0,  0x88cf,  0x0,  0x88d7,  0x0,  0x88de,  0x0,  0x88e1,  0x0,  0x88f8,  0x0,  0x88fa,  0x0,  0x8910,  0x0,  0x8941,  0x0,  0x8964,  0x0,  0x897e,  0x0,  0x8986,  0x0,  0x898b,  0x0,  0x8996,  0x0,  0x89d2,  0x0,  0x89e3,  0x0,  0x8a00,  0x0,  0x8aa0,  0x0,  0x8aaa,  0x0,  0x8abf,  0x0,  0x8acb,  0x0,  0x8ad2,  0x0,  0x8ad6,  0x0,  0x8aed,  0x0,  0x8af8,  0x0,  0x8afe,  0x0,  0x8b01,  0x0,  0x8b39,  0x0,  0x8b58,  0x0,  0x8b80,  0x0,  0x8b8a,  0x0,  0x8c37,  0x0,  0x8c46,  0x0,  0x8c48,  0x0,  0x8c55,  0x0,  0x8c78,  0x0,  0x8c9d,  0x0,  0x8ca1,  0x0,  0x8ca9,  0x0,  0x8cab,  0x0,  0x8cc1,  0x0,  0x8cc2,  0x0,  0x8cc7,  0x0,  0x8cc8,  0x0,  0x8cd3,  0x0,  0x8d08,  0x0,  0x8d1b,  0x0,  0x8d64,  0x0,  0x8d70,  0x0,  0x8d77,  0x0,  0x8db3,  0x0,  0x8dbc,  0x0,  0x8dcb,  0x0,  0x8def,  0x0,  0x8df0,  0x0,  0x8eab,  0x0,  0x8eca,  0x0,  0x8ed4,  0x0,  0x8f26,  0x0,  0x8f2a,  0x0,  0x8f38,  0x0,  0x8f3b,  0x0,  0x8f62,  0x0,  0x8f9b,  0x0,  0x8f9e,  0x0,  0x8fb0,  0x0,  0x8fb5,  0x0,  0x8fb6,  0x0,  0x9023,  0x0,  0x9038,  0x0,  0x904a,  0x0,  0x9069,  0x0,  0x9072,  0x0,  0x907c,  0x0,  0x908f,  0x0,  0x9091,  0x0,  0x9094,  0x0,  0x90ce,  0x0,  0x90de,  0x0,  0x90f1,  0x0,  0x90fd,  0x0,  0x9111,  0x0,  0x911b,  0x0,  0x9149,  0x0,  0x916a,  0x0,  0x9199,  0x0,  0x91b4,  0x0,  0x91c6,  0x0,  0x91cc,  0x0,  0x91cf,  0x0,  0x91d1,  0x0,  0x9234,  0x0,  0x9238,  0x0,  0x9276,  0x0,  0x927c,  0x0,  0x92d7,  0x0,  0x92d8,  0x0,  0x9304,  0x0,  0x934a,  0x0,  0x93f9,  0x0,  0x9415,  0x0,  0x9577,  0x0,  0x9580,  0x0,  0x958b,  0x0,  0x95ad,  0x0,  0x95b7,  0x0,  0x961c,  0x0,  0x962e,  0x0,  0x964b,  0x0,  0x964d,  0x0,  0x9675,  0x0,  0x9678,  0x0,  0x967c,  0x0,  0x9686,  0x0,  0x96a3,  0x0,  0x96b6,  0x0,  0x96b7,  0x0,  0x96b8,  0x0,  0x96b9,  0x0,  0x96c3,  0x0,  0x96e2,  0x0,  0x96e3,  0x0,  0x96e8,  0x0,  0x96f6,  0x0,  0x96f7,  0x0,  0x9723,  0x0,  0x9732,  0x0,  0x9748,  0x0,  0x9751,  0x0,  0x9756,  0x0,  0x975e,  0x0,  0x9762,  0x0,  0x9769,  0x0,  0x97cb,  0x0,  0x97db,  0x0,  0x97e0,  0x0,  0x97ed,  0x0,  0x97f3,  0x0,  0x97ff,  0x0,  0x9801,  0x0,  0x9805,  0x0,  0x980b,  0x0,  0x9818,  0x0,  0x9829,  0x0,  0x983b,  0x0,  0x985e,  0x0,  0x98a8,  0x0,  0x98db,  0x0,  0x98df,  0x0,  0x98e2,  0x0,  0x98ef,  0x0,  0x98fc,  0x0,  0x9928,  0x0,  0x9929,  0x0,  0x9996,  0x0,  0x9999,  0x0,  0x99a7,  0x0,  0x99ac,  0x0,  0x99c2,  0x0,  0x99f1,  0x0,  0x99fe,  0x0,  0x9a6a,  0x0,  0x9aa8,  0x0,  0x9ad8,  0x0,  0x9adf,  0x0,  0x9b12,  0x0,  0x9b25,  0x0,  0x9b2f,  0x0,  0x9b32,  0x0,  0x9b3c,  0x0,  0x9b5a,  0x0,  0x9b6f,  0x0,  0x9c40,  0x0,  0x9c57,  0x0,  0x9ce5,  0x0,  0x9cfd,  0x0,  0x9d67,  0x0,  0x9db4,  0x0,  0x9dfa,  0x0,  0x9e1e,  0x0,  0x9e75,  0x0,  0x9e7f,  0x0,  0x9e97,  0x0,  0x9e9f,  0x0,  0x9ea5,  0x0,  0x9ebb,  0x0,  0x9ec3,  0x0,  0x9ecd,  0x0,  0x9ece,  0x0,  0x9ed1,  0x0,  0x9ef9,  0x0,  0x9efd,  0x0,  0x9efe,  0x0,  0x9f05,  0x0,  0x9f0e,  0x0,  0x9f0f,  0x0,  0x9f13,  0x0,  0x9f16,  0x0,  0x9f20,  0x0,  0x9f3b,  0x0,  0x9f43,  0x0,  0x9f4a,  0x0,  0x9f52,  0x0,  0x9f8d,  0x0,  0x9f8e,  0x0,  0x9f9c,  0x0,  0x9f9f,  0x0,  0x9fa0,  0x0,  0xa76f,  0x0,  0x11099,  0x110ba,  0x0,  0x1109b,  0x110ba,  0x0,  0x110a5,  0x110ba,  0x0,  0x11131,  0x11127,  0x0,  0x11132,  0x11127,  0x0,  0x1d157,  0x1d165,  0x0,  0x1d158,  0x1d165,  0x0,  0x1d158,  0x1d165,  0x1d16e,  0x0,  0x1d158,  0x1d165,  0x1d16f,  0x0,  0x1d158,  0x1d165,  0x1d170,  0x0,  0x1d158,  0x1d165,  0x1d171,  0x0,  0x1d158,  0x1d165,  0x1d172,  0x0,  0x1d1b9,  0x1d165,  0x0,  0x1d1b9,  0x1d165,  0x1d16e,  0x0,  0x1d1b9,  0x1d165,  0x1d16f,  0x0,  0x1d1ba,  0x1d165,  0x0,  0x1d1ba,  0x1d165,  0x1d16e,  0x0,  0x1d1ba,  0x1d165,  0x1d16f,  0x0,  0x20122,  0x0,  0x2051c,  0x0,  0x20525,  0x0,  0x2054b,  0x0,  0x2063a,  0x0,  0x20804,  0x0,  0x208de,  0x0,  0x20a2c,  0x0,  0x20b63,  0x0,  0x214e4,  0x0,  0x216a8,  0x0,  0x216ea,  0x0,  0x219c8,  0x0,  0x21b18,  0x0,  0x21d0b,  0x0,  0x21de4,  0x0,  0x21de6,  0x0,  0x22183,  0x0,  0x2219f,  0x0,  0x22331,  0x0,  0x226d4,  0x0,  0x22844,  0x0,  0x2284a,  0x0,  0x22b0c,  0x0,  0x22bf1,  0x0,  0x2300a,  0x0,  0x232b8,  0x0,  0x2335f,  0x0,  0x23393,  0x0,  0x2339c,  0x0,  0x233c3,  0x0,  0x233d5,  0x0,  0x2346d,  0x0,  0x236a3,  0x0,  0x238a7,  0x0,  0x23a8d,  0x0,  0x23afa,  0x0,  0x23cbc,  0x0,  0x23d1e,  0x0,  0x23ed1,  0x0,  0x23f5e,  0x0,  0x23f8e,  0x0,  0x24263,  0x0,  0x242ee,  0x0,  0x243ab,  0x0,  0x24608,  0x0,  0x24735,  0x0,  0x24814,  0x0,  0x24c36,  0x0,  0x24c92,  0x0,  0x24fa1,  0x0,  0x24fb8,  0x0,  0x25044,  0x0,  0x250f2,  0x0,  0x250f3,  0x0,  0x25119,  0x0,  0x25133,  0x0,  0x25249,  0x0,  0x2541d,  0x0,  0x25626,  0x0,  0x2569a,  0x0,  0x256c5,  0x0,  0x2597c,  0x0,  0x25aa7,  0x0,  0x25bab,  0x0,  0x25c80,  0x0,  0x25cd0,  0x0,  0x25f86,  0x0,  0x261da,  0x0,  0x26228,  0x0,  0x26247,  0x0,  0x262d9,  0x0,  0x2633e,  0x0,  0x264da,  0x0,  0x26523,  0x0,  0x265a8,  0x0,  0x267a7,  0x0,  0x267b5,  0x0,  0x26b3c,  0x0,  0x26c36,  0x0,  0x26cd5,  0x0,  0x26d6b,  0x0,  0x26f2c,  0x0,  0x26fb1,  0x0,  0x270d2,  0x0,  0x273ca,  0x0,  0x27667,  0x0,  0x278ae,  0x0,  0x27966,  0x0,  0x27ca8,  0x0,  0x27ed3,  0x0,  0x27f2f,  0x0,  0x285d2,  0x0,  0x285ed,  0x0,  0x2872e,  0x0,  0x28bfa,  0x0,  0x28d77,  0x0,  0x29145,  0x0,  0x291df,  0x0,  0x2921a,  0x0,  0x2940a,  0x0,  0x29496,  0x0,  0x295b6,  0x0,  0x29b30,  0x0,  0x2a0ce,  0x0,  0x2a105,  0x0,  0x2a20e,  0x0,  0x2a291,  0x0,  0x2a392,  0x0,  0x2a600,  0x0]; return t; }
+}
+
+}
+
+
+static if(size_t.sizeof == 4) {
+//22656 bytes
+enum compatMappingTrieEntries = TrieEntry!(ushort, 8, 8, 5)([ 0x0,  0x40,  0x540], [ 0x100,  0xa00,  0x21c0], [ 0x2020100,  0x4020302,  0x2020205,  0x7060202,  0x2020202,  0x8020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x0,  0x0,  0x10000,  0x30002,  0x50004,  0x70006,  0x80000,  0xa0009,  0xc000b,  0x0,  0xd0000,  0xf000e,  0x0,  0x110010,  0x130012,  0x150014,  0x170016,  0x190018,  0x0,  0x1b001a,  0x0,  0x0,  0x1c,  0x0,  0x1d0000,  0x1e0000,  0x0,  0x1f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x200000,  0x21,  0x0,  0x22,  0x230000,  0x24,  0x0,  0x0,  0x0,  0x25,  0x26,  0x27,  0x0,  0x28,  0x0,  0x29,  0x0,  0x2a,  0x0,  0x2b,  0x2c0000,  0x0,  0x2d0000,  0x2e,  0x2f,  0x310030,  0x330032,  0x0,  0x340000,  0x0,  0x0,  0x350000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x370036,  0x38,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x390000,  0x3b003a,  0x3d003c,  0x0,  0x3f003e,  0x410040,  0x430042,  0x450044,  0x470046,  0x490048,  0x4b004a,  0x4d004c,  0x4f004e,  0x510050,  0x530052,  0x0,  0x550054,  0x570056,  0x590058,  0x5a,  0x5c005b,  0x5e005d,  0x60005f,  0x610000,  0x620000,  0x0,  0x0,  0x0,  0x0,  0x630000,  0x650064,  0x670066,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x68,  0x690000,  0x0,  0x6a,  0x0,  0x0,  0x0,  0x0,  0x0,  0x6b0000,  0x0,  0x0,  0x0,  0x6c0000,  0x0,  0x0,  0x0,  0x0,  0x6d,  0x6e0000,  0x70006f,  0x720071,  0x740073,  0x75,  0x770076,  0x790078,  0x7b007a,  0x7d007c,  0x7e0000,  0x80007f,  0x81,  0x0,  0x830082,  0x850084,  0x870086,  0x890088,  0x8b008a,  0x8d008c,  0x8f008e,  0x910090,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x920000,  0x0,  0x930000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x950094,  0x970096,  0x990098,  0x9b009a,  0x9d009c,  0x9f009e,  0xa100a0,  0xa2,  0xa400a3,  0xa600a5,  0xa800a7,  0xaa00a9,  0xac00ab,  0xae00ad,  0xb000af,  0xb200b1,  0xb400b3,  0xb600b5,  0xb800b7,  0xba00b9,  0xbc00bb,  0xbe00bd,  0xc000bf,  0xc200c1,  0xc400c3,  0xc600c5,  0xc800c7,  0xca00c9,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xcc00cb,  0x0,  0xcd0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xcf00ce,  0xd00000,  0xd1,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xd300d2,  0xd500d4,  0xd700d6,  0xd900d8,  0xdb00da,  0xdd00dc,  0xd200de,  0xdf00d3,  0xe000d5,  0xe200e1,  0xe300d9,  0xe500e4,  0xe700e6,  0xe900e8,  0xeb00ea,  0xed00ec,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xef00ee,  0xf100f0,  0xf300f2,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xf500f4,  0xf700f6,  0xf8,  0x0,  0xfa00f9,  0xfb,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xfd00fc,  0xff00fe,  0x1010100,  0x1030102,  0x1050104,  0x1070106,  0x1090108,  0x10b010a,  0x10c,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1,  0x0,  0x0,  0x0,  0x15,  0x692,  0x0,  0x90000,  0x0,  0x30f0343,  0x11b20003,  0x0,  0x3140048,  0x787,  0x3c603ce,  0x494,  0x570056d,  0x5860573,  0x5b005a6,  0x5f80000,  0x62e062b,  0x6580631,  0x6e706e4,  0x6f906ea,  0x78f0000,  0x7a907a6,  0x7bf07ac,  0x7e3,  0x8b10000,  0x8b708b4,  0x95f08cb,  0x0,  0x9ac09a9,  0x9c209af,  0x9ec09e2,  0xa470000,  0xa890a86,  0xab30a8c,  0xb460b43,  0xb550b49,  0xc410000,  0xc5e0c5b,  0xc740c61,  0xc98,  0xd680000,  0xd6e0d6b,  0xe0c0d82,  0xe1b0000,  0x9c50589,  0x9c8058c,  0xa0a05ce,  0xa3b05ec,  0xa3e05ef,  0xa4105f2,  0xa4405f5,  0xa6e061a,  0x0,  0xaa20647,  0xaad0652,  0xab00655,  0xad00675,  0xab9065e,  0xafb069a,  0xb0106a0,  0xb0406a3,  0xb0a06a9,  0xb1606ba,  0x0,  0xb4c06ed,  0xb4f06f0,  0xb5206f3,  0xb6b070f,  0x6f6,  0xb3706d8,  0xb730717,  0xbae072e,  0x7430000,  0x7500bcc,  0x7460bd9,  0x7400bcf,  0xbc9,  0x78c0000,  0x79b0c3e,  0x7950c4d,  0xed70c47,  0x0,  0xc8307ce,  0xc8e07d9,  0xca207ed,  0x0,  0xd070842,  0xd1d0858,  0xd0d0848,  0xd2b086c,  0xd320873,  0xd49088a,  0xd380879,  0xd5d08a6,  0xd54089d,  0x0,  0xd7108ba,  0xd7808c1,  0xd7f08c8,  0xd9808e1,  0xd9b08e4,  0xdc4090d,  0xde9093f,  0xe0f0962,  0x979096e,  0x97f0e29,  0x60d0e2f,  0x8400614,  0xcae07f9,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x8f00000,  0xda7,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x613060c,  0x7360a67,  0xbb9073d,  0x7830780,  0x5b70c32,  0x70309f3,  0x7f00b5f,  0x8e70ca5,  0x8d60d9e,  0x8d20d8d,  0x8da0d89,  0x8ce0d91,  0xd85,  0x9e505a9,  0x9de05a2,  0xe630e5a,  0x0,  0xb0706a6,  0xba80728,  0xccc0817,  0xccf081a,  0xecc0e7b,  0x6090b76,  0xa640610,  0xaf80697,  0x0,  0xc3b0789,  0x9ef05b3,  0xe600e57,  0xe680e5d,  0x9f605ba,  0x9f905bd,  0xabc0661,  0xabf0664,  0xb620706,  0xb650709,  0xca807f3,  0xcab07f6,  0xd10084b,  0xd13084e,  0xda108ea,  0xda408ed,  0xd460887,  0xd5a08a3,  0x0,  0xb1f06c3,  0x0,  0x0,  0x0,  0x9db059f,  0xac9066e,  0xc9b07e6,  0xc7b07c6,  0xc9107dc,  0xc9407df,  0xe150968,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe9a0b0d,  0xa11073e,  0xeb60eb4,  0xde10eb8,  0x695,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x12000f,  0x4b0024,  0x270006,  0x0,  0xa280e96,  0xb410840,  0xecf,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x4001a,  0x2b0000,  0x1d,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xed5,  0x0,  0x0,  0x54,  0x0,  0x546,  0x0,  0x0,  0x1c0003,  0x7410ee8,  0xf630f43,  0xfb4,  0xfed,  0x103c1016,  0x1185,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x101f0fbd,  0x10f5108f,  0x11751119,  0x1213,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x120c117e,  0x120311d5,  0x124b,  0x116e10ea,  0x10161011,  0x123c101f,  0x11ee,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x11f011ae,  0x11f8,  0x10f00fad,  0x0,  0x100d0000,  0x0,  0x0,  0x0,  0x12b612b0,  0x12ad0000,  0x0,  0x12a40000,  0x0,  0x0,  0x12c212ce,  0x12d7,  0x0,  0x0,  0x0,  0x0,  0x12c80000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x130a0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x12f812f2,  0x12ef0000,  0x0,  0x132d0000,  0x0,  0x0,  0x13041310,  0x131b,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x13331330,  0x0,  0x0,  0x0,  0x0,  0x12b90000,  0x12fb,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x12e912a7,  0x12ec12aa,  0x0,  0x12f512b3,  0x0,  0x13391336,  0x12fe12bc,  0x130112bf,  0x0,  0x130712c5,  0x130d12cb,  0x131512d1,  0x0,  0x133f133c,  0x132a12e6,  0x131812d4,  0x131e12da,  0x132112dd,  0x132412e0,  0x0,  0x132712e3,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x13420000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x13e913e6,  0x13ec178f,  0x17ca,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x13ef0000,  0x185b1792,  0x1811,  0x0,  0x0,  0x0,  0x186d,  0x1852,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x186a0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18820000,  0x0,  0x0,  0x0,  0x188b0000,  0x0,  0x188e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18731870,  0x18791876,  0x187f187c,  0x18881885,  0x0,  0x0,  0x0,  0x0,  0x0,  0x189a0000,  0x189d,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18941891,  0x18970000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18ac0000,  0x0,  0x18af,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18a00000,  0x18a618a3,  0x0,  0x18a9,  0x0,  0x0,  0x0,  0x0,  0x18bb,  0x18b80000,  0x18be,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18b518b2,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18c1,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18ca18c4,  0x18c7,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18cd,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18d0,  0x0,  0x0,  0x18da0000,  0x18dd,  0x18d618d3,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18e618e0,  0x18e3,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18e9,  0x18ef18ec,  0x18f3,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18f60000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18ff0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18fc18f9,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1902,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x19070000,  0x0,  0x0,  0x0,  0x0,  0x190a0000,  0x0,  0x0,  0x190d,  0x0,  0x19100000,  0x0,  0x0,  0x1913,  0x0,  0x0,  0x0,  0x0,  0x0,  0x19040000,  0x0,  0x0,  0x0,  0x0,  0x19160000,  0x19190000,  0x19311935,  0x1938193c,  0x0,  0x0,  0x0,  0x191c0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x19220000,  0x0,  0x0,  0x0,  0x0,  0x19250000,  0x0,  0x0,  0x1928,  0x0,  0x192b0000,  0x0,  0x0,  0x192e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x191f0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x193f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1942,  0x0,  0x0,  0x0,  0x0,  0x1a38,  0x1a3b,  0x1a3e,  0x1a41,  0x1a44,  0x0,  0x1a47,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1a4a0000,  0x1a4d0000,  0x0,  0x1a531a50,  0x1a560000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe550568,  0x5d5,  0x62905e6,  0x6870e75,  0x6cf06ac,  0x71a0607,  0x7230734,  0x77e,  0xe7e07a4,  0x82c06af,  0x56b088d,  0x6920770,  0xe840e82,  0x9371a59,  0xa7d0a2e,  0xe8e0e8c,  0x6020e90,  0xb790000,  0xe7105d3,  0xe880787,  0x1a5d1a5b,  0xba30cd3,  0x1a610a24,  0x86a0ea4,  0x10ea1a63,  0x10ee10ec,  0x123e123c,  0xa110ae0,  0x86a0a24,  0x10ec10ea,  0x123c11f0,  0x123e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1313,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe860000,  0xe8a09a0,  0xe900e66,  0xe920ad9,  0xe980e94,  0xe9e0e9c,  0x1a650ea0,  0xea20ed1,  0xed31a67,  0xea60ea8,  0xeac0eaa,  0xeb00eae,  0xeba0eb2,  0xe790ebc,  0xec00ebe,  0xec21a5f,  0x6110ec4,  0xec80ec6,  0x116e0eca,  0xa0705cb,  0xa1305da,  0xa1605dd,  0xa1905e0,  0xa4a05fb,  0xa6b0617,  0xa71061d,  0xa7a0626,  0xa740620,  0xa770623,  0xaa5064a,  0xaa9064e,  0xad30678,  0xad6067b,  0xacc0671,  0xaef0684,  0xafe069d,  0xb1906bd,  0xb2206c6,  0xb1c06c0,  0xb2506c9,  0xb2806cc,  0xb6e0712,  0xb5806fc,  0xba50725,  0xbab072b,  0xbb10731,  0xbd20749,  0xbd5074c,  0xbdf0756,  0xbdc0753,  0xc120772,  0xc150775,  0xc180778,  0xc440792,  0xc4a0798,  0xc5307a1,  0xc50079e,  0xc7707c2,  0xc7f07ca,  0xc8607d1,  0xc8a07d5,  0xcec0835,  0xcef0838,  0xd0a0845,  0xd160851,  0xd190854,  0xd20085b,  0xd350876,  0xd3f0880,  0xd2e086f,  0xd3b087c,  0xd420883,  0xd4e089a,  0xd5708a0,  0xd6308ac,  0xd6008a9,  0xdc1090a,  0xdca0913,  0xdc70910,  0xd7408bd,  0xd7b08c4,  0xddb0924,  0xdde0927,  0xde30939,  0xde6093c,  0xdef0945,  0xdec0942,  0xdf50948,  0xe010954,  0xe040957,  0xe18096b,  0xe2c097c,  0xe350985,  0xe380988,  0xd510b2b,  0xe210df2,  0xd3509a6,  0x0,  0x0,  0x9fc05c0,  0x9e905ad,  0x9b6057a,  0x9b20576,  0x9be0582,  0x9ba057e,  0x9ff05c3,  0x9cf0593,  0x9cb058f,  0x9d7059b,  0x9d30597,  0xa0305c7,  0xac20667,  0xab6065b,  0xa9f0644,  0xa930638,  0xa8f0634,  0xa9b0640,  0xa97063c,  0xac5066a,  0xb5c0700,  0xb68070c,  0xcc50810,  0xc9f07ea,  0xc6807b3,  0xc6407af,  0xc7007bb,  0xc6c07b7,  0xcc80813,  0xcb50800,  0xcb107fc,  0xcbd0808,  0xcb90804,  0xcc1080c,  0xdbe0907,  0xd9508de,  0xdae08f7,  0xdaa08f3,  0xdb608ff,  0xdb208fb,  0xdba0903,  0xe09095c,  0xe240974,  0xe1e0971,  0xe120965,  0x0,  0x0,  0x0,  0x10be109c,  0x10c1109f,  0x10ca10a8,  0x10d310b1,  0xf130ef1,  0xf160ef4,  0xf1f0efd,  0xf280f06,  0x110310f8,  0x110610fb,  0x110a10ff,  0x0,  0xf510f46,  0xf540f49,  0xf580f4d,  0x0,  0x11421120,  0x11451123,  0x114e112c,  0x11571135,  0xf880f66,  0xf8b0f69,  0xf940f72,  0xf9d0f7b,  0x119c118d,  0x119f1190,  0x11a31194,  0x11a71198,  0xfcf0fc0,  0xfd20fc3,  0xfd60fc7,  0xfda0fcb,  0x11e311d8,  0x11e611db,  0x11ea11df,  0x0,  0xffb0ff0,  0xffe0ff3,  0x10020ff7,  0x0,  0x122a121b,  0x122d121e,  0x12311222,  0x12351226,  0x10220000,  0x10250000,  0x10290000,  0x102d0000,  0x12741252,  0x12771255,  0x1280125e,  0x12891267,  0x1061103f,  0x10641042,  0x106d104b,  0x10761054,  0x108f1088,  0x10f510f2,  0x11191112,  0x11751172,  0x11d511d2,  0x12031200,  0x124b1244,  0x0,  0x10dc10ba,  0x10c510a3,  0x10ce10ac,  0x10d710b5,  0xf310f0f,  0xf1a0ef8,  0xf230f01,  0xf2c0f0a,  0x1160113e,  0x11491127,  0x11521130,  0x115b1139,  0xfa60f84,  0xf8f0f6d,  0xf980f76,  0xfa10f7f,  0x12921270,  0x127b1259,  0x12841262,  0x128d126b,  0x107f105d,  0x10681046,  0x1071104f,  0x107a1058,  0x10961099,  0x10e7108b,  0x1092,  0x10e310e0,  0xeeb0eee,  0xee80ee5,  0x2a0f35,  0x2a1170,  0x200051,  0x116b1115,  0x111c,  0x11671164,  0xf430f40,  0xf630f60,  0x2d0faa,  0x350031,  0x1178117b,  0x11851181,  0x0,  0x118911ab,  0xfb70fba,  0xfb40fb1,  0x3c0000,  0x440040,  0x12061209,  0x1213120f,  0x11f511f2,  0x12171239,  0x1019101c,  0x10161013,  0x18100a,  0x995001c,  0x0,  0x129d1247,  0x124e,  0x12991296,  0xfed0fea,  0x103c1039,  0x31083,  0x39,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x1,  0x0,  0x0,  0x1a690000,  0x0,  0x0,  0x4e0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2fc02fa,  0x2ff,  0x0,  0x0,  0x0,  0x10000,  0x0,  0x1a6f0000,  0x1a72,  0x1a7e1a7b,  0x0,  0x0,  0x8f,  0xc,  0x0,  0x0,  0x0,  0x5630000,  0x920560,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1a760000,  0x0,  0x0,  0x0,  0x10000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xae00305,  0x0,  0x3740365,  0x3920383,  0x3b003a1,  0x1aad02f4,  0xa10544,  0xb3b00a5,  0x3140305,  0x30f0343,  0x3740365,  0x3920383,  0x3b003a1,  0x1aad02f4,  0xa10544,  0xa5,  0xa7d0692,  0xb410787,  0xb0d0e8c,  0xa280b79,  0xb3b05d3,  0x8400cd3,  0xba3,  0x0,  0x0,  0x0,  0x0,  0x0,  0x83f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x9a2099e,  0xe4d05e3,  0xa1e0000,  0xe770a22,  0xe500000,  0x6ac0602,  0x6ac06ac,  0xe6d0b0d,  0x6cf06cf,  0xa280734,  0x77e0000,  0x786,  0x6af0000,  0x82c083b,  0x82c082c,  0x0,  0x88f0863,  0x897,  0x60a,  0x77c,  0x60a,  0x5b0071a,  0x5e305d5,  0xa7d0000,  0x67e0629,  0x7230000,  0x13540787,  0x136a1362,  0xae0136f,  0x6800000,  0x10ec11ee,  0x10060f3a,  0x1aab,  0x0,  0x5e60000,  0xa7d0a2e,  0x73e0ae0,  0x0,  0x0,  0x0,  0x3e203da,  0x3ca03c1,  0x3d20455,  0x4980459,  0x3d604cf,  0x3de04e7,  0x4eb049c,  0x3be0511,  0x6d106cf,  0x6de06d4,  0x91806b2,  0x91f091b,  0x68206e1,  0x950094d,  0x5e30734,  0x72305e6,  0xb300ae0,  0xb3d0b33,  0xdcf086a,  0xdd60dd2,  0xb410b40,  0xdfd0dfa,  0x9a00a28,  0x5d30a2e,  0x0,  0x0,  0x0,  0x0,  0x30d0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1a8d1a86,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1a92,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1a950000,  0x1a981a9b,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1aa0,  0x0,  0x1aa50000,  0x0,  0x1aa8,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1aaf,  0x1ab2,  0x0,  0x0,  0x1ab81ab5,  0x1ac10000,  0x1ac4,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1ac80000,  0x0,  0x1acb,  0x1ace0000,  0x1ad10000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x556,  0x1ad7,  0x0,  0x0,  0x0,  0x0,  0x1ad40000,  0x55b054a,  0x1add1ada,  0x0,  0x1ae31ae0,  0x0,  0x1ae91ae6,  0x0,  0x0,  0x0,  0x1aef1aec,  0x0,  0x1afb1af8,  0x0,  0x1b011afe,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1b0d1b0a,  0x1b131b10,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1af51af2,  0x1b071b04,  0x0,  0x0,  0x0,  0x1b191b16,  0x1b1f1b1c,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1b350000,  0x1b37,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3430314,  0x365030f,  0x3830374,  0x3a10392,  0x31c03b0,  0x342032f,  0x3640355,  0x3820373,  0x3a00391,  0x3f703af,  0xd900a3,  0xe600e2,  0xee00ea,  0xf600f2,  0xa700fa,  0xb100ac,  0xbb00b6,  0xc500c0,  0xcf00ca,  0xdd00d4,  0x3460319,  0x3680359,  0x3860377,  0x3a40395,  0x31f03b3,  0x3450332,  0x3670358,  0x3850376,  0x3a30394,  0x3fa03b2,  0x16a0166,  0x172016e,  0x17a0176,  0x182017e,  0x18a0186,  0x192018e,  0x19a0196,  0x1a2019e,  0x1aa01a6,  0x1b201ae,  0x1ba01b6,  0x1c201be,  0x1ca01c6,  0x5d50568,  0x5e605e3,  0x67e0629,  0x6ac0687,  0x60706cf,  0x734071a,  0x77e0723,  0x6af07a4,  0x82c083b,  0x88d085e,  0x6b2056b,  0x6820770,  0x60a095a,  0x9370692,  0xa2e09a0,  0xad90a7d,  0xb0d0602,  0x73e0ae0,  0xa280b79,  0xb3b05d3,  0xcd30787,  0xa1105d8,  0xba30840,  0x86a0a24,  0xb410de1,  0x6110695,  0x305,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1abc,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x54f0542,  0x552,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1b2c,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x6b2073e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1b2f0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x227c0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x26b00000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1efb1ee9,  0x1f091f01,  0x1f131f0d,  0x1f1b1f17,  0x1f4b1f21,  0x1f5f1f57,  0x1f6f1f67,  0x1f871f77,  0x1f8b1f89,  0x1fb91fa5,  0x1fc51fc1,  0x1fcd1fc7,  0x1fdd1fdb,  0x1feb1fe9,  0x1ff71fef,  0x204f2045,  0x2079206f,  0x207f207d,  0x20982087,  0x20b420ae,  0x20ca20c4,  0x20ce20cc,  0x20dc20da,  0x20f820f2,  0x210020fc,  0x210f2108,  0x21292113,  0x212f212b,  0x21352131,  0x21412139,  0x218b214f,  0x21972195,  0x21d921d7,  0x21e521e3,  0x21ed21e9,  0x32521f1,  0x3292211,  0x22602223,  0x226e2266,  0x227a2274,  0x2280227e,  0x22842282,  0x22e22286,  0x230c2306,  0x2310230e,  0x23162312,  0x23222318,  0x23342330,  0x23562354,  0x235c235a,  0x23622360,  0x23762374,  0x23862384,  0x238a2388,  0x23a62394,  0x23aa23a8,  0x23dc23bc,  0x23ee23de,  0x23fa23f6,  0x241c240a,  0x2442243e,  0x2452244c,  0x245a2456,  0x245e245c,  0x246c246a,  0x247e247a,  0x24842482,  0x248e248a,  0x24922490,  0x24982496,  0x24f224e8,  0x250e250c,  0x25282512,  0x2530252c,  0x25522534,  0x25582554,  0x255c255a,  0x25742572,  0x25822578,  0x25922584,  0x25982596,  0x25ba25aa,  0x25c425c2,  0x25de25c8,  0x25e825e0,  0x260025fa,  0x26142608,  0x261a2618,  0x261e261c,  0x26262624,  0x2638262a,  0x263c263a,  0x264a2648,  0x2658264e,  0x265c265a,  0x26622660,  0x26662664,  0x26702668,  0x267e267c,  0x26862684,  0x268a2688,  0x2690268e,  0x26982692,  0x26a0269c,  0x26a626a2,  0x26aa26a8,  0x26b226ae,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1b49,  0x1fcf1fcd,  0x1fd1,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1b7e,  0x1b81,  0x1b84,  0x1b87,  0x1b8a,  0x1b8d,  0x1b90,  0x1b93,  0x1b96,  0x1b99,  0x1b9c,  0x1b9f,  0x1ba20000,  0x1ba50000,  0x1ba80000,  0x0,  0x0,  0x0,  0x1bae1bab,  0x1bb10000,  0x1bb4,  0x1bba1bb7,  0x1bbd0000,  0x1bc0,  0x1bc91bc6,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1b7b,  0x0,  0x0,  0x870000,  0x8a,  0x1bcc1bd3,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1c26,  0x1c43,  0x1bf6,  0x1c92,  0x1c9b,  0x1caf,  0x1cbf,  0x1cca,  0x1ccf,  0x1cdc,  0x1ce1,  0x1ceb,  0x1cf20000,  0x1cf70000,  0x1c100000,  0x0,  0x0,  0x0,  0x1d261d1d,  0x1d3b0000,  0x1d42,  0x1d611d57,  0x1d760000,  0x1d7e,  0x1caa1da1,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1c01,  0x1e440000,  0x1e521e4d,  0x1e57,  0x0,  0x1ca11e60,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x19440000,  0x1a101949,  0x1a12194b,  0x19501a14,  0x19571955,  0x1a181a16,  0x1a1c1a1a,  0x1a201a1e,  0x195c19a6,  0x19661961,  0x196819b0,  0x196f196d,  0x19811977,  0x198e1983,  0x19981993,  0x1947199d,  0x19da19d8,  0x19de19dc,  0x19e219e0,  0x198c19e4,  0x19ea19e8,  0x19ee19ec,  0x19f21975,  0x19f619f4,  0x19fa19f8,  0x19fe197f,  0x19a219d4,  0x1a2219a4,  0x1a261a24,  0x1a2a1a28,  0x1a2e1a2c,  0x1a3019a8,  0x19aa1a32,  0x19ae19ac,  0x19b419b2,  0x19b819b6,  0x19bc19ba,  0x19c019be,  0x19c419c2,  0x19c819c6,  0x19cc19ca,  0x1a361a34,  0x19d019ce,  0x1a0019d2,  0x1a041a02,  0x1a081a06,  0x1a0c1a0a,  0x1a0e,  0x0,  0x1f171ee9,  0x20471eef,  0x1efd1ef1,  0x23641ef3,  0x1ef71f0d,  0x208c1eeb,  0x1f212051,  0x1d701ce,  0x1e901e0,  0x1fb01f2,  0x20d0204,  0x2330225,  0x245023c,  0x257024e,  0x1db01d2,  0x1ed01e4,  0x1ff01f6,  0x2110208,  0x2370229,  0x2490240,  0x25b0252,  0x216022e,  0x21e,  0x2700260,  0x2a00268,  0x2880274,  0x2840264,  0x290026c,  0x2c402b0,  0x2b802c0,  0x2a402ec,  0x2bc02ac,  0x2d002b4,  0x2c80298,  0x2d402e4,  0x278028c,  0x2a8029c,  0x27c02cc,  0x29402e8,  0x28002d8,  0x2e002dc,  0x21112021,  0x23fe21e3,  0x0,  0x0,  0x0,  0x0,  0x406082e,  0x41c0411,  0x4320427,  0x4400439,  0x44e0447,  0x475046e,  0x47f047c,  0x4850482,  0x194b1944,  0x19571950,  0x1961195c,  0x196f1968,  0x19831977,  0x1993198e,  0x199d1998,  0x194d1946,  0x19591952,  0x1963195e,  0x1971196a,  0x19851979,  0x19951990,  0x199f199a,  0x197c1988,  0x1974,  0x1f171ee9,  0x20471eef,  0x1f611f19,  0x1f5f1eed,  0x1fcd1f0f,  0x22e20329,  0x22232286,  0x204f25c8,  0x223b0325,  0x2240221b,  0x231c2007,  0x23ca255e,  0x23e21fab,  0x20982368,  0x1f4925a2,  0x22961fdf,  0x1f2b262c,  0x208a1f73,  0x1efd1ef1,  0x20fa1ef3,  0x1fc92001,  0x20b220b8,  0x1f292390,  0x1fd72568,  0x4882083,  0x48e048b,  0x4b10491,  0x4b704b4,  0x4bd04ba,  0x4c304c0,  0x4c904c6,  0x4e404cc,  0x34e033b,  0x4d604a3,  0x50304f2,  0x5290518,  0x327053a,  0x34d033a,  0xa8206b4,  0x7390a7f,  0x1bf11bd8,  0x1c0a1bff,  0x1c241c1a,  0x1c731c41,  0x1c991c90,  0x1cbd1cad,  0x1ccd1c1e,  0x1cdf1cda,  0x1cf01bfb,  0x1bde1cf5,  0x1d0f1ca6,  0x1c8e1d11,  0x1d1b1d0d,  0x1d551d39,  0x1d9f1d74,  0x1ddc1c31,  0x1def1c22,  0x1e041e00,  0x1e191e11,  0x1c351e1b,  0x1e341bed,  0x1e421c5d,  0x1e501e4b,  0x1e55,  0x1be01bda,  0x1beb1be5,  0x1bf91bf3,  0x1c0c1c04,  0x1c1c1c13,  0x1c331c20,  0x1c3c1c37,  0x1c2e1c29,  0x1c4b1c46,  0x1c501c57,  0x1c5f1c5c,  0x1c6d1c66,  0x1c7d1c61,  0x1c8b1c84,  0x1ca41c95,  0x1cb21ca8,  0x1cc21cb7,  0x1cd61cd2,  0x1cfa1ce4,  0x1c811d03,  0x1d171d0c,  0x1d291d35,  0x1d201d30,  0x1d4c1d45,  0x1d3e1d51,  0x1d6b1d64,  0x1d701d5a,  0x1d811d95,  0x1d9b1d85,  0x1d8f1d8a,  0x1dac1d79,  0x1db81da4,  0x1dbb1db2,  0x1dc51dbf,  0x1dce1dca,  0x1dd61dd2,  0x1de31dde,  0x1df11de6,  0x1c681df5,  0x1e0b1e06,  0x1e1f1e13,  0x1e291e24,  0x1e361e2e,  0x1c6f1e39,  0x33f0311,  0x3610352,  0x37f0370,  0x39d038e,  0x3bb03ac,  0x33e032b,  0x3600351,  0x37e036f,  0x39c038d,  0x3ba03ab,  0x40d0402,  0x4230418,  0xb0f042e,  0x56a0a53,  0xc580a0f,  0xa590ce6,  0xa600a5c,  0x210a06db,  0x20892200,  0x223d21f9,  0xc260cda,  0xbea11b4,  0x71c0b7b,  0x689075b,  0xb8c0a26,  0xc290cdd,  0x11c011b7,  0x6010bf6,  0xb7e068d,  0x68c0764,  0x11c30893,  0xa560bfd,  0xaec0b94,  0x11c60c35,  0xa300c00,  0xc030b97,  0xa340a33,  0xc070b9a,  0xa380a37,  0xc1b0b9e,  0x6910c1f,  0x7680b82,  0xcf60690,  0xd000cfa,  0xc380ce9,  0xc0f11c9,  0xc2c0ce0,  0xbed11ba,  0x76c0b86,  0xc2f0ce3,  0xbf011bd,  0x76f0b89,  0x77b0bb4,  0x5d70999,  0xa2d0a2a,  0x5e805ff,  0x6940a50,  0x6ae0b13,  0x71f0b3a,  0xba20722,  0xbbf0bbc,  0xbc60bc2,  0xbf90bf3,  0x8200c0b,  0x8230cd5,  0xd25082b,  0x9360869,  0x5d1092a,  0x34a0337,  0x36c035d,  0x38a037b,  0x3a80399,  0x32303b7,  0x3490336,  0x36b035c,  0x389037a,  0x3a70398,  0x3fe03b6,  0x4140409,  0x42a041f,  0x43c0435,  0x44a0443,  0x4710451,  0xaf40478,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x26b4,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe730e6b,  0x0,  0x0,  0x0,  0x22132556,  0x256a2584,  0x1eff22c6,  0x26ae1ff9,  0x209226ae,  0x202b25c8,  0x21872090,  0x244a2382,  0x250424e6,  0x25a8251e,  0x229a2254,  0x233c22f0,  0x25bc24ca,  0x1f112652,  0x225e1fe3,  0x24e42302,  0x20e6267a,  0x24dc22d6,  0x21a12526,  0x250a2478,  0x221d211f,  0x232822a6,  0x1f3125ae,  0x1fb31f7d,  0x225a21d5,  0x23922300,  0x24e02456,  0x257e24ec,  0x266a2610,  0x23b02678,  0x242c23d0,  0x25d624bc,  0x2540267e,  0x212d206d,  0x24682408,  0x23b4231a,  0x260c2566,  0x20d4206b,  0x22b02256,  0x242422ca,  0x25ec2438,  0x246e1fb1,  0x1f811f83,  0x242e23e6,  0x25f024c8,  0x21a3254e,  0x25462254,  0x20be1f05,  0x23322159,  0x1fc32372,  0x1f3923b8,  0x1ef5214b,  0x21e12290,  0x1fed2422,  0x23982063,  0x253824cc,  0x25962276,  0x21ab228c,  0x21bb24a8,  0x1f1f2370,  0x1f7f1f5d,  0x24182244,  0x253e2494,  0x1fb725c6,  0x20982011,  0x21ef2127,  0x23ba22d8,  0x265625e4,  0x268c2680,  0x220f1fa5,  0x2590226c,  0x217b210d,  0x21d12189,  0x22f622d0,  0x23e0234e,  0x24642432,  0x24d02588,  0x25d8259c,  0x1fa71f91,  0x22ee201b,  0x25382514,  0x2155211d,  0x227221b7,  0x232c2406,  0x20491f27,  0x20f020be,  0x233a215b,  0x24502348,  0x25ca2460,  0x2612260a,  0x1f332630,  0x25c023da,  0x216725fe,  0x1f451f15,  0x20d020c0,  0x225421e7,  0x238022fc,  0x25a624d6,  0x220726aa,  0x1fa325ea,  0x2233222d,  0x22be22a2,  0x236e2340,  0x242023ae,  0x1f612636,  0x25f22191,  0x20e21f3d,  0x258a22b2,  0x216b2143,  0x23322237,  0x1f9525f6,  0x20d82009,  0x222521fc,  0x2294224a,  0x2378233e,  0x25162446,  0x25c4251c,  0x1fcb2604,  0x200b22c0,  0x235022fe,  0x25f824de,  0x2682266e,  0x22ae2231,  0x23f6247c,  0x240e23fc,  0x22ea2326,  0x1f23254c,  0x1f9724b0,  0x21151f8f,  0x241421a5,  0x229c20b6,  0x258e220d,  0x25ee250e,  0x2123252c,  0x20371f4d,  0x0,  0x2061,  0x2205,  0x1f850000,  0x238c232a,  0x23cc23be,  0x23d823ce,  0x24102616,  0x2452,  0x24e2,  0x2544,  0x259e0000,  0x25b4,  0x0,  0x26422640,  0x26762644,  0x25fc25b0,  0x1f471f35,  0x1faf1f51,  0x1fd51fb5,  0x203d202f,  0x205f2041,  0x20d62065,  0x216120da,  0x21792175,  0x21db2185,  0x220921f3,  0x22a82246,  0x22ce22b6,  0x230822f8,  0x23b22342,  0x23c42240,  0x23c623c2,  0x23ca23c8,  0x23d623d4,  0x23f223e8,  0x24322400,  0x243a2436,  0x24582444,  0x249a2480,  0x24ce249a,  0x252e2522,  0x254a2548,  0x256e256c,  0x259e259a,  0x26282606,  0x215d2634,  0x248c274b,  0x0,  0x1f7b1ef9,  0x1f2f1f5b,  0x1f651f4f,  0x1fbb1fad,  0x2025202f,  0x203b202d,  0x20692061,  0x2094208e,  0x20aa20a2,  0x21252121,  0x214d213d,  0x21712165,  0x21792169,  0x21852173,  0x21bf2193,  0x21c921c5,  0x220521dd,  0x221f221d,  0x226e2229,  0x22a22276,  0x22c422c8,  0x22dc22ce,  0x23a422f8,  0x2324230a,  0x234a232a,  0x236a2358,  0x237e237c,  0x238e238c,  0x23a02396,  0x23b6239e,  0x240023f4,  0x2428240c,  0x24402432,  0x24b22458,  0x250024c6,  0x252a2524,  0x253a252e,  0x253c2544,  0x25462548,  0x254a2542,  0x256e2550,  0x25a4258c,  0x25ce25be,  0x260625f4,  0x26202616,  0x262e2628,  0x265e2634,  0x272126ae,  0x2733271f,  0x1ea11e8d,  0x27671ea3,  0x27a92779,  0x26ac26a4,  0x0,  0x0,  0x0,  0xadf0adb,  0xade0ae3,  0xd280ae2,  0xd28,  0x0,  0x0,  0x0,  0x0,  0x0,  0x134e0000,  0x13481345,  0x134b1351,  0x0,  0x0,  0x13850000,  0x13d20000,  0x135413a6,  0x1374136f,  0x1360138e,  0x13b7139b,  0x2f413cd,  0x13ca13c7,  0x13c313bf,  0x13591356,  0x1364135c,  0x1371136c,  0x137c1376,  0x137f,  0x13881382,  0x1390138b,  0x1398,  0x139d,  0x13a313a0,  0x13a80000,  0x13ab,  0x13b413b1,  0x13bc13b9,  0x137913cf,  0x13931367,  0x135f13ae,  0x18181818,  0x181e181e,  0x181e181e,  0x18201820,  0x18201820,  0x18241824,  0x18241824,  0x181c181c,  0x181c181c,  0x18221822,  0x18221822,  0x181a181a,  0x181a181a,  0x183c183c,  0x183c183c,  0x183e183e,  0x183e183e,  0x18281828,  0x18281828,  0x18261826,  0x18261826,  0x182a182a,  0x182a182a,  0x182c182c,  0x182c182c,  0x18321832,  0x18301830,  0x18341834,  0x182e182e,  0x18381838,  0x18361836,  0x18401840,  0x18401840,  0x18441844,  0x18441844,  0x18481848,  0x18481848,  0x18461846,  0x18461846,  0x184a184a,  0x184c184c,  0x184c184c,  0x186d186d,  0x18501850,  0x18501850,  0x184e184e,  0x184e184e,  0x15911591,  0x186a186a,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18420000,  0x18421842,  0x18031842,  0x17ff1803,  0x180717ff,  0x185b1807,  0x18621862,  0x18551855,  0x18601860,  0x180b180b,  0x180b180b,  0x14151415,  0x17cd17cd,  0x180d180d,  0x17f117f1,  0x18011801,  0x17fd17fd,  0x18051805,  0x18091809,  0x17f51809,  0x17f517f5,  0x18641864,  0x18641864,  0x17d517d1,  0x17f517e5,  0x13f417f9,  0x13fe13f7,  0x1414140b,  0x141e1417,  0x1438142d,  0x146a144d,  0x1472146d,  0x1484147b,  0x148c1487,  0x14311422,  0x14d11435,  0x143c14d4,  0x150514fa,  0x151a150c,  0x15931562,  0x15a515a2,  0x15ba15b0,  0x15c815c5,  0x15e415df,  0x16071575,  0x163f160a,  0x16451642,  0x1653164c,  0x165b1656,  0x16711662,  0x16791674,  0x167f167c,  0x16851682,  0x16931688,  0x16aa1696,  0x16c816b9,  0x1579158c,  0x145116e0,  0x14591455,  0x145d1526,  0x172d1461,  0x174f1740,  0x17691758,  0x1771176c,  0x177f1774,  0x179c1782,  0x17aa17a3,  0x17c417b3,  0x14e417c7,  0x179714ee,  0x64005d,  0x72006b,  0x800079,  0x17e117dd,  0x17e917e5,  0x17f917f5,  0x140813db,  0x140e140b,  0x14171414,  0x144a1447,  0x1464144d,  0x146d146a,  0x14781475,  0x147e147b,  0x14871484,  0x16561653,  0x16741671,  0x16851679,  0x16931688,  0x158c1696,  0x16e01579,  0x152616e5,  0x17551752,  0x17631758,  0x176c1769,  0x17ad1797,  0x17b317b0,  0x17c417be,  0x17d117c7,  0x17d917d5,  0x17ed17e5,  0x13f713f4,  0x140b13fe,  0x141e1411,  0x1438142d,  0x1467144d,  0x148c147b,  0x14311422,  0x14d11435,  0x14fa143c,  0x150c1505,  0x1562151a,  0x1593156d,  0x15a515a2,  0x15ba15b0,  0x15df15c5,  0x157515e4,  0x160a1607,  0x1642163f,  0x164c1645,  0x1662165b,  0x167f167c,  0x16851682,  0x16aa1688,  0x16c816b9,  0x13e0158c,  0x14551451,  0x15261459,  0x1740172d,  0x1758174f,  0x17711766,  0x17851774,  0x17a3179c,  0x17b317aa,  0x17e515ed,  0x140b17ed,  0x144d1411,  0x147b1467,  0x151a1481,  0x154c1529,  0x16851557,  0x158c1688,  0x17661758,  0x15ed17b3,  0x162c1625,  0x15d71633,  0x15ff15da,  0x16191602,  0x152c161c,  0x155a152f,  0x1490155d,  0x142613fb,  0x1440142a,  0x159a1402,  0x15bd159d,  0x153415c0,  0x1546153b,  0x1549154c,  0x15701517,  0x15d715b7,  0x15ff15da,  0x16191602,  0x152c161c,  0x155a152f,  0x1490155d,  0x142613fb,  0x1440142a,  0x159a1402,  0x15bd159d,  0x153415c0,  0x1546153b,  0x1549154c,  0x15701517,  0x153415b7,  0x1546153b,  0x1529154c,  0x15c81557,  0x150514fa,  0x1534150c,  0x1546153b,  0x15df15c8,  0x13e313e3,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x14301421,  0x14341430,  0x1450143b,  0x14581454,  0x14a314a3,  0x14c114c5,  0x14fd1508,  0x15211501,  0x151d1521,  0x15251525,  0x15651565,  0x153e1596,  0x1537153e,  0x154f154f,  0x15531553,  0x15b315a8,  0x15cb15b3,  0x15cf15cb,  0x15e715d3,  0x15f315f3,  0x160d15f7,  0x16111615,  0x16481648,  0x16691665,  0x16c416bc,  0x16ad16c0,  0x16cb16ad,  0x16d216cb,  0x16fe16d2,  0x170b1702,  0x16f316eb,  0x17161712,  0x0,  0x177716ef,  0x1743177b,  0x17341747,  0x17381734,  0x175b175f,  0x17b617b6,  0x14291401,  0x14431425,  0x1460143f,  0x14ab145c,  0x14a7148f,  0x1569150f,  0x15ac1542,  0x16d616b5,  0x179f17a6,  0x172117ba,  0x174b166d,  0x16bc1665,  0x168f15fb,  0x171a1730,  0x168b16b1,  0x173016b1,  0x14ba1493,  0x164f16f7,  0x168b13fa,  0x159615e7,  0x173c1513,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x165e158f,  0x13d913de,  0x15731706,  0x15eb14e9,  0x1578158a,  0x1497157c,  0x14f1,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1b3102f6,  0x5401b33,  0x8d0546,  0x1b770093,  0x2ff1b79,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1a6d02fc,  0x9931a6b,  0xa10993,  0xe3b00a5,  0x1b4b0e3f,  0x1b451b4f,  0x1b391b47,  0x1b351b3b,  0x1b3d1b37,  0x1b411b3f,  0x1b43,  0x98b0000,  0xc098f,  0xc000c,  0x993000c,  0x9930993,  0x1b3102f6,  0x2fa,  0x5400546,  0x8d0093,  0xa11a6d,  0xe3b00a5,  0x1b4b0e3f,  0x971b4f,  0x2f2009d,  0x2f802f4,  0x5590548,  0x544,  0x99098d,  0x566009b,  0x0,  0x0,  0x161f0057,  0x5a,  0x61,  0x16220068,  0x1629006f,  0x16300076,  0x1637007d,  0x163a0084,  0x13e613d5,  0x13e913e6,  0x178f13e9,  0x13ec178f,  0x17ca13ec,  0x17ca17ca,  0x13d717ca,  0x13f213d7,  0x13f213f2,  0x141a13f2,  0x141c141a,  0x141c141c,  0x1470141c,  0x14701470,  0x13f51470,  0x13f513f5,  0x13f813f5,  0x13f813f8,  0x13ff13f8,  0x13ff13ff,  0x14e013ff,  0x14e214e0,  0x13dc14e2,  0x140913dc,  0x14f81409,  0x14f814f8,  0x153214f8,  0x15321532,  0x15601532,  0x15601560,  0x15a01560,  0x15a015a0,  0x15c315a0,  0x15c315c3,  0x15dd15c3,  0x15dd15dd,  0x15e215dd,  0x15e215e2,  0x160515e2,  0x16051605,  0x163d1605,  0x163d163d,  0x1659163d,  0x16591659,  0x16771659,  0x16771677,  0x14ec1677,  0x14ec14ec,  0x140c14ec,  0x140c140c,  0x140f140c,  0x140f140f,  0x13e1140f,  0x13e113e1,  0x178813e1,  0x14151788,  0x13fc1415,  0x13fc13fc,  0x169e13fc,  0x16a2169e,  0x16a616a2,  0x169b16a6,  0x169b,  0x0,  0x8d0000,  0x970095,  0x9b0099,  0x9f009d,  0xa500a1,  0x2f402f2,  0x2f802f6,  0x30302fa,  0x3140305,  0x30f0343,  0x3740365,  0x3920383,  0x3b003a1,  0x5460540,  0x5440548,  0x930559,  0x5680566,  0x5e305d5,  0x62905e6,  0x687067e,  0x6cf06ac,  0x71a0607,  0x7230734,  0x7a4077e,  0x83b06af,  0x85e082c,  0x56b088d,  0x77006b2,  0x95a0682,  0x98b060a,  0x98f098d,  0x9930991,  0x6920995,  0x9a00937,  0xa7d0a2e,  0x6020ad9,  0xae00b0d,  0xb79073e,  0x5d30a28,  0x7870b3b,  0x5d80cd3,  0x8400a11,  0xa240ba3,  0xde1086a,  0x6950b41,  0xe3b0611,  0xe3f0e3d,  0x1b280e41,  0x1b331b2a,  0x1b3f1b3d,  0x1e5c1b31,  0x1bd61e55,  0x1bfd1bef,  0x1c181c08,  0x1e0f1e02,  0x1cee1e17,  0x1bd81c16,  0x1bff1bf1,  0x1c1a1c0a,  0x1c411c24,  0x1c901c73,  0x1cad1c99,  0x1c1e1cbd,  0x1cda1ccd,  0x1bfb1cdf,  0x1cf51cf0,  0x1ca61bde,  0x1d111d0f,  0x1d0d1c8e,  0x1d391d1b,  0x1d741d55,  0x1c311d9f,  0x1c221ddc,  0x1e001def,  0x1e111e04,  0x1e1b1e19,  0x1bed1c35,  0x1c5d1e34,  0x1c061e42,  0x8b0088,  0x194419d4,  0x1a101949,  0x1a12194b,  0x19501a14,  0x19571955,  0x1a181a16,  0x1a1c1a1a,  0x1a201a1e,  0x195c19a6,  0x19661961,  0x196819b0,  0x196f196d,  0x19811977,  0x198e1983,  0x19981993,  0x199d,  0x0,  0x19d81947,  0x19dc19da,  0x19e019de,  0x0,  0x19e419e2,  0x19e8198c,  0x19ec19ea,  0x0,  0x197519ee,  0x19f419f2,  0x19f819f6,  0x0,  0x197f19fa,  0x19fe,  0x0,  0xe450e43,  0x90e4b,  0xe470e49,  0x1a82,  0x1a841b22,  0x1a8b1a89,  0x1b241a90,  0x1b26,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x26b6,  0x26b9,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x26bc0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x26c226bf,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x26c826c5,  0x26cf26cb,  0x26d726d3,  0x26db,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x26df0000,  0x26e226ea,  0x26e626ed,  0x26f1,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x5d50568,  0x5e605e3,  0x67e0629,  0x6ac0687,  0x60706cf,  0x734071a,  0x77e0723,  0x6af07a4,  0x82c083b,  0x88d085e,  0x6b2056b,  0x6820770,  0x60a095a,  0x9370692,  0xa2e09a0,  0xad90a7d,  0xb0d0602,  0x73e0ae0,  0xa280b79,  0xb3b05d3,  0xcd30787,  0xa1105d8,  0xba30840,  0x86a0a24,  0xb410de1,  0x6110695,  0x5d50568,  0x5e605e3,  0x67e0629,  0x6ac0687,  0x60706cf,  0x734071a,  0x77e0723,  0x6af07a4,  0x82c083b,  0x88d085e,  0x6b2056b,  0x6820770,  0x60a095a,  0x9370692,  0xa2e09a0,  0xad90a7d,  0x602,  0x73e0ae0,  0xa280b79,  0xb3b05d3,  0xcd30787,  0xa1105d8,  0xba30840,  0x86a0a24,  0xb410de1,  0x6110695,  0x5d50568,  0x5e605e3,  0x67e0629,  0x6ac0687,  0x60706cf,  0x734071a,  0x77e0723,  0x6af07a4,  0x82c083b,  0x88d085e,  0x6b2056b,  0x6820770,  0x60a095a,  0x9370692,  0xa2e09a0,  0xad90a7d,  0xb0d0602,  0x73e0ae0,  0xa280b79,  0xb3b05d3,  0xcd30787,  0xa1105d8,  0xba30840,  0x86a0a24,  0xb410de1,  0x6110695,  0x568,  0x5e605e3,  0x0,  0x687,  0x6070000,  0x71a,  0x77e0000,  0x6af07a4,  0x83b,  0x88d085e,  0x6b2056b,  0x6820770,  0x60a095a,  0x9370692,  0xa2e09a0,  0xad90000,  0xb0d0000,  0x73e0ae0,  0xa280b79,  0xb3b05d3,  0xcd30000,  0xa1105d8,  0xba30840,  0x86a0a24,  0xb410de1,  0x6110695,  0x5d50568,  0x5e605e3,  0x67e0629,  0x6ac0687,  0x60706cf,  0x734071a,  0x77e0723,  0x6af07a4,  0x82c083b,  0x88d085e,  0x6b2056b,  0x6820770,  0x60a095a,  0x9370692,  0xa2e09a0,  0xad90a7d,  0xb0d0602,  0x73e0ae0,  0xa280b79,  0xb3b05d3,  0xcd30787,  0xa1105d8,  0xba30840,  0x86a0a24,  0xb410de1,  0x6110695,  0x5d50568,  0x5e60000,  0x67e0629,  0x687,  0x6070000,  0x734071a,  0x77e0723,  0x6af07a4,  0x83b,  0x88d085e,  0x6b2056b,  0x6820770,  0x95a,  0x9370692,  0xa2e09a0,  0xad90a7d,  0xb0d0602,  0x73e0ae0,  0xa280b79,  0xb3b05d3,  0xcd30787,  0xa1105d8,  0xba30840,  0x86a0a24,  0xb410de1,  0x6110695,  0x5d50568,  0x5e60000,  0x67e0629,  0x687,  0x60706cf,  0x734071a,  0x723,  0x7a4,  0x0,  0x88d085e,  0x6b2056b,  0x6820770,  0x95a,  0x9370692,  0xa2e09a0,  0xad90a7d,  0xb0d0602,  0x73e0ae0,  0xa280b79,  0xb3b05d3,  0xcd30787,  0xa1105d8,  0xba30840,  0x86a0a24,  0xb410de1,  0x6110695,  0x5d50568,  0x5e605e3,  0x67e0629,  0x6ac0687,  0x60706cf,  0x734071a,  0x77e0723,  0x6af07a4,  0x82c083b,  0x88d085e,  0x6b2056b,  0x6820770,  0x60a095a,  0x9370692,  0xa2e09a0,  0xad90a7d,  0xb0d0602,  0x73e0ae0,  0xa280b79,  0xb3b05d3,  0xcd30787,  0xa1105d8,  0xba30840,  0x86a0a24,  0xb410de1,  0x6110695,  0x77e0723,  0x6af07a4,  0x82c083b,  0x88d085e,  0x6b2056b,  0x6820770,  0x60a095a,  0x9370692,  0xa2e09a0,  0xad90a7d,  0xb0d0602,  0x73e0ae0,  0xa280b79,  0xb3b05d3,  0xcd30787,  0xa1105d8,  0x60a095a,  0x9370692,  0xa2e09a0,  0xad90a7d,  0xb0d0602,  0x73e0ae0,  0xa280b79,  0xb3b05d3,  0xcd30787,  0xa1105d8,  0xba30840,  0x86a0a24,  0xb410de1,  0x6110695,  0x5d50568,  0x5e605e3,  0x67e0629,  0x6ac0687,  0x60706cf,  0x734071a,  0x77e0723,  0x6af07a4,  0x82c083b,  0x88d085e,  0x6b2056b,  0x6820770,  0x60a095a,  0x9370692,  0xa2e09a0,  0xad90a7d,  0xb0d0602,  0x73e0ae0,  0xa280b79,  0xb3b05d3,  0xcd30787,  0xa1105d8,  0xba30840,  0x86a0a24,  0xb410de1,  0x6110695,  0x5d50568,  0x5e605e3,  0x67e0629,  0x6ac0687,  0x60706cf,  0x734071a,  0x77e0723,  0x6af07a4,  0xb410de1,  0x6110695,  0xe800e6f,  0x0,  0xf380ee3,  0xf3c0f3a,  0xf5c0f3e,  0xfad0f5e,  0xfde0faf,  0xfe20fe0,  0xfe60fe4,  0x10060fe8,  0xfad1008,  0x100f100d,  0x10311011,  0x10351033,  0x1aa3077c,  0x10ea1086,  0x10ee10ec,  0x110e10f0,  0x116e1110,  0x11ae1170,  0x11b211b0,  0x11ce11cc,  0x11ee11d0,  0x11f811f0,  0x11fc11fa,  0x123c11fe,  0x1240123e,  0x1a9e1242,  0x116e10f0,  0x123c11ae,  0x11ee11f0,  0xf380ee3,  0xf3c0f3a,  0xf5c0f3e,  0xfad0f5e,  0xfde0faf,  0xfe20fe0,  0xfe60fe4,  0x10060fe8,  0xfad1008,  0x100f100d,  0x10311011,  0x10351033,  0x1aa3077c,  0x10ea1086,  0x10ee10ec,  0x110e10f0,  0x116e1110,  0x11ae1170,  0x11b211b0,  0x11ce11cc,  0x11ee11d0,  0x11f811f0,  0x11fc11fa,  0x123c11fe,  0x1240123e,  0x1a9e1242,  0x116e10f0,  0x123c11ae,  0x11ee11f0,  0xf380ee3,  0xf3c0f3a,  0xf5c0f3e,  0xfad0f5e,  0xfde0faf,  0xfe20fe0,  0xfe60fe4,  0x10060fe8,  0xfad1008,  0x100f100d,  0x10311011,  0x10351033,  0x1aa3077c,  0x10ea1086,  0x10ee10ec,  0x110e10f0,  0x116e1110,  0x11ae1170,  0x11b211b0,  0x11ce11cc,  0x11ee11d0,  0x11f811f0,  0x11fc11fa,  0x123c11fe,  0x1240123e,  0x1a9e1242,  0x116e10f0,  0x123c11ae,  0x11ee11f0,  0xf380ee3,  0xf3c0f3a,  0xf5c0f3e,  0xfad0f5e,  0xfde0faf,  0xfe20fe0,  0xfe60fe4,  0x10060fe8,  0xfad1008,  0x100f100d,  0x10311011,  0x10351033,  0x1aa3077c,  0x10ea1086,  0x10ee10ec,  0x110e10f0,  0x116e1110,  0x11ae1170,  0x11b211b0,  0x11ce11cc,  0x11ee11d0,  0x11f811f0,  0x11fc11fa,  0x123c11fe,  0x1240123e,  0x1a9e1242,  0x116e10f0,  0x123c11ae,  0x11ee11f0,  0xf380ee3,  0xf3c0f3a,  0xf5c0f3e,  0xfad0f5e,  0xfde0faf,  0xfe20fe0,  0xfe60fe4,  0x10060fe8,  0xfad1008,  0x100f100d,  0x10311011,  0x10351033,  0x1aa3077c,  0x10ea1086,  0x10ee10ec,  0x110e10f0,  0x116e1110,  0x11ae1170,  0x11b211b0,  0x11ce11cc,  0x11ee11d0,  0x11f811f0,  0x11fc11fa,  0x123c11fe,  0x1240123e,  0x1a9e1242,  0x116e10f0,  0x123c11ae,  0x11ee11f0,  0x12a212a0,  0x0,  0x3140305,  0x30f0343,  0x3740365,  0x3920383,  0x3b003a1,  0x3140305,  0x30f0343,  0x3740365,  0x3920383,  0x3b003a1,  0x3140305,  0x30f0343,  0x3740365,  0x3920383,  0x3b003a1,  0x3140305,  0x30f0343,  0x3740365,  0x3920383,  0x3b003a1,  0x3140305,  0x30f0343,  0x3740365,  0x3920383,  0x3b003a1,  0x13f213d7,  0x14e013f5,  0x17880000,  0x13f81409,  0x13fc15c3,  0x14ec1677,  0x140f140c,  0x15e214f8,  0x1560163d,  0x13dc1659,  0x141c1532,  0x13ff1470,  0x15a014e2,  0x160515dd,  0x184a1814,  0x1816183a,  0x13f20000,  0x13f5,  0x13e1,  0x13f80000,  0x13fc0000,  0x14ec1677,  0x140f140c,  0x15e214f8,  0x1560163d,  0x1659,  0x141c1532,  0x13ff1470,  0x15a00000,  0x16050000,  0x0,  0x0,  0x0,  0x13f5,  0x0,  0x13f80000,  0x13fc0000,  0x14ec0000,  0x140f0000,  0x15e214f8,  0x15600000,  0x1659,  0x1532,  0x13ff0000,  0x15a00000,  0x16050000,  0x184a0000,  0x18160000,  0x13f20000,  0x13f5,  0x13e1,  0x13f80000,  0x13fc15c3,  0x1677,  0x140f140c,  0x15e214f8,  0x1560163d,  0x1659,  0x141c1532,  0x13ff1470,  0x15a00000,  0x160515dd,  0x1814,  0x183a,  0x13f213d7,  0x14e013f5,  0x178813e1,  0x13f81409,  0x13fc15c3,  0x14ec0000,  0x140f140c,  0x15e214f8,  0x1560163d,  0x13dc1659,  0x141c1532,  0x13ff1470,  0x15a014e2,  0x160515dd,  0x0,  0x0,  0x13f20000,  0x14e013f5,  0x17880000,  0x13f81409,  0x13fc15c3,  0x14ec0000,  0x140f140c,  0x15e214f8,  0x1560163d,  0x13dc1659,  0x141c1532,  0x13ff1470,  0x15a014e2,  0x160515dd,  0x0,  0x0,  0x307030a,  0x3f10316,  0x4ab0468,  0x4fa04de,  0x520050b,  0x531,  0x0,  0x0,  0x10200fe,  0x10a0106,  0x112010e,  0x11a0116,  0x122011e,  0x12a0126,  0x132012e,  0x13a0136,  0x142013e,  0x14a0146,  0x152014e,  0x15a0156,  0x162015e,  0x5e31b4d,  0x5e5082c,  0x933,  0x5d50568,  0x5e605e3,  0x67e0629,  0x6ac0687,  0x60706cf,  0x734071a,  0x77e0723,  0x6af07a4,  0x82c083b,  0x88d085e,  0x6b2056b,  0x6820770,  0x60a095a,  0x76c06b1,  0x8660860,  0x9300827,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x761075e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x606,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1c9e1bc3,  0x1cad,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x20b02197,  0x1cf71ff3,  0x20811f17,  0x208c2532,  0x21fe1f1d,  0x21e722f2,  0x21451f9d,  0x21eb1f69,  0x24261f93,  0x2560235c,  0x200f2073,  0x219d22cc,  0x1ee921b3,  0x25a01eef,  0x1efd20fa,  0x21ad2001,  0x21992574,  0x23f023d2,  0x22bc2005,  0x329221b,  0x1f9f2366,  0x2035,  0x0,  0x0,  0x1b511b69,  0x1b5d1b55,  0x1b611b6d,  0x1b591b71,  0x1b65,  0x0,  0x0,  0x0,  0x1ffd2147,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1f031f07,  0x26f51f0b,  0x1f351f2d,  0x1f3b1f37,  0x1f411f3f,  0x1f431f47,  0x26fd1e63,  0x1f531f51,  0x1f631f55,  0x1e6526f7,  0x1f691f59,  0x1f7126fb,  0x1f251f75,  0x1f7b1f79,  0x1f8927b9,  0x1e691f8d,  0x1f9b1f99,  0x1fa11f9f,  0x1fad1e6b,  0x1fb51faf,  0x1fbd1fbb,  0x1fc31fbf,  0x1fd51fd3,  0x1fe11fd9,  0x1fe71fe5,  0x1fe71fe7,  0x22e42703,  0x1ff51ff1,  0x1ffb2705,  0x20031fff,  0x200d2017,  0x20152013,  0x201d2019,  0x2023201f,  0x20292027,  0x202d2029,  0x20332031,  0x204b2039,  0x204d203d,  0x2043203f,  0x20711f8f,  0x20572055,  0x20532059,  0x205b205d,  0x27072067,  0x20772075,  0x2081207b,  0x20962085,  0x270b2709,  0x209e209c,  0x209a20a0,  0x1e6d20a4,  0x20a81e6f,  0x20ac20ac,  0x20ba270d,  0x20be20bc,  0x270f20c2,  0x20c820c6,  0x20cc2137,  0x20d21e71,  0x20e020da,  0x271320de,  0x271520e4,  0x20e820ea,  0x20f420ec,  0x1e7320f6,  0x210220fe,  0x21062104,  0x27171e75,  0x21171e77,  0x211b2119,  0x27cd211f,  0x271b212b,  0x2486271b,  0x21332133,  0x27291e79,  0x213b277d,  0x1e7b213f,  0x21512149,  0x21572153,  0x1e7f215f,  0x21611e7d,  0x2163271d,  0x216f216d,  0x216f2171,  0x21792177,  0x217d2181,  0x2183217f,  0x21872185,  0x218f210b,  0x219f219b,  0x21b121a7,  0x21af2723,  0x21b521a9,  0x21c321b9,  0x21c72725,  0x21bd21c1,  0x21cb1e81,  0x21d321cf,  0x1e8321cd,  0x21df21db,  0x21f52727,  0x22032215,  0x22091e89,  0x1e851e87,  0x1f6d1f6b,  0x220b2217,  0x1ebb2470,  0x221f221d,  0x222b2221,  0x27312227,  0x22351e8b,  0x2242222f,  0x27352246,  0x22392248,  0x1e8d224c,  0x2250224e,  0x22582252,  0x225c2737,  0x22621e8f,  0x22642739,  0x226a1e91,  0x22762270,  0x273b2278,  0x273d2711,  0x273f2288,  0x2292228e,  0x2298228a,  0x22a822a0,  0x22a422a2,  0x22ac22aa,  0x229e2741,  0x22ba22b8,  0x22c41e93,  0x274322c2,  0x22d222b4,  0x27472745,  0x22de22d4,  0x22da22dc,  0x22e01e95,  0x22e622e8,  0x26f922ec,  0x274922f4,  0x274d22fa,  0x230a2304,  0x274f2314,  0x2320231e,  0x27532751,  0x2336232e,  0x23381e97,  0x1e991e99,  0x23462344,  0x234c234a,  0x1e9b2352,  0x2755235e,  0x2757236c,  0x27192372,  0x2759237a,  0x275d275b,  0x1e9f1e9d,  0x27612396,  0x2763275f,  0x239a2765,  0x239c239c,  0x1ea323a0,  0x1ea523a2,  0x27691ea7,  0x23b023ac,  0x1ea923b6,  0x23c8276b,  0x276f276d,  0x23e423d8,  0x23e81eab,  0x23ec23ea,  0x27732771,  0x23f82773,  0x27751ead,  0x24042402,  0x27771eaf,  0x1eb12412,  0x2416241a,  0x277b241e,  0x1eb3242a,  0x24342430,  0x1eb5243c,  0x2781277f,  0x27831eb7,  0x27852448,  0x2454244e,  0x27872458,  0x24622789,  0x2466278b,  0x1eb9272b,  0x24742472,  0x24761ebd,  0x278d20a6,  0x272d278f,  0x2486272f,  0x25942488,  0x249e1ebf,  0x24a0249c,  0x24a21fa9,  0x24a624a4,  0x279124aa,  0x24ac24a8,  0x24b824b6,  0x24ba24ae,  0x24ce24c4,  0x24be24b4,  0x24c224c0,  0x27972793,  0x1ec12795,  0x24d424d2,  0x279f24d8,  0x279924da,  0x1ec51ec3,  0x279d279b,  0x24ea1ec7,  0x24ee24ec,  0x24f624f0,  0x24fa24f4,  0x250024f8,  0x24fe24fc,  0x1ec92502,  0x25082506,  0x25101ecb,  0x27a12512,  0x251a2518,  0x25201ecd,  0x27a31e67,  0x1ecf27a5,  0x25361ed1,  0x25502542,  0x27a72558,  0x25642562,  0x25762570,  0x26ff27ab,  0x257a257c,  0x27012580,  0x258c2586,  0x27af27ad,  0x25b225ac,  0x27b125b6,  0x25cc25b8,  0x25d425d2,  0x25da25d0,  0x27b325dc,  0x1ed325e2,  0x27b525e6,  0x26021ed5,  0x260e20ee,  0x27bb27b7,  0x1ed91ed7,  0x27bd2622,  0x27bf1edb,  0x262e262e,  0x27c12632,  0x1edd263e,  0x264c2646,  0x26542650,  0x27c31edf,  0x266c265e,  0x1ee12672,  0x26741ee3,  0x1ee527c5,  0x27c927c7,  0x268627cb,  0x26901ee7,  0x26962694,  0x269e269a,  0x27cf26a2,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//12288 bytes
+enum canonMappingTrieEntries = TrieEntry!(ushort, 8, 7, 6)([ 0x0,  0x40,  0x240], [ 0x100,  0x400,  0x1380], [ 0x2020100,  0x3020202,  0x2020204,  0x2050202,  0x2020202,  0x6020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x0,  0x10000,  0x30002,  0x50004,  0x6,  0x0,  0x70000,  0x90008,  0xb000a,  0xc0000,  0x0,  0x0,  0xd,  0xe0000,  0x0,  0x0,  0x0,  0x0,  0x10000f,  0x110000,  0x130012,  0x0,  0x140000,  0x160015,  0x170000,  0x180000,  0x190000,  0x1a0000,  0x0,  0x0,  0x1b0000,  0x1c,  0x1d,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1f001e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x210020,  0x230022,  0x250024,  0x270026,  0x28,  0x0,  0x29,  0x2b002a,  0x2d002c,  0x2f002e,  0x30,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x310000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x320000,  0x340033,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x360035,  0x380037,  0x3a0039,  0x3c003b,  0x3e003d,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3f,  0x40,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x410000,  0x430042,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x450044,  0x470046,  0x490048,  0x4b004a,  0x4c,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xf000c,  0x250012,  0x4f0045,  0x850000,  0xa1009e,  0xcb00a4,  0x121011e,  0x1330124,  0x1880000,  0x1a0019d,  0x1b601a3,  0x1da,  0x26d0000,  0x2730270,  0x2f30287,  0x0,  0x322031f,  0x3380325,  0x3620358,  0x3980000,  0x3b403b1,  0x3de03b7,  0x4370434,  0x446043a,  0x49c0000,  0x4b404b1,  0x4ca04b7,  0x4ee,  0x5840000,  0x58a0587,  0x60d059e,  0x61c0000,  0x33b0028,  0x33e002b,  0x380006d,  0x38c0079,  0x38f007c,  0x392007f,  0x3950082,  0x3a2008f,  0x0,  0x3cd00ba,  0x3d800c5,  0x3db00c8,  0x3fb00e8,  0x3e400d1,  0x40a00f7,  0x41000fd,  0x4130100,  0x4190106,  0x41c0109,  0x0,  0x43d0127,  0x440012a,  0x443012d,  0x45c0149,  0x130,  0x0,  0x462014f,  0x471015d,  0x1630000,  0x1700477,  0x1660484,  0x47a,  0x0,  0x1850000,  0x1940499,  0x18e04a8,  0x4a2,  0x0,  0x4d901c5,  0x4e401d0,  0x4f801e4,  0x0,  0x52f021b,  0x5450231,  0x5350221,  0x54b0237,  0x552023e,  0x5690255,  0x5580244,  0x57b0264,  0x572025b,  0x0,  0x58d0276,  0x594027d,  0x59b0284,  0x5b4029d,  0x5b702a0,  0x5e002c9,  0x5f502de,  0x61002f6,  0x30b0302,  0x3110628,  0x314062e,  0x631,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x50401f0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2ac0000,  0x5c3,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x560000,  0x13d0369,  0x1e70450,  0x2a304fb,  0x29205ba,  0x28e05a9,  0x29605a5,  0x28a05ad,  0x5a1,  0x35b0048,  0x3540041,  0x653064a,  0x0,  0x4160103,  0x46b0157,  0x522020e,  0x5250211,  0x65f065c,  0x465,  0x0,  0x40700f4,  0x0,  0x4960182,  0x3650052,  0x6500647,  0x656064d,  0x36c0059,  0x36f005c,  0x3e700d4,  0x3ea00d7,  0x4530140,  0x4560143,  0x4fe01ea,  0x50101ed,  0x5380224,  0x53b0227,  0x5bd02a6,  0x5c002a9,  0x5660252,  0x5780261,  0x0,  0x4250112,  0x0,  0x0,  0x0,  0x351003e,  0x3f400e1,  0x4f101dd,  0x4d101bd,  0x4e701d3,  0x4ea01d6,  0x61602fc,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000d,  0x66b0000,  0x137,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x662,  0x0,  0x0,  0x0,  0x0,  0x1,  0x0,  0x0,  0x63d0000,  0x6450670,  0x6df06c3,  0x72c,  0x759,  0x7980778,  0x8d1,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7810735,  0x84707e9,  0x8c10867,  0x92f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x92808ca,  0x91f08fd,  0x95f,  0x0,  0x9b40000,  0x9b7,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x9cc09c6,  0x9c30000,  0x0,  0x9ba0000,  0x0,  0x0,  0x9d809e4,  0x9ed,  0x0,  0x0,  0x0,  0x0,  0x9de0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xa200000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xa0e0a08,  0xa050000,  0x0,  0xa410000,  0x0,  0x0,  0xa1a0a26,  0xa2f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xa470a44,  0x0,  0x0,  0x0,  0x0,  0x9cf0000,  0xa11,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x9ff09bd,  0xa0209c0,  0x0,  0xa0b09c9,  0x0,  0xa4d0a4a,  0xa1409d2,  0xa1709d5,  0x0,  0xa1d09db,  0xa2309e1,  0xa2909e7,  0x0,  0xa530a50,  0xa3e09fc,  0xa2c09ea,  0xa3209f0,  0xa3509f3,  0xa3809f6,  0x0,  0xa3b09f9,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xac10abe,  0xac40ac7,  0xaca,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xad3,  0xacd,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xad00000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xae80000,  0x0,  0x0,  0x0,  0xaf10000,  0x0,  0xaf4,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xad90ad6,  0xadf0adc,  0xae50ae2,  0xaee0aeb,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb000000,  0xb03,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xafa0af7,  0xafd0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb120000,  0x0,  0xb15,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb060000,  0xb0c0b09,  0x0,  0xb0f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb21,  0xb1e0000,  0xb24,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb1b0b18,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb27,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb300b2a,  0xb2d,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb33,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb36,  0x0,  0x0,  0xb400000,  0xb43,  0xb3c0b39,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb4c0b46,  0xb49,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb4f,  0xb550b52,  0xb59,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb5f0000,  0x0,  0x0,  0x0,  0x0,  0xb620000,  0x0,  0x0,  0xb65,  0x0,  0xb680000,  0x0,  0x0,  0xb6b,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb5c0000,  0x0,  0x0,  0x0,  0x0,  0xb6e0000,  0xb710000,  0xb89,  0xb8c,  0x0,  0x0,  0x0,  0xb740000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb7a0000,  0x0,  0x0,  0x0,  0x0,  0xb7d0000,  0x0,  0x0,  0xb80,  0x0,  0xb830000,  0x0,  0x0,  0xb86,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb770000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb8f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb92,  0xb95,  0xb98,  0xb9b,  0xb9e,  0x0,  0xba1,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xba40000,  0xba70000,  0x0,  0xbad0baa,  0xbb00000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x37d006a,  0x3830070,  0x3860073,  0x3890076,  0x39b0088,  0x39f008c,  0x3a50092,  0x3ae009b,  0x3a80095,  0x3ab0098,  0x3d000bd,  0x3d400c1,  0x3fe00eb,  0x40100ee,  0x3f700e4,  0x40400f1,  0x40d00fa,  0x41f010c,  0x4280115,  0x422010f,  0x42b0118,  0x42e011b,  0x45f014c,  0x4490136,  0x4680154,  0x46e015a,  0x4740160,  0x47d0169,  0x480016c,  0x48a0176,  0x4870173,  0x48d0179,  0x490017c,  0x493017f,  0x49f018b,  0x4a50191,  0x4ae019a,  0x4ab0197,  0x4cd01b9,  0x4d501c1,  0x4dc01c8,  0x4e001cc,  0x5290215,  0x52c0218,  0x532021e,  0x53e022a,  0x541022d,  0x5480234,  0x5550241,  0x55f024b,  0x54e023a,  0x55b0247,  0x562024e,  0x56c0258,  0x575025e,  0x581026a,  0x57e0267,  0x5dd02c6,  0x5e602cf,  0x5e302cc,  0x5900279,  0x5970280,  0x5e902d2,  0x5ec02d5,  0x5ef02d8,  0x5f202db,  0x5fb02e4,  0x5f802e1,  0x60102e7,  0x60402ea,  0x60702ed,  0x61902ff,  0x62b030e,  0x6340317,  0x637031a,  0x56f0431,  0x62205fe,  0x6590000,  0x0,  0x0,  0x372005f,  0x35f004c,  0x32c0019,  0x3280015,  0x3340021,  0x330001d,  0x3750062,  0x3450032,  0x341002e,  0x34d003a,  0x3490036,  0x3790066,  0x3ed00da,  0x3e100ce,  0x3ca00b7,  0x3be00ab,  0x3ba00a7,  0x3c600b3,  0x3c200af,  0x3f000dd,  0x44d013a,  0x4590146,  0x51b0207,  0x4f501e1,  0x4be01aa,  0x4ba01a6,  0x4c601b2,  0x4c201ae,  0x51e020a,  0x50b01f7,  0x50701f3,  0x51301ff,  0x50f01fb,  0x5170203,  0x5da02c3,  0x5b1029a,  0x5ca02b3,  0x5c602af,  0x5d202bb,  0x5ce02b7,  0x5d602bf,  0x60a02f0,  0x6250308,  0x61f0305,  0x61302f9,  0x0,  0x0,  0x0,  0x81807f6,  0x81b07f9,  0x8240802,  0x82d080b,  0x69b0679,  0x69e067c,  0x6a70685,  0x6b0068e,  0x855084a,  0x858084d,  0x85c0851,  0x0,  0x6d106c6,  0x6d406c9,  0x6d806cd,  0x0,  0x890086e,  0x8930871,  0x89c087a,  0x8a50883,  0x70406e2,  0x70706e5,  0x71006ee,  0x71906f7,  0x8e808d9,  0x8eb08dc,  0x8ef08e0,  0x8f308e4,  0x7470738,  0x74a073b,  0x74e073f,  0x7520743,  0x90b0900,  0x90e0903,  0x9120907,  0x0,  0x767075c,  0x76a075f,  0x76e0763,  0x0,  0x9460937,  0x949093a,  0x94d093e,  0x9510942,  0x7840000,  0x7870000,  0x78b0000,  0x78f0000,  0x9880966,  0x98b0969,  0x9940972,  0x99d097b,  0x7bd079b,  0x7c0079e,  0x7c907a7,  0x7d207b0,  0x7e907e2,  0x8470844,  0x8670860,  0x8c108be,  0x8fd08fa,  0x91f091c,  0x95f0958,  0x0,  0x8360814,  0x81f07fd,  0x8280806,  0x831080f,  0x6b90697,  0x6a20680,  0x6ab0689,  0x6b40692,  0x8ae088c,  0x8970875,  0x8a0087e,  0x8a90887,  0x7220700,  0x70b06e9,  0x71406f2,  0x71d06fb,  0x9a60984,  0x98f096d,  0x9980976,  0x9a1097f,  0x7db07b9,  0x7c407a2,  0x7cd07ab,  0x7d607b4,  0x7f007f3,  0x84107e5,  0x7ec,  0x83d083a,  0x6730676,  0x670066d,  0x6bd,  0x8bc,  0x6400000,  0x8b90863,  0x86a,  0x8b508b2,  0x6c306c0,  0x6df06dc,  0xbb30726,  0xbb90bb6,  0x8c408c7,  0x8d108cd,  0x0,  0x8d508f7,  0x72f0732,  0x72c0729,  0xbbc0000,  0xbc20bbf,  0x9220925,  0x92f092b,  0x9190916,  0x9330955,  0x77b077e,  0x7780775,  0x63a0772,  0x31d063d,  0x0,  0x9b1095b,  0x962,  0x9ad09aa,  0x7590756,  0x7980795,  0x64307df,  0x0,  0xbc70bc5,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x793,  0x0,  0x4f0152,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xbcc0bc9,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xbcf,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xbd20000,  0xbd50bd8,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xbdb,  0x0,  0xbde0000,  0x0,  0xbe1,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xbe4,  0xbe7,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xbea0000,  0x0,  0xbed,  0xbf00000,  0xbf30000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x6,  0xbf9,  0x0,  0x0,  0x0,  0x0,  0xbf60000,  0x90003,  0xbff0bfc,  0x0,  0xc050c02,  0x0,  0xc0b0c08,  0x0,  0x0,  0x0,  0xc110c0e,  0x0,  0xc1d0c1a,  0x0,  0xc230c20,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc2f0c2c,  0xc350c32,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc170c14,  0xc290c26,  0x0,  0x0,  0x0,  0xc3b0c38,  0xc410c3e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc470000,  0xc49,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc44,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc4e,  0xc51,  0xc54,  0xc57,  0xc5a,  0xc5d,  0xc60,  0xc63,  0xc66,  0xc69,  0xc6c,  0xc6f,  0xc720000,  0xc750000,  0xc780000,  0x0,  0x0,  0x0,  0xc7e0c7b,  0xc810000,  0xc84,  0xc8a0c87,  0xc8d0000,  0xc90,  0xc960c93,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc4b,  0x0,  0x0,  0x0,  0x0,  0xc99,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc9f,  0xca2,  0xca5,  0xca8,  0xcab,  0xcae,  0xcb1,  0xcb4,  0xcb7,  0xcba,  0xcbd,  0xcc0,  0xcc30000,  0xcc60000,  0xcc90000,  0x0,  0x0,  0x0,  0xccf0ccc,  0xcd20000,  0xcd5,  0xcdb0cd8,  0xcde0000,  0xce1,  0xce70ce4,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc9c,  0xcea0000,  0xcf00ced,  0xcf3,  0x0,  0xcf6,  0xfb71241,  0x124b125d,  0xd831043,  0x13270e29,  0xe991327,  0xe4f1293,  0xf550e97,  0x116710cd,  0x11fd11e3,  0x12791215,  0x10190feb,  0x109d1069,  0x128911c7,  0xd8d12f3,  0xff50e1d,  0x11e11079,  0xedb1309,  0x11d91051,  0xf65121d,  0x12031189,  0xfbd0eff,  0x108d1025,  0xd9d127d,  0xe050dd9,  0xff10f95,  0x10d31077,  0x11dd1171,  0x125911e7,  0x12fb12cf,  0x10e91307,  0x114d1107,  0x12a111b9,  0x122f130b,  0xf0b0e87,  0x117d112f,  0x10ed1083,  0x12cb1249,  0xecb0e85,  0x102f0fed,  0x11471047,  0x12b11159,  0x117f0e03,  0xddd0ddf,  0x114f1115,  0x12b511c5,  0xf67123d,  0x12350feb,  0xebb0d87,  0x10950f27,  0xe1110c1,  0xda510f1,  0xd7f0f1b,  0xf9d1011,  0xe231145,  0x10d70e7d,  0x122711c9,  0x126d1005,  0xf6f100d,  0xf7b11a5,  0xd9110bf,  0xddb0dc3,  0x113d0fdb,  0x122d1195,  0xe091291,  0xe9f0e37,  0xfa10f07,  0x10f31053,  0x12f712ab,  0x1313130d,  0xfb50df9,  0x12690ffd,  0xf490ef3,  0xf910f57,  0x106d104b,  0x111110af,  0x11791153,  0x11cd1261,  0x12a31271,  0xdfb0de9,  0x10670e41,  0x1227120b,  0xf230efd,  0x10030f77,  0x1091112d,  0xe670d97,  0xee50ebb,  0x109b0f29,  0x116b10a9,  0x12951175,  0x12d112c9,  0xd9f12dd,  0x128d110f,  0xf3512c1,  0xdb10d8f,  0xec70ebd,  0xfeb0f9f,  0x10cb1073,  0x127711d3,  0xfad1323,  0xdf712af,  0xfd10fcb,  0x103b1021,  0x10bd10a1,  0x114310e7,  0xdc512e3,  0x12b70f5d,  0xed70da9,  0x12631031,  0xf390f17,  0x10950fd5,  0xdeb12bb,  0xecf0e31,  0xfc30fa7,  0x10150fe1,  0x10c3109f,  0x120d1163,  0x128f1213,  0xe1312c5,  0xe33103d,  0x10b11075,  0x12bd11db,  0x130f12ff,  0x102d0fcf,  0x1121118b,  0x11331125,  0x1063108b,  0xd93123b,  0xded11ad,  0xef50de7,  0x11390f69,  0x101b0eb5,  0x12670fb3,  0x12b31205,  0xf031221,  0xe590db5,  0x0,  0xe7b,  0xfab,  0xde10000,  0x10cf108f,  0x110310f5,  0x110d1105,  0x113512d3,  0x116d,  0x11df,  0x1233,  0x12730000,  0x1283,  0x0,  0x12e912e7,  0x130512eb,  0x12bf127f,  0xdb30da1,  0xe010db9,  0xe170e07,  0xe5f0e53,  0xe790e63,  0xecd0e7f,  0xf2f0ed1,  0xf470f43,  0xf970f53,  0xfaf0fa3,  0x10270fdd,  0x10491035,  0x107d106f,  0x10eb10a3,  0x10fb10f7,  0x10fd10f9,  0x110110ff,  0x110b1109,  0x111d1117,  0x11531127,  0x115b1157,  0x11731161,  0x1197118d,  0x11cb1197,  0x12231219,  0x12391237,  0x124f124d,  0x1273126f,  0x12d912c7,  0xf2b12e1,  0x119313be,  0x0,  0xdd70d81,  0xd9b0dc1,  0xdc90db7,  0xe0b0dff,  0xe490e53,  0xe5d0e51,  0xe830e7b,  0xe9b0e95,  0xeb10ea9,  0xf050f01,  0xf1d0f13,  0xf3f0f33,  0xf470f37,  0xf530f41,  0xf7f0f5f,  0xf890f85,  0xfab0f99,  0xfbf0fbd,  0xfff0fc7,  0x10211005,  0x10411045,  0x10571049,  0x10e3106f,  0x1089107f,  0x10ab108f,  0x10b910b5,  0x10c910c7,  0x10d110cf,  0x10df10d5,  0x10ef10dd,  0x1127111f,  0x11491131,  0x115f1153,  0x11af1173,  0x11f911c3,  0x121f121b,  0x12291223,  0x122b1233,  0x12351237,  0x12391231,  0x124f123f,  0x12751265,  0x1299128b,  0x12c712b9,  0x12d512d3,  0x12db12d9,  0x12f912e1,  0x13941327,  0x13a61392,  0xd370d23,  0x13da0d39,  0x141c13ec,  0x13251321,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xa7a0000,  0xabb0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0xab50ab2,  0xaae0aaa,  0xa590a56,  0xa5f0a5c,  0xa680a65,  0xa710a6b,  0xa74,  0xa7d0a77,  0xa830a80,  0xa89,  0xa8c,  0xa920a8f,  0xa950000,  0xa98,  0xaa10a9e,  0xaa70aa4,  0xa6e0ab8,  0xa860a62,  0xa9b,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1329,  0x132c,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x132f0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x13351332,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x133b1338,  0x1342133e,  0x134a1346,  0x134e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x13520000,  0x1355135d,  0x13591360,  0x1364,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xd850d89,  0x13680d8b,  0xda10d99,  0xda70da3,  0xdad0dab,  0xdaf0db3,  0x13700cf9,  0xdbb0db9,  0xdc70dbd,  0xcfb136a,  0xdcb0dbf,  0xdd1136e,  0xd950dd3,  0xdd70dd5,  0xde3142c,  0xcff0de5,  0xdf10def,  0xdf50df3,  0xdff0d01,  0xe070e01,  0xe0d0e0b,  0xe110e0f,  0xe170e15,  0xe1b0e19,  0xe210e1f,  0xe210e21,  0x105d1376,  0xe270e25,  0xe2b1378,  0xe2f0e2d,  0xe350e3d,  0xe3b0e39,  0xe430e3f,  0xe470e45,  0xe4d0e4b,  0xe510e4d,  0xe570e55,  0xe690e5b,  0xe6b0e5f,  0xe650e61,  0xe890de7,  0xe710e6f,  0xe6d0e73,  0xe750e77,  0x137a0e81,  0xe8d0e8b,  0xe910e8f,  0xe9d0e93,  0x137e137c,  0xea50ea3,  0xea10ea7,  0xd030eab,  0xeaf0d05,  0xeb30eb3,  0xeb71380,  0xebb0eb9,  0x13820ebf,  0xec30ec1,  0xec50f0f,  0xec90d07,  0xed50ed1,  0x13860ed3,  0x13880ed9,  0xedd0edf,  0xee70ee1,  0xd090ee9,  0xeed0eeb,  0xef10eef,  0x138a0d0b,  0xef70d0d,  0xefb0ef9,  0x14400eff,  0x138e0f09,  0x118f138e,  0xf0d0f0d,  0x139c0d0f,  0xf1113f0,  0xd110f15,  0xf1f0f19,  0xf250f21,  0xd150f2d,  0xf2f0d13,  0xf311390,  0xf3d0f3b,  0xf3d0f3f,  0xf470f45,  0xf4b0f4f,  0xf510f4d,  0xf550f53,  0xf5b0f59,  0xf630f61,  0xf730f6b,  0xf711396,  0xf750f6d,  0xf830f79,  0xf871398,  0xf7d0f81,  0xf8b0d17,  0xf930f8f,  0xd190f8d,  0xf9b0f97,  0xfa5139a,  0xfa90fb9,  0xfaf0d1f,  0xd1b0d1d,  0xdcf0dcd,  0xfb10fbb,  0xd511181,  0xfbf0fbd,  0xfc90fc1,  0x13a40fc5,  0xfd30d21,  0xfd90fcd,  0x13a80fdd,  0xfd70fdf,  0xd230fe3,  0xfe70fe5,  0xfef0fe9,  0xff313aa,  0xff70d25,  0xff913ac,  0xffb0d27,  0x10051001,  0x13ae1007,  0x13b01384,  0x13b21009,  0x1013100f,  0x1017100b,  0x1027101f,  0x10231021,  0x102b1029,  0x101d13b4,  0x10391037,  0x10410d29,  0x13b6103f,  0x104d1033,  0x13ba13b8,  0x1059104f,  0x10551057,  0x105b0d2b,  0x105f1061,  0x136c1065,  0x13bc106b,  0x13c01071,  0x107f107b,  0x13c21081,  0x10871085,  0x13c613c4,  0x10971093,  0x10990d2d,  0xd2f0d2f,  0x10a710a5,  0x10ad10ab,  0xd3110b3,  0x13c810b7,  0x13ca10bb,  0x138c10c1,  0x13cc10c5,  0x13d013ce,  0xd350d33,  0x13d410d5,  0x13d613d2,  0x10d913d8,  0x10db10db,  0xd3910df,  0xd3b10e1,  0x13dc0d3d,  0x10e910e5,  0xd3f10ef,  0x10ff13de,  0x13e213e0,  0x1113110d,  0x11170d41,  0x111b1119,  0x13e613e4,  0x112313e6,  0x13e80d43,  0x112b1129,  0x13ea0d45,  0xd471137,  0x113b113f,  0x13ee1141,  0xd49114b,  0x11551151,  0xd4b115d,  0x13f413f2,  0x13f60d4d,  0x13f81165,  0x116f1169,  0x13fa1173,  0x117713fc,  0x117b13fe,  0xd4f139e,  0x11851183,  0x11870d53,  0x14000ead,  0x13a01402,  0x118f13a2,  0x126b1191,  0x119b0d55,  0x119d1199,  0x119f0dfd,  0x11a311a1,  0x140411a7,  0x11a911a5,  0x11b511b3,  0x11b711ab,  0x11cb11c1,  0x11bb11b1,  0x11bf11bd,  0x140a1406,  0xd571408,  0x11d111cf,  0x141211d5,  0x140c11d7,  0xd5b0d59,  0x1410140e,  0x11e50d5d,  0x11e911e7,  0x11ef11eb,  0x11f311ed,  0x11f911f1,  0x11f711f5,  0xd5f11fb,  0x120111ff,  0x12070d61,  0x14141209,  0x1211120f,  0x12170d63,  0x14160cfd,  0xd651418,  0x12250d67,  0x123f1231,  0x141a1243,  0x12471245,  0x12531251,  0x1372141e,  0x12551257,  0x1374125b,  0x1265125f,  0x14221420,  0x1281127b,  0x14241285,  0x12971287,  0x129f129d,  0x12a5129b,  0x142612a7,  0xd6912a9,  0x142812ad,  0x12c30d6b,  0x12cd0ee3,  0x142e142a,  0xd6f0d6d,  0x143012d7,  0x14320d71,  0x12db12db,  0x143412df,  0xd7312e5,  0x12ef12ed,  0x12f512f1,  0x14360d75,  0x12fd12f9,  0xd771301,  0x13030d79,  0xd7b1438,  0x143c143a,  0x1311143e,  0x13150d7d,  0x13191317,  0x131d131b,  0x1442131f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+@property
+{
+private alias _IDCA = immutable(dchar[]);
+_IDCA decompCanonTable() { static _IDCA t = [ 0x0,  0x3b,  0x0,  0x3c,  0x338,  0x0,  0x3d,  0x338,  0x0,  0x3e,  0x338,  0x0,  0x41,  0x300,  0x0,  0x41,  0x301,  0x0,  0x41,  0x302,  0x0,  0x41,  0x302,  0x300,  0x0,  0x41,  0x302,  0x301,  0x0,  0x41,  0x302,  0x303,  0x0,  0x41,  0x302,  0x309,  0x0,  0x41,  0x303,  0x0,  0x41,  0x304,  0x0,  0x41,  0x306,  0x0,  0x41,  0x306,  0x300,  0x0,  0x41,  0x306,  0x301,  0x0,  0x41,  0x306,  0x303,  0x0,  0x41,  0x306,  0x309,  0x0,  0x41,  0x307,  0x0,  0x41,  0x307,  0x304,  0x0,  0x41,  0x308,  0x0,  0x41,  0x308,  0x304,  0x0,  0x41,  0x309,  0x0,  0x41,  0x30a,  0x0,  0x41,  0x30a,  0x301,  0x0,  0x41,  0x30c,  0x0,  0x41,  0x30f,  0x0,  0x41,  0x311,  0x0,  0x41,  0x323,  0x0,  0x41,  0x323,  0x302,  0x0,  0x41,  0x323,  0x306,  0x0,  0x41,  0x325,  0x0,  0x41,  0x328,  0x0,  0x42,  0x307,  0x0,  0x42,  0x323,  0x0,  0x42,  0x331,  0x0,  0x43,  0x301,  0x0,  0x43,  0x302,  0x0,  0x43,  0x307,  0x0,  0x43,  0x30c,  0x0,  0x43,  0x327,  0x0,  0x43,  0x327,  0x301,  0x0,  0x44,  0x307,  0x0,  0x44,  0x30c,  0x0,  0x44,  0x323,  0x0,  0x44,  0x327,  0x0,  0x44,  0x32d,  0x0,  0x44,  0x331,  0x0,  0x45,  0x300,  0x0,  0x45,  0x301,  0x0,  0x45,  0x302,  0x0,  0x45,  0x302,  0x300,  0x0,  0x45,  0x302,  0x301,  0x0,  0x45,  0x302,  0x303,  0x0,  0x45,  0x302,  0x309,  0x0,  0x45,  0x303,  0x0,  0x45,  0x304,  0x0,  0x45,  0x304,  0x300,  0x0,  0x45,  0x304,  0x301,  0x0,  0x45,  0x306,  0x0,  0x45,  0x307,  0x0,  0x45,  0x308,  0x0,  0x45,  0x309,  0x0,  0x45,  0x30c,  0x0,  0x45,  0x30f,  0x0,  0x45,  0x311,  0x0,  0x45,  0x323,  0x0,  0x45,  0x323,  0x302,  0x0,  0x45,  0x327,  0x0,  0x45,  0x327,  0x306,  0x0,  0x45,  0x328,  0x0,  0x45,  0x32d,  0x0,  0x45,  0x330,  0x0,  0x46,  0x307,  0x0,  0x47,  0x301,  0x0,  0x47,  0x302,  0x0,  0x47,  0x304,  0x0,  0x47,  0x306,  0x0,  0x47,  0x307,  0x0,  0x47,  0x30c,  0x0,  0x47,  0x327,  0x0,  0x48,  0x302,  0x0,  0x48,  0x307,  0x0,  0x48,  0x308,  0x0,  0x48,  0x30c,  0x0,  0x48,  0x323,  0x0,  0x48,  0x327,  0x0,  0x48,  0x32e,  0x0,  0x49,  0x300,  0x0,  0x49,  0x301,  0x0,  0x49,  0x302,  0x0,  0x49,  0x303,  0x0,  0x49,  0x304,  0x0,  0x49,  0x306,  0x0,  0x49,  0x307,  0x0,  0x49,  0x308,  0x0,  0x49,  0x308,  0x301,  0x0,  0x49,  0x309,  0x0,  0x49,  0x30c,  0x0,  0x49,  0x30f,  0x0,  0x49,  0x311,  0x0,  0x49,  0x323,  0x0,  0x49,  0x328,  0x0,  0x49,  0x330,  0x0,  0x4a,  0x302,  0x0,  0x4b,  0x0,  0x4b,  0x301,  0x0,  0x4b,  0x30c,  0x0,  0x4b,  0x323,  0x0,  0x4b,  0x327,  0x0,  0x4b,  0x331,  0x0,  0x4c,  0x301,  0x0,  0x4c,  0x30c,  0x0,  0x4c,  0x323,  0x0,  0x4c,  0x323,  0x304,  0x0,  0x4c,  0x327,  0x0,  0x4c,  0x32d,  0x0,  0x4c,  0x331,  0x0,  0x4d,  0x301,  0x0,  0x4d,  0x307,  0x0,  0x4d,  0x323,  0x0,  0x4e,  0x300,  0x0,  0x4e,  0x301,  0x0,  0x4e,  0x303,  0x0,  0x4e,  0x307,  0x0,  0x4e,  0x30c,  0x0,  0x4e,  0x323,  0x0,  0x4e,  0x327,  0x0,  0x4e,  0x32d,  0x0,  0x4e,  0x331,  0x0,  0x4f,  0x300,  0x0,  0x4f,  0x301,  0x0,  0x4f,  0x302,  0x0,  0x4f,  0x302,  0x300,  0x0,  0x4f,  0x302,  0x301,  0x0,  0x4f,  0x302,  0x303,  0x0,  0x4f,  0x302,  0x309,  0x0,  0x4f,  0x303,  0x0,  0x4f,  0x303,  0x301,  0x0,  0x4f,  0x303,  0x304,  0x0,  0x4f,  0x303,  0x308,  0x0,  0x4f,  0x304,  0x0,  0x4f,  0x304,  0x300,  0x0,  0x4f,  0x304,  0x301,  0x0,  0x4f,  0x306,  0x0,  0x4f,  0x307,  0x0,  0x4f,  0x307,  0x304,  0x0,  0x4f,  0x308,  0x0,  0x4f,  0x308,  0x304,  0x0,  0x4f,  0x309,  0x0,  0x4f,  0x30b,  0x0,  0x4f,  0x30c,  0x0,  0x4f,  0x30f,  0x0,  0x4f,  0x311,  0x0,  0x4f,  0x31b,  0x0,  0x4f,  0x31b,  0x300,  0x0,  0x4f,  0x31b,  0x301,  0x0,  0x4f,  0x31b,  0x303,  0x0,  0x4f,  0x31b,  0x309,  0x0,  0x4f,  0x31b,  0x323,  0x0,  0x4f,  0x323,  0x0,  0x4f,  0x323,  0x302,  0x0,  0x4f,  0x328,  0x0,  0x4f,  0x328,  0x304,  0x0,  0x50,  0x301,  0x0,  0x50,  0x307,  0x0,  0x52,  0x301,  0x0,  0x52,  0x307,  0x0,  0x52,  0x30c,  0x0,  0x52,  0x30f,  0x0,  0x52,  0x311,  0x0,  0x52,  0x323,  0x0,  0x52,  0x323,  0x304,  0x0,  0x52,  0x327,  0x0,  0x52,  0x331,  0x0,  0x53,  0x301,  0x0,  0x53,  0x301,  0x307,  0x0,  0x53,  0x302,  0x0,  0x53,  0x307,  0x0,  0x53,  0x30c,  0x0,  0x53,  0x30c,  0x307,  0x0,  0x53,  0x323,  0x0,  0x53,  0x323,  0x307,  0x0,  0x53,  0x326,  0x0,  0x53,  0x327,  0x0,  0x54,  0x307,  0x0,  0x54,  0x30c,  0x0,  0x54,  0x323,  0x0,  0x54,  0x326,  0x0,  0x54,  0x327,  0x0,  0x54,  0x32d,  0x0,  0x54,  0x331,  0x0,  0x55,  0x300,  0x0,  0x55,  0x301,  0x0,  0x55,  0x302,  0x0,  0x55,  0x303,  0x0,  0x55,  0x303,  0x301,  0x0,  0x55,  0x304,  0x0,  0x55,  0x304,  0x308,  0x0,  0x55,  0x306,  0x0,  0x55,  0x308,  0x0,  0x55,  0x308,  0x300,  0x0,  0x55,  0x308,  0x301,  0x0,  0x55,  0x308,  0x304,  0x0,  0x55,  0x308,  0x30c,  0x0,  0x55,  0x309,  0x0,  0x55,  0x30a,  0x0,  0x55,  0x30b,  0x0,  0x55,  0x30c,  0x0,  0x55,  0x30f,  0x0,  0x55,  0x311,  0x0,  0x55,  0x31b,  0x0,  0x55,  0x31b,  0x300,  0x0,  0x55,  0x31b,  0x301,  0x0,  0x55,  0x31b,  0x303,  0x0,  0x55,  0x31b,  0x309,  0x0,  0x55,  0x31b,  0x323,  0x0,  0x55,  0x323,  0x0,  0x55,  0x324,  0x0,  0x55,  0x328,  0x0,  0x55,  0x32d,  0x0,  0x55,  0x330,  0x0,  0x56,  0x303,  0x0,  0x56,  0x323,  0x0,  0x57,  0x300,  0x0,  0x57,  0x301,  0x0,  0x57,  0x302,  0x0,  0x57,  0x307,  0x0,  0x57,  0x308,  0x0,  0x57,  0x323,  0x0,  0x58,  0x307,  0x0,  0x58,  0x308,  0x0,  0x59,  0x300,  0x0,  0x59,  0x301,  0x0,  0x59,  0x302,  0x0,  0x59,  0x303,  0x0,  0x59,  0x304,  0x0,  0x59,  0x307,  0x0,  0x59,  0x308,  0x0,  0x59,  0x309,  0x0,  0x59,  0x323,  0x0,  0x5a,  0x301,  0x0,  0x5a,  0x302,  0x0,  0x5a,  0x307,  0x0,  0x5a,  0x30c,  0x0,  0x5a,  0x323,  0x0,  0x5a,  0x331,  0x0,  0x60,  0x0,  0x61,  0x300,  0x0,  0x61,  0x301,  0x0,  0x61,  0x302,  0x0,  0x61,  0x302,  0x300,  0x0,  0x61,  0x302,  0x301,  0x0,  0x61,  0x302,  0x303,  0x0,  0x61,  0x302,  0x309,  0x0,  0x61,  0x303,  0x0,  0x61,  0x304,  0x0,  0x61,  0x306,  0x0,  0x61,  0x306,  0x300,  0x0,  0x61,  0x306,  0x301,  0x0,  0x61,  0x306,  0x303,  0x0,  0x61,  0x306,  0x309,  0x0,  0x61,  0x307,  0x0,  0x61,  0x307,  0x304,  0x0,  0x61,  0x308,  0x0,  0x61,  0x308,  0x304,  0x0,  0x61,  0x309,  0x0,  0x61,  0x30a,  0x0,  0x61,  0x30a,  0x301,  0x0,  0x61,  0x30c,  0x0,  0x61,  0x30f,  0x0,  0x61,  0x311,  0x0,  0x61,  0x323,  0x0,  0x61,  0x323,  0x302,  0x0,  0x61,  0x323,  0x306,  0x0,  0x61,  0x325,  0x0,  0x61,  0x328,  0x0,  0x62,  0x307,  0x0,  0x62,  0x323,  0x0,  0x62,  0x331,  0x0,  0x63,  0x301,  0x0,  0x63,  0x302,  0x0,  0x63,  0x307,  0x0,  0x63,  0x30c,  0x0,  0x63,  0x327,  0x0,  0x63,  0x327,  0x301,  0x0,  0x64,  0x307,  0x0,  0x64,  0x30c,  0x0,  0x64,  0x323,  0x0,  0x64,  0x327,  0x0,  0x64,  0x32d,  0x0,  0x64,  0x331,  0x0,  0x65,  0x300,  0x0,  0x65,  0x301,  0x0,  0x65,  0x302,  0x0,  0x65,  0x302,  0x300,  0x0,  0x65,  0x302,  0x301,  0x0,  0x65,  0x302,  0x303,  0x0,  0x65,  0x302,  0x309,  0x0,  0x65,  0x303,  0x0,  0x65,  0x304,  0x0,  0x65,  0x304,  0x300,  0x0,  0x65,  0x304,  0x301,  0x0,  0x65,  0x306,  0x0,  0x65,  0x307,  0x0,  0x65,  0x308,  0x0,  0x65,  0x309,  0x0,  0x65,  0x30c,  0x0,  0x65,  0x30f,  0x0,  0x65,  0x311,  0x0,  0x65,  0x323,  0x0,  0x65,  0x323,  0x302,  0x0,  0x65,  0x327,  0x0,  0x65,  0x327,  0x306,  0x0,  0x65,  0x328,  0x0,  0x65,  0x32d,  0x0,  0x65,  0x330,  0x0,  0x66,  0x307,  0x0,  0x67,  0x301,  0x0,  0x67,  0x302,  0x0,  0x67,  0x304,  0x0,  0x67,  0x306,  0x0,  0x67,  0x307,  0x0,  0x67,  0x30c,  0x0,  0x67,  0x327,  0x0,  0x68,  0x302,  0x0,  0x68,  0x307,  0x0,  0x68,  0x308,  0x0,  0x68,  0x30c,  0x0,  0x68,  0x323,  0x0,  0x68,  0x327,  0x0,  0x68,  0x32e,  0x0,  0x68,  0x331,  0x0,  0x69,  0x300,  0x0,  0x69,  0x301,  0x0,  0x69,  0x302,  0x0,  0x69,  0x303,  0x0,  0x69,  0x304,  0x0,  0x69,  0x306,  0x0,  0x69,  0x308,  0x0,  0x69,  0x308,  0x301,  0x0,  0x69,  0x309,  0x0,  0x69,  0x30c,  0x0,  0x69,  0x30f,  0x0,  0x69,  0x311,  0x0,  0x69,  0x323,  0x0,  0x69,  0x328,  0x0,  0x69,  0x330,  0x0,  0x6a,  0x302,  0x0,  0x6a,  0x30c,  0x0,  0x6b,  0x301,  0x0,  0x6b,  0x30c,  0x0,  0x6b,  0x323,  0x0,  0x6b,  0x327,  0x0,  0x6b,  0x331,  0x0,  0x6c,  0x301,  0x0,  0x6c,  0x30c,  0x0,  0x6c,  0x323,  0x0,  0x6c,  0x323,  0x304,  0x0,  0x6c,  0x327,  0x0,  0x6c,  0x32d,  0x0,  0x6c,  0x331,  0x0,  0x6d,  0x301,  0x0,  0x6d,  0x307,  0x0,  0x6d,  0x323,  0x0,  0x6e,  0x300,  0x0,  0x6e,  0x301,  0x0,  0x6e,  0x303,  0x0,  0x6e,  0x307,  0x0,  0x6e,  0x30c,  0x0,  0x6e,  0x323,  0x0,  0x6e,  0x327,  0x0,  0x6e,  0x32d,  0x0,  0x6e,  0x331,  0x0,  0x6f,  0x300,  0x0,  0x6f,  0x301,  0x0,  0x6f,  0x302,  0x0,  0x6f,  0x302,  0x300,  0x0,  0x6f,  0x302,  0x301,  0x0,  0x6f,  0x302,  0x303,  0x0,  0x6f,  0x302,  0x309,  0x0,  0x6f,  0x303,  0x0,  0x6f,  0x303,  0x301,  0x0,  0x6f,  0x303,  0x304,  0x0,  0x6f,  0x303,  0x308,  0x0,  0x6f,  0x304,  0x0,  0x6f,  0x304,  0x300,  0x0,  0x6f,  0x304,  0x301,  0x0,  0x6f,  0x306,  0x0,  0x6f,  0x307,  0x0,  0x6f,  0x307,  0x304,  0x0,  0x6f,  0x308,  0x0,  0x6f,  0x308,  0x304,  0x0,  0x6f,  0x309,  0x0,  0x6f,  0x30b,  0x0,  0x6f,  0x30c,  0x0,  0x6f,  0x30f,  0x0,  0x6f,  0x311,  0x0,  0x6f,  0x31b,  0x0,  0x6f,  0x31b,  0x300,  0x0,  0x6f,  0x31b,  0x301,  0x0,  0x6f,  0x31b,  0x303,  0x0,  0x6f,  0x31b,  0x309,  0x0,  0x6f,  0x31b,  0x323,  0x0,  0x6f,  0x323,  0x0,  0x6f,  0x323,  0x302,  0x0,  0x6f,  0x328,  0x0,  0x6f,  0x328,  0x304,  0x0,  0x70,  0x301,  0x0,  0x70,  0x307,  0x0,  0x72,  0x301,  0x0,  0x72,  0x307,  0x0,  0x72,  0x30c,  0x0,  0x72,  0x30f,  0x0,  0x72,  0x311,  0x0,  0x72,  0x323,  0x0,  0x72,  0x323,  0x304,  0x0,  0x72,  0x327,  0x0,  0x72,  0x331,  0x0,  0x73,  0x301,  0x0,  0x73,  0x301,  0x307,  0x0,  0x73,  0x302,  0x0,  0x73,  0x307,  0x0,  0x73,  0x30c,  0x0,  0x73,  0x30c,  0x307,  0x0,  0x73,  0x323,  0x0,  0x73,  0x323,  0x307,  0x0,  0x73,  0x326,  0x0,  0x73,  0x327,  0x0,  0x74,  0x307,  0x0,  0x74,  0x308,  0x0,  0x74,  0x30c,  0x0,  0x74,  0x323,  0x0,  0x74,  0x326,  0x0,  0x74,  0x327,  0x0,  0x74,  0x32d,  0x0,  0x74,  0x331,  0x0,  0x75,  0x300,  0x0,  0x75,  0x301,  0x0,  0x75,  0x302,  0x0,  0x75,  0x303,  0x0,  0x75,  0x303,  0x301,  0x0,  0x75,  0x304,  0x0,  0x75,  0x304,  0x308,  0x0,  0x75,  0x306,  0x0,  0x75,  0x308,  0x0,  0x75,  0x308,  0x300,  0x0,  0x75,  0x308,  0x301,  0x0,  0x75,  0x308,  0x304,  0x0,  0x75,  0x308,  0x30c,  0x0,  0x75,  0x309,  0x0,  0x75,  0x30a,  0x0,  0x75,  0x30b,  0x0,  0x75,  0x30c,  0x0,  0x75,  0x30f,  0x0,  0x75,  0x311,  0x0,  0x75,  0x31b,  0x0,  0x75,  0x31b,  0x300,  0x0,  0x75,  0x31b,  0x301,  0x0,  0x75,  0x31b,  0x303,  0x0,  0x75,  0x31b,  0x309,  0x0,  0x75,  0x31b,  0x323,  0x0,  0x75,  0x323,  0x0,  0x75,  0x324,  0x0,  0x75,  0x328,  0x0,  0x75,  0x32d,  0x0,  0x75,  0x330,  0x0,  0x76,  0x303,  0x0,  0x76,  0x323,  0x0,  0x77,  0x300,  0x0,  0x77,  0x301,  0x0,  0x77,  0x302,  0x0,  0x77,  0x307,  0x0,  0x77,  0x308,  0x0,  0x77,  0x30a,  0x0,  0x77,  0x323,  0x0,  0x78,  0x307,  0x0,  0x78,  0x308,  0x0,  0x79,  0x300,  0x0,  0x79,  0x301,  0x0,  0x79,  0x302,  0x0,  0x79,  0x303,  0x0,  0x79,  0x304,  0x0,  0x79,  0x307,  0x0,  0x79,  0x308,  0x0,  0x79,  0x309,  0x0,  0x79,  0x30a,  0x0,  0x79,  0x323,  0x0,  0x7a,  0x301,  0x0,  0x7a,  0x302,  0x0,  0x7a,  0x307,  0x0,  0x7a,  0x30c,  0x0,  0x7a,  0x323,  0x0,  0x7a,  0x331,  0x0,  0xa8,  0x300,  0x0,  0xa8,  0x301,  0x0,  0xa8,  0x342,  0x0,  0xb4,  0x0,  0xb7,  0x0,  0xc6,  0x301,  0x0,  0xc6,  0x304,  0x0,  0xd8,  0x301,  0x0,  0xe6,  0x301,  0x0,  0xe6,  0x304,  0x0,  0xf8,  0x301,  0x0,  0x17f,  0x307,  0x0,  0x1b7,  0x30c,  0x0,  0x292,  0x30c,  0x0,  0x2b9,  0x0,  0x300,  0x0,  0x301,  0x0,  0x308,  0x301,  0x0,  0x313,  0x0,  0x391,  0x300,  0x0,  0x391,  0x301,  0x0,  0x391,  0x304,  0x0,  0x391,  0x306,  0x0,  0x391,  0x313,  0x0,  0x391,  0x313,  0x300,  0x0,  0x391,  0x313,  0x300,  0x345,  0x0,  0x391,  0x313,  0x301,  0x0,  0x391,  0x313,  0x301,  0x345,  0x0,  0x391,  0x313,  0x342,  0x0,  0x391,  0x313,  0x342,  0x345,  0x0,  0x391,  0x313,  0x345,  0x0,  0x391,  0x314,  0x0,  0x391,  0x314,  0x300,  0x0,  0x391,  0x314,  0x300,  0x345,  0x0,  0x391,  0x314,  0x301,  0x0,  0x391,  0x314,  0x301,  0x345,  0x0,  0x391,  0x314,  0x342,  0x0,  0x391,  0x314,  0x342,  0x345,  0x0,  0x391,  0x314,  0x345,  0x0,  0x391,  0x345,  0x0,  0x395,  0x300,  0x0,  0x395,  0x301,  0x0,  0x395,  0x313,  0x0,  0x395,  0x313,  0x300,  0x0,  0x395,  0x313,  0x301,  0x0,  0x395,  0x314,  0x0,  0x395,  0x314,  0x300,  0x0,  0x395,  0x314,  0x301,  0x0,  0x397,  0x300,  0x0,  0x397,  0x301,  0x0,  0x397,  0x313,  0x0,  0x397,  0x313,  0x300,  0x0,  0x397,  0x313,  0x300,  0x345,  0x0,  0x397,  0x313,  0x301,  0x0,  0x397,  0x313,  0x301,  0x345,  0x0,  0x397,  0x313,  0x342,  0x0,  0x397,  0x313,  0x342,  0x345,  0x0,  0x397,  0x313,  0x345,  0x0,  0x397,  0x314,  0x0,  0x397,  0x314,  0x300,  0x0,  0x397,  0x314,  0x300,  0x345,  0x0,  0x397,  0x314,  0x301,  0x0,  0x397,  0x314,  0x301,  0x345,  0x0,  0x397,  0x314,  0x342,  0x0,  0x397,  0x314,  0x342,  0x345,  0x0,  0x397,  0x314,  0x345,  0x0,  0x397,  0x345,  0x0,  0x399,  0x300,  0x0,  0x399,  0x301,  0x0,  0x399,  0x304,  0x0,  0x399,  0x306,  0x0,  0x399,  0x308,  0x0,  0x399,  0x313,  0x0,  0x399,  0x313,  0x300,  0x0,  0x399,  0x313,  0x301,  0x0,  0x399,  0x313,  0x342,  0x0,  0x399,  0x314,  0x0,  0x399,  0x314,  0x300,  0x0,  0x399,  0x314,  0x301,  0x0,  0x399,  0x314,  0x342,  0x0,  0x39f,  0x300,  0x0,  0x39f,  0x301,  0x0,  0x39f,  0x313,  0x0,  0x39f,  0x313,  0x300,  0x0,  0x39f,  0x313,  0x301,  0x0,  0x39f,  0x314,  0x0,  0x39f,  0x314,  0x300,  0x0,  0x39f,  0x314,  0x301,  0x0,  0x3a1,  0x314,  0x0,  0x3a5,  0x300,  0x0,  0x3a5,  0x301,  0x0,  0x3a5,  0x304,  0x0,  0x3a5,  0x306,  0x0,  0x3a5,  0x308,  0x0,  0x3a5,  0x314,  0x0,  0x3a5,  0x314,  0x300,  0x0,  0x3a5,  0x314,  0x301,  0x0,  0x3a5,  0x314,  0x342,  0x0,  0x3a9,  0x0,  0x3a9,  0x300,  0x0,  0x3a9,  0x301,  0x0,  0x3a9,  0x313,  0x0,  0x3a9,  0x313,  0x300,  0x0,  0x3a9,  0x313,  0x300,  0x345,  0x0,  0x3a9,  0x313,  0x301,  0x0,  0x3a9,  0x313,  0x301,  0x345,  0x0,  0x3a9,  0x313,  0x342,  0x0,  0x3a9,  0x313,  0x342,  0x345,  0x0,  0x3a9,  0x313,  0x345,  0x0,  0x3a9,  0x314,  0x0,  0x3a9,  0x314,  0x300,  0x0,  0x3a9,  0x314,  0x300,  0x345,  0x0,  0x3a9,  0x314,  0x301,  0x0,  0x3a9,  0x314,  0x301,  0x345,  0x0,  0x3a9,  0x314,  0x342,  0x0,  0x3a9,  0x314,  0x342,  0x345,  0x0,  0x3a9,  0x314,  0x345,  0x0,  0x3a9,  0x345,  0x0,  0x3b1,  0x300,  0x0,  0x3b1,  0x300,  0x345,  0x0,  0x3b1,  0x301,  0x0,  0x3b1,  0x301,  0x345,  0x0,  0x3b1,  0x304,  0x0,  0x3b1,  0x306,  0x0,  0x3b1,  0x313,  0x0,  0x3b1,  0x313,  0x300,  0x0,  0x3b1,  0x313,  0x300,  0x345,  0x0,  0x3b1,  0x313,  0x301,  0x0,  0x3b1,  0x313,  0x301,  0x345,  0x0,  0x3b1,  0x313,  0x342,  0x0,  0x3b1,  0x313,  0x342,  0x345,  0x0,  0x3b1,  0x313,  0x345,  0x0,  0x3b1,  0x314,  0x0,  0x3b1,  0x314,  0x300,  0x0,  0x3b1,  0x314,  0x300,  0x345,  0x0,  0x3b1,  0x314,  0x301,  0x0,  0x3b1,  0x314,  0x301,  0x345,  0x0,  0x3b1,  0x314,  0x342,  0x0,  0x3b1,  0x314,  0x342,  0x345,  0x0,  0x3b1,  0x314,  0x345,  0x0,  0x3b1,  0x342,  0x0,  0x3b1,  0x342,  0x345,  0x0,  0x3b1,  0x345,  0x0,  0x3b5,  0x300,  0x0,  0x3b5,  0x301,  0x0,  0x3b5,  0x313,  0x0,  0x3b5,  0x313,  0x300,  0x0,  0x3b5,  0x313,  0x301,  0x0,  0x3b5,  0x314,  0x0,  0x3b5,  0x314,  0x300,  0x0,  0x3b5,  0x314,  0x301,  0x0,  0x3b7,  0x300,  0x0,  0x3b7,  0x300,  0x345,  0x0,  0x3b7,  0x301,  0x0,  0x3b7,  0x301,  0x345,  0x0,  0x3b7,  0x313,  0x0,  0x3b7,  0x313,  0x300,  0x0,  0x3b7,  0x313,  0x300,  0x345,  0x0,  0x3b7,  0x313,  0x301,  0x0,  0x3b7,  0x313,  0x301,  0x345,  0x0,  0x3b7,  0x313,  0x342,  0x0,  0x3b7,  0x313,  0x342,  0x345,  0x0,  0x3b7,  0x313,  0x345,  0x0,  0x3b7,  0x314,  0x0,  0x3b7,  0x314,  0x300,  0x0,  0x3b7,  0x314,  0x300,  0x345,  0x0,  0x3b7,  0x314,  0x301,  0x0,  0x3b7,  0x314,  0x301,  0x345,  0x0,  0x3b7,  0x314,  0x342,  0x0,  0x3b7,  0x314,  0x342,  0x345,  0x0,  0x3b7,  0x314,  0x345,  0x0,  0x3b7,  0x342,  0x0,  0x3b7,  0x342,  0x345,  0x0,  0x3b7,  0x345,  0x0,  0x3b9,  0x0,  0x3b9,  0x300,  0x0,  0x3b9,  0x301,  0x0,  0x3b9,  0x304,  0x0,  0x3b9,  0x306,  0x0,  0x3b9,  0x308,  0x0,  0x3b9,  0x308,  0x300,  0x0,  0x3b9,  0x308,  0x301,  0x0,  0x3b9,  0x308,  0x342,  0x0,  0x3b9,  0x313,  0x0,  0x3b9,  0x313,  0x300,  0x0,  0x3b9,  0x313,  0x301,  0x0,  0x3b9,  0x313,  0x342,  0x0,  0x3b9,  0x314,  0x0,  0x3b9,  0x314,  0x300,  0x0,  0x3b9,  0x314,  0x301,  0x0,  0x3b9,  0x314,  0x342,  0x0,  0x3b9,  0x342,  0x0,  0x3bf,  0x300,  0x0,  0x3bf,  0x301,  0x0,  0x3bf,  0x313,  0x0,  0x3bf,  0x313,  0x300,  0x0,  0x3bf,  0x313,  0x301,  0x0,  0x3bf,  0x314,  0x0,  0x3bf,  0x314,  0x300,  0x0,  0x3bf,  0x314,  0x301,  0x0,  0x3c1,  0x313,  0x0,  0x3c1,  0x314,  0x0,  0x3c5,  0x300,  0x0,  0x3c5,  0x301,  0x0,  0x3c5,  0x304,  0x0,  0x3c5,  0x306,  0x0,  0x3c5,  0x308,  0x0,  0x3c5,  0x308,  0x300,  0x0,  0x3c5,  0x308,  0x301,  0x0,  0x3c5,  0x308,  0x342,  0x0,  0x3c5,  0x313,  0x0,  0x3c5,  0x313,  0x300,  0x0,  0x3c5,  0x313,  0x301,  0x0,  0x3c5,  0x313,  0x342,  0x0,  0x3c5,  0x314,  0x0,  0x3c5,  0x314,  0x300,  0x0,  0x3c5,  0x314,  0x301,  0x0,  0x3c5,  0x314,  0x342,  0x0,  0x3c5,  0x342,  0x0,  0x3c9,  0x300,  0x0,  0x3c9,  0x300,  0x345,  0x0,  0x3c9,  0x301,  0x0,  0x3c9,  0x301,  0x345,  0x0,  0x3c9,  0x313,  0x0,  0x3c9,  0x313,  0x300,  0x0,  0x3c9,  0x313,  0x300,  0x345,  0x0,  0x3c9,  0x313,  0x301,  0x0,  0x3c9,  0x313,  0x301,  0x345,  0x0,  0x3c9,  0x313,  0x342,  0x0,  0x3c9,  0x313,  0x342,  0x345,  0x0,  0x3c9,  0x313,  0x345,  0x0,  0x3c9,  0x314,  0x0,  0x3c9,  0x314,  0x300,  0x0,  0x3c9,  0x314,  0x300,  0x345,  0x0,  0x3c9,  0x314,  0x301,  0x0,  0x3c9,  0x314,  0x301,  0x345,  0x0,  0x3c9,  0x314,  0x342,  0x0,  0x3c9,  0x314,  0x342,  0x345,  0x0,  0x3c9,  0x314,  0x345,  0x0,  0x3c9,  0x342,  0x0,  0x3c9,  0x342,  0x345,  0x0,  0x3c9,  0x345,  0x0,  0x3d2,  0x301,  0x0,  0x3d2,  0x308,  0x0,  0x406,  0x308,  0x0,  0x410,  0x306,  0x0,  0x410,  0x308,  0x0,  0x413,  0x301,  0x0,  0x415,  0x300,  0x0,  0x415,  0x306,  0x0,  0x415,  0x308,  0x0,  0x416,  0x306,  0x0,  0x416,  0x308,  0x0,  0x417,  0x308,  0x0,  0x418,  0x300,  0x0,  0x418,  0x304,  0x0,  0x418,  0x306,  0x0,  0x418,  0x308,  0x0,  0x41a,  0x301,  0x0,  0x41e,  0x308,  0x0,  0x423,  0x304,  0x0,  0x423,  0x306,  0x0,  0x423,  0x308,  0x0,  0x423,  0x30b,  0x0,  0x427,  0x308,  0x0,  0x42b,  0x308,  0x0,  0x42d,  0x308,  0x0,  0x430,  0x306,  0x0,  0x430,  0x308,  0x0,  0x433,  0x301,  0x0,  0x435,  0x300,  0x0,  0x435,  0x306,  0x0,  0x435,  0x308,  0x0,  0x436,  0x306,  0x0,  0x436,  0x308,  0x0,  0x437,  0x308,  0x0,  0x438,  0x300,  0x0,  0x438,  0x304,  0x0,  0x438,  0x306,  0x0,  0x438,  0x308,  0x0,  0x43a,  0x301,  0x0,  0x43e,  0x308,  0x0,  0x443,  0x304,  0x0,  0x443,  0x306,  0x0,  0x443,  0x308,  0x0,  0x443,  0x30b,  0x0,  0x447,  0x308,  0x0,  0x44b,  0x308,  0x0,  0x44d,  0x308,  0x0,  0x456,  0x308,  0x0,  0x474,  0x30f,  0x0,  0x475,  0x30f,  0x0,  0x4d8,  0x308,  0x0,  0x4d9,  0x308,  0x0,  0x4e8,  0x308,  0x0,  0x4e9,  0x308,  0x0,  0x5d0,  0x5b7,  0x0,  0x5d0,  0x5b8,  0x0,  0x5d0,  0x5bc,  0x0,  0x5d1,  0x5bc,  0x0,  0x5d1,  0x5bf,  0x0,  0x5d2,  0x5bc,  0x0,  0x5d3,  0x5bc,  0x0,  0x5d4,  0x5bc,  0x0,  0x5d5,  0x5b9,  0x0,  0x5d5,  0x5bc,  0x0,  0x5d6,  0x5bc,  0x0,  0x5d8,  0x5bc,  0x0,  0x5d9,  0x5b4,  0x0,  0x5d9,  0x5bc,  0x0,  0x5da,  0x5bc,  0x0,  0x5db,  0x5bc,  0x0,  0x5db,  0x5bf,  0x0,  0x5dc,  0x5bc,  0x0,  0x5de,  0x5bc,  0x0,  0x5e0,  0x5bc,  0x0,  0x5e1,  0x5bc,  0x0,  0x5e3,  0x5bc,  0x0,  0x5e4,  0x5bc,  0x0,  0x5e4,  0x5bf,  0x0,  0x5e6,  0x5bc,  0x0,  0x5e7,  0x5bc,  0x0,  0x5e8,  0x5bc,  0x0,  0x5e9,  0x5bc,  0x0,  0x5e9,  0x5bc,  0x5c1,  0x0,  0x5e9,  0x5bc,  0x5c2,  0x0,  0x5e9,  0x5c1,  0x0,  0x5e9,  0x5c2,  0x0,  0x5ea,  0x5bc,  0x0,  0x5f2,  0x5b7,  0x0,  0x627,  0x653,  0x0,  0x627,  0x654,  0x0,  0x627,  0x655,  0x0,  0x648,  0x654,  0x0,  0x64a,  0x654,  0x0,  0x6c1,  0x654,  0x0,  0x6d2,  0x654,  0x0,  0x6d5,  0x654,  0x0,  0x915,  0x93c,  0x0,  0x916,  0x93c,  0x0,  0x917,  0x93c,  0x0,  0x91c,  0x93c,  0x0,  0x921,  0x93c,  0x0,  0x922,  0x93c,  0x0,  0x928,  0x93c,  0x0,  0x92b,  0x93c,  0x0,  0x92f,  0x93c,  0x0,  0x930,  0x93c,  0x0,  0x933,  0x93c,  0x0,  0x9a1,  0x9bc,  0x0,  0x9a2,  0x9bc,  0x0,  0x9af,  0x9bc,  0x0,  0x9c7,  0x9be,  0x0,  0x9c7,  0x9d7,  0x0,  0xa16,  0xa3c,  0x0,  0xa17,  0xa3c,  0x0,  0xa1c,  0xa3c,  0x0,  0xa2b,  0xa3c,  0x0,  0xa32,  0xa3c,  0x0,  0xa38,  0xa3c,  0x0,  0xb21,  0xb3c,  0x0,  0xb22,  0xb3c,  0x0,  0xb47,  0xb3e,  0x0,  0xb47,  0xb56,  0x0,  0xb47,  0xb57,  0x0,  0xb92,  0xbd7,  0x0,  0xbc6,  0xbbe,  0x0,  0xbc6,  0xbd7,  0x0,  0xbc7,  0xbbe,  0x0,  0xc46,  0xc56,  0x0,  0xcbf,  0xcd5,  0x0,  0xcc6,  0xcc2,  0x0,  0xcc6,  0xcc2,  0xcd5,  0x0,  0xcc6,  0xcd5,  0x0,  0xcc6,  0xcd6,  0x0,  0xd46,  0xd3e,  0x0,  0xd46,  0xd57,  0x0,  0xd47,  0xd3e,  0x0,  0xdd9,  0xdca,  0x0,  0xdd9,  0xdcf,  0x0,  0xdd9,  0xdcf,  0xdca,  0x0,  0xdd9,  0xddf,  0x0,  0xf40,  0xfb5,  0x0,  0xf42,  0xfb7,  0x0,  0xf4c,  0xfb7,  0x0,  0xf51,  0xfb7,  0x0,  0xf56,  0xfb7,  0x0,  0xf5b,  0xfb7,  0x0,  0xf71,  0xf72,  0x0,  0xf71,  0xf74,  0x0,  0xf71,  0xf80,  0x0,  0xf90,  0xfb5,  0x0,  0xf92,  0xfb7,  0x0,  0xf9c,  0xfb7,  0x0,  0xfa1,  0xfb7,  0x0,  0xfa6,  0xfb7,  0x0,  0xfab,  0xfb7,  0x0,  0xfb2,  0xf80,  0x0,  0xfb3,  0xf80,  0x0,  0x1025,  0x102e,  0x0,  0x1b05,  0x1b35,  0x0,  0x1b07,  0x1b35,  0x0,  0x1b09,  0x1b35,  0x0,  0x1b0b,  0x1b35,  0x0,  0x1b0d,  0x1b35,  0x0,  0x1b11,  0x1b35,  0x0,  0x1b3a,  0x1b35,  0x0,  0x1b3c,  0x1b35,  0x0,  0x1b3e,  0x1b35,  0x0,  0x1b3f,  0x1b35,  0x0,  0x1b42,  0x1b35,  0x0,  0x1fbf,  0x300,  0x0,  0x1fbf,  0x301,  0x0,  0x1fbf,  0x342,  0x0,  0x1ffe,  0x300,  0x0,  0x1ffe,  0x301,  0x0,  0x1ffe,  0x342,  0x0,  0x2002,  0x0,  0x2003,  0x0,  0x2190,  0x338,  0x0,  0x2192,  0x338,  0x0,  0x2194,  0x338,  0x0,  0x21d0,  0x338,  0x0,  0x21d2,  0x338,  0x0,  0x21d4,  0x338,  0x0,  0x2203,  0x338,  0x0,  0x2208,  0x338,  0x0,  0x220b,  0x338,  0x0,  0x2223,  0x338,  0x0,  0x2225,  0x338,  0x0,  0x223c,  0x338,  0x0,  0x2243,  0x338,  0x0,  0x2245,  0x338,  0x0,  0x2248,  0x338,  0x0,  0x224d,  0x338,  0x0,  0x2261,  0x338,  0x0,  0x2264,  0x338,  0x0,  0x2265,  0x338,  0x0,  0x2272,  0x338,  0x0,  0x2273,  0x338,  0x0,  0x2276,  0x338,  0x0,  0x2277,  0x338,  0x0,  0x227a,  0x338,  0x0,  0x227b,  0x338,  0x0,  0x227c,  0x338,  0x0,  0x227d,  0x338,  0x0,  0x2282,  0x338,  0x0,  0x2283,  0x338,  0x0,  0x2286,  0x338,  0x0,  0x2287,  0x338,  0x0,  0x2291,  0x338,  0x0,  0x2292,  0x338,  0x0,  0x22a2,  0x338,  0x0,  0x22a8,  0x338,  0x0,  0x22a9,  0x338,  0x0,  0x22ab,  0x338,  0x0,  0x22b2,  0x338,  0x0,  0x22b3,  0x338,  0x0,  0x22b4,  0x338,  0x0,  0x22b5,  0x338,  0x0,  0x2add,  0x338,  0x0,  0x3008,  0x0,  0x3009,  0x0,  0x3046,  0x3099,  0x0,  0x304b,  0x3099,  0x0,  0x304d,  0x3099,  0x0,  0x304f,  0x3099,  0x0,  0x3051,  0x3099,  0x0,  0x3053,  0x3099,  0x0,  0x3055,  0x3099,  0x0,  0x3057,  0x3099,  0x0,  0x3059,  0x3099,  0x0,  0x305b,  0x3099,  0x0,  0x305d,  0x3099,  0x0,  0x305f,  0x3099,  0x0,  0x3061,  0x3099,  0x0,  0x3064,  0x3099,  0x0,  0x3066,  0x3099,  0x0,  0x3068,  0x3099,  0x0,  0x306f,  0x3099,  0x0,  0x306f,  0x309a,  0x0,  0x3072,  0x3099,  0x0,  0x3072,  0x309a,  0x0,  0x3075,  0x3099,  0x0,  0x3075,  0x309a,  0x0,  0x3078,  0x3099,  0x0,  0x3078,  0x309a,  0x0,  0x307b,  0x3099,  0x0,  0x307b,  0x309a,  0x0,  0x309d,  0x3099,  0x0,  0x30a6,  0x3099,  0x0,  0x30ab,  0x3099,  0x0,  0x30ad,  0x3099,  0x0,  0x30af,  0x3099,  0x0,  0x30b1,  0x3099,  0x0,  0x30b3,  0x3099,  0x0,  0x30b5,  0x3099,  0x0,  0x30b7,  0x3099,  0x0,  0x30b9,  0x3099,  0x0,  0x30bb,  0x3099,  0x0,  0x30bd,  0x3099,  0x0,  0x30bf,  0x3099,  0x0,  0x30c1,  0x3099,  0x0,  0x30c4,  0x3099,  0x0,  0x30c6,  0x3099,  0x0,  0x30c8,  0x3099,  0x0,  0x30cf,  0x3099,  0x0,  0x30cf,  0x309a,  0x0,  0x30d2,  0x3099,  0x0,  0x30d2,  0x309a,  0x0,  0x30d5,  0x3099,  0x0,  0x30d5,  0x309a,  0x0,  0x30d8,  0x3099,  0x0,  0x30d8,  0x309a,  0x0,  0x30db,  0x3099,  0x0,  0x30db,  0x309a,  0x0,  0x30ef,  0x3099,  0x0,  0x30f0,  0x3099,  0x0,  0x30f1,  0x3099,  0x0,  0x30f2,  0x3099,  0x0,  0x30fd,  0x3099,  0x0,  0x349e,  0x0,  0x34b9,  0x0,  0x34bb,  0x0,  0x34df,  0x0,  0x3515,  0x0,  0x36ee,  0x0,  0x36fc,  0x0,  0x3781,  0x0,  0x382f,  0x0,  0x3862,  0x0,  0x387c,  0x0,  0x38c7,  0x0,  0x38e3,  0x0,  0x391c,  0x0,  0x393a,  0x0,  0x3a2e,  0x0,  0x3a6c,  0x0,  0x3ae4,  0x0,  0x3b08,  0x0,  0x3b19,  0x0,  0x3b49,  0x0,  0x3b9d,  0x0,  0x3c18,  0x0,  0x3c4e,  0x0,  0x3d33,  0x0,  0x3d96,  0x0,  0x3eac,  0x0,  0x3eb8,  0x0,  0x3f1b,  0x0,  0x3ffc,  0x0,  0x4008,  0x0,  0x4018,  0x0,  0x4039,  0x0,  0x4046,  0x0,  0x4096,  0x0,  0x40e3,  0x0,  0x412f,  0x0,  0x4202,  0x0,  0x4227,  0x0,  0x42a0,  0x0,  0x4301,  0x0,  0x4334,  0x0,  0x4359,  0x0,  0x43d5,  0x0,  0x43d9,  0x0,  0x440b,  0x0,  0x446b,  0x0,  0x452b,  0x0,  0x455d,  0x0,  0x4561,  0x0,  0x456b,  0x0,  0x45d7,  0x0,  0x45f9,  0x0,  0x4635,  0x0,  0x46be,  0x0,  0x46c7,  0x0,  0x4995,  0x0,  0x49e6,  0x0,  0x4a6e,  0x0,  0x4a76,  0x0,  0x4ab2,  0x0,  0x4b33,  0x0,  0x4bce,  0x0,  0x4cce,  0x0,  0x4ced,  0x0,  0x4cf8,  0x0,  0x4d56,  0x0,  0x4e0d,  0x0,  0x4e26,  0x0,  0x4e32,  0x0,  0x4e38,  0x0,  0x4e39,  0x0,  0x4e3d,  0x0,  0x4e41,  0x0,  0x4e82,  0x0,  0x4e86,  0x0,  0x4eae,  0x0,  0x4ec0,  0x0,  0x4ecc,  0x0,  0x4ee4,  0x0,  0x4f60,  0x0,  0x4f80,  0x0,  0x4f86,  0x0,  0x4f8b,  0x0,  0x4fae,  0x0,  0x4fbb,  0x0,  0x4fbf,  0x0,  0x5002,  0x0,  0x502b,  0x0,  0x507a,  0x0,  0x5099,  0x0,  0x50cf,  0x0,  0x50da,  0x0,  0x50e7,  0x0,  0x5140,  0x0,  0x5145,  0x0,  0x514d,  0x0,  0x5154,  0x0,  0x5164,  0x0,  0x5167,  0x0,  0x5168,  0x0,  0x5169,  0x0,  0x516d,  0x0,  0x5177,  0x0,  0x5180,  0x0,  0x518d,  0x0,  0x5192,  0x0,  0x5195,  0x0,  0x5197,  0x0,  0x51a4,  0x0,  0x51ac,  0x0,  0x51b5,  0x0,  0x51b7,  0x0,  0x51c9,  0x0,  0x51cc,  0x0,  0x51dc,  0x0,  0x51de,  0x0,  0x51f5,  0x0,  0x5203,  0x0,  0x5207,  0x0,  0x5217,  0x0,  0x5229,  0x0,  0x523a,  0x0,  0x523b,  0x0,  0x5246,  0x0,  0x5272,  0x0,  0x5277,  0x0,  0x5289,  0x0,  0x529b,  0x0,  0x52a3,  0x0,  0x52b3,  0x0,  0x52c7,  0x0,  0x52c9,  0x0,  0x52d2,  0x0,  0x52de,  0x0,  0x52e4,  0x0,  0x52f5,  0x0,  0x52fa,  0x0,  0x5305,  0x0,  0x5306,  0x0,  0x5317,  0x0,  0x533f,  0x0,  0x5349,  0x0,  0x5351,  0x0,  0x535a,  0x0,  0x5373,  0x0,  0x5375,  0x0,  0x537d,  0x0,  0x537f,  0x0,  0x53c3,  0x0,  0x53ca,  0x0,  0x53df,  0x0,  0x53e5,  0x0,  0x53eb,  0x0,  0x53f1,  0x0,  0x5406,  0x0,  0x540f,  0x0,  0x541d,  0x0,  0x5438,  0x0,  0x5442,  0x0,  0x5448,  0x0,  0x5468,  0x0,  0x549e,  0x0,  0x54a2,  0x0,  0x54bd,  0x0,  0x54f6,  0x0,  0x5510,  0x0,  0x5553,  0x0,  0x5555,  0x0,  0x5563,  0x0,  0x5584,  0x0,  0x5587,  0x0,  0x5599,  0x0,  0x559d,  0x0,  0x55ab,  0x0,  0x55b3,  0x0,  0x55c0,  0x0,  0x55c2,  0x0,  0x55e2,  0x0,  0x5606,  0x0,  0x5651,  0x0,  0x5668,  0x0,  0x5674,  0x0,  0x56f9,  0x0,  0x5716,  0x0,  0x5717,  0x0,  0x578b,  0x0,  0x57ce,  0x0,  0x57f4,  0x0,  0x580d,  0x0,  0x5831,  0x0,  0x5832,  0x0,  0x5840,  0x0,  0x585a,  0x0,  0x585e,  0x0,  0x58a8,  0x0,  0x58ac,  0x0,  0x58b3,  0x0,  0x58d8,  0x0,  0x58df,  0x0,  0x58ee,  0x0,  0x58f2,  0x0,  0x58f7,  0x0,  0x5906,  0x0,  0x591a,  0x0,  0x5922,  0x0,  0x5944,  0x0,  0x5948,  0x0,  0x5951,  0x0,  0x5954,  0x0,  0x5962,  0x0,  0x5973,  0x0,  0x59d8,  0x0,  0x59ec,  0x0,  0x5a1b,  0x0,  0x5a27,  0x0,  0x5a62,  0x0,  0x5a66,  0x0,  0x5ab5,  0x0,  0x5b08,  0x0,  0x5b28,  0x0,  0x5b3e,  0x0,  0x5b85,  0x0,  0x5bc3,  0x0,  0x5bd8,  0x0,  0x5be7,  0x0,  0x5bee,  0x0,  0x5bf3,  0x0,  0x5bff,  0x0,  0x5c06,  0x0,  0x5c22,  0x0,  0x5c3f,  0x0,  0x5c60,  0x0,  0x5c62,  0x0,  0x5c64,  0x0,  0x5c65,  0x0,  0x5c6e,  0x0,  0x5c8d,  0x0,  0x5cc0,  0x0,  0x5d19,  0x0,  0x5d43,  0x0,  0x5d50,  0x0,  0x5d6b,  0x0,  0x5d6e,  0x0,  0x5d7c,  0x0,  0x5db2,  0x0,  0x5dba,  0x0,  0x5de1,  0x0,  0x5de2,  0x0,  0x5dfd,  0x0,  0x5e28,  0x0,  0x5e3d,  0x0,  0x5e69,  0x0,  0x5e74,  0x0,  0x5ea6,  0x0,  0x5eb0,  0x0,  0x5eb3,  0x0,  0x5eb6,  0x0,  0x5ec9,  0x0,  0x5eca,  0x0,  0x5ed2,  0x0,  0x5ed3,  0x0,  0x5ed9,  0x0,  0x5eec,  0x0,  0x5efe,  0x0,  0x5f04,  0x0,  0x5f22,  0x0,  0x5f53,  0x0,  0x5f62,  0x0,  0x5f69,  0x0,  0x5f6b,  0x0,  0x5f8b,  0x0,  0x5f9a,  0x0,  0x5fa9,  0x0,  0x5fad,  0x0,  0x5fcd,  0x0,  0x5fd7,  0x0,  0x5ff5,  0x0,  0x5ff9,  0x0,  0x6012,  0x0,  0x601c,  0x0,  0x6075,  0x0,  0x6081,  0x0,  0x6094,  0x0,  0x60c7,  0x0,  0x60d8,  0x0,  0x60e1,  0x0,  0x6108,  0x0,  0x6144,  0x0,  0x6148,  0x0,  0x614c,  0x0,  0x614e,  0x0,  0x6160,  0x0,  0x6168,  0x0,  0x617a,  0x0,  0x618e,  0x0,  0x6190,  0x0,  0x61a4,  0x0,  0x61af,  0x0,  0x61b2,  0x0,  0x61de,  0x0,  0x61f2,  0x0,  0x61f6,  0x0,  0x6200,  0x0,  0x6210,  0x0,  0x621b,  0x0,  0x622e,  0x0,  0x6234,  0x0,  0x625d,  0x0,  0x62b1,  0x0,  0x62c9,  0x0,  0x62cf,  0x0,  0x62d3,  0x0,  0x62d4,  0x0,  0x62fc,  0x0,  0x62fe,  0x0,  0x633d,  0x0,  0x6350,  0x0,  0x6368,  0x0,  0x637b,  0x0,  0x6383,  0x0,  0x63a0,  0x0,  0x63a9,  0x0,  0x63c4,  0x0,  0x63c5,  0x0,  0x63e4,  0x0,  0x641c,  0x0,  0x6422,  0x0,  0x6452,  0x0,  0x6469,  0x0,  0x6477,  0x0,  0x647e,  0x0,  0x649a,  0x0,  0x649d,  0x0,  0x64c4,  0x0,  0x654f,  0x0,  0x6556,  0x0,  0x656c,  0x0,  0x6578,  0x0,  0x6599,  0x0,  0x65c5,  0x0,  0x65e2,  0x0,  0x65e3,  0x0,  0x6613,  0x0,  0x6649,  0x0,  0x6674,  0x0,  0x6688,  0x0,  0x6691,  0x0,  0x669c,  0x0,  0x66b4,  0x0,  0x66c6,  0x0,  0x66f4,  0x0,  0x66f8,  0x0,  0x6700,  0x0,  0x6717,  0x0,  0x671b,  0x0,  0x6721,  0x0,  0x674e,  0x0,  0x6753,  0x0,  0x6756,  0x0,  0x675e,  0x0,  0x677b,  0x0,  0x6785,  0x0,  0x6797,  0x0,  0x67f3,  0x0,  0x67fa,  0x0,  0x6817,  0x0,  0x681f,  0x0,  0x6852,  0x0,  0x6881,  0x0,  0x6885,  0x0,  0x688e,  0x0,  0x68a8,  0x0,  0x6914,  0x0,  0x6942,  0x0,  0x69a3,  0x0,  0x69ea,  0x0,  0x6a02,  0x0,  0x6a13,  0x0,  0x6aa8,  0x0,  0x6ad3,  0x0,  0x6adb,  0x0,  0x6b04,  0x0,  0x6b21,  0x0,  0x6b54,  0x0,  0x6b72,  0x0,  0x6b77,  0x0,  0x6b79,  0x0,  0x6b9f,  0x0,  0x6bae,  0x0,  0x6bba,  0x0,  0x6bbb,  0x0,  0x6c4e,  0x0,  0x6c67,  0x0,  0x6c88,  0x0,  0x6cbf,  0x0,  0x6ccc,  0x0,  0x6ccd,  0x0,  0x6ce5,  0x0,  0x6d16,  0x0,  0x6d1b,  0x0,  0x6d1e,  0x0,  0x6d34,  0x0,  0x6d3e,  0x0,  0x6d41,  0x0,  0x6d69,  0x0,  0x6d6a,  0x0,  0x6d77,  0x0,  0x6d78,  0x0,  0x6d85,  0x0,  0x6dcb,  0x0,  0x6dda,  0x0,  0x6dea,  0x0,  0x6df9,  0x0,  0x6e1a,  0x0,  0x6e2f,  0x0,  0x6e6e,  0x0,  0x6e9c,  0x0,  0x6eba,  0x0,  0x6ec7,  0x0,  0x6ecb,  0x0,  0x6ed1,  0x0,  0x6edb,  0x0,  0x6f0f,  0x0,  0x6f22,  0x0,  0x6f23,  0x0,  0x6f6e,  0x0,  0x6fc6,  0x0,  0x6feb,  0x0,  0x6ffe,  0x0,  0x701b,  0x0,  0x701e,  0x0,  0x7039,  0x0,  0x704a,  0x0,  0x7070,  0x0,  0x7077,  0x0,  0x707d,  0x0,  0x7099,  0x0,  0x70ad,  0x0,  0x70c8,  0x0,  0x70d9,  0x0,  0x7145,  0x0,  0x7149,  0x0,  0x716e,  0x0,  0x719c,  0x0,  0x71ce,  0x0,  0x71d0,  0x0,  0x7210,  0x0,  0x721b,  0x0,  0x7228,  0x0,  0x722b,  0x0,  0x7235,  0x0,  0x7250,  0x0,  0x7262,  0x0,  0x7280,  0x0,  0x7295,  0x0,  0x72af,  0x0,  0x72c0,  0x0,  0x72fc,  0x0,  0x732a,  0x0,  0x7375,  0x0,  0x737a,  0x0,  0x7387,  0x0,  0x738b,  0x0,  0x73a5,  0x0,  0x73b2,  0x0,  0x73de,  0x0,  0x7406,  0x0,  0x7409,  0x0,  0x7422,  0x0,  0x7447,  0x0,  0x745c,  0x0,  0x7469,  0x0,  0x7471,  0x0,  0x7485,  0x0,  0x7489,  0x0,  0x7498,  0x0,  0x74ca,  0x0,  0x7506,  0x0,  0x7524,  0x0,  0x753b,  0x0,  0x753e,  0x0,  0x7559,  0x0,  0x7565,  0x0,  0x7570,  0x0,  0x75e2,  0x0,  0x7610,  0x0,  0x761d,  0x0,  0x761f,  0x0,  0x7642,  0x0,  0x7669,  0x0,  0x76ca,  0x0,  0x76db,  0x0,  0x76e7,  0x0,  0x76f4,  0x0,  0x7701,  0x0,  0x771e,  0x0,  0x771f,  0x0,  0x7740,  0x0,  0x774a,  0x0,  0x778b,  0x0,  0x77a7,  0x0,  0x784e,  0x0,  0x786b,  0x0,  0x788c,  0x0,  0x7891,  0x0,  0x78ca,  0x0,  0x78cc,  0x0,  0x78fb,  0x0,  0x792a,  0x0,  0x793c,  0x0,  0x793e,  0x0,  0x7948,  0x0,  0x7949,  0x0,  0x7950,  0x0,  0x7956,  0x0,  0x795d,  0x0,  0x795e,  0x0,  0x7965,  0x0,  0x797f,  0x0,  0x798d,  0x0,  0x798e,  0x0,  0x798f,  0x0,  0x79ae,  0x0,  0x79ca,  0x0,  0x79eb,  0x0,  0x7a1c,  0x0,  0x7a40,  0x0,  0x7a4a,  0x0,  0x7a4f,  0x0,  0x7a81,  0x0,  0x7ab1,  0x0,  0x7acb,  0x0,  0x7aee,  0x0,  0x7b20,  0x0,  0x7bc0,  0x0,  0x7bc6,  0x0,  0x7bc9,  0x0,  0x7c3e,  0x0,  0x7c60,  0x0,  0x7c7b,  0x0,  0x7c92,  0x0,  0x7cbe,  0x0,  0x7cd2,  0x0,  0x7cd6,  0x0,  0x7ce3,  0x0,  0x7ce7,  0x0,  0x7ce8,  0x0,  0x7d00,  0x0,  0x7d10,  0x0,  0x7d22,  0x0,  0x7d2f,  0x0,  0x7d5b,  0x0,  0x7d63,  0x0,  0x7da0,  0x0,  0x7dbe,  0x0,  0x7dc7,  0x0,  0x7df4,  0x0,  0x7e02,  0x0,  0x7e09,  0x0,  0x7e37,  0x0,  0x7e41,  0x0,  0x7e45,  0x0,  0x7f3e,  0x0,  0x7f72,  0x0,  0x7f79,  0x0,  0x7f7a,  0x0,  0x7f85,  0x0,  0x7f95,  0x0,  0x7f9a,  0x0,  0x7fbd,  0x0,  0x7ffa,  0x0,  0x8001,  0x0,  0x8005,  0x0,  0x8046,  0x0,  0x8060,  0x0,  0x806f,  0x0,  0x8070,  0x0,  0x807e,  0x0,  0x808b,  0x0,  0x80ad,  0x0,  0x80b2,  0x0,  0x8103,  0x0,  0x813e,  0x0,  0x81d8,  0x0,  0x81e8,  0x0,  0x81ed,  0x0,  0x8201,  0x0,  0x8204,  0x0,  0x8218,  0x0,  0x826f,  0x0,  0x8279,  0x0,  0x828b,  0x0,  0x8291,  0x0,  0x829d,  0x0,  0x82b1,  0x0,  0x82b3,  0x0,  0x82bd,  0x0,  0x82e5,  0x0,  0x82e6,  0x0,  0x831d,  0x0,  0x8323,  0x0,  0x8336,  0x0,  0x8352,  0x0,  0x8353,  0x0,  0x8363,  0x0,  0x83ad,  0x0,  0x83bd,  0x0,  0x83c9,  0x0,  0x83ca,  0x0,  0x83cc,  0x0,  0x83dc,  0x0,  0x83e7,  0x0,  0x83ef,  0x0,  0x83f1,  0x0,  0x843d,  0x0,  0x8449,  0x0,  0x8457,  0x0,  0x84ee,  0x0,  0x84f1,  0x0,  0x84f3,  0x0,  0x84fc,  0x0,  0x8516,  0x0,  0x8564,  0x0,  0x85cd,  0x0,  0x85fa,  0x0,  0x8606,  0x0,  0x8612,  0x0,  0x862d,  0x0,  0x863f,  0x0,  0x8650,  0x0,  0x865c,  0x0,  0x8667,  0x0,  0x8669,  0x0,  0x8688,  0x0,  0x86a9,  0x0,  0x86e2,  0x0,  0x870e,  0x0,  0x8728,  0x0,  0x876b,  0x0,  0x8779,  0x0,  0x8786,  0x0,  0x87ba,  0x0,  0x87e1,  0x0,  0x8801,  0x0,  0x881f,  0x0,  0x884c,  0x0,  0x8860,  0x0,  0x8863,  0x0,  0x88c2,  0x0,  0x88cf,  0x0,  0x88d7,  0x0,  0x88de,  0x0,  0x88e1,  0x0,  0x88f8,  0x0,  0x88fa,  0x0,  0x8910,  0x0,  0x8941,  0x0,  0x8964,  0x0,  0x8986,  0x0,  0x898b,  0x0,  0x8996,  0x0,  0x8aa0,  0x0,  0x8aaa,  0x0,  0x8abf,  0x0,  0x8acb,  0x0,  0x8ad2,  0x0,  0x8ad6,  0x0,  0x8aed,  0x0,  0x8af8,  0x0,  0x8afe,  0x0,  0x8b01,  0x0,  0x8b39,  0x0,  0x8b58,  0x0,  0x8b80,  0x0,  0x8b8a,  0x0,  0x8c48,  0x0,  0x8c55,  0x0,  0x8cab,  0x0,  0x8cc1,  0x0,  0x8cc2,  0x0,  0x8cc8,  0x0,  0x8cd3,  0x0,  0x8d08,  0x0,  0x8d1b,  0x0,  0x8d77,  0x0,  0x8dbc,  0x0,  0x8dcb,  0x0,  0x8def,  0x0,  0x8df0,  0x0,  0x8eca,  0x0,  0x8ed4,  0x0,  0x8f26,  0x0,  0x8f2a,  0x0,  0x8f38,  0x0,  0x8f3b,  0x0,  0x8f62,  0x0,  0x8f9e,  0x0,  0x8fb0,  0x0,  0x8fb6,  0x0,  0x9023,  0x0,  0x9038,  0x0,  0x9072,  0x0,  0x907c,  0x0,  0x908f,  0x0,  0x9094,  0x0,  0x90ce,  0x0,  0x90de,  0x0,  0x90f1,  0x0,  0x90fd,  0x0,  0x9111,  0x0,  0x911b,  0x0,  0x916a,  0x0,  0x9199,  0x0,  0x91b4,  0x0,  0x91cc,  0x0,  0x91cf,  0x0,  0x91d1,  0x0,  0x9234,  0x0,  0x9238,  0x0,  0x9276,  0x0,  0x927c,  0x0,  0x92d7,  0x0,  0x92d8,  0x0,  0x9304,  0x0,  0x934a,  0x0,  0x93f9,  0x0,  0x9415,  0x0,  0x958b,  0x0,  0x95ad,  0x0,  0x95b7,  0x0,  0x962e,  0x0,  0x964b,  0x0,  0x964d,  0x0,  0x9675,  0x0,  0x9678,  0x0,  0x967c,  0x0,  0x9686,  0x0,  0x96a3,  0x0,  0x96b7,  0x0,  0x96b8,  0x0,  0x96c3,  0x0,  0x96e2,  0x0,  0x96e3,  0x0,  0x96f6,  0x0,  0x96f7,  0x0,  0x9723,  0x0,  0x9732,  0x0,  0x9748,  0x0,  0x9756,  0x0,  0x97db,  0x0,  0x97e0,  0x0,  0x97ff,  0x0,  0x980b,  0x0,  0x9818,  0x0,  0x9829,  0x0,  0x983b,  0x0,  0x985e,  0x0,  0x98e2,  0x0,  0x98ef,  0x0,  0x98fc,  0x0,  0x9928,  0x0,  0x9929,  0x0,  0x99a7,  0x0,  0x99c2,  0x0,  0x99f1,  0x0,  0x99fe,  0x0,  0x9a6a,  0x0,  0x9b12,  0x0,  0x9b6f,  0x0,  0x9c40,  0x0,  0x9c57,  0x0,  0x9cfd,  0x0,  0x9d67,  0x0,  0x9db4,  0x0,  0x9dfa,  0x0,  0x9e1e,  0x0,  0x9e7f,  0x0,  0x9e97,  0x0,  0x9e9f,  0x0,  0x9ebb,  0x0,  0x9ece,  0x0,  0x9ef9,  0x0,  0x9efe,  0x0,  0x9f05,  0x0,  0x9f0f,  0x0,  0x9f16,  0x0,  0x9f3b,  0x0,  0x9f43,  0x0,  0x9f8d,  0x0,  0x9f8e,  0x0,  0x9f9c,  0x0,  0x11099,  0x110ba,  0x0,  0x1109b,  0x110ba,  0x0,  0x110a5,  0x110ba,  0x0,  0x11131,  0x11127,  0x0,  0x11132,  0x11127,  0x0,  0x1d157,  0x1d165,  0x0,  0x1d158,  0x1d165,  0x0,  0x1d158,  0x1d165,  0x1d16e,  0x0,  0x1d158,  0x1d165,  0x1d16f,  0x0,  0x1d158,  0x1d165,  0x1d170,  0x0,  0x1d158,  0x1d165,  0x1d171,  0x0,  0x1d158,  0x1d165,  0x1d172,  0x0,  0x1d1b9,  0x1d165,  0x0,  0x1d1b9,  0x1d165,  0x1d16e,  0x0,  0x1d1b9,  0x1d165,  0x1d16f,  0x0,  0x1d1ba,  0x1d165,  0x0,  0x1d1ba,  0x1d165,  0x1d16e,  0x0,  0x1d1ba,  0x1d165,  0x1d16f,  0x0,  0x20122,  0x0,  0x2051c,  0x0,  0x20525,  0x0,  0x2054b,  0x0,  0x2063a,  0x0,  0x20804,  0x0,  0x208de,  0x0,  0x20a2c,  0x0,  0x20b63,  0x0,  0x214e4,  0x0,  0x216a8,  0x0,  0x216ea,  0x0,  0x219c8,  0x0,  0x21b18,  0x0,  0x21d0b,  0x0,  0x21de4,  0x0,  0x21de6,  0x0,  0x22183,  0x0,  0x2219f,  0x0,  0x22331,  0x0,  0x226d4,  0x0,  0x22844,  0x0,  0x2284a,  0x0,  0x22b0c,  0x0,  0x22bf1,  0x0,  0x2300a,  0x0,  0x232b8,  0x0,  0x2335f,  0x0,  0x23393,  0x0,  0x2339c,  0x0,  0x233c3,  0x0,  0x233d5,  0x0,  0x2346d,  0x0,  0x236a3,  0x0,  0x238a7,  0x0,  0x23a8d,  0x0,  0x23afa,  0x0,  0x23cbc,  0x0,  0x23d1e,  0x0,  0x23ed1,  0x0,  0x23f5e,  0x0,  0x23f8e,  0x0,  0x24263,  0x0,  0x242ee,  0x0,  0x243ab,  0x0,  0x24608,  0x0,  0x24735,  0x0,  0x24814,  0x0,  0x24c36,  0x0,  0x24c92,  0x0,  0x24fa1,  0x0,  0x24fb8,  0x0,  0x25044,  0x0,  0x250f2,  0x0,  0x250f3,  0x0,  0x25119,  0x0,  0x25133,  0x0,  0x25249,  0x0,  0x2541d,  0x0,  0x25626,  0x0,  0x2569a,  0x0,  0x256c5,  0x0,  0x2597c,  0x0,  0x25aa7,  0x0,  0x25bab,  0x0,  0x25c80,  0x0,  0x25cd0,  0x0,  0x25f86,  0x0,  0x261da,  0x0,  0x26228,  0x0,  0x26247,  0x0,  0x262d9,  0x0,  0x2633e,  0x0,  0x264da,  0x0,  0x26523,  0x0,  0x265a8,  0x0,  0x267a7,  0x0,  0x267b5,  0x0,  0x26b3c,  0x0,  0x26c36,  0x0,  0x26cd5,  0x0,  0x26d6b,  0x0,  0x26f2c,  0x0,  0x26fb1,  0x0,  0x270d2,  0x0,  0x273ca,  0x0,  0x27667,  0x0,  0x278ae,  0x0,  0x27966,  0x0,  0x27ca8,  0x0,  0x27ed3,  0x0,  0x27f2f,  0x0,  0x285d2,  0x0,  0x285ed,  0x0,  0x2872e,  0x0,  0x28bfa,  0x0,  0x28d77,  0x0,  0x29145,  0x0,  0x291df,  0x0,  0x2921a,  0x0,  0x2940a,  0x0,  0x29496,  0x0,  0x295b6,  0x0,  0x29b30,  0x0,  0x2a0ce,  0x0,  0x2a105,  0x0,  0x2a20e,  0x0,  0x2a291,  0x0,  0x2a392,  0x0,  0x2a600,  0x0]; return t; }
+_IDCA decompCompatTable() { static _IDCA t = [ 0x0,  0x20,  0x0,  0x20,  0x301,  0x0,  0x20,  0x303,  0x0,  0x20,  0x304,  0x0,  0x20,  0x305,  0x0,  0x20,  0x306,  0x0,  0x20,  0x307,  0x0,  0x20,  0x308,  0x0,  0x20,  0x308,  0x300,  0x0,  0x20,  0x308,  0x301,  0x0,  0x20,  0x308,  0x342,  0x0,  0x20,  0x30a,  0x0,  0x20,  0x30b,  0x0,  0x20,  0x313,  0x0,  0x20,  0x313,  0x300,  0x0,  0x20,  0x313,  0x301,  0x0,  0x20,  0x313,  0x342,  0x0,  0x20,  0x314,  0x0,  0x20,  0x314,  0x300,  0x0,  0x20,  0x314,  0x301,  0x0,  0x20,  0x314,  0x342,  0x0,  0x20,  0x327,  0x0,  0x20,  0x328,  0x0,  0x20,  0x333,  0x0,  0x20,  0x342,  0x0,  0x20,  0x345,  0x0,  0x20,  0x64b,  0x0,  0x20,  0x64c,  0x0,  0x20,  0x64c,  0x651,  0x0,  0x20,  0x64d,  0x0,  0x20,  0x64d,  0x651,  0x0,  0x20,  0x64e,  0x0,  0x20,  0x64e,  0x651,  0x0,  0x20,  0x64f,  0x0,  0x20,  0x64f,  0x651,  0x0,  0x20,  0x650,  0x0,  0x20,  0x650,  0x651,  0x0,  0x20,  0x651,  0x0,  0x20,  0x651,  0x670,  0x0,  0x20,  0x652,  0x0,  0x20,  0x3099,  0x0,  0x20,  0x309a,  0x0,  0x21,  0x0,  0x21,  0x21,  0x0,  0x21,  0x3f,  0x0,  0x22,  0x0,  0x23,  0x0,  0x24,  0x0,  0x25,  0x0,  0x26,  0x0,  0x27,  0x0,  0x28,  0x0,  0x28,  0x31,  0x29,  0x0,  0x28,  0x31,  0x30,  0x29,  0x0,  0x28,  0x31,  0x31,  0x29,  0x0,  0x28,  0x31,  0x32,  0x29,  0x0,  0x28,  0x31,  0x33,  0x29,  0x0,  0x28,  0x31,  0x34,  0x29,  0x0,  0x28,  0x31,  0x35,  0x29,  0x0,  0x28,  0x31,  0x36,  0x29,  0x0,  0x28,  0x31,  0x37,  0x29,  0x0,  0x28,  0x31,  0x38,  0x29,  0x0,  0x28,  0x31,  0x39,  0x29,  0x0,  0x28,  0x32,  0x29,  0x0,  0x28,  0x32,  0x30,  0x29,  0x0,  0x28,  0x33,  0x29,  0x0,  0x28,  0x34,  0x29,  0x0,  0x28,  0x35,  0x29,  0x0,  0x28,  0x36,  0x29,  0x0,  0x28,  0x37,  0x29,  0x0,  0x28,  0x38,  0x29,  0x0,  0x28,  0x39,  0x29,  0x0,  0x28,  0x41,  0x29,  0x0,  0x28,  0x42,  0x29,  0x0,  0x28,  0x43,  0x29,  0x0,  0x28,  0x44,  0x29,  0x0,  0x28,  0x45,  0x29,  0x0,  0x28,  0x46,  0x29,  0x0,  0x28,  0x47,  0x29,  0x0,  0x28,  0x48,  0x29,  0x0,  0x28,  0x49,  0x29,  0x0,  0x28,  0x4a,  0x29,  0x0,  0x28,  0x4b,  0x29,  0x0,  0x28,  0x4c,  0x29,  0x0,  0x28,  0x4d,  0x29,  0x0,  0x28,  0x4e,  0x29,  0x0,  0x28,  0x4f,  0x29,  0x0,  0x28,  0x50,  0x29,  0x0,  0x28,  0x51,  0x29,  0x0,  0x28,  0x52,  0x29,  0x0,  0x28,  0x53,  0x29,  0x0,  0x28,  0x54,  0x29,  0x0,  0x28,  0x55,  0x29,  0x0,  0x28,  0x56,  0x29,  0x0,  0x28,  0x57,  0x29,  0x0,  0x28,  0x58,  0x29,  0x0,  0x28,  0x59,  0x29,  0x0,  0x28,  0x5a,  0x29,  0x0,  0x28,  0x61,  0x29,  0x0,  0x28,  0x62,  0x29,  0x0,  0x28,  0x63,  0x29,  0x0,  0x28,  0x64,  0x29,  0x0,  0x28,  0x65,  0x29,  0x0,  0x28,  0x66,  0x29,  0x0,  0x28,  0x67,  0x29,  0x0,  0x28,  0x68,  0x29,  0x0,  0x28,  0x69,  0x29,  0x0,  0x28,  0x6a,  0x29,  0x0,  0x28,  0x6b,  0x29,  0x0,  0x28,  0x6c,  0x29,  0x0,  0x28,  0x6d,  0x29,  0x0,  0x28,  0x6e,  0x29,  0x0,  0x28,  0x6f,  0x29,  0x0,  0x28,  0x70,  0x29,  0x0,  0x28,  0x71,  0x29,  0x0,  0x28,  0x72,  0x29,  0x0,  0x28,  0x73,  0x29,  0x0,  0x28,  0x74,  0x29,  0x0,  0x28,  0x75,  0x29,  0x0,  0x28,  0x76,  0x29,  0x0,  0x28,  0x77,  0x29,  0x0,  0x28,  0x78,  0x29,  0x0,  0x28,  0x79,  0x29,  0x0,  0x28,  0x7a,  0x29,  0x0,  0x28,  0x1100,  0x29,  0x0,  0x28,  0x1100,  0x1161,  0x29,  0x0,  0x28,  0x1102,  0x29,  0x0,  0x28,  0x1102,  0x1161,  0x29,  0x0,  0x28,  0x1103,  0x29,  0x0,  0x28,  0x1103,  0x1161,  0x29,  0x0,  0x28,  0x1105,  0x29,  0x0,  0x28,  0x1105,  0x1161,  0x29,  0x0,  0x28,  0x1106,  0x29,  0x0,  0x28,  0x1106,  0x1161,  0x29,  0x0,  0x28,  0x1107,  0x29,  0x0,  0x28,  0x1107,  0x1161,  0x29,  0x0,  0x28,  0x1109,  0x29,  0x0,  0x28,  0x1109,  0x1161,  0x29,  0x0,  0x28,  0x110b,  0x29,  0x0,  0x28,  0x110b,  0x1161,  0x29,  0x0,  0x28,  0x110b,  0x1169,  0x110c,  0x1165,  0x11ab,  0x29,  0x0,  0x28,  0x110b,  0x1169,  0x1112,  0x116e,  0x29,  0x0,  0x28,  0x110c,  0x29,  0x0,  0x28,  0x110c,  0x1161,  0x29,  0x0,  0x28,  0x110c,  0x116e,  0x29,  0x0,  0x28,  0x110e,  0x29,  0x0,  0x28,  0x110e,  0x1161,  0x29,  0x0,  0x28,  0x110f,  0x29,  0x0,  0x28,  0x110f,  0x1161,  0x29,  0x0,  0x28,  0x1110,  0x29,  0x0,  0x28,  0x1110,  0x1161,  0x29,  0x0,  0x28,  0x1111,  0x29,  0x0,  0x28,  0x1111,  0x1161,  0x29,  0x0,  0x28,  0x1112,  0x29,  0x0,  0x28,  0x1112,  0x1161,  0x29,  0x0,  0x28,  0x4e00,  0x29,  0x0,  0x28,  0x4e03,  0x29,  0x0,  0x28,  0x4e09,  0x29,  0x0,  0x28,  0x4e5d,  0x29,  0x0,  0x28,  0x4e8c,  0x29,  0x0,  0x28,  0x4e94,  0x29,  0x0,  0x28,  0x4ee3,  0x29,  0x0,  0x28,  0x4f01,  0x29,  0x0,  0x28,  0x4f11,  0x29,  0x0,  0x28,  0x516b,  0x29,  0x0,  0x28,  0x516d,  0x29,  0x0,  0x28,  0x52b4,  0x29,  0x0,  0x28,  0x5341,  0x29,  0x0,  0x28,  0x5354,  0x29,  0x0,  0x28,  0x540d,  0x29,  0x0,  0x28,  0x547c,  0x29,  0x0,  0x28,  0x56db,  0x29,  0x0,  0x28,  0x571f,  0x29,  0x0,  0x28,  0x5b66,  0x29,  0x0,  0x28,  0x65e5,  0x29,  0x0,  0x28,  0x6708,  0x29,  0x0,  0x28,  0x6709,  0x29,  0x0,  0x28,  0x6728,  0x29,  0x0,  0x28,  0x682a,  0x29,  0x0,  0x28,  0x6c34,  0x29,  0x0,  0x28,  0x706b,  0x29,  0x0,  0x28,  0x7279,  0x29,  0x0,  0x28,  0x76e3,  0x29,  0x0,  0x28,  0x793e,  0x29,  0x0,  0x28,  0x795d,  0x29,  0x0,  0x28,  0x796d,  0x29,  0x0,  0x28,  0x81ea,  0x29,  0x0,  0x28,  0x81f3,  0x29,  0x0,  0x28,  0x8ca1,  0x29,  0x0,  0x28,  0x8cc7,  0x29,  0x0,  0x28,  0x91d1,  0x29,  0x0,  0x29,  0x0,  0x2a,  0x0,  0x2b,  0x0,  0x2c,  0x0,  0x2d,  0x0,  0x2e,  0x0,  0x2e,  0x2e,  0x0,  0x2e,  0x2e,  0x2e,  0x0,  0x2f,  0x0,  0x30,  0x0,  0x30,  0x2c,  0x0,  0x30,  0x2e,  0x0,  0x30,  0x2044,  0x33,  0x0,  0x30,  0x70b9,  0x0,  0x31,  0x0,  0x31,  0x2c,  0x0,  0x31,  0x2e,  0x0,  0x31,  0x30,  0x0,  0x31,  0x30,  0x2e,  0x0,  0x31,  0x30,  0x65e5,  0x0,  0x31,  0x30,  0x6708,  0x0,  0x31,  0x30,  0x70b9,  0x0,  0x31,  0x31,  0x0,  0x31,  0x31,  0x2e,  0x0,  0x31,  0x31,  0x65e5,  0x0,  0x31,  0x31,  0x6708,  0x0,  0x31,  0x31,  0x70b9,  0x0,  0x31,  0x32,  0x0,  0x31,  0x32,  0x2e,  0x0,  0x31,  0x32,  0x65e5,  0x0,  0x31,  0x32,  0x6708,  0x0,  0x31,  0x32,  0x70b9,  0x0,  0x31,  0x33,  0x0,  0x31,  0x33,  0x2e,  0x0,  0x31,  0x33,  0x65e5,  0x0,  0x31,  0x33,  0x70b9,  0x0,  0x31,  0x34,  0x0,  0x31,  0x34,  0x2e,  0x0,  0x31,  0x34,  0x65e5,  0x0,  0x31,  0x34,  0x70b9,  0x0,  0x31,  0x35,  0x0,  0x31,  0x35,  0x2e,  0x0,  0x31,  0x35,  0x65e5,  0x0,  0x31,  0x35,  0x70b9,  0x0,  0x31,  0x36,  0x0,  0x31,  0x36,  0x2e,  0x0,  0x31,  0x36,  0x65e5,  0x0,  0x31,  0x36,  0x70b9,  0x0,  0x31,  0x37,  0x0,  0x31,  0x37,  0x2e,  0x0,  0x31,  0x37,  0x65e5,  0x0,  0x31,  0x37,  0x70b9,  0x0,  0x31,  0x38,  0x0,  0x31,  0x38,  0x2e,  0x0,  0x31,  0x38,  0x65e5,  0x0,  0x31,  0x38,  0x70b9,  0x0,  0x31,  0x39,  0x0,  0x31,  0x39,  0x2e,  0x0,  0x31,  0x39,  0x65e5,  0x0,  0x31,  0x39,  0x70b9,  0x0,  0x31,  0x2044,  0x0,  0x31,  0x2044,  0x31,  0x30,  0x0,  0x31,  0x2044,  0x32,  0x0,  0x31,  0x2044,  0x33,  0x0,  0x31,  0x2044,  0x34,  0x0,  0x31,  0x2044,  0x35,  0x0,  0x31,  0x2044,  0x36,  0x0,  0x31,  0x2044,  0x37,  0x0,  0x31,  0x2044,  0x38,  0x0,  0x31,  0x2044,  0x39,  0x0,  0x31,  0x65e5,  0x0,  0x31,  0x6708,  0x0,  0x31,  0x70b9,  0x0,  0x32,  0x0,  0x32,  0x2c,  0x0,  0x32,  0x2e,  0x0,  0x32,  0x30,  0x0,  0x32,  0x30,  0x2e,  0x0,  0x32,  0x30,  0x65e5,  0x0,  0x32,  0x30,  0x70b9,  0x0,  0x32,  0x31,  0x0,  0x32,  0x31,  0x65e5,  0x0,  0x32,  0x31,  0x70b9,  0x0,  0x32,  0x32,  0x0,  0x32,  0x32,  0x65e5,  0x0,  0x32,  0x32,  0x70b9,  0x0,  0x32,  0x33,  0x0,  0x32,  0x33,  0x65e5,  0x0,  0x32,  0x33,  0x70b9,  0x0,  0x32,  0x34,  0x0,  0x32,  0x34,  0x65e5,  0x0,  0x32,  0x34,  0x70b9,  0x0,  0x32,  0x35,  0x0,  0x32,  0x35,  0x65e5,  0x0,  0x32,  0x36,  0x0,  0x32,  0x36,  0x65e5,  0x0,  0x32,  0x37,  0x0,  0x32,  0x37,  0x65e5,  0x0,  0x32,  0x38,  0x0,  0x32,  0x38,  0x65e5,  0x0,  0x32,  0x39,  0x0,  0x32,  0x39,  0x65e5,  0x0,  0x32,  0x2044,  0x33,  0x0,  0x32,  0x2044,  0x35,  0x0,  0x32,  0x65e5,  0x0,  0x32,  0x6708,  0x0,  0x32,  0x70b9,  0x0,  0x33,  0x0,  0x33,  0x2c,  0x0,  0x33,  0x2e,  0x0,  0x33,  0x30,  0x0,  0x33,  0x30,  0x65e5,  0x0,  0x33,  0x31,  0x0,  0x33,  0x31,  0x65e5,  0x0,  0x33,  0x32,  0x0,  0x33,  0x33,  0x0,  0x33,  0x34,  0x0,  0x33,  0x35,  0x0,  0x33,  0x36,  0x0,  0x33,  0x37,  0x0,  0x33,  0x38,  0x0,  0x33,  0x39,  0x0,  0x33,  0x2044,  0x34,  0x0,  0x33,  0x2044,  0x35,  0x0,  0x33,  0x2044,  0x38,  0x0,  0x33,  0x65e5,  0x0,  0x33,  0x6708,  0x0,  0x33,  0x70b9,  0x0,  0x34,  0x0,  0x34,  0x2c,  0x0,  0x34,  0x2e,  0x0,  0x34,  0x30,  0x0,  0x34,  0x31,  0x0,  0x34,  0x32,  0x0,  0x34,  0x33,  0x0,  0x34,  0x34,  0x0,  0x34,  0x35,  0x0,  0x34,  0x36,  0x0,  0x34,  0x37,  0x0,  0x34,  0x38,  0x0,  0x34,  0x39,  0x0,  0x34,  0x2044,  0x35,  0x0,  0x34,  0x65e5,  0x0,  0x34,  0x6708,  0x0,  0x34,  0x70b9,  0x0,  0x35,  0x0,  0x35,  0x2c,  0x0,  0x35,  0x2e,  0x0,  0x35,  0x30,  0x0,  0x35,  0x2044,  0x36,  0x0,  0x35,  0x2044,  0x38,  0x0,  0x35,  0x65e5,  0x0,  0x35,  0x6708,  0x0,  0x35,  0x70b9,  0x0,  0x36,  0x0,  0x36,  0x2c,  0x0,  0x36,  0x2e,  0x0,  0x36,  0x65e5,  0x0,  0x36,  0x6708,  0x0,  0x36,  0x70b9,  0x0,  0x37,  0x0,  0x37,  0x2c,  0x0,  0x37,  0x2e,  0x0,  0x37,  0x2044,  0x38,  0x0,  0x37,  0x65e5,  0x0,  0x37,  0x6708,  0x0,  0x37,  0x70b9,  0x0,  0x38,  0x0,  0x38,  0x2c,  0x0,  0x38,  0x2e,  0x0,  0x38,  0x65e5,  0x0,  0x38,  0x6708,  0x0,  0x38,  0x70b9,  0x0,  0x39,  0x0,  0x39,  0x2c,  0x0,  0x39,  0x2e,  0x0,  0x39,  0x65e5,  0x0,  0x39,  0x6708,  0x0,  0x39,  0x70b9,  0x0,  0x3a,  0x0,  0x3a,  0x3a,  0x3d,  0x0,  0x3b,  0x0,  0x3c,  0x0,  0x3c,  0x338,  0x0,  0x3d,  0x0,  0x3d,  0x3d,  0x0,  0x3d,  0x3d,  0x3d,  0x0,  0x3d,  0x338,  0x0,  0x3e,  0x0,  0x3e,  0x338,  0x0,  0x3f,  0x0,  0x3f,  0x21,  0x0,  0x3f,  0x3f,  0x0,  0x40,  0x0,  0x41,  0x0,  0x41,  0x55,  0x0,  0x41,  0x300,  0x0,  0x41,  0x301,  0x0,  0x41,  0x302,  0x0,  0x41,  0x302,  0x300,  0x0,  0x41,  0x302,  0x301,  0x0,  0x41,  0x302,  0x303,  0x0,  0x41,  0x302,  0x309,  0x0,  0x41,  0x303,  0x0,  0x41,  0x304,  0x0,  0x41,  0x306,  0x0,  0x41,  0x306,  0x300,  0x0,  0x41,  0x306,  0x301,  0x0,  0x41,  0x306,  0x303,  0x0,  0x41,  0x306,  0x309,  0x0,  0x41,  0x307,  0x0,  0x41,  0x307,  0x304,  0x0,  0x41,  0x308,  0x0,  0x41,  0x308,  0x304,  0x0,  0x41,  0x309,  0x0,  0x41,  0x30a,  0x0,  0x41,  0x30a,  0x301,  0x0,  0x41,  0x30c,  0x0,  0x41,  0x30f,  0x0,  0x41,  0x311,  0x0,  0x41,  0x323,  0x0,  0x41,  0x323,  0x302,  0x0,  0x41,  0x323,  0x306,  0x0,  0x41,  0x325,  0x0,  0x41,  0x328,  0x0,  0x41,  0x2215,  0x6d,  0x0,  0x42,  0x0,  0x42,  0x71,  0x0,  0x42,  0x307,  0x0,  0x42,  0x323,  0x0,  0x42,  0x331,  0x0,  0x43,  0x0,  0x43,  0x44,  0x0,  0x43,  0x6f,  0x2e,  0x0,  0x43,  0x301,  0x0,  0x43,  0x302,  0x0,  0x43,  0x307,  0x0,  0x43,  0x30c,  0x0,  0x43,  0x327,  0x0,  0x43,  0x327,  0x301,  0x0,  0x43,  0x2215,  0x6b,  0x67,  0x0,  0x44,  0x0,  0x44,  0x4a,  0x0,  0x44,  0x5a,  0x0,  0x44,  0x5a,  0x30c,  0x0,  0x44,  0x7a,  0x0,  0x44,  0x7a,  0x30c,  0x0,  0x44,  0x307,  0x0,  0x44,  0x30c,  0x0,  0x44,  0x323,  0x0,  0x44,  0x327,  0x0,  0x44,  0x32d,  0x0,  0x44,  0x331,  0x0,  0x45,  0x0,  0x45,  0x300,  0x0,  0x45,  0x301,  0x0,  0x45,  0x302,  0x0,  0x45,  0x302,  0x300,  0x0,  0x45,  0x302,  0x301,  0x0,  0x45,  0x302,  0x303,  0x0,  0x45,  0x302,  0x309,  0x0,  0x45,  0x303,  0x0,  0x45,  0x304,  0x0,  0x45,  0x304,  0x300,  0x0,  0x45,  0x304,  0x301,  0x0,  0x45,  0x306,  0x0,  0x45,  0x307,  0x0,  0x45,  0x308,  0x0,  0x45,  0x309,  0x0,  0x45,  0x30c,  0x0,  0x45,  0x30f,  0x0,  0x45,  0x311,  0x0,  0x45,  0x323,  0x0,  0x45,  0x323,  0x302,  0x0,  0x45,  0x327,  0x0,  0x45,  0x327,  0x306,  0x0,  0x45,  0x328,  0x0,  0x45,  0x32d,  0x0,  0x45,  0x330,  0x0,  0x46,  0x0,  0x46,  0x41,  0x58,  0x0,  0x46,  0x307,  0x0,  0x47,  0x0,  0x47,  0x42,  0x0,  0x47,  0x48,  0x7a,  0x0,  0x47,  0x50,  0x61,  0x0,  0x47,  0x79,  0x0,  0x47,  0x301,  0x0,  0x47,  0x302,  0x0,  0x47,  0x304,  0x0,  0x47,  0x306,  0x0,  0x47,  0x307,  0x0,  0x47,  0x30c,  0x0,  0x47,  0x327,  0x0,  0x48,  0x0,  0x48,  0x50,  0x0,  0x48,  0x56,  0x0,  0x48,  0x67,  0x0,  0x48,  0x7a,  0x0,  0x48,  0x302,  0x0,  0x48,  0x307,  0x0,  0x48,  0x308,  0x0,  0x48,  0x30c,  0x0,  0x48,  0x323,  0x0,  0x48,  0x327,  0x0,  0x48,  0x32e,  0x0,  0x49,  0x0,  0x49,  0x49,  0x0,  0x49,  0x49,  0x49,  0x0,  0x49,  0x4a,  0x0,  0x49,  0x55,  0x0,  0x49,  0x56,  0x0,  0x49,  0x58,  0x0,  0x49,  0x300,  0x0,  0x49,  0x301,  0x0,  0x49,  0x302,  0x0,  0x49,  0x303,  0x0,  0x49,  0x304,  0x0,  0x49,  0x306,  0x0,  0x49,  0x307,  0x0,  0x49,  0x308,  0x0,  0x49,  0x308,  0x301,  0x0,  0x49,  0x309,  0x0,  0x49,  0x30c,  0x0,  0x49,  0x30f,  0x0,  0x49,  0x311,  0x0,  0x49,  0x323,  0x0,  0x49,  0x328,  0x0,  0x49,  0x330,  0x0,  0x4a,  0x0,  0x4a,  0x302,  0x0,  0x4b,  0x0,  0x4b,  0x42,  0x0,  0x4b,  0x4b,  0x0,  0x4b,  0x4d,  0x0,  0x4b,  0x301,  0x0,  0x4b,  0x30c,  0x0,  0x4b,  0x323,  0x0,  0x4b,  0x327,  0x0,  0x4b,  0x331,  0x0,  0x4c,  0x0,  0x4c,  0x4a,  0x0,  0x4c,  0x54,  0x44,  0x0,  0x4c,  0x6a,  0x0,  0x4c,  0xb7,  0x0,  0x4c,  0x301,  0x0,  0x4c,  0x30c,  0x0,  0x4c,  0x323,  0x0,  0x4c,  0x323,  0x304,  0x0,  0x4c,  0x327,  0x0,  0x4c,  0x32d,  0x0,  0x4c,  0x331,  0x0,  0x4d,  0x0,  0x4d,  0x42,  0x0,  0x4d,  0x43,  0x0,  0x4d,  0x44,  0x0,  0x4d,  0x48,  0x7a,  0x0,  0x4d,  0x50,  0x61,  0x0,  0x4d,  0x56,  0x0,  0x4d,  0x57,  0x0,  0x4d,  0x301,  0x0,  0x4d,  0x307,  0x0,  0x4d,  0x323,  0x0,  0x4d,  0x3a9,  0x0,  0x4e,  0x0,  0x4e,  0x4a,  0x0,  0x4e,  0x6a,  0x0,  0x4e,  0x6f,  0x0,  0x4e,  0x300,  0x0,  0x4e,  0x301,  0x0,  0x4e,  0x303,  0x0,  0x4e,  0x307,  0x0,  0x4e,  0x30c,  0x0,  0x4e,  0x323,  0x0,  0x4e,  0x327,  0x0,  0x4e,  0x32d,  0x0,  0x4e,  0x331,  0x0,  0x4f,  0x0,  0x4f,  0x300,  0x0,  0x4f,  0x301,  0x0,  0x4f,  0x302,  0x0,  0x4f,  0x302,  0x300,  0x0,  0x4f,  0x302,  0x301,  0x0,  0x4f,  0x302,  0x303,  0x0,  0x4f,  0x302,  0x309,  0x0,  0x4f,  0x303,  0x0,  0x4f,  0x303,  0x301,  0x0,  0x4f,  0x303,  0x304,  0x0,  0x4f,  0x303,  0x308,  0x0,  0x4f,  0x304,  0x0,  0x4f,  0x304,  0x300,  0x0,  0x4f,  0x304,  0x301,  0x0,  0x4f,  0x306,  0x0,  0x4f,  0x307,  0x0,  0x4f,  0x307,  0x304,  0x0,  0x4f,  0x308,  0x0,  0x4f,  0x308,  0x304,  0x0,  0x4f,  0x309,  0x0,  0x4f,  0x30b,  0x0,  0x4f,  0x30c,  0x0,  0x4f,  0x30f,  0x0,  0x4f,  0x311,  0x0,  0x4f,  0x31b,  0x0,  0x4f,  0x31b,  0x300,  0x0,  0x4f,  0x31b,  0x301,  0x0,  0x4f,  0x31b,  0x303,  0x0,  0x4f,  0x31b,  0x309,  0x0,  0x4f,  0x31b,  0x323,  0x0,  0x4f,  0x323,  0x0,  0x4f,  0x323,  0x302,  0x0,  0x4f,  0x328,  0x0,  0x4f,  0x328,  0x304,  0x0,  0x50,  0x0,  0x50,  0x48,  0x0,  0x50,  0x50,  0x4d,  0x0,  0x50,  0x50,  0x56,  0x0,  0x50,  0x52,  0x0,  0x50,  0x54,  0x45,  0x0,  0x50,  0x61,  0x0,  0x50,  0x301,  0x0,  0x50,  0x307,  0x0,  0x51,  0x0,  0x52,  0x0,  0x52,  0x73,  0x0,  0x52,  0x301,  0x0,  0x52,  0x307,  0x0,  0x52,  0x30c,  0x0,  0x52,  0x30f,  0x0,  0x52,  0x311,  0x0,  0x52,  0x323,  0x0,  0x52,  0x323,  0x304,  0x0,  0x52,  0x327,  0x0,  0x52,  0x331,  0x0,  0x53,  0x0,  0x53,  0x44,  0x0,  0x53,  0x4d,  0x0,  0x53,  0x53,  0x0,  0x53,  0x76,  0x0,  0x53,  0x301,  0x0,  0x53,  0x301,  0x307,  0x0,  0x53,  0x302,  0x0,  0x53,  0x307,  0x0,  0x53,  0x30c,  0x0,  0x53,  0x30c,  0x307,  0x0,  0x53,  0x323,  0x0,  0x53,  0x323,  0x307,  0x0,  0x53,  0x326,  0x0,  0x53,  0x327,  0x0,  0x54,  0x0,  0x54,  0x45,  0x4c,  0x0,  0x54,  0x48,  0x7a,  0x0,  0x54,  0x4d,  0x0,  0x54,  0x307,  0x0,  0x54,  0x30c,  0x0,  0x54,  0x323,  0x0,  0x54,  0x326,  0x0,  0x54,  0x327,  0x0,  0x54,  0x32d,  0x0,  0x54,  0x331,  0x0,  0x55,  0x0,  0x55,  0x300,  0x0,  0x55,  0x301,  0x0,  0x55,  0x302,  0x0,  0x55,  0x303,  0x0,  0x55,  0x303,  0x301,  0x0,  0x55,  0x304,  0x0,  0x55,  0x304,  0x308,  0x0,  0x55,  0x306,  0x0,  0x55,  0x308,  0x0,  0x55,  0x308,  0x300,  0x0,  0x55,  0x308,  0x301,  0x0,  0x55,  0x308,  0x304,  0x0,  0x55,  0x308,  0x30c,  0x0,  0x55,  0x309,  0x0,  0x55,  0x30a,  0x0,  0x55,  0x30b,  0x0,  0x55,  0x30c,  0x0,  0x55,  0x30f,  0x0,  0x55,  0x311,  0x0,  0x55,  0x31b,  0x0,  0x55,  0x31b,  0x300,  0x0,  0x55,  0x31b,  0x301,  0x0,  0x55,  0x31b,  0x303,  0x0,  0x55,  0x31b,  0x309,  0x0,  0x55,  0x31b,  0x323,  0x0,  0x55,  0x323,  0x0,  0x55,  0x324,  0x0,  0x55,  0x328,  0x0,  0x55,  0x32d,  0x0,  0x55,  0x330,  0x0,  0x56,  0x0,  0x56,  0x49,  0x0,  0x56,  0x49,  0x49,  0x0,  0x56,  0x49,  0x49,  0x49,  0x0,  0x56,  0x303,  0x0,  0x56,  0x323,  0x0,  0x56,  0x2215,  0x6d,  0x0,  0x57,  0x0,  0x57,  0x43,  0x0,  0x57,  0x5a,  0x0,  0x57,  0x62,  0x0,  0x57,  0x300,  0x0,  0x57,  0x301,  0x0,  0x57,  0x302,  0x0,  0x57,  0x307,  0x0,  0x57,  0x308,  0x0,  0x57,  0x323,  0x0,  0x58,  0x0,  0x58,  0x49,  0x0,  0x58,  0x49,  0x49,  0x0,  0x58,  0x307,  0x0,  0x58,  0x308,  0x0,  0x59,  0x0,  0x59,  0x300,  0x0,  0x59,  0x301,  0x0,  0x59,  0x302,  0x0,  0x59,  0x303,  0x0,  0x59,  0x304,  0x0,  0x59,  0x307,  0x0,  0x59,  0x308,  0x0,  0x59,  0x309,  0x0,  0x59,  0x323,  0x0,  0x5a,  0x0,  0x5a,  0x301,  0x0,  0x5a,  0x302,  0x0,  0x5a,  0x307,  0x0,  0x5a,  0x30c,  0x0,  0x5a,  0x323,  0x0,  0x5a,  0x331,  0x0,  0x5b,  0x0,  0x5c,  0x0,  0x5d,  0x0,  0x5e,  0x0,  0x5f,  0x0,  0x60,  0x0,  0x61,  0x0,  0x61,  0x2e,  0x6d,  0x2e,  0x0,  0x61,  0x2f,  0x63,  0x0,  0x61,  0x2f,  0x73,  0x0,  0x61,  0x2be,  0x0,  0x61,  0x300,  0x0,  0x61,  0x301,  0x0,  0x61,  0x302,  0x0,  0x61,  0x302,  0x300,  0x0,  0x61,  0x302,  0x301,  0x0,  0x61,  0x302,  0x303,  0x0,  0x61,  0x302,  0x309,  0x0,  0x61,  0x303,  0x0,  0x61,  0x304,  0x0,  0x61,  0x306,  0x0,  0x61,  0x306,  0x300,  0x0,  0x61,  0x306,  0x301,  0x0,  0x61,  0x306,  0x303,  0x0,  0x61,  0x306,  0x309,  0x0,  0x61,  0x307,  0x0,  0x61,  0x307,  0x304,  0x0,  0x61,  0x308,  0x0,  0x61,  0x308,  0x304,  0x0,  0x61,  0x309,  0x0,  0x61,  0x30a,  0x0,  0x61,  0x30a,  0x301,  0x0,  0x61,  0x30c,  0x0,  0x61,  0x30f,  0x0,  0x61,  0x311,  0x0,  0x61,  0x323,  0x0,  0x61,  0x323,  0x302,  0x0,  0x61,  0x323,  0x306,  0x0,  0x61,  0x325,  0x0,  0x61,  0x328,  0x0,  0x62,  0x0,  0x62,  0x61,  0x72,  0x0,  0x62,  0x307,  0x0,  0x62,  0x323,  0x0,  0x62,  0x331,  0x0,  0x63,  0x0,  0x63,  0x2f,  0x6f,  0x0,  0x63,  0x2f,  0x75,  0x0,  0x63,  0x61,  0x6c,  0x0,  0x63,  0x63,  0x0,  0x63,  0x64,  0x0,  0x63,  0x6d,  0x0,  0x63,  0x6d,  0x32,  0x0,  0x63,  0x6d,  0x33,  0x0,  0x63,  0x301,  0x0,  0x63,  0x302,  0x0,  0x63,  0x307,  0x0,  0x63,  0x30c,  0x0,  0x63,  0x327,  0x0,  0x63,  0x327,  0x301,  0x0,  0x64,  0x0,  0x64,  0x42,  0x0,  0x64,  0x61,  0x0,  0x64,  0x6c,  0x0,  0x64,  0x6d,  0x0,  0x64,  0x6d,  0x32,  0x0,  0x64,  0x6d,  0x33,  0x0,  0x64,  0x7a,  0x0,  0x64,  0x7a,  0x30c,  0x0,  0x64,  0x307,  0x0,  0x64,  0x30c,  0x0,  0x64,  0x323,  0x0,  0x64,  0x327,  0x0,  0x64,  0x32d,  0x0,  0x64,  0x331,  0x0,  0x65,  0x0,  0x65,  0x56,  0x0,  0x65,  0x72,  0x67,  0x0,  0x65,  0x300,  0x0,  0x65,  0x301,  0x0,  0x65,  0x302,  0x0,  0x65,  0x302,  0x300,  0x0,  0x65,  0x302,  0x301,  0x0,  0x65,  0x302,  0x303,  0x0,  0x65,  0x302,  0x309,  0x0,  0x65,  0x303,  0x0,  0x65,  0x304,  0x0,  0x65,  0x304,  0x300,  0x0,  0x65,  0x304,  0x301,  0x0,  0x65,  0x306,  0x0,  0x65,  0x307,  0x0,  0x65,  0x308,  0x0,  0x65,  0x309,  0x0,  0x65,  0x30c,  0x0,  0x65,  0x30f,  0x0,  0x65,  0x311,  0x0,  0x65,  0x323,  0x0,  0x65,  0x323,  0x302,  0x0,  0x65,  0x327,  0x0,  0x65,  0x327,  0x306,  0x0,  0x65,  0x328,  0x0,  0x65,  0x32d,  0x0,  0x65,  0x330,  0x0,  0x66,  0x0,  0x66,  0x66,  0x0,  0x66,  0x66,  0x69,  0x0,  0x66,  0x66,  0x6c,  0x0,  0x66,  0x69,  0x0,  0x66,  0x6c,  0x0,  0x66,  0x6d,  0x0,  0x66,  0x307,  0x0,  0x67,  0x0,  0x67,  0x61,  0x6c,  0x0,  0x67,  0x301,  0x0,  0x67,  0x302,  0x0,  0x67,  0x304,  0x0,  0x67,  0x306,  0x0,  0x67,  0x307,  0x0,  0x67,  0x30c,  0x0,  0x67,  0x327,  0x0,  0x68,  0x0,  0x68,  0x50,  0x61,  0x0,  0x68,  0x61,  0x0,  0x68,  0x302,  0x0,  0x68,  0x307,  0x0,  0x68,  0x308,  0x0,  0x68,  0x30c,  0x0,  0x68,  0x323,  0x0,  0x68,  0x327,  0x0,  0x68,  0x32e,  0x0,  0x68,  0x331,  0x0,  0x69,  0x0,  0x69,  0x69,  0x0,  0x69,  0x69,  0x69,  0x0,  0x69,  0x6a,  0x0,  0x69,  0x6e,  0x0,  0x69,  0x76,  0x0,  0x69,  0x78,  0x0,  0x69,  0x300,  0x0,  0x69,  0x301,  0x0,  0x69,  0x302,  0x0,  0x69,  0x303,  0x0,  0x69,  0x304,  0x0,  0x69,  0x306,  0x0,  0x69,  0x308,  0x0,  0x69,  0x308,  0x301,  0x0,  0x69,  0x309,  0x0,  0x69,  0x30c,  0x0,  0x69,  0x30f,  0x0,  0x69,  0x311,  0x0,  0x69,  0x323,  0x0,  0x69,  0x328,  0x0,  0x69,  0x330,  0x0,  0x6a,  0x0,  0x6a,  0x302,  0x0,  0x6a,  0x30c,  0x0,  0x6b,  0x0,  0x6b,  0x41,  0x0,  0x6b,  0x48,  0x7a,  0x0,  0x6b,  0x50,  0x61,  0x0,  0x6b,  0x56,  0x0,  0x6b,  0x57,  0x0,  0x6b,  0x63,  0x61,  0x6c,  0x0,  0x6b,  0x67,  0x0,  0x6b,  0x6c,  0x0,  0x6b,  0x6d,  0x0,  0x6b,  0x6d,  0x32,  0x0,  0x6b,  0x6d,  0x33,  0x0,  0x6b,  0x74,  0x0,  0x6b,  0x301,  0x0,  0x6b,  0x30c,  0x0,  0x6b,  0x323,  0x0,  0x6b,  0x327,  0x0,  0x6b,  0x331,  0x0,  0x6b,  0x3a9,  0x0,  0x6c,  0x0,  0x6c,  0x6a,  0x0,  0x6c,  0x6d,  0x0,  0x6c,  0x6e,  0x0,  0x6c,  0x6f,  0x67,  0x0,  0x6c,  0x78,  0x0,  0x6c,  0xb7,  0x0,  0x6c,  0x301,  0x0,  0x6c,  0x30c,  0x0,  0x6c,  0x323,  0x0,  0x6c,  0x323,  0x304,  0x0,  0x6c,  0x327,  0x0,  0x6c,  0x32d,  0x0,  0x6c,  0x331,  0x0,  0x6d,  0x0,  0x6d,  0x32,  0x0,  0x6d,  0x33,  0x0,  0x6d,  0x41,  0x0,  0x6d,  0x56,  0x0,  0x6d,  0x57,  0x0,  0x6d,  0x62,  0x0,  0x6d,  0x67,  0x0,  0x6d,  0x69,  0x6c,  0x0,  0x6d,  0x6c,  0x0,  0x6d,  0x6d,  0x0,  0x6d,  0x6d,  0x32,  0x0,  0x6d,  0x6d,  0x33,  0x0,  0x6d,  0x6f,  0x6c,  0x0,  0x6d,  0x73,  0x0,  0x6d,  0x301,  0x0,  0x6d,  0x307,  0x0,  0x6d,  0x323,  0x0,  0x6d,  0x2215,  0x73,  0x0,  0x6d,  0x2215,  0x73,  0x32,  0x0,  0x6e,  0x0,  0x6e,  0x41,  0x0,  0x6e,  0x46,  0x0,  0x6e,  0x56,  0x0,  0x6e,  0x57,  0x0,  0x6e,  0x6a,  0x0,  0x6e,  0x6d,  0x0,  0x6e,  0x73,  0x0,  0x6e,  0x300,  0x0,  0x6e,  0x301,  0x0,  0x6e,  0x303,  0x0,  0x6e,  0x307,  0x0,  0x6e,  0x30c,  0x0,  0x6e,  0x323,  0x0,  0x6e,  0x327,  0x0,  0x6e,  0x32d,  0x0,  0x6e,  0x331,  0x0,  0x6f,  0x0,  0x6f,  0x56,  0x0,  0x6f,  0x300,  0x0,  0x6f,  0x301,  0x0,  0x6f,  0x302,  0x0,  0x6f,  0x302,  0x300,  0x0,  0x6f,  0x302,  0x301,  0x0,  0x6f,  0x302,  0x303,  0x0,  0x6f,  0x302,  0x309,  0x0,  0x6f,  0x303,  0x0,  0x6f,  0x303,  0x301,  0x0,  0x6f,  0x303,  0x304,  0x0,  0x6f,  0x303,  0x308,  0x0,  0x6f,  0x304,  0x0,  0x6f,  0x304,  0x300,  0x0,  0x6f,  0x304,  0x301,  0x0,  0x6f,  0x306,  0x0,  0x6f,  0x307,  0x0,  0x6f,  0x307,  0x304,  0x0,  0x6f,  0x308,  0x0,  0x6f,  0x308,  0x304,  0x0,  0x6f,  0x309,  0x0,  0x6f,  0x30b,  0x0,  0x6f,  0x30c,  0x0,  0x6f,  0x30f,  0x0,  0x6f,  0x311,  0x0,  0x6f,  0x31b,  0x0,  0x6f,  0x31b,  0x300,  0x0,  0x6f,  0x31b,  0x301,  0x0,  0x6f,  0x31b,  0x303,  0x0,  0x6f,  0x31b,  0x309,  0x0,  0x6f,  0x31b,  0x323,  0x0,  0x6f,  0x323,  0x0,  0x6f,  0x323,  0x302,  0x0,  0x6f,  0x328,  0x0,  0x6f,  0x328,  0x304,  0x0,  0x70,  0x0,  0x70,  0x2e,  0x6d,  0x2e,  0x0,  0x70,  0x41,  0x0,  0x70,  0x46,  0x0,  0x70,  0x56,  0x0,  0x70,  0x57,  0x0,  0x70,  0x63,  0x0,  0x70,  0x73,  0x0,  0x70,  0x301,  0x0,  0x70,  0x307,  0x0,  0x71,  0x0,  0x72,  0x0,  0x72,  0x61,  0x64,  0x0,  0x72,  0x61,  0x64,  0x2215,  0x73,  0x0,  0x72,  0x61,  0x64,  0x2215,  0x73,  0x32,  0x0,  0x72,  0x301,  0x0,  0x72,  0x307,  0x0,  0x72,  0x30c,  0x0,  0x72,  0x30f,  0x0,  0x72,  0x311,  0x0,  0x72,  0x323,  0x0,  0x72,  0x323,  0x304,  0x0,  0x72,  0x327,  0x0,  0x72,  0x331,  0x0,  0x73,  0x0,  0x73,  0x72,  0x0,  0x73,  0x74,  0x0,  0x73,  0x301,  0x0,  0x73,  0x301,  0x307,  0x0,  0x73,  0x302,  0x0,  0x73,  0x307,  0x0,  0x73,  0x30c,  0x0,  0x73,  0x30c,  0x307,  0x0,  0x73,  0x323,  0x0,  0x73,  0x323,  0x307,  0x0,  0x73,  0x326,  0x0,  0x73,  0x327,  0x0,  0x74,  0x0,  0x74,  0x307,  0x0,  0x74,  0x308,  0x0,  0x74,  0x30c,  0x0,  0x74,  0x323,  0x0,  0x74,  0x326,  0x0,  0x74,  0x327,  0x0,  0x74,  0x32d,  0x0,  0x74,  0x331,  0x0,  0x75,  0x0,  0x75,  0x300,  0x0,  0x75,  0x301,  0x0,  0x75,  0x302,  0x0,  0x75,  0x303,  0x0,  0x75,  0x303,  0x301,  0x0,  0x75,  0x304,  0x0,  0x75,  0x304,  0x308,  0x0,  0x75,  0x306,  0x0,  0x75,  0x308,  0x0,  0x75,  0x308,  0x300,  0x0,  0x75,  0x308,  0x301,  0x0,  0x75,  0x308,  0x304,  0x0,  0x75,  0x308,  0x30c,  0x0,  0x75,  0x309,  0x0,  0x75,  0x30a,  0x0,  0x75,  0x30b,  0x0,  0x75,  0x30c,  0x0,  0x75,  0x30f,  0x0,  0x75,  0x311,  0x0,  0x75,  0x31b,  0x0,  0x75,  0x31b,  0x300,  0x0,  0x75,  0x31b,  0x301,  0x0,  0x75,  0x31b,  0x303,  0x0,  0x75,  0x31b,  0x309,  0x0,  0x75,  0x31b,  0x323,  0x0,  0x75,  0x323,  0x0,  0x75,  0x324,  0x0,  0x75,  0x328,  0x0,  0x75,  0x32d,  0x0,  0x75,  0x330,  0x0,  0x76,  0x0,  0x76,  0x69,  0x0,  0x76,  0x69,  0x69,  0x0,  0x76,  0x69,  0x69,  0x69,  0x0,  0x76,  0x303,  0x0,  0x76,  0x323,  0x0,  0x77,  0x0,  0x77,  0x300,  0x0,  0x77,  0x301,  0x0,  0x77,  0x302,  0x0,  0x77,  0x307,  0x0,  0x77,  0x308,  0x0,  0x77,  0x30a,  0x0,  0x77,  0x323,  0x0,  0x78,  0x0,  0x78,  0x69,  0x0,  0x78,  0x69,  0x69,  0x0,  0x78,  0x307,  0x0,  0x78,  0x308,  0x0,  0x79,  0x0,  0x79,  0x300,  0x0,  0x79,  0x301,  0x0,  0x79,  0x302,  0x0,  0x79,  0x303,  0x0,  0x79,  0x304,  0x0,  0x79,  0x307,  0x0,  0x79,  0x308,  0x0,  0x79,  0x309,  0x0,  0x79,  0x30a,  0x0,  0x79,  0x323,  0x0,  0x7a,  0x0,  0x7a,  0x301,  0x0,  0x7a,  0x302,  0x0,  0x7a,  0x307,  0x0,  0x7a,  0x30c,  0x0,  0x7a,  0x323,  0x0,  0x7a,  0x331,  0x0,  0x7b,  0x0,  0x7c,  0x0,  0x7d,  0x0,  0x7e,  0x0,  0xa2,  0x0,  0xa3,  0x0,  0xa5,  0x0,  0xa6,  0x0,  0xac,  0x0,  0xb0,  0x43,  0x0,  0xb0,  0x46,  0x0,  0xb7,  0x0,  0xc6,  0x0,  0xc6,  0x301,  0x0,  0xc6,  0x304,  0x0,  0xd8,  0x301,  0x0,  0xe6,  0x301,  0x0,  0xe6,  0x304,  0x0,  0xf0,  0x0,  0xf8,  0x301,  0x0,  0x126,  0x0,  0x127,  0x0,  0x131,  0x0,  0x14b,  0x0,  0x153,  0x0,  0x18e,  0x0,  0x190,  0x0,  0x1ab,  0x0,  0x1b7,  0x30c,  0x0,  0x222,  0x0,  0x237,  0x0,  0x250,  0x0,  0x251,  0x0,  0x252,  0x0,  0x254,  0x0,  0x255,  0x0,  0x259,  0x0,  0x25b,  0x0,  0x25c,  0x0,  0x25f,  0x0,  0x261,  0x0,  0x263,  0x0,  0x265,  0x0,  0x266,  0x0,  0x268,  0x0,  0x269,  0x0,  0x26a,  0x0,  0x26d,  0x0,  0x26f,  0x0,  0x270,  0x0,  0x271,  0x0,  0x272,  0x0,  0x273,  0x0,  0x274,  0x0,  0x275,  0x0,  0x278,  0x0,  0x279,  0x0,  0x27b,  0x0,  0x281,  0x0,  0x282,  0x0,  0x283,  0x0,  0x289,  0x0,  0x28a,  0x0,  0x28b,  0x0,  0x28c,  0x0,  0x290,  0x0,  0x291,  0x0,  0x292,  0x0,  0x292,  0x30c,  0x0,  0x295,  0x0,  0x29d,  0x0,  0x29f,  0x0,  0x2b9,  0x0,  0x2bc,  0x6e,  0x0,  0x300,  0x0,  0x301,  0x0,  0x308,  0x301,  0x0,  0x313,  0x0,  0x391,  0x0,  0x391,  0x300,  0x0,  0x391,  0x301,  0x0,  0x391,  0x304,  0x0,  0x391,  0x306,  0x0,  0x391,  0x313,  0x0,  0x391,  0x313,  0x300,  0x0,  0x391,  0x313,  0x300,  0x345,  0x0,  0x391,  0x313,  0x301,  0x0,  0x391,  0x313,  0x301,  0x345,  0x0,  0x391,  0x313,  0x342,  0x0,  0x391,  0x313,  0x342,  0x345,  0x0,  0x391,  0x313,  0x345,  0x0,  0x391,  0x314,  0x0,  0x391,  0x314,  0x300,  0x0,  0x391,  0x314,  0x300,  0x345,  0x0,  0x391,  0x314,  0x301,  0x0,  0x391,  0x314,  0x301,  0x345,  0x0,  0x391,  0x314,  0x342,  0x0,  0x391,  0x314,  0x342,  0x345,  0x0,  0x391,  0x314,  0x345,  0x0,  0x391,  0x345,  0x0,  0x392,  0x0,  0x393,  0x0,  0x394,  0x0,  0x395,  0x0,  0x395,  0x300,  0x0,  0x395,  0x301,  0x0,  0x395,  0x313,  0x0,  0x395,  0x313,  0x300,  0x0,  0x395,  0x313,  0x301,  0x0,  0x395,  0x314,  0x0,  0x395,  0x314,  0x300,  0x0,  0x395,  0x314,  0x301,  0x0,  0x396,  0x0,  0x397,  0x0,  0x397,  0x300,  0x0,  0x397,  0x301,  0x0,  0x397,  0x313,  0x0,  0x397,  0x313,  0x300,  0x0,  0x397,  0x313,  0x300,  0x345,  0x0,  0x397,  0x313,  0x301,  0x0,  0x397,  0x313,  0x301,  0x345,  0x0,  0x397,  0x313,  0x342,  0x0,  0x397,  0x313,  0x342,  0x345,  0x0,  0x397,  0x313,  0x345,  0x0,  0x397,  0x314,  0x0,  0x397,  0x314,  0x300,  0x0,  0x397,  0x314,  0x300,  0x345,  0x0,  0x397,  0x314,  0x301,  0x0,  0x397,  0x314,  0x301,  0x345,  0x0,  0x397,  0x314,  0x342,  0x0,  0x397,  0x314,  0x342,  0x345,  0x0,  0x397,  0x314,  0x345,  0x0,  0x397,  0x345,  0x0,  0x398,  0x0,  0x399,  0x0,  0x399,  0x300,  0x0,  0x399,  0x301,  0x0,  0x399,  0x304,  0x0,  0x399,  0x306,  0x0,  0x399,  0x308,  0x0,  0x399,  0x313,  0x0,  0x399,  0x313,  0x300,  0x0,  0x399,  0x313,  0x301,  0x0,  0x399,  0x313,  0x342,  0x0,  0x399,  0x314,  0x0,  0x399,  0x314,  0x300,  0x0,  0x399,  0x314,  0x301,  0x0,  0x399,  0x314,  0x342,  0x0,  0x39a,  0x0,  0x39b,  0x0,  0x39c,  0x0,  0x39d,  0x0,  0x39e,  0x0,  0x39f,  0x0,  0x39f,  0x300,  0x0,  0x39f,  0x301,  0x0,  0x39f,  0x313,  0x0,  0x39f,  0x313,  0x300,  0x0,  0x39f,  0x313,  0x301,  0x0,  0x39f,  0x314,  0x0,  0x39f,  0x314,  0x300,  0x0,  0x39f,  0x314,  0x301,  0x0,  0x3a0,  0x0,  0x3a1,  0x0,  0x3a1,  0x314,  0x0,  0x3a3,  0x0,  0x3a4,  0x0,  0x3a5,  0x0,  0x3a5,  0x300,  0x0,  0x3a5,  0x301,  0x0,  0x3a5,  0x304,  0x0,  0x3a5,  0x306,  0x0,  0x3a5,  0x308,  0x0,  0x3a5,  0x314,  0x0,  0x3a5,  0x314,  0x300,  0x0,  0x3a5,  0x314,  0x301,  0x0,  0x3a5,  0x314,  0x342,  0x0,  0x3a6,  0x0,  0x3a7,  0x0,  0x3a8,  0x0,  0x3a9,  0x0,  0x3a9,  0x300,  0x0,  0x3a9,  0x301,  0x0,  0x3a9,  0x313,  0x0,  0x3a9,  0x313,  0x300,  0x0,  0x3a9,  0x313,  0x300,  0x345,  0x0,  0x3a9,  0x313,  0x301,  0x0,  0x3a9,  0x313,  0x301,  0x345,  0x0,  0x3a9,  0x313,  0x342,  0x0,  0x3a9,  0x313,  0x342,  0x345,  0x0,  0x3a9,  0x313,  0x345,  0x0,  0x3a9,  0x314,  0x0,  0x3a9,  0x314,  0x300,  0x0,  0x3a9,  0x314,  0x300,  0x345,  0x0,  0x3a9,  0x314,  0x301,  0x0,  0x3a9,  0x314,  0x301,  0x345,  0x0,  0x3a9,  0x314,  0x342,  0x0,  0x3a9,  0x314,  0x342,  0x345,  0x0,  0x3a9,  0x314,  0x345,  0x0,  0x3a9,  0x345,  0x0,  0x3b1,  0x0,  0x3b1,  0x300,  0x0,  0x3b1,  0x300,  0x345,  0x0,  0x3b1,  0x301,  0x0,  0x3b1,  0x301,  0x345,  0x0,  0x3b1,  0x304,  0x0,  0x3b1,  0x306,  0x0,  0x3b1,  0x313,  0x0,  0x3b1,  0x313,  0x300,  0x0,  0x3b1,  0x313,  0x300,  0x345,  0x0,  0x3b1,  0x313,  0x301,  0x0,  0x3b1,  0x313,  0x301,  0x345,  0x0,  0x3b1,  0x313,  0x342,  0x0,  0x3b1,  0x313,  0x342,  0x345,  0x0,  0x3b1,  0x313,  0x345,  0x0,  0x3b1,  0x314,  0x0,  0x3b1,  0x314,  0x300,  0x0,  0x3b1,  0x314,  0x300,  0x345,  0x0,  0x3b1,  0x314,  0x301,  0x0,  0x3b1,  0x314,  0x301,  0x345,  0x0,  0x3b1,  0x314,  0x342,  0x0,  0x3b1,  0x314,  0x342,  0x345,  0x0,  0x3b1,  0x314,  0x345,  0x0,  0x3b1,  0x342,  0x0,  0x3b1,  0x342,  0x345,  0x0,  0x3b1,  0x345,  0x0,  0x3b2,  0x0,  0x3b3,  0x0,  0x3b4,  0x0,  0x3b5,  0x0,  0x3b5,  0x300,  0x0,  0x3b5,  0x301,  0x0,  0x3b5,  0x313,  0x0,  0x3b5,  0x313,  0x300,  0x0,  0x3b5,  0x313,  0x301,  0x0,  0x3b5,  0x314,  0x0,  0x3b5,  0x314,  0x300,  0x0,  0x3b5,  0x314,  0x301,  0x0,  0x3b6,  0x0,  0x3b7,  0x0,  0x3b7,  0x300,  0x0,  0x3b7,  0x300,  0x345,  0x0,  0x3b7,  0x301,  0x0,  0x3b7,  0x301,  0x345,  0x0,  0x3b7,  0x313,  0x0,  0x3b7,  0x313,  0x300,  0x0,  0x3b7,  0x313,  0x300,  0x345,  0x0,  0x3b7,  0x313,  0x301,  0x0,  0x3b7,  0x313,  0x301,  0x345,  0x0,  0x3b7,  0x313,  0x342,  0x0,  0x3b7,  0x313,  0x342,  0x345,  0x0,  0x3b7,  0x313,  0x345,  0x0,  0x3b7,  0x314,  0x0,  0x3b7,  0x314,  0x300,  0x0,  0x3b7,  0x314,  0x300,  0x345,  0x0,  0x3b7,  0x314,  0x301,  0x0,  0x3b7,  0x314,  0x301,  0x345,  0x0,  0x3b7,  0x314,  0x342,  0x0,  0x3b7,  0x314,  0x342,  0x345,  0x0,  0x3b7,  0x314,  0x345,  0x0,  0x3b7,  0x342,  0x0,  0x3b7,  0x342,  0x345,  0x0,  0x3b7,  0x345,  0x0,  0x3b8,  0x0,  0x3b9,  0x0,  0x3b9,  0x300,  0x0,  0x3b9,  0x301,  0x0,  0x3b9,  0x304,  0x0,  0x3b9,  0x306,  0x0,  0x3b9,  0x308,  0x0,  0x3b9,  0x308,  0x300,  0x0,  0x3b9,  0x308,  0x301,  0x0,  0x3b9,  0x308,  0x342,  0x0,  0x3b9,  0x313,  0x0,  0x3b9,  0x313,  0x300,  0x0,  0x3b9,  0x313,  0x301,  0x0,  0x3b9,  0x313,  0x342,  0x0,  0x3b9,  0x314,  0x0,  0x3b9,  0x314,  0x300,  0x0,  0x3b9,  0x314,  0x301,  0x0,  0x3b9,  0x314,  0x342,  0x0,  0x3b9,  0x342,  0x0,  0x3ba,  0x0,  0x3bb,  0x0,  0x3bc,  0x0,  0x3bc,  0x41,  0x0,  0x3bc,  0x46,  0x0,  0x3bc,  0x56,  0x0,  0x3bc,  0x57,  0x0,  0x3bc,  0x67,  0x0,  0x3bc,  0x6c,  0x0,  0x3bc,  0x6d,  0x0,  0x3bc,  0x73,  0x0,  0x3bd,  0x0,  0x3be,  0x0,  0x3bf,  0x0,  0x3bf,  0x300,  0x0,  0x3bf,  0x301,  0x0,  0x3bf,  0x313,  0x0,  0x3bf,  0x313,  0x300,  0x0,  0x3bf,  0x313,  0x301,  0x0,  0x3bf,  0x314,  0x0,  0x3bf,  0x314,  0x300,  0x0,  0x3bf,  0x314,  0x301,  0x0,  0x3c0,  0x0,  0x3c1,  0x0,  0x3c1,  0x313,  0x0,  0x3c1,  0x314,  0x0,  0x3c2,  0x0,  0x3c3,  0x0,  0x3c4,  0x0,  0x3c5,  0x0,  0x3c5,  0x300,  0x0,  0x3c5,  0x301,  0x0,  0x3c5,  0x304,  0x0,  0x3c5,  0x306,  0x0,  0x3c5,  0x308,  0x0,  0x3c5,  0x308,  0x300,  0x0,  0x3c5,  0x308,  0x301,  0x0,  0x3c5,  0x308,  0x342,  0x0,  0x3c5,  0x313,  0x0,  0x3c5,  0x313,  0x300,  0x0,  0x3c5,  0x313,  0x301,  0x0,  0x3c5,  0x313,  0x342,  0x0,  0x3c5,  0x314,  0x0,  0x3c5,  0x314,  0x300,  0x0,  0x3c5,  0x314,  0x301,  0x0,  0x3c5,  0x314,  0x342,  0x0,  0x3c5,  0x342,  0x0,  0x3c6,  0x0,  0x3c7,  0x0,  0x3c8,  0x0,  0x3c9,  0x0,  0x3c9,  0x300,  0x0,  0x3c9,  0x300,  0x345,  0x0,  0x3c9,  0x301,  0x0,  0x3c9,  0x301,  0x345,  0x0,  0x3c9,  0x313,  0x0,  0x3c9,  0x313,  0x300,  0x0,  0x3c9,  0x313,  0x300,  0x345,  0x0,  0x3c9,  0x313,  0x301,  0x0,  0x3c9,  0x313,  0x301,  0x345,  0x0,  0x3c9,  0x313,  0x342,  0x0,  0x3c9,  0x313,  0x342,  0x345,  0x0,  0x3c9,  0x313,  0x345,  0x0,  0x3c9,  0x314,  0x0,  0x3c9,  0x314,  0x300,  0x0,  0x3c9,  0x314,  0x300,  0x345,  0x0,  0x3c9,  0x314,  0x301,  0x0,  0x3c9,  0x314,  0x301,  0x345,  0x0,  0x3c9,  0x314,  0x342,  0x0,  0x3c9,  0x314,  0x342,  0x345,  0x0,  0x3c9,  0x314,  0x345,  0x0,  0x3c9,  0x342,  0x0,  0x3c9,  0x342,  0x345,  0x0,  0x3c9,  0x345,  0x0,  0x3dc,  0x0,  0x3dd,  0x0,  0x406,  0x308,  0x0,  0x410,  0x306,  0x0,  0x410,  0x308,  0x0,  0x413,  0x301,  0x0,  0x415,  0x300,  0x0,  0x415,  0x306,  0x0,  0x415,  0x308,  0x0,  0x416,  0x306,  0x0,  0x416,  0x308,  0x0,  0x417,  0x308,  0x0,  0x418,  0x300,  0x0,  0x418,  0x304,  0x0,  0x418,  0x306,  0x0,  0x418,  0x308,  0x0,  0x41a,  0x301,  0x0,  0x41e,  0x308,  0x0,  0x423,  0x304,  0x0,  0x423,  0x306,  0x0,  0x423,  0x308,  0x0,  0x423,  0x30b,  0x0,  0x427,  0x308,  0x0,  0x42b,  0x308,  0x0,  0x42d,  0x308,  0x0,  0x430,  0x306,  0x0,  0x430,  0x308,  0x0,  0x433,  0x301,  0x0,  0x435,  0x300,  0x0,  0x435,  0x306,  0x0,  0x435,  0x308,  0x0,  0x436,  0x306,  0x0,  0x436,  0x308,  0x0,  0x437,  0x308,  0x0,  0x438,  0x300,  0x0,  0x438,  0x304,  0x0,  0x438,  0x306,  0x0,  0x438,  0x308,  0x0,  0x43a,  0x301,  0x0,  0x43d,  0x0,  0x43e,  0x308,  0x0,  0x443,  0x304,  0x0,  0x443,  0x306,  0x0,  0x443,  0x308,  0x0,  0x443,  0x30b,  0x0,  0x447,  0x308,  0x0,  0x44b,  0x308,  0x0,  0x44d,  0x308,  0x0,  0x456,  0x308,  0x0,  0x474,  0x30f,  0x0,  0x475,  0x30f,  0x0,  0x4d8,  0x308,  0x0,  0x4d9,  0x308,  0x0,  0x4e8,  0x308,  0x0,  0x4e9,  0x308,  0x0,  0x565,  0x582,  0x0,  0x574,  0x565,  0x0,  0x574,  0x56b,  0x0,  0x574,  0x56d,  0x0,  0x574,  0x576,  0x0,  0x57e,  0x576,  0x0,  0x5d0,  0x0,  0x5d0,  0x5b7,  0x0,  0x5d0,  0x5b8,  0x0,  0x5d0,  0x5bc,  0x0,  0x5d0,  0x5dc,  0x0,  0x5d1,  0x0,  0x5d1,  0x5bc,  0x0,  0x5d1,  0x5bf,  0x0,  0x5d2,  0x0,  0x5d2,  0x5bc,  0x0,  0x5d3,  0x0,  0x5d3,  0x5bc,  0x0,  0x5d4,  0x0,  0x5d4,  0x5bc,  0x0,  0x5d5,  0x5b9,  0x0,  0x5d5,  0x5bc,  0x0,  0x5d6,  0x5bc,  0x0,  0x5d8,  0x5bc,  0x0,  0x5d9,  0x5b4,  0x0,  0x5d9,  0x5bc,  0x0,  0x5da,  0x5bc,  0x0,  0x5db,  0x0,  0x5db,  0x5bc,  0x0,  0x5db,  0x5bf,  0x0,  0x5dc,  0x0,  0x5dc,  0x5bc,  0x0,  0x5dd,  0x0,  0x5de,  0x5bc,  0x0,  0x5e0,  0x5bc,  0x0,  0x5e1,  0x5bc,  0x0,  0x5e2,  0x0,  0x5e3,  0x5bc,  0x0,  0x5e4,  0x5bc,  0x0,  0x5e4,  0x5bf,  0x0,  0x5e6,  0x5bc,  0x0,  0x5e7,  0x5bc,  0x0,  0x5e8,  0x0,  0x5e8,  0x5bc,  0x0,  0x5e9,  0x5bc,  0x0,  0x5e9,  0x5bc,  0x5c1,  0x0,  0x5e9,  0x5bc,  0x5c2,  0x0,  0x5e9,  0x5c1,  0x0,  0x5e9,  0x5c2,  0x0,  0x5ea,  0x0,  0x5ea,  0x5bc,  0x0,  0x5f2,  0x5b7,  0x0,  0x621,  0x0,  0x627,  0x0,  0x627,  0x643,  0x628,  0x631,  0x0,  0x627,  0x644,  0x644,  0x647,  0x0,  0x627,  0x64b,  0x0,  0x627,  0x653,  0x0,  0x627,  0x654,  0x0,  0x627,  0x655,  0x0,  0x627,  0x674,  0x0,  0x628,  0x0,  0x628,  0x62c,  0x0,  0x628,  0x62d,  0x0,  0x628,  0x62d,  0x64a,  0x0,  0x628,  0x62e,  0x0,  0x628,  0x62e,  0x64a,  0x0,  0x628,  0x631,  0x0,  0x628,  0x632,  0x0,  0x628,  0x645,  0x0,  0x628,  0x646,  0x0,  0x628,  0x647,  0x0,  0x628,  0x649,  0x0,  0x628,  0x64a,  0x0,  0x629,  0x0,  0x62a,  0x0,  0x62a,  0x62c,  0x0,  0x62a,  0x62c,  0x645,  0x0,  0x62a,  0x62c,  0x649,  0x0,  0x62a,  0x62c,  0x64a,  0x0,  0x62a,  0x62d,  0x0,  0x62a,  0x62d,  0x62c,  0x0,  0x62a,  0x62d,  0x645,  0x0,  0x62a,  0x62e,  0x0,  0x62a,  0x62e,  0x645,  0x0,  0x62a,  0x62e,  0x649,  0x0,  0x62a,  0x62e,  0x64a,  0x0,  0x62a,  0x631,  0x0,  0x62a,  0x632,  0x0,  0x62a,  0x645,  0x0,  0x62a,  0x645,  0x62c,  0x0,  0x62a,  0x645,  0x62d,  0x0,  0x62a,  0x645,  0x62e,  0x0,  0x62a,  0x645,  0x649,  0x0,  0x62a,  0x645,  0x64a,  0x0,  0x62a,  0x646,  0x0,  0x62a,  0x647,  0x0,  0x62a,  0x649,  0x0,  0x62a,  0x64a,  0x0,  0x62b,  0x0,  0x62b,  0x62c,  0x0,  0x62b,  0x631,  0x0,  0x62b,  0x632,  0x0,  0x62b,  0x645,  0x0,  0x62b,  0x646,  0x0,  0x62b,  0x647,  0x0,  0x62b,  0x649,  0x0,  0x62b,  0x64a,  0x0,  0x62c,  0x0,  0x62c,  0x62d,  0x0,  0x62c,  0x62d,  0x649,  0x0,  0x62c,  0x62d,  0x64a,  0x0,  0x62c,  0x644,  0x20,  0x62c,  0x644,  0x627,  0x644,  0x647,  0x0,  0x62c,  0x645,  0x0,  0x62c,  0x645,  0x62d,  0x0,  0x62c,  0x645,  0x649,  0x0,  0x62c,  0x645,  0x64a,  0x0,  0x62c,  0x649,  0x0,  0x62c,  0x64a,  0x0,  0x62d,  0x0,  0x62d,  0x62c,  0x0,  0x62d,  0x62c,  0x64a,  0x0,  0x62d,  0x645,  0x0,  0x62d,  0x645,  0x649,  0x0,  0x62d,  0x645,  0x64a,  0x0,  0x62d,  0x649,  0x0,  0x62d,  0x64a,  0x0,  0x62e,  0x0,  0x62e,  0x62c,  0x0,  0x62e,  0x62d,  0x0,  0x62e,  0x645,  0x0,  0x62e,  0x649,  0x0,  0x62e,  0x64a,  0x0,  0x62f,  0x0,  0x630,  0x0,  0x630,  0x670,  0x0,  0x631,  0x0,  0x631,  0x633,  0x648,  0x644,  0x0,  0x631,  0x670,  0x0,  0x631,  0x6cc,  0x627,  0x644,  0x0,  0x632,  0x0,  0x633,  0x0,  0x633,  0x62c,  0x0,  0x633,  0x62c,  0x62d,  0x0,  0x633,  0x62c,  0x649,  0x0,  0x633,  0x62d,  0x0,  0x633,  0x62d,  0x62c,  0x0,  0x633,  0x62e,  0x0,  0x633,  0x62e,  0x649,  0x0,  0x633,  0x62e,  0x64a,  0x0,  0x633,  0x631,  0x0,  0x633,  0x645,  0x0,  0x633,  0x645,  0x62c,  0x0,  0x633,  0x645,  0x62d,  0x0,  0x633,  0x645,  0x645,  0x0,  0x633,  0x647,  0x0,  0x633,  0x649,  0x0,  0x633,  0x64a,  0x0,  0x634,  0x0,  0x634,  0x62c,  0x0,  0x634,  0x62c,  0x64a,  0x0,  0x634,  0x62d,  0x0,  0x634,  0x62d,  0x645,  0x0,  0x634,  0x62d,  0x64a,  0x0,  0x634,  0x62e,  0x0,  0x634,  0x631,  0x0,  0x634,  0x645,  0x0,  0x634,  0x645,  0x62e,  0x0,  0x634,  0x645,  0x645,  0x0,  0x634,  0x647,  0x0,  0x634,  0x649,  0x0,  0x634,  0x64a,  0x0,  0x635,  0x0,  0x635,  0x62d,  0x0,  0x635,  0x62d,  0x62d,  0x0,  0x635,  0x62d,  0x64a,  0x0,  0x635,  0x62e,  0x0,  0x635,  0x631,  0x0,  0x635,  0x644,  0x639,  0x645,  0x0,  0x635,  0x644,  0x649,  0x0,  0x635,  0x644,  0x649,  0x20,  0x627,  0x644,  0x644,  0x647,  0x20,  0x639,  0x644,  0x64a,  0x647,  0x20,  0x648,  0x633,  0x644,  0x645,  0x0,  0x635,  0x644,  0x6d2,  0x0,  0x635,  0x645,  0x0,  0x635,  0x645,  0x645,  0x0,  0x635,  0x649,  0x0,  0x635,  0x64a,  0x0,  0x636,  0x0,  0x636,  0x62c,  0x0,  0x636,  0x62d,  0x0,  0x636,  0x62d,  0x649,  0x0,  0x636,  0x62d,  0x64a,  0x0,  0x636,  0x62e,  0x0,  0x636,  0x62e,  0x645,  0x0,  0x636,  0x631,  0x0,  0x636,  0x645,  0x0,  0x636,  0x649,  0x0,  0x636,  0x64a,  0x0,  0x637,  0x0,  0x637,  0x62d,  0x0,  0x637,  0x645,  0x0,  0x637,  0x645,  0x62d,  0x0,  0x637,  0x645,  0x645,  0x0,  0x637,  0x645,  0x64a,  0x0,  0x637,  0x649,  0x0,  0x637,  0x64a,  0x0,  0x638,  0x0,  0x638,  0x645,  0x0,  0x639,  0x0,  0x639,  0x62c,  0x0,  0x639,  0x62c,  0x645,  0x0,  0x639,  0x644,  0x64a,  0x647,  0x0,  0x639,  0x645,  0x0,  0x639,  0x645,  0x645,  0x0,  0x639,  0x645,  0x649,  0x0,  0x639,  0x645,  0x64a,  0x0,  0x639,  0x649,  0x0,  0x639,  0x64a,  0x0,  0x63a,  0x0,  0x63a,  0x62c,  0x0,  0x63a,  0x645,  0x0,  0x63a,  0x645,  0x645,  0x0,  0x63a,  0x645,  0x649,  0x0,  0x63a,  0x645,  0x64a,  0x0,  0x63a,  0x649,  0x0,  0x63a,  0x64a,  0x0,  0x640,  0x64b,  0x0,  0x640,  0x64e,  0x0,  0x640,  0x64e,  0x651,  0x0,  0x640,  0x64f,  0x0,  0x640,  0x64f,  0x651,  0x0,  0x640,  0x650,  0x0,  0x640,  0x650,  0x651,  0x0,  0x640,  0x651,  0x0,  0x640,  0x652,  0x0,  0x641,  0x0,  0x641,  0x62c,  0x0,  0x641,  0x62d,  0x0,  0x641,  0x62e,  0x0,  0x641,  0x62e,  0x645,  0x0,  0x641,  0x645,  0x0,  0x641,  0x645,  0x64a,  0x0,  0x641,  0x649,  0x0,  0x641,  0x64a,  0x0,  0x642,  0x0,  0x642,  0x62d,  0x0,  0x642,  0x644,  0x6d2,  0x0,  0x642,  0x645,  0x0,  0x642,  0x645,  0x62d,  0x0,  0x642,  0x645,  0x645,  0x0,  0x642,  0x645,  0x64a,  0x0,  0x642,  0x649,  0x0,  0x642,  0x64a,  0x0,  0x643,  0x0,  0x643,  0x627,  0x0,  0x643,  0x62c,  0x0,  0x643,  0x62d,  0x0,  0x643,  0x62e,  0x0,  0x643,  0x644,  0x0,  0x643,  0x645,  0x0,  0x643,  0x645,  0x645,  0x0,  0x643,  0x645,  0x64a,  0x0,  0x643,  0x649,  0x0,  0x643,  0x64a,  0x0,  0x644,  0x0,  0x644,  0x627,  0x0,  0x644,  0x627,  0x653,  0x0,  0x644,  0x627,  0x654,  0x0,  0x644,  0x627,  0x655,  0x0,  0x644,  0x62c,  0x0,  0x644,  0x62c,  0x62c,  0x0,  0x644,  0x62c,  0x645,  0x0,  0x644,  0x62c,  0x64a,  0x0,  0x644,  0x62d,  0x0,  0x644,  0x62d,  0x645,  0x0,  0x644,  0x62d,  0x649,  0x0,  0x644,  0x62d,  0x64a,  0x0,  0x644,  0x62e,  0x0,  0x644,  0x62e,  0x645,  0x0,  0x644,  0x645,  0x0,  0x644,  0x645,  0x62d,  0x0,  0x644,  0x645,  0x64a,  0x0,  0x644,  0x647,  0x0,  0x644,  0x649,  0x0,  0x644,  0x64a,  0x0,  0x645,  0x0,  0x645,  0x627,  0x0,  0x645,  0x62c,  0x0,  0x645,  0x62c,  0x62d,  0x0,  0x645,  0x62c,  0x62e,  0x0,  0x645,  0x62c,  0x645,  0x0,  0x645,  0x62c,  0x64a,  0x0,  0x645,  0x62d,  0x0,  0x645,  0x62d,  0x62c,  0x0,  0x645,  0x62d,  0x645,  0x0,  0x645,  0x62d,  0x645,  0x62f,  0x0,  0x645,  0x62d,  0x64a,  0x0,  0x645,  0x62e,  0x0,  0x645,  0x62e,  0x62c,  0x0,  0x645,  0x62e,  0x645,  0x0,  0x645,  0x62e,  0x64a,  0x0,  0x645,  0x645,  0x0,  0x645,  0x645,  0x64a,  0x0,  0x645,  0x649,  0x0,  0x645,  0x64a,  0x0,  0x646,  0x0,  0x646,  0x62c,  0x0,  0x646,  0x62c,  0x62d,  0x0,  0x646,  0x62c,  0x645,  0x0,  0x646,  0x62c,  0x649,  0x0,  0x646,  0x62c,  0x64a,  0x0,  0x646,  0x62d,  0x0,  0x646,  0x62d,  0x645,  0x0,  0x646,  0x62d,  0x649,  0x0,  0x646,  0x62d,  0x64a,  0x0,  0x646,  0x62e,  0x0,  0x646,  0x631,  0x0,  0x646,  0x632,  0x0,  0x646,  0x645,  0x0,  0x646,  0x645,  0x649,  0x0,  0x646,  0x645,  0x64a,  0x0,  0x646,  0x646,  0x0,  0x646,  0x647,  0x0,  0x646,  0x649,  0x0,  0x646,  0x64a,  0x0,  0x647,  0x0,  0x647,  0x62c,  0x0,  0x647,  0x645,  0x0,  0x647,  0x645,  0x62c,  0x0,  0x647,  0x645,  0x645,  0x0,  0x647,  0x649,  0x0,  0x647,  0x64a,  0x0,  0x647,  0x670,  0x0,  0x648,  0x0,  0x648,  0x633,  0x644,  0x645,  0x0,  0x648,  0x654,  0x0,  0x648,  0x674,  0x0,  0x649,  0x0,  0x649,  0x670,  0x0,  0x64a,  0x0,  0x64a,  0x62c,  0x0,  0x64a,  0x62c,  0x64a,  0x0,  0x64a,  0x62d,  0x0,  0x64a,  0x62d,  0x64a,  0x0,  0x64a,  0x62e,  0x0,  0x64a,  0x631,  0x0,  0x64a,  0x632,  0x0,  0x64a,  0x645,  0x0,  0x64a,  0x645,  0x645,  0x0,  0x64a,  0x645,  0x64a,  0x0,  0x64a,  0x646,  0x0,  0x64a,  0x647,  0x0,  0x64a,  0x649,  0x0,  0x64a,  0x64a,  0x0,  0x64a,  0x654,  0x0,  0x64a,  0x654,  0x627,  0x0,  0x64a,  0x654,  0x62c,  0x0,  0x64a,  0x654,  0x62d,  0x0,  0x64a,  0x654,  0x62e,  0x0,  0x64a,  0x654,  0x631,  0x0,  0x64a,  0x654,  0x632,  0x0,  0x64a,  0x654,  0x645,  0x0,  0x64a,  0x654,  0x646,  0x0,  0x64a,  0x654,  0x647,  0x0,  0x64a,  0x654,  0x648,  0x0,  0x64a,  0x654,  0x649,  0x0,  0x64a,  0x654,  0x64a,  0x0,  0x64a,  0x654,  0x6c6,  0x0,  0x64a,  0x654,  0x6c7,  0x0,  0x64a,  0x654,  0x6c8,  0x0,  0x64a,  0x654,  0x6d0,  0x0,  0x64a,  0x654,  0x6d5,  0x0,  0x64a,  0x674,  0x0,  0x66e,  0x0,  0x66f,  0x0,  0x671,  0x0,  0x679,  0x0,  0x67a,  0x0,  0x67b,  0x0,  0x67e,  0x0,  0x67f,  0x0,  0x680,  0x0,  0x683,  0x0,  0x684,  0x0,  0x686,  0x0,  0x687,  0x0,  0x688,  0x0,  0x68c,  0x0,  0x68d,  0x0,  0x68e,  0x0,  0x691,  0x0,  0x698,  0x0,  0x6a1,  0x0,  0x6a4,  0x0,  0x6a6,  0x0,  0x6a9,  0x0,  0x6ad,  0x0,  0x6af,  0x0,  0x6b1,  0x0,  0x6b3,  0x0,  0x6ba,  0x0,  0x6bb,  0x0,  0x6be,  0x0,  0x6c1,  0x0,  0x6c1,  0x654,  0x0,  0x6c5,  0x0,  0x6c6,  0x0,  0x6c7,  0x0,  0x6c7,  0x674,  0x0,  0x6c8,  0x0,  0x6c9,  0x0,  0x6cb,  0x0,  0x6cc,  0x0,  0x6d0,  0x0,  0x6d2,  0x0,  0x6d2,  0x654,  0x0,  0x6d5,  0x654,  0x0,  0x915,  0x93c,  0x0,  0x916,  0x93c,  0x0,  0x917,  0x93c,  0x0,  0x91c,  0x93c,  0x0,  0x921,  0x93c,  0x0,  0x922,  0x93c,  0x0,  0x928,  0x93c,  0x0,  0x92b,  0x93c,  0x0,  0x92f,  0x93c,  0x0,  0x930,  0x93c,  0x0,  0x933,  0x93c,  0x0,  0x9a1,  0x9bc,  0x0,  0x9a2,  0x9bc,  0x0,  0x9af,  0x9bc,  0x0,  0x9c7,  0x9be,  0x0,  0x9c7,  0x9d7,  0x0,  0xa16,  0xa3c,  0x0,  0xa17,  0xa3c,  0x0,  0xa1c,  0xa3c,  0x0,  0xa2b,  0xa3c,  0x0,  0xa32,  0xa3c,  0x0,  0xa38,  0xa3c,  0x0,  0xb21,  0xb3c,  0x0,  0xb22,  0xb3c,  0x0,  0xb47,  0xb3e,  0x0,  0xb47,  0xb56,  0x0,  0xb47,  0xb57,  0x0,  0xb92,  0xbd7,  0x0,  0xbc6,  0xbbe,  0x0,  0xbc6,  0xbd7,  0x0,  0xbc7,  0xbbe,  0x0,  0xc46,  0xc56,  0x0,  0xcbf,  0xcd5,  0x0,  0xcc6,  0xcc2,  0x0,  0xcc6,  0xcc2,  0xcd5,  0x0,  0xcc6,  0xcd5,  0x0,  0xcc6,  0xcd6,  0x0,  0xd46,  0xd3e,  0x0,  0xd46,  0xd57,  0x0,  0xd47,  0xd3e,  0x0,  0xdd9,  0xdca,  0x0,  0xdd9,  0xdcf,  0x0,  0xdd9,  0xdcf,  0xdca,  0x0,  0xdd9,  0xddf,  0x0,  0xe4d,  0xe32,  0x0,  0xeab,  0xe99,  0x0,  0xeab,  0xea1,  0x0,  0xecd,  0xeb2,  0x0,  0xf0b,  0x0,  0xf40,  0xfb5,  0x0,  0xf42,  0xfb7,  0x0,  0xf4c,  0xfb7,  0x0,  0xf51,  0xfb7,  0x0,  0xf56,  0xfb7,  0x0,  0xf5b,  0xfb7,  0x0,  0xf71,  0xf72,  0x0,  0xf71,  0xf74,  0x0,  0xf71,  0xf80,  0x0,  0xf90,  0xfb5,  0x0,  0xf92,  0xfb7,  0x0,  0xf9c,  0xfb7,  0x0,  0xfa1,  0xfb7,  0x0,  0xfa6,  0xfb7,  0x0,  0xfab,  0xfb7,  0x0,  0xfb2,  0xf71,  0xf80,  0x0,  0xfb2,  0xf80,  0x0,  0xfb3,  0xf71,  0xf80,  0x0,  0xfb3,  0xf80,  0x0,  0x1025,  0x102e,  0x0,  0x10dc,  0x0,  0x1100,  0x0,  0x1100,  0x1161,  0x0,  0x1101,  0x0,  0x1102,  0x0,  0x1102,  0x1161,  0x0,  0x1103,  0x0,  0x1103,  0x1161,  0x0,  0x1104,  0x0,  0x1105,  0x0,  0x1105,  0x1161,  0x0,  0x1106,  0x0,  0x1106,  0x1161,  0x0,  0x1107,  0x0,  0x1107,  0x1161,  0x0,  0x1108,  0x0,  0x1109,  0x0,  0x1109,  0x1161,  0x0,  0x110a,  0x0,  0x110b,  0x0,  0x110b,  0x1161,  0x0,  0x110b,  0x116e,  0x0,  0x110c,  0x0,  0x110c,  0x1161,  0x0,  0x110c,  0x116e,  0x110b,  0x1174,  0x0,  0x110d,  0x0,  0x110e,  0x0,  0x110e,  0x1161,  0x0,  0x110e,  0x1161,  0x11b7,  0x1100,  0x1169,  0x0,  0x110f,  0x0,  0x110f,  0x1161,  0x0,  0x1110,  0x0,  0x1110,  0x1161,  0x0,  0x1111,  0x0,  0x1111,  0x1161,  0x0,  0x1112,  0x0,  0x1112,  0x1161,  0x0,  0x1114,  0x0,  0x1115,  0x0,  0x111a,  0x0,  0x111c,  0x0,  0x111d,  0x0,  0x111e,  0x0,  0x1120,  0x0,  0x1121,  0x0,  0x1122,  0x0,  0x1123,  0x0,  0x1127,  0x0,  0x1129,  0x0,  0x112b,  0x0,  0x112c,  0x0,  0x112d,  0x0,  0x112e,  0x0,  0x112f,  0x0,  0x1132,  0x0,  0x1136,  0x0,  0x1140,  0x0,  0x1147,  0x0,  0x114c,  0x0,  0x1157,  0x0,  0x1158,  0x0,  0x1159,  0x0,  0x1160,  0x0,  0x1161,  0x0,  0x1162,  0x0,  0x1163,  0x0,  0x1164,  0x0,  0x1165,  0x0,  0x1166,  0x0,  0x1167,  0x0,  0x1168,  0x0,  0x1169,  0x0,  0x116a,  0x0,  0x116b,  0x0,  0x116c,  0x0,  0x116d,  0x0,  0x116e,  0x0,  0x116f,  0x0,  0x1170,  0x0,  0x1171,  0x0,  0x1172,  0x0,  0x1173,  0x0,  0x1174,  0x0,  0x1175,  0x0,  0x1184,  0x0,  0x1185,  0x0,  0x1188,  0x0,  0x1191,  0x0,  0x1192,  0x0,  0x1194,  0x0,  0x119e,  0x0,  0x11a1,  0x0,  0x11aa,  0x0,  0x11ac,  0x0,  0x11ad,  0x0,  0x11b0,  0x0,  0x11b1,  0x0,  0x11b2,  0x0,  0x11b3,  0x0,  0x11b4,  0x0,  0x11b5,  0x0,  0x11c7,  0x0,  0x11c8,  0x0,  0x11cc,  0x0,  0x11ce,  0x0,  0x11d3,  0x0,  0x11d7,  0x0,  0x11d9,  0x0,  0x11dd,  0x0,  0x11df,  0x0,  0x11f1,  0x0,  0x11f2,  0x0,  0x1b05,  0x1b35,  0x0,  0x1b07,  0x1b35,  0x0,  0x1b09,  0x1b35,  0x0,  0x1b0b,  0x1b35,  0x0,  0x1b0d,  0x1b35,  0x0,  0x1b11,  0x1b35,  0x0,  0x1b3a,  0x1b35,  0x0,  0x1b3c,  0x1b35,  0x0,  0x1b3e,  0x1b35,  0x0,  0x1b3f,  0x1b35,  0x0,  0x1b42,  0x1b35,  0x0,  0x1d02,  0x0,  0x1d16,  0x0,  0x1d17,  0x0,  0x1d1c,  0x0,  0x1d1d,  0x0,  0x1d25,  0x0,  0x1d7b,  0x0,  0x1d85,  0x0,  0x2010,  0x0,  0x2013,  0x0,  0x2014,  0x0,  0x2032,  0x2032,  0x0,  0x2032,  0x2032,  0x2032,  0x0,  0x2032,  0x2032,  0x2032,  0x2032,  0x0,  0x2035,  0x2035,  0x0,  0x2035,  0x2035,  0x2035,  0x0,  0x20a9,  0x0,  0x2190,  0x0,  0x2190,  0x338,  0x0,  0x2191,  0x0,  0x2192,  0x0,  0x2192,  0x338,  0x0,  0x2193,  0x0,  0x2194,  0x338,  0x0,  0x21d0,  0x338,  0x0,  0x21d2,  0x338,  0x0,  0x21d4,  0x338,  0x0,  0x2202,  0x0,  0x2203,  0x338,  0x0,  0x2207,  0x0,  0x2208,  0x338,  0x0,  0x220b,  0x338,  0x0,  0x2211,  0x0,  0x2212,  0x0,  0x2223,  0x338,  0x0,  0x2225,  0x338,  0x0,  0x222b,  0x222b,  0x0,  0x222b,  0x222b,  0x222b,  0x0,  0x222b,  0x222b,  0x222b,  0x222b,  0x0,  0x222e,  0x222e,  0x0,  0x222e,  0x222e,  0x222e,  0x0,  0x223c,  0x338,  0x0,  0x2243,  0x338,  0x0,  0x2245,  0x338,  0x0,  0x2248,  0x338,  0x0,  0x224d,  0x338,  0x0,  0x2261,  0x338,  0x0,  0x2264,  0x338,  0x0,  0x2265,  0x338,  0x0,  0x2272,  0x338,  0x0,  0x2273,  0x338,  0x0,  0x2276,  0x338,  0x0,  0x2277,  0x338,  0x0,  0x227a,  0x338,  0x0,  0x227b,  0x338,  0x0,  0x227c,  0x338,  0x0,  0x227d,  0x338,  0x0,  0x2282,  0x338,  0x0,  0x2283,  0x338,  0x0,  0x2286,  0x338,  0x0,  0x2287,  0x338,  0x0,  0x2291,  0x338,  0x0,  0x2292,  0x338,  0x0,  0x22a2,  0x338,  0x0,  0x22a8,  0x338,  0x0,  0x22a9,  0x338,  0x0,  0x22ab,  0x338,  0x0,  0x22b2,  0x338,  0x0,  0x22b3,  0x338,  0x0,  0x22b4,  0x338,  0x0,  0x22b5,  0x338,  0x0,  0x2502,  0x0,  0x25a0,  0x0,  0x25cb,  0x0,  0x2985,  0x0,  0x2986,  0x0,  0x2add,  0x338,  0x0,  0x2d61,  0x0,  0x3001,  0x0,  0x3002,  0x0,  0x3008,  0x0,  0x3009,  0x0,  0x300a,  0x0,  0x300b,  0x0,  0x300c,  0x0,  0x300d,  0x0,  0x300e,  0x0,  0x300f,  0x0,  0x3010,  0x0,  0x3011,  0x0,  0x3012,  0x0,  0x3014,  0x0,  0x3014,  0x53,  0x3015,  0x0,  0x3014,  0x4e09,  0x3015,  0x0,  0x3014,  0x4e8c,  0x3015,  0x0,  0x3014,  0x52dd,  0x3015,  0x0,  0x3014,  0x5b89,  0x3015,  0x0,  0x3014,  0x6253,  0x3015,  0x0,  0x3014,  0x6557,  0x3015,  0x0,  0x3014,  0x672c,  0x3015,  0x0,  0x3014,  0x70b9,  0x3015,  0x0,  0x3014,  0x76d7,  0x3015,  0x0,  0x3015,  0x0,  0x3016,  0x0,  0x3017,  0x0,  0x3046,  0x3099,  0x0,  0x304b,  0x3099,  0x0,  0x304d,  0x3099,  0x0,  0x304f,  0x3099,  0x0,  0x3051,  0x3099,  0x0,  0x3053,  0x3099,  0x0,  0x3055,  0x3099,  0x0,  0x3057,  0x3099,  0x0,  0x3059,  0x3099,  0x0,  0x305b,  0x3099,  0x0,  0x305d,  0x3099,  0x0,  0x305f,  0x3099,  0x0,  0x3061,  0x3099,  0x0,  0x3064,  0x3099,  0x0,  0x3066,  0x3099,  0x0,  0x3068,  0x3099,  0x0,  0x306f,  0x3099,  0x0,  0x306f,  0x309a,  0x0,  0x3072,  0x3099,  0x0,  0x3072,  0x309a,  0x0,  0x3075,  0x3099,  0x0,  0x3075,  0x309a,  0x0,  0x3078,  0x3099,  0x0,  0x3078,  0x309a,  0x0,  0x307b,  0x304b,  0x0,  0x307b,  0x3099,  0x0,  0x307b,  0x309a,  0x0,  0x3088,  0x308a,  0x0,  0x3099,  0x0,  0x309a,  0x0,  0x309d,  0x3099,  0x0,  0x30a1,  0x0,  0x30a2,  0x0,  0x30a2,  0x30cf,  0x309a,  0x30fc,  0x30c8,  0x0,  0x30a2,  0x30eb,  0x30d5,  0x30a1,  0x0,  0x30a2,  0x30f3,  0x30d8,  0x309a,  0x30a2,  0x0,  0x30a2,  0x30fc,  0x30eb,  0x0,  0x30a3,  0x0,  0x30a4,  0x0,  0x30a4,  0x30cb,  0x30f3,  0x30af,  0x3099,  0x0,  0x30a4,  0x30f3,  0x30c1,  0x0,  0x30a5,  0x0,  0x30a6,  0x0,  0x30a6,  0x3099,  0x0,  0x30a6,  0x30a9,  0x30f3,  0x0,  0x30a7,  0x0,  0x30a8,  0x0,  0x30a8,  0x30b9,  0x30af,  0x30fc,  0x30c8,  0x3099,  0x0,  0x30a8,  0x30fc,  0x30ab,  0x30fc,  0x0,  0x30a9,  0x0,  0x30aa,  0x0,  0x30aa,  0x30f3,  0x30b9,  0x0,  0x30aa,  0x30fc,  0x30e0,  0x0,  0x30ab,  0x0,  0x30ab,  0x3099,  0x0,  0x30ab,  0x3099,  0x30ed,  0x30f3,  0x0,  0x30ab,  0x3099,  0x30f3,  0x30de,  0x0,  0x30ab,  0x30a4,  0x30ea,  0x0,  0x30ab,  0x30e9,  0x30c3,  0x30c8,  0x0,  0x30ab,  0x30ed,  0x30ea,  0x30fc,  0x0,  0x30ad,  0x0,  0x30ad,  0x3099,  0x0,  0x30ad,  0x3099,  0x30ab,  0x3099,  0x0,  0x30ad,  0x3099,  0x30cb,  0x30fc,  0x0,  0x30ad,  0x3099,  0x30eb,  0x30bf,  0x3099,  0x30fc,  0x0,  0x30ad,  0x30e5,  0x30ea,  0x30fc,  0x0,  0x30ad,  0x30ed,  0x0,  0x30ad,  0x30ed,  0x30af,  0x3099,  0x30e9,  0x30e0,  0x0,  0x30ad,  0x30ed,  0x30e1,  0x30fc,  0x30c8,  0x30eb,  0x0,  0x30ad,  0x30ed,  0x30ef,  0x30c3,  0x30c8,  0x0,  0x30af,  0x0,  0x30af,  0x3099,  0x0,  0x30af,  0x3099,  0x30e9,  0x30e0,  0x0,  0x30af,  0x3099,  0x30e9,  0x30e0,  0x30c8,  0x30f3,  0x0,  0x30af,  0x30eb,  0x30bb,  0x3099,  0x30a4,  0x30ed,  0x0,  0x30af,  0x30ed,  0x30fc,  0x30cd,  0x0,  0x30b1,  0x0,  0x30b1,  0x3099,  0x0,  0x30b1,  0x30fc,  0x30b9,  0x0,  0x30b3,  0x0,  0x30b3,  0x3099,  0x0,  0x30b3,  0x30b3,  0x0,  0x30b3,  0x30c8,  0x0,  0x30b3,  0x30eb,  0x30ca,  0x0,  0x30b3,  0x30fc,  0x30db,  0x309a,  0x0,  0x30b5,  0x0,  0x30b5,  0x3099,  0x0,  0x30b5,  0x30a4,  0x30af,  0x30eb,  0x0,  0x30b5,  0x30f3,  0x30c1,  0x30fc,  0x30e0,  0x0,  0x30b7,  0x0,  0x30b7,  0x3099,  0x0,  0x30b7,  0x30ea,  0x30f3,  0x30af,  0x3099,  0x0,  0x30b9,  0x0,  0x30b9,  0x3099,  0x0,  0x30bb,  0x0,  0x30bb,  0x3099,  0x0,  0x30bb,  0x30f3,  0x30c1,  0x0,  0x30bb,  0x30f3,  0x30c8,  0x0,  0x30bd,  0x0,  0x30bd,  0x3099,  0x0,  0x30bf,  0x0,  0x30bf,  0x3099,  0x0,  0x30bf,  0x3099,  0x30fc,  0x30b9,  0x0,  0x30c1,  0x0,  0x30c1,  0x3099,  0x0,  0x30c3,  0x0,  0x30c4,  0x0,  0x30c4,  0x3099,  0x0,  0x30c6,  0x0,  0x30c6,  0x3099,  0x0,  0x30c6,  0x3099,  0x30b7,  0x0,  0x30c8,  0x0,  0x30c8,  0x3099,  0x0,  0x30c8,  0x3099,  0x30eb,  0x0,  0x30c8,  0x30f3,  0x0,  0x30ca,  0x0,  0x30ca,  0x30ce,  0x0,  0x30cb,  0x0,  0x30cc,  0x0,  0x30cd,  0x0,  0x30ce,  0x0,  0x30ce,  0x30c3,  0x30c8,  0x0,  0x30cf,  0x0,  0x30cf,  0x3099,  0x0,  0x30cf,  0x3099,  0x30fc,  0x30ec,  0x30eb,  0x0,  0x30cf,  0x309a,  0x0,  0x30cf,  0x309a,  0x30fc,  0x30bb,  0x30f3,  0x30c8,  0x0,  0x30cf,  0x309a,  0x30fc,  0x30c4,  0x0,  0x30cf,  0x30a4,  0x30c4,  0x0,  0x30d2,  0x0,  0x30d2,  0x3099,  0x0,  0x30d2,  0x3099,  0x30eb,  0x0,  0x30d2,  0x309a,  0x0,  0x30d2,  0x309a,  0x30a2,  0x30b9,  0x30c8,  0x30eb,  0x0,  0x30d2,  0x309a,  0x30af,  0x30eb,  0x0,  0x30d2,  0x309a,  0x30b3,  0x0,  0x30d5,  0x0,  0x30d5,  0x3099,  0x0,  0x30d5,  0x3099,  0x30c3,  0x30b7,  0x30a7,  0x30eb,  0x0,  0x30d5,  0x309a,  0x0,  0x30d5,  0x30a1,  0x30e9,  0x30c3,  0x30c8,  0x3099,  0x0,  0x30d5,  0x30a3,  0x30fc,  0x30c8,  0x0,  0x30d5,  0x30e9,  0x30f3,  0x0,  0x30d8,  0x0,  0x30d8,  0x3099,  0x0,  0x30d8,  0x3099,  0x30fc,  0x30bf,  0x0,  0x30d8,  0x309a,  0x0,  0x30d8,  0x309a,  0x30bd,  0x0,  0x30d8,  0x309a,  0x30cb,  0x30d2,  0x0,  0x30d8,  0x309a,  0x30f3,  0x30b9,  0x0,  0x30d8,  0x309a,  0x30fc,  0x30b7,  0x3099,  0x0,  0x30d8,  0x30af,  0x30bf,  0x30fc,  0x30eb,  0x0,  0x30d8,  0x30eb,  0x30c4,  0x0,  0x30db,  0x0,  0x30db,  0x3099,  0x0,  0x30db,  0x3099,  0x30eb,  0x30c8,  0x0,  0x30db,  0x309a,  0x0,  0x30db,  0x309a,  0x30a4,  0x30f3,  0x30c8,  0x0,  0x30db,  0x309a,  0x30f3,  0x30c8,  0x3099,  0x0,  0x30db,  0x30f3,  0x0,  0x30db,  0x30fc,  0x30eb,  0x0,  0x30db,  0x30fc,  0x30f3,  0x0,  0x30de,  0x0,  0x30de,  0x30a4,  0x30af,  0x30ed,  0x0,  0x30de,  0x30a4,  0x30eb,  0x0,  0x30de,  0x30c3,  0x30cf,  0x0,  0x30de,  0x30eb,  0x30af,  0x0,  0x30de,  0x30f3,  0x30b7,  0x30e7,  0x30f3,  0x0,  0x30df,  0x0,  0x30df,  0x30af,  0x30ed,  0x30f3,  0x0,  0x30df,  0x30ea,  0x0,  0x30df,  0x30ea,  0x30cf,  0x3099,  0x30fc,  0x30eb,  0x0,  0x30e0,  0x0,  0x30e1,  0x0,  0x30e1,  0x30ab,  0x3099,  0x0,  0x30e1,  0x30ab,  0x3099,  0x30c8,  0x30f3,  0x0,  0x30e1,  0x30fc,  0x30c8,  0x30eb,  0x0,  0x30e2,  0x0,  0x30e3,  0x0,  0x30e4,  0x0,  0x30e4,  0x30fc,  0x30c8,  0x3099,  0x0,  0x30e4,  0x30fc,  0x30eb,  0x0,  0x30e5,  0x0,  0x30e6,  0x0,  0x30e6,  0x30a2,  0x30f3,  0x0,  0x30e7,  0x0,  0x30e8,  0x0,  0x30e9,  0x0,  0x30ea,  0x0,  0x30ea,  0x30c3,  0x30c8,  0x30eb,  0x0,  0x30ea,  0x30e9,  0x0,  0x30eb,  0x0,  0x30eb,  0x30d2,  0x309a,  0x30fc,  0x0,  0x30eb,  0x30fc,  0x30d5,  0x3099,  0x30eb,  0x0,  0x30ec,  0x0,  0x30ec,  0x30e0,  0x0,  0x30ec,  0x30f3,  0x30c8,  0x30b1,  0x3099,  0x30f3,  0x0,  0x30ed,  0x0,  0x30ef,  0x0,  0x30ef,  0x3099,  0x0,  0x30ef,  0x30c3,  0x30c8,  0x0,  0x30f0,  0x0,  0x30f0,  0x3099,  0x0,  0x30f1,  0x0,  0x30f1,  0x3099,  0x0,  0x30f2,  0x0,  0x30f2,  0x3099,  0x0,  0x30f3,  0x0,  0x30fb,  0x0,  0x30fc,  0x0,  0x30fd,  0x3099,  0x0,  0x349e,  0x0,  0x34b9,  0x0,  0x34bb,  0x0,  0x34df,  0x0,  0x3515,  0x0,  0x36ee,  0x0,  0x36fc,  0x0,  0x3781,  0x0,  0x382f,  0x0,  0x3862,  0x0,  0x387c,  0x0,  0x38c7,  0x0,  0x38e3,  0x0,  0x391c,  0x0,  0x393a,  0x0,  0x3a2e,  0x0,  0x3a6c,  0x0,  0x3ae4,  0x0,  0x3b08,  0x0,  0x3b19,  0x0,  0x3b49,  0x0,  0x3b9d,  0x0,  0x3c18,  0x0,  0x3c4e,  0x0,  0x3d33,  0x0,  0x3d96,  0x0,  0x3eac,  0x0,  0x3eb8,  0x0,  0x3f1b,  0x0,  0x3ffc,  0x0,  0x4008,  0x0,  0x4018,  0x0,  0x4039,  0x0,  0x4046,  0x0,  0x4096,  0x0,  0x40e3,  0x0,  0x412f,  0x0,  0x4202,  0x0,  0x4227,  0x0,  0x42a0,  0x0,  0x4301,  0x0,  0x4334,  0x0,  0x4359,  0x0,  0x43d5,  0x0,  0x43d9,  0x0,  0x440b,  0x0,  0x446b,  0x0,  0x452b,  0x0,  0x455d,  0x0,  0x4561,  0x0,  0x456b,  0x0,  0x45d7,  0x0,  0x45f9,  0x0,  0x4635,  0x0,  0x46be,  0x0,  0x46c7,  0x0,  0x4995,  0x0,  0x49e6,  0x0,  0x4a6e,  0x0,  0x4a76,  0x0,  0x4ab2,  0x0,  0x4b33,  0x0,  0x4bce,  0x0,  0x4cce,  0x0,  0x4ced,  0x0,  0x4cf8,  0x0,  0x4d56,  0x0,  0x4e00,  0x0,  0x4e01,  0x0,  0x4e03,  0x0,  0x4e09,  0x0,  0x4e0a,  0x0,  0x4e0b,  0x0,  0x4e0d,  0x0,  0x4e19,  0x0,  0x4e26,  0x0,  0x4e28,  0x0,  0x4e2d,  0x0,  0x4e32,  0x0,  0x4e36,  0x0,  0x4e38,  0x0,  0x4e39,  0x0,  0x4e3d,  0x0,  0x4e3f,  0x0,  0x4e41,  0x0,  0x4e59,  0x0,  0x4e5d,  0x0,  0x4e82,  0x0,  0x4e85,  0x0,  0x4e86,  0x0,  0x4e8c,  0x0,  0x4e94,  0x0,  0x4ea0,  0x0,  0x4ea4,  0x0,  0x4eae,  0x0,  0x4eba,  0x0,  0x4ec0,  0x0,  0x4ecc,  0x0,  0x4ee4,  0x0,  0x4f01,  0x0,  0x4f11,  0x0,  0x4f60,  0x0,  0x4f80,  0x0,  0x4f86,  0x0,  0x4f8b,  0x0,  0x4fae,  0x0,  0x4fbb,  0x0,  0x4fbf,  0x0,  0x5002,  0x0,  0x502b,  0x0,  0x507a,  0x0,  0x5099,  0x0,  0x50cf,  0x0,  0x50da,  0x0,  0x50e7,  0x0,  0x512a,  0x0,  0x513f,  0x0,  0x5140,  0x0,  0x5145,  0x0,  0x514d,  0x0,  0x5154,  0x0,  0x5164,  0x0,  0x5165,  0x0,  0x5167,  0x0,  0x5168,  0x0,  0x5169,  0x0,  0x516b,  0x0,  0x516d,  0x0,  0x5177,  0x0,  0x5180,  0x0,  0x5182,  0x0,  0x518d,  0x0,  0x5192,  0x0,  0x5195,  0x0,  0x5196,  0x0,  0x5197,  0x0,  0x5199,  0x0,  0x51a4,  0x0,  0x51ab,  0x0,  0x51ac,  0x0,  0x51b5,  0x0,  0x51b7,  0x0,  0x51c9,  0x0,  0x51cc,  0x0,  0x51dc,  0x0,  0x51de,  0x0,  0x51e0,  0x0,  0x51f5,  0x0,  0x5200,  0x0,  0x5203,  0x0,  0x5207,  0x0,  0x5217,  0x0,  0x521d,  0x0,  0x5229,  0x0,  0x523a,  0x0,  0x523b,  0x0,  0x5246,  0x0,  0x524d,  0x0,  0x5272,  0x0,  0x5277,  0x0,  0x5289,  0x0,  0x529b,  0x0,  0x52a3,  0x0,  0x52b3,  0x0,  0x52b4,  0x0,  0x52c7,  0x0,  0x52c9,  0x0,  0x52d2,  0x0,  0x52de,  0x0,  0x52e4,  0x0,  0x52f5,  0x0,  0x52f9,  0x0,  0x52fa,  0x0,  0x5305,  0x0,  0x5306,  0x0,  0x5315,  0x0,  0x5317,  0x0,  0x531a,  0x0,  0x5338,  0x0,  0x533b,  0x0,  0x533f,  0x0,  0x5341,  0x0,  0x5344,  0x0,  0x5345,  0x0,  0x5349,  0x0,  0x5351,  0x0,  0x5354,  0x0,  0x535a,  0x0,  0x535c,  0x0,  0x5369,  0x0,  0x5370,  0x0,  0x5373,  0x0,  0x5375,  0x0,  0x537d,  0x0,  0x537f,  0x0,  0x5382,  0x0,  0x53b6,  0x0,  0x53c3,  0x0,  0x53c8,  0x0,  0x53ca,  0x0,  0x53cc,  0x0,  0x53df,  0x0,  0x53e3,  0x0,  0x53e5,  0x0,  0x53eb,  0x0,  0x53ef,  0x0,  0x53f1,  0x0,  0x53f3,  0x0,  0x5406,  0x0,  0x5408,  0x0,  0x540d,  0x0,  0x540f,  0x0,  0x541d,  0x0,  0x5438,  0x0,  0x5439,  0x0,  0x5442,  0x0,  0x5448,  0x0,  0x5468,  0x0,  0x549e,  0x0,  0x54a2,  0x0,  0x54bd,  0x0,  0x54f6,  0x0,  0x5510,  0x0,  0x554f,  0x0,  0x5553,  0x0,  0x5555,  0x0,  0x5563,  0x0,  0x5584,  0x0,  0x5587,  0x0,  0x5599,  0x0,  0x559d,  0x0,  0x55ab,  0x0,  0x55b3,  0x0,  0x55b6,  0x0,  0x55c0,  0x0,  0x55c2,  0x0,  0x55e2,  0x0,  0x5606,  0x0,  0x5651,  0x0,  0x5668,  0x0,  0x5674,  0x0,  0x56d7,  0x0,  0x56db,  0x0,  0x56f9,  0x0,  0x5716,  0x0,  0x5717,  0x0,  0x571f,  0x0,  0x5730,  0x0,  0x578b,  0x0,  0x57ce,  0x0,  0x57f4,  0x0,  0x580d,  0x0,  0x5831,  0x0,  0x5832,  0x0,  0x5840,  0x0,  0x585a,  0x0,  0x585e,  0x0,  0x58a8,  0x0,  0x58ac,  0x0,  0x58b3,  0x0,  0x58d8,  0x0,  0x58df,  0x0,  0x58eb,  0x0,  0x58ee,  0x0,  0x58f0,  0x0,  0x58f2,  0x0,  0x58f7,  0x0,  0x5902,  0x0,  0x5906,  0x0,  0x590a,  0x0,  0x5915,  0x0,  0x591a,  0x0,  0x591c,  0x0,  0x5922,  0x0,  0x5927,  0x0,  0x5927,  0x6b63,  0x0,  0x5929,  0x0,  0x5944,  0x0,  0x5948,  0x0,  0x5951,  0x0,  0x5954,  0x0,  0x5962,  0x0,  0x5973,  0x0,  0x59d8,  0x0,  0x59ec,  0x0,  0x5a1b,  0x0,  0x5a27,  0x0,  0x5a62,  0x0,  0x5a66,  0x0,  0x5ab5,  0x0,  0x5b08,  0x0,  0x5b28,  0x0,  0x5b3e,  0x0,  0x5b50,  0x0,  0x5b57,  0x0,  0x5b66,  0x0,  0x5b80,  0x0,  0x5b85,  0x0,  0x5b97,  0x0,  0x5bc3,  0x0,  0x5bd8,  0x0,  0x5be7,  0x0,  0x5bee,  0x0,  0x5bf3,  0x0,  0x5bf8,  0x0,  0x5bff,  0x0,  0x5c06,  0x0,  0x5c0f,  0x0,  0x5c22,  0x0,  0x5c38,  0x0,  0x5c3f,  0x0,  0x5c60,  0x0,  0x5c62,  0x0,  0x5c64,  0x0,  0x5c65,  0x0,  0x5c6e,  0x0,  0x5c71,  0x0,  0x5c8d,  0x0,  0x5cc0,  0x0,  0x5d19,  0x0,  0x5d43,  0x0,  0x5d50,  0x0,  0x5d6b,  0x0,  0x5d6e,  0x0,  0x5d7c,  0x0,  0x5db2,  0x0,  0x5dba,  0x0,  0x5ddb,  0x0,  0x5de1,  0x0,  0x5de2,  0x0,  0x5de5,  0x0,  0x5de6,  0x0,  0x5df1,  0x0,  0x5dfd,  0x0,  0x5dfe,  0x0,  0x5e28,  0x0,  0x5e3d,  0x0,  0x5e69,  0x0,  0x5e72,  0x0,  0x5e73,  0x6210,  0x0,  0x5e74,  0x0,  0x5e7a,  0x0,  0x5e7c,  0x0,  0x5e7f,  0x0,  0x5ea6,  0x0,  0x5eb0,  0x0,  0x5eb3,  0x0,  0x5eb6,  0x0,  0x5ec9,  0x0,  0x5eca,  0x0,  0x5ed2,  0x0,  0x5ed3,  0x0,  0x5ed9,  0x0,  0x5eec,  0x0,  0x5ef4,  0x0,  0x5efe,  0x0,  0x5f04,  0x0,  0x5f0b,  0x0,  0x5f13,  0x0,  0x5f22,  0x0,  0x5f50,  0x0,  0x5f53,  0x0,  0x5f61,  0x0,  0x5f62,  0x0,  0x5f69,  0x0,  0x5f6b,  0x0,  0x5f73,  0x0,  0x5f8b,  0x0,  0x5f8c,  0x0,  0x5f97,  0x0,  0x5f9a,  0x0,  0x5fa9,  0x0,  0x5fad,  0x0,  0x5fc3,  0x0,  0x5fcd,  0x0,  0x5fd7,  0x0,  0x5ff5,  0x0,  0x5ff9,  0x0,  0x6012,  0x0,  0x601c,  0x0,  0x6075,  0x0,  0x6081,  0x0,  0x6094,  0x0,  0x60c7,  0x0,  0x60d8,  0x0,  0x60e1,  0x0,  0x6108,  0x0,  0x6144,  0x0,  0x6148,  0x0,  0x614c,  0x0,  0x614e,  0x0,  0x6160,  0x0,  0x6168,  0x0,  0x617a,  0x0,  0x618e,  0x0,  0x6190,  0x0,  0x61a4,  0x0,  0x61af,  0x0,  0x61b2,  0x0,  0x61de,  0x0,  0x61f2,  0x0,  0x61f6,  0x0,  0x6200,  0x0,  0x6208,  0x0,  0x6210,  0x0,  0x621b,  0x0,  0x622e,  0x0,  0x6234,  0x0,  0x6236,  0x0,  0x624b,  0x0,  0x6253,  0x0,  0x625d,  0x0,  0x6295,  0x0,  0x62b1,  0x0,  0x62c9,  0x0,  0x62cf,  0x0,  0x62d3,  0x0,  0x62d4,  0x0,  0x62fc,  0x0,  0x62fe,  0x0,  0x6307,  0x0,  0x633d,  0x0,  0x6350,  0x0,  0x6355,  0x0,  0x6368,  0x0,  0x637b,  0x0,  0x6383,  0x0,  0x63a0,  0x0,  0x63a9,  0x0,  0x63c4,  0x0,  0x63c5,  0x0,  0x63e4,  0x0,  0x641c,  0x0,  0x6422,  0x0,  0x6452,  0x0,  0x6469,  0x0,  0x6477,  0x0,  0x647e,  0x0,  0x649a,  0x0,  0x649d,  0x0,  0x64c4,  0x0,  0x652f,  0x0,  0x6534,  0x0,  0x654f,  0x0,  0x6556,  0x0,  0x656c,  0x0,  0x6578,  0x0,  0x6587,  0x0,  0x6597,  0x0,  0x6599,  0x0,  0x65a4,  0x0,  0x65b0,  0x0,  0x65b9,  0x0,  0x65c5,  0x0,  0x65e0,  0x0,  0x65e2,  0x0,  0x65e3,  0x0,  0x65e5,  0x0,  0x660e,  0x6cbb,  0x0,  0x6613,  0x0,  0x6620,  0x0,  0x662d,  0x548c,  0x0,  0x6649,  0x0,  0x6674,  0x0,  0x6688,  0x0,  0x6691,  0x0,  0x669c,  0x0,  0x66b4,  0x0,  0x66c6,  0x0,  0x66f0,  0x0,  0x66f4,  0x0,  0x66f8,  0x0,  0x6700,  0x0,  0x6708,  0x0,  0x6709,  0x0,  0x6717,  0x0,  0x671b,  0x0,  0x6721,  0x0,  0x6728,  0x0,  0x674e,  0x0,  0x6753,  0x0,  0x6756,  0x0,  0x675e,  0x0,  0x677b,  0x0,  0x6785,  0x0,  0x6797,  0x0,  0x67f3,  0x0,  0x67fa,  0x0,  0x6817,  0x0,  0x681f,  0x0,  0x682a,  0x0,  0x682a,  0x5f0f,  0x4f1a,  0x793e,  0x0,  0x6852,  0x0,  0x6881,  0x0,  0x6885,  0x0,  0x688e,  0x0,  0x68a8,  0x0,  0x6914,  0x0,  0x6942,  0x0,  0x69a3,  0x0,  0x69ea,  0x0,  0x6a02,  0x0,  0x6a13,  0x0,  0x6aa8,  0x0,  0x6ad3,  0x0,  0x6adb,  0x0,  0x6b04,  0x0,  0x6b20,  0x0,  0x6b21,  0x0,  0x6b54,  0x0,  0x6b62,  0x0,  0x6b63,  0x0,  0x6b72,  0x0,  0x6b77,  0x0,  0x6b79,  0x0,  0x6b9f,  0x0,  0x6bae,  0x0,  0x6bb3,  0x0,  0x6bba,  0x0,  0x6bbb,  0x0,  0x6bcb,  0x0,  0x6bcd,  0x0,  0x6bd4,  0x0,  0x6bdb,  0x0,  0x6c0f,  0x0,  0x6c14,  0x0,  0x6c34,  0x0,  0x6c4e,  0x0,  0x6c67,  0x0,  0x6c88,  0x0,  0x6cbf,  0x0,  0x6ccc,  0x0,  0x6ccd,  0x0,  0x6ce5,  0x0,  0x6ce8,  0x0,  0x6d16,  0x0,  0x6d1b,  0x0,  0x6d1e,  0x0,  0x6d34,  0x0,  0x6d3e,  0x0,  0x6d41,  0x0,  0x6d69,  0x0,  0x6d6a,  0x0,  0x6d77,  0x0,  0x6d78,  0x0,  0x6d85,  0x0,  0x6dcb,  0x0,  0x6dda,  0x0,  0x6dea,  0x0,  0x6df9,  0x0,  0x6e1a,  0x0,  0x6e2f,  0x0,  0x6e6e,  0x0,  0x6e80,  0x0,  0x6e9c,  0x0,  0x6eba,  0x0,  0x6ec7,  0x0,  0x6ecb,  0x0,  0x6ed1,  0x0,  0x6edb,  0x0,  0x6f0f,  0x0,  0x6f14,  0x0,  0x6f22,  0x0,  0x6f23,  0x0,  0x6f6e,  0x0,  0x6fc6,  0x0,  0x6feb,  0x0,  0x6ffe,  0x0,  0x701b,  0x0,  0x701e,  0x0,  0x7039,  0x0,  0x704a,  0x0,  0x706b,  0x0,  0x7070,  0x0,  0x7077,  0x0,  0x707d,  0x0,  0x7099,  0x0,  0x70ad,  0x0,  0x70c8,  0x0,  0x70d9,  0x0,  0x7121,  0x0,  0x7145,  0x0,  0x7149,  0x0,  0x716e,  0x0,  0x719c,  0x0,  0x71ce,  0x0,  0x71d0,  0x0,  0x7210,  0x0,  0x721b,  0x0,  0x7228,  0x0,  0x722a,  0x0,  0x722b,  0x0,  0x7235,  0x0,  0x7236,  0x0,  0x723b,  0x0,  0x723f,  0x0,  0x7247,  0x0,  0x7250,  0x0,  0x7259,  0x0,  0x725b,  0x0,  0x7262,  0x0,  0x7279,  0x0,  0x7280,  0x0,  0x7295,  0x0,  0x72ac,  0x0,  0x72af,  0x0,  0x72c0,  0x0,  0x72fc,  0x0,  0x732a,  0x0,  0x7375,  0x0,  0x737a,  0x0,  0x7384,  0x0,  0x7387,  0x0,  0x7389,  0x0,  0x738b,  0x0,  0x73a5,  0x0,  0x73b2,  0x0,  0x73de,  0x0,  0x7406,  0x0,  0x7409,  0x0,  0x7422,  0x0,  0x7447,  0x0,  0x745c,  0x0,  0x7469,  0x0,  0x7471,  0x0,  0x7485,  0x0,  0x7489,  0x0,  0x7498,  0x0,  0x74ca,  0x0,  0x74dc,  0x0,  0x74e6,  0x0,  0x7506,  0x0,  0x7518,  0x0,  0x751f,  0x0,  0x7524,  0x0,  0x7528,  0x0,  0x7530,  0x0,  0x7532,  0x0,  0x7533,  0x0,  0x7537,  0x0,  0x753b,  0x0,  0x753e,  0x0,  0x7559,  0x0,  0x7565,  0x0,  0x7570,  0x0,  0x758b,  0x0,  0x7592,  0x0,  0x75e2,  0x0,  0x7610,  0x0,  0x761d,  0x0,  0x761f,  0x0,  0x7642,  0x0,  0x7669,  0x0,  0x7676,  0x0,  0x767d,  0x0,  0x76ae,  0x0,  0x76bf,  0x0,  0x76ca,  0x0,  0x76db,  0x0,  0x76e3,  0x0,  0x76e7,  0x0,  0x76ee,  0x0,  0x76f4,  0x0,  0x7701,  0x0,  0x771e,  0x0,  0x771f,  0x0,  0x7740,  0x0,  0x774a,  0x0,  0x778b,  0x0,  0x77a7,  0x0,  0x77db,  0x0,  0x77e2,  0x0,  0x77f3,  0x0,  0x784e,  0x0,  0x786b,  0x0,  0x788c,  0x0,  0x7891,  0x0,  0x78ca,  0x0,  0x78cc,  0x0,  0x78fb,  0x0,  0x792a,  0x0,  0x793a,  0x0,  0x793c,  0x0,  0x793e,  0x0,  0x7948,  0x0,  0x7949,  0x0,  0x7950,  0x0,  0x7956,  0x0,  0x795d,  0x0,  0x795e,  0x0,  0x7965,  0x0,  0x797f,  0x0,  0x7981,  0x0,  0x798d,  0x0,  0x798e,  0x0,  0x798f,  0x0,  0x79ae,  0x0,  0x79b8,  0x0,  0x79be,  0x0,  0x79ca,  0x0,  0x79d8,  0x0,  0x79eb,  0x0,  0x7a1c,  0x0,  0x7a40,  0x0,  0x7a4a,  0x0,  0x7a4f,  0x0,  0x7a74,  0x0,  0x7a7a,  0x0,  0x7a81,  0x0,  0x7ab1,  0x0,  0x7acb,  0x0,  0x7aee,  0x0,  0x7af9,  0x0,  0x7b20,  0x0,  0x7b8f,  0x0,  0x7bc0,  0x0,  0x7bc6,  0x0,  0x7bc9,  0x0,  0x7c3e,  0x0,  0x7c60,  0x0,  0x7c73,  0x0,  0x7c7b,  0x0,  0x7c92,  0x0,  0x7cbe,  0x0,  0x7cd2,  0x0,  0x7cd6,  0x0,  0x7ce3,  0x0,  0x7ce7,  0x0,  0x7ce8,  0x0,  0x7cf8,  0x0,  0x7d00,  0x0,  0x7d10,  0x0,  0x7d22,  0x0,  0x7d2f,  0x0,  0x7d42,  0x0,  0x7d5b,  0x0,  0x7d63,  0x0,  0x7da0,  0x0,  0x7dbe,  0x0,  0x7dc7,  0x0,  0x7df4,  0x0,  0x7e02,  0x0,  0x7e09,  0x0,  0x7e37,  0x0,  0x7e41,  0x0,  0x7e45,  0x0,  0x7f36,  0x0,  0x7f3e,  0x0,  0x7f51,  0x0,  0x7f72,  0x0,  0x7f79,  0x0,  0x7f7a,  0x0,  0x7f85,  0x0,  0x7f8a,  0x0,  0x7f95,  0x0,  0x7f9a,  0x0,  0x7fbd,  0x0,  0x7ffa,  0x0,  0x8001,  0x0,  0x8005,  0x0,  0x800c,  0x0,  0x8012,  0x0,  0x8033,  0x0,  0x8046,  0x0,  0x8060,  0x0,  0x806f,  0x0,  0x8070,  0x0,  0x807e,  0x0,  0x807f,  0x0,  0x8089,  0x0,  0x808b,  0x0,  0x80ad,  0x0,  0x80b2,  0x0,  0x8103,  0x0,  0x813e,  0x0,  0x81d8,  0x0,  0x81e3,  0x0,  0x81e8,  0x0,  0x81ea,  0x0,  0x81ed,  0x0,  0x81f3,  0x0,  0x81fc,  0x0,  0x8201,  0x0,  0x8204,  0x0,  0x820c,  0x0,  0x8218,  0x0,  0x821b,  0x0,  0x821f,  0x0,  0x826e,  0x0,  0x826f,  0x0,  0x8272,  0x0,  0x8278,  0x0,  0x8279,  0x0,  0x828b,  0x0,  0x8291,  0x0,  0x829d,  0x0,  0x82b1,  0x0,  0x82b3,  0x0,  0x82bd,  0x0,  0x82e5,  0x0,  0x82e6,  0x0,  0x831d,  0x0,  0x8323,  0x0,  0x8336,  0x0,  0x8352,  0x0,  0x8353,  0x0,  0x8363,  0x0,  0x83ad,  0x0,  0x83bd,  0x0,  0x83c9,  0x0,  0x83ca,  0x0,  0x83cc,  0x0,  0x83dc,  0x0,  0x83e7,  0x0,  0x83ef,  0x0,  0x83f1,  0x0,  0x843d,  0x0,  0x8449,  0x0,  0x8457,  0x0,  0x84ee,  0x0,  0x84f1,  0x0,  0x84f3,  0x0,  0x84fc,  0x0,  0x8516,  0x0,  0x8564,  0x0,  0x85cd,  0x0,  0x85fa,  0x0,  0x8606,  0x0,  0x8612,  0x0,  0x862d,  0x0,  0x863f,  0x0,  0x864d,  0x0,  0x8650,  0x0,  0x865c,  0x0,  0x8667,  0x0,  0x8669,  0x0,  0x866b,  0x0,  0x8688,  0x0,  0x86a9,  0x0,  0x86e2,  0x0,  0x870e,  0x0,  0x8728,  0x0,  0x876b,  0x0,  0x8779,  0x0,  0x8786,  0x0,  0x87ba,  0x0,  0x87e1,  0x0,  0x8801,  0x0,  0x881f,  0x0,  0x8840,  0x0,  0x884c,  0x0,  0x8860,  0x0,  0x8863,  0x0,  0x88c2,  0x0,  0x88cf,  0x0,  0x88d7,  0x0,  0x88de,  0x0,  0x88e1,  0x0,  0x88f8,  0x0,  0x88fa,  0x0,  0x8910,  0x0,  0x8941,  0x0,  0x8964,  0x0,  0x897e,  0x0,  0x8986,  0x0,  0x898b,  0x0,  0x8996,  0x0,  0x89d2,  0x0,  0x89e3,  0x0,  0x8a00,  0x0,  0x8aa0,  0x0,  0x8aaa,  0x0,  0x8abf,  0x0,  0x8acb,  0x0,  0x8ad2,  0x0,  0x8ad6,  0x0,  0x8aed,  0x0,  0x8af8,  0x0,  0x8afe,  0x0,  0x8b01,  0x0,  0x8b39,  0x0,  0x8b58,  0x0,  0x8b80,  0x0,  0x8b8a,  0x0,  0x8c37,  0x0,  0x8c46,  0x0,  0x8c48,  0x0,  0x8c55,  0x0,  0x8c78,  0x0,  0x8c9d,  0x0,  0x8ca1,  0x0,  0x8ca9,  0x0,  0x8cab,  0x0,  0x8cc1,  0x0,  0x8cc2,  0x0,  0x8cc7,  0x0,  0x8cc8,  0x0,  0x8cd3,  0x0,  0x8d08,  0x0,  0x8d1b,  0x0,  0x8d64,  0x0,  0x8d70,  0x0,  0x8d77,  0x0,  0x8db3,  0x0,  0x8dbc,  0x0,  0x8dcb,  0x0,  0x8def,  0x0,  0x8df0,  0x0,  0x8eab,  0x0,  0x8eca,  0x0,  0x8ed4,  0x0,  0x8f26,  0x0,  0x8f2a,  0x0,  0x8f38,  0x0,  0x8f3b,  0x0,  0x8f62,  0x0,  0x8f9b,  0x0,  0x8f9e,  0x0,  0x8fb0,  0x0,  0x8fb5,  0x0,  0x8fb6,  0x0,  0x9023,  0x0,  0x9038,  0x0,  0x904a,  0x0,  0x9069,  0x0,  0x9072,  0x0,  0x907c,  0x0,  0x908f,  0x0,  0x9091,  0x0,  0x9094,  0x0,  0x90ce,  0x0,  0x90de,  0x0,  0x90f1,  0x0,  0x90fd,  0x0,  0x9111,  0x0,  0x911b,  0x0,  0x9149,  0x0,  0x916a,  0x0,  0x9199,  0x0,  0x91b4,  0x0,  0x91c6,  0x0,  0x91cc,  0x0,  0x91cf,  0x0,  0x91d1,  0x0,  0x9234,  0x0,  0x9238,  0x0,  0x9276,  0x0,  0x927c,  0x0,  0x92d7,  0x0,  0x92d8,  0x0,  0x9304,  0x0,  0x934a,  0x0,  0x93f9,  0x0,  0x9415,  0x0,  0x9577,  0x0,  0x9580,  0x0,  0x958b,  0x0,  0x95ad,  0x0,  0x95b7,  0x0,  0x961c,  0x0,  0x962e,  0x0,  0x964b,  0x0,  0x964d,  0x0,  0x9675,  0x0,  0x9678,  0x0,  0x967c,  0x0,  0x9686,  0x0,  0x96a3,  0x0,  0x96b6,  0x0,  0x96b7,  0x0,  0x96b8,  0x0,  0x96b9,  0x0,  0x96c3,  0x0,  0x96e2,  0x0,  0x96e3,  0x0,  0x96e8,  0x0,  0x96f6,  0x0,  0x96f7,  0x0,  0x9723,  0x0,  0x9732,  0x0,  0x9748,  0x0,  0x9751,  0x0,  0x9756,  0x0,  0x975e,  0x0,  0x9762,  0x0,  0x9769,  0x0,  0x97cb,  0x0,  0x97db,  0x0,  0x97e0,  0x0,  0x97ed,  0x0,  0x97f3,  0x0,  0x97ff,  0x0,  0x9801,  0x0,  0x9805,  0x0,  0x980b,  0x0,  0x9818,  0x0,  0x9829,  0x0,  0x983b,  0x0,  0x985e,  0x0,  0x98a8,  0x0,  0x98db,  0x0,  0x98df,  0x0,  0x98e2,  0x0,  0x98ef,  0x0,  0x98fc,  0x0,  0x9928,  0x0,  0x9929,  0x0,  0x9996,  0x0,  0x9999,  0x0,  0x99a7,  0x0,  0x99ac,  0x0,  0x99c2,  0x0,  0x99f1,  0x0,  0x99fe,  0x0,  0x9a6a,  0x0,  0x9aa8,  0x0,  0x9ad8,  0x0,  0x9adf,  0x0,  0x9b12,  0x0,  0x9b25,  0x0,  0x9b2f,  0x0,  0x9b32,  0x0,  0x9b3c,  0x0,  0x9b5a,  0x0,  0x9b6f,  0x0,  0x9c40,  0x0,  0x9c57,  0x0,  0x9ce5,  0x0,  0x9cfd,  0x0,  0x9d67,  0x0,  0x9db4,  0x0,  0x9dfa,  0x0,  0x9e1e,  0x0,  0x9e75,  0x0,  0x9e7f,  0x0,  0x9e97,  0x0,  0x9e9f,  0x0,  0x9ea5,  0x0,  0x9ebb,  0x0,  0x9ec3,  0x0,  0x9ecd,  0x0,  0x9ece,  0x0,  0x9ed1,  0x0,  0x9ef9,  0x0,  0x9efd,  0x0,  0x9efe,  0x0,  0x9f05,  0x0,  0x9f0e,  0x0,  0x9f0f,  0x0,  0x9f13,  0x0,  0x9f16,  0x0,  0x9f20,  0x0,  0x9f3b,  0x0,  0x9f43,  0x0,  0x9f4a,  0x0,  0x9f52,  0x0,  0x9f8d,  0x0,  0x9f8e,  0x0,  0x9f9c,  0x0,  0x9f9f,  0x0,  0x9fa0,  0x0,  0xa76f,  0x0,  0x11099,  0x110ba,  0x0,  0x1109b,  0x110ba,  0x0,  0x110a5,  0x110ba,  0x0,  0x11131,  0x11127,  0x0,  0x11132,  0x11127,  0x0,  0x1d157,  0x1d165,  0x0,  0x1d158,  0x1d165,  0x0,  0x1d158,  0x1d165,  0x1d16e,  0x0,  0x1d158,  0x1d165,  0x1d16f,  0x0,  0x1d158,  0x1d165,  0x1d170,  0x0,  0x1d158,  0x1d165,  0x1d171,  0x0,  0x1d158,  0x1d165,  0x1d172,  0x0,  0x1d1b9,  0x1d165,  0x0,  0x1d1b9,  0x1d165,  0x1d16e,  0x0,  0x1d1b9,  0x1d165,  0x1d16f,  0x0,  0x1d1ba,  0x1d165,  0x0,  0x1d1ba,  0x1d165,  0x1d16e,  0x0,  0x1d1ba,  0x1d165,  0x1d16f,  0x0,  0x20122,  0x0,  0x2051c,  0x0,  0x20525,  0x0,  0x2054b,  0x0,  0x2063a,  0x0,  0x20804,  0x0,  0x208de,  0x0,  0x20a2c,  0x0,  0x20b63,  0x0,  0x214e4,  0x0,  0x216a8,  0x0,  0x216ea,  0x0,  0x219c8,  0x0,  0x21b18,  0x0,  0x21d0b,  0x0,  0x21de4,  0x0,  0x21de6,  0x0,  0x22183,  0x0,  0x2219f,  0x0,  0x22331,  0x0,  0x226d4,  0x0,  0x22844,  0x0,  0x2284a,  0x0,  0x22b0c,  0x0,  0x22bf1,  0x0,  0x2300a,  0x0,  0x232b8,  0x0,  0x2335f,  0x0,  0x23393,  0x0,  0x2339c,  0x0,  0x233c3,  0x0,  0x233d5,  0x0,  0x2346d,  0x0,  0x236a3,  0x0,  0x238a7,  0x0,  0x23a8d,  0x0,  0x23afa,  0x0,  0x23cbc,  0x0,  0x23d1e,  0x0,  0x23ed1,  0x0,  0x23f5e,  0x0,  0x23f8e,  0x0,  0x24263,  0x0,  0x242ee,  0x0,  0x243ab,  0x0,  0x24608,  0x0,  0x24735,  0x0,  0x24814,  0x0,  0x24c36,  0x0,  0x24c92,  0x0,  0x24fa1,  0x0,  0x24fb8,  0x0,  0x25044,  0x0,  0x250f2,  0x0,  0x250f3,  0x0,  0x25119,  0x0,  0x25133,  0x0,  0x25249,  0x0,  0x2541d,  0x0,  0x25626,  0x0,  0x2569a,  0x0,  0x256c5,  0x0,  0x2597c,  0x0,  0x25aa7,  0x0,  0x25bab,  0x0,  0x25c80,  0x0,  0x25cd0,  0x0,  0x25f86,  0x0,  0x261da,  0x0,  0x26228,  0x0,  0x26247,  0x0,  0x262d9,  0x0,  0x2633e,  0x0,  0x264da,  0x0,  0x26523,  0x0,  0x265a8,  0x0,  0x267a7,  0x0,  0x267b5,  0x0,  0x26b3c,  0x0,  0x26c36,  0x0,  0x26cd5,  0x0,  0x26d6b,  0x0,  0x26f2c,  0x0,  0x26fb1,  0x0,  0x270d2,  0x0,  0x273ca,  0x0,  0x27667,  0x0,  0x278ae,  0x0,  0x27966,  0x0,  0x27ca8,  0x0,  0x27ed3,  0x0,  0x27f2f,  0x0,  0x285d2,  0x0,  0x285ed,  0x0,  0x2872e,  0x0,  0x28bfa,  0x0,  0x28d77,  0x0,  0x29145,  0x0,  0x291df,  0x0,  0x2921a,  0x0,  0x2940a,  0x0,  0x29496,  0x0,  0x295b6,  0x0,  0x29b30,  0x0,  0x2a0ce,  0x0,  0x2a105,  0x0,  0x2a20e,  0x0,  0x2a291,  0x0,  0x2a392,  0x0,  0x2a600,  0x0]; return t; }
+}
+
+}
+
diff --git a/std/internal/unicode_grapheme.d b/std/internal/unicode_grapheme.d
new file mode 100644
index 000000000..ffc5c061d
--- /dev/null
+++ b/std/internal/unicode_grapheme.d
@@ -0,0 +1,28 @@
+module std.internal.unicode_grapheme;
+import std.internal.unicode_tables;
+
+static if(size_t.sizeof == 8) {
+//832 bytes
+enum hangulLVTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x20,  0x40], [ 0x100,  0x80,  0xa00], [ 0x2010000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x4000300020001,  0x1000700060005,  0x5000400030002,  0x2000100070006,  0x6000500040003,  0x3000200010007,  0x7000600050004,  0x4000300020001,  0x1000700060005,  0x5000400030002,  0x8000100070006,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x100000010000001,  0x1000000100000,  0x10000001000,  0x1000000100000010,  0x10000001000000,  0x100000010000,  0x1000000100,  0x100000010000001,  0x1000000100000,  0x10000001000,  0x1000000100000010,  0x10000001000000,  0x100000010000,  0x1000000100,  0x100000010000001,  0x1000000100000,  0x10000001000,  0x1000000100000010,  0x10000001000000,  0x100000010000,  0x1000000100,  0x100000010000001,  0x1000000100000,  0x10000001000,  0x1000000100000010,  0x10000001000000,  0x100000010000,  0x1000000100,  0x10000001000000,  0x100000010000,  0x100,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//832 bytes
+enum hangulLVTTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x20,  0x40], [ 0x100,  0x80,  0xa00], [ 0x2010000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x4000300020001,  0x1000700060005,  0x5000400030002,  0x2000100070006,  0x6000500040003,  0x3000200010007,  0x7000600050004,  0x4000300020001,  0x1000700060005,  0x5000400030002,  0x8000100070006,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xfeffffffeffffffe,  0xfffeffffffefffff,  0xfffffeffffffefff,  0xeffffffeffffffef,  0xffeffffffeffffff,  0xffffeffffffeffff,  0xffffffeffffffeff,  0xfeffffffeffffffe,  0xfffeffffffefffff,  0xfffffeffffffefff,  0xeffffffeffffffef,  0xffeffffffeffffff,  0xffffeffffffeffff,  0xffffffeffffffeff,  0xfeffffffeffffffe,  0xfffeffffffefffff,  0xfffffeffffffefff,  0xeffffffeffffffef,  0xffeffffffeffffff,  0xffffeffffffeffff,  0xffffffeffffffeff,  0xfeffffffeffffffe,  0xfffeffffffefffff,  0xfffffeffffffefff,  0xeffffffeffffffef,  0xffeffffffeffffff,  0xffffeffffffeffff,  0xffffffeffffffeff,  0xffeffffffeffffff,  0xffffeffffffeffff,  0xffffffeff,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//1536 bytes
+enum mcTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x20,  0x60], [ 0x100,  0x100,  0x1800], [ 0x202030202020100,  0x206020205020204,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3000200010000,  0x6000000050004,  0x7,  0x8000000000000,  0xb000a00090000,  0xc,  0x0,  0x0,  0x0,  0x0,  0xd,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x110010000f000e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x130012,  0x1400000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x15000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x160000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc800000000000008,  0xde01,  0xc00000000000000c,  0x801981,  0xc000000000000008,  0x1,  0xc000000000000008,  0x1a01,  0x400000000000000c,  0x801981,  0xc000000000000000,  0x801dc6,  0xe,  0x1e,  0x400000000000000c,  0x600d9f,  0xc00000000000000c,  0x801dc1,  0xc,  0xc0000ff038000,  0xc000000000000000,  0x8000000000000000,  0x0,  0x0,  0x1902180000000000,  0x3f9c00c00000,  0x1c009f98,  0x0,  0x0,  0x0,  0xc040000000000000,  0x1bf,  0x1fb0e7800000000,  0x0,  0xffff000000000000,  0x301,  0x6000000,  0x7e01a00a00000,  0x0,  0x0,  0xe820000000000010,  0x1b,  0x34c200000004,  0xc5c8000000000,  0x300ff000000000,  0x0,  0x0,  0xc000200000000,  0xc00000000000,  0x0,  0x0,  0x0,  0x9800000000,  0x0,  0xfff0000000000003,  0xf,  0x0,  0xc0000,  0xec30000000000008,  0x1,  0x19800000000000,  0x800000000002000,  0x0,  0x20c80000000000,  0x0,  0x0,  0x0,  0x16d800000000,  0x5,  0x0,  0x187000000000004,  0x0,  0x100000000000,  0x0,  0x8038000000000004,  0x1,  0x0,  0x0,  0x40d00000000000,  0x0,  0x0,  0x7ffffffffffe0000,  0x0,  0x0,  0x0,  0x7e06000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//2336 bytes
+enum graphemeExtendTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x20,  0x70], [ 0x100,  0x140,  0x2d00], [ 0x402030202020100,  0x207020206020205,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020208,  0x202020202020202,  0x202020202020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1000000000000,  0x5000400030002,  0x9000800070006,  0xd000c000b000a,  0xf00000000000e,  0x10000000000000,  0x14001300120011,  0x160015,  0x17,  0x0,  0x0,  0x190018,  0x1a,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1b00000000,  0x1f001e001d001c,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x20000000000000,  0x22002100000000,  0x230000,  0x0,  0x2400000000,  0x0,  0x260025,  0x2700000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x28000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2a00290000,  0x0,  0x0,  0x0,  0x2b0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffffffffffff,  0xffffffffffff,  0x0,  0x0,  0x0,  0x0,  0x3f8,  0x0,  0x0,  0x0,  0xbffffffffffe0000,  0xb6,  0x7ff0000,  0x10000fffff800,  0x0,  0x3d9f9fc00000,  0xffff000000020000,  0x7ff,  0x1ffc000000000,  0xff80000000000,  0x3eeffbc00000,  0xe000000,  0x0,  0x7ffffff000000000,  0x1400000000000007,  0xc00fe21fe,  0x5000000000000002,  0xc0080201e,  0x1000000000000006,  0x23000000023986,  0x1000000000000006,  0xc000021be,  0xd000000000000002,  0xc00c0201e,  0x4000000000000004,  0x802001,  0xc000000000000000,  0xc00603dc1,  0x9000000000000000,  0xc00603044,  0x4000000000000000,  0xc0080201e,  0x0,  0x805c8400,  0x7f2000000000000,  0x7f80,  0x1bf2000000000000,  0x3f00,  0x2a0000003000000,  0x7ffe000000000000,  0x1ffffffffeffe0df,  0x40,  0x66fde00000000000,  0x1e0001c3000000,  0x20002064,  0x0,  0x0,  0xe0000000,  0x0,  0x0,  0x1c0000001c0000,  0xc0000000c0000,  0x3fb0000000000000,  0x200ffe40,  0x3800,  0x0,  0x20000000000,  0x0,  0xe04018700000000,  0x0,  0x0,  0x0,  0x9800000,  0x9ff81fe57f400000,  0x0,  0x0,  0x17d000000000000f,  0xff80000000004,  0xb3c00000003,  0x3a34000000000,  0xcff00000000000,  0x0,  0x0,  0x1021fdfff70000,  0x0,  0x0,  0x0,  0xf000007fffffffff,  0x3000,  0x0,  0x0,  0x1ffffffff0000,  0x0,  0x0,  0x0,  0x3800000000000,  0x0,  0x8000000000000000,  0x0,  0xffffffff00000000,  0xfc0000000000,  0x0,  0x6000000,  0x0,  0x0,  0x3ff7800000000000,  0x80000000,  0x3000000000000,  0x6000000844,  0x0,  0x0,  0x3ffff00000010,  0x3fc000000000,  0x3ff80,  0x13c8000000000007,  0x0,  0x667e0000000000,  0x1008,  0xc19d000000000000,  0x40300000000002,  0x0,  0x0,  0x0,  0x212000000000,  0x40000000,  0x0,  0x0,  0x0,  0x7f0000ffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc0000000,  0x0,  0x0,  0x0,  0x0,  0x2000000000000000,  0x870000000000f06e,  0x0,  0x0,  0x0,  0xff00000000000002,  0x7f,  0x678000000000003,  0x0,  0x1fef8000000007,  0x0,  0x7fc0000000000003,  0x0,  0x0,  0x0,  0xbf280000000000,  0x0,  0x0,  0x0,  0x78000,  0x0,  0x0,  0xf807c3a000000000,  0x3c0000000fe7,  0x0,  0x0,  0x1c,  0x0,  0x0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffff,  0x0,  0x0,  0x0,  0x0]);
+
+}
+
+
+static if(size_t.sizeof == 4) {
+//832 bytes
+enum hangulLVTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x40,  0x80], [ 0x100,  0x80,  0xa00], [ 0x0,  0x20100,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x20001,  0x40003,  0x60005,  0x10007,  0x30002,  0x50004,  0x70006,  0x20001,  0x40003,  0x60005,  0x10007,  0x30002,  0x50004,  0x70006,  0x20001,  0x40003,  0x60005,  0x10007,  0x30002,  0x50004,  0x70006,  0x80001,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000001,  0x1000000,  0x100000,  0x10000,  0x1000,  0x100,  0x10,  0x10000001,  0x1000000,  0x100000,  0x10000,  0x1000,  0x100,  0x10,  0x10000001,  0x1000000,  0x100000,  0x10000,  0x1000,  0x100,  0x10,  0x10000001,  0x1000000,  0x100000,  0x10000,  0x1000,  0x100,  0x10,  0x10000001,  0x1000000,  0x100000,  0x10000,  0x1000,  0x100,  0x10,  0x10000001,  0x1000000,  0x100000,  0x10000,  0x1000,  0x100,  0x10,  0x10000001,  0x1000000,  0x100000,  0x10000,  0x1000,  0x100,  0x10,  0x10000001,  0x1000000,  0x100000,  0x10000,  0x1000,  0x100,  0x10,  0x1000000,  0x100000,  0x10000,  0x1000,  0x100,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//832 bytes
+enum hangulLVTTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x40,  0x80], [ 0x100,  0x80,  0xa00], [ 0x0,  0x20100,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x20001,  0x40003,  0x60005,  0x10007,  0x30002,  0x50004,  0x70006,  0x20001,  0x40003,  0x60005,  0x10007,  0x30002,  0x50004,  0x70006,  0x20001,  0x40003,  0x60005,  0x10007,  0x30002,  0x50004,  0x70006,  0x80001,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xeffffffe,  0xfeffffff,  0xffefffff,  0xfffeffff,  0xffffefff,  0xfffffeff,  0xffffffef,  0xeffffffe,  0xfeffffff,  0xffefffff,  0xfffeffff,  0xffffefff,  0xfffffeff,  0xffffffef,  0xeffffffe,  0xfeffffff,  0xffefffff,  0xfffeffff,  0xffffefff,  0xfffffeff,  0xffffffef,  0xeffffffe,  0xfeffffff,  0xffefffff,  0xfffeffff,  0xffffefff,  0xfffffeff,  0xffffffef,  0xeffffffe,  0xfeffffff,  0xffefffff,  0xfffeffff,  0xffffefff,  0xfffffeff,  0xffffffef,  0xeffffffe,  0xfeffffff,  0xffefffff,  0xfffeffff,  0xffffefff,  0xfffffeff,  0xffffffef,  0xeffffffe,  0xfeffffff,  0xffefffff,  0xfffeffff,  0xffffefff,  0xfffffeff,  0xffffffef,  0xeffffffe,  0xfeffffff,  0xffefffff,  0xfffeffff,  0xffffefff,  0xfffffeff,  0xffffffef,  0xfeffffff,  0xffefffff,  0xfffeffff,  0xffffefff,  0xfffffeff,  0xf,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//1536 bytes
+enum mcTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x40,  0xc0], [ 0x100,  0x100,  0x1800], [ 0x2020100,  0x2020302,  0x5020204,  0x2060202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000,  0x30002,  0x50004,  0x60000,  0x7,  0x0,  0x0,  0x80000,  0x90000,  0xb000a,  0xc,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xd,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xf000e,  0x110010,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x130012,  0x0,  0x0,  0x14,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x150000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x160000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x8,  0xc8000000,  0xde01,  0x0,  0xc,  0xc0000000,  0x801981,  0x0,  0x8,  0xc0000000,  0x1,  0x0,  0x8,  0xc0000000,  0x1a01,  0x0,  0xc,  0x40000000,  0x801981,  0x0,  0x0,  0xc0000000,  0x801dc6,  0x0,  0xe,  0x0,  0x1e,  0x0,  0xc,  0x40000000,  0x600d9f,  0x0,  0xc,  0xc0000000,  0x801dc1,  0x0,  0xc,  0x0,  0xff038000,  0xc0000,  0x0,  0xc0000000,  0x0,  0x80000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x19021800,  0xc00000,  0x3f9c,  0x1c009f98,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc0400000,  0x1bf,  0x0,  0x0,  0x1fb0e78,  0x0,  0x0,  0x0,  0xffff0000,  0x301,  0x0,  0x6000000,  0x0,  0xa00000,  0x7e01a,  0x0,  0x0,  0x0,  0x0,  0x10,  0xe8200000,  0x1b,  0x0,  0x4,  0x34c2,  0x0,  0xc5c80,  0x0,  0x300ff0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc0002,  0x0,  0xc000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x98,  0x0,  0x0,  0x3,  0xfff00000,  0xf,  0x0,  0x0,  0x0,  0xc0000,  0x0,  0x8,  0xec300000,  0x1,  0x0,  0x0,  0x198000,  0x2000,  0x8000000,  0x0,  0x0,  0x0,  0x20c800,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x16d8,  0x5,  0x0,  0x0,  0x0,  0x4,  0x1870000,  0x0,  0x0,  0x0,  0x1000,  0x0,  0x0,  0x4,  0x80380000,  0x1,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x40d000,  0x0,  0x0,  0x0,  0x0,  0xfffe0000,  0x7fffffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7e060,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//2336 bytes
+enum graphemeExtendTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x40,  0xe0], [ 0x100,  0x140,  0x2d00], [ 0x2020100,  0x4020302,  0x6020205,  0x2070202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020208,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000,  0x30002,  0x50004,  0x70006,  0x90008,  0xb000a,  0xd000c,  0xe,  0xf0000,  0x0,  0x100000,  0x120011,  0x140013,  0x160015,  0x0,  0x17,  0x0,  0x0,  0x0,  0x0,  0x0,  0x190018,  0x0,  0x1a,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1b,  0x1d001c,  0x1f001e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x200000,  0x0,  0x220021,  0x230000,  0x0,  0x0,  0x0,  0x0,  0x24,  0x0,  0x0,  0x260025,  0x0,  0x0,  0x27,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x280000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x290000,  0x2a,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2b0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3f8,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xfffe0000,  0xbfffffff,  0xb6,  0x0,  0x7ff0000,  0x0,  0xfffff800,  0x10000,  0x0,  0x0,  0x9fc00000,  0x3d9f,  0x20000,  0xffff0000,  0x7ff,  0x0,  0x0,  0x1ffc0,  0x0,  0xff800,  0xfbc00000,  0x3eef,  0xe000000,  0x0,  0x0,  0x0,  0x0,  0x7ffffff0,  0x7,  0x14000000,  0xfe21fe,  0xc,  0x2,  0x50000000,  0x80201e,  0xc,  0x6,  0x10000000,  0x23986,  0x230000,  0x6,  0x10000000,  0x21be,  0xc,  0x2,  0xd0000000,  0xc0201e,  0xc,  0x4,  0x40000000,  0x802001,  0x0,  0x0,  0xc0000000,  0x603dc1,  0xc,  0x0,  0x90000000,  0x603044,  0xc,  0x0,  0x40000000,  0x80201e,  0xc,  0x0,  0x0,  0x805c8400,  0x0,  0x0,  0x7f20000,  0x7f80,  0x0,  0x0,  0x1bf20000,  0x3f00,  0x0,  0x3000000,  0x2a00000,  0x0,  0x7ffe0000,  0xfeffe0df,  0x1fffffff,  0x40,  0x0,  0x0,  0x66fde000,  0xc3000000,  0x1e0001,  0x20002064,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe0000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1c0000,  0x1c0000,  0xc0000,  0xc0000,  0x0,  0x3fb00000,  0x200ffe40,  0x0,  0x3800,  0x0,  0x0,  0x0,  0x0,  0x200,  0x0,  0x0,  0x0,  0xe040187,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x9800000,  0x0,  0x7f400000,  0x9ff81fe5,  0x0,  0x0,  0x0,  0x0,  0xf,  0x17d00000,  0x4,  0xff800,  0x3,  0xb3c,  0x0,  0x3a340,  0x0,  0xcff000,  0x0,  0x0,  0x0,  0x0,  0xfff70000,  0x1021fd,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xf000007f,  0x3000,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffff0000,  0x1ffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x38000,  0x0,  0x0,  0x0,  0x80000000,  0x0,  0x0,  0x0,  0xffffffff,  0x0,  0xfc00,  0x0,  0x0,  0x6000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3ff78000,  0x80000000,  0x0,  0x0,  0x30000,  0x844,  0x60,  0x0,  0x0,  0x0,  0x0,  0x10,  0x3ffff,  0x0,  0x3fc0,  0x3ff80,  0x0,  0x7,  0x13c80000,  0x0,  0x0,  0x0,  0x667e00,  0x1008,  0x0,  0x0,  0xc19d0000,  0x2,  0x403000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2120,  0x40000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffff,  0x7f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc0000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x20000000,  0xf06e,  0x87000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2,  0xff000000,  0x7f,  0x0,  0x3,  0x6780000,  0x0,  0x0,  0x7,  0x1fef80,  0x0,  0x0,  0x3,  0x7fc00000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xbf2800,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x78000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xf807c3a0,  0xfe7,  0x3c00,  0x0,  0x0,  0x0,  0x0,  0x1c,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+
+}
+
diff --git a/std/internal/unicode_norm.d b/std/internal/unicode_norm.d
new file mode 100644
index 000000000..7d142d8b6
--- /dev/null
+++ b/std/internal/unicode_norm.d
@@ -0,0 +1,28 @@
+module std.internal.unicode_norm;
+import std.internal.unicode_tables;
+
+static if(size_t.sizeof == 8) {
+//1600 bytes
+enum nfcQCTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x20,  0x60], [ 0x100,  0x100,  0x1a00], [ 0x302020202020100,  0x205020202020204,  0x602020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1000000000000,  0x200000000,  0x5000400030000,  0x8000000070006,  0xa0009,  0x0,  0xb000000000000,  0xc000000000000,  0xf0000000e000d,  0x0,  0x1000000000,  0x0,  0x11,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x14001300120000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x160015,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x170000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1800120012,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10361f8081a9fdf,  0x401000000000003f,  0x80,  0x0,  0x0,  0x380000,  0x0,  0x0,  0x1000000000000000,  0xff000000,  0x4000000000000000,  0xb0800000,  0x48000000000000,  0x4e000000,  0x0,  0x0,  0x4000000000000000,  0x30c00000,  0x4000000000000000,  0x800000,  0x0,  0x400000,  0x0,  0x600004,  0x4000000000000000,  0x800000,  0x0,  0x80008400,  0x0,  0x168020010842008,  0x200108420080002,  0x0,  0x400000000000,  0x0,  0x0,  0x0,  0x0,  0x3ffffe00000000,  0xffffff0000000000,  0x7,  0x20000000000000,  0x0,  0x0,  0x0,  0x0,  0x2aaa000000000000,  0x4800000000000000,  0x2a00c80808080a00,  0x3,  0x0,  0x0,  0x0,  0xc4000000000,  0x0,  0x0,  0x0,  0x60000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000000,  0x0,  0x0,  0x6000000,  0x0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xfffffc657fe53fff,  0xffff3fffffffffff,  0xffffffffffffffff,  0x3ffffff,  0x5f7ffc00a0000000,  0x7fdb,  0x0,  0x0,  0x0,  0x0,  0x400000000000000,  0x0,  0x8000000000,  0x0,  0x0,  0x0,  0x0,  0x1fc0000000,  0xf800000000000000,  0x1,  0x3fffffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//1920 bytes
+enum nfdQCTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x20,  0x70], [ 0x100,  0x140,  0x2000], [ 0x504030202020100,  0x207020202020206,  0x802020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3000200010000,  0x5000600050004,  0x9000800070005,  0xc0005000b000a,  0x500050005000d,  0x5000500050005,  0xe000500050005,  0x10000f00050005,  0x14001300120011,  0x5000500050005,  0x5001500050005,  0x5000500050005,  0x5000500050016,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x17001700170017,  0x17001700170017,  0x17001700170017,  0x17001700170017,  0x17001700170017,  0x17001700170017,  0x17001700170017,  0x17001700170017,  0x17001700170017,  0x17001700170017,  0x18001700170017,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x1a001900170005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x50005001c001b,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x50005001d0005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5001e00170017,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x5000500050005,  0x0,  0x0,  0x0,  0xbe7effbf3e7effbf,  0x7ef1ff3ffffcffff,  0x7fffff3ffff3f1f8,  0x1800300000000,  0xff31ffcfdfffe000,  0xfffc0cfffffff,  0x0,  0x0,  0x0,  0x0,  0x401000000000001b,  0x1fc000001d7e0,  0x187c00,  0x20000000200708b,  0xc00000708b0000,  0x0,  0x33ffcfcfccf0006,  0x0,  0x0,  0x0,  0x0,  0x7c00000000,  0x0,  0x0,  0x80005,  0x12020000000000,  0xff000000,  0x0,  0xb0001800,  0x48000000000000,  0x4e000000,  0x0,  0x0,  0x0,  0x30001900,  0x100000,  0x1c00,  0x0,  0x100,  0x0,  0xd81,  0x0,  0x1c00,  0x0,  0x74000000,  0x0,  0x168020010842008,  0x200108420080002,  0x0,  0x4000000000,  0x0,  0x0,  0x0,  0x2800000000045540,  0xb,  0x0,  0x0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff0bffffff,  0x3ffffffffffffff,  0xffffffff3f3fffff,  0x3fffffffaaff3f3f,  0x5fdfffffffffffff,  0x3fdcffffefcfffde,  0x3,  0x0,  0x0,  0x0,  0xc4000000000,  0x0,  0x40000c000000,  0xe000,  0x5000001210,  0x333e00500000292,  0xf00000000333,  0x3c0f00000000,  0x60000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000000,  0x0,  0x36db02a555555000,  0x5555500040100000,  0x4790000036db02a5,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xfffffffff,  0x0,  0xfffffc657fe53fff,  0xffff3fffffffffff,  0xffffffffffffffff,  0x3ffffff,  0x5f7ffc00a0000000,  0x7fdb,  0x0,  0x0,  0x0,  0x0,  0x80014000000,  0x0,  0xc00000000000,  0x0,  0x0,  0x0,  0x0,  0x1fc0000000,  0xf800000000000000,  0x1,  0x3fffffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//2560 bytes
+enum nfkcQCTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x20,  0x70], [ 0x100,  0x140,  0x3400], [ 0x402030202020100,  0x706020202020205,  0x802020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3000200010000,  0x4000600050004,  0x9000800070004,  0xd000c000b000a,  0x40004000f000e,  0x4000400040004,  0x10000400040004,  0x13001200110004,  0x17001600150014,  0x4000400040018,  0x4001900040004,  0x1d001c001b001a,  0x210020001f001e,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x22000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x24002300210004,  0x27002600250021,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400290028,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x40004002a0004,  0x2e002d002c002b,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4002f00040004,  0x4003100300004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4003200210021,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x4000400040004,  0x0,  0x0,  0x773c850100000000,  0x0,  0x800c000000000000,  0x8000000000000201,  0x0,  0xe000000001ff0,  0x0,  0x0,  0x1ff000000000000,  0x1f3f000000,  0x10361f8081a9fdf,  0x441000000000003f,  0xb0,  0x2370000007f0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x80,  0x0,  0x0,  0x1e0000000380000,  0x0,  0x0,  0x1000000000000000,  0xff000000,  0x4000000000000000,  0xb0800000,  0x48000000000000,  0x4e000000,  0x0,  0x0,  0x4000000000000000,  0x30c00000,  0x4000000000000000,  0x800000,  0x0,  0x400000,  0x0,  0x600004,  0x4000000000000000,  0x800000,  0x0,  0x80008400,  0x8000000000000,  0x0,  0x8000000000000,  0x30000000,  0x1000,  0x3e8020010842008,  0x200108420080002,  0x0,  0x400000000000,  0x0,  0x0,  0x1000000000000000,  0x0,  0x3ffffe00000000,  0xffffff0000000000,  0x7,  0x20000000000000,  0x0,  0x0,  0x0,  0xf7ff700000000000,  0x10007ffffffbfff,  0xfffffffff8000000,  0x0,  0x0,  0x0,  0xc000000,  0x0,  0x0,  0x2aaa000000000000,  0xe800000000000000,  0x6a00e808e808ea03,  0x50d88070008207ff,  0xfff3000080800380,  0x1001fff7fff,  0x0,  0xfbfbbd573e6ffeef,  0xffffffffffff03e1,  0x200,  0x0,  0x1b00000000000,  0x0,  0x0,  0x0,  0x60000000000,  0x0,  0x0,  0x0,  0x0,  0xffffffff00000000,  0xffffffffffffffff,  0x7ffffffffff,  0x1000,  0x70000000000000,  0x0,  0x10000000,  0x0,  0x3000000000000000,  0x0,  0x0,  0x0,  0x800000000000,  0x0,  0x0,  0x0,  0x0,  0x80000000,  0x8000000000000,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x3fffff,  0x740000000000001,  0x0,  0x9e000000,  0x8000000000000000,  0xfffe000000000000,  0xffffffffffffffff,  0xfffc7fff,  0x0,  0xffffffff7fffffff,  0x7fffffffffff00ff,  0xffffffffffffffff,  0x7fffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x0,  0x1000000000000,  0x0,  0x300000000000000,  0xfffffc657fe53fff,  0xffff3fffffffffff,  0xffffffffffffffff,  0x3ffffff,  0x5f7fffffa0f8007f,  0xffffffffffffffdb,  0x3ffffffffffff,  0xfffffffffff80000,  0x3fffffffffffffff,  0xffffffffffff0000,  0xfffffffffffcffff,  0x1fff0000000000ff,  0xffff000003ff0000,  0xffd70f7ffff7ff9f,  0xffffffffffffffff,  0x1fffffffffffffff,  0xfffffffffffffffe,  0xffffffffffffffff,  0x7fffffffffffffff,  0x7f7f1cfcfcfc,  0x0,  0x0,  0x400000000000000,  0x0,  0x8000000000,  0x0,  0x0,  0x0,  0x0,  0x1fc0000000,  0xf800000000000000,  0x1,  0xffffffffffffffff,  0xffffffffffdfffff,  0xebffde64dfffffff,  0xffffffffffffffef,  0x7bffffffdfdfe7bf,  0xfffffffffffdfc5f,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffff3fffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffcfff,  0xaf7fe96ffffffef,  0x5ef7f796aa96ea84,  0xffffbee0ffffbff,  0x0,  0xffff7fffffff07ff,  0xc000000ffff,  0x10000,  0x0,  0x7ffffffffff0007,  0x301ff,  0x0,  0x0,  0x3fffffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//2656 bytes
+enum nfkdQCTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x20,  0x78], [ 0x100,  0x160,  0x3500], [ 0x504030202020100,  0x807020202020206,  0x902020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3000200010000,  0x7000600050004,  0xa000900080007,  0xe000d000c000b,  0x700070007000f,  0x7000700070007,  0x10000700070007,  0x13001200110007,  0x17001600150014,  0x7000700070018,  0x7001900070007,  0x1d001c001b001a,  0x210020001f001e,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x22000700070007,  0x7000700070007,  0x21002100210021,  0x21002100210021,  0x21002100210021,  0x21002100210021,  0x21002100210021,  0x21002100210021,  0x21002100210021,  0x21002100210021,  0x21002100210021,  0x21002100210021,  0x23002100210021,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x25002400210007,  0x28002700260021,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x70007002a0029,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x70007002b0007,  0x2f002e002d002c,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7003000070007,  0x7003200310007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7003300210021,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x7000700070007,  0x0,  0x0,  0x773c850100000000,  0xbe7effbf3e7effbf,  0xfefdff3ffffcffff,  0xffffff3ffff3f3f9,  0x1800300000000,  0xff3fffcfdffffff0,  0xfffc0cfffffff,  0x0,  0x1ff000000000000,  0x1f3f000000,  0x0,  0x441000000000001b,  0x1fc000001d7f0,  0x2370000007f7c00,  0x20000000200708b,  0xc00000708b0000,  0x0,  0x33ffcfcfccf0006,  0x0,  0x0,  0x80,  0x0,  0x7c00000000,  0x1e0000000000000,  0x0,  0x80005,  0x0,  0x0,  0x0,  0x0,  0x12020000000000,  0xff000000,  0x0,  0xb0001800,  0x48000000000000,  0x4e000000,  0x0,  0x0,  0x0,  0x30001900,  0x100000,  0x1c00,  0x0,  0x100,  0x0,  0xd81,  0x0,  0x1c00,  0x0,  0x74000000,  0x8000000000000,  0x0,  0x8000000000000,  0x30000000,  0x1000,  0x3e8020010842008,  0x200108420080002,  0x0,  0x4000000000,  0x0,  0x0,  0x1000000000000000,  0x2800000000045540,  0xb,  0x0,  0x0,  0xf7ff700000000000,  0x10007ffffffbfff,  0xfffffffff8000000,  0x0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff0fffffff,  0x3ffffffffffffff,  0xffffffff3f3fffff,  0x3fffffffaaff3f3f,  0xffdfffffffffffff,  0x7fdcffffefcfffdf,  0x50d88070008207ff,  0xfff3000080800380,  0x1001fff7fff,  0x0,  0xfbfbbd573e6ffeef,  0xffffffffffff03e1,  0x40000c000200,  0xe000,  0x1b05000001210,  0x333e00500000292,  0xf00000000333,  0x3c0f00000000,  0x60000000000,  0x0,  0x0,  0x0,  0x0,  0xffffffff00000000,  0xffffffffffffffff,  0x7ffffffffff,  0x1000,  0x70000000000000,  0x0,  0x10000000,  0x0,  0x3000000000000000,  0x0,  0x0,  0x0,  0x800000000000,  0x0,  0x0,  0x0,  0x0,  0x80000000,  0x8000000000000,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x3fffff,  0x740000000000001,  0x36db02a555555000,  0x55555000d8100000,  0xc790000036db02a5,  0xfffe000000000000,  0xffffffffffffffff,  0xfffc7fff,  0x0,  0xffffffff7fffffff,  0x7fffffffffff00ff,  0xffffffffffffffff,  0x7fffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x0,  0x1000000000000,  0x0,  0x300000000000000,  0xffffffffffffffff,  0xffffffffffffffff,  0xfffffffff,  0x0,  0xfffffc657fe53fff,  0xffff3fffffffffff,  0xffffffffffffffff,  0x3ffffff,  0x5f7fffffa0f8007f,  0xffffffffffffffdb,  0x3ffffffffffff,  0xfffffffffff80000,  0x3fffffffffffffff,  0xffffffffffff0000,  0xfffffffffffcffff,  0x1fff0000000000ff,  0xffff000003ff0000,  0xffd70f7ffff7ff9f,  0xffffffffffffffff,  0x1fffffffffffffff,  0xfffffffffffffffe,  0xffffffffffffffff,  0x7fffffffffffffff,  0x7f7f1cfcfcfc,  0x0,  0x0,  0x80014000000,  0x0,  0xc00000000000,  0x0,  0x0,  0x0,  0x0,  0x1fc0000000,  0xf800000000000000,  0x1,  0xffffffffffffffff,  0xffffffffffdfffff,  0xebffde64dfffffff,  0xffffffffffffffef,  0x7bffffffdfdfe7bf,  0xfffffffffffdfc5f,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffff3fffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffcfff,  0xaf7fe96ffffffef,  0x5ef7f796aa96ea84,  0xffffbee0ffffbff,  0x0,  0xffff7fffffff07ff,  0xc000000ffff,  0x10000,  0x0,  0x7ffffffffff0007,  0x301ff,  0x0,  0x0,  0x3fffffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+
+}
+
+
+static if(size_t.sizeof == 4) {
+//1600 bytes
+enum nfcQCTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x40,  0xc0], [ 0x100,  0x100,  0x1a00], [ 0x2020100,  0x3020202,  0x2020204,  0x2050202,  0x2020202,  0x6020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000,  0x0,  0x2,  0x30000,  0x50004,  0x70006,  0x80000,  0xa0009,  0x0,  0x0,  0x0,  0x0,  0xb0000,  0x0,  0xc0000,  0xe000d,  0xf0000,  0x0,  0x0,  0x0,  0x10,  0x0,  0x0,  0x11,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x120000,  0x140013,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x160015,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x170000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x120012,  0x18,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x81a9fdf,  0x10361f8,  0x3f,  0x40100000,  0x80,  0x0,  0x0,  0x0,  0x0,  0x0,  0x380000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000000,  0xff000000,  0x0,  0x0,  0x40000000,  0xb0800000,  0x0,  0x0,  0x480000,  0x4e000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x40000000,  0x30c00000,  0x0,  0x0,  0x40000000,  0x800000,  0x0,  0x0,  0x0,  0x400000,  0x0,  0x0,  0x0,  0x600004,  0x0,  0x0,  0x40000000,  0x800000,  0x0,  0x0,  0x0,  0x80008400,  0x0,  0x0,  0x0,  0x10842008,  0x1680200,  0x20080002,  0x2001084,  0x0,  0x0,  0x0,  0x4000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3ffffe,  0x0,  0xffffff00,  0x7,  0x0,  0x0,  0x200000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2aaa0000,  0x0,  0x48000000,  0x8080a00,  0x2a00c808,  0x3,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc40,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x600,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x6000000,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x7fe53fff,  0xfffffc65,  0xffffffff,  0xffff3fff,  0xffffffff,  0xffffffff,  0x3ffffff,  0x0,  0xa0000000,  0x5f7ffc00,  0x7fdb,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x4000000,  0x0,  0x0,  0x0,  0x80,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc0000000,  0x1f,  0x0,  0xf8000000,  0x1,  0x0,  0x3fffffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//1920 bytes
+enum nfdQCTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x40,  0xe0], [ 0x100,  0x140,  0x2000], [ 0x2020100,  0x5040302,  0x2020206,  0x2070202,  0x2020202,  0x8020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000,  0x30002,  0x50004,  0x50006,  0x70005,  0x90008,  0xb000a,  0xc0005,  0x5000d,  0x50005,  0x50005,  0x50005,  0x50005,  0xe0005,  0x50005,  0x10000f,  0x120011,  0x140013,  0x50005,  0x50005,  0x50005,  0x50015,  0x50005,  0x50005,  0x50016,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x170017,  0x170017,  0x170017,  0x170017,  0x170017,  0x170017,  0x170017,  0x170017,  0x170017,  0x170017,  0x170017,  0x170017,  0x170017,  0x170017,  0x170017,  0x170017,  0x170017,  0x170017,  0x170017,  0x170017,  0x170017,  0x180017,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x170005,  0x1a0019,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x1c001b,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x1d0005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x170017,  0x5001e,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x50005,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3e7effbf,  0xbe7effbf,  0xfffcffff,  0x7ef1ff3f,  0xfff3f1f8,  0x7fffff3f,  0x0,  0x18003,  0xdfffe000,  0xff31ffcf,  0xcfffffff,  0xfffc0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1b,  0x40100000,  0x1d7e0,  0x1fc00,  0x187c00,  0x0,  0x200708b,  0x2000000,  0x708b0000,  0xc00000,  0x0,  0x0,  0xfccf0006,  0x33ffcfc,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7c,  0x0,  0x0,  0x0,  0x0,  0x80005,  0x0,  0x0,  0x120200,  0xff000000,  0x0,  0x0,  0x0,  0xb0001800,  0x0,  0x0,  0x480000,  0x4e000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x30001900,  0x0,  0x100000,  0x0,  0x1c00,  0x0,  0x0,  0x0,  0x100,  0x0,  0x0,  0x0,  0xd81,  0x0,  0x0,  0x0,  0x1c00,  0x0,  0x0,  0x0,  0x74000000,  0x0,  0x0,  0x0,  0x10842008,  0x1680200,  0x20080002,  0x2001084,  0x0,  0x0,  0x0,  0x40,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x45540,  0x28000000,  0xb,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xbffffff,  0xffffffff,  0xffffffff,  0x3ffffff,  0x3f3fffff,  0xffffffff,  0xaaff3f3f,  0x3fffffff,  0xffffffff,  0x5fdfffff,  0xefcfffde,  0x3fdcffff,  0x3,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc40,  0x0,  0x0,  0xc000000,  0x4000,  0xe000,  0x0,  0x1210,  0x50,  0x292,  0x333e005,  0x333,  0xf000,  0x0,  0x3c0f,  0x0,  0x600,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000000,  0x0,  0x0,  0x0,  0x55555000,  0x36db02a5,  0x40100000,  0x55555000,  0x36db02a5,  0x47900000,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xf,  0x0,  0x0,  0x7fe53fff,  0xfffffc65,  0xffffffff,  0xffff3fff,  0xffffffff,  0xffffffff,  0x3ffffff,  0x0,  0xa0000000,  0x5f7ffc00,  0x7fdb,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x14000000,  0x800,  0x0,  0x0,  0x0,  0xc000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc0000000,  0x1f,  0x0,  0xf8000000,  0x1,  0x0,  0x3fffffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//2560 bytes
+enum nfkcQCTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x40,  0xe0], [ 0x100,  0x140,  0x3400], [ 0x2020100,  0x4020302,  0x2020205,  0x7060202,  0x2020202,  0x8020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000,  0x30002,  0x50004,  0x40006,  0x70004,  0x90008,  0xb000a,  0xd000c,  0xf000e,  0x40004,  0x40004,  0x40004,  0x40004,  0x100004,  0x110004,  0x130012,  0x150014,  0x170016,  0x40018,  0x40004,  0x40004,  0x40019,  0x1b001a,  0x1d001c,  0x1f001e,  0x210020,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x220004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x210004,  0x240023,  0x250021,  0x270026,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x290028,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x2a0004,  0x40004,  0x2c002b,  0x2e002d,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x4002f,  0x300004,  0x40031,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x210021,  0x40032,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x40004,  0x0,  0x0,  0x0,  0x0,  0x0,  0x773c8501,  0x0,  0x0,  0x0,  0x800c0000,  0x201,  0x80000000,  0x0,  0x0,  0x1ff0,  0xe0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1ff0000,  0x3f000000,  0x1f,  0x81a9fdf,  0x10361f8,  0x3f,  0x44100000,  0xb0,  0x0,  0x7f0000,  0x2370000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x80,  0x0,  0x0,  0x0,  0x0,  0x0,  0x380000,  0x1e00000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000000,  0xff000000,  0x0,  0x0,  0x40000000,  0xb0800000,  0x0,  0x0,  0x480000,  0x4e000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x40000000,  0x30c00000,  0x0,  0x0,  0x40000000,  0x800000,  0x0,  0x0,  0x0,  0x400000,  0x0,  0x0,  0x0,  0x600004,  0x0,  0x0,  0x40000000,  0x800000,  0x0,  0x0,  0x0,  0x80008400,  0x0,  0x0,  0x80000,  0x0,  0x0,  0x0,  0x80000,  0x30000000,  0x0,  0x1000,  0x0,  0x10842008,  0x3e80200,  0x20080002,  0x2001084,  0x0,  0x0,  0x0,  0x4000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000000,  0x0,  0x0,  0x0,  0x3ffffe,  0x0,  0xffffff00,  0x7,  0x0,  0x0,  0x200000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xf7ff7000,  0xffffbfff,  0x10007ff,  0xf8000000,  0xffffffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2aaa0000,  0x0,  0xe8000000,  0xe808ea03,  0x6a00e808,  0x8207ff,  0x50d88070,  0x80800380,  0xfff30000,  0x1fff7fff,  0x100,  0x0,  0x0,  0x3e6ffeef,  0xfbfbbd57,  0xffff03e1,  0xffffffff,  0x200,  0x0,  0x0,  0x0,  0x0,  0x1b000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x600,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x7ff,  0x1000,  0x0,  0x0,  0x700000,  0x0,  0x0,  0x10000000,  0x0,  0x0,  0x0,  0x0,  0x30000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x8000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x80000000,  0x0,  0x0,  0x80000,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3fffff,  0x0,  0x1,  0x7400000,  0x0,  0x0,  0x9e000000,  0x0,  0x0,  0x80000000,  0x0,  0xfffe0000,  0xffffffff,  0xffffffff,  0xfffc7fff,  0x0,  0x0,  0x0,  0x7fffffff,  0xffffffff,  0xffff00ff,  0x7fffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x7fffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x0,  0x0,  0x0,  0x10000,  0x0,  0x0,  0x0,  0x3000000,  0x7fe53fff,  0xfffffc65,  0xffffffff,  0xffff3fff,  0xffffffff,  0xffffffff,  0x3ffffff,  0x0,  0xa0f8007f,  0x5f7fffff,  0xffffffdb,  0xffffffff,  0xffffffff,  0x3ffff,  0xfff80000,  0xffffffff,  0xffffffff,  0x3fffffff,  0xffff0000,  0xffffffff,  0xfffcffff,  0xffffffff,  0xff,  0x1fff0000,  0x3ff0000,  0xffff0000,  0xfff7ff9f,  0xffd70f7f,  0xffffffff,  0xffffffff,  0xffffffff,  0x1fffffff,  0xfffffffe,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x7fffffff,  0x1cfcfcfc,  0x7f7f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x4000000,  0x0,  0x0,  0x0,  0x80,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc0000000,  0x1f,  0x0,  0xf8000000,  0x1,  0x0,  0xffffffff,  0xffffffff,  0xffdfffff,  0xffffffff,  0xdfffffff,  0xebffde64,  0xffffffef,  0xffffffff,  0xdfdfe7bf,  0x7bffffff,  0xfffdfc5f,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffff3f,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffcfff,  0xffffffff,  0xffffffef,  0xaf7fe96,  0xaa96ea84,  0x5ef7f796,  0xffffbff,  0xffffbee,  0x0,  0x0,  0xffff07ff,  0xffff7fff,  0xffff,  0xc00,  0x10000,  0x0,  0x0,  0x0,  0xffff0007,  0x7ffffff,  0x301ff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3fffffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//2656 bytes
+enum nfkdQCTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x40,  0xf0], [ 0x100,  0x160,  0x3500], [ 0x2020100,  0x5040302,  0x2020206,  0x8070202,  0x2020202,  0x9020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000,  0x30002,  0x50004,  0x70006,  0x80007,  0xa0009,  0xc000b,  0xe000d,  0x7000f,  0x70007,  0x70007,  0x70007,  0x70007,  0x100007,  0x110007,  0x130012,  0x150014,  0x170016,  0x70018,  0x70007,  0x70007,  0x70019,  0x1b001a,  0x1d001c,  0x1f001e,  0x210020,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x220007,  0x70007,  0x70007,  0x210021,  0x210021,  0x210021,  0x210021,  0x210021,  0x210021,  0x210021,  0x210021,  0x210021,  0x210021,  0x210021,  0x210021,  0x210021,  0x210021,  0x210021,  0x210021,  0x210021,  0x210021,  0x210021,  0x210021,  0x210021,  0x230021,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x210007,  0x250024,  0x260021,  0x280027,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x2a0029,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x2b0007,  0x70007,  0x2d002c,  0x2f002e,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70030,  0x310007,  0x70032,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x210021,  0x70033,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x70007,  0x0,  0x0,  0x0,  0x0,  0x0,  0x773c8501,  0x3e7effbf,  0xbe7effbf,  0xfffcffff,  0xfefdff3f,  0xfff3f3f9,  0xffffff3f,  0x0,  0x18003,  0xdffffff0,  0xff3fffcf,  0xcfffffff,  0xfffc0,  0x0,  0x0,  0x0,  0x1ff0000,  0x3f000000,  0x1f,  0x0,  0x0,  0x1b,  0x44100000,  0x1d7f0,  0x1fc00,  0x7f7c00,  0x2370000,  0x200708b,  0x2000000,  0x708b0000,  0xc00000,  0x0,  0x0,  0xfccf0006,  0x33ffcfc,  0x0,  0x0,  0x0,  0x0,  0x80,  0x0,  0x0,  0x0,  0x0,  0x7c,  0x0,  0x1e00000,  0x0,  0x0,  0x80005,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x120200,  0xff000000,  0x0,  0x0,  0x0,  0xb0001800,  0x0,  0x0,  0x480000,  0x4e000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x30001900,  0x0,  0x100000,  0x0,  0x1c00,  0x0,  0x0,  0x0,  0x100,  0x0,  0x0,  0x0,  0xd81,  0x0,  0x0,  0x0,  0x1c00,  0x0,  0x0,  0x0,  0x74000000,  0x0,  0x0,  0x80000,  0x0,  0x0,  0x0,  0x80000,  0x30000000,  0x0,  0x1000,  0x0,  0x10842008,  0x3e80200,  0x20080002,  0x2001084,  0x0,  0x0,  0x0,  0x40,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000000,  0x45540,  0x28000000,  0xb,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xf7ff7000,  0xffffbfff,  0x10007ff,  0xf8000000,  0xffffffff,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xfffffff,  0xffffffff,  0xffffffff,  0x3ffffff,  0x3f3fffff,  0xffffffff,  0xaaff3f3f,  0x3fffffff,  0xffffffff,  0xffdfffff,  0xefcfffdf,  0x7fdcffff,  0x8207ff,  0x50d88070,  0x80800380,  0xfff30000,  0x1fff7fff,  0x100,  0x0,  0x0,  0x3e6ffeef,  0xfbfbbd57,  0xffff03e1,  0xffffffff,  0xc000200,  0x4000,  0xe000,  0x0,  0x1210,  0x1b050,  0x292,  0x333e005,  0x333,  0xf000,  0x0,  0x3c0f,  0x0,  0x600,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x7ff,  0x1000,  0x0,  0x0,  0x700000,  0x0,  0x0,  0x10000000,  0x0,  0x0,  0x0,  0x0,  0x30000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x8000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x80000000,  0x0,  0x0,  0x80000,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3fffff,  0x0,  0x1,  0x7400000,  0x55555000,  0x36db02a5,  0xd8100000,  0x55555000,  0x36db02a5,  0xc7900000,  0x0,  0xfffe0000,  0xffffffff,  0xffffffff,  0xfffc7fff,  0x0,  0x0,  0x0,  0x7fffffff,  0xffffffff,  0xffff00ff,  0x7fffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x7fffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x0,  0x0,  0x0,  0x10000,  0x0,  0x0,  0x0,  0x3000000,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xf,  0x0,  0x0,  0x7fe53fff,  0xfffffc65,  0xffffffff,  0xffff3fff,  0xffffffff,  0xffffffff,  0x3ffffff,  0x0,  0xa0f8007f,  0x5f7fffff,  0xffffffdb,  0xffffffff,  0xffffffff,  0x3ffff,  0xfff80000,  0xffffffff,  0xffffffff,  0x3fffffff,  0xffff0000,  0xffffffff,  0xfffcffff,  0xffffffff,  0xff,  0x1fff0000,  0x3ff0000,  0xffff0000,  0xfff7ff9f,  0xffd70f7f,  0xffffffff,  0xffffffff,  0xffffffff,  0x1fffffff,  0xfffffffe,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x7fffffff,  0x1cfcfcfc,  0x7f7f,  0x0,  0x0,  0x0,  0x0,  0x14000000,  0x800,  0x0,  0x0,  0x0,  0xc000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc0000000,  0x1f,  0x0,  0xf8000000,  0x1,  0x0,  0xffffffff,  0xffffffff,  0xffdfffff,  0xffffffff,  0xdfffffff,  0xebffde64,  0xffffffef,  0xffffffff,  0xdfdfe7bf,  0x7bffffff,  0xfffdfc5f,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffff3f,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffcfff,  0xffffffff,  0xffffffef,  0xaf7fe96,  0xaa96ea84,  0x5ef7f796,  0xffffbff,  0xffffbee,  0x0,  0x0,  0xffff07ff,  0xffff7fff,  0xffff,  0xc00,  0x10000,  0x0,  0x0,  0x0,  0xffff0007,  0x7ffffff,  0x301ff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3fffffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+
+}
+
diff --git a/std/internal/unicode_tables.d b/std/internal/unicode_tables.d
new file mode 100644
index 000000000..31365f831
--- /dev/null
+++ b/std/internal/unicode_tables.d
@@ -0,0 +1,2357 @@
+//Written in the D programming language
+/**
+ * License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
+ *
+ * Authors: Dmitry Olshansky
+ *
+ */
+//Automatically generated from Unicode Character Database files
+
+module std.internal.unicode_tables;
+@safe pure nothrow:
+
+
+struct SimpleCaseEntry
+{
+    uint ch;
+    ubyte n, bucket;// n - number in bucket
+    @property ubyte size() const
+    {
+        return bucket & 0x3F;
+    }
+    @property auto isLower() const
+    {
+        return bucket & 0x40;
+    }
+    @property auto isUpper() const
+    {
+        return bucket & 0x80;
+    }
+}
+
+struct FullCaseEntry
+{
+    dchar[3] seq;
+    ubyte n, size;// n number in batch, size - size of batch
+    ubyte entry_len;
+
+    @property auto value() const @trusted
+    {
+        return seq[0..entry_len];
+    }
+}
+
+struct CompEntry
+{
+    dchar rhs, composed;
+}
+
+struct UnicodeProperty
+{
+    string name;
+    ubyte[] compressed;
+}
+
+struct TrieEntry(T...)
+{
+    size_t[] offsets;
+    size_t[] sizes;
+    size_t[] data;
+}
+
+@property immutable(SimpleCaseEntry[]) simpleCaseTable()
+{
+alias SCE = SimpleCaseEntry;
+static immutable SCE[] t = [
+SCE(0x2c00, 0, 0x82),
+SCE(0x2c30, 1, 0x42),SCE(0x24c3, 0, 0x82),SCE(0x24dd, 1, 0x42),SCE(0x2c01, 0, 0x82),
+SCE(0x2c31, 1, 0x42),SCE(0x2c1d, 0, 0x82),SCE(0x2c4d, 1, 0x42),SCE(0x2c02, 0, 0x82),
+SCE(0x2c32, 1, 0x42),SCE(0x2c03, 0, 0x82),SCE(0x2c33, 1, 0x42),SCE(0x2c04, 0, 0x82),
+SCE(0x2c34, 1, 0x42),SCE(0x2c05, 0, 0x82),SCE(0x2c35, 1, 0x42),SCE(0x2c06, 0, 0x82),
+SCE(0x2c36, 1, 0x42),SCE(0x10400, 0, 0x82),SCE(0x10428, 1, 0x42),SCE(0x2cc2, 0, 0x82),
+SCE(0x2cc3, 1, 0x42),SCE(0x2c07, 0, 0x82),SCE(0x2c37, 1, 0x42),SCE(0x2c08, 0, 0x82),
+SCE(0x2c38, 1, 0x42),SCE(0x2c09, 0, 0x82),SCE(0x2c39, 1, 0x42),SCE(0x2c0a, 0, 0x82),
+SCE(0x2c3a, 1, 0x42),SCE(0xa68c, 0, 0x82),SCE(0xa68d, 1, 0x42),SCE(0x0041, 0, 0x82),
+SCE(0x0061, 1, 0x42),SCE(0x0042, 0, 0x82),SCE(0x0062, 1, 0x42),SCE(0x0043, 0, 0x82),
+SCE(0x0063, 1, 0x42),SCE(0x0044, 0, 0x82),SCE(0x0064, 1, 0x42),SCE(0x0045, 0, 0x82),
+SCE(0x0065, 1, 0x42),SCE(0x0046, 0, 0x82),SCE(0x0066, 1, 0x42),SCE(0x0047, 0, 0x82),
+SCE(0x0067, 1, 0x42),SCE(0x0048, 0, 0x82),SCE(0x0068, 1, 0x42),SCE(0x0049, 0, 0x82),
+SCE(0x0069, 1, 0x42),SCE(0x004a, 0, 0x82),SCE(0x006a, 1, 0x42),SCE(0x004b, 0, 0x83),
+SCE(0x006b, 1, 0x43),SCE(0x212a, 2, 0x83),SCE(0x004c, 0, 0x82),SCE(0x006c, 1, 0x42),
+SCE(0x004d, 0, 0x82),SCE(0x006d, 1, 0x42),SCE(0x004e, 0, 0x82),SCE(0x006e, 1, 0x42),
+SCE(0x004f, 0, 0x82),SCE(0x006f, 1, 0x42),SCE(0x0050, 0, 0x82),SCE(0x0070, 1, 0x42),
+SCE(0x0051, 0, 0x82),SCE(0x0071, 1, 0x42),SCE(0x0052, 0, 0x82),SCE(0x0072, 1, 0x42),
+SCE(0x0053, 0, 0x83),SCE(0x0073, 1, 0x43),SCE(0x017f, 2, 0x43),SCE(0x0054, 0, 0x82),
+SCE(0x0074, 1, 0x42),SCE(0x0055, 0, 0x82),SCE(0x0075, 1, 0x42),SCE(0x0056, 0, 0x82),
+SCE(0x0076, 1, 0x42),SCE(0x0057, 0, 0x82),SCE(0x0077, 1, 0x42),SCE(0x0058, 0, 0x82),
+SCE(0x0078, 1, 0x42),SCE(0x0059, 0, 0x82),SCE(0x0079, 1, 0x42),SCE(0x005a, 0, 0x82),
+SCE(0x007a, 1, 0x42),SCE(0x2c0f, 0, 0x82),SCE(0x2c3f, 1, 0x42),SCE(0x2c10, 0, 0x82),
+SCE(0x2c40, 1, 0x42),SCE(0x10402, 0, 0x82),SCE(0x1042a, 1, 0x42),SCE(0x2cc4, 0, 0x82),
+SCE(0x2cc5, 1, 0x42),SCE(0x2166, 0, 0x82),SCE(0x2176, 1, 0x42),SCE(0x2c11, 0, 0x82),
+SCE(0x2c41, 1, 0x42),SCE(0x2c12, 0, 0x82),SCE(0x2c42, 1, 0x42),SCE(0x2168, 0, 0x82),
+SCE(0x2178, 1, 0x42),SCE(0x2c13, 0, 0x82),SCE(0x2c43, 1, 0x42),SCE(0xa682, 0, 0x82),
+SCE(0xa683, 1, 0x42),SCE(0x2c14, 0, 0x82),SCE(0x2c44, 1, 0x42),SCE(0x216a, 0, 0x82),
+SCE(0x217a, 1, 0x42),SCE(0x24c7, 0, 0x82),SCE(0x24e1, 1, 0x42),SCE(0x2c15, 0, 0x82),
+SCE(0x2c45, 1, 0x42),SCE(0x10403, 0, 0x82),SCE(0x1042b, 1, 0x42),SCE(0x2c16, 0, 0x82),
+SCE(0x2c46, 1, 0x42),SCE(0x216c, 0, 0x82),SCE(0x217c, 1, 0x42),SCE(0x2c17, 0, 0x82),
+SCE(0x2c47, 1, 0x42),SCE(0xff38, 0, 0x82),SCE(0xff58, 1, 0x42),SCE(0x2c18, 0, 0x82),
+SCE(0x2c48, 1, 0x42),SCE(0x216e, 0, 0x82),SCE(0x217e, 1, 0x42),SCE(0x2c19, 0, 0x82),
+SCE(0x2c49, 1, 0x42),SCE(0x2c1a, 0, 0x82),SCE(0x2c4a, 1, 0x42),SCE(0x2c1e, 0, 0x82),
+SCE(0x2c4e, 1, 0x42),SCE(0x10a0, 0, 0x82),SCE(0x2d00, 1, 0x42),SCE(0x10a1, 0, 0x82),
+SCE(0x2d01, 1, 0x42),SCE(0x10a2, 0, 0x82),SCE(0x2d02, 1, 0x42),SCE(0x10a3, 0, 0x82),
+SCE(0x2d03, 1, 0x42),SCE(0x10a4, 0, 0x82),SCE(0x2d04, 1, 0x42),SCE(0x10a5, 0, 0x82),
+SCE(0x2d05, 1, 0x42),SCE(0x10a6, 0, 0x82),SCE(0x2d06, 1, 0x42),SCE(0x10a7, 0, 0x82),
+SCE(0x2d07, 1, 0x42),SCE(0x10a8, 0, 0x82),SCE(0x2d08, 1, 0x42),SCE(0x10a9, 0, 0x82),
+SCE(0x2d09, 1, 0x42),SCE(0x10aa, 0, 0x82),SCE(0x2d0a, 1, 0x42),SCE(0x10ab, 0, 0x82),
+SCE(0x2d0b, 1, 0x42),SCE(0x10ac, 0, 0x82),SCE(0x2d0c, 1, 0x42),SCE(0x10ad, 0, 0x82),
+SCE(0x2d0d, 1, 0x42),SCE(0x10ae, 0, 0x82),SCE(0x2d0e, 1, 0x42),SCE(0x10af, 0, 0x82),
+SCE(0x2d0f, 1, 0x42),SCE(0x10b0, 0, 0x82),SCE(0x2d10, 1, 0x42),SCE(0x10b1, 0, 0x82),
+SCE(0x2d11, 1, 0x42),SCE(0x10b2, 0, 0x82),SCE(0x2d12, 1, 0x42),SCE(0x10b3, 0, 0x82),
+SCE(0x2d13, 1, 0x42),SCE(0x10b4, 0, 0x82),SCE(0x2d14, 1, 0x42),SCE(0x10b5, 0, 0x82),
+SCE(0x2d15, 1, 0x42),SCE(0x10b6, 0, 0x82),SCE(0x2d16, 1, 0x42),SCE(0x10b7, 0, 0x82),
+SCE(0x2d17, 1, 0x42),SCE(0x10b8, 0, 0x82),SCE(0x2d18, 1, 0x42),SCE(0x10b9, 0, 0x82),
+SCE(0x2d19, 1, 0x42),SCE(0x10ba, 0, 0x82),SCE(0x2d1a, 1, 0x42),SCE(0x10bb, 0, 0x82),
+SCE(0x2d1b, 1, 0x42),SCE(0x10bc, 0, 0x82),SCE(0x2d1c, 1, 0x42),SCE(0x10bd, 0, 0x82),
+SCE(0x2d1d, 1, 0x42),SCE(0x10be, 0, 0x82),SCE(0x2d1e, 1, 0x42),SCE(0x10bf, 0, 0x82),
+SCE(0x2d1f, 1, 0x42),SCE(0x00c0, 0, 0x82),SCE(0x00e0, 1, 0x42),SCE(0x00c1, 0, 0x82),
+SCE(0x00e1, 1, 0x42),SCE(0x10c2, 0, 0x82),SCE(0x2d22, 1, 0x42),SCE(0x00c3, 0, 0x82),
+SCE(0x00e3, 1, 0x42),SCE(0x10c4, 0, 0x82),SCE(0x2d24, 1, 0x42),SCE(0x00c5, 0, 0x83),
+SCE(0x00e5, 1, 0x43),SCE(0x212b, 2, 0x83),SCE(0x00c6, 0, 0x82),SCE(0x00e6, 1, 0x42),
+SCE(0x00c7, 0, 0x82),SCE(0x00e7, 1, 0x42),SCE(0x00c8, 0, 0x82),SCE(0x00e8, 1, 0x42),
+SCE(0x00c9, 0, 0x82),SCE(0x00e9, 1, 0x42),SCE(0x00ca, 0, 0x82),SCE(0x00ea, 1, 0x42),
+SCE(0x00cb, 0, 0x82),SCE(0x00eb, 1, 0x42),SCE(0x00cc, 0, 0x82),SCE(0x00ec, 1, 0x42),
+SCE(0x00cd, 0, 0x82),SCE(0x00ed, 1, 0x42),SCE(0x00ce, 0, 0x82),SCE(0x00ee, 1, 0x42),
+SCE(0x00cf, 0, 0x82),SCE(0x00ef, 1, 0x42),SCE(0x00d0, 0, 0x82),SCE(0x00f0, 1, 0x42),
+SCE(0x00d1, 0, 0x82),SCE(0x00f1, 1, 0x42),SCE(0x00d2, 0, 0x82),SCE(0x00f2, 1, 0x42),
+SCE(0x00d3, 0, 0x82),SCE(0x00f3, 1, 0x42),SCE(0x00d4, 0, 0x82),SCE(0x00f4, 1, 0x42),
+SCE(0x00d5, 0, 0x82),SCE(0x00f5, 1, 0x42),SCE(0x00d6, 0, 0x82),SCE(0x00f6, 1, 0x42),
+SCE(0x00d8, 0, 0x82),SCE(0x00f8, 1, 0x42),SCE(0x00d9, 0, 0x82),SCE(0x00f9, 1, 0x42),
+SCE(0x00da, 0, 0x82),SCE(0x00fa, 1, 0x42),SCE(0x00db, 0, 0x82),SCE(0x00fb, 1, 0x42),
+SCE(0x00dc, 0, 0x82),SCE(0x00fc, 1, 0x42),SCE(0x00dd, 0, 0x82),SCE(0x00fd, 1, 0x42),
+SCE(0x00de, 0, 0x82),SCE(0x00fe, 1, 0x42),SCE(0x2c25, 0, 0x82),SCE(0x2c55, 1, 0x42),
+SCE(0x2c26, 0, 0x82),SCE(0x2c56, 1, 0x42),SCE(0x2c27, 0, 0x82),SCE(0x2c57, 1, 0x42),
+SCE(0x2c28, 0, 0x82),SCE(0x2c58, 1, 0x42),SCE(0x1040f, 0, 0x82),SCE(0x10437, 1, 0x42),
+SCE(0x24cb, 0, 0x82),SCE(0x24e5, 1, 0x42),SCE(0x2c29, 0, 0x82),SCE(0x2c59, 1, 0x42),
+SCE(0x10407, 0, 0x82),SCE(0x1042f, 1, 0x42),SCE(0x2c2a, 0, 0x82),SCE(0x2c5a, 1, 0x42),
+SCE(0x0100, 0, 0x82),SCE(0x0101, 1, 0x42),SCE(0x0102, 0, 0x82),SCE(0x0103, 1, 0x42),
+SCE(0x2c2b, 0, 0x82),SCE(0x2c5b, 1, 0x42),SCE(0x0104, 0, 0x82),SCE(0x0105, 1, 0x42),
+SCE(0x0106, 0, 0x82),SCE(0x0107, 1, 0x42),SCE(0x0108, 0, 0x82),SCE(0x0109, 1, 0x42),
+SCE(0x2c2c, 0, 0x82),SCE(0x2c5c, 1, 0x42),SCE(0x010a, 0, 0x82),SCE(0x010b, 1, 0x42),
+SCE(0x010c, 0, 0x82),SCE(0x010d, 1, 0x42),SCE(0x010e, 0, 0x82),SCE(0x010f, 1, 0x42),
+SCE(0x2c2d, 0, 0x82),SCE(0x2c5d, 1, 0x42),SCE(0x0110, 0, 0x82),SCE(0x0111, 1, 0x42),
+SCE(0x0112, 0, 0x82),SCE(0x0113, 1, 0x42),SCE(0x0114, 0, 0x82),SCE(0x0115, 1, 0x42),
+SCE(0x2c2e, 0, 0x82),SCE(0x2c5e, 1, 0x42),SCE(0x0116, 0, 0x82),SCE(0x0117, 1, 0x42),
+SCE(0x0118, 0, 0x82),SCE(0x0119, 1, 0x42),SCE(0x011a, 0, 0x82),SCE(0x011b, 1, 0x42),
+SCE(0x011c, 0, 0x82),SCE(0x011d, 1, 0x42),SCE(0x011e, 0, 0x82),SCE(0x011f, 1, 0x42),
+SCE(0x0120, 0, 0x82),SCE(0x0121, 1, 0x42),SCE(0x0122, 0, 0x82),SCE(0x0123, 1, 0x42),
+SCE(0x0124, 0, 0x82),SCE(0x0125, 1, 0x42),SCE(0x0126, 0, 0x82),SCE(0x0127, 1, 0x42),
+SCE(0x0128, 0, 0x82),SCE(0x0129, 1, 0x42),SCE(0x012a, 0, 0x82),SCE(0x012b, 1, 0x42),
+SCE(0x00c5, 0, 0x83),SCE(0x00e5, 1, 0x43),SCE(0x212b, 2, 0x83),SCE(0x012c, 0, 0x82),
+SCE(0x012d, 1, 0x42),SCE(0x012e, 0, 0x82),SCE(0x012f, 1, 0x42),SCE(0x0132, 0, 0x82),
+SCE(0x0133, 1, 0x42),SCE(0x0134, 0, 0x82),SCE(0x0135, 1, 0x42),SCE(0x0136, 0, 0x82),
+SCE(0x0137, 1, 0x42),SCE(0x0139, 0, 0x82),SCE(0x013a, 1, 0x42),SCE(0x013b, 0, 0x82),
+SCE(0x013c, 1, 0x42),SCE(0x2cde, 0, 0x82),SCE(0x2cdf, 1, 0x42),SCE(0x013d, 0, 0x82),
+SCE(0x013e, 1, 0x42),SCE(0x013f, 0, 0x82),SCE(0x0140, 1, 0x42),SCE(0x0141, 0, 0x82),
+SCE(0x0142, 1, 0x42),SCE(0x0143, 0, 0x82),SCE(0x0144, 1, 0x42),SCE(0x0145, 0, 0x82),
+SCE(0x0146, 1, 0x42),SCE(0x0147, 0, 0x82),SCE(0x0148, 1, 0x42),SCE(0x014a, 0, 0x82),
+SCE(0x014b, 1, 0x42),SCE(0x014c, 0, 0x82),SCE(0x014d, 1, 0x42),SCE(0x014e, 0, 0x82),
+SCE(0x014f, 1, 0x42),SCE(0x0150, 0, 0x82),SCE(0x0151, 1, 0x42),SCE(0x0152, 0, 0x82),
+SCE(0x0153, 1, 0x42),SCE(0x0154, 0, 0x82),SCE(0x0155, 1, 0x42),SCE(0x0156, 0, 0x82),
+SCE(0x0157, 1, 0x42),SCE(0x0158, 0, 0x82),SCE(0x0159, 1, 0x42),SCE(0x015a, 0, 0x82),
+SCE(0x015b, 1, 0x42),SCE(0x015c, 0, 0x82),SCE(0x015d, 1, 0x42),SCE(0x015e, 0, 0x82),
+SCE(0x015f, 1, 0x42),SCE(0x0160, 0, 0x82),SCE(0x0161, 1, 0x42),SCE(0x2161, 0, 0x82),
+SCE(0x2171, 1, 0x42),SCE(0x0162, 0, 0x82),SCE(0x0163, 1, 0x42),SCE(0x2163, 0, 0x82),
+SCE(0x2173, 1, 0x42),SCE(0x0164, 0, 0x82),SCE(0x0165, 1, 0x42),SCE(0x2165, 0, 0x82),
+SCE(0x2175, 1, 0x42),SCE(0x0166, 0, 0x82),SCE(0x0167, 1, 0x42),SCE(0x2167, 0, 0x82),
+SCE(0x2177, 1, 0x42),SCE(0x0168, 0, 0x82),SCE(0x0169, 1, 0x42),SCE(0x2169, 0, 0x82),
+SCE(0x2179, 1, 0x42),SCE(0x016a, 0, 0x82),SCE(0x016b, 1, 0x42),SCE(0x216b, 0, 0x82),
+SCE(0x217b, 1, 0x42),SCE(0x016c, 0, 0x82),SCE(0x016d, 1, 0x42),SCE(0x216d, 0, 0x82),
+SCE(0x217d, 1, 0x42),SCE(0x016e, 0, 0x82),SCE(0x016f, 1, 0x42),SCE(0x216f, 0, 0x82),
+SCE(0x217f, 1, 0x42),SCE(0x0170, 0, 0x82),SCE(0x0171, 1, 0x42),SCE(0x2ccc, 0, 0x82),
+SCE(0x2ccd, 1, 0x42),SCE(0x0172, 0, 0x82),SCE(0x0173, 1, 0x42),SCE(0x0174, 0, 0x82),
+SCE(0x0175, 1, 0x42),SCE(0x0176, 0, 0x82),SCE(0x0177, 1, 0x42),SCE(0x00ff, 0, 0x42),
+SCE(0x0178, 1, 0x82),SCE(0x0179, 0, 0x82),SCE(0x017a, 1, 0x42),SCE(0x017b, 0, 0x82),
+SCE(0x017c, 1, 0x42),SCE(0x017d, 0, 0x82),SCE(0x017e, 1, 0x42),SCE(0x0053, 0, 0x83),
+SCE(0x0073, 1, 0x43),SCE(0x017f, 2, 0x43),SCE(0x0181, 0, 0x82),SCE(0x0253, 1, 0x42),
+SCE(0x0182, 0, 0x82),SCE(0x0183, 1, 0x42),SCE(0x2183, 0, 0x82),SCE(0x2184, 1, 0x42),
+SCE(0x0184, 0, 0x82),SCE(0x0185, 1, 0x42),SCE(0x0186, 0, 0x82),SCE(0x0254, 1, 0x42),
+SCE(0x0187, 0, 0x82),SCE(0x0188, 1, 0x42),SCE(0x0189, 0, 0x82),SCE(0x0256, 1, 0x42),
+SCE(0x018a, 0, 0x82),SCE(0x0257, 1, 0x42),SCE(0x018b, 0, 0x82),SCE(0x018c, 1, 0x42),
+SCE(0x018e, 0, 0x82),SCE(0x01dd, 1, 0x42),SCE(0x018f, 0, 0x82),SCE(0x0259, 1, 0x42),
+SCE(0x0190, 0, 0x82),SCE(0x025b, 1, 0x42),SCE(0x0191, 0, 0x82),SCE(0x0192, 1, 0x42),
+SCE(0x0193, 0, 0x82),SCE(0x0260, 1, 0x42),SCE(0x0194, 0, 0x82),SCE(0x0263, 1, 0x42),
+SCE(0x0196, 0, 0x82),SCE(0x0269, 1, 0x42),SCE(0x0197, 0, 0x82),SCE(0x0268, 1, 0x42),
+SCE(0x0198, 0, 0x82),SCE(0x0199, 1, 0x42),SCE(0x019c, 0, 0x82),SCE(0x026f, 1, 0x42),
+SCE(0x019d, 0, 0x82),SCE(0x0272, 1, 0x42),SCE(0x019f, 0, 0x82),SCE(0x0275, 1, 0x42),
+SCE(0x01a0, 0, 0x82),SCE(0x01a1, 1, 0x42),SCE(0x01a2, 0, 0x82),SCE(0x01a3, 1, 0x42),
+SCE(0x01a4, 0, 0x82),SCE(0x01a5, 1, 0x42),SCE(0x01a6, 0, 0x82),SCE(0x0280, 1, 0x42),
+SCE(0x01a7, 0, 0x82),SCE(0x01a8, 1, 0x42),SCE(0x01a9, 0, 0x82),SCE(0x0283, 1, 0x42),
+SCE(0x01ac, 0, 0x82),SCE(0x01ad, 1, 0x42),SCE(0x01ae, 0, 0x82),SCE(0x0288, 1, 0x42),
+SCE(0x01af, 0, 0x82),SCE(0x01b0, 1, 0x42),SCE(0x01b1, 0, 0x82),SCE(0x028a, 1, 0x42),
+SCE(0x01b2, 0, 0x82),SCE(0x028b, 1, 0x42),SCE(0x01b3, 0, 0x82),SCE(0x01b4, 1, 0x42),
+SCE(0x01b5, 0, 0x82),SCE(0x01b6, 1, 0x42),SCE(0x01b7, 0, 0x82),SCE(0x0292, 1, 0x42),
+SCE(0x01b8, 0, 0x82),SCE(0x01b9, 1, 0x42),SCE(0x01bc, 0, 0x82),SCE(0x01bd, 1, 0x42),
+SCE(0x01c4, 0, 0x83),SCE(0x01c5, 1, 0x3),SCE(0x01c6, 2, 0x43),SCE(0x01c4, 0, 0x83),
+SCE(0x01c5, 1, 0x3),SCE(0x01c6, 2, 0x43),SCE(0x01c7, 0, 0x83),SCE(0x01c8, 1, 0x3),
+SCE(0x01c9, 2, 0x43),SCE(0x01c7, 0, 0x83),SCE(0x01c8, 1, 0x3),SCE(0x01c9, 2, 0x43),
+SCE(0x01ca, 0, 0x83),SCE(0x01cb, 1, 0x3),SCE(0x01cc, 2, 0x43),SCE(0x01ca, 0, 0x83),
+SCE(0x01cb, 1, 0x3),SCE(0x01cc, 2, 0x43),SCE(0x01cd, 0, 0x82),SCE(0x01ce, 1, 0x42),
+SCE(0x01cf, 0, 0x82),SCE(0x01d0, 1, 0x42),SCE(0x01d1, 0, 0x82),SCE(0x01d2, 1, 0x42),
+SCE(0x01d3, 0, 0x82),SCE(0x01d4, 1, 0x42),SCE(0x01d5, 0, 0x82),SCE(0x01d6, 1, 0x42),
+SCE(0x01d7, 0, 0x82),SCE(0x01d8, 1, 0x42),SCE(0x01d9, 0, 0x82),SCE(0x01da, 1, 0x42),
+SCE(0x01db, 0, 0x82),SCE(0x01dc, 1, 0x42),SCE(0x01de, 0, 0x82),SCE(0x01df, 1, 0x42),
+SCE(0xff36, 0, 0x82),SCE(0xff56, 1, 0x42),SCE(0x01e0, 0, 0x82),SCE(0x01e1, 1, 0x42),
+SCE(0x01e2, 0, 0x82),SCE(0x01e3, 1, 0x42),SCE(0x01e4, 0, 0x82),SCE(0x01e5, 1, 0x42),
+SCE(0x01e6, 0, 0x82),SCE(0x01e7, 1, 0x42),SCE(0x01e8, 0, 0x82),SCE(0x01e9, 1, 0x42),
+SCE(0x01ea, 0, 0x82),SCE(0x01eb, 1, 0x42),SCE(0x01ec, 0, 0x82),SCE(0x01ed, 1, 0x42),
+SCE(0x01ee, 0, 0x82),SCE(0x01ef, 1, 0x42),SCE(0x01f1, 0, 0x83),SCE(0x01f2, 1, 0x3),
+SCE(0x01f3, 2, 0x43),SCE(0x01f1, 0, 0x83),SCE(0x01f2, 1, 0x3),SCE(0x01f3, 2, 0x43),
+SCE(0x01f4, 0, 0x82),SCE(0x01f5, 1, 0x42),SCE(0x0195, 0, 0x42),SCE(0x01f6, 1, 0x82),
+SCE(0x01bf, 0, 0x42),SCE(0x01f7, 1, 0x82),SCE(0x01f8, 0, 0x82),SCE(0x01f9, 1, 0x42),
+SCE(0x1041d, 0, 0x82),SCE(0x10445, 1, 0x42),SCE(0x01fa, 0, 0x82),SCE(0x01fb, 1, 0x42),
+SCE(0x01fc, 0, 0x82),SCE(0x01fd, 1, 0x42),SCE(0x01fe, 0, 0x82),SCE(0x01ff, 1, 0x42),
+SCE(0x0200, 0, 0x82),SCE(0x0201, 1, 0x42),SCE(0x0202, 0, 0x82),SCE(0x0203, 1, 0x42),
+SCE(0x0204, 0, 0x82),SCE(0x0205, 1, 0x42),SCE(0x0206, 0, 0x82),SCE(0x0207, 1, 0x42),
+SCE(0x0208, 0, 0x82),SCE(0x0209, 1, 0x42),SCE(0x020a, 0, 0x82),SCE(0x020b, 1, 0x42),
+SCE(0x020c, 0, 0x82),SCE(0x020d, 1, 0x42),SCE(0x020e, 0, 0x82),SCE(0x020f, 1, 0x42),
+SCE(0x0210, 0, 0x82),SCE(0x0211, 1, 0x42),SCE(0x0212, 0, 0x82),SCE(0x0213, 1, 0x42),
+SCE(0x0214, 0, 0x82),SCE(0x0215, 1, 0x42),SCE(0x0216, 0, 0x82),SCE(0x0217, 1, 0x42),
+SCE(0x0218, 0, 0x82),SCE(0x0219, 1, 0x42),SCE(0x021a, 0, 0x82),SCE(0x021b, 1, 0x42),
+SCE(0x021c, 0, 0x82),SCE(0x021d, 1, 0x42),SCE(0x021e, 0, 0x82),SCE(0x021f, 1, 0x42),
+SCE(0x019e, 0, 0x42),SCE(0x0220, 1, 0x82),SCE(0x0222, 0, 0x82),SCE(0x0223, 1, 0x42),
+SCE(0x0224, 0, 0x82),SCE(0x0225, 1, 0x42),SCE(0x0226, 0, 0x82),SCE(0x0227, 1, 0x42),
+SCE(0x0228, 0, 0x82),SCE(0x0229, 1, 0x42),SCE(0x022a, 0, 0x82),SCE(0x022b, 1, 0x42),
+SCE(0x022c, 0, 0x82),SCE(0x022d, 1, 0x42),SCE(0x022e, 0, 0x82),SCE(0x022f, 1, 0x42),
+SCE(0x0230, 0, 0x82),SCE(0x0231, 1, 0x42),SCE(0x0232, 0, 0x82),SCE(0x0233, 1, 0x42),
+SCE(0xa684, 0, 0x82),SCE(0xa685, 1, 0x42),SCE(0x023a, 0, 0x82),SCE(0x2c65, 1, 0x42),
+SCE(0x023b, 0, 0x82),SCE(0x023c, 1, 0x42),SCE(0x019a, 0, 0x42),SCE(0x023d, 1, 0x82),
+SCE(0x023e, 0, 0x82),SCE(0x2c66, 1, 0x42),SCE(0x0241, 0, 0x82),SCE(0x0242, 1, 0x42),
+SCE(0x10412, 0, 0x82),SCE(0x1043a, 1, 0x42),SCE(0x0180, 0, 0x42),SCE(0x0243, 1, 0x82),
+SCE(0x0244, 0, 0x82),SCE(0x0289, 1, 0x42),SCE(0x0245, 0, 0x82),SCE(0x028c, 1, 0x42),
+SCE(0x0246, 0, 0x82),SCE(0x0247, 1, 0x42),SCE(0x0248, 0, 0x82),SCE(0x0249, 1, 0x42),
+SCE(0x024a, 0, 0x82),SCE(0x024b, 1, 0x42),SCE(0x024c, 0, 0x82),SCE(0x024d, 1, 0x42),
+SCE(0x2c1b, 0, 0x82),SCE(0x2c4b, 1, 0x42),SCE(0x024e, 0, 0x82),SCE(0x024f, 1, 0x42),
+SCE(0x1040a, 0, 0x82),SCE(0x10432, 1, 0x42),SCE(0x2160, 0, 0x82),SCE(0x2170, 1, 0x42),
+SCE(0xa692, 0, 0x82),SCE(0xa693, 1, 0x42),SCE(0x027d, 0, 0x42),SCE(0x2c64, 1, 0x82),
+SCE(0x10410, 0, 0x82),SCE(0x10438, 1, 0x42),SCE(0x2c21, 0, 0x82),SCE(0x2c51, 1, 0x42),
+SCE(0x2c69, 0, 0x82),SCE(0x2c6a, 1, 0x42),SCE(0x10409, 0, 0x82),SCE(0x10431, 1, 0x42),
+SCE(0x10414, 0, 0x82),SCE(0x1043c, 1, 0x42),SCE(0x2162, 0, 0x82),SCE(0x2172, 1, 0x42),
+SCE(0x1041e, 0, 0x82),SCE(0x10446, 1, 0x42),SCE(0x0271, 0, 0x42),SCE(0x2c6e, 1, 0x82),
+SCE(0x10415, 0, 0x82),SCE(0x1043d, 1, 0x42),SCE(0x0252, 0, 0x42),SCE(0x2c70, 1, 0x82),
+SCE(0x2c72, 0, 0x82),SCE(0x2c73, 1, 0x42),SCE(0x2c0b, 0, 0x82),SCE(0x2c3b, 1, 0x42),
+SCE(0x10416, 0, 0x82),SCE(0x1043e, 1, 0x42),SCE(0x2c75, 0, 0x82),SCE(0x2c76, 1, 0x42),
+SCE(0x2164, 0, 0x82),SCE(0x2174, 1, 0x42),SCE(0xa640, 0, 0x82),SCE(0xa641, 1, 0x42),
+SCE(0xff22, 0, 0x82),SCE(0xff42, 1, 0x42),SCE(0x2c0c, 0, 0x82),SCE(0x2c3c, 1, 0x42),
+SCE(0x10417, 0, 0x82),SCE(0x1043f, 1, 0x42),SCE(0xff24, 0, 0x82),SCE(0xff44, 1, 0x42),
+SCE(0xff25, 0, 0x82),SCE(0xff45, 1, 0x42),SCE(0xff26, 0, 0x82),SCE(0xff46, 1, 0x42),
+SCE(0x2c0d, 0, 0x82),SCE(0x2c3d, 1, 0x42),SCE(0x24c1, 0, 0x82),SCE(0x24db, 1, 0x42),
+SCE(0xa728, 0, 0x82),SCE(0xa729, 1, 0x42),SCE(0x023f, 0, 0x42),SCE(0x2c7e, 1, 0x82),
+SCE(0x10411, 0, 0x82),SCE(0x10439, 1, 0x42),SCE(0xff29, 0, 0x82),SCE(0xff49, 1, 0x42),
+SCE(0x1040b, 0, 0x82),SCE(0x10433, 1, 0x42),SCE(0xa72a, 0, 0x82),SCE(0xa72b, 1, 0x42),
+SCE(0x2c80, 0, 0x82),SCE(0x2c81, 1, 0x42),SCE(0xff2b, 0, 0x82),SCE(0xff4b, 1, 0x42),
+SCE(0xa72c, 0, 0x82),SCE(0xa72d, 1, 0x42),SCE(0x2c0e, 0, 0x82),SCE(0x2c3e, 1, 0x42),
+SCE(0xff2d, 0, 0x82),SCE(0xff4d, 1, 0x42),SCE(0x10419, 0, 0x82),SCE(0x10441, 1, 0x42),
+SCE(0xa72e, 0, 0x82),SCE(0xa72f, 1, 0x42),SCE(0x1040d, 0, 0x82),SCE(0x10435, 1, 0x42),
+SCE(0xff2f, 0, 0x82),SCE(0xff4f, 1, 0x42),SCE(0xff31, 0, 0x82),SCE(0xff51, 1, 0x42),
+SCE(0xff32, 0, 0x82),SCE(0xff52, 1, 0x42),SCE(0x1041a, 0, 0x82),SCE(0x10442, 1, 0x42),
+SCE(0xff34, 0, 0x82),SCE(0xff54, 1, 0x42),SCE(0x2c98, 0, 0x82),SCE(0x2c99, 1, 0x42),
+SCE(0x2c8a, 0, 0x82),SCE(0x2c8b, 1, 0x42),SCE(0x0345, 0, 0x44),SCE(0x0399, 1, 0x84),
+SCE(0x03b9, 2, 0x44),SCE(0x1fbe, 3, 0x44),SCE(0x2c8c, 0, 0x82),SCE(0x2c8d, 1, 0x42),
+SCE(0xff37, 0, 0x82),SCE(0xff57, 1, 0x42),SCE(0xa656, 0, 0x82),SCE(0xa657, 1, 0x42),
+SCE(0x1041b, 0, 0x82),SCE(0x10443, 1, 0x42),SCE(0xa738, 0, 0x82),SCE(0xa739, 1, 0x42),
+SCE(0x2c8e, 0, 0x82),SCE(0x2c8f, 1, 0x42),SCE(0xff39, 0, 0x82),SCE(0xff59, 1, 0x42),
+SCE(0x10404, 0, 0x82),SCE(0x1042c, 1, 0x42),SCE(0xa73a, 0, 0x82),SCE(0xa73b, 1, 0x42),
+SCE(0x2c90, 0, 0x82),SCE(0x2c91, 1, 0x42),SCE(0xa73c, 0, 0x82),SCE(0xa73d, 1, 0x42),
+SCE(0x2c92, 0, 0x82),SCE(0x2c93, 1, 0x42),SCE(0x1041c, 0, 0x82),SCE(0x10444, 1, 0x42),
+SCE(0x0370, 0, 0x82),SCE(0x0371, 1, 0x42),SCE(0x0372, 0, 0x82),SCE(0x0373, 1, 0x42),
+SCE(0xa73e, 0, 0x82),SCE(0xa73f, 1, 0x42),SCE(0x0376, 0, 0x82),SCE(0x0377, 1, 0x42),
+SCE(0x2c94, 0, 0x82),SCE(0x2c95, 1, 0x42),SCE(0x2c96, 0, 0x82),SCE(0x2c97, 1, 0x42),
+SCE(0x0386, 0, 0x82),SCE(0x03ac, 1, 0x42),SCE(0x10405, 0, 0x82),SCE(0x1042d, 1, 0x42),
+SCE(0x0388, 0, 0x82),SCE(0x03ad, 1, 0x42),SCE(0x0389, 0, 0x82),SCE(0x03ae, 1, 0x42),
+SCE(0x038a, 0, 0x82),SCE(0x03af, 1, 0x42),SCE(0x038c, 0, 0x82),SCE(0x03cc, 1, 0x42),
+SCE(0x038e, 0, 0x82),SCE(0x03cd, 1, 0x42),SCE(0x038f, 0, 0x82),SCE(0x03ce, 1, 0x42),
+SCE(0x0391, 0, 0x82),SCE(0x03b1, 1, 0x42),SCE(0x0392, 0, 0x83),SCE(0x03b2, 1, 0x43),
+SCE(0x03d0, 2, 0x43),SCE(0x0393, 0, 0x82),SCE(0x03b3, 1, 0x42),SCE(0x0394, 0, 0x82),
+SCE(0x03b4, 1, 0x42),SCE(0x0395, 0, 0x83),SCE(0x03b5, 1, 0x43),SCE(0x03f5, 2, 0x43),
+SCE(0x0396, 0, 0x82),SCE(0x03b6, 1, 0x42),SCE(0x0397, 0, 0x82),SCE(0x03b7, 1, 0x42),
+SCE(0x0398, 0, 0x84),SCE(0x03b8, 1, 0x44),SCE(0x03d1, 2, 0x44),SCE(0x03f4, 3, 0x84),
+SCE(0x0345, 0, 0x44),SCE(0x0399, 1, 0x84),SCE(0x03b9, 2, 0x44),SCE(0x1fbe, 3, 0x44),
+SCE(0x039a, 0, 0x83),SCE(0x03ba, 1, 0x43),SCE(0x03f0, 2, 0x43),SCE(0x039b, 0, 0x82),
+SCE(0x03bb, 1, 0x42),SCE(0x00b5, 0, 0x43),SCE(0x039c, 1, 0x83),SCE(0x03bc, 2, 0x43),
+SCE(0x039d, 0, 0x82),SCE(0x03bd, 1, 0x42),SCE(0x039e, 0, 0x82),SCE(0x03be, 1, 0x42),
+SCE(0x039f, 0, 0x82),SCE(0x03bf, 1, 0x42),SCE(0x03a0, 0, 0x83),SCE(0x03c0, 1, 0x43),
+SCE(0x03d6, 2, 0x43),SCE(0x03a1, 0, 0x83),SCE(0x03c1, 1, 0x43),SCE(0x03f1, 2, 0x43),
+SCE(0x03a3, 0, 0x83),SCE(0x03c2, 1, 0x43),SCE(0x03c3, 2, 0x43),SCE(0x03a4, 0, 0x82),
+SCE(0x03c4, 1, 0x42),SCE(0x03a5, 0, 0x82),SCE(0x03c5, 1, 0x42),SCE(0x03a6, 0, 0x83),
+SCE(0x03c6, 1, 0x43),SCE(0x03d5, 2, 0x43),SCE(0x03a7, 0, 0x82),SCE(0x03c7, 1, 0x42),
+SCE(0x03a8, 0, 0x82),SCE(0x03c8, 1, 0x42),SCE(0x03a9, 0, 0x83),SCE(0x03c9, 1, 0x43),
+SCE(0x2126, 2, 0x83),SCE(0x03aa, 0, 0x82),SCE(0x03ca, 1, 0x42),SCE(0x03ab, 0, 0x82),
+SCE(0x03cb, 1, 0x42),SCE(0x24c9, 0, 0x82),SCE(0x24e3, 1, 0x42),SCE(0x2ce0, 0, 0x82),
+SCE(0x2ce1, 1, 0x42),SCE(0xa748, 0, 0x82),SCE(0xa749, 1, 0x42),SCE(0x2c9c, 0, 0x82),
+SCE(0x2c9d, 1, 0x42),SCE(0x2c9e, 0, 0x82),SCE(0x2c9f, 1, 0x42),SCE(0xa74a, 0, 0x82),
+SCE(0xa74b, 1, 0x42),SCE(0x2ca0, 0, 0x82),SCE(0x2ca1, 1, 0x42),SCE(0x03a3, 0, 0x83),
+SCE(0x03c2, 1, 0x43),SCE(0x03c3, 2, 0x43),SCE(0x1041f, 0, 0x82),SCE(0x10447, 1, 0x42),
+SCE(0xa74c, 0, 0x82),SCE(0xa74d, 1, 0x42),SCE(0xa68a, 0, 0x82),SCE(0xa68b, 1, 0x42),
+SCE(0x2ca2, 0, 0x82),SCE(0x2ca3, 1, 0x42),SCE(0x03cf, 0, 0x82),SCE(0x03d7, 1, 0x42),
+SCE(0x0392, 0, 0x83),SCE(0x03b2, 1, 0x43),SCE(0x03d0, 2, 0x43),SCE(0x0398, 0, 0x84),
+SCE(0x03b8, 1, 0x44),SCE(0x03d1, 2, 0x44),SCE(0x03f4, 3, 0x84),SCE(0x03a6, 0, 0x83),
+SCE(0x03c6, 1, 0x43),SCE(0x03d5, 2, 0x43),SCE(0x03a0, 0, 0x83),SCE(0x03c0, 1, 0x43),
+SCE(0x03d6, 2, 0x43),SCE(0x03d8, 0, 0x82),SCE(0x03d9, 1, 0x42),SCE(0x2ca4, 0, 0x82),
+SCE(0x2ca5, 1, 0x42),SCE(0x03da, 0, 0x82),SCE(0x03db, 1, 0x42),SCE(0x03dc, 0, 0x82),
+SCE(0x03dd, 1, 0x42),SCE(0x03de, 0, 0x82),SCE(0x03df, 1, 0x42),SCE(0x03e0, 0, 0x82),
+SCE(0x03e1, 1, 0x42),SCE(0x03e2, 0, 0x82),SCE(0x03e3, 1, 0x42),SCE(0x03e4, 0, 0x82),
+SCE(0x03e5, 1, 0x42),SCE(0x2ca6, 0, 0x82),SCE(0x2ca7, 1, 0x42),SCE(0x03e6, 0, 0x82),
+SCE(0x03e7, 1, 0x42),SCE(0x10420, 0, 0x82),SCE(0x10448, 1, 0x42),SCE(0x03e8, 0, 0x82),
+SCE(0x03e9, 1, 0x42),SCE(0x2ce2, 0, 0x82),SCE(0x2ce3, 1, 0x42),SCE(0x03ea, 0, 0x82),
+SCE(0x03eb, 1, 0x42),SCE(0x03ec, 0, 0x82),SCE(0x03ed, 1, 0x42),SCE(0x03ee, 0, 0x82),
+SCE(0x03ef, 1, 0x42),SCE(0x039a, 0, 0x83),SCE(0x03ba, 1, 0x43),SCE(0x03f0, 2, 0x43),
+SCE(0x03a1, 0, 0x83),SCE(0x03c1, 1, 0x43),SCE(0x03f1, 2, 0x43),SCE(0x0398, 0, 0x84),
+SCE(0x03b8, 1, 0x44),SCE(0x03d1, 2, 0x44),SCE(0x03f4, 3, 0x84),SCE(0x0395, 0, 0x83),
+SCE(0x03b5, 1, 0x43),SCE(0x03f5, 2, 0x43),SCE(0x03f7, 0, 0x82),SCE(0x03f8, 1, 0x42),
+SCE(0x03f2, 0, 0x42),SCE(0x03f9, 1, 0x82),SCE(0x03fa, 0, 0x82),SCE(0x03fb, 1, 0x42),
+SCE(0x037b, 0, 0x42),SCE(0x03fd, 1, 0x82),SCE(0x037c, 0, 0x42),SCE(0x03fe, 1, 0x82),
+SCE(0x037d, 0, 0x42),SCE(0x03ff, 1, 0x82),SCE(0x0400, 0, 0x82),SCE(0x0450, 1, 0x42),
+SCE(0x0401, 0, 0x82),SCE(0x0451, 1, 0x42),SCE(0x0402, 0, 0x82),SCE(0x0452, 1, 0x42),
+SCE(0x0403, 0, 0x82),SCE(0x0453, 1, 0x42),SCE(0x0404, 0, 0x82),SCE(0x0454, 1, 0x42),
+SCE(0x0405, 0, 0x82),SCE(0x0455, 1, 0x42),SCE(0x0406, 0, 0x82),SCE(0x0456, 1, 0x42),
+SCE(0x0407, 0, 0x82),SCE(0x0457, 1, 0x42),SCE(0x0408, 0, 0x82),SCE(0x0458, 1, 0x42),
+SCE(0x0409, 0, 0x82),SCE(0x0459, 1, 0x42),SCE(0x040a, 0, 0x82),SCE(0x045a, 1, 0x42),
+SCE(0x040b, 0, 0x82),SCE(0x045b, 1, 0x42),SCE(0x040c, 0, 0x82),SCE(0x045c, 1, 0x42),
+SCE(0x040d, 0, 0x82),SCE(0x045d, 1, 0x42),SCE(0x040e, 0, 0x82),SCE(0x045e, 1, 0x42),
+SCE(0x040f, 0, 0x82),SCE(0x045f, 1, 0x42),SCE(0x0410, 0, 0x82),SCE(0x0430, 1, 0x42),
+SCE(0x0411, 0, 0x82),SCE(0x0431, 1, 0x42),SCE(0x0412, 0, 0x82),SCE(0x0432, 1, 0x42),
+SCE(0x0413, 0, 0x82),SCE(0x0433, 1, 0x42),SCE(0x0414, 0, 0x82),SCE(0x0434, 1, 0x42),
+SCE(0x0415, 0, 0x82),SCE(0x0435, 1, 0x42),SCE(0x0416, 0, 0x82),SCE(0x0436, 1, 0x42),
+SCE(0x0417, 0, 0x82),SCE(0x0437, 1, 0x42),SCE(0x0418, 0, 0x82),SCE(0x0438, 1, 0x42),
+SCE(0x0419, 0, 0x82),SCE(0x0439, 1, 0x42),SCE(0x041a, 0, 0x82),SCE(0x043a, 1, 0x42),
+SCE(0x041b, 0, 0x82),SCE(0x043b, 1, 0x42),SCE(0x041c, 0, 0x82),SCE(0x043c, 1, 0x42),
+SCE(0x041d, 0, 0x82),SCE(0x043d, 1, 0x42),SCE(0x041e, 0, 0x82),SCE(0x043e, 1, 0x42),
+SCE(0x041f, 0, 0x82),SCE(0x043f, 1, 0x42),SCE(0x0420, 0, 0x82),SCE(0x0440, 1, 0x42),
+SCE(0x0421, 0, 0x82),SCE(0x0441, 1, 0x42),SCE(0x0422, 0, 0x82),SCE(0x0442, 1, 0x42),
+SCE(0x0423, 0, 0x82),SCE(0x0443, 1, 0x42),SCE(0x0424, 0, 0x82),SCE(0x0444, 1, 0x42),
+SCE(0x0425, 0, 0x82),SCE(0x0445, 1, 0x42),SCE(0x0426, 0, 0x82),SCE(0x0446, 1, 0x42),
+SCE(0x0427, 0, 0x82),SCE(0x0447, 1, 0x42),SCE(0x0428, 0, 0x82),SCE(0x0448, 1, 0x42),
+SCE(0x0429, 0, 0x82),SCE(0x0449, 1, 0x42),SCE(0x042a, 0, 0x82),SCE(0x044a, 1, 0x42),
+SCE(0x042b, 0, 0x82),SCE(0x044b, 1, 0x42),SCE(0x042c, 0, 0x82),SCE(0x044c, 1, 0x42),
+SCE(0x042d, 0, 0x82),SCE(0x044d, 1, 0x42),SCE(0x042e, 0, 0x82),SCE(0x044e, 1, 0x42),
+SCE(0x042f, 0, 0x82),SCE(0x044f, 1, 0x42),SCE(0xff3a, 0, 0x82),SCE(0xff5a, 1, 0x42),
+SCE(0x2cb4, 0, 0x82),SCE(0x2cb5, 1, 0x42),SCE(0x00b5, 0, 0x43),SCE(0x039c, 1, 0x83),
+SCE(0x03bc, 2, 0x43),SCE(0x10423, 0, 0x82),SCE(0x1044b, 1, 0x42),SCE(0x24b6, 0, 0x82),
+SCE(0x24d0, 1, 0x42),SCE(0x24b8, 0, 0x82),SCE(0x24d2, 1, 0x42),SCE(0xff2c, 0, 0x82),
+SCE(0xff4c, 1, 0x42),SCE(0x10421, 0, 0x82),SCE(0x10449, 1, 0x42),SCE(0x24ba, 0, 0x82),
+SCE(0x24d4, 1, 0x42),SCE(0x10424, 0, 0x82),SCE(0x1044c, 1, 0x42),SCE(0x0460, 0, 0x82),
+SCE(0x0461, 1, 0x42),SCE(0x0462, 0, 0x82),SCE(0x0463, 1, 0x42),SCE(0x1d7d, 0, 0x42),
+SCE(0x2c63, 1, 0x82),SCE(0x0464, 0, 0x82),SCE(0x0465, 1, 0x42),SCE(0x0466, 0, 0x82),
+SCE(0x0467, 1, 0x42),SCE(0x2c67, 0, 0x82),SCE(0x2c68, 1, 0x42),SCE(0x0468, 0, 0x82),
+SCE(0x0469, 1, 0x42),SCE(0x24bc, 0, 0x82),SCE(0x24d6, 1, 0x42),SCE(0x046a, 0, 0x82),
+SCE(0x046b, 1, 0x42),SCE(0x2c6b, 0, 0x82),SCE(0x2c6c, 1, 0x42),SCE(0x046c, 0, 0x82),
+SCE(0x046d, 1, 0x42),SCE(0x0251, 0, 0x42),SCE(0x2c6d, 1, 0x82),SCE(0x046e, 0, 0x82),
+SCE(0x046f, 1, 0x42),SCE(0x0250, 0, 0x42),SCE(0x2c6f, 1, 0x82),SCE(0x0470, 0, 0x82),
+SCE(0x0471, 1, 0x42),SCE(0xa768, 0, 0x82),SCE(0xa769, 1, 0x42),SCE(0x0472, 0, 0x82),
+SCE(0x0473, 1, 0x42),SCE(0x0474, 0, 0x82),SCE(0x0475, 1, 0x42),SCE(0x24be, 0, 0x82),
+SCE(0x24d8, 1, 0x42),SCE(0x0476, 0, 0x82),SCE(0x0477, 1, 0x42),SCE(0x0478, 0, 0x82),
+SCE(0x0479, 1, 0x42),SCE(0x047a, 0, 0x82),SCE(0x047b, 1, 0x42),SCE(0x047c, 0, 0x82),
+SCE(0x047d, 1, 0x42),SCE(0xa76a, 0, 0x82),SCE(0xa76b, 1, 0x42),SCE(0x047e, 0, 0x82),
+SCE(0x047f, 1, 0x42),SCE(0x0240, 0, 0x42),SCE(0x2c7f, 1, 0x82),SCE(0x0480, 0, 0x82),
+SCE(0x0481, 1, 0x42),SCE(0x10c0, 0, 0x82),SCE(0x2d20, 1, 0x42),SCE(0x2c82, 0, 0x82),
+SCE(0x2c83, 1, 0x42),SCE(0x2c84, 0, 0x82),SCE(0x2c85, 1, 0x42),SCE(0x2c86, 0, 0x82),
+SCE(0x2c87, 1, 0x42),SCE(0x10c1, 0, 0x82),SCE(0x2d21, 1, 0x42),SCE(0x2c88, 0, 0x82),
+SCE(0x2c89, 1, 0x42),SCE(0xa76c, 0, 0x82),SCE(0xa76d, 1, 0x42),SCE(0x048a, 0, 0x82),
+SCE(0x048b, 1, 0x42),SCE(0x048c, 0, 0x82),SCE(0x048d, 1, 0x42),SCE(0x00c2, 0, 0x82),
+SCE(0x00e2, 1, 0x42),SCE(0x048e, 0, 0x82),SCE(0x048f, 1, 0x42),SCE(0x0490, 0, 0x82),
+SCE(0x0491, 1, 0x42),SCE(0x0492, 0, 0x82),SCE(0x0493, 1, 0x42),SCE(0x10c3, 0, 0x82),
+SCE(0x2d23, 1, 0x42),SCE(0x0494, 0, 0x82),SCE(0x0495, 1, 0x42),SCE(0xa76e, 0, 0x82),
+SCE(0xa76f, 1, 0x42),SCE(0x0496, 0, 0x82),SCE(0x0497, 1, 0x42),SCE(0x0498, 0, 0x82),
+SCE(0x0499, 1, 0x42),SCE(0x00c4, 0, 0x82),SCE(0x00e4, 1, 0x42),SCE(0x049a, 0, 0x82),
+SCE(0x049b, 1, 0x42),SCE(0x10426, 0, 0x82),SCE(0x1044e, 1, 0x42),SCE(0x049c, 0, 0x82),
+SCE(0x049d, 1, 0x42),SCE(0x049e, 0, 0x82),SCE(0x049f, 1, 0x42),SCE(0x10c5, 0, 0x82),
+SCE(0x2d25, 1, 0x42),SCE(0x04a0, 0, 0x82),SCE(0x04a1, 1, 0x42),SCE(0x04a2, 0, 0x82),
+SCE(0x04a3, 1, 0x42),SCE(0x04a4, 0, 0x82),SCE(0x04a5, 1, 0x42),SCE(0x2cc6, 0, 0x82),
+SCE(0x2cc7, 1, 0x42),SCE(0x04a6, 0, 0x82),SCE(0x04a7, 1, 0x42),SCE(0x04a8, 0, 0x82),
+SCE(0x04a9, 1, 0x42),SCE(0x2c60, 0, 0x82),SCE(0x2c61, 1, 0x42),SCE(0x04aa, 0, 0x82),
+SCE(0x04ab, 1, 0x42),SCE(0x10c7, 0, 0x82),SCE(0x2d27, 1, 0x42),SCE(0x04ac, 0, 0x82),
+SCE(0x04ad, 1, 0x42),SCE(0x10413, 0, 0x82),SCE(0x1043b, 1, 0x42),SCE(0x04ae, 0, 0x82),
+SCE(0x04af, 1, 0x42),SCE(0x04b0, 0, 0x82),SCE(0x04b1, 1, 0x42),SCE(0x2cc8, 0, 0x82),
+SCE(0x2cc9, 1, 0x42),SCE(0x04b2, 0, 0x82),SCE(0x04b3, 1, 0x42),SCE(0x04b4, 0, 0x82),
+SCE(0x04b5, 1, 0x42),SCE(0x04b6, 0, 0x82),SCE(0x04b7, 1, 0x42),SCE(0x24b7, 0, 0x82),
+SCE(0x24d1, 1, 0x42),SCE(0x04b8, 0, 0x82),SCE(0x04b9, 1, 0x42),SCE(0x24b9, 0, 0x82),
+SCE(0x24d3, 1, 0x42),SCE(0x04ba, 0, 0x82),SCE(0x04bb, 1, 0x42),SCE(0x24bb, 0, 0x82),
+SCE(0x24d5, 1, 0x42),SCE(0x04bc, 0, 0x82),SCE(0x04bd, 1, 0x42),SCE(0x24bd, 0, 0x82),
+SCE(0x24d7, 1, 0x42),SCE(0x04be, 0, 0x82),SCE(0x04bf, 1, 0x42),SCE(0x24bf, 0, 0x82),
+SCE(0x24d9, 1, 0x42),SCE(0x04c0, 0, 0x82),SCE(0x04cf, 1, 0x42),SCE(0x04c1, 0, 0x82),
+SCE(0x04c2, 1, 0x42),SCE(0x24c2, 0, 0x82),SCE(0x24dc, 1, 0x42),SCE(0x04c3, 0, 0x82),
+SCE(0x04c4, 1, 0x42),SCE(0x24c4, 0, 0x82),SCE(0x24de, 1, 0x42),SCE(0x04c5, 0, 0x82),
+SCE(0x04c6, 1, 0x42),SCE(0x24c6, 0, 0x82),SCE(0x24e0, 1, 0x42),SCE(0x04c7, 0, 0x82),
+SCE(0x04c8, 1, 0x42),SCE(0x24c8, 0, 0x82),SCE(0x24e2, 1, 0x42),SCE(0x04c9, 0, 0x82),
+SCE(0x04ca, 1, 0x42),SCE(0x24ca, 0, 0x82),SCE(0x24e4, 1, 0x42),SCE(0x04cb, 0, 0x82),
+SCE(0x04cc, 1, 0x42),SCE(0x24cc, 0, 0x82),SCE(0x24e6, 1, 0x42),SCE(0x04cd, 0, 0x82),
+SCE(0x04ce, 1, 0x42),SCE(0x24ce, 0, 0x82),SCE(0x24e8, 1, 0x42),SCE(0x10cd, 0, 0x82),
+SCE(0x2d2d, 1, 0x42),SCE(0x04d0, 0, 0x82),SCE(0x04d1, 1, 0x42),SCE(0x04d2, 0, 0x82),
+SCE(0x04d3, 1, 0x42),SCE(0x04d4, 0, 0x82),SCE(0x04d5, 1, 0x42),SCE(0x2cce, 0, 0x82),
+SCE(0x2ccf, 1, 0x42),SCE(0x04d6, 0, 0x82),SCE(0x04d7, 1, 0x42),SCE(0xa779, 0, 0x82),
+SCE(0xa77a, 1, 0x42),SCE(0x04d8, 0, 0x82),SCE(0x04d9, 1, 0x42),SCE(0x04da, 0, 0x82),
+SCE(0x04db, 1, 0x42),SCE(0x24cf, 0, 0x82),SCE(0x24e9, 1, 0x42),SCE(0x04dc, 0, 0x82),
+SCE(0x04dd, 1, 0x42),SCE(0x04de, 0, 0x82),SCE(0x04df, 1, 0x42),SCE(0x04e0, 0, 0x82),
+SCE(0x04e1, 1, 0x42),SCE(0x2cd0, 0, 0x82),SCE(0x2cd1, 1, 0x42),SCE(0x04e2, 0, 0x82),
+SCE(0x04e3, 1, 0x42),SCE(0x04e4, 0, 0x82),SCE(0x04e5, 1, 0x42),SCE(0x026b, 0, 0x42),
+SCE(0x2c62, 1, 0x82),SCE(0x04e6, 0, 0x82),SCE(0x04e7, 1, 0x42),SCE(0x04e8, 0, 0x82),
+SCE(0x04e9, 1, 0x42),SCE(0x04ea, 0, 0x82),SCE(0x04eb, 1, 0x42),SCE(0x2132, 0, 0x82),
+SCE(0x214e, 1, 0x42),SCE(0x04ec, 0, 0x82),SCE(0x04ed, 1, 0x42),SCE(0x2cd2, 0, 0x82),
+SCE(0x2cd3, 1, 0x42),SCE(0x04ee, 0, 0x82),SCE(0x04ef, 1, 0x42),SCE(0x04f0, 0, 0x82),
+SCE(0x04f1, 1, 0x42),SCE(0x10422, 0, 0x82),SCE(0x1044a, 1, 0x42),SCE(0x04f2, 0, 0x82),
+SCE(0x04f3, 1, 0x42),SCE(0x04f4, 0, 0x82),SCE(0x04f5, 1, 0x42),SCE(0x04f6, 0, 0x82),
+SCE(0x04f7, 1, 0x42),SCE(0x04f8, 0, 0x82),SCE(0x04f9, 1, 0x42),SCE(0x2cd4, 0, 0x82),
+SCE(0x2cd5, 1, 0x42),SCE(0x04fa, 0, 0x82),SCE(0x04fb, 1, 0x42),SCE(0x04fc, 0, 0x82),
+SCE(0x04fd, 1, 0x42),SCE(0x04fe, 0, 0x82),SCE(0x04ff, 1, 0x42),SCE(0x0500, 0, 0x82),
+SCE(0x0501, 1, 0x42),SCE(0x0502, 0, 0x82),SCE(0x0503, 1, 0x42),SCE(0x0504, 0, 0x82),
+SCE(0x0505, 1, 0x42),SCE(0x2cd6, 0, 0x82),SCE(0x2cd7, 1, 0x42),SCE(0x0506, 0, 0x82),
+SCE(0x0507, 1, 0x42),SCE(0x0508, 0, 0x82),SCE(0x0509, 1, 0x42),SCE(0x050a, 0, 0x82),
+SCE(0x050b, 1, 0x42),SCE(0x050c, 0, 0x82),SCE(0x050d, 1, 0x42),SCE(0x050e, 0, 0x82),
+SCE(0x050f, 1, 0x42),SCE(0x0510, 0, 0x82),SCE(0x0511, 1, 0x42),SCE(0x2cd8, 0, 0x82),
+SCE(0x2cd9, 1, 0x42),SCE(0x0512, 0, 0x82),SCE(0x0513, 1, 0x42),SCE(0x0514, 0, 0x82),
+SCE(0x0515, 1, 0x42),SCE(0x0516, 0, 0x82),SCE(0x0517, 1, 0x42),SCE(0x0518, 0, 0x82),
+SCE(0x0519, 1, 0x42),SCE(0x051a, 0, 0x82),SCE(0x051b, 1, 0x42),SCE(0x2ca8, 0, 0x82),
+SCE(0x2ca9, 1, 0x42),SCE(0x051c, 0, 0x82),SCE(0x051d, 1, 0x42),SCE(0x2cda, 0, 0x82),
+SCE(0x2cdb, 1, 0x42),SCE(0x051e, 0, 0x82),SCE(0x051f, 1, 0x42),SCE(0x0520, 0, 0x82),
+SCE(0x0521, 1, 0x42),SCE(0x0522, 0, 0x82),SCE(0x0523, 1, 0x42),SCE(0x0524, 0, 0x82),
+SCE(0x0525, 1, 0x42),SCE(0x0526, 0, 0x82),SCE(0x0527, 1, 0x42),SCE(0x2c20, 0, 0x82),
+SCE(0x2c50, 1, 0x42),SCE(0x2cdc, 0, 0x82),SCE(0x2cdd, 1, 0x42),SCE(0x0531, 0, 0x82),
+SCE(0x0561, 1, 0x42),SCE(0x0532, 0, 0x82),SCE(0x0562, 1, 0x42),SCE(0x0533, 0, 0x82),
+SCE(0x0563, 1, 0x42),SCE(0x0534, 0, 0x82),SCE(0x0564, 1, 0x42),SCE(0x0535, 0, 0x82),
+SCE(0x0565, 1, 0x42),SCE(0x0536, 0, 0x82),SCE(0x0566, 1, 0x42),SCE(0x0537, 0, 0x82),
+SCE(0x0567, 1, 0x42),SCE(0x0538, 0, 0x82),SCE(0x0568, 1, 0x42),SCE(0x0539, 0, 0x82),
+SCE(0x0569, 1, 0x42),SCE(0x053a, 0, 0x82),SCE(0x056a, 1, 0x42),SCE(0x053b, 0, 0x82),
+SCE(0x056b, 1, 0x42),SCE(0x053c, 0, 0x82),SCE(0x056c, 1, 0x42),SCE(0x053d, 0, 0x82),
+SCE(0x056d, 1, 0x42),SCE(0x053e, 0, 0x82),SCE(0x056e, 1, 0x42),SCE(0x053f, 0, 0x82),
+SCE(0x056f, 1, 0x42),SCE(0x0540, 0, 0x82),SCE(0x0570, 1, 0x42),SCE(0x0541, 0, 0x82),
+SCE(0x0571, 1, 0x42),SCE(0x0542, 0, 0x82),SCE(0x0572, 1, 0x42),SCE(0x0543, 0, 0x82),
+SCE(0x0573, 1, 0x42),SCE(0x0544, 0, 0x82),SCE(0x0574, 1, 0x42),SCE(0x0545, 0, 0x82),
+SCE(0x0575, 1, 0x42),SCE(0x0546, 0, 0x82),SCE(0x0576, 1, 0x42),SCE(0x0547, 0, 0x82),
+SCE(0x0577, 1, 0x42),SCE(0x0548, 0, 0x82),SCE(0x0578, 1, 0x42),SCE(0x0549, 0, 0x82),
+SCE(0x0579, 1, 0x42),SCE(0x054a, 0, 0x82),SCE(0x057a, 1, 0x42),SCE(0x054b, 0, 0x82),
+SCE(0x057b, 1, 0x42),SCE(0x054c, 0, 0x82),SCE(0x057c, 1, 0x42),SCE(0x054d, 0, 0x82),
+SCE(0x057d, 1, 0x42),SCE(0x054e, 0, 0x82),SCE(0x057e, 1, 0x42),SCE(0x054f, 0, 0x82),
+SCE(0x057f, 1, 0x42),SCE(0x0550, 0, 0x82),SCE(0x0580, 1, 0x42),SCE(0x0551, 0, 0x82),
+SCE(0x0581, 1, 0x42),SCE(0x0552, 0, 0x82),SCE(0x0582, 1, 0x42),SCE(0x0553, 0, 0x82),
+SCE(0x0583, 1, 0x42),SCE(0x0554, 0, 0x82),SCE(0x0584, 1, 0x42),SCE(0x0555, 0, 0x82),
+SCE(0x0585, 1, 0x42),SCE(0x0556, 0, 0x82),SCE(0x0586, 1, 0x42),SCE(0x2caa, 0, 0x82),
+SCE(0x2cab, 1, 0x42),SCE(0x2c22, 0, 0x82),SCE(0x2c52, 1, 0x42),SCE(0x2c23, 0, 0x82),
+SCE(0x2c53, 1, 0x42),SCE(0x2ceb, 0, 0x82),SCE(0x2cec, 1, 0x42),SCE(0x2cca, 0, 0x82),
+SCE(0x2ccb, 1, 0x42),SCE(0xa642, 0, 0x82),SCE(0xa643, 1, 0x42),SCE(0x2ced, 0, 0x82),
+SCE(0x2cee, 1, 0x42),SCE(0x2cac, 0, 0x82),SCE(0x2cad, 1, 0x42),SCE(0xa644, 0, 0x82),
+SCE(0xa645, 1, 0x42),SCE(0x2c24, 0, 0x82),SCE(0x2c54, 1, 0x42),SCE(0xa646, 0, 0x82),
+SCE(0xa647, 1, 0x42),SCE(0x2cf2, 0, 0x82),SCE(0x2cf3, 1, 0x42),SCE(0x10408, 0, 0x82),
+SCE(0x10430, 1, 0x42),SCE(0xa648, 0, 0x82),SCE(0xa649, 1, 0x42),SCE(0xa64a, 0, 0x82),
+SCE(0xa64b, 1, 0x42),SCE(0xa64c, 0, 0x82),SCE(0xa64d, 1, 0x42),SCE(0x2cae, 0, 0x82),
+SCE(0x2caf, 1, 0x42),SCE(0xa64e, 0, 0x82),SCE(0xa64f, 1, 0x42),SCE(0xa650, 0, 0x82),
+SCE(0xa651, 1, 0x42),SCE(0xa78b, 0, 0x82),SCE(0xa78c, 1, 0x42),SCE(0xa652, 0, 0x82),
+SCE(0xa653, 1, 0x42),SCE(0xa7a8, 0, 0x82),SCE(0xa7a9, 1, 0x42),SCE(0xa654, 0, 0x82),
+SCE(0xa655, 1, 0x42),SCE(0x0266, 0, 0x42),SCE(0xa7aa, 1, 0x82),SCE(0x1e00, 0, 0x82),
+SCE(0x1e01, 1, 0x42),SCE(0x1e02, 0, 0x82),SCE(0x1e03, 1, 0x42),SCE(0x1e04, 0, 0x82),
+SCE(0x1e05, 1, 0x42),SCE(0x2c1f, 0, 0x82),SCE(0x2c4f, 1, 0x42),SCE(0x1e06, 0, 0x82),
+SCE(0x1e07, 1, 0x42),SCE(0x1040e, 0, 0x82),SCE(0x10436, 1, 0x42),SCE(0x1e08, 0, 0x82),
+SCE(0x1e09, 1, 0x42),SCE(0x1e0a, 0, 0x82),SCE(0x1e0b, 1, 0x42),SCE(0x2cb0, 0, 0x82),
+SCE(0x2cb1, 1, 0x42),SCE(0x1e0c, 0, 0x82),SCE(0x1e0d, 1, 0x42),SCE(0x1e0e, 0, 0x82),
+SCE(0x1e0f, 1, 0x42),SCE(0x1e10, 0, 0x82),SCE(0x1e11, 1, 0x42),SCE(0xa658, 0, 0x82),
+SCE(0xa659, 1, 0x42),SCE(0x1e12, 0, 0x82),SCE(0x1e13, 1, 0x42),SCE(0x1e14, 0, 0x82),
+SCE(0x1e15, 1, 0x42),SCE(0x24cd, 0, 0x82),SCE(0x24e7, 1, 0x42),SCE(0x1e16, 0, 0x82),
+SCE(0x1e17, 1, 0x42),SCE(0x1e18, 0, 0x82),SCE(0x1e19, 1, 0x42),SCE(0x1e1a, 0, 0x82),
+SCE(0x1e1b, 1, 0x42),SCE(0x1e1c, 0, 0x82),SCE(0x1e1d, 1, 0x42),SCE(0xa65a, 0, 0x82),
+SCE(0xa65b, 1, 0x42),SCE(0x1e1e, 0, 0x82),SCE(0x1e1f, 1, 0x42),SCE(0x1e20, 0, 0x82),
+SCE(0x1e21, 1, 0x42),SCE(0x1e22, 0, 0x82),SCE(0x1e23, 1, 0x42),SCE(0x1e24, 0, 0x82),
+SCE(0x1e25, 1, 0x42),SCE(0x1e26, 0, 0x82),SCE(0x1e27, 1, 0x42),SCE(0x1e28, 0, 0x82),
+SCE(0x1e29, 1, 0x42),SCE(0xa65c, 0, 0x82),SCE(0xa65d, 1, 0x42),SCE(0x1e2a, 0, 0x82),
+SCE(0x1e2b, 1, 0x42),SCE(0x1e2c, 0, 0x82),SCE(0x1e2d, 1, 0x42),SCE(0x1e2e, 0, 0x82),
+SCE(0x1e2f, 1, 0x42),SCE(0x1e30, 0, 0x82),SCE(0x1e31, 1, 0x42),SCE(0x1e32, 0, 0x82),
+SCE(0x1e33, 1, 0x42),SCE(0x1e34, 0, 0x82),SCE(0x1e35, 1, 0x42),SCE(0xa65e, 0, 0x82),
+SCE(0xa65f, 1, 0x42),SCE(0x1e36, 0, 0x82),SCE(0x1e37, 1, 0x42),SCE(0x1e38, 0, 0x82),
+SCE(0x1e39, 1, 0x42),SCE(0x1e3a, 0, 0x82),SCE(0x1e3b, 1, 0x42),SCE(0x1e3c, 0, 0x82),
+SCE(0x1e3d, 1, 0x42),SCE(0x1e3e, 0, 0x82),SCE(0x1e3f, 1, 0x42),SCE(0x1e40, 0, 0x82),
+SCE(0x1e41, 1, 0x42),SCE(0xa660, 0, 0x82),SCE(0xa661, 1, 0x42),SCE(0x1e42, 0, 0x82),
+SCE(0x1e43, 1, 0x42),SCE(0x1e44, 0, 0x82),SCE(0x1e45, 1, 0x42),SCE(0x1e46, 0, 0x82),
+SCE(0x1e47, 1, 0x42),SCE(0x2cb2, 0, 0x82),SCE(0x2cb3, 1, 0x42),SCE(0x1e48, 0, 0x82),
+SCE(0x1e49, 1, 0x42),SCE(0x2cc0, 0, 0x82),SCE(0x2cc1, 1, 0x42),SCE(0x1e4a, 0, 0x82),
+SCE(0x1e4b, 1, 0x42),SCE(0x1e4c, 0, 0x82),SCE(0x1e4d, 1, 0x42),SCE(0xa662, 0, 0x82),
+SCE(0xa663, 1, 0x42),SCE(0x1e4e, 0, 0x82),SCE(0x1e4f, 1, 0x42),SCE(0x1e50, 0, 0x82),
+SCE(0x1e51, 1, 0x42),SCE(0x1e52, 0, 0x82),SCE(0x1e53, 1, 0x42),SCE(0x1e54, 0, 0x82),
+SCE(0x1e55, 1, 0x42),SCE(0x1e56, 0, 0x82),SCE(0x1e57, 1, 0x42),SCE(0x1e58, 0, 0x82),
+SCE(0x1e59, 1, 0x42),SCE(0xa664, 0, 0x82),SCE(0xa665, 1, 0x42),SCE(0x1e5a, 0, 0x82),
+SCE(0x1e5b, 1, 0x42),SCE(0x1e5c, 0, 0x82),SCE(0x1e5d, 1, 0x42),SCE(0x1e5e, 0, 0x82),
+SCE(0x1e5f, 1, 0x42),SCE(0x1e60, 0, 0x83),SCE(0x1e61, 1, 0x43),SCE(0x1e9b, 2, 0x43),
+SCE(0x1e62, 0, 0x82),SCE(0x1e63, 1, 0x42),SCE(0x1e64, 0, 0x82),SCE(0x1e65, 1, 0x42),
+SCE(0xa666, 0, 0x82),SCE(0xa667, 1, 0x42),SCE(0x1e66, 0, 0x82),SCE(0x1e67, 1, 0x42),
+SCE(0x1e68, 0, 0x82),SCE(0x1e69, 1, 0x42),SCE(0x1e6a, 0, 0x82),SCE(0x1e6b, 1, 0x42),
+SCE(0x1e6c, 0, 0x82),SCE(0x1e6d, 1, 0x42),SCE(0x1e6e, 0, 0x82),SCE(0x1e6f, 1, 0x42),
+SCE(0x1e70, 0, 0x82),SCE(0x1e71, 1, 0x42),SCE(0xa668, 0, 0x82),SCE(0xa669, 1, 0x42),
+SCE(0x1e72, 0, 0x82),SCE(0x1e73, 1, 0x42),SCE(0x1e74, 0, 0x82),SCE(0x1e75, 1, 0x42),
+SCE(0x1e76, 0, 0x82),SCE(0x1e77, 1, 0x42),SCE(0x2cbe, 0, 0x82),SCE(0x2cbf, 1, 0x42),
+SCE(0x1e78, 0, 0x82),SCE(0x1e79, 1, 0x42),SCE(0x1e7a, 0, 0x82),SCE(0x1e7b, 1, 0x42),
+SCE(0x1e7c, 0, 0x82),SCE(0x1e7d, 1, 0x42),SCE(0xa66a, 0, 0x82),SCE(0xa66b, 1, 0x42),
+SCE(0x1e7e, 0, 0x82),SCE(0x1e7f, 1, 0x42),SCE(0x1e80, 0, 0x82),SCE(0x1e81, 1, 0x42),
+SCE(0x1e82, 0, 0x82),SCE(0x1e83, 1, 0x42),SCE(0x1e84, 0, 0x82),SCE(0x1e85, 1, 0x42),
+SCE(0x1e86, 0, 0x82),SCE(0x1e87, 1, 0x42),SCE(0x1e88, 0, 0x82),SCE(0x1e89, 1, 0x42),
+SCE(0xa66c, 0, 0x82),SCE(0xa66d, 1, 0x42),SCE(0x1e8a, 0, 0x82),SCE(0x1e8b, 1, 0x42),
+SCE(0x1e8c, 0, 0x82),SCE(0x1e8d, 1, 0x42),SCE(0x1e8e, 0, 0x82),SCE(0x1e8f, 1, 0x42),
+SCE(0x1e90, 0, 0x82),SCE(0x1e91, 1, 0x42),SCE(0x1e92, 0, 0x82),SCE(0x1e93, 1, 0x42),
+SCE(0x1e94, 0, 0x82),SCE(0x1e95, 1, 0x42),SCE(0xa696, 0, 0x82),SCE(0xa697, 1, 0x42),
+SCE(0x10406, 0, 0x82),SCE(0x1042e, 1, 0x42),SCE(0x1e60, 0, 0x83),SCE(0x1e61, 1, 0x43),
+SCE(0x1e9b, 2, 0x43),SCE(0x00df, 0, 0x42),SCE(0x1e9e, 1, 0x82),SCE(0x1ea0, 0, 0x82),
+SCE(0x1ea1, 1, 0x42),SCE(0x1ea2, 0, 0x82),SCE(0x1ea3, 1, 0x42),SCE(0x1ea4, 0, 0x82),
+SCE(0x1ea5, 1, 0x42),SCE(0x24c5, 0, 0x82),SCE(0x24df, 1, 0x42),SCE(0x1ea6, 0, 0x82),
+SCE(0x1ea7, 1, 0x42),SCE(0x1ea8, 0, 0x82),SCE(0x1ea9, 1, 0x42),SCE(0x1eaa, 0, 0x82),
+SCE(0x1eab, 1, 0x42),SCE(0x1eac, 0, 0x82),SCE(0x1ead, 1, 0x42),SCE(0x1eae, 0, 0x82),
+SCE(0x1eaf, 1, 0x42),SCE(0xff28, 0, 0x82),SCE(0xff48, 1, 0x42),SCE(0x1eb0, 0, 0x82),
+SCE(0x1eb1, 1, 0x42),SCE(0x1eb2, 0, 0x82),SCE(0x1eb3, 1, 0x42),SCE(0x10425, 0, 0x82),
+SCE(0x1044d, 1, 0x42),SCE(0x1eb4, 0, 0x82),SCE(0x1eb5, 1, 0x42),SCE(0x1eb6, 0, 0x82),
+SCE(0x1eb7, 1, 0x42),SCE(0x1eb8, 0, 0x82),SCE(0x1eb9, 1, 0x42),SCE(0x1eba, 0, 0x82),
+SCE(0x1ebb, 1, 0x42),SCE(0x1ebc, 0, 0x82),SCE(0x1ebd, 1, 0x42),SCE(0x1ebe, 0, 0x82),
+SCE(0x1ebf, 1, 0x42),SCE(0x2cb6, 0, 0x82),SCE(0x2cb7, 1, 0x42),SCE(0x1ec0, 0, 0x82),
+SCE(0x1ec1, 1, 0x42),SCE(0x1ec2, 0, 0x82),SCE(0x1ec3, 1, 0x42),SCE(0x2c9a, 0, 0x82),
+SCE(0x2c9b, 1, 0x42),SCE(0x1ec4, 0, 0x82),SCE(0x1ec5, 1, 0x42),SCE(0x1ec6, 0, 0x82),
+SCE(0x1ec7, 1, 0x42),SCE(0x1ec8, 0, 0x82),SCE(0x1ec9, 1, 0x42),SCE(0x1eca, 0, 0x82),
+SCE(0x1ecb, 1, 0x42),SCE(0x1ecc, 0, 0x82),SCE(0x1ecd, 1, 0x42),SCE(0x1ece, 0, 0x82),
+SCE(0x1ecf, 1, 0x42),SCE(0x1ed0, 0, 0x82),SCE(0x1ed1, 1, 0x42),SCE(0x1ed2, 0, 0x82),
+SCE(0x1ed3, 1, 0x42),SCE(0x1ed4, 0, 0x82),SCE(0x1ed5, 1, 0x42),SCE(0x1ed6, 0, 0x82),
+SCE(0x1ed7, 1, 0x42),SCE(0x1ed8, 0, 0x82),SCE(0x1ed9, 1, 0x42),SCE(0x1eda, 0, 0x82),
+SCE(0x1edb, 1, 0x42),SCE(0x1edc, 0, 0x82),SCE(0x1edd, 1, 0x42),SCE(0x1ede, 0, 0x82),
+SCE(0x1edf, 1, 0x42),SCE(0x1ee0, 0, 0x82),SCE(0x1ee1, 1, 0x42),SCE(0x1ee2, 0, 0x82),
+SCE(0x1ee3, 1, 0x42),SCE(0x1ee4, 0, 0x82),SCE(0x1ee5, 1, 0x42),SCE(0x03a9, 0, 0x83),
+SCE(0x03c9, 1, 0x43),SCE(0x2126, 2, 0x83),SCE(0x1ee6, 0, 0x82),SCE(0x1ee7, 1, 0x42),
+SCE(0x1ee8, 0, 0x82),SCE(0x1ee9, 1, 0x42),SCE(0x1eea, 0, 0x82),SCE(0x1eeb, 1, 0x42),
+SCE(0xff2a, 0, 0x82),SCE(0xff4a, 1, 0x42),SCE(0x1eec, 0, 0x82),SCE(0x1eed, 1, 0x42),
+SCE(0x1eee, 0, 0x82),SCE(0x1eef, 1, 0x42),SCE(0x1ef0, 0, 0x82),SCE(0x1ef1, 1, 0x42),
+SCE(0x1ef2, 0, 0x82),SCE(0x1ef3, 1, 0x42),SCE(0x1ef4, 0, 0x82),SCE(0x1ef5, 1, 0x42),
+SCE(0x1ef6, 0, 0x82),SCE(0x1ef7, 1, 0x42),SCE(0x1ef8, 0, 0x82),SCE(0x1ef9, 1, 0x42),
+SCE(0x1efa, 0, 0x82),SCE(0x1efb, 1, 0x42),SCE(0x2cb8, 0, 0x82),SCE(0x2cb9, 1, 0x42),
+SCE(0x1efc, 0, 0x82),SCE(0x1efd, 1, 0x42),SCE(0x004b, 0, 0x83),SCE(0x006b, 1, 0x43),
+SCE(0x212a, 2, 0x83),SCE(0x1efe, 0, 0x82),SCE(0x1eff, 1, 0x42),SCE(0xa680, 0, 0x82),
+SCE(0xa681, 1, 0x42),SCE(0x1f00, 0, 0x42),SCE(0x1f08, 1, 0x82),SCE(0x1f01, 0, 0x42),
+SCE(0x1f09, 1, 0x82),SCE(0x1f02, 0, 0x42),SCE(0x1f0a, 1, 0x82),SCE(0x1f03, 0, 0x42),
+SCE(0x1f0b, 1, 0x82),SCE(0x1f04, 0, 0x42),SCE(0x1f0c, 1, 0x82),SCE(0x1f05, 0, 0x42),
+SCE(0x1f0d, 1, 0x82),SCE(0x1f06, 0, 0x42),SCE(0x1f0e, 1, 0x82),SCE(0x1f07, 0, 0x42),
+SCE(0x1f0f, 1, 0x82),SCE(0x10418, 0, 0x82),SCE(0x10440, 1, 0x42),SCE(0x0265, 0, 0x42),
+SCE(0xa78d, 1, 0x82),SCE(0x1f10, 0, 0x42),SCE(0x1f18, 1, 0x82),SCE(0x1f11, 0, 0x42),
+SCE(0x1f19, 1, 0x82),SCE(0x1f12, 0, 0x42),SCE(0x1f1a, 1, 0x82),SCE(0x1f13, 0, 0x42),
+SCE(0x1f1b, 1, 0x82),SCE(0x1f14, 0, 0x42),SCE(0x1f1c, 1, 0x82),SCE(0x1f15, 0, 0x42),
+SCE(0x1f1d, 1, 0x82),SCE(0xff21, 0, 0x82),SCE(0xff41, 1, 0x42),SCE(0xa722, 0, 0x82),
+SCE(0xa723, 1, 0x42),SCE(0xff23, 0, 0x82),SCE(0xff43, 1, 0x42),SCE(0xa724, 0, 0x82),
+SCE(0xa725, 1, 0x42),SCE(0xa686, 0, 0x82),SCE(0xa687, 1, 0x42),SCE(0xa726, 0, 0x82),
+SCE(0xa727, 1, 0x42),SCE(0xff27, 0, 0x82),SCE(0xff47, 1, 0x42),SCE(0x1f20, 0, 0x42),
+SCE(0x1f28, 1, 0x82),SCE(0x1f21, 0, 0x42),SCE(0x1f29, 1, 0x82),SCE(0x1f22, 0, 0x42),
+SCE(0x1f2a, 1, 0x82),SCE(0x1f23, 0, 0x42),SCE(0x1f2b, 1, 0x82),SCE(0x1f24, 0, 0x42),
+SCE(0x1f2c, 1, 0x82),SCE(0x1f25, 0, 0x42),SCE(0x1f2d, 1, 0x82),SCE(0x1f26, 0, 0x42),
+SCE(0x1f2e, 1, 0x82),SCE(0x1f27, 0, 0x42),SCE(0x1f2f, 1, 0x82),SCE(0xff30, 0, 0x82),
+SCE(0xff50, 1, 0x42),SCE(0xa688, 0, 0x82),SCE(0xa689, 1, 0x42),SCE(0xa732, 0, 0x82),
+SCE(0xa733, 1, 0x42),SCE(0xff33, 0, 0x82),SCE(0xff53, 1, 0x42),SCE(0xa734, 0, 0x82),
+SCE(0xa735, 1, 0x42),SCE(0xff35, 0, 0x82),SCE(0xff55, 1, 0x42),SCE(0xa736, 0, 0x82),
+SCE(0xa737, 1, 0x42),SCE(0x2cba, 0, 0x82),SCE(0x2cbb, 1, 0x42),SCE(0x1f30, 0, 0x42),
+SCE(0x1f38, 1, 0x82),SCE(0x1f31, 0, 0x42),SCE(0x1f39, 1, 0x82),SCE(0x1f32, 0, 0x42),
+SCE(0x1f3a, 1, 0x82),SCE(0x1f33, 0, 0x42),SCE(0x1f3b, 1, 0x82),SCE(0x1f34, 0, 0x42),
+SCE(0x1f3c, 1, 0x82),SCE(0x1f35, 0, 0x42),SCE(0x1f3d, 1, 0x82),SCE(0x1f36, 0, 0x42),
+SCE(0x1f3e, 1, 0x82),SCE(0x1f37, 0, 0x42),SCE(0x1f3f, 1, 0x82),SCE(0xa740, 0, 0x82),
+SCE(0xa741, 1, 0x42),SCE(0xa742, 0, 0x82),SCE(0xa743, 1, 0x42),SCE(0xa744, 0, 0x82),
+SCE(0xa745, 1, 0x42),SCE(0xa746, 0, 0x82),SCE(0xa747, 1, 0x42),SCE(0x1f40, 0, 0x42),
+SCE(0x1f48, 1, 0x82),SCE(0x1f41, 0, 0x42),SCE(0x1f49, 1, 0x82),SCE(0x1f42, 0, 0x42),
+SCE(0x1f4a, 1, 0x82),SCE(0x1f43, 0, 0x42),SCE(0x1f4b, 1, 0x82),SCE(0x1f44, 0, 0x42),
+SCE(0x1f4c, 1, 0x82),SCE(0x1f45, 0, 0x42),SCE(0x1f4d, 1, 0x82),SCE(0xa74e, 0, 0x82),
+SCE(0xa74f, 1, 0x42),SCE(0xa750, 0, 0x82),SCE(0xa751, 1, 0x42),SCE(0xa752, 0, 0x82),
+SCE(0xa753, 1, 0x42),SCE(0xa754, 0, 0x82),SCE(0xa755, 1, 0x42),SCE(0xa68e, 0, 0x82),
+SCE(0xa68f, 1, 0x42),SCE(0xa756, 0, 0x82),SCE(0xa757, 1, 0x42),SCE(0xa758, 0, 0x82),
+SCE(0xa759, 1, 0x42),SCE(0x1f51, 0, 0x42),SCE(0x1f59, 1, 0x82),SCE(0xa75a, 0, 0x82),
+SCE(0xa75b, 1, 0x42),SCE(0x1f53, 0, 0x42),SCE(0x1f5b, 1, 0x82),SCE(0xa75c, 0, 0x82),
+SCE(0xa75d, 1, 0x42),SCE(0x1f55, 0, 0x42),SCE(0x1f5d, 1, 0x82),SCE(0xa75e, 0, 0x82),
+SCE(0xa75f, 1, 0x42),SCE(0x1f57, 0, 0x42),SCE(0x1f5f, 1, 0x82),SCE(0xa760, 0, 0x82),
+SCE(0xa761, 1, 0x42),SCE(0xa690, 0, 0x82),SCE(0xa691, 1, 0x42),SCE(0xa762, 0, 0x82),
+SCE(0xa763, 1, 0x42),SCE(0xff2e, 0, 0x82),SCE(0xff4e, 1, 0x42),SCE(0xa764, 0, 0x82),
+SCE(0xa765, 1, 0x42),SCE(0xa766, 0, 0x82),SCE(0xa767, 1, 0x42),SCE(0x1f60, 0, 0x42),
+SCE(0x1f68, 1, 0x82),SCE(0x1f61, 0, 0x42),SCE(0x1f69, 1, 0x82),SCE(0x1f62, 0, 0x42),
+SCE(0x1f6a, 1, 0x82),SCE(0x1f63, 0, 0x42),SCE(0x1f6b, 1, 0x82),SCE(0x1f64, 0, 0x42),
+SCE(0x1f6c, 1, 0x82),SCE(0x1f65, 0, 0x42),SCE(0x1f6d, 1, 0x82),SCE(0x1f66, 0, 0x42),
+SCE(0x1f6e, 1, 0x82),SCE(0x1f67, 0, 0x42),SCE(0x1f6f, 1, 0x82),SCE(0x2c1c, 0, 0x82),
+SCE(0x2c4c, 1, 0x42),SCE(0x2cbc, 0, 0x82),SCE(0x2cbd, 1, 0x42),SCE(0xa694, 0, 0x82),
+SCE(0xa695, 1, 0x42),SCE(0xa77b, 0, 0x82),SCE(0xa77c, 1, 0x42),SCE(0x1d79, 0, 0x42),
+SCE(0xa77d, 1, 0x82),SCE(0xa77e, 0, 0x82),SCE(0xa77f, 1, 0x42),SCE(0xa780, 0, 0x82),
+SCE(0xa781, 1, 0x42),SCE(0xa782, 0, 0x82),SCE(0xa783, 1, 0x42),SCE(0xa784, 0, 0x82),
+SCE(0xa785, 1, 0x42),SCE(0xa786, 0, 0x82),SCE(0xa787, 1, 0x42),SCE(0x1f80, 0, 0x42),
+SCE(0x1f88, 1, 0x2),SCE(0x1f81, 0, 0x42),SCE(0x1f89, 1, 0x2),SCE(0x1f82, 0, 0x42),
+SCE(0x1f8a, 1, 0x2),SCE(0x1f83, 0, 0x42),SCE(0x1f8b, 1, 0x2),SCE(0x1f84, 0, 0x42),
+SCE(0x1f8c, 1, 0x2),SCE(0x1f85, 0, 0x42),SCE(0x1f8d, 1, 0x2),SCE(0x1f86, 0, 0x42),
+SCE(0x1f8e, 1, 0x2),SCE(0x1f87, 0, 0x42),SCE(0x1f8f, 1, 0x2),SCE(0xa790, 0, 0x82),
+SCE(0xa791, 1, 0x42),SCE(0xa792, 0, 0x82),SCE(0xa793, 1, 0x42),SCE(0x1f90, 0, 0x42),
+SCE(0x1f98, 1, 0x2),SCE(0x1f91, 0, 0x42),SCE(0x1f99, 1, 0x2),SCE(0x1f92, 0, 0x42),
+SCE(0x1f9a, 1, 0x2),SCE(0x1f93, 0, 0x42),SCE(0x1f9b, 1, 0x2),SCE(0x1f94, 0, 0x42),
+SCE(0x1f9c, 1, 0x2),SCE(0x1f95, 0, 0x42),SCE(0x1f9d, 1, 0x2),SCE(0x1f96, 0, 0x42),
+SCE(0x1f9e, 1, 0x2),SCE(0x1f97, 0, 0x42),SCE(0x1f9f, 1, 0x2),SCE(0xa7a0, 0, 0x82),
+SCE(0xa7a1, 1, 0x42),SCE(0xa7a2, 0, 0x82),SCE(0xa7a3, 1, 0x42),SCE(0xa7a4, 0, 0x82),
+SCE(0xa7a5, 1, 0x42),SCE(0xa7a6, 0, 0x82),SCE(0xa7a7, 1, 0x42),SCE(0x1fa0, 0, 0x42),
+SCE(0x1fa8, 1, 0x2),SCE(0x1fa1, 0, 0x42),SCE(0x1fa9, 1, 0x2),SCE(0x1fa2, 0, 0x42),
+SCE(0x1faa, 1, 0x2),SCE(0x1fa3, 0, 0x42),SCE(0x1fab, 1, 0x2),SCE(0x1fa4, 0, 0x42),
+SCE(0x1fac, 1, 0x2),SCE(0x1fa5, 0, 0x42),SCE(0x1fad, 1, 0x2),SCE(0x1fa6, 0, 0x42),
+SCE(0x1fae, 1, 0x2),SCE(0x1fa7, 0, 0x42),SCE(0x1faf, 1, 0x2),SCE(0x1fb0, 0, 0x42),
+SCE(0x1fb8, 1, 0x82),SCE(0x1fb1, 0, 0x42),SCE(0x1fb9, 1, 0x82),SCE(0x1f70, 0, 0x42),
+SCE(0x1fba, 1, 0x82),SCE(0x1f71, 0, 0x42),SCE(0x1fbb, 1, 0x82),SCE(0x1fb3, 0, 0x42),
+SCE(0x1fbc, 1, 0x2),SCE(0x0345, 0, 0x44),SCE(0x0399, 1, 0x84),SCE(0x03b9, 2, 0x44),
+SCE(0x1fbe, 3, 0x44),SCE(0x1f72, 0, 0x42),SCE(0x1fc8, 1, 0x82),SCE(0x1f73, 0, 0x42),
+SCE(0x1fc9, 1, 0x82),SCE(0x1f74, 0, 0x42),SCE(0x1fca, 1, 0x82),SCE(0x1f75, 0, 0x42),
+SCE(0x1fcb, 1, 0x82),SCE(0x1fc3, 0, 0x42),SCE(0x1fcc, 1, 0x2),SCE(0x1fd0, 0, 0x42),
+SCE(0x1fd8, 1, 0x82),SCE(0x1fd1, 0, 0x42),SCE(0x1fd9, 1, 0x82),SCE(0x1f76, 0, 0x42),
+SCE(0x1fda, 1, 0x82),SCE(0x1f77, 0, 0x42),SCE(0x1fdb, 1, 0x82),SCE(0x10427, 0, 0x82),
+SCE(0x1044f, 1, 0x42),SCE(0x1fe0, 0, 0x42),SCE(0x1fe8, 1, 0x82),SCE(0x1fe1, 0, 0x42),
+SCE(0x1fe9, 1, 0x82),SCE(0x1f7a, 0, 0x42),SCE(0x1fea, 1, 0x82),SCE(0x1f7b, 0, 0x42),
+SCE(0x1feb, 1, 0x82),SCE(0x1fe5, 0, 0x42),SCE(0x1fec, 1, 0x82),SCE(0x10401, 0, 0x82),
+SCE(0x10429, 1, 0x42),SCE(0x1040c, 0, 0x82),SCE(0x10434, 1, 0x42),SCE(0x1f78, 0, 0x42),
+SCE(0x1ff8, 1, 0x82),SCE(0x1f79, 0, 0x42),SCE(0x1ff9, 1, 0x82),SCE(0x1f7c, 0, 0x42),
+SCE(0x1ffa, 1, 0x82),SCE(0x1f7d, 0, 0x42),SCE(0x1ffb, 1, 0x82),SCE(0x1ff3, 0, 0x42),
+SCE(0x1ffc, 1, 0x2),SCE(0x24c0, 0, 0x82),SCE(0x24da, 1, 0x42),];
+return t;
+}
+@property immutable(FullCaseEntry[]) fullCaseTable()
+{
+alias FCE = FullCaseEntry;
+static immutable FCE[] t = [
+FCE("Ⰰ", 0, 2, 1),
+FCE("ⰰ", 1, 2, 1),FCE("Ⓝ", 0, 2, 1),FCE("ⓝ", 1, 2, 1),FCE("Ⰱ", 0, 2, 1),
+FCE("ⰱ", 1, 2, 1),FCE("Ⱍ", 0, 2, 1),FCE("ⱍ", 1, 2, 1),FCE("Ⰲ", 0, 2, 1),
+FCE("ⰲ", 1, 2, 1),FCE("Ⰳ", 0, 2, 1),FCE("ⰳ", 1, 2, 1),FCE("Ⰴ", 0, 2, 1),
+FCE("ⰴ", 1, 2, 1),FCE("Ⰵ", 0, 2, 1),FCE("ⰵ", 1, 2, 1),FCE("Ⰶ", 0, 2, 1),
+FCE("ⰶ", 1, 2, 1),FCE("𐐀", 0, 2, 1),FCE("𐐨", 1, 2, 1),FCE("Ⳃ", 0, 2, 1),
+FCE("ⳃ", 1, 2, 1),FCE("Ⰷ", 0, 2, 1),FCE("ⰷ", 1, 2, 1),FCE("Ⰸ", 0, 2, 1),
+FCE("ⰸ", 1, 2, 1),FCE("Ⰹ", 0, 2, 1),FCE("ⰹ", 1, 2, 1),FCE("Ⰺ", 0, 2, 1),
+FCE("ⰺ", 1, 2, 1),FCE("Ꚍ", 0, 2, 1),FCE("ꚍ", 1, 2, 1),FCE("A", 0, 2, 1),
+FCE("a", 1, 2, 1),FCE("B", 0, 2, 1),FCE("b", 1, 2, 1),FCE("C", 0, 2, 1),
+FCE("c", 1, 2, 1),FCE("D", 0, 2, 1),FCE("d", 1, 2, 1),FCE("E", 0, 2, 1),
+FCE("e", 1, 2, 1),FCE("F", 0, 2, 1),FCE("f", 1, 2, 1),FCE("G", 0, 2, 1),
+FCE("g", 1, 2, 1),FCE("H", 0, 2, 1),FCE("h", 1, 2, 1),FCE("I", 0, 2, 1),
+FCE("i", 1, 2, 1),FCE("J", 0, 2, 1),FCE("j", 1, 2, 1),FCE("K", 0, 3, 1),
+FCE("k", 1, 3, 1),FCE("K", 2, 3, 1),FCE("L", 0, 2, 1),FCE("l", 1, 2, 1),
+FCE("M", 0, 2, 1),FCE("m", 1, 2, 1),FCE("N", 0, 2, 1),FCE("n", 1, 2, 1),
+FCE("O", 0, 2, 1),FCE("o", 1, 2, 1),FCE("P", 0, 2, 1),FCE("p", 1, 2, 1),
+FCE("Q", 0, 2, 1),FCE("q", 1, 2, 1),FCE("R", 0, 2, 1),FCE("r", 1, 2, 1),
+FCE("S", 0, 3, 1),FCE("s", 1, 3, 1),FCE("ſ", 2, 3, 1),FCE("T", 0, 2, 1),
+FCE("t", 1, 2, 1),FCE("U", 0, 2, 1),FCE("u", 1, 2, 1),FCE("V", 0, 2, 1),
+FCE("v", 1, 2, 1),FCE("W", 0, 2, 1),FCE("w", 1, 2, 1),FCE("X", 0, 2, 1),
+FCE("x", 1, 2, 1),FCE("Y", 0, 2, 1),FCE("y", 1, 2, 1),FCE("Z", 0, 2, 1),
+FCE("z", 1, 2, 1),FCE("Ⰿ", 0, 2, 1),FCE("ⰿ", 1, 2, 1),FCE("Ⱀ", 0, 2, 1),
+FCE("ⱀ", 1, 2, 1),FCE("𐐂", 0, 2, 1),FCE("𐐪", 1, 2, 1),FCE("Ⳅ", 0, 2, 1),
+FCE("ⳅ", 1, 2, 1),FCE("Ⅶ", 0, 2, 1),FCE("ⅶ", 1, 2, 1),FCE("Ⱁ", 0, 2, 1),
+FCE("ⱁ", 1, 2, 1),FCE("Ⱂ", 0, 2, 1),FCE("ⱂ", 1, 2, 1),FCE("Ⅸ", 0, 2, 1),
+FCE("ⅸ", 1, 2, 1),FCE("Ⱃ", 0, 2, 1),FCE("ⱃ", 1, 2, 1),FCE("Ꚃ", 0, 2, 1),
+FCE("ꚃ", 1, 2, 1),FCE("Ⱄ", 0, 2, 1),FCE("ⱄ", 1, 2, 1),FCE("Ⅺ", 0, 2, 1),
+FCE("ⅺ", 1, 2, 1),FCE("Ⓡ", 0, 2, 1),FCE("ⓡ", 1, 2, 1),FCE("Ⱅ", 0, 2, 1),
+FCE("ⱅ", 1, 2, 1),FCE("𐐃", 0, 2, 1),FCE("𐐫", 1, 2, 1),FCE("Ⱆ", 0, 2, 1),
+FCE("ⱆ", 1, 2, 1),FCE("Ⅼ", 0, 2, 1),FCE("ⅼ", 1, 2, 1),FCE("Ⱇ", 0, 2, 1),
+FCE("ⱇ", 1, 2, 1),FCE("X", 0, 2, 1),FCE("x", 1, 2, 1),FCE("Ⱈ", 0, 2, 1),
+FCE("ⱈ", 1, 2, 1),FCE("Ⅾ", 0, 2, 1),FCE("ⅾ", 1, 2, 1),FCE("Ⱉ", 0, 2, 1),
+FCE("ⱉ", 1, 2, 1),FCE("Ⱊ", 0, 2, 1),FCE("ⱊ", 1, 2, 1),FCE("Ⱎ", 0, 2, 1),
+FCE("ⱎ", 1, 2, 1),FCE("Ⴀ", 0, 2, 1),FCE("ⴀ", 1, 2, 1),FCE("Ⴁ", 0, 2, 1),
+FCE("ⴁ", 1, 2, 1),FCE("Ⴂ", 0, 2, 1),FCE("ⴂ", 1, 2, 1),FCE("Ⴃ", 0, 2, 1),
+FCE("ⴃ", 1, 2, 1),FCE("Ⴄ", 0, 2, 1),FCE("ⴄ", 1, 2, 1),FCE("Ⴅ", 0, 2, 1),
+FCE("ⴅ", 1, 2, 1),FCE("Ⴆ", 0, 2, 1),FCE("ⴆ", 1, 2, 1),FCE("Ⴇ", 0, 2, 1),
+FCE("ⴇ", 1, 2, 1),FCE("Ⴈ", 0, 2, 1),FCE("ⴈ", 1, 2, 1),FCE("Ⴉ", 0, 2, 1),
+FCE("ⴉ", 1, 2, 1),FCE("Ⴊ", 0, 2, 1),FCE("ⴊ", 1, 2, 1),FCE("Ⴋ", 0, 2, 1),
+FCE("ⴋ", 1, 2, 1),FCE("Ⴌ", 0, 2, 1),FCE("ⴌ", 1, 2, 1),FCE("Ⴍ", 0, 2, 1),
+FCE("ⴍ", 1, 2, 1),FCE("Ⴎ", 0, 2, 1),FCE("ⴎ", 1, 2, 1),FCE("Ⴏ", 0, 2, 1),
+FCE("ⴏ", 1, 2, 1),FCE("Ⴐ", 0, 2, 1),FCE("ⴐ", 1, 2, 1),FCE("Ⴑ", 0, 2, 1),
+FCE("ⴑ", 1, 2, 1),FCE("Ⴒ", 0, 2, 1),FCE("ⴒ", 1, 2, 1),FCE("Ⴓ", 0, 2, 1),
+FCE("ⴓ", 1, 2, 1),FCE("Ⴔ", 0, 2, 1),FCE("ⴔ", 1, 2, 1),FCE("Ⴕ", 0, 2, 1),
+FCE("ⴕ", 1, 2, 1),FCE("Ⴖ", 0, 2, 1),FCE("ⴖ", 1, 2, 1),FCE("Ⴗ", 0, 2, 1),
+FCE("ⴗ", 1, 2, 1),FCE("Ⴘ", 0, 2, 1),FCE("ⴘ", 1, 2, 1),FCE("Ⴙ", 0, 2, 1),
+FCE("ⴙ", 1, 2, 1),FCE("Ⴚ", 0, 2, 1),FCE("ⴚ", 1, 2, 1),FCE("Ⴛ", 0, 2, 1),
+FCE("ⴛ", 1, 2, 1),FCE("Ⴜ", 0, 2, 1),FCE("ⴜ", 1, 2, 1),FCE("Ⴝ", 0, 2, 1),
+FCE("ⴝ", 1, 2, 1),FCE("Ⴞ", 0, 2, 1),FCE("ⴞ", 1, 2, 1),FCE("Ⴟ", 0, 2, 1),
+FCE("ⴟ", 1, 2, 1),FCE("À", 0, 2, 1),FCE("à", 1, 2, 1),FCE("Á", 0, 2, 1),
+FCE("á", 1, 2, 1),FCE("Ⴢ", 0, 2, 1),FCE("ⴢ", 1, 2, 1),FCE("Ã", 0, 2, 1),
+FCE("ã", 1, 2, 1),FCE("Ⴤ", 0, 2, 1),FCE("ⴤ", 1, 2, 1),FCE("Å", 0, 3, 1),
+FCE("å", 1, 3, 1),FCE("Å", 2, 3, 1),FCE("Æ", 0, 2, 1),FCE("æ", 1, 2, 1),
+FCE("Ç", 0, 2, 1),FCE("ç", 1, 2, 1),FCE("È", 0, 2, 1),FCE("è", 1, 2, 1),
+FCE("É", 0, 2, 1),FCE("é", 1, 2, 1),FCE("Ê", 0, 2, 1),FCE("ê", 1, 2, 1),
+FCE("Ë", 0, 2, 1),FCE("ë", 1, 2, 1),FCE("Ì", 0, 2, 1),FCE("ì", 1, 2, 1),
+FCE("Í", 0, 2, 1),FCE("í", 1, 2, 1),FCE("Î", 0, 2, 1),FCE("î", 1, 2, 1),
+FCE("Ï", 0, 2, 1),FCE("ï", 1, 2, 1),FCE("Ð", 0, 2, 1),FCE("ð", 1, 2, 1),
+FCE("Ñ", 0, 2, 1),FCE("ñ", 1, 2, 1),FCE("Ò", 0, 2, 1),FCE("ò", 1, 2, 1),
+FCE("Ó", 0, 2, 1),FCE("ó", 1, 2, 1),FCE("Ô", 0, 2, 1),FCE("ô", 1, 2, 1),
+FCE("Õ", 0, 2, 1),FCE("õ", 1, 2, 1),FCE("Ö", 0, 2, 1),FCE("ö", 1, 2, 1),
+FCE("Ø", 0, 2, 1),FCE("ø", 1, 2, 1),FCE("Ù", 0, 2, 1),FCE("ù", 1, 2, 1),
+FCE("Ú", 0, 2, 1),FCE("ú", 1, 2, 1),FCE("Û", 0, 2, 1),FCE("û", 1, 2, 1),
+FCE("Ü", 0, 2, 1),FCE("ü", 1, 2, 1),FCE("Ý", 0, 2, 1),FCE("ý", 1, 2, 1),
+FCE("Þ", 0, 2, 1),FCE("þ", 1, 2, 1),FCE("ß", 0, 3, 1),FCE("ẞ", 1, 3, 1),
+FCE("ss", 2, 3, 2),FCE("Ⱖ", 0, 2, 1),FCE("ⱖ", 1, 2, 1),FCE("Ⱗ", 0, 2, 1),
+FCE("ⱗ", 1, 2, 1),FCE("Ⱘ", 0, 2, 1),FCE("ⱘ", 1, 2, 1),FCE("𐐆", 0, 2, 1),
+FCE("𐐮", 1, 2, 1),FCE("𐐏", 0, 2, 1),FCE("𐐷", 1, 2, 1),FCE("Ⓥ", 0, 2, 1),
+FCE("ⓥ", 1, 2, 1),FCE("Ⱙ", 0, 2, 1),FCE("ⱙ", 1, 2, 1),FCE("𐐇", 0, 2, 1),
+FCE("𐐯", 1, 2, 1),FCE("Ⱚ", 0, 2, 1),FCE("ⱚ", 1, 2, 1),FCE("Ā", 0, 2, 1),
+FCE("ā", 1, 2, 1),FCE("Ă", 0, 2, 1),FCE("ă", 1, 2, 1),FCE("Ⱛ", 0, 2, 1),
+FCE("ⱛ", 1, 2, 1),FCE("Ą", 0, 2, 1),FCE("ą", 1, 2, 1),FCE("Ć", 0, 2, 1),
+FCE("ć", 1, 2, 1),FCE("Ĉ", 0, 2, 1),FCE("ĉ", 1, 2, 1),FCE("Ⱜ", 0, 2, 1),
+FCE("ⱜ", 1, 2, 1),FCE("Ċ", 0, 2, 1),FCE("ċ", 1, 2, 1),FCE("Č", 0, 2, 1),
+FCE("č", 1, 2, 1),FCE("Ď", 0, 2, 1),FCE("ď", 1, 2, 1),FCE("Ⱝ", 0, 2, 1),
+FCE("ⱝ", 1, 2, 1),FCE("Đ", 0, 2, 1),FCE("đ", 1, 2, 1),FCE("Ē", 0, 2, 1),
+FCE("ē", 1, 2, 1),FCE("Ĕ", 0, 2, 1),FCE("ĕ", 1, 2, 1),FCE("Ⱞ", 0, 2, 1),
+FCE("ⱞ", 1, 2, 1),FCE("Ė", 0, 2, 1),FCE("ė", 1, 2, 1),FCE("Ę", 0, 2, 1),
+FCE("ę", 1, 2, 1),FCE("Ě", 0, 2, 1),FCE("ě", 1, 2, 1),FCE("Ĝ", 0, 2, 1),
+FCE("ĝ", 1, 2, 1),FCE("Ğ", 0, 2, 1),FCE("ğ", 1, 2, 1),FCE("Ġ", 0, 2, 1),
+FCE("ġ", 1, 2, 1),FCE("Ģ", 0, 2, 1),FCE("ģ", 1, 2, 1),FCE("K", 0, 2, 1),
+FCE("k", 1, 2, 1),FCE("Ĥ", 0, 2, 1),FCE("ĥ", 1, 2, 1),FCE("Ħ", 0, 2, 1),
+FCE("ħ", 1, 2, 1),FCE("Ĩ", 0, 2, 1),FCE("ĩ", 1, 2, 1),FCE("Ī", 0, 2, 1),
+FCE("ī", 1, 2, 1),FCE("Å", 0, 3, 1),FCE("å", 1, 3, 1),FCE("Å", 2, 3, 1),
+FCE("Ĭ", 0, 2, 1),FCE("ĭ", 1, 2, 1),FCE("Į", 0, 2, 1),FCE("į", 1, 2, 1),
+FCE("İ", 0, 2, 1),FCE("i̇", 1, 2, 2),FCE("IJ", 0, 2, 1),FCE("ij", 1, 2, 1),
+FCE("Ĵ", 0, 2, 1),FCE("ĵ", 1, 2, 1),FCE("Ķ", 0, 2, 1),FCE("ķ", 1, 2, 1),
+FCE("Ĺ", 0, 2, 1),FCE("ĺ", 1, 2, 1),FCE("Ļ", 0, 2, 1),FCE("ļ", 1, 2, 1),
+FCE("Ⳟ", 0, 2, 1),FCE("ⳟ", 1, 2, 1),FCE("Ľ", 0, 2, 1),FCE("ľ", 1, 2, 1),
+FCE("Ŀ", 0, 2, 1),FCE("ŀ", 1, 2, 1),FCE("Ł", 0, 2, 1),FCE("ł", 1, 2, 1),
+FCE("Ń", 0, 2, 1),FCE("ń", 1, 2, 1),FCE("Ņ", 0, 2, 1),FCE("ņ", 1, 2, 1),
+FCE("Ň", 0, 2, 1),FCE("ň", 1, 2, 1),FCE("ʼn", 0, 2, 1),FCE("ʼn", 1, 2, 2),
+FCE("Ŋ", 0, 2, 1),FCE("ŋ", 1, 2, 1),FCE("Ō", 0, 2, 1),FCE("ō", 1, 2, 1),
+FCE("Ŏ", 0, 2, 1),FCE("ŏ", 1, 2, 1),FCE("Ő", 0, 2, 1),FCE("ő", 1, 2, 1),
+FCE("Œ", 0, 2, 1),FCE("œ", 1, 2, 1),FCE("Ŕ", 0, 2, 1),FCE("ŕ", 1, 2, 1),
+FCE("Ŗ", 0, 2, 1),FCE("ŗ", 1, 2, 1),FCE("Ř", 0, 2, 1),FCE("ř", 1, 2, 1),
+FCE("Ś", 0, 2, 1),FCE("ś", 1, 2, 1),FCE("Ŝ", 0, 2, 1),FCE("ŝ", 1, 2, 1),
+FCE("Ş", 0, 2, 1),FCE("ş", 1, 2, 1),FCE("Š", 0, 2, 1),FCE("š", 1, 2, 1),
+FCE("Ⅱ", 0, 2, 1),FCE("ⅱ", 1, 2, 1),FCE("Ţ", 0, 2, 1),FCE("ţ", 1, 2, 1),
+FCE("Ⅳ", 0, 2, 1),FCE("ⅳ", 1, 2, 1),FCE("Ť", 0, 2, 1),FCE("ť", 1, 2, 1),
+FCE("Ⅵ", 0, 2, 1),FCE("ⅵ", 1, 2, 1),FCE("Ŧ", 0, 2, 1),FCE("ŧ", 1, 2, 1),
+FCE("Ⅷ", 0, 2, 1),FCE("ⅷ", 1, 2, 1),FCE("Ũ", 0, 2, 1),FCE("ũ", 1, 2, 1),
+FCE("Ⅹ", 0, 2, 1),FCE("ⅹ", 1, 2, 1),FCE("Ū", 0, 2, 1),FCE("ū", 1, 2, 1),
+FCE("Ⅻ", 0, 2, 1),FCE("ⅻ", 1, 2, 1),FCE("Ŭ", 0, 2, 1),FCE("ŭ", 1, 2, 1),
+FCE("Ⅽ", 0, 2, 1),FCE("ⅽ", 1, 2, 1),FCE("Ů", 0, 2, 1),FCE("ů", 1, 2, 1),
+FCE("Ⅿ", 0, 2, 1),FCE("ⅿ", 1, 2, 1),FCE("Ű", 0, 2, 1),FCE("ű", 1, 2, 1),
+FCE("Ⳍ", 0, 2, 1),FCE("ⳍ", 1, 2, 1),FCE("Ų", 0, 2, 1),FCE("ų", 1, 2, 1),
+FCE("Ŵ", 0, 2, 1),FCE("ŵ", 1, 2, 1),FCE("Ŷ", 0, 2, 1),FCE("ŷ", 1, 2, 1),
+FCE("ÿ", 0, 2, 1),FCE("Ÿ", 1, 2, 1),FCE("Ź", 0, 2, 1),FCE("ź", 1, 2, 1),
+FCE("Ż", 0, 2, 1),FCE("ż", 1, 2, 1),FCE("Ž", 0, 2, 1),FCE("ž", 1, 2, 1),
+FCE("S", 0, 3, 1),FCE("s", 1, 3, 1),FCE("ſ", 2, 3, 1),FCE("Ɓ", 0, 2, 1),
+FCE("ɓ", 1, 2, 1),FCE("Ƃ", 0, 2, 1),FCE("ƃ", 1, 2, 1),FCE("Ↄ", 0, 2, 1),
+FCE("ↄ", 1, 2, 1),FCE("Ƅ", 0, 2, 1),FCE("ƅ", 1, 2, 1),FCE("Ɔ", 0, 2, 1),
+FCE("ɔ", 1, 2, 1),FCE("Ƈ", 0, 2, 1),FCE("ƈ", 1, 2, 1),FCE("Ɖ", 0, 2, 1),
+FCE("ɖ", 1, 2, 1),FCE("Ɗ", 0, 2, 1),FCE("ɗ", 1, 2, 1),FCE("Ƌ", 0, 2, 1),
+FCE("ƌ", 1, 2, 1),FCE("Ǝ", 0, 2, 1),FCE("ǝ", 1, 2, 1),FCE("Ə", 0, 2, 1),
+FCE("ə", 1, 2, 1),FCE("Ɛ", 0, 2, 1),FCE("ɛ", 1, 2, 1),FCE("Ƒ", 0, 2, 1),
+FCE("ƒ", 1, 2, 1),FCE("Ɠ", 0, 2, 1),FCE("ɠ", 1, 2, 1),FCE("Ɣ", 0, 2, 1),
+FCE("ɣ", 1, 2, 1),FCE("Ɩ", 0, 2, 1),FCE("ɩ", 1, 2, 1),FCE("Ɨ", 0, 2, 1),
+FCE("ɨ", 1, 2, 1),FCE("Ƙ", 0, 2, 1),FCE("ƙ", 1, 2, 1),FCE("Ɯ", 0, 2, 1),
+FCE("ɯ", 1, 2, 1),FCE("Ɲ", 0, 2, 1),FCE("ɲ", 1, 2, 1),FCE("Ꙋ", 0, 2, 1),
+FCE("ꙋ", 1, 2, 1),FCE("Ɵ", 0, 2, 1),FCE("ɵ", 1, 2, 1),FCE("Ơ", 0, 2, 1),
+FCE("ơ", 1, 2, 1),FCE("Ƣ", 0, 2, 1),FCE("ƣ", 1, 2, 1),FCE("Ƥ", 0, 2, 1),
+FCE("ƥ", 1, 2, 1),FCE("Ʀ", 0, 2, 1),FCE("ʀ", 1, 2, 1),FCE("Ƨ", 0, 2, 1),
+FCE("ƨ", 1, 2, 1),FCE("Ʃ", 0, 2, 1),FCE("ʃ", 1, 2, 1),FCE("Ƭ", 0, 2, 1),
+FCE("ƭ", 1, 2, 1),FCE("Ʈ", 0, 2, 1),FCE("ʈ", 1, 2, 1),FCE("Ư", 0, 2, 1),
+FCE("ư", 1, 2, 1),FCE("Ʊ", 0, 2, 1),FCE("ʊ", 1, 2, 1),FCE("Ʋ", 0, 2, 1),
+FCE("ʋ", 1, 2, 1),FCE("Ƴ", 0, 2, 1),FCE("ƴ", 1, 2, 1),FCE("Ƶ", 0, 2, 1),
+FCE("ƶ", 1, 2, 1),FCE("Ʒ", 0, 2, 1),FCE("ʒ", 1, 2, 1),FCE("Ƹ", 0, 2, 1),
+FCE("ƹ", 1, 2, 1),FCE("Ƽ", 0, 2, 1),FCE("ƽ", 1, 2, 1),FCE("DŽ", 0, 3, 1),
+FCE("Dž", 1, 3, 1),FCE("dž", 2, 3, 1),FCE("DŽ", 0, 3, 1),FCE("Dž", 1, 3, 1),
+FCE("dž", 2, 3, 1),FCE("LJ", 0, 3, 1),FCE("Lj", 1, 3, 1),FCE("lj", 2, 3, 1),
+FCE("LJ", 0, 3, 1),FCE("Lj", 1, 3, 1),FCE("lj", 2, 3, 1),FCE("NJ", 0, 3, 1),
+FCE("Nj", 1, 3, 1),FCE("nj", 2, 3, 1),FCE("NJ", 0, 3, 1),FCE("Nj", 1, 3, 1),
+FCE("nj", 2, 3, 1),FCE("Ǎ", 0, 2, 1),FCE("ǎ", 1, 2, 1),FCE("Ǐ", 0, 2, 1),
+FCE("ǐ", 1, 2, 1),FCE("Ǒ", 0, 2, 1),FCE("ǒ", 1, 2, 1),FCE("Ǔ", 0, 2, 1),
+FCE("ǔ", 1, 2, 1),FCE("Ǖ", 0, 2, 1),FCE("ǖ", 1, 2, 1),FCE("Ǘ", 0, 2, 1),
+FCE("ǘ", 1, 2, 1),FCE("Ǚ", 0, 2, 1),FCE("ǚ", 1, 2, 1),FCE("Ǜ", 0, 2, 1),
+FCE("ǜ", 1, 2, 1),FCE("Ǟ", 0, 2, 1),FCE("ǟ", 1, 2, 1),FCE("V", 0, 2, 1),
+FCE("v", 1, 2, 1),FCE("Ǡ", 0, 2, 1),FCE("ǡ", 1, 2, 1),FCE("Ǣ", 0, 2, 1),
+FCE("ǣ", 1, 2, 1),FCE("Ǥ", 0, 2, 1),FCE("ǥ", 1, 2, 1),FCE("Ǧ", 0, 2, 1),
+FCE("ǧ", 1, 2, 1),FCE("Ǩ", 0, 2, 1),FCE("ǩ", 1, 2, 1),FCE("Ǫ", 0, 2, 1),
+FCE("ǫ", 1, 2, 1),FCE("Ǭ", 0, 2, 1),FCE("ǭ", 1, 2, 1),FCE("Ǯ", 0, 2, 1),
+FCE("ǯ", 1, 2, 1),FCE("ǰ", 0, 2, 1),FCE("ǰ", 1, 2, 2),FCE("DZ", 0, 3, 1),
+FCE("Dz", 1, 3, 1),FCE("dz", 2, 3, 1),FCE("DZ", 0, 3, 1),FCE("Dz", 1, 3, 1),
+FCE("dz", 2, 3, 1),FCE("Ǵ", 0, 2, 1),FCE("ǵ", 1, 2, 1),FCE("ƕ", 0, 2, 1),
+FCE("Ƕ", 1, 2, 1),FCE("ƿ", 0, 2, 1),FCE("Ƿ", 1, 2, 1),FCE("Ǹ", 0, 2, 1),
+FCE("ǹ", 1, 2, 1),FCE("𐐝", 0, 2, 1),FCE("𐑅", 1, 2, 1),FCE("Ǻ", 0, 2, 1),
+FCE("ǻ", 1, 2, 1),FCE("Ǽ", 0, 2, 1),FCE("ǽ", 1, 2, 1),FCE("Ǿ", 0, 2, 1),
+FCE("ǿ", 1, 2, 1),FCE("Ȁ", 0, 2, 1),FCE("ȁ", 1, 2, 1),FCE("Ȃ", 0, 2, 1),
+FCE("ȃ", 1, 2, 1),FCE("Ȅ", 0, 2, 1),FCE("ȅ", 1, 2, 1),FCE("Ȇ", 0, 2, 1),
+FCE("ȇ", 1, 2, 1),FCE("fi", 0, 2, 1),FCE("fi", 1, 2, 2),FCE("Ȉ", 0, 2, 1),
+FCE("ȉ", 1, 2, 1),FCE("Ȋ", 0, 2, 1),FCE("ȋ", 1, 2, 1),FCE("Ȍ", 0, 2, 1),
+FCE("ȍ", 1, 2, 1),FCE("Ȏ", 0, 2, 1),FCE("ȏ", 1, 2, 1),FCE("Ȑ", 0, 2, 1),
+FCE("ȑ", 1, 2, 1),FCE("Ȓ", 0, 2, 1),FCE("ȓ", 1, 2, 1),FCE("Ȕ", 0, 2, 1),
+FCE("ȕ", 1, 2, 1),FCE("Ȗ", 0, 2, 1),FCE("ȗ", 1, 2, 1),FCE("Ș", 0, 2, 1),
+FCE("ș", 1, 2, 1),FCE("Ț", 0, 2, 1),FCE("ț", 1, 2, 1),FCE("Ȝ", 0, 2, 1),
+FCE("ȝ", 1, 2, 1),FCE("Ȟ", 0, 2, 1),FCE("ȟ", 1, 2, 1),FCE("ƞ", 0, 2, 1),
+FCE("Ƞ", 1, 2, 1),FCE("Ȣ", 0, 2, 1),FCE("ȣ", 1, 2, 1),FCE("Ȥ", 0, 2, 1),
+FCE("ȥ", 1, 2, 1),FCE("Ȧ", 0, 2, 1),FCE("ȧ", 1, 2, 1),FCE("Ȩ", 0, 2, 1),
+FCE("ȩ", 1, 2, 1),FCE("Ꝗ", 0, 2, 1),FCE("ꝗ", 1, 2, 1),FCE("Ȫ", 0, 2, 1),
+FCE("ȫ", 1, 2, 1),FCE("Ȭ", 0, 2, 1),FCE("ȭ", 1, 2, 1),FCE("Ȯ", 0, 2, 1),
+FCE("ȯ", 1, 2, 1),FCE("Ȱ", 0, 2, 1),FCE("ȱ", 1, 2, 1),FCE("Ȳ", 0, 2, 1),
+FCE("ȳ", 1, 2, 1),FCE("Ꚅ", 0, 2, 1),FCE("ꚅ", 1, 2, 1),FCE("Ⱥ", 0, 2, 1),
+FCE("ⱥ", 1, 2, 1),FCE("Ȼ", 0, 2, 1),FCE("ȼ", 1, 2, 1),FCE("ƚ", 0, 2, 1),
+FCE("Ƚ", 1, 2, 1),FCE("Ⱦ", 0, 2, 1),FCE("ⱦ", 1, 2, 1),FCE("Ɂ", 0, 2, 1),
+FCE("ɂ", 1, 2, 1),FCE("𐐒", 0, 2, 1),FCE("𐐺", 1, 2, 1),FCE("ƀ", 0, 2, 1),
+FCE("Ƀ", 1, 2, 1),FCE("Ʉ", 0, 2, 1),FCE("ʉ", 1, 2, 1),FCE("Ʌ", 0, 2, 1),
+FCE("ʌ", 1, 2, 1),FCE("Ɇ", 0, 2, 1),FCE("ɇ", 1, 2, 1),FCE("Ɉ", 0, 2, 1),
+FCE("ɉ", 1, 2, 1),FCE("Ɋ", 0, 2, 1),FCE("ɋ", 1, 2, 1),FCE("Ɍ", 0, 2, 1),
+FCE("ɍ", 1, 2, 1),FCE("Ⱋ", 0, 2, 1),FCE("ⱋ", 1, 2, 1),FCE("Ɏ", 0, 2, 1),
+FCE("ɏ", 1, 2, 1),FCE("𐐊", 0, 2, 1),FCE("𐐲", 1, 2, 1),FCE("Ⅰ", 0, 2, 1),
+FCE("ⅰ", 1, 2, 1),FCE("Ꚓ", 0, 2, 1),FCE("ꚓ", 1, 2, 1),FCE("ɽ", 0, 2, 1),
+FCE("Ɽ", 1, 2, 1),FCE("𐐐", 0, 2, 1),FCE("𐐸", 1, 2, 1),FCE("Ⱑ", 0, 2, 1),
+FCE("ⱑ", 1, 2, 1),FCE("Ⱪ", 0, 2, 1),FCE("ⱪ", 1, 2, 1),FCE("𐐉", 0, 2, 1),
+FCE("𐐱", 1, 2, 1),FCE("𐐔", 0, 2, 1),FCE("𐐼", 1, 2, 1),FCE("ﬕ", 0, 2, 1),
+FCE("մի", 1, 2, 2),FCE("Ⅲ", 0, 2, 1),FCE("ⅲ", 1, 2, 1),FCE("𐐞", 0, 2, 1),
+FCE("𐑆", 1, 2, 1),FCE("ɱ", 0, 2, 1),FCE("Ɱ", 1, 2, 1),FCE("𐐕", 0, 2, 1),
+FCE("𐐽", 1, 2, 1),FCE("ɒ", 0, 2, 1),FCE("Ɒ", 1, 2, 1),FCE("Ⱳ", 0, 2, 1),
+FCE("ⱳ", 1, 2, 1),FCE("Ⰻ", 0, 2, 1),FCE("ⰻ", 1, 2, 1),FCE("𐐖", 0, 2, 1),
+FCE("𐐾", 1, 2, 1),FCE("Ꚗ", 0, 2, 1),FCE("ꚗ", 1, 2, 1),FCE("Ⱶ", 0, 2, 1),
+FCE("ⱶ", 1, 2, 1),FCE("Ⅴ", 0, 2, 1),FCE("ⅴ", 1, 2, 1),FCE("Ꙁ", 0, 2, 1),
+FCE("ꙁ", 1, 2, 1),FCE("B", 0, 2, 1),FCE("b", 1, 2, 1),FCE("Ⰼ", 0, 2, 1),
+FCE("ⰼ", 1, 2, 1),FCE("𐐗", 0, 2, 1),FCE("𐐿", 1, 2, 1),FCE("D", 0, 2, 1),
+FCE("d", 1, 2, 1),FCE("E", 0, 2, 1),FCE("e", 1, 2, 1),FCE("F", 0, 2, 1),
+FCE("f", 1, 2, 1),FCE("Ⰽ", 0, 2, 1),FCE("ⰽ", 1, 2, 1),FCE("Ⓛ", 0, 2, 1),
+FCE("ⓛ", 1, 2, 1),FCE("Ꜩ", 0, 2, 1),FCE("ꜩ", 1, 2, 1),FCE("ȿ", 0, 2, 1),
+FCE("Ȿ", 1, 2, 1),FCE("𐐑", 0, 2, 1),FCE("𐐹", 1, 2, 1),FCE("I", 0, 2, 1),
+FCE("i", 1, 2, 1),FCE("𐐋", 0, 2, 1),FCE("𐐳", 1, 2, 1),FCE("Ꜫ", 0, 2, 1),
+FCE("ꜫ", 1, 2, 1),FCE("ff", 0, 2, 1),FCE("ff", 1, 2, 2),FCE("Ⲁ", 0, 2, 1),
+FCE("ⲁ", 1, 2, 1),FCE("fl", 0, 2, 1),FCE("fl", 1, 2, 2),FCE("ffi", 0, 2, 1),
+FCE("ffi", 1, 2, 3),FCE("ffl", 0, 2, 1),FCE("ffl", 1, 2, 3),FCE("ſt", 0, 3, 1),
+FCE("st", 1, 3, 1),FCE("st", 2, 3, 2),FCE("ſt", 0, 3, 1),FCE("st", 1, 3, 1),
+FCE("st", 2, 3, 2),FCE("Ꜭ", 0, 2, 1),FCE("ꜭ", 1, 2, 1),FCE("Ⰾ", 0, 2, 1),
+FCE("ⰾ", 1, 2, 1),FCE("M", 0, 2, 1),FCE("m", 1, 2, 1),FCE("ﬓ", 0, 2, 1),
+FCE("մն", 1, 2, 2),FCE("ﬔ", 0, 2, 1),FCE("մե", 1, 2, 2),FCE("Ꜯ", 0, 2, 1),
+FCE("ꜯ", 1, 2, 1),FCE("ﬖ", 0, 2, 1),FCE("վն", 1, 2, 2),FCE("ﬗ", 0, 2, 1),
+FCE("մխ", 1, 2, 2),FCE("𐐍", 0, 2, 1),FCE("𐐵", 1, 2, 1),FCE("O", 0, 2, 1),
+FCE("o", 1, 2, 1),FCE("Q", 0, 2, 1),FCE("q", 1, 2, 1),FCE("R", 0, 2, 1),
+FCE("r", 1, 2, 1),FCE("𐐚", 0, 2, 1),FCE("𐑂", 1, 2, 1),FCE("T", 0, 2, 1),
+FCE("t", 1, 2, 1),FCE("Ⲙ", 0, 2, 1),FCE("ⲙ", 1, 2, 1),FCE("Ⲋ", 0, 2, 1),
+FCE("ⲋ", 1, 2, 1),FCE("ͅ", 0, 4, 1),FCE("Ι", 1, 4, 1),FCE("ι", 2, 4, 1),
+FCE("ι", 3, 4, 1),FCE("Ⲍ", 0, 2, 1),FCE("ⲍ", 1, 2, 1),FCE("W", 0, 2, 1),
+FCE("w", 1, 2, 1),FCE("Ꙗ", 0, 2, 1),FCE("ꙗ", 1, 2, 1),FCE("𐐛", 0, 2, 1),
+FCE("𐑃", 1, 2, 1),FCE("Ꜹ", 0, 2, 1),FCE("ꜹ", 1, 2, 1),FCE("Ⲏ", 0, 2, 1),
+FCE("ⲏ", 1, 2, 1),FCE("Y", 0, 2, 1),FCE("y", 1, 2, 1),FCE("𐐄", 0, 2, 1),
+FCE("𐐬", 1, 2, 1),FCE("Ꜻ", 0, 2, 1),FCE("ꜻ", 1, 2, 1),FCE("Ⲑ", 0, 2, 1),
+FCE("ⲑ", 1, 2, 1),FCE("Ꜽ", 0, 2, 1),FCE("ꜽ", 1, 2, 1),FCE("Ⲓ", 0, 2, 1),
+FCE("ⲓ", 1, 2, 1),FCE("𐐜", 0, 2, 1),FCE("𐑄", 1, 2, 1),FCE("Ͱ", 0, 2, 1),
+FCE("ͱ", 1, 2, 1),FCE("Ͳ", 0, 2, 1),FCE("ͳ", 1, 2, 1),FCE("Ꜿ", 0, 2, 1),
+FCE("ꜿ", 1, 2, 1),FCE("Ͷ", 0, 2, 1),FCE("ͷ", 1, 2, 1),FCE("Ⲕ", 0, 2, 1),
+FCE("ⲕ", 1, 2, 1),FCE("Ⲗ", 0, 2, 1),FCE("ⲗ", 1, 2, 1),FCE("Ά", 0, 2, 1),
+FCE("ά", 1, 2, 1),FCE("𐐅", 0, 2, 1),FCE("𐐭", 1, 2, 1),FCE("Έ", 0, 2, 1),
+FCE("έ", 1, 2, 1),FCE("Ή", 0, 2, 1),FCE("ή", 1, 2, 1),FCE("Ί", 0, 2, 1),
+FCE("ί", 1, 2, 1),FCE("Ό", 0, 2, 1),FCE("ό", 1, 2, 1),FCE("Ύ", 0, 2, 1),
+FCE("ύ", 1, 2, 1),FCE("Ώ", 0, 2, 1),FCE("ώ", 1, 2, 1),FCE("ΐ", 0, 3, 1),
+FCE("ΐ", 1, 3, 1),FCE("ΐ", 2, 3, 3),FCE("Α", 0, 2, 1),FCE("α", 1, 2, 1),
+FCE("Β", 0, 3, 1),FCE("β", 1, 3, 1),FCE("ϐ", 2, 3, 1),FCE("Γ", 0, 2, 1),
+FCE("γ", 1, 2, 1),FCE("Δ", 0, 2, 1),FCE("δ", 1, 2, 1),FCE("Ε", 0, 3, 1),
+FCE("ε", 1, 3, 1),FCE("ϵ", 2, 3, 1),FCE("Ζ", 0, 2, 1),FCE("ζ", 1, 2, 1),
+FCE("Η", 0, 2, 1),FCE("η", 1, 2, 1),FCE("Θ", 0, 4, 1),FCE("θ", 1, 4, 1),
+FCE("ϑ", 2, 4, 1),FCE("ϴ", 3, 4, 1),FCE("ͅ", 0, 4, 1),FCE("Ι", 1, 4, 1),
+FCE("ι", 2, 4, 1),FCE("ι", 3, 4, 1),FCE("Κ", 0, 3, 1),FCE("κ", 1, 3, 1),
+FCE("ϰ", 2, 3, 1),FCE("Λ", 0, 2, 1),FCE("λ", 1, 2, 1),FCE("µ", 0, 3, 1),
+FCE("Μ", 1, 3, 1),FCE("μ", 2, 3, 1),FCE("Ν", 0, 2, 1),FCE("ν", 1, 2, 1),
+FCE("Ξ", 0, 2, 1),FCE("ξ", 1, 2, 1),FCE("Ο", 0, 2, 1),FCE("ο", 1, 2, 1),
+FCE("Π", 0, 3, 1),FCE("π", 1, 3, 1),FCE("ϖ", 2, 3, 1),FCE("Ρ", 0, 3, 1),
+FCE("ρ", 1, 3, 1),FCE("ϱ", 2, 3, 1),FCE("Σ", 0, 3, 1),FCE("ς", 1, 3, 1),
+FCE("σ", 2, 3, 1),FCE("Τ", 0, 2, 1),FCE("τ", 1, 2, 1),FCE("Υ", 0, 2, 1),
+FCE("υ", 1, 2, 1),FCE("Φ", 0, 3, 1),FCE("φ", 1, 3, 1),FCE("ϕ", 2, 3, 1),
+FCE("Χ", 0, 2, 1),FCE("χ", 1, 2, 1),FCE("Ψ", 0, 2, 1),FCE("ψ", 1, 2, 1),
+FCE("Ω", 0, 3, 1),FCE("ω", 1, 3, 1),FCE("Ω", 2, 3, 1),FCE("Ϊ", 0, 2, 1),
+FCE("ϊ", 1, 2, 1),FCE("Ϋ", 0, 2, 1),FCE("ϋ", 1, 2, 1),FCE("Ⓣ", 0, 2, 1),
+FCE("ⓣ", 1, 2, 1),FCE("Ⳡ", 0, 2, 1),FCE("ⳡ", 1, 2, 1),FCE("ΰ", 0, 3, 1),
+FCE("ΰ", 1, 3, 1),FCE("ΰ", 2, 3, 3),FCE("Ꝉ", 0, 2, 1),FCE("ꝉ", 1, 2, 1),
+FCE("Ⲝ", 0, 2, 1),FCE("ⲝ", 1, 2, 1),FCE("Ⲟ", 0, 2, 1),FCE("ⲟ", 1, 2, 1),
+FCE("Ꝋ", 0, 2, 1),FCE("ꝋ", 1, 2, 1),FCE("Ⲡ", 0, 2, 1),FCE("ⲡ", 1, 2, 1),
+FCE("Σ", 0, 3, 1),FCE("ς", 1, 3, 1),FCE("σ", 2, 3, 1),FCE("𐐟", 0, 2, 1),
+FCE("𐑇", 1, 2, 1),FCE("Ꝍ", 0, 2, 1),FCE("ꝍ", 1, 2, 1),FCE("Ꚋ", 0, 2, 1),
+FCE("ꚋ", 1, 2, 1),FCE("Ⲣ", 0, 2, 1),FCE("ⲣ", 1, 2, 1),FCE("Ϗ", 0, 2, 1),
+FCE("ϗ", 1, 2, 1),FCE("Β", 0, 3, 1),FCE("β", 1, 3, 1),FCE("ϐ", 2, 3, 1),
+FCE("Θ", 0, 4, 1),FCE("θ", 1, 4, 1),FCE("ϑ", 2, 4, 1),FCE("ϴ", 3, 4, 1),
+FCE("Φ", 0, 3, 1),FCE("φ", 1, 3, 1),FCE("ϕ", 2, 3, 1),FCE("Π", 0, 3, 1),
+FCE("π", 1, 3, 1),FCE("ϖ", 2, 3, 1),FCE("Ϙ", 0, 2, 1),FCE("ϙ", 1, 2, 1),
+FCE("Ⲥ", 0, 2, 1),FCE("ⲥ", 1, 2, 1),FCE("Ϛ", 0, 2, 1),FCE("ϛ", 1, 2, 1),
+FCE("Ϝ", 0, 2, 1),FCE("ϝ", 1, 2, 1),FCE("Ϟ", 0, 2, 1),FCE("ϟ", 1, 2, 1),
+FCE("Ϡ", 0, 2, 1),FCE("ϡ", 1, 2, 1),FCE("Ꝑ", 0, 2, 1),FCE("ꝑ", 1, 2, 1),
+FCE("Ϣ", 0, 2, 1),FCE("ϣ", 1, 2, 1),FCE("Ϥ", 0, 2, 1),FCE("ϥ", 1, 2, 1),
+FCE("Ⲧ", 0, 2, 1),FCE("ⲧ", 1, 2, 1),FCE("Ϧ", 0, 2, 1),FCE("ϧ", 1, 2, 1),
+FCE("𐐠", 0, 2, 1),FCE("𐑈", 1, 2, 1),FCE("Ϩ", 0, 2, 1),FCE("ϩ", 1, 2, 1),
+FCE("Ⳣ", 0, 2, 1),FCE("ⳣ", 1, 2, 1),FCE("Ϫ", 0, 2, 1),FCE("ϫ", 1, 2, 1),
+FCE("Ϭ", 0, 2, 1),FCE("ϭ", 1, 2, 1),FCE("Ꝓ", 0, 2, 1),FCE("ꝓ", 1, 2, 1),
+FCE("Ϯ", 0, 2, 1),FCE("ϯ", 1, 2, 1),FCE("Κ", 0, 3, 1),FCE("κ", 1, 3, 1),
+FCE("ϰ", 2, 3, 1),FCE("Ρ", 0, 3, 1),FCE("ρ", 1, 3, 1),FCE("ϱ", 2, 3, 1),
+FCE("Θ", 0, 4, 1),FCE("θ", 1, 4, 1),FCE("ϑ", 2, 4, 1),FCE("ϴ", 3, 4, 1),
+FCE("Ε", 0, 3, 1),FCE("ε", 1, 3, 1),FCE("ϵ", 2, 3, 1),FCE("Ϸ", 0, 2, 1),
+FCE("ϸ", 1, 2, 1),FCE("ϲ", 0, 2, 1),FCE("Ϲ", 1, 2, 1),FCE("Ϻ", 0, 2, 1),
+FCE("ϻ", 1, 2, 1),FCE("ͻ", 0, 2, 1),FCE("Ͻ", 1, 2, 1),FCE("ͼ", 0, 2, 1),
+FCE("Ͼ", 1, 2, 1),FCE("ͽ", 0, 2, 1),FCE("Ͽ", 1, 2, 1),FCE("Ѐ", 0, 2, 1),
+FCE("ѐ", 1, 2, 1),FCE("Ё", 0, 2, 1),FCE("ё", 1, 2, 1),FCE("Ђ", 0, 2, 1),
+FCE("ђ", 1, 2, 1),FCE("Ѓ", 0, 2, 1),FCE("ѓ", 1, 2, 1),FCE("Є", 0, 2, 1),
+FCE("є", 1, 2, 1),FCE("Ѕ", 0, 2, 1),FCE("ѕ", 1, 2, 1),FCE("І", 0, 2, 1),
+FCE("і", 1, 2, 1),FCE("Ї", 0, 2, 1),FCE("ї", 1, 2, 1),FCE("Ј", 0, 2, 1),
+FCE("ј", 1, 2, 1),FCE("Љ", 0, 2, 1),FCE("љ", 1, 2, 1),FCE("Њ", 0, 2, 1),
+FCE("њ", 1, 2, 1),FCE("Ћ", 0, 2, 1),FCE("ћ", 1, 2, 1),FCE("Ќ", 0, 2, 1),
+FCE("ќ", 1, 2, 1),FCE("Ѝ", 0, 2, 1),FCE("ѝ", 1, 2, 1),FCE("Ў", 0, 2, 1),
+FCE("ў", 1, 2, 1),FCE("Џ", 0, 2, 1),FCE("џ", 1, 2, 1),FCE("А", 0, 2, 1),
+FCE("а", 1, 2, 1),FCE("Б", 0, 2, 1),FCE("б", 1, 2, 1),FCE("В", 0, 2, 1),
+FCE("в", 1, 2, 1),FCE("Г", 0, 2, 1),FCE("г", 1, 2, 1),FCE("Д", 0, 2, 1),
+FCE("д", 1, 2, 1),FCE("Е", 0, 2, 1),FCE("е", 1, 2, 1),FCE("Ж", 0, 2, 1),
+FCE("ж", 1, 2, 1),FCE("З", 0, 2, 1),FCE("з", 1, 2, 1),FCE("И", 0, 2, 1),
+FCE("и", 1, 2, 1),FCE("Й", 0, 2, 1),FCE("й", 1, 2, 1),FCE("К", 0, 2, 1),
+FCE("к", 1, 2, 1),FCE("Л", 0, 2, 1),FCE("л", 1, 2, 1),FCE("М", 0, 2, 1),
+FCE("м", 1, 2, 1),FCE("Н", 0, 2, 1),FCE("н", 1, 2, 1),FCE("О", 0, 2, 1),
+FCE("о", 1, 2, 1),FCE("П", 0, 2, 1),FCE("п", 1, 2, 1),FCE("Р", 0, 2, 1),
+FCE("р", 1, 2, 1),FCE("С", 0, 2, 1),FCE("с", 1, 2, 1),FCE("Т", 0, 2, 1),
+FCE("т", 1, 2, 1),FCE("У", 0, 2, 1),FCE("у", 1, 2, 1),FCE("Ф", 0, 2, 1),
+FCE("ф", 1, 2, 1),FCE("Х", 0, 2, 1),FCE("х", 1, 2, 1),FCE("Ц", 0, 2, 1),
+FCE("ц", 1, 2, 1),FCE("Ч", 0, 2, 1),FCE("ч", 1, 2, 1),FCE("Ш", 0, 2, 1),
+FCE("ш", 1, 2, 1),FCE("Щ", 0, 2, 1),FCE("щ", 1, 2, 1),FCE("Ъ", 0, 2, 1),
+FCE("ъ", 1, 2, 1),FCE("Ы", 0, 2, 1),FCE("ы", 1, 2, 1),FCE("Ь", 0, 2, 1),
+FCE("ь", 1, 2, 1),FCE("Э", 0, 2, 1),FCE("э", 1, 2, 1),FCE("Ю", 0, 2, 1),
+FCE("ю", 1, 2, 1),FCE("Я", 0, 2, 1),FCE("я", 1, 2, 1),FCE("Z", 0, 2, 1),
+FCE("z", 1, 2, 1),FCE("Ⲵ", 0, 2, 1),FCE("ⲵ", 1, 2, 1),FCE("µ", 0, 3, 1),
+FCE("Μ", 1, 3, 1),FCE("μ", 2, 3, 1),FCE("𐐣", 0, 2, 1),FCE("𐑋", 1, 2, 1),
+FCE("Ⓐ", 0, 2, 1),FCE("ⓐ", 1, 2, 1),FCE("Ⓒ", 0, 2, 1),FCE("ⓒ", 1, 2, 1),
+FCE("L", 0, 2, 1),FCE("l", 1, 2, 1),FCE("𐐡", 0, 2, 1),FCE("𐑉", 1, 2, 1),
+FCE("Ⓔ", 0, 2, 1),FCE("ⓔ", 1, 2, 1),FCE("𐐙", 0, 2, 1),FCE("𐑁", 1, 2, 1),
+FCE("Ѡ", 0, 2, 1),FCE("ѡ", 1, 2, 1),FCE("Ѣ", 0, 2, 1),FCE("ѣ", 1, 2, 1),
+FCE("ᵽ", 0, 2, 1),FCE("Ᵽ", 1, 2, 1),FCE("Ѥ", 0, 2, 1),FCE("ѥ", 1, 2, 1),
+FCE("Ѧ", 0, 2, 1),FCE("ѧ", 1, 2, 1),FCE("Ⱨ", 0, 2, 1),FCE("ⱨ", 1, 2, 1),
+FCE("Ѩ", 0, 2, 1),FCE("ѩ", 1, 2, 1),FCE("Ⓖ", 0, 2, 1),FCE("ⓖ", 1, 2, 1),
+FCE("Ѫ", 0, 2, 1),FCE("ѫ", 1, 2, 1),FCE("Ⱬ", 0, 2, 1),FCE("ⱬ", 1, 2, 1),
+FCE("Ѭ", 0, 2, 1),FCE("ѭ", 1, 2, 1),FCE("ɑ", 0, 2, 1),FCE("Ɑ", 1, 2, 1),
+FCE("Ѯ", 0, 2, 1),FCE("ѯ", 1, 2, 1),FCE("ɐ", 0, 2, 1),FCE("Ɐ", 1, 2, 1),
+FCE("Ѱ", 0, 2, 1),FCE("ѱ", 1, 2, 1),FCE("Ꝩ", 0, 2, 1),FCE("ꝩ", 1, 2, 1),
+FCE("Ѳ", 0, 2, 1),FCE("ѳ", 1, 2, 1),FCE("Ѵ", 0, 2, 1),FCE("ѵ", 1, 2, 1),
+FCE("Ⓘ", 0, 2, 1),FCE("ⓘ", 1, 2, 1),FCE("Ѷ", 0, 2, 1),FCE("ѷ", 1, 2, 1),
+FCE("Ѹ", 0, 2, 1),FCE("ѹ", 1, 2, 1),FCE("Ѻ", 0, 2, 1),FCE("ѻ", 1, 2, 1),
+FCE("Ѽ", 0, 2, 1),FCE("ѽ", 1, 2, 1),FCE("Ꝫ", 0, 2, 1),FCE("ꝫ", 1, 2, 1),
+FCE("Ѿ", 0, 2, 1),FCE("ѿ", 1, 2, 1),FCE("ɀ", 0, 2, 1),FCE("Ɀ", 1, 2, 1),
+FCE("Ҁ", 0, 2, 1),FCE("ҁ", 1, 2, 1),FCE("Ⴠ", 0, 2, 1),FCE("ⴠ", 1, 2, 1),
+FCE("Ⲃ", 0, 2, 1),FCE("ⲃ", 1, 2, 1),FCE("Ⲅ", 0, 2, 1),FCE("ⲅ", 1, 2, 1),
+FCE("Ⲇ", 0, 2, 1),FCE("ⲇ", 1, 2, 1),FCE("Ⴡ", 0, 2, 1),FCE("ⴡ", 1, 2, 1),
+FCE("Ⲉ", 0, 2, 1),FCE("ⲉ", 1, 2, 1),FCE("Ꝭ", 0, 2, 1),FCE("ꝭ", 1, 2, 1),
+FCE("Ҋ", 0, 2, 1),FCE("ҋ", 1, 2, 1),FCE("Ҍ", 0, 2, 1),FCE("ҍ", 1, 2, 1),
+FCE("Â", 0, 2, 1),FCE("â", 1, 2, 1),FCE("Ҏ", 0, 2, 1),FCE("ҏ", 1, 2, 1),
+FCE("Ґ", 0, 2, 1),FCE("ґ", 1, 2, 1),FCE("Ғ", 0, 2, 1),FCE("ғ", 1, 2, 1),
+FCE("Ⴣ", 0, 2, 1),FCE("ⴣ", 1, 2, 1),FCE("Ҕ", 0, 2, 1),FCE("ҕ", 1, 2, 1),
+FCE("Ꝯ", 0, 2, 1),FCE("ꝯ", 1, 2, 1),FCE("Җ", 0, 2, 1),FCE("җ", 1, 2, 1),
+FCE("Ҙ", 0, 2, 1),FCE("ҙ", 1, 2, 1),FCE("Ä", 0, 2, 1),FCE("ä", 1, 2, 1),
+FCE("Қ", 0, 2, 1),FCE("қ", 1, 2, 1),FCE("𐐦", 0, 2, 1),FCE("𐑎", 1, 2, 1),
+FCE("Ҝ", 0, 2, 1),FCE("ҝ", 1, 2, 1),FCE("Ҟ", 0, 2, 1),FCE("ҟ", 1, 2, 1),
+FCE("Ⴥ", 0, 2, 1),FCE("ⴥ", 1, 2, 1),FCE("Ҡ", 0, 2, 1),FCE("ҡ", 1, 2, 1),
+FCE("Ң", 0, 2, 1),FCE("ң", 1, 2, 1),FCE("Ҥ", 0, 2, 1),FCE("ҥ", 1, 2, 1),
+FCE("Ⳇ", 0, 2, 1),FCE("ⳇ", 1, 2, 1),FCE("Ҧ", 0, 2, 1),FCE("ҧ", 1, 2, 1),
+FCE("Ҩ", 0, 2, 1),FCE("ҩ", 1, 2, 1),FCE("Ⱡ", 0, 2, 1),FCE("ⱡ", 1, 2, 1),
+FCE("Ҫ", 0, 2, 1),FCE("ҫ", 1, 2, 1),FCE("Ⴧ", 0, 2, 1),FCE("ⴧ", 1, 2, 1),
+FCE("Ҭ", 0, 2, 1),FCE("ҭ", 1, 2, 1),FCE("𐐓", 0, 2, 1),FCE("𐐻", 1, 2, 1),
+FCE("Ү", 0, 2, 1),FCE("ү", 1, 2, 1),FCE("Ұ", 0, 2, 1),FCE("ұ", 1, 2, 1),
+FCE("Ⳉ", 0, 2, 1),FCE("ⳉ", 1, 2, 1),FCE("Ҳ", 0, 2, 1),FCE("ҳ", 1, 2, 1),
+FCE("Ҵ", 0, 2, 1),FCE("ҵ", 1, 2, 1),FCE("Ҷ", 0, 2, 1),FCE("ҷ", 1, 2, 1),
+FCE("Ⓑ", 0, 2, 1),FCE("ⓑ", 1, 2, 1),FCE("Ҹ", 0, 2, 1),FCE("ҹ", 1, 2, 1),
+FCE("Ⓓ", 0, 2, 1),FCE("ⓓ", 1, 2, 1),FCE("Һ", 0, 2, 1),FCE("һ", 1, 2, 1),
+FCE("Ⓕ", 0, 2, 1),FCE("ⓕ", 1, 2, 1),FCE("Ҽ", 0, 2, 1),FCE("ҽ", 1, 2, 1),
+FCE("Ⓗ", 0, 2, 1),FCE("ⓗ", 1, 2, 1),FCE("Ҿ", 0, 2, 1),FCE("ҿ", 1, 2, 1),
+FCE("Ⓙ", 0, 2, 1),FCE("ⓙ", 1, 2, 1),FCE("Ӏ", 0, 2, 1),FCE("ӏ", 1, 2, 1),
+FCE("Ӂ", 0, 2, 1),FCE("ӂ", 1, 2, 1),FCE("Ⓜ", 0, 2, 1),FCE("ⓜ", 1, 2, 1),
+FCE("Ӄ", 0, 2, 1),FCE("ӄ", 1, 2, 1),FCE("Ⓞ", 0, 2, 1),FCE("ⓞ", 1, 2, 1),
+FCE("Ӆ", 0, 2, 1),FCE("ӆ", 1, 2, 1),FCE("Ⓠ", 0, 2, 1),FCE("ⓠ", 1, 2, 1),
+FCE("Ӈ", 0, 2, 1),FCE("ӈ", 1, 2, 1),FCE("Ⓢ", 0, 2, 1),FCE("ⓢ", 1, 2, 1),
+FCE("Ӊ", 0, 2, 1),FCE("ӊ", 1, 2, 1),FCE("Ⓤ", 0, 2, 1),FCE("ⓤ", 1, 2, 1),
+FCE("Ӌ", 0, 2, 1),FCE("ӌ", 1, 2, 1),FCE("Ⓦ", 0, 2, 1),FCE("ⓦ", 1, 2, 1),
+FCE("Ӎ", 0, 2, 1),FCE("ӎ", 1, 2, 1),FCE("Ⓨ", 0, 2, 1),FCE("ⓨ", 1, 2, 1),
+FCE("Ⴭ", 0, 2, 1),FCE("ⴭ", 1, 2, 1),FCE("Ӑ", 0, 2, 1),FCE("ӑ", 1, 2, 1),
+FCE("Ӓ", 0, 2, 1),FCE("ӓ", 1, 2, 1),FCE("Ӕ", 0, 2, 1),FCE("ӕ", 1, 2, 1),
+FCE("Ⳏ", 0, 2, 1),FCE("ⳏ", 1, 2, 1),FCE("Ӗ", 0, 2, 1),FCE("ӗ", 1, 2, 1),
+FCE("Ꝺ", 0, 2, 1),FCE("ꝺ", 1, 2, 1),FCE("Ә", 0, 2, 1),FCE("ә", 1, 2, 1),
+FCE("Ӛ", 0, 2, 1),FCE("ӛ", 1, 2, 1),FCE("Ⓩ", 0, 2, 1),FCE("ⓩ", 1, 2, 1),
+FCE("Ӝ", 0, 2, 1),FCE("ӝ", 1, 2, 1),FCE("Ӟ", 0, 2, 1),FCE("ӟ", 1, 2, 1),
+FCE("Ӡ", 0, 2, 1),FCE("ӡ", 1, 2, 1),FCE("Ⳑ", 0, 2, 1),FCE("ⳑ", 1, 2, 1),
+FCE("Ӣ", 0, 2, 1),FCE("ӣ", 1, 2, 1),FCE("Ӥ", 0, 2, 1),FCE("ӥ", 1, 2, 1),
+FCE("ɫ", 0, 2, 1),FCE("Ɫ", 1, 2, 1),FCE("Ӧ", 0, 2, 1),FCE("ӧ", 1, 2, 1),
+FCE("Ө", 0, 2, 1),FCE("ө", 1, 2, 1),FCE("Ӫ", 0, 2, 1),FCE("ӫ", 1, 2, 1),
+FCE("Ⅎ", 0, 2, 1),FCE("ⅎ", 1, 2, 1),FCE("Ӭ", 0, 2, 1),FCE("ӭ", 1, 2, 1),
+FCE("Ⳓ", 0, 2, 1),FCE("ⳓ", 1, 2, 1),FCE("Ӯ", 0, 2, 1),FCE("ӯ", 1, 2, 1),
+FCE("Ӱ", 0, 2, 1),FCE("ӱ", 1, 2, 1),FCE("𐐢", 0, 2, 1),FCE("𐑊", 1, 2, 1),
+FCE("Ӳ", 0, 2, 1),FCE("ӳ", 1, 2, 1),FCE("Ӵ", 0, 2, 1),FCE("ӵ", 1, 2, 1),
+FCE("Ӷ", 0, 2, 1),FCE("ӷ", 1, 2, 1),FCE("Ӹ", 0, 2, 1),FCE("ӹ", 1, 2, 1),
+FCE("Ⳕ", 0, 2, 1),FCE("ⳕ", 1, 2, 1),FCE("Ӻ", 0, 2, 1),FCE("ӻ", 1, 2, 1),
+FCE("Ӽ", 0, 2, 1),FCE("ӽ", 1, 2, 1),FCE("Ӿ", 0, 2, 1),FCE("ӿ", 1, 2, 1),
+FCE("Ԁ", 0, 2, 1),FCE("ԁ", 1, 2, 1),FCE("Ꞁ", 0, 2, 1),FCE("ꞁ", 1, 2, 1),
+FCE("Ԃ", 0, 2, 1),FCE("ԃ", 1, 2, 1),FCE("Ԅ", 0, 2, 1),FCE("ԅ", 1, 2, 1),
+FCE("Ⳗ", 0, 2, 1),FCE("ⳗ", 1, 2, 1),FCE("Ԇ", 0, 2, 1),FCE("ԇ", 1, 2, 1),
+FCE("Ԉ", 0, 2, 1),FCE("ԉ", 1, 2, 1),FCE("Ԋ", 0, 2, 1),FCE("ԋ", 1, 2, 1),
+FCE("Ԍ", 0, 2, 1),FCE("ԍ", 1, 2, 1),FCE("Ꞃ", 0, 2, 1),FCE("ꞃ", 1, 2, 1),
+FCE("Ԏ", 0, 2, 1),FCE("ԏ", 1, 2, 1),FCE("Ԑ", 0, 2, 1),FCE("ԑ", 1, 2, 1),
+FCE("Ⳙ", 0, 2, 1),FCE("ⳙ", 1, 2, 1),FCE("Ԓ", 0, 2, 1),FCE("ԓ", 1, 2, 1),
+FCE("Ԕ", 0, 2, 1),FCE("ԕ", 1, 2, 1),FCE("Ԗ", 0, 2, 1),FCE("ԗ", 1, 2, 1),
+FCE("Ԙ", 0, 2, 1),FCE("ԙ", 1, 2, 1),FCE("Ꞅ", 0, 2, 1),FCE("ꞅ", 1, 2, 1),
+FCE("Ԛ", 0, 2, 1),FCE("ԛ", 1, 2, 1),FCE("Ⲩ", 0, 2, 1),FCE("ⲩ", 1, 2, 1),
+FCE("Ԝ", 0, 2, 1),FCE("ԝ", 1, 2, 1),FCE("Ⳛ", 0, 2, 1),FCE("ⳛ", 1, 2, 1),
+FCE("Ԟ", 0, 2, 1),FCE("ԟ", 1, 2, 1),FCE("Ԡ", 0, 2, 1),FCE("ԡ", 1, 2, 1),
+FCE("Ԣ", 0, 2, 1),FCE("ԣ", 1, 2, 1),FCE("Ԥ", 0, 2, 1),FCE("ԥ", 1, 2, 1),
+FCE("Ꞇ", 0, 2, 1),FCE("ꞇ", 1, 2, 1),FCE("Ԧ", 0, 2, 1),FCE("ԧ", 1, 2, 1),
+FCE("Ⱐ", 0, 2, 1),FCE("ⱐ", 1, 2, 1),FCE("Ⳝ", 0, 2, 1),FCE("ⳝ", 1, 2, 1),
+FCE("Ա", 0, 2, 1),FCE("ա", 1, 2, 1),FCE("Բ", 0, 2, 1),FCE("բ", 1, 2, 1),
+FCE("Գ", 0, 2, 1),FCE("գ", 1, 2, 1),FCE("Դ", 0, 2, 1),FCE("դ", 1, 2, 1),
+FCE("Ե", 0, 2, 1),FCE("ե", 1, 2, 1),FCE("Զ", 0, 2, 1),FCE("զ", 1, 2, 1),
+FCE("Է", 0, 2, 1),FCE("է", 1, 2, 1),FCE("Ը", 0, 2, 1),FCE("ը", 1, 2, 1),
+FCE("Թ", 0, 2, 1),FCE("թ", 1, 2, 1),FCE("Ժ", 0, 2, 1),FCE("ժ", 1, 2, 1),
+FCE("Ի", 0, 2, 1),FCE("ի", 1, 2, 1),FCE("Լ", 0, 2, 1),FCE("լ", 1, 2, 1),
+FCE("Խ", 0, 2, 1),FCE("խ", 1, 2, 1),FCE("Ծ", 0, 2, 1),FCE("ծ", 1, 2, 1),
+FCE("Կ", 0, 2, 1),FCE("կ", 1, 2, 1),FCE("Հ", 0, 2, 1),FCE("հ", 1, 2, 1),
+FCE("Ձ", 0, 2, 1),FCE("ձ", 1, 2, 1),FCE("Ղ", 0, 2, 1),FCE("ղ", 1, 2, 1),
+FCE("Ճ", 0, 2, 1),FCE("ճ", 1, 2, 1),FCE("Մ", 0, 2, 1),FCE("մ", 1, 2, 1),
+FCE("Յ", 0, 2, 1),FCE("յ", 1, 2, 1),FCE("Ն", 0, 2, 1),FCE("ն", 1, 2, 1),
+FCE("Շ", 0, 2, 1),FCE("շ", 1, 2, 1),FCE("Ո", 0, 2, 1),FCE("ո", 1, 2, 1),
+FCE("Չ", 0, 2, 1),FCE("չ", 1, 2, 1),FCE("Պ", 0, 2, 1),FCE("պ", 1, 2, 1),
+FCE("Ջ", 0, 2, 1),FCE("ջ", 1, 2, 1),FCE("Ռ", 0, 2, 1),FCE("ռ", 1, 2, 1),
+FCE("Ս", 0, 2, 1),FCE("ս", 1, 2, 1),FCE("Վ", 0, 2, 1),FCE("վ", 1, 2, 1),
+FCE("Տ", 0, 2, 1),FCE("տ", 1, 2, 1),FCE("Ր", 0, 2, 1),FCE("ր", 1, 2, 1),
+FCE("Ց", 0, 2, 1),FCE("ց", 1, 2, 1),FCE("Ւ", 0, 2, 1),FCE("ւ", 1, 2, 1),
+FCE("Փ", 0, 2, 1),FCE("փ", 1, 2, 1),FCE("Ք", 0, 2, 1),FCE("ք", 1, 2, 1),
+FCE("Օ", 0, 2, 1),FCE("օ", 1, 2, 1),FCE("Ֆ", 0, 2, 1),FCE("ֆ", 1, 2, 1),
+FCE("Ⲫ", 0, 2, 1),FCE("ⲫ", 1, 2, 1),FCE("Ꞑ", 0, 2, 1),FCE("ꞑ", 1, 2, 1),
+FCE("Ⱒ", 0, 2, 1),FCE("ⱒ", 1, 2, 1),FCE("Ꞓ", 0, 2, 1),FCE("ꞓ", 1, 2, 1),
+FCE("Ⱓ", 0, 2, 1),FCE("ⱓ", 1, 2, 1),FCE("Ⳬ", 0, 2, 1),FCE("ⳬ", 1, 2, 1),
+FCE("Ⳋ", 0, 2, 1),FCE("ⳋ", 1, 2, 1),FCE("և", 0, 2, 1),FCE("եւ", 1, 2, 2),
+FCE("Ꙃ", 0, 2, 1),FCE("ꙃ", 1, 2, 1),FCE("Ⳮ", 0, 2, 1),FCE("ⳮ", 1, 2, 1),
+FCE("Ⲭ", 0, 2, 1),FCE("ⲭ", 1, 2, 1),FCE("Ꙅ", 0, 2, 1),FCE("ꙅ", 1, 2, 1),
+FCE("Ⱔ", 0, 2, 1),FCE("ⱔ", 1, 2, 1),FCE("Ꝕ", 0, 2, 1),FCE("ꝕ", 1, 2, 1),
+FCE("Ꙇ", 0, 2, 1),FCE("ꙇ", 1, 2, 1),FCE("Ⳳ", 0, 2, 1),FCE("ⳳ", 1, 2, 1),
+FCE("𐐈", 0, 2, 1),FCE("𐐰", 1, 2, 1),FCE("Ꙉ", 0, 2, 1),FCE("ꙉ", 1, 2, 1),
+FCE("Ⱕ", 0, 2, 1),FCE("ⱕ", 1, 2, 1),FCE("Ꞡ", 0, 2, 1),FCE("ꞡ", 1, 2, 1),
+FCE("Ꙍ", 0, 2, 1),FCE("ꙍ", 1, 2, 1),FCE("Ꞣ", 0, 2, 1),FCE("ꞣ", 1, 2, 1),
+FCE("Ⲯ", 0, 2, 1),FCE("ⲯ", 1, 2, 1),FCE("Ꙏ", 0, 2, 1),FCE("ꙏ", 1, 2, 1),
+FCE("Ꞥ", 0, 2, 1),FCE("ꞥ", 1, 2, 1),FCE("Ꙑ", 0, 2, 1),FCE("ꙑ", 1, 2, 1),
+FCE("Ꞧ", 0, 2, 1),FCE("ꞧ", 1, 2, 1),FCE("Ꞌ", 0, 2, 1),FCE("ꞌ", 1, 2, 1),
+FCE("Ꙓ", 0, 2, 1),FCE("ꙓ", 1, 2, 1),FCE("Ꞩ", 0, 2, 1),FCE("ꞩ", 1, 2, 1),
+FCE("Ꙕ", 0, 2, 1),FCE("ꙕ", 1, 2, 1),FCE("ɦ", 0, 2, 1),FCE("Ɦ", 1, 2, 1),
+FCE("Ḁ", 0, 2, 1),FCE("ḁ", 1, 2, 1),FCE("Ḃ", 0, 2, 1),FCE("ḃ", 1, 2, 1),
+FCE("Ḅ", 0, 2, 1),FCE("ḅ", 1, 2, 1),FCE("Ⱏ", 0, 2, 1),FCE("ⱏ", 1, 2, 1),
+FCE("Ḇ", 0, 2, 1),FCE("ḇ", 1, 2, 1),FCE("𐐎", 0, 2, 1),FCE("𐐶", 1, 2, 1),
+FCE("Ḉ", 0, 2, 1),FCE("ḉ", 1, 2, 1),FCE("Ḋ", 0, 2, 1),FCE("ḋ", 1, 2, 1),
+FCE("Ⲱ", 0, 2, 1),FCE("ⲱ", 1, 2, 1),FCE("Ḍ", 0, 2, 1),FCE("ḍ", 1, 2, 1),
+FCE("Ḏ", 0, 2, 1),FCE("ḏ", 1, 2, 1),FCE("Ḑ", 0, 2, 1),FCE("ḑ", 1, 2, 1),
+FCE("Ꙙ", 0, 2, 1),FCE("ꙙ", 1, 2, 1),FCE("Ḓ", 0, 2, 1),FCE("ḓ", 1, 2, 1),
+FCE("Ḕ", 0, 2, 1),FCE("ḕ", 1, 2, 1),FCE("Ⓧ", 0, 2, 1),FCE("ⓧ", 1, 2, 1),
+FCE("Ḗ", 0, 2, 1),FCE("ḗ", 1, 2, 1),FCE("Ḙ", 0, 2, 1),FCE("ḙ", 1, 2, 1),
+FCE("Ḛ", 0, 2, 1),FCE("ḛ", 1, 2, 1),FCE("Ḝ", 0, 2, 1),FCE("ḝ", 1, 2, 1),
+FCE("Ꙛ", 0, 2, 1),FCE("ꙛ", 1, 2, 1),FCE("Ḟ", 0, 2, 1),FCE("ḟ", 1, 2, 1),
+FCE("Ḡ", 0, 2, 1),FCE("ḡ", 1, 2, 1),FCE("Ḣ", 0, 2, 1),FCE("ḣ", 1, 2, 1),
+FCE("Ḥ", 0, 2, 1),FCE("ḥ", 1, 2, 1),FCE("Ḧ", 0, 2, 1),FCE("ḧ", 1, 2, 1),
+FCE("Ḩ", 0, 2, 1),FCE("ḩ", 1, 2, 1),FCE("Ꙝ", 0, 2, 1),FCE("ꙝ", 1, 2, 1),
+FCE("Ḫ", 0, 2, 1),FCE("ḫ", 1, 2, 1),FCE("Ḭ", 0, 2, 1),FCE("ḭ", 1, 2, 1),
+FCE("Ḯ", 0, 2, 1),FCE("ḯ", 1, 2, 1),FCE("Ḱ", 0, 2, 1),FCE("ḱ", 1, 2, 1),
+FCE("Ḳ", 0, 2, 1),FCE("ḳ", 1, 2, 1),FCE("Ḵ", 0, 2, 1),FCE("ḵ", 1, 2, 1),
+FCE("Ꙟ", 0, 2, 1),FCE("ꙟ", 1, 2, 1),FCE("Ḷ", 0, 2, 1),FCE("ḷ", 1, 2, 1),
+FCE("Ḹ", 0, 2, 1),FCE("ḹ", 1, 2, 1),FCE("Ḻ", 0, 2, 1),FCE("ḻ", 1, 2, 1),
+FCE("Ḽ", 0, 2, 1),FCE("ḽ", 1, 2, 1),FCE("Ḿ", 0, 2, 1),FCE("ḿ", 1, 2, 1),
+FCE("Ṁ", 0, 2, 1),FCE("ṁ", 1, 2, 1),FCE("Ꙡ", 0, 2, 1),FCE("ꙡ", 1, 2, 1),
+FCE("Ṃ", 0, 2, 1),FCE("ṃ", 1, 2, 1),FCE("Ṅ", 0, 2, 1),FCE("ṅ", 1, 2, 1),
+FCE("Ṇ", 0, 2, 1),FCE("ṇ", 1, 2, 1),FCE("Ⲳ", 0, 2, 1),FCE("ⲳ", 1, 2, 1),
+FCE("Ṉ", 0, 2, 1),FCE("ṉ", 1, 2, 1),FCE("Ⳁ", 0, 2, 1),FCE("ⳁ", 1, 2, 1),
+FCE("Ṋ", 0, 2, 1),FCE("ṋ", 1, 2, 1),FCE("Ṍ", 0, 2, 1),FCE("ṍ", 1, 2, 1),
+FCE("Ꙣ", 0, 2, 1),FCE("ꙣ", 1, 2, 1),FCE("Ṏ", 0, 2, 1),FCE("ṏ", 1, 2, 1),
+FCE("Ṑ", 0, 2, 1),FCE("ṑ", 1, 2, 1),FCE("Ṓ", 0, 2, 1),FCE("ṓ", 1, 2, 1),
+FCE("Ṕ", 0, 2, 1),FCE("ṕ", 1, 2, 1),FCE("Ṗ", 0, 2, 1),FCE("ṗ", 1, 2, 1),
+FCE("Ṙ", 0, 2, 1),FCE("ṙ", 1, 2, 1),FCE("Ꙥ", 0, 2, 1),FCE("ꙥ", 1, 2, 1),
+FCE("Ṛ", 0, 2, 1),FCE("ṛ", 1, 2, 1),FCE("Ṝ", 0, 2, 1),FCE("ṝ", 1, 2, 1),
+FCE("Ṟ", 0, 2, 1),FCE("ṟ", 1, 2, 1),FCE("Ṡ", 0, 3, 1),FCE("ṡ", 1, 3, 1),
+FCE("ẛ", 2, 3, 1),FCE("Ṣ", 0, 2, 1),FCE("ṣ", 1, 2, 1),FCE("𐐤", 0, 2, 1),
+FCE("𐑌", 1, 2, 1),FCE("Ṥ", 0, 2, 1),FCE("ṥ", 1, 2, 1),FCE("Ꙧ", 0, 2, 1),
+FCE("ꙧ", 1, 2, 1),FCE("Ṧ", 0, 2, 1),FCE("ṧ", 1, 2, 1),FCE("Ṩ", 0, 2, 1),
+FCE("ṩ", 1, 2, 1),FCE("Ṫ", 0, 2, 1),FCE("ṫ", 1, 2, 1),FCE("Ṭ", 0, 2, 1),
+FCE("ṭ", 1, 2, 1),FCE("Ṯ", 0, 2, 1),FCE("ṯ", 1, 2, 1),FCE("Ṱ", 0, 2, 1),
+FCE("ṱ", 1, 2, 1),FCE("Ꙩ", 0, 2, 1),FCE("ꙩ", 1, 2, 1),FCE("Ṳ", 0, 2, 1),
+FCE("ṳ", 1, 2, 1),FCE("Ṵ", 0, 2, 1),FCE("ṵ", 1, 2, 1),FCE("Ṷ", 0, 2, 1),
+FCE("ṷ", 1, 2, 1),FCE("Ⲿ", 0, 2, 1),FCE("ⲿ", 1, 2, 1),FCE("Ṹ", 0, 2, 1),
+FCE("ṹ", 1, 2, 1),FCE("Ṻ", 0, 2, 1),FCE("ṻ", 1, 2, 1),FCE("Ṽ", 0, 2, 1),
+FCE("ṽ", 1, 2, 1),FCE("Ꙫ", 0, 2, 1),FCE("ꙫ", 1, 2, 1),FCE("Ṿ", 0, 2, 1),
+FCE("ṿ", 1, 2, 1),FCE("Ẁ", 0, 2, 1),FCE("ẁ", 1, 2, 1),FCE("Ẃ", 0, 2, 1),
+FCE("ẃ", 1, 2, 1),FCE("Ẅ", 0, 2, 1),FCE("ẅ", 1, 2, 1),FCE("Ẇ", 0, 2, 1),
+FCE("ẇ", 1, 2, 1),FCE("Ẉ", 0, 2, 1),FCE("ẉ", 1, 2, 1),FCE("Ꙭ", 0, 2, 1),
+FCE("ꙭ", 1, 2, 1),FCE("Ẋ", 0, 2, 1),FCE("ẋ", 1, 2, 1),FCE("Ẍ", 0, 2, 1),
+FCE("ẍ", 1, 2, 1),FCE("Ẏ", 0, 2, 1),FCE("ẏ", 1, 2, 1),FCE("Ẑ", 0, 2, 1),
+FCE("ẑ", 1, 2, 1),FCE("Ẓ", 0, 2, 1),FCE("ẓ", 1, 2, 1),FCE("Ẕ", 0, 2, 1),
+FCE("ẕ", 1, 2, 1),FCE("ẖ", 0, 2, 1),FCE("ẖ", 1, 2, 2),FCE("ẗ", 0, 2, 1),
+FCE("ẗ", 1, 2, 2),FCE("ẘ", 0, 2, 1),FCE("ẘ", 1, 2, 2),FCE("ẙ", 0, 2, 1),
+FCE("ẙ", 1, 2, 2),FCE("ẚ", 0, 2, 1),FCE("aʾ", 1, 2, 2),FCE("Ṡ", 0, 3, 1),
+FCE("ṡ", 1, 3, 1),FCE("ẛ", 2, 3, 1),FCE("ß", 0, 3, 1),FCE("ẞ", 1, 3, 1),
+FCE("ss", 2, 3, 2),FCE("Ạ", 0, 2, 1),FCE("ạ", 1, 2, 1),FCE("Ả", 0, 2, 1),
+FCE("ả", 1, 2, 1),FCE("Ấ", 0, 2, 1),FCE("ấ", 1, 2, 1),FCE("Ⓟ", 0, 2, 1),
+FCE("ⓟ", 1, 2, 1),FCE("Ầ", 0, 2, 1),FCE("ầ", 1, 2, 1),FCE("Ẩ", 0, 2, 1),
+FCE("ẩ", 1, 2, 1),FCE("Ẫ", 0, 2, 1),FCE("ẫ", 1, 2, 1),FCE("Ậ", 0, 2, 1),
+FCE("ậ", 1, 2, 1),FCE("Ắ", 0, 2, 1),FCE("ắ", 1, 2, 1),FCE("H", 0, 2, 1),
+FCE("h", 1, 2, 1),FCE("Ằ", 0, 2, 1),FCE("ằ", 1, 2, 1),FCE("Ẳ", 0, 2, 1),
+FCE("ẳ", 1, 2, 1),FCE("𐐥", 0, 2, 1),FCE("𐑍", 1, 2, 1),FCE("Ẵ", 0, 2, 1),
+FCE("ẵ", 1, 2, 1),FCE("Ặ", 0, 2, 1),FCE("ặ", 1, 2, 1),FCE("Ẹ", 0, 2, 1),
+FCE("ẹ", 1, 2, 1),FCE("Ẻ", 0, 2, 1),FCE("ẻ", 1, 2, 1),FCE("Ẽ", 0, 2, 1),
+FCE("ẽ", 1, 2, 1),FCE("Ế", 0, 2, 1),FCE("ế", 1, 2, 1),FCE("Ⲷ", 0, 2, 1),
+FCE("ⲷ", 1, 2, 1),FCE("Ề", 0, 2, 1),FCE("ề", 1, 2, 1),FCE("Ể", 0, 2, 1),
+FCE("ể", 1, 2, 1),FCE("Ⲛ", 0, 2, 1),FCE("ⲛ", 1, 2, 1),FCE("Ễ", 0, 2, 1),
+FCE("ễ", 1, 2, 1),FCE("Ệ", 0, 2, 1),FCE("ệ", 1, 2, 1),FCE("Ỉ", 0, 2, 1),
+FCE("ỉ", 1, 2, 1),FCE("Ị", 0, 2, 1),FCE("ị", 1, 2, 1),FCE("Ọ", 0, 2, 1),
+FCE("ọ", 1, 2, 1),FCE("Ỏ", 0, 2, 1),FCE("ỏ", 1, 2, 1),FCE("Ố", 0, 2, 1),
+FCE("ố", 1, 2, 1),FCE("Ồ", 0, 2, 1),FCE("ồ", 1, 2, 1),FCE("Ổ", 0, 2, 1),
+FCE("ổ", 1, 2, 1),FCE("Ỗ", 0, 2, 1),FCE("ỗ", 1, 2, 1),FCE("Ộ", 0, 2, 1),
+FCE("ộ", 1, 2, 1),FCE("Ớ", 0, 2, 1),FCE("ớ", 1, 2, 1),FCE("Ờ", 0, 2, 1),
+FCE("ờ", 1, 2, 1),FCE("Ở", 0, 2, 1),FCE("ở", 1, 2, 1),FCE("Ỡ", 0, 2, 1),
+FCE("ỡ", 1, 2, 1),FCE("Ợ", 0, 2, 1),FCE("ợ", 1, 2, 1),FCE("Ụ", 0, 2, 1),
+FCE("ụ", 1, 2, 1),FCE("Ω", 0, 3, 1),FCE("ω", 1, 3, 1),FCE("Ω", 2, 3, 1),
+FCE("Ủ", 0, 2, 1),FCE("ủ", 1, 2, 1),FCE("Ứ", 0, 2, 1),FCE("ứ", 1, 2, 1),
+FCE("Ừ", 0, 2, 1),FCE("ừ", 1, 2, 1),FCE("J", 0, 2, 1),FCE("j", 1, 2, 1),
+FCE("Ử", 0, 2, 1),FCE("ử", 1, 2, 1),FCE("Ữ", 0, 2, 1),FCE("ữ", 1, 2, 1),
+FCE("Ự", 0, 2, 1),FCE("ự", 1, 2, 1),FCE("Ỳ", 0, 2, 1),FCE("ỳ", 1, 2, 1),
+FCE("Ỵ", 0, 2, 1),FCE("ỵ", 1, 2, 1),FCE("Ỷ", 0, 2, 1),FCE("ỷ", 1, 2, 1),
+FCE("Ỹ", 0, 2, 1),FCE("ỹ", 1, 2, 1),FCE("Ỻ", 0, 2, 1),FCE("ỻ", 1, 2, 1),
+FCE("Ⲹ", 0, 2, 1),FCE("ⲹ", 1, 2, 1),FCE("Ỽ", 0, 2, 1),FCE("ỽ", 1, 2, 1),
+FCE("K", 0, 3, 1),FCE("k", 1, 3, 1),FCE("K", 2, 3, 1),FCE("Ỿ", 0, 2, 1),
+FCE("ỿ", 1, 2, 1),FCE("Ꚁ", 0, 2, 1),FCE("ꚁ", 1, 2, 1),FCE("ἀ", 0, 2, 1),
+FCE("Ἀ", 1, 2, 1),FCE("ἁ", 0, 2, 1),FCE("Ἁ", 1, 2, 1),FCE("ἂ", 0, 2, 1),
+FCE("Ἂ", 1, 2, 1),FCE("ἃ", 0, 2, 1),FCE("Ἃ", 1, 2, 1),FCE("ἄ", 0, 2, 1),
+FCE("Ἄ", 1, 2, 1),FCE("ἅ", 0, 2, 1),FCE("Ἅ", 1, 2, 1),FCE("ἆ", 0, 2, 1),
+FCE("Ἆ", 1, 2, 1),FCE("ἇ", 0, 2, 1),FCE("Ἇ", 1, 2, 1),FCE("𐐘", 0, 2, 1),
+FCE("𐑀", 1, 2, 1),FCE("ɥ", 0, 2, 1),FCE("Ɥ", 1, 2, 1),FCE("ἐ", 0, 2, 1),
+FCE("Ἐ", 1, 2, 1),FCE("ἑ", 0, 2, 1),FCE("Ἑ", 1, 2, 1),FCE("ἒ", 0, 2, 1),
+FCE("Ἒ", 1, 2, 1),FCE("ἓ", 0, 2, 1),FCE("Ἓ", 1, 2, 1),FCE("ἔ", 0, 2, 1),
+FCE("Ἔ", 1, 2, 1),FCE("ἕ", 0, 2, 1),FCE("Ἕ", 1, 2, 1),FCE("A", 0, 2, 1),
+FCE("a", 1, 2, 1),FCE("Ꜣ", 0, 2, 1),FCE("ꜣ", 1, 2, 1),FCE("C", 0, 2, 1),
+FCE("c", 1, 2, 1),FCE("Ꜥ", 0, 2, 1),FCE("ꜥ", 1, 2, 1),FCE("Ꚇ", 0, 2, 1),
+FCE("ꚇ", 1, 2, 1),FCE("Ꜧ", 0, 2, 1),FCE("ꜧ", 1, 2, 1),FCE("G", 0, 2, 1),
+FCE("g", 1, 2, 1),FCE("ἠ", 0, 2, 1),FCE("Ἠ", 1, 2, 1),FCE("ἡ", 0, 2, 1),
+FCE("Ἡ", 1, 2, 1),FCE("ἢ", 0, 2, 1),FCE("Ἢ", 1, 2, 1),FCE("ἣ", 0, 2, 1),
+FCE("Ἣ", 1, 2, 1),FCE("ἤ", 0, 2, 1),FCE("Ἤ", 1, 2, 1),FCE("ἥ", 0, 2, 1),
+FCE("Ἥ", 1, 2, 1),FCE("ἦ", 0, 2, 1),FCE("Ἦ", 1, 2, 1),FCE("ἧ", 0, 2, 1),
+FCE("Ἧ", 1, 2, 1),FCE("P", 0, 2, 1),FCE("p", 1, 2, 1),FCE("Ꚉ", 0, 2, 1),
+FCE("ꚉ", 1, 2, 1),FCE("Ꜳ", 0, 2, 1),FCE("ꜳ", 1, 2, 1),FCE("S", 0, 2, 1),
+FCE("s", 1, 2, 1),FCE("Ꜵ", 0, 2, 1),FCE("ꜵ", 1, 2, 1),FCE("U", 0, 2, 1),
+FCE("u", 1, 2, 1),FCE("Ꜷ", 0, 2, 1),FCE("ꜷ", 1, 2, 1),FCE("Ⲻ", 0, 2, 1),
+FCE("ⲻ", 1, 2, 1),FCE("ἰ", 0, 2, 1),FCE("Ἰ", 1, 2, 1),FCE("ἱ", 0, 2, 1),
+FCE("Ἱ", 1, 2, 1),FCE("ἲ", 0, 2, 1),FCE("Ἲ", 1, 2, 1),FCE("ἳ", 0, 2, 1),
+FCE("Ἳ", 1, 2, 1),FCE("ἴ", 0, 2, 1),FCE("Ἴ", 1, 2, 1),FCE("ἵ", 0, 2, 1),
+FCE("Ἵ", 1, 2, 1),FCE("ἶ", 0, 2, 1),FCE("Ἶ", 1, 2, 1),FCE("ἷ", 0, 2, 1),
+FCE("Ἷ", 1, 2, 1),FCE("Ꝁ", 0, 2, 1),FCE("ꝁ", 1, 2, 1),FCE("Ꝃ", 0, 2, 1),
+FCE("ꝃ", 1, 2, 1),FCE("Ꝅ", 0, 2, 1),FCE("ꝅ", 1, 2, 1),FCE("Ꝇ", 0, 2, 1),
+FCE("ꝇ", 1, 2, 1),FCE("ὀ", 0, 2, 1),FCE("Ὀ", 1, 2, 1),FCE("ὁ", 0, 2, 1),
+FCE("Ὁ", 1, 2, 1),FCE("ὂ", 0, 2, 1),FCE("Ὂ", 1, 2, 1),FCE("ὃ", 0, 2, 1),
+FCE("Ὃ", 1, 2, 1),FCE("ὄ", 0, 2, 1),FCE("Ὄ", 1, 2, 1),FCE("ὅ", 0, 2, 1),
+FCE("Ὅ", 1, 2, 1),FCE("Ꝏ", 0, 2, 1),FCE("ꝏ", 1, 2, 1),FCE("ὐ", 0, 2, 1),
+FCE("ὐ", 1, 2, 2),FCE("ὒ", 0, 2, 1),FCE("ὒ", 1, 2, 3),FCE("ὔ", 0, 2, 1),
+FCE("ὔ", 1, 2, 3),FCE("Ꚏ", 0, 2, 1),FCE("ꚏ", 1, 2, 1),FCE("ὖ", 0, 2, 1),
+FCE("ὖ", 1, 2, 3),FCE("Ꝙ", 0, 2, 1),FCE("ꝙ", 1, 2, 1),FCE("ὑ", 0, 2, 1),
+FCE("Ὑ", 1, 2, 1),FCE("Ꝛ", 0, 2, 1),FCE("ꝛ", 1, 2, 1),FCE("ὓ", 0, 2, 1),
+FCE("Ὓ", 1, 2, 1),FCE("Ꝝ", 0, 2, 1),FCE("ꝝ", 1, 2, 1),FCE("ὕ", 0, 2, 1),
+FCE("Ὕ", 1, 2, 1),FCE("Ꝟ", 0, 2, 1),FCE("ꝟ", 1, 2, 1),FCE("ὗ", 0, 2, 1),
+FCE("Ὗ", 1, 2, 1),FCE("Ꝡ", 0, 2, 1),FCE("ꝡ", 1, 2, 1),FCE("Ꚑ", 0, 2, 1),
+FCE("ꚑ", 1, 2, 1),FCE("Ꝣ", 0, 2, 1),FCE("ꝣ", 1, 2, 1),FCE("N", 0, 2, 1),
+FCE("n", 1, 2, 1),FCE("Ꝥ", 0, 2, 1),FCE("ꝥ", 1, 2, 1),FCE("Ꝧ", 0, 2, 1),
+FCE("ꝧ", 1, 2, 1),FCE("ὠ", 0, 2, 1),FCE("Ὠ", 1, 2, 1),FCE("ὡ", 0, 2, 1),
+FCE("Ὡ", 1, 2, 1),FCE("ὢ", 0, 2, 1),FCE("Ὢ", 1, 2, 1),FCE("ὣ", 0, 2, 1),
+FCE("Ὣ", 1, 2, 1),FCE("ὤ", 0, 2, 1),FCE("Ὤ", 1, 2, 1),FCE("ὥ", 0, 2, 1),
+FCE("Ὥ", 1, 2, 1),FCE("ὦ", 0, 2, 1),FCE("Ὦ", 1, 2, 1),FCE("ὧ", 0, 2, 1),
+FCE("Ὧ", 1, 2, 1),FCE("Ⱌ", 0, 2, 1),FCE("ⱌ", 1, 2, 1),FCE("Ⲽ", 0, 2, 1),
+FCE("ⲽ", 1, 2, 1),FCE("Ꚕ", 0, 2, 1),FCE("ꚕ", 1, 2, 1),FCE("Ꝼ", 0, 2, 1),
+FCE("ꝼ", 1, 2, 1),FCE("ᵹ", 0, 2, 1),FCE("Ᵹ", 1, 2, 1),FCE("Ꝿ", 0, 2, 1),
+FCE("ꝿ", 1, 2, 1),FCE("ᾀ", 0, 3, 1),FCE("ᾈ", 1, 3, 1),FCE("ἀι", 2, 3, 2),
+FCE("ᾁ", 0, 3, 1),FCE("ᾉ", 1, 3, 1),FCE("ἁι", 2, 3, 2),FCE("ᾂ", 0, 3, 1),
+FCE("ᾊ", 1, 3, 1),FCE("ἂι", 2, 3, 2),FCE("ᾃ", 0, 3, 1),FCE("ᾋ", 1, 3, 1),
+FCE("ἃι", 2, 3, 2),FCE("ᾄ", 0, 3, 1),FCE("ᾌ", 1, 3, 1),FCE("ἄι", 2, 3, 2),
+FCE("ᾅ", 0, 3, 1),FCE("ᾍ", 1, 3, 1),FCE("ἅι", 2, 3, 2),FCE("ᾆ", 0, 3, 1),
+FCE("ᾎ", 1, 3, 1),FCE("ἆι", 2, 3, 2),FCE("ᾇ", 0, 3, 1),FCE("ᾏ", 1, 3, 1),
+FCE("ἇι", 2, 3, 2),FCE("ᾀ", 0, 3, 1),FCE("ᾈ", 1, 3, 1),FCE("ἀι", 2, 3, 2),
+FCE("ᾁ", 0, 3, 1),FCE("ᾉ", 1, 3, 1),FCE("ἁι", 2, 3, 2),FCE("ᾂ", 0, 3, 1),
+FCE("ᾊ", 1, 3, 1),FCE("ἂι", 2, 3, 2),FCE("ᾃ", 0, 3, 1),FCE("ᾋ", 1, 3, 1),
+FCE("ἃι", 2, 3, 2),FCE("ᾄ", 0, 3, 1),FCE("ᾌ", 1, 3, 1),FCE("ἄι", 2, 3, 2),
+FCE("ᾅ", 0, 3, 1),FCE("ᾍ", 1, 3, 1),FCE("ἅι", 2, 3, 2),FCE("ᾆ", 0, 3, 1),
+FCE("ᾎ", 1, 3, 1),FCE("ἆι", 2, 3, 2),FCE("ᾇ", 0, 3, 1),FCE("ᾏ", 1, 3, 1),
+FCE("ἇι", 2, 3, 2),FCE("ᾐ", 0, 3, 1),FCE("ᾘ", 1, 3, 1),FCE("ἠι", 2, 3, 2),
+FCE("ᾑ", 0, 3, 1),FCE("ᾙ", 1, 3, 1),FCE("ἡι", 2, 3, 2),FCE("ᾒ", 0, 3, 1),
+FCE("ᾚ", 1, 3, 1),FCE("ἢι", 2, 3, 2),FCE("ᾓ", 0, 3, 1),FCE("ᾛ", 1, 3, 1),
+FCE("ἣι", 2, 3, 2),FCE("ᾔ", 0, 3, 1),FCE("ᾜ", 1, 3, 1),FCE("ἤι", 2, 3, 2),
+FCE("ᾕ", 0, 3, 1),FCE("ᾝ", 1, 3, 1),FCE("ἥι", 2, 3, 2),FCE("ᾖ", 0, 3, 1),
+FCE("ᾞ", 1, 3, 1),FCE("ἦι", 2, 3, 2),FCE("ᾗ", 0, 3, 1),FCE("ᾟ", 1, 3, 1),
+FCE("ἧι", 2, 3, 2),FCE("ᾐ", 0, 3, 1),FCE("ᾘ", 1, 3, 1),FCE("ἠι", 2, 3, 2),
+FCE("ᾑ", 0, 3, 1),FCE("ᾙ", 1, 3, 1),FCE("ἡι", 2, 3, 2),FCE("ᾒ", 0, 3, 1),
+FCE("ᾚ", 1, 3, 1),FCE("ἢι", 2, 3, 2),FCE("ᾓ", 0, 3, 1),FCE("ᾛ", 1, 3, 1),
+FCE("ἣι", 2, 3, 2),FCE("ᾔ", 0, 3, 1),FCE("ᾜ", 1, 3, 1),FCE("ἤι", 2, 3, 2),
+FCE("ᾕ", 0, 3, 1),FCE("ᾝ", 1, 3, 1),FCE("ἥι", 2, 3, 2),FCE("ᾖ", 0, 3, 1),
+FCE("ᾞ", 1, 3, 1),FCE("ἦι", 2, 3, 2),FCE("ᾗ", 0, 3, 1),FCE("ᾟ", 1, 3, 1),
+FCE("ἧι", 2, 3, 2),FCE("ᾠ", 0, 3, 1),FCE("ᾨ", 1, 3, 1),FCE("ὠι", 2, 3, 2),
+FCE("ᾡ", 0, 3, 1),FCE("ᾩ", 1, 3, 1),FCE("ὡι", 2, 3, 2),FCE("ᾢ", 0, 3, 1),
+FCE("ᾪ", 1, 3, 1),FCE("ὢι", 2, 3, 2),FCE("ᾣ", 0, 3, 1),FCE("ᾫ", 1, 3, 1),
+FCE("ὣι", 2, 3, 2),FCE("ᾤ", 0, 3, 1),FCE("ᾬ", 1, 3, 1),FCE("ὤι", 2, 3, 2),
+FCE("ᾥ", 0, 3, 1),FCE("ᾭ", 1, 3, 1),FCE("ὥι", 2, 3, 2),FCE("ᾦ", 0, 3, 1),
+FCE("ᾮ", 1, 3, 1),FCE("ὦι", 2, 3, 2),FCE("ᾧ", 0, 3, 1),FCE("ᾯ", 1, 3, 1),
+FCE("ὧι", 2, 3, 2),FCE("ᾠ", 0, 3, 1),FCE("ᾨ", 1, 3, 1),FCE("ὠι", 2, 3, 2),
+FCE("ᾡ", 0, 3, 1),FCE("ᾩ", 1, 3, 1),FCE("ὡι", 2, 3, 2),FCE("ᾢ", 0, 3, 1),
+FCE("ᾪ", 1, 3, 1),FCE("ὢι", 2, 3, 2),FCE("ᾣ", 0, 3, 1),FCE("ᾫ", 1, 3, 1),
+FCE("ὣι", 2, 3, 2),FCE("ᾤ", 0, 3, 1),FCE("ᾬ", 1, 3, 1),FCE("ὤι", 2, 3, 2),
+FCE("ᾥ", 0, 3, 1),FCE("ᾭ", 1, 3, 1),FCE("ὥι", 2, 3, 2),FCE("ᾦ", 0, 3, 1),
+FCE("ᾮ", 1, 3, 1),FCE("ὦι", 2, 3, 2),FCE("ᾧ", 0, 3, 1),FCE("ᾯ", 1, 3, 1),
+FCE("ὧι", 2, 3, 2),FCE("ᾲ", 0, 2, 1),FCE("ὰι", 1, 2, 2),FCE("ᾳ", 0, 3, 1),
+FCE("ᾼ", 1, 3, 1),FCE("αι", 2, 3, 2),FCE("ᾴ", 0, 2, 1),FCE("άι", 1, 2, 2),
+FCE("ᾶ", 0, 2, 1),FCE("ᾶ", 1, 2, 2),FCE("ᾷ", 0, 2, 1),FCE("ᾶι", 1, 2, 3),
+FCE("ᾰ", 0, 2, 1),FCE("Ᾰ", 1, 2, 1),FCE("ᾱ", 0, 2, 1),FCE("Ᾱ", 1, 2, 1),
+FCE("ὰ", 0, 2, 1),FCE("Ὰ", 1, 2, 1),FCE("ά", 0, 2, 1),FCE("Ά", 1, 2, 1),
+FCE("ᾳ", 0, 3, 1),FCE("ᾼ", 1, 3, 1),FCE("αι", 2, 3, 2),FCE("ͅ", 0, 4, 1),
+FCE("Ι", 1, 4, 1),FCE("ι", 2, 4, 1),FCE("ι", 3, 4, 1),FCE("ῂ", 0, 2, 1),
+FCE("ὴι", 1, 2, 2),FCE("ῃ", 0, 3, 1),FCE("ῌ", 1, 3, 1),FCE("ηι", 2, 3, 2),
+FCE("ῄ", 0, 2, 1),FCE("ήι", 1, 2, 2),FCE("𐐌", 0, 2, 1),FCE("𐐴", 1, 2, 1),
+FCE("ῆ", 0, 2, 1),FCE("ῆ", 1, 2, 2),FCE("ῇ", 0, 2, 1),FCE("ῆι", 1, 2, 3),
+FCE("ὲ", 0, 2, 1),FCE("Ὲ", 1, 2, 1),FCE("έ", 0, 2, 1),FCE("Έ", 1, 2, 1),
+FCE("ὴ", 0, 2, 1),FCE("Ὴ", 1, 2, 1),FCE("ή", 0, 2, 1),FCE("Ή", 1, 2, 1),
+FCE("ῃ", 0, 3, 1),FCE("ῌ", 1, 3, 1),FCE("ηι", 2, 3, 2),FCE("ῒ", 0, 2, 1),
+FCE("ῒ", 1, 2, 3),FCE("ΐ", 0, 3, 1),FCE("ΐ", 1, 3, 1),FCE("ΐ", 2, 3, 3),
+FCE("ῖ", 0, 2, 1),FCE("ῖ", 1, 2, 2),FCE("ῗ", 0, 2, 1),FCE("ῗ", 1, 2, 3),
+FCE("ῐ", 0, 2, 1),FCE("Ῐ", 1, 2, 1),FCE("ῑ", 0, 2, 1),FCE("Ῑ", 1, 2, 1),
+FCE("ὶ", 0, 2, 1),FCE("Ὶ", 1, 2, 1),FCE("ί", 0, 2, 1),FCE("Ί", 1, 2, 1),
+FCE("𐐧", 0, 2, 1),FCE("𐑏", 1, 2, 1),FCE("ῢ", 0, 2, 1),FCE("ῢ", 1, 2, 3),
+FCE("ΰ", 0, 3, 1),FCE("ΰ", 1, 3, 1),FCE("ΰ", 2, 3, 3),FCE("ῤ", 0, 2, 1),
+FCE("ῤ", 1, 2, 2),FCE("ῦ", 0, 2, 1),FCE("ῦ", 1, 2, 2),FCE("ῧ", 0, 2, 1),
+FCE("ῧ", 1, 2, 3),FCE("ῠ", 0, 2, 1),FCE("Ῠ", 1, 2, 1),FCE("ῡ", 0, 2, 1),
+FCE("Ῡ", 1, 2, 1),FCE("ὺ", 0, 2, 1),FCE("Ὺ", 1, 2, 1),FCE("ύ", 0, 2, 1),
+FCE("Ύ", 1, 2, 1),FCE("ῥ", 0, 2, 1),FCE("Ῥ", 1, 2, 1),FCE("𐐁", 0, 2, 1),
+FCE("𐐩", 1, 2, 1),FCE("ῲ", 0, 2, 1),FCE("ὼι", 1, 2, 2),FCE("ῳ", 0, 3, 1),
+FCE("ῼ", 1, 3, 1),FCE("ωι", 2, 3, 2),FCE("ῴ", 0, 2, 1),FCE("ώι", 1, 2, 2),
+FCE("ῶ", 0, 2, 1),FCE("ῶ", 1, 2, 2),FCE("ῷ", 0, 2, 1),FCE("ῶι", 1, 2, 3),
+FCE("ὸ", 0, 2, 1),FCE("Ὸ", 1, 2, 1),FCE("ό", 0, 2, 1),FCE("Ό", 1, 2, 1),
+FCE("ὼ", 0, 2, 1),FCE("Ὼ", 1, 2, 1),FCE("ώ", 0, 2, 1),FCE("Ώ", 1, 2, 1),
+FCE("ῳ", 0, 3, 1),FCE("ῼ", 1, 3, 1),FCE("ωι", 2, 3, 2),FCE("Ⓚ", 0, 2, 1),
+FCE("ⓚ", 1, 2, 1),];
+return t;
+}
+
+struct uniProps
+{
+private alias _U = immutable(UnicodeProperty);
+@property static _U[] tab() { return _tab; }
+static immutable:
+private alias _T = ubyte[];
+_T So = [0x80, 0xa6, 0x1, 0x2, 0x1, 0x4, 0x1, 0x1, 0x1, 0x83, 0xd1, 0x1, 0x81, 0x8b, 0x2, 0x80, 0xce, 0x1, 0xa, 0x1, 0x13, 0x2, 0x80, 0xf7, 0x1, 0x82, 0x3, 0x1, 0x81, 0x75, 0x1, 0x80, 0x82, 0x6, 0x1, 0x1, 0x80, 0x84, 0x1, 0x80, 0xf9, 0x1, 0x81, 0x87, 0x3, 0xf, 0x1, 0x1, 0x3, 0x2, 0x6, 0x14, 0x1, 0x1, 0x1, 0x1, 0x1, 0x80, 0x85, 0x8, 0x1, 0x6, 0x1, 0x2, 0x5, 0x4, 0x80, 0xc5, 0x2, 0x82, 0xf0, 0xa, 0x85, 0xa6, 0x1, 0x80, 0x9d, 0x22, 0x81, 0x61, 0xa, 0x9, 0x9, 0x85, 0x83, 0x2, 0x1, 0x4, 0x1, 0x2, 0xa, 0x1, 0x1, 0x2, 0x6, 0x6, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x1, 0xb, 0x2, 0xe, 0x1, 0x1, 0x2, 0x1, 0x1, 0x45, 0x5, 0x2, 0x4, 0x1, 0x2, 0x1, 0x2, 0x1, 0x7, 0x1, 0x1f, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1f, 0x81, 0xc, 0x8, 0x4, 0x14, 0x2, 0x7, 0x2, 0x51, 0x1, 0x1e, 0x19, 0x28, 0x6, 0x12, 0xc, 0x27, 0x19, 0xb, 0x51, 0x4e, 0x16, 0x80, 0xb7, 0x1, 0x9, 0x1, 0x36, 0x8, 0x6f, 0x1, 0x80, 0x90, 0x1, 0x67, 0x2c, 0x2c, 0x40, 0x81, 0x0, 0x82, 0x0, 0x30, 0x15, 0x2, 0x9, 0xa, 0x81, 0x8b, 0x6, 0x81, 0x95, 0x1a, 0x1, 0x59, 0xc, 0x80, 0xd6, 0x1a, 0xc, 0x8, 0x1, 0xd, 0x2, 0xc, 0x1, 0x15, 0x2, 0x6, 0x2, 0x81, 0x50, 0x2, 0x4, 0xa, 0x20, 0x24, 0x1c, 0x1f, 0xb, 0x1e, 0x8, 0x1, 0xf, 0x20, 0xa, 0x27, 0xf, 0x3f, 0x1, 0x81, 0x0, 0x99, 0xc0, 0x40, 0xa0, 0x56, 0x90, 0x37, 0x83, 0x61, 0x4, 0xa, 0x2, 0x1, 0x1, 0x82, 0x3d, 0x3, 0xa0, 0x53, 0x83, 0x1, 0x81, 0xe6, 0x1, 0x3, 0x1, 0x4, 0x2, 0xd, 0x2, 0x81, 0x39, 0x9, 0x39, 0x11, 0x6, 0xc, 0x34, 0x2d, 0xa0, 0xce, 0x3, 0x80, 0xf6, 0xa, 0x27, 0x2, 0x3c, 0x5, 0x3, 0x16, 0x2, 0x7, 0x1e, 0x4, 0x30, 0x22, 0x42, 0x3, 0x1, 0x80, 0xba, 0x57, 0x9c, 0xa9, 0x2c, 0x4, 0x64, 0xc, 0xf, 0x2, 0xe, 0x2, 0xf, 0x1, 0xf, 0x30, 0x1f, 0x1, 0x3c, 0x4, 0x2b, 0x4b, 0x1d, 0xd, 0x2b, 0x5, 0x9, 0x7, 0x2, 0x80, 0xae, 0x21, 0xf, 0x6, 0x1, 0x46, 0x3, 0x14, 0xc, 0x25, 0x1, 0x5, 0x15, 0x11, 0xf, 0x3f, 0x1, 0x1, 0x1, 0x80, 0xb6, 0x1, 0x4, 0x3, 0x3e, 0x2, 0x4, 0xc, 0x18, 0x80, 0x93, 0x46, 0x4, 0xb, 0x30, 0x46, 0x3a, 0x74];
+_T Pf = [0x80, 0xbb, 0x1, 0x9f, 0x5d, 0x1, 0x3, 0x1, 0x1c, 0x1, 0x8d, 0xc8, 0x1, 0x1, 0x1, 0x4, 0x1, 0x2, 0x1, 0xf, 0x1, 0x3, 0x1];
+_T Bidi_Control = [0x86, 0x1c, 0x1, 0x99, 0xf1, 0x2, 0x1a, 0x5, 0x37, 0x4];
+_T Hex_Digit = [0x30, 0xa, 0x7, 0x6, 0x1a, 0x6, 0xa0, 0xfe, 0xa9, 0xa, 0x7, 0x6, 0x1a, 0x6];
+_T Other_Lowercase = [0x80, 0xaa, 0x1, 0xf, 0x1, 0x81, 0xf5, 0x9, 0x7, 0x2, 0x1e, 0x5, 0x60, 0x1, 0x34, 0x1, 0x99, 0xb1, 0x3f, 0xd, 0x1, 0x22, 0x25, 0x82, 0xb1, 0x1, 0xd, 0x1, 0x10, 0xd, 0x80, 0xd3, 0x10, 0x83, 0x50, 0x1a, 0x87, 0x92, 0x2, 0xa0, 0x7a, 0xf2, 0x1, 0x80, 0x87, 0x2];
+_T Quotation_Mark = [0x22, 0x1, 0x4, 0x1, 0x80, 0x83, 0x1, 0xf, 0x1, 0x9f, 0x5c, 0x8, 0x19, 0x2, 0x8f, 0xd1, 0x4, 0xd, 0x3, 0xa0, 0xce, 0x21, 0x4, 0x80, 0xbd, 0x1, 0x4, 0x1, 0x5a, 0x2];
+_T XID_Start = [0x41, 0x1a, 0x6, 0x1a, 0x2f, 0x1, 0xa, 0x1, 0x4, 0x1, 0x5, 0x17, 0x1, 0x1f, 0x1, 0x81, 0xca, 0x4, 0xc, 0xe, 0x5, 0x7, 0x1, 0x1, 0x1, 0x80, 0x81, 0x5, 0x1, 0x2, 0x3, 0x3, 0x8, 0x1, 0x1, 0x3, 0x1, 0x1, 0x1, 0x14, 0x1, 0x53, 0x1, 0x80, 0x8b, 0x8, 0x80, 0x9e, 0x9, 0x26, 0x2, 0x1, 0x7, 0x27, 0x48, 0x1b, 0x5, 0x3, 0x2d, 0x2b, 0x23, 0x2, 0x1, 0x63, 0x1, 0x1, 0xf, 0x2, 0x7, 0x2, 0xa, 0x3, 0x2, 0x1, 0x10, 0x1, 0x1, 0x1e, 0x1d, 0x59, 0xb, 0x1, 0x18, 0x21, 0x9, 0x2, 0x4, 0x1, 0x5, 0x16, 0x4, 0x1, 0x9, 0x1, 0x3, 0x1, 0x17, 0x19, 0x47, 0x1, 0x1, 0xb, 0x57, 0x36, 0x3, 0x1, 0x12, 0x1, 0x7, 0xa, 0xf, 0x7, 0x1, 0x7, 0x5, 0x8, 0x2, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x1, 0x3, 0x4, 0x3, 0x1, 0x10, 0x1, 0xd, 0x2, 0x1, 0x3, 0xe, 0x2, 0x13, 0x6, 0x4, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x2, 0x1, 0x2, 0x1f, 0x4, 0x1, 0x1, 0x13, 0x3, 0x10, 0x9, 0x1, 0x3, 0x1, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x5, 0x3, 0x1, 0x12, 0x1, 0xf, 0x2, 0x23, 0x8, 0x2, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x5, 0x3, 0x1, 0x1e, 0x2, 0x1, 0x3, 0xf, 0x1, 0x11, 0x1, 0x1, 0x6, 0x3, 0x3, 0x1, 0x4, 0x3, 0x2, 0x1, 0x1, 0x1, 0x2, 0x3, 0x2, 0x3, 0x3, 0x3, 0xc, 0x16, 0x1, 0x34, 0x8, 0x1, 0x3, 0x1, 0x17, 0x1, 0xa, 0x1, 0x5, 0x3, 0x1, 0x1a, 0x2, 0x6, 0x2, 0x23, 0x8, 0x1, 0x3, 0x1, 0x17, 0x1, 0xa, 0x1, 0x5, 0x3, 0x1, 0x20, 0x1, 0x1, 0x2, 0xf, 0x2, 0x12, 0x8, 0x1, 0x3, 0x1, 0x29, 0x2, 0x1, 0x10, 0x1, 0x11, 0x2, 0x18, 0x6, 0x5, 0x12, 0x3, 0x18, 0x1, 0x9, 0x1, 0x1, 0x2, 0x7, 0x3a, 0x30, 0x1, 0x1, 0xd, 0x7, 0x3a, 0x2, 0x1, 0x1, 0x2, 0x2, 0x1, 0x1, 0x2, 0x1, 0x6, 0x4, 0x1, 0x7, 0x1, 0x3, 0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0x1, 0x4, 0x1, 0x1, 0xa, 0x1, 0x2, 0x5, 0x1, 0x1, 0x15, 0x4, 0x20, 0x1, 0x3f, 0x8, 0x1, 0x24, 0x1b, 0x5, 0x73, 0x2b, 0x14, 0x1, 0x10, 0x6, 0x4, 0x4, 0x3, 0x1, 0x3, 0x2, 0x7, 0x3, 0x4, 0xd, 0xc, 0x1, 0x11, 0x26, 0x1, 0x1, 0x5, 0x1, 0x2, 0x2b, 0x1, 0x81, 0x4d, 0x1, 0x4, 0x2, 0x7, 0x1, 0x1, 0x1, 0x4, 0x2, 0x29, 0x1, 0x4, 0x2, 0x21, 0x1, 0x4, 0x2, 0x7, 0x1, 0x1, 0x1, 0x4, 0x2, 0xf, 0x1, 0x39, 0x1, 0x4, 0x2, 0x43, 0x25, 0x10, 0x10, 0x55, 0xc, 0x82, 0x6c, 0x2, 0x11, 0x1, 0x1a, 0x5, 0x4b, 0x3, 0x3, 0xf, 0xd, 0x1, 0x4, 0xe, 0x12, 0xe, 0x12, 0xe, 0xd, 0x1, 0x3, 0xf, 0x34, 0x23, 0x1, 0x4, 0x1, 0x43, 0x58, 0x8, 0x29, 0x1, 0x1, 0x5, 0x46, 0xa, 0x1d, 0x33, 0x1e, 0x2, 0x5, 0xb, 0x2c, 0x15, 0x7, 0x38, 0x17, 0x9, 0x35, 0x52, 0x1, 0x5d, 0x2f, 0x11, 0x7, 0x37, 0x1e, 0xd, 0x2, 0xa, 0x2c, 0x1a, 0x24, 0x29, 0x3, 0xa, 0x24, 0x6b, 0x4, 0x1, 0x4, 0x3, 0x2, 0x9, 0x80, 0xc0, 0x40, 0x81, 0x16, 0x2, 0x6, 0x2, 0x26, 0x2, 0x6, 0x2, 0x8, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1f, 0x2, 0x35, 0x1, 0x7, 0x1, 0x1, 0x3, 0x3, 0x1, 0x7, 0x3, 0x4, 0x2, 0x6, 0x4, 0xd, 0x5, 0x3, 0x1, 0x7, 0x74, 0x1, 0xd, 0x1, 0x10, 0xd, 0x65, 0x1, 0x4, 0x1, 0x2, 0xa, 0x1, 0x1, 0x2, 0x6, 0x6, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x10, 0x2, 0x4, 0x5, 0x5, 0x4, 0x1, 0x11, 0x29, 0x8a, 0x77, 0x2f, 0x1, 0x2f, 0x1, 0x80, 0x85, 0x6, 0x4, 0x3, 0x2, 0xc, 0x26, 0x1, 0x1, 0x5, 0x1, 0x2, 0x38, 0x7, 0x1, 0x10, 0x17, 0x9, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x82, 0x26, 0x3, 0x19, 0x9, 0x7, 0x5, 0x2, 0x5, 0x4, 0x56, 0x6, 0x3, 0x1, 0x5a, 0x1, 0x4, 0x5, 0x29, 0x3, 0x5e, 0x11, 0x1b, 0x35, 0x10, 0x82, 0x0, 0x99, 0xb6, 0x4a, 0xa0, 0x51, 0xcd, 0x33, 0x84, 0x8d, 0x43, 0x2e, 0x2, 0x81, 0xd, 0x3, 0x10, 0xa, 0x2, 0x14, 0x2f, 0x10, 0x19, 0x8, 0x50, 0x27, 0x9, 0x2, 0x67, 0x2, 0x4, 0x1, 0x4, 0xc, 0xb, 0x4d, 0xa, 0x1, 0x3, 0x1, 0x4, 0x1, 0x17, 0x1d, 0x34, 0xe, 0x32, 0x3e, 0x6, 0x3, 0x1, 0xe, 0x1c, 0xa, 0x17, 0x19, 0x1d, 0x7, 0x2f, 0x1c, 0x1, 0x30, 0x29, 0x17, 0x3, 0x1, 0x8, 0x14, 0x17, 0x3, 0x1, 0x5, 0x30, 0x1, 0x1, 0x3, 0x2, 0x2, 0x5, 0x2, 0x1, 0x1, 0x1, 0x18, 0x3, 0x2, 0xb, 0x7, 0x3, 0xc, 0x6, 0x2, 0x6, 0x2, 0x6, 0x9, 0x7, 0x1, 0x7, 0x80, 0x91, 0x23, 0x1d, 0xa0, 0x2b, 0xa4, 0xc, 0x17, 0x4, 0x31, 0xa0, 0x21, 0x4, 0x81, 0x6e, 0x2, 0x6a, 0x26, 0x7, 0xc, 0x5, 0x5, 0x1, 0x1, 0xa, 0x1, 0xd, 0x1, 0x5, 0x1, 0x1, 0x1, 0x2, 0x1, 0x2, 0x1, 0x6c, 0x21, 0x80, 0x8b, 0x6, 0x80, 0xda, 0x12, 0x40, 0x2, 0x36, 0x28, 0xa, 0x77, 0x1, 0x1, 0x1, 0x3, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x7e, 0x24, 0x1a, 0x6, 0x1a, 0xb, 0x38, 0x2, 0x1f, 0x3, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x3, 0x23, 0xc, 0x1, 0x1a, 0x1, 0x13, 0x1, 0x2, 0x1, 0xf, 0x2, 0xe, 0x22, 0x7b, 0x45, 0x35, 0x81, 0xb, 0x1d, 0x3, 0x31, 0x2f, 0x1f, 0x11, 0x1b, 0x35, 0x1e, 0x2, 0x24, 0x4, 0x8, 0x1, 0x5, 0x2a, 0x80, 0x9e, 0x83, 0x62, 0x6, 0x2, 0x1, 0x1, 0x2c, 0x1, 0x2, 0x3, 0x1, 0x2, 0x17, 0x80, 0xaa, 0x16, 0xa, 0x1a, 0x46, 0x38, 0x6, 0x2, 0x40, 0x1, 0xf, 0x4, 0x1, 0x3, 0x1, 0x1b, 0x2c, 0x1d, 0x80, 0x83, 0x36, 0xa, 0x16, 0xa, 0x13, 0x80, 0x8d, 0x49, 0x83, 0xba, 0x35, 0x4b, 0x2d, 0x20, 0x19, 0x1a, 0x24, 0x5c, 0x30, 0xe, 0x4, 0x84, 0xbb, 0x2b, 0x89, 0x55, 0x83, 0x6f, 0x80, 0x91, 0x63, 0x8b, 0x9d, 0x84, 0x2f, 0xa0, 0x33, 0xd1, 0x82, 0x39, 0x84, 0xc7, 0x45, 0xb, 0x1, 0x42, 0xd, 0xa0, 0x40, 0x60, 0x2, 0xa0, 0x23, 0xfe, 0x55, 0x1, 0x47, 0x1, 0x2, 0x2, 0x1, 0x2, 0x2, 0x2, 0x4, 0x1, 0xc, 0x1, 0x1, 0x1, 0x7, 0x1, 0x41, 0x1, 0x4, 0x2, 0x8, 0x1, 0x7, 0x1, 0x1c, 0x1, 0x4, 0x1, 0x5, 0x1, 0x1, 0x3, 0x7, 0x1, 0x81, 0x54, 0x2, 0x19, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x8, 0x96, 0x34, 0x4, 0x1, 0x1b, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0xa, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x6, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x3, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x2, 0x4, 0x1, 0x7, 0x1, 0x4, 0x1, 0x4, 0x1, 0x1, 0x1, 0xa, 0x1, 0x11, 0x5, 0x3, 0x1, 0x5, 0x1, 0x11, 0x91, 0x44, 0xa0, 0xa6, 0xd7, 0x29, 0x90, 0x35, 0xb, 0x80, 0xde, 0xa0, 0x3f, 0xe2, 0x82, 0x1e];
+_T Terminal_Punctuation = [0x21, 0x1, 0xa, 0x1, 0x1, 0x1, 0xb, 0x2, 0x3, 0x1, 0x83, 0x3e, 0x1, 0x8, 0x1, 0x82, 0x1, 0x1, 0x39, 0x1, 0x48, 0x1, 0xe, 0x1, 0x3, 0x1, 0x80, 0xb4, 0x1, 0x2b, 0xb, 0x1, 0x1, 0x80, 0xeb, 0x2, 0x36, 0xf, 0x1f, 0x1, 0x81, 0x5, 0x2, 0x84, 0xf4, 0x2, 0x80, 0xac, 0x1, 0x4, 0x6, 0x81, 0x37, 0x2, 0x83, 0x15, 0x8, 0x83, 0x4, 0x2, 0x7c, 0x3, 0x80, 0xe6, 0x3, 0x3, 0x1, 0x27, 0x4, 0x2, 0x2, 0x81, 0x3a, 0x2, 0x81, 0x62, 0x4, 0x80, 0xae, 0x2, 0x1, 0x3, 0x80, 0xdb, 0x5, 0x3e, 0x2, 0x83, 0xbc, 0x2, 0x9, 0x3, 0x8d, 0xe4, 0x1, 0x81, 0xd2, 0x2, 0xa0, 0x74, 0xfb, 0x2, 0x81, 0xd, 0x3, 0x80, 0xe3, 0x5, 0x81, 0x7e, 0x2, 0x56, 0x2, 0x5f, 0x1, 0x80, 0x97, 0x3, 0x80, 0x93, 0x3, 0x7f, 0x1, 0x10, 0x2, 0x80, 0xf9, 0x1, 0xa0, 0x52, 0x64, 0x3, 0x1, 0x4, 0x80, 0xa9, 0x1, 0xa, 0x1, 0x1, 0x1, 0xb, 0x2, 0x3, 0x1, 0x41, 0x1, 0x2, 0x1, 0x84, 0x3a, 0x1, 0x30, 0x1, 0x84, 0x86, 0x1, 0x80, 0xc7, 0x1, 0x82, 0x1a, 0x6, 0x85, 0x7, 0x7, 0x70, 0x4, 0x7f, 0x3, 0x80, 0x81, 0x2, 0x92, 0xa9, 0x4];
+_T Math = [0x2b, 0x1, 0x10, 0x3, 0x1f, 0x1, 0x1d, 0x1, 0x1, 0x1, 0x2d, 0x1, 0x4, 0x1, 0x25, 0x1, 0x1f, 0x1, 0x82, 0xd8, 0x3, 0x2, 0x1, 0x1a, 0x2, 0x2, 0x3, 0x82, 0xf, 0x3, 0x9a, 0xd, 0x1, 0x1b, 0x3, 0xb, 0x1, 0x3, 0x1, 0xd, 0x1, 0xe, 0x4, 0x15, 0x5, 0xb, 0x5, 0x41, 0xd, 0x4, 0x1, 0x3, 0x2, 0x4, 0x5, 0x12, 0x1, 0x4, 0x1, 0x2, 0xa, 0x1, 0x1, 0x2, 0x6, 0x6, 0x1, 0x3, 0x2, 0x2, 0x2, 0x1, 0x3, 0x1, 0x6, 0x3, 0xe, 0x1, 0x1, 0x44, 0x18, 0x1, 0x6, 0x1, 0x2, 0x4, 0x2, 0x4, 0x20, 0x1, 0x1, 0x6, 0x2, 0xe, 0x81, 0xc, 0x8, 0x4, 0x14, 0x2, 0x5a, 0x1, 0x1e, 0x1b, 0x1, 0x1, 0x18, 0x1, 0xb, 0x7, 0x81, 0xbd, 0x2, 0xc, 0xa, 0x4, 0x6, 0x4, 0x2, 0x2, 0x2, 0x3, 0x5, 0xe, 0x1, 0x1, 0x1, 0x2, 0x6, 0xb, 0x8, 0x5, 0x2, 0x39, 0x1, 0x1, 0x1, 0x1d, 0x4, 0x9, 0x3, 0x81, 0x50, 0x40, 0x81, 0x0, 0x82, 0x0, 0x30, 0x15, 0x2, 0x6, 0xa0, 0xcf, 0xdc, 0x1, 0x83, 0x37, 0x6, 0x1, 0x1, 0x80, 0xa2, 0x1, 0x10, 0x3, 0x1d, 0x1, 0x1, 0x1, 0x1d, 0x1, 0x1, 0x1, 0x80, 0x83, 0x1, 0x6, 0x4, 0xa0, 0xd4, 0x13, 0x55, 0x1, 0x47, 0x1, 0x2, 0x2, 0x1, 0x2, 0x2, 0x2, 0x4, 0x1, 0xc, 0x1, 0x1, 0x1, 0x7, 0x1, 0x41, 0x1, 0x4, 0x2, 0x8, 0x1, 0x7, 0x1, 0x1c, 0x1, 0x4, 0x1, 0x5, 0x1, 0x1, 0x3, 0x7, 0x1, 0x81, 0x54, 0x2, 0x81, 0x24, 0x2, 0x32, 0x96, 0x0, 0x4, 0x1, 0x1b, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0xa, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x6, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x3, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x2, 0x4, 0x1, 0x7, 0x1, 0x4, 0x1, 0x4, 0x1, 0x1, 0x1, 0xa, 0x1, 0x11, 0x5, 0x3, 0x1, 0x5, 0x1, 0x11, 0x34, 0x2];
+_T Lu = [0x41, 0x1a, 0x65, 0x17, 0x1, 0x7, 0x21, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x3, 0x2, 0x1, 0x1, 0x1, 0x2, 0x1, 0x3, 0x2, 0x4, 0x1, 0x2, 0x1, 0x3, 0x3, 0x2, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x3, 0x1, 0x1, 0x1, 0x2, 0x3, 0x1, 0x7, 0x1, 0x2, 0x1, 0x2, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x2, 0x1, 0x1, 0x3, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x7, 0x2, 0x1, 0x2, 0x2, 0x1, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x81, 0x21, 0x1, 0x1, 0x1, 0x3, 0x1, 0xf, 0x1, 0x1, 0x3, 0x1, 0x1, 0x1, 0x2, 0x1, 0x11, 0x1, 0x9, 0x23, 0x1, 0x2, 0x3, 0x3, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x5, 0x1, 0x2, 0x1, 0x1, 0x2, 0x2, 0x33, 0x30, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x9, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0xa, 0x26, 0x8b, 0x49, 0x26, 0x1, 0x1, 0x5, 0x1, 0x8d, 0x32, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x9, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x9, 0x8, 0x8, 0x6, 0xa, 0x8, 0x8, 0x8, 0x8, 0x6, 0xb, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x8, 0x8, 0x48, 0x4, 0xc, 0x4, 0xc, 0x4, 0xc, 0x5, 0xb, 0x4, 0x81, 0x6, 0x1, 0x4, 0x1, 0x3, 0x3, 0x2, 0x3, 0x2, 0x1, 0x3, 0x5, 0x6, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x2, 0x4, 0xa, 0x2, 0x5, 0x1, 0x3d, 0x1, 0x8a, 0x7c, 0x2f, 0x31, 0x1, 0x1, 0x3, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x1, 0x1, 0x2, 0x1, 0x8, 0x3, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x8, 0x1, 0x1, 0x1, 0x4, 0x1, 0xa0, 0x79, 0x4d, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x13, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x80, 0x8b, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x3, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0xa, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0xd, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0xa0, 0x57, 0x76, 0x1a, 0x84, 0xc5, 0x28, 0xa0, 0xcf, 0xd8, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1, 0x1, 0x2, 0x2, 0x1, 0x2, 0x2, 0x2, 0x4, 0x1, 0x8, 0x1a, 0x1a, 0x1a, 0x2, 0x1, 0x4, 0x2, 0x8, 0x1, 0x7, 0x1b, 0x2, 0x1, 0x4, 0x1, 0x5, 0x1, 0x1, 0x3, 0x7, 0x1b, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1e, 0x19, 0x21, 0x19, 0x21, 0x19, 0x21, 0x19, 0x21, 0x19, 0x21, 0x1];
+_T Other_Uppercase = [0xa0, 0x21, 0x60, 0x10, 0x83, 0x46, 0x1a];
+_T Sk = [0x5e, 0x1, 0x1, 0x1, 0x47, 0x1, 0x6, 0x1, 0x4, 0x1, 0x3, 0x1, 0x82, 0x9, 0x4, 0xc, 0xe, 0x5, 0x7, 0x1, 0x1, 0x1, 0x11, 0x75, 0x1, 0xe, 0x2, 0x9c, 0x37, 0x1, 0x1, 0x3, 0xb, 0x3, 0xd, 0x3, 0xd, 0x3, 0xd, 0x2, 0x90, 0x9c, 0x2, 0xa0, 0x76, 0x63, 0x17, 0x9, 0x2, 0x67, 0x2, 0xa0, 0x54, 0x27, 0x10, 0x83, 0x7c, 0x1, 0x1, 0x1, 0x80, 0xa2, 0x1];
+_T Other_ID_Start = [0xa0, 0x21, 0x18, 0x1, 0x15, 0x1, 0x8f, 0x6c, 0x2];
+_T Nl = [0x96, 0xee, 0x3, 0x8a, 0x6f, 0x23, 0x2, 0x4, 0x8e, 0x7e, 0x1, 0x19, 0x9, 0xe, 0x3, 0xa0, 0x76, 0xab, 0xa, 0xa0, 0x5a, 0x50, 0x35, 0x81, 0xcc, 0x1, 0x8, 0x1, 0x80, 0x86, 0x5, 0xa0, 0x20, 0x2a, 0x63];
+_T Other_Alphabetic = [0x83, 0x45, 0x1, 0x82, 0x6a, 0xe, 0x1, 0x1, 0x1, 0x2, 0x1, 0x2, 0x1, 0x1, 0x48, 0xb, 0x30, 0xd, 0x1, 0x7, 0x10, 0x1, 0x65, 0x7, 0x4, 0x4, 0x2, 0x2, 0x4, 0x1, 0x23, 0x1, 0x1e, 0x10, 0x66, 0xb, 0x65, 0x2, 0x3, 0x9, 0x1, 0x3, 0x1, 0x4, 0x80, 0xb7, 0x6, 0x6, 0xf, 0x1, 0x4, 0x36, 0x2, 0x2, 0xf, 0x1, 0x2, 0x5, 0x3, 0xa, 0x2, 0x1d, 0x3, 0x3a, 0x7, 0x2, 0x2, 0x2, 0x2, 0xa, 0x1, 0xa, 0x2, 0x1d, 0x3, 0x3a, 0x5, 0x4, 0x2, 0x2, 0x2, 0x4, 0x1, 0x1e, 0x2, 0x3, 0x1, 0xb, 0x3, 0x3a, 0x8, 0x1, 0x3, 0x1, 0x2, 0x15, 0x2, 0x1d, 0x3, 0x3a, 0x7, 0x2, 0x2, 0x2, 0x2, 0x9, 0x2, 0xa, 0x2, 0x1e, 0x1, 0x3b, 0x5, 0x3, 0x3, 0x1, 0x3, 0xa, 0x1, 0x29, 0x3, 0x3a, 0x7, 0x1, 0x3, 0x1, 0x3, 0x8, 0x2, 0xb, 0x2, 0x1e, 0x2, 0x3a, 0x7, 0x1, 0x3, 0x1, 0x3, 0x8, 0x2, 0xb, 0x2, 0x1e, 0x2, 0x3a, 0x7, 0x1, 0x3, 0x1, 0x3, 0xa, 0x1, 0xa, 0x2, 0x1e, 0x2, 0x4b, 0x6, 0x1, 0x1, 0x1, 0x8, 0x12, 0x2, 0x3d, 0x1, 0x2, 0x7, 0x12, 0x1, 0x63, 0x1, 0x2, 0x6, 0x1, 0x2, 0x10, 0x1, 0x80, 0xa3, 0x11, 0xb, 0xb, 0x1, 0x24, 0x6e, 0xc, 0x1, 0x1, 0x2, 0x4, 0x17, 0x4, 0x4, 0x3, 0x1, 0x1, 0x4, 0x2, 0x8, 0x4, 0xd, 0x5, 0x15, 0x2, 0x82, 0xc1, 0x1, 0x83, 0xb2, 0x2, 0x1e, 0x2, 0x1e, 0x2, 0x1e, 0x2, 0x42, 0x13, 0x80, 0xe0, 0x1, 0x76, 0xc, 0x4, 0x9, 0x77, 0x11, 0x7, 0x2, 0x4d, 0x5, 0x39, 0xa, 0x2, 0x14, 0x80, 0x8b, 0x5, 0x30, 0xf, 0x3c, 0x3, 0x1e, 0x9, 0x2, 0x2, 0x39, 0xb, 0x32, 0x12, 0x80, 0xbc, 0x2, 0x87, 0xc2, 0x34, 0x88, 0xf6, 0x20, 0xa0, 0x78, 0x74, 0x8, 0x23, 0x1, 0x81, 0x83, 0x5, 0x58, 0x2, 0x32, 0x10, 0x62, 0x5, 0x1c, 0xc, 0x2d, 0x4, 0x30, 0xc, 0x69, 0xe, 0xc, 0x1, 0x8, 0x2, 0x62, 0x1, 0x1, 0x3, 0x2, 0x2, 0x5, 0x1, 0x2c, 0x5, 0x5, 0x1, 0x80, 0xed, 0x8, 0xa0, 0x4f, 0x33, 0x1, 0x8e, 0xe2, 0x3, 0x1, 0x2, 0x5, 0x4, 0x85, 0xf0, 0x3, 0x35, 0xe, 0x3c, 0x1, 0x2d, 0x9, 0x47, 0x3, 0x24, 0xc, 0x4d, 0x3, 0x30, 0xd, 0x84, 0xeb, 0xb, 0xa0, 0x58, 0x9b, 0x2e];
+_T Alphabetic = [0x41, 0x1a, 0x6, 0x1a, 0x2f, 0x1, 0xa, 0x1, 0x4, 0x1, 0x5, 0x17, 0x1, 0x1f, 0x1, 0x81, 0xca, 0x4, 0xc, 0xe, 0x5, 0x7, 0x1, 0x1, 0x1, 0x56, 0x1, 0x2a, 0x5, 0x1, 0x2, 0x2, 0x4, 0x8, 0x1, 0x1, 0x3, 0x1, 0x1, 0x1, 0x14, 0x1, 0x53, 0x1, 0x80, 0x8b, 0x8, 0x80, 0x9e, 0x9, 0x26, 0x2, 0x1, 0x7, 0x27, 0x28, 0xe, 0x1, 0x1, 0x1, 0x2, 0x1, 0x2, 0x1, 0x1, 0x8, 0x1b, 0x5, 0x3, 0x1d, 0xb, 0x5, 0x38, 0x1, 0x7, 0xe, 0x66, 0x1, 0x8, 0x4, 0x8, 0x4, 0x3, 0xa, 0x3, 0x2, 0x1, 0x10, 0x30, 0xd, 0x65, 0x18, 0x21, 0x9, 0x2, 0x4, 0x1, 0x5, 0x18, 0x2, 0x13, 0x13, 0x19, 0x47, 0x1, 0x1, 0xb, 0x37, 0x6, 0x6, 0xf, 0x1, 0x3c, 0x1, 0x10, 0x1, 0x3, 0x4, 0xf, 0xd, 0x7, 0x1, 0x7, 0x1, 0x3, 0x1, 0x8, 0x2, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x1, 0x3, 0x4, 0x3, 0x8, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x8, 0x1, 0x4, 0x2, 0x1, 0x5, 0xc, 0x2, 0xf, 0x3, 0x1, 0x6, 0x4, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x2, 0x1, 0x2, 0x4, 0x5, 0x4, 0x2, 0x2, 0x2, 0x4, 0x1, 0x7, 0x4, 0x1, 0x1, 0x11, 0x6, 0xb, 0x3, 0x1, 0x9, 0x1, 0x3, 0x1, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x5, 0x3, 0x9, 0x1, 0x3, 0x1, 0x2, 0x3, 0x1, 0xf, 0x4, 0x1d, 0x3, 0x1, 0x8, 0x2, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x5, 0x3, 0x8, 0x2, 0x2, 0x2, 0x2, 0x9, 0x2, 0x4, 0x2, 0x1, 0x5, 0xd, 0x1, 0x10, 0x2, 0x1, 0x6, 0x3, 0x3, 0x1, 0x4, 0x3, 0x2, 0x1, 0x1, 0x1, 0x2, 0x3, 0x2, 0x3, 0x3, 0x3, 0xc, 0x4, 0x5, 0x3, 0x3, 0x1, 0x3, 0x3, 0x1, 0x6, 0x1, 0x29, 0x3, 0x1, 0x8, 0x1, 0x3, 0x1, 0x17, 0x1, 0xa, 0x1, 0x5, 0x3, 0x8, 0x1, 0x3, 0x1, 0x3, 0x8, 0x2, 0x1, 0x2, 0x6, 0x4, 0x1e, 0x2, 0x1, 0x8, 0x1, 0x3, 0x1, 0x17, 0x1, 0xa, 0x1, 0x5, 0x3, 0x8, 0x1, 0x3, 0x1, 0x3, 0x8, 0x2, 0x7, 0x1, 0x1, 0x4, 0xd, 0x2, 0xf, 0x2, 0x1, 0x8, 0x1, 0x3, 0x1, 0x29, 0x2, 0x8, 0x1, 0x3, 0x1, 0x3, 0x1, 0x1, 0x8, 0x1, 0x8, 0x4, 0x16, 0x6, 0x2, 0x2, 0x1, 0x12, 0x3, 0x18, 0x1, 0x9, 0x1, 0x1, 0x2, 0x7, 0x8, 0x6, 0x1, 0x1, 0x1, 0x8, 0x12, 0x2, 0xd, 0x3a, 0x5, 0x7, 0x6, 0x1, 0x33, 0x2, 0x1, 0x1, 0x2, 0x2, 0x1, 0x1, 0x2, 0x1, 0x6, 0x4, 0x1, 0x7, 0x1, 0x3, 0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0x1, 0xd, 0x1, 0x3, 0x2, 0x5, 0x1, 0x1, 0x6, 0x1, 0xe, 0x4, 0x20, 0x1, 0x3f, 0x8, 0x1, 0x24, 0x4, 0x11, 0x6, 0x10, 0x1, 0x24, 0x43, 0x37, 0x1, 0x1, 0x2, 0x5, 0x10, 0x13, 0x2, 0x4, 0x5, 0x19, 0x7, 0x1, 0xd, 0x2, 0x2, 0x26, 0x1, 0x1, 0x5, 0x1, 0x2, 0x2b, 0x1, 0x81, 0x4d, 0x1, 0x4, 0x2, 0x7, 0x1, 0x1, 0x1, 0x4, 0x2, 0x29, 0x1, 0x4, 0x2, 0x21, 0x1, 0x4, 0x2, 0x7, 0x1, 0x1, 0x1, 0x4, 0x2, 0xf, 0x1, 0x39, 0x1, 0x4, 0x2, 0x43, 0x4, 0x1, 0x20, 0x10, 0x10, 0x55, 0xc, 0x82, 0x6c, 0x2, 0x11, 0x1, 0x1a, 0x5, 0x4b, 0x3, 0x3, 0xf, 0xd, 0x1, 0x6, 0xc, 0x14, 0xc, 0x14, 0xc, 0xd, 0x1, 0x3, 0x1, 0x2, 0xc, 0x34, 0x2, 0x13, 0xe, 0x1, 0x4, 0x1, 0x43, 0x58, 0x8, 0x2b, 0x5, 0x46, 0xa, 0x1d, 0x3, 0xc, 0x4, 0x9, 0x17, 0x1e, 0x2, 0x5, 0xb, 0x2c, 0x4, 0x1a, 0x36, 0x1c, 0x4, 0x3f, 0x2, 0x14, 0x32, 0x1, 0x58, 0x34, 0x1, 0xf, 0x1, 0x7, 0x34, 0x2a, 0x2, 0x4, 0xa, 0x2c, 0x1, 0xb, 0xe, 0x36, 0x17, 0x3, 0xa, 0x24, 0x6b, 0x4, 0x1, 0x6, 0x1, 0x2, 0x9, 0x80, 0xc0, 0x40, 0x81, 0x16, 0x2, 0x6, 0x2, 0x26, 0x2, 0x6, 0x2, 0x8, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1f, 0x2, 0x35, 0x1, 0x7, 0x1, 0x1, 0x3, 0x3, 0x1, 0x7, 0x3, 0x4, 0x2, 0x6, 0x4, 0xd, 0x5, 0x3, 0x1, 0x7, 0x74, 0x1, 0xd, 0x1, 0x10, 0xd, 0x65, 0x1, 0x4, 0x1, 0x2, 0xa, 0x1, 0x1, 0x3, 0x5, 0x6, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x1, 0xb, 0x2, 0x4, 0x5, 0x5, 0x4, 0x1, 0x11, 0x29, 0x83, 0x2d, 0x34, 0x87, 0x16, 0x2f, 0x1, 0x2f, 0x1, 0x80, 0x85, 0x6, 0x4, 0x3, 0x2, 0xc, 0x26, 0x1, 0x1, 0x5, 0x1, 0x2, 0x38, 0x7, 0x1, 0x10, 0x17, 0x9, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x20, 0x2f, 0x1, 0x81, 0xd5, 0x3, 0x19, 0x9, 0x7, 0x5, 0x2, 0x5, 0x4, 0x56, 0x6, 0x3, 0x1, 0x5a, 0x1, 0x4, 0x5, 0x29, 0x3, 0x5e, 0x11, 0x1b, 0x35, 0x10, 0x82, 0x0, 0x99, 0xb6, 0x4a, 0xa0, 0x51, 0xcd, 0x33, 0x84, 0x8d, 0x43, 0x2e, 0x2, 0x81, 0xd, 0x3, 0x10, 0xa, 0x2, 0x14, 0x2f, 0x5, 0x8, 0x3, 0x19, 0x7, 0x51, 0x27, 0x9, 0x2, 0x67, 0x2, 0x4, 0x1, 0x4, 0xc, 0xb, 0x4d, 0xa, 0x1, 0x3, 0x1, 0x4, 0x1, 0x1c, 0x18, 0x34, 0xc, 0x44, 0x2e, 0x6, 0x3, 0x1, 0xe, 0x21, 0x5, 0x23, 0xd, 0x1d, 0x3, 0x33, 0x1, 0xc, 0xf, 0x1, 0x30, 0x37, 0x9, 0xe, 0x12, 0x17, 0x3, 0x1, 0x5, 0x3f, 0x1, 0x1, 0x1, 0x1, 0x18, 0x3, 0x2, 0x10, 0x2, 0x4, 0xb, 0x6, 0x2, 0x6, 0x2, 0x6, 0x9, 0x7, 0x1, 0x7, 0x80, 0x91, 0x2b, 0x15, 0xa0, 0x2b, 0xa4, 0xc, 0x17, 0x4, 0x31, 0xa0, 0x21, 0x4, 0x81, 0x6e, 0x2, 0x6a, 0x26, 0x7, 0xc, 0x5, 0x5, 0xc, 0x1, 0xd, 0x1, 0x5, 0x1, 0x1, 0x1, 0x2, 0x1, 0x2, 0x1, 0x6c, 0x21, 0x81, 0x6b, 0x12, 0x40, 0x2, 0x36, 0x28, 0xc, 0x74, 0x5, 0x1, 0x80, 0x87, 0x24, 0x1a, 0x6, 0x1a, 0xb, 0x59, 0x3, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x3, 0x23, 0xc, 0x1, 0x1a, 0x1, 0x13, 0x1, 0x2, 0x1, 0xf, 0x2, 0xe, 0x22, 0x7b, 0x45, 0x35, 0x81, 0xb, 0x1d, 0x3, 0x31, 0x2f, 0x1f, 0x11, 0x1b, 0x35, 0x1e, 0x2, 0x24, 0x4, 0x8, 0x1, 0x5, 0x2a, 0x80, 0x9e, 0x83, 0x62, 0x6, 0x2, 0x1, 0x1, 0x2c, 0x1, 0x2, 0x3, 0x1, 0x2, 0x17, 0x80, 0xaa, 0x16, 0xa, 0x1a, 0x46, 0x38, 0x6, 0x2, 0x40, 0x4, 0x1, 0x2, 0x5, 0x8, 0x1, 0x3, 0x1, 0x1b, 0x2c, 0x1d, 0x80, 0x83, 0x36, 0xa, 0x16, 0xa, 0x13, 0x80, 0x8d, 0x49, 0x83, 0xb7, 0x46, 0x3c, 0x37, 0x17, 0x19, 0x17, 0x33, 0x4d, 0x40, 0x1, 0x4, 0x84, 0xbb, 0x36, 0x89, 0x4a, 0x83, 0x6f, 0x80, 0x91, 0x63, 0x8b, 0x9d, 0x84, 0x2f, 0xa0, 0x33, 0xd1, 0x82, 0x39, 0x84, 0xc7, 0x45, 0xb, 0x2f, 0x14, 0xd, 0xa0, 0x40, 0x60, 0x2, 0xa0, 0x23, 0xfe, 0x55, 0x1, 0x47, 0x1, 0x2, 0x2, 0x1, 0x2, 0x2, 0x2, 0x4, 0x1, 0xc, 0x1, 0x1, 0x1, 0x7, 0x1, 0x41, 0x1, 0x4, 0x2, 0x8, 0x1, 0x7, 0x1, 0x1c, 0x1, 0x4, 0x1, 0x5, 0x1, 0x1, 0x3, 0x7, 0x1, 0x81, 0x54, 0x2, 0x19, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x8, 0x96, 0x34, 0x4, 0x1, 0x1b, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0xa, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x6, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x3, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x2, 0x4, 0x1, 0x7, 0x1, 0x4, 0x1, 0x4, 0x1, 0x1, 0x1, 0xa, 0x1, 0x11, 0x5, 0x3, 0x1, 0x5, 0x1, 0x11, 0x91, 0x44, 0xa0, 0xa6, 0xd7, 0x29, 0x90, 0x35, 0xb, 0x80, 0xde, 0xa0, 0x3f, 0xe2, 0x82, 0x1e];
+_T Zs = [0x20, 0x1, 0x7f, 0x1, 0x95, 0xdf, 0x1, 0x89, 0x7f, 0xb, 0x24, 0x1, 0x2f, 0x1, 0x8f, 0xa0, 0x1];
+_T Variation_Selector = [0x98, 0xb, 0x3, 0xa0, 0xe5, 0xf2, 0x10, 0xad, 0x2, 0xf0, 0x80, 0xf0];
+_T Other_Default_Ignorable_Code_Point = [0x83, 0x4f, 0x1, 0x8e, 0xf, 0x2, 0x86, 0x53, 0x2, 0x88, 0xaf, 0x1, 0x90, 0xfe, 0x1, 0xa0, 0xce, 0x3b, 0x1, 0x4f, 0x9, 0xad, 0x0, 0x7, 0x1, 0x1, 0x1e, 0x60, 0x80, 0x80, 0x80, 0xf0, 0x8e, 0x10];
+_T IDS_Binary_Operator = [0xa0, 0x2f, 0xf0, 0x2, 0x2, 0x8];
+_T Grapheme_Base = [0x20, 0x5f, 0x21, 0xd, 0x1, 0x82, 0x52, 0x70, 0x8, 0x2, 0x5, 0x5, 0x7, 0x1, 0x1, 0x1, 0x14, 0x1, 0x80, 0xe0, 0x7, 0x80, 0x9e, 0x9, 0x26, 0x2, 0x7, 0x1, 0x27, 0x1, 0x2, 0x4, 0x1, 0x2e, 0x1, 0x1, 0x1, 0x2, 0x1, 0x2, 0x1, 0x9, 0x1b, 0x5, 0x5, 0x11, 0xa, 0xb, 0x1, 0x2, 0x2d, 0x15, 0x10, 0x1, 0x65, 0x8, 0x1, 0x6, 0x2, 0x2, 0x1, 0x4, 0x20, 0x2, 0x1, 0x1, 0x1e, 0x1d, 0x59, 0xb, 0x1, 0xe, 0x2b, 0x9, 0x7, 0x5, 0x16, 0x4, 0x1, 0x9, 0x1, 0x3, 0x1, 0x7, 0xf, 0x1, 0x19, 0x5, 0x1, 0x41, 0x1, 0x1, 0xb, 0x56, 0x37, 0x1, 0x1, 0x1, 0x4, 0x8, 0x4, 0x1, 0x3, 0x7, 0xa, 0x2, 0x14, 0x1, 0x7, 0x2, 0x2, 0x1, 0x8, 0x2, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x1, 0x3, 0x4, 0x3, 0x1, 0x1, 0x2, 0x6, 0x2, 0x2, 0x2, 0x1, 0x1, 0xd, 0x2, 0x1, 0x3, 0x4, 0x16, 0x7, 0x1, 0x1, 0x6, 0x4, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x2, 0x1, 0x2, 0x4, 0x3, 0x18, 0x4, 0x1, 0x1, 0x7, 0xa, 0x2, 0x3, 0xe, 0x1, 0x1, 0x9, 0x1, 0x3, 0x1, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x5, 0x3, 0x4, 0x8, 0x1, 0x1, 0x2, 0x3, 0x1, 0xf, 0x2, 0x4, 0xc, 0x10, 0x2, 0x1, 0x8, 0x2, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x5, 0x3, 0x1, 0x2, 0x1, 0x6, 0x2, 0x2, 0x2, 0xf, 0x2, 0x1, 0x3, 0x4, 0x12, 0xb, 0x1, 0x1, 0x6, 0x3, 0x3, 0x1, 0x4, 0x3, 0x2, 0x1, 0x1, 0x1, 0x2, 0x3, 0x2, 0x3, 0x3, 0x3, 0xc, 0x5, 0x1, 0x1, 0x2, 0x3, 0x3, 0x1, 0x3, 0x3, 0x1, 0x15, 0x15, 0x6, 0x3, 0x1, 0x8, 0x1, 0x3, 0x1, 0x17, 0x1, 0xa, 0x1, 0x5, 0x3, 0x1, 0x3, 0x4, 0x13, 0x2, 0x6, 0x2, 0x4, 0xa, 0x8, 0x8, 0x2, 0x2, 0x1, 0x8, 0x1, 0x3, 0x1, 0x17, 0x1, 0xa, 0x1, 0x5, 0x3, 0x2, 0x1, 0x2, 0x1, 0x2, 0x2, 0x2, 0x1, 0x2, 0x12, 0x1, 0x1, 0x2, 0x4, 0xa, 0x1, 0x2, 0xf, 0x2, 0x1, 0x8, 0x1, 0x3, 0x1, 0x29, 0x2, 0x1, 0x1, 0x2, 0x5, 0x3, 0x1, 0x3, 0x1, 0x1, 0x11, 0x2, 0x4, 0x10, 0x3, 0x7, 0x2, 0x2, 0x1, 0x12, 0x3, 0x18, 0x1, 0x9, 0x1, 0x1, 0x2, 0x7, 0x9, 0x2, 0x6, 0x7, 0x13, 0x3, 0xc, 0x30, 0x1, 0x2, 0xb, 0x8, 0x8, 0xd, 0x25, 0x2, 0x1, 0x1, 0x2, 0x2, 0x1, 0x1, 0x2, 0x1, 0x6, 0x4, 0x1, 0x7, 0x1, 0x3, 0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0x1, 0x4, 0x1, 0x2, 0x9, 0x1, 0x2, 0x5, 0x1, 0x1, 0x9, 0xa, 0x2, 0x4, 0x20, 0x18, 0x2, 0x1b, 0x1, 0x1, 0x1, 0x1, 0x1, 0xe, 0x1, 0x24, 0x12, 0x1, 0x5, 0x1, 0x2, 0x5, 0x31, 0x8, 0x1, 0x6, 0x1, 0xd, 0x25, 0x2d, 0x4, 0x1, 0x6, 0x1, 0x2, 0x2, 0x2, 0x19, 0x2, 0x4, 0x3, 0x10, 0x4, 0xd, 0x1, 0x2, 0x2, 0x6, 0x1, 0xf, 0x1, 0x28, 0x1, 0x1, 0x5, 0x1, 0x2, 0x81, 0x79, 0x1, 0x4, 0x2, 0x7, 0x1, 0x1, 0x1, 0x4, 0x2, 0x29, 0x1, 0x4, 0x2, 0x21, 0x1, 0x4, 0x2, 0x7, 0x1, 0x1, 0x1, 0x4, 0x2, 0xf, 0x1, 0x39, 0x1, 0x4, 0x2, 0x43, 0x5, 0x1d, 0x3, 0x1a, 0x6, 0x55, 0xb, 0x82, 0x9d, 0x3, 0x51, 0xf, 0xd, 0x1, 0x4, 0xe, 0x12, 0x3, 0x2, 0x9, 0x12, 0xe, 0xd, 0x1, 0x3, 0xf, 0x34, 0x2, 0x1, 0x7, 0x8, 0x1, 0x2, 0xb, 0x9, 0x3, 0xa, 0x6, 0xa, 0x6, 0xb, 0x5, 0xa, 0x6, 0x58, 0x8, 0x29, 0x1, 0x1, 0x5, 0x46, 0xa, 0x1d, 0x6, 0x4, 0x2, 0x3, 0x4, 0x2, 0x1, 0x6, 0x7, 0x1, 0x3, 0x2a, 0x2, 0x5, 0xb, 0x2c, 0x4, 0x1a, 0x6, 0xb, 0x3, 0x39, 0x2, 0x2, 0x3, 0x38, 0x1, 0x1, 0x9, 0x1, 0x1, 0x2, 0x8, 0x6, 0xd, 0xa, 0x6, 0xa, 0x6, 0xe, 0x56, 0x30, 0x1, 0x1, 0x5, 0x1, 0x1, 0x5, 0x1, 0x9, 0x4, 0x1b, 0x9, 0x9, 0x5, 0x20, 0x4, 0x2, 0x2, 0x1, 0x1, 0x3a, 0x1, 0x1, 0x2, 0x3, 0x1, 0x1, 0x3, 0x2, 0x8, 0x30, 0x8, 0x2, 0x5, 0xf, 0x3, 0x33, 0x40, 0x8, 0xb, 0x1, 0xd, 0x1, 0x7, 0x4, 0x1, 0x6, 0x1, 0x2, 0x9, 0x80, 0xc0, 0x40, 0x81, 0x16, 0x2, 0x6, 0x2, 0x26, 0x2, 0x6, 0x2, 0x8, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1f, 0x2, 0x35, 0x1, 0xf, 0x1, 0xe, 0x2, 0x6, 0x1, 0x13, 0x2, 0x3, 0x1, 0x9, 0x1, 0xb, 0x5, 0x18, 0x7, 0x31, 0x10, 0x2, 0x2, 0x1b, 0x1, 0xd, 0x3, 0x1b, 0x45, 0x80, 0x8a, 0x6, 0x82, 0x64, 0xc, 0x27, 0x19, 0xb, 0x15, 0x82, 0xa0, 0x1, 0x84, 0x4c, 0x3, 0xa, 0x80, 0xa6, 0x2f, 0x1, 0x2f, 0x1, 0x80, 0x8f, 0x3, 0x2, 0x5, 0x2d, 0x1, 0x1, 0x5, 0x1, 0x2, 0x38, 0x7, 0x2, 0xf, 0x17, 0x9, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x21, 0x3c, 0x44, 0x1a, 0x1, 0x59, 0xc, 0x80, 0xd6, 0x1a, 0xc, 0x4, 0x2a, 0x6, 0x10, 0x1, 0x56, 0x4, 0x65, 0x5, 0x29, 0x3, 0x5e, 0x1, 0x2b, 0x5, 0x24, 0xc, 0x2f, 0x1, 0x80, 0xdf, 0x1, 0x9a, 0xb6, 0xa, 0xa0, 0x52, 0xd, 0x33, 0x84, 0x8d, 0x3, 0x37, 0x9, 0x81, 0x5c, 0x14, 0x2f, 0x4, 0x1, 0xa, 0x1a, 0x8, 0x50, 0x2, 0x6, 0x8, 0x80, 0x8f, 0x1, 0x4, 0xc, 0xb, 0x4d, 0xa, 0x1, 0x3, 0x1, 0x4, 0x1, 0x19, 0x2, 0x5, 0x4, 0xa, 0x6, 0x38, 0x8, 0x44, 0xa, 0xc, 0x18, 0xa, 0x4, 0x26, 0x8, 0x19, 0xb, 0x2, 0xb, 0x1e, 0x6, 0x30, 0x1, 0x2, 0x4, 0x2, 0x1, 0x11, 0x1, 0xb, 0x4, 0x2, 0x20, 0x29, 0x6, 0x2, 0x2, 0x2, 0xb, 0x3, 0x1, 0x8, 0x1, 0x1, 0x2, 0xa, 0x2, 0x20, 0x4, 0x30, 0x1, 0x1, 0x3, 0x2, 0x2, 0x5, 0x2, 0x1, 0x1, 0x1, 0x18, 0x11, 0x2, 0x8, 0xb, 0x6, 0x2, 0x6, 0x2, 0x6, 0x9, 0x7, 0x1, 0x7, 0x80, 0x91, 0x25, 0x1, 0x2, 0x1, 0x4, 0x3, 0xa, 0x6, 0xa0, 0x2b, 0xa4, 0xc, 0x17, 0x4, 0x31, 0xa0, 0x21, 0x4, 0x81, 0x6e, 0x2, 0x6a, 0x26, 0x7, 0xc, 0x5, 0x5, 0x1, 0x1, 0x18, 0x1, 0x5, 0x1, 0x1, 0x1, 0x2, 0x1, 0x2, 0x1, 0x7c, 0x11, 0x81, 0x6d, 0x10, 0x40, 0x2, 0x36, 0x28, 0xe, 0x12, 0xa, 0x16, 0x23, 0x1, 0x13, 0x1, 0x4, 0x4, 0x5, 0x1, 0x80, 0x87, 0x4, 0x80, 0x9d, 0x2, 0x1f, 0x3, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x3, 0x3, 0x7, 0x1, 0x7, 0xd, 0x2, 0x2, 0xc, 0x1, 0x1a, 0x1, 0x13, 0x1, 0x2, 0x1, 0xf, 0x2, 0xe, 0x22, 0x7b, 0x5, 0x3, 0x4, 0x2d, 0x3, 0x54, 0x5, 0xc, 0x34, 0x2d, 0x80, 0x83, 0x1d, 0x3, 0x31, 0x2f, 0x1f, 0x1, 0x4, 0xc, 0x1b, 0x35, 0x1e, 0x1, 0x25, 0x4, 0xe, 0x2a, 0x80, 0x9e, 0x2, 0xa, 0x83, 0x56, 0x6, 0x2, 0x1, 0x1, 0x2c, 0x1, 0x2, 0x3, 0x1, 0x2, 0x17, 0x1, 0x9, 0x80, 0xa0, 0x1c, 0x3, 0x1b, 0x5, 0x1, 0x40, 0x38, 0x6, 0x2, 0x40, 0x1, 0xf, 0x4, 0x1, 0x3, 0x1, 0x1b, 0xc, 0x8, 0x8, 0x9, 0x7, 0x20, 0x80, 0x80, 0x36, 0x3, 0x1d, 0x2, 0x1b, 0x5, 0x8, 0x80, 0x80, 0x49, 0x82, 0x17, 0x1f, 0x81, 0x81, 0x1, 0x1, 0x36, 0xf, 0x7, 0x4, 0x1e, 0x12, 0x31, 0x4, 0x2, 0x2, 0x2, 0x1, 0x4, 0xe, 0x19, 0x7, 0xa, 0x9, 0x24, 0x5, 0x1, 0x9, 0xe, 0x3e, 0x34, 0x9, 0xa, 0x7, 0xa, 0x84, 0xa6, 0x2b, 0x1, 0x1, 0x1, 0x2, 0x6, 0x1, 0x9, 0xa, 0x89, 0x36, 0x83, 0x6f, 0x80, 0x91, 0x63, 0xd, 0x4, 0x8b, 0x8c, 0x84, 0x2f, 0xa0, 0x33, 0xd1, 0x82, 0x39, 0x84, 0xc7, 0x45, 0xb, 0x2f, 0x14, 0xd, 0xa0, 0x40, 0x60, 0x2, 0x9f, 0xfe, 0x80, 0xf6, 0xa, 0x27, 0x2, 0x3c, 0x1, 0x1, 0x3, 0x4, 0x15, 0x2, 0x7, 0x1e, 0x4, 0x30, 0x22, 0x42, 0x3, 0x1, 0x80, 0xba, 0x57, 0x9, 0x12, 0x80, 0x8e, 0x55, 0x1, 0x47, 0x1, 0x2, 0x2, 0x1, 0x2, 0x2, 0x2, 0x4, 0x1, 0xc, 0x1, 0x1, 0x1, 0x7, 0x1, 0x41, 0x1, 0x4, 0x2, 0x8, 0x1, 0x7, 0x1, 0x1c, 0x1, 0x4, 0x1, 0x5, 0x1, 0x1, 0x3, 0x7, 0x1, 0x81, 0x54, 0x2, 0x81, 0x24, 0x2, 0x32, 0x96, 0x0, 0x4, 0x1, 0x1b, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0xa, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x6, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x3, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x2, 0x4, 0x1, 0x7, 0x1, 0x4, 0x1, 0x4, 0x1, 0x1, 0x1, 0xa, 0x1, 0x11, 0x5, 0x3, 0x1, 0x5, 0x1, 0x11, 0x34, 0x2, 0x81, 0xe, 0x2c, 0x4, 0x64, 0xc, 0xf, 0x2, 0xe, 0x2, 0xf, 0x1, 0xf, 0x20, 0xb, 0x5, 0x1f, 0x1, 0x3c, 0x4, 0x2b, 0x4b, 0x1d, 0xd, 0x2b, 0x5, 0x9, 0x7, 0x2, 0x80, 0xae, 0x21, 0xf, 0x6, 0x1, 0x46, 0x3, 0x14, 0xc, 0x25, 0x1, 0x5, 0x15, 0x11, 0xf, 0x3f, 0x1, 0x1, 0x1, 0x80, 0xb6, 0x1, 0x4, 0x3, 0x3e, 0x2, 0x4, 0xc, 0x18, 0x80, 0x93, 0x46, 0x4, 0xb, 0x30, 0x46, 0x3a, 0x74, 0x88, 0x8c, 0xa0, 0xa6, 0xd7, 0x29, 0x90, 0x35, 0xb, 0x80, 0xde, 0xa0, 0x3f, 0xe2, 0x82, 0x1e];
+_T Case_Ignorable = [0x27, 0x1, 0x6, 0x1, 0xb, 0x1, 0x23, 0x1, 0x1, 0x1, 0x47, 0x1, 0x4, 0x1, 0x1, 0x1, 0x4, 0x1, 0x2, 0x2, 0x81, 0xf7, 0x80, 0xc0, 0x4, 0x2, 0x4, 0x1, 0x9, 0x2, 0x1, 0x1, 0x80, 0xfb, 0x7, 0x80, 0xcf, 0x1, 0x37, 0x2d, 0x1, 0x1, 0x1, 0x2, 0x1, 0x2, 0x1, 0x1, 0x2c, 0x1, 0xb, 0x5, 0xb, 0xb, 0x1, 0x1, 0x23, 0x1, 0xa, 0x15, 0x10, 0x1, 0x65, 0x8, 0x1, 0xa, 0x1, 0x4, 0x21, 0x1, 0x1, 0x1, 0x1e, 0x1b, 0x5b, 0xb, 0x3a, 0xb, 0x4, 0x1, 0x1b, 0x18, 0x2b, 0x3, 0x80, 0x88, 0x1b, 0x1, 0x3, 0x37, 0x1, 0x1, 0x1, 0x4, 0x8, 0x4, 0x1, 0x3, 0x7, 0xa, 0x2, 0xd, 0x1, 0xf, 0x1, 0x3a, 0x1, 0x4, 0x4, 0x8, 0x1, 0x14, 0x2, 0x1d, 0x2, 0x39, 0x1, 0x4, 0x2, 0x4, 0x2, 0x2, 0x3, 0x3, 0x1, 0x1e, 0x2, 0x3, 0x1, 0xb, 0x2, 0x39, 0x1, 0x4, 0x5, 0x1, 0x2, 0x4, 0x1, 0x14, 0x2, 0x1d, 0x1, 0x3a, 0x1, 0x2, 0x1, 0x1, 0x4, 0x8, 0x1, 0x8, 0x1, 0xb, 0x2, 0x1e, 0x1, 0x3d, 0x1, 0xc, 0x1, 0x70, 0x3, 0x5, 0x3, 0x1, 0x4, 0x7, 0x2, 0xb, 0x2, 0x58, 0x1, 0x2, 0x1, 0x6, 0x1, 0x5, 0x2, 0x14, 0x2, 0x5d, 0x4, 0x8, 0x1, 0x14, 0x2, 0x66, 0x1, 0x7, 0x3, 0x1, 0x1, 0x5a, 0x1, 0x2, 0x7, 0xb, 0x9, 0x62, 0x1, 0x2, 0x6, 0x1, 0x2, 0x9, 0x1, 0x1, 0x6, 0x4a, 0x2, 0x1b, 0x1, 0x1, 0x1, 0x1, 0x1, 0x37, 0xe, 0x1, 0x5, 0x1, 0x2, 0x5, 0xb, 0x1, 0x24, 0x9, 0x1, 0x66, 0x4, 0x1, 0x6, 0x1, 0x2, 0x2, 0x2, 0x19, 0x2, 0x4, 0x3, 0x10, 0x4, 0xd, 0x1, 0x2, 0x2, 0x6, 0x1, 0xf, 0x1, 0x5e, 0x1, 0x82, 0x60, 0x3, 0x83, 0xb2, 0x3, 0x1d, 0x3, 0x1d, 0x2, 0x1e, 0x2, 0x40, 0x2, 0x1, 0x7, 0x8, 0x1, 0x2, 0xb, 0x3, 0x1, 0x5, 0x1, 0x2d, 0x4, 0x34, 0x1, 0x65, 0x1, 0x76, 0x3, 0x4, 0x2, 0x9, 0x1, 0x6, 0x3, 0x80, 0xdb, 0x2, 0x2, 0x1, 0x3a, 0x1, 0x1, 0x7, 0x1, 0x1, 0x1, 0x1, 0x2, 0x8, 0x6, 0xa, 0x2, 0x1, 0x27, 0x1, 0x58, 0x4, 0x30, 0x1, 0x1, 0x5, 0x1, 0x1, 0x5, 0x1, 0x28, 0x9, 0xc, 0x2, 0x20, 0x4, 0x2, 0x2, 0x1, 0x1, 0x3a, 0x1, 0x1, 0x2, 0x3, 0x1, 0x1, 0x3, 0x3a, 0x8, 0x2, 0x2, 0x40, 0x6, 0x52, 0x3, 0x1, 0xd, 0x1, 0x7, 0x4, 0x1, 0x6, 0x1, 0x37, 0x3f, 0xd, 0x1, 0x22, 0x4c, 0x15, 0x4, 0x81, 0xbd, 0x1, 0x1, 0x3, 0xb, 0x3, 0xd, 0x3, 0xd, 0x3, 0xd, 0x2, 0xc, 0x5, 0x8, 0x2, 0xa, 0x1, 0x2, 0x1, 0x2, 0x5, 0x31, 0x5, 0x1, 0xa, 0x1, 0x1, 0xd, 0x1, 0x10, 0xd, 0x33, 0x21, 0x8b, 0x8b, 0x2, 0x71, 0x3, 0x7d, 0x1, 0xf, 0x1, 0x60, 0x20, 0x2f, 0x1, 0x81, 0xd5, 0x1, 0x24, 0x4, 0x3, 0x5, 0x5, 0x1, 0x5d, 0x6, 0x5d, 0x3, 0xa0, 0x6f, 0x16, 0x1, 0x84, 0xe2, 0x6, 0x81, 0xe, 0x1, 0x62, 0x4, 0x1, 0xa, 0x1, 0x1, 0x1f, 0x1, 0x50, 0x2, 0xe, 0x22, 0x4e, 0x1, 0x17, 0x3, 0x6d, 0x2, 0x8, 0x1, 0x3, 0x1, 0x4, 0x1, 0x19, 0x2, 0x80, 0x9d, 0x1, 0x1b, 0x12, 0x34, 0x8, 0x19, 0xb, 0x2e, 0x3, 0x30, 0x1, 0x2, 0x4, 0x2, 0x1, 0x12, 0x1, 0x59, 0x6, 0x2, 0x2, 0x2, 0x2, 0xc, 0x1, 0x8, 0x1, 0x23, 0x1, 0x3f, 0x1, 0x1, 0x3, 0x2, 0x2, 0x5, 0x2, 0x1, 0x1, 0x1b, 0x1, 0xe, 0x2, 0x5, 0x2, 0x1, 0x1, 0x80, 0xee, 0x1, 0x2, 0x1, 0x4, 0x1, 0xa0, 0x4f, 0x30, 0x1, 0x80, 0x93, 0x10, 0x82, 0x3e, 0x10, 0x3, 0x1, 0xc, 0x7, 0x2b, 0x1, 0x2, 0x1, 0x80, 0xa9, 0x1, 0x7, 0x1, 0x6, 0x1, 0xb, 0x1, 0x23, 0x1, 0x1, 0x1, 0x2f, 0x1, 0x2d, 0x2, 0x43, 0x1, 0x15, 0x3, 0x82, 0x1, 0x1, 0x88, 0x3, 0x3, 0x1, 0x2, 0x5, 0x4, 0x28, 0x3, 0x4, 0x1, 0x85, 0xc1, 0x1, 0x36, 0xf, 0x39, 0x2, 0x31, 0x4, 0x2, 0x2, 0x2, 0x1, 0x42, 0x3, 0x24, 0x5, 0x1, 0x8, 0x4b, 0x2, 0x34, 0x9, 0x84, 0xec, 0x1, 0x1, 0x1, 0x2, 0x6, 0x1, 0x1, 0xa0, 0x58, 0xd7, 0x11, 0xa0, 0x61, 0xc7, 0x3, 0x9, 0x10, 0x2, 0x7, 0x1e, 0x4, 0x80, 0x94, 0x3, 0xac, 0x2d, 0xbc, 0x1, 0x1e, 0x60, 0x80, 0x80, 0x80, 0xf0];
+_T STerm = [0x21, 0x1, 0xc, 0x1, 0x10, 0x1, 0x85, 0x1c, 0x1, 0x1, 0x1, 0x2a, 0x1, 0x80, 0x95, 0x1, 0x80, 0xb4, 0x1, 0x2b, 0x3, 0x80, 0xf6, 0x1, 0x81, 0x6a, 0x2, 0x86, 0xe4, 0x2, 0x83, 0x16, 0x1, 0x4, 0x2, 0x83, 0x5, 0x1, 0x80, 0xc6, 0x2, 0x80, 0xcc, 0x1, 0x5, 0x1, 0x81, 0x3a, 0x2, 0x81, 0x62, 0x4, 0x80, 0xae, 0x2, 0x2, 0x2, 0x80, 0xdb, 0x2, 0x41, 0x2, 0x83, 0xbc, 0x2, 0x9, 0x3, 0x8d, 0xe4, 0x1, 0x81, 0xd3, 0x1, 0xa0, 0x74, 0xfc, 0x1, 0x81, 0xe, 0x2, 0x80, 0xe3, 0x1, 0x3, 0x1, 0x81, 0x7e, 0x2, 0x56, 0x2, 0x5f, 0x1, 0x80, 0x98, 0x2, 0x80, 0x93, 0x3, 0x80, 0x90, 0x2, 0x80, 0xf9, 0x1, 0xa0, 0x52, 0x66, 0x1, 0x3, 0x2, 0x80, 0xa9, 0x1, 0xc, 0x1, 0x10, 0x1, 0x41, 0x1, 0x8a, 0xf4, 0x2, 0x85, 0xef, 0x2, 0x75, 0x4, 0x7f, 0x3, 0x80, 0x81, 0x2];
+_T Diacritic = [0x5e, 0x1, 0x1, 0x1, 0x47, 0x1, 0x6, 0x1, 0x4, 0x1, 0x2, 0x2, 0x81, 0xf7, 0x80, 0x9f, 0x1, 0x8, 0x5, 0x6, 0x11, 0x2, 0x4, 0x1, 0x9, 0x2, 0x80, 0xfd, 0x5, 0x80, 0xd1, 0x1, 0x37, 0x11, 0x1, 0x1b, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x80, 0x86, 0x8, 0x4, 0x2, 0x80, 0x86, 0x2, 0x4, 0x2, 0x3, 0x3, 0x43, 0x1b, 0x5b, 0xb, 0x3a, 0xb, 0x22, 0x2, 0x80, 0xca, 0x1b, 0x3d, 0x1, 0x10, 0x1, 0x3, 0x4, 0x1c, 0x1, 0x4a, 0x1, 0x10, 0x1, 0x6e, 0x1, 0x10, 0x1, 0x6e, 0x1, 0x10, 0x1, 0x6e, 0x1, 0x10, 0x1, 0x7f, 0x1, 0x7f, 0x1, 0x6e, 0x1, 0x10, 0x1, 0x7f, 0x1, 0x7c, 0x1, 0x7c, 0x6, 0x1, 0x1, 0x79, 0x5, 0x4b, 0x2, 0x1b, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x2, 0x42, 0x3, 0x1, 0x2, 0x3e, 0x1, 0x70, 0x1, 0x1, 0x2, 0x4c, 0x7, 0x1, 0x1, 0xa, 0x2, 0x87, 0x2d, 0xb, 0x9, 0x1, 0x81, 0x5b, 0x3, 0x81, 0x39, 0x8, 0x2, 0x1, 0x80, 0xb4, 0x1, 0xf, 0x1, 0x26, 0x9, 0x36, 0x2, 0x80, 0x8a, 0x2, 0x40, 0x6, 0x52, 0x19, 0x4, 0x1, 0x6, 0x1, 0x37, 0x3f, 0x59, 0xc, 0x2d, 0x3, 0x81, 0xbd, 0x1, 0x1, 0x3, 0xb, 0x3, 0xd, 0x3, 0xd, 0x3, 0xd, 0x2, 0x8c, 0xf0, 0x3, 0x81, 0x3d, 0x1, 0x81, 0xfa, 0x6, 0x69, 0x4, 0x5f, 0x1, 0xa0, 0x75, 0x72, 0x1, 0xc, 0x2, 0x1, 0x1, 0x70, 0x2, 0x25, 0xb, 0x66, 0x1, 0x6f, 0x2, 0x80, 0xca, 0x1, 0x1b, 0x12, 0x39, 0x4, 0x24, 0x1, 0x5f, 0x1, 0xc, 0x1, 0x80, 0xba, 0x1, 0x43, 0x4, 0x33, 0x1, 0x80, 0xf5, 0x2, 0xa0, 0x4f, 0x30, 0x1, 0x83, 0x1, 0x7, 0x81, 0x17, 0x1, 0x1, 0x1, 0x2f, 0x1, 0x2d, 0x2, 0x43, 0x1, 0x90, 0xd5, 0x2, 0x78, 0x2, 0x80, 0x8b, 0x1, 0x84, 0xf5, 0x2, 0xa0, 0x58, 0xd7, 0x11, 0xa0, 0x61, 0xc7, 0x3, 0x3, 0x6, 0x8, 0x8, 0x2, 0x7, 0x1e, 0x4];
+_T Lm = [0x82, 0xb0, 0x12, 0x4, 0xc, 0xe, 0x5, 0x7, 0x1, 0x1, 0x1, 0x80, 0x85, 0x1, 0x5, 0x1, 0x81, 0xde, 0x1, 0x80, 0xe6, 0x1, 0x80, 0xa4, 0x2, 0x81, 0xd, 0x2, 0x4, 0x1, 0x1f, 0x1, 0x9, 0x1, 0x3, 0x1, 0x81, 0x48, 0x1, 0x84, 0xd4, 0x1, 0x7f, 0x1, 0x82, 0x35, 0x1, 0x86, 0xda, 0x1, 0x6b, 0x1, 0x82, 0x63, 0x1, 0x81, 0xd0, 0x6, 0x80, 0xae, 0x3f, 0xd, 0x1, 0x22, 0x25, 0x82, 0xb1, 0x1, 0xd, 0x1, 0x10, 0xd, 0x8b, 0xdf, 0x2, 0x80, 0xf1, 0x1, 0x80, 0xbf, 0x1, 0x81, 0xd5, 0x1, 0x2b, 0x5, 0x5, 0x1, 0x61, 0x2, 0x5d, 0x3, 0xa0, 0x6f, 0x16, 0x1, 0x84, 0xe2, 0x6, 0x81, 0xe, 0x1, 0x72, 0x1, 0x80, 0x97, 0x9, 0x50, 0x1, 0x17, 0x1, 0x6f, 0x2, 0x81, 0xd5, 0x1, 0x80, 0xa0, 0x1, 0x6c, 0x1, 0x15, 0x2, 0xa0, 0x54, 0x7b, 0x1, 0x2d, 0x2, 0xa0, 0x6f, 0xf3, 0xd];
+_T Mc = [0x89, 0x3, 0x1, 0x37, 0x1, 0x2, 0x3, 0x8, 0x4, 0x1, 0x2, 0x32, 0x2, 0x3a, 0x3, 0x6, 0x2, 0x2, 0x2, 0xa, 0x1, 0x2b, 0x1, 0x3a, 0x3, 0x42, 0x1, 0x3a, 0x3, 0x8, 0x1, 0x1, 0x2, 0x35, 0x2, 0x3a, 0x1, 0x1, 0x1, 0x6, 0x2, 0x2, 0x2, 0xa, 0x1, 0x66, 0x2, 0x1, 0x2, 0x3, 0x3, 0x1, 0x3, 0xa, 0x1, 0x29, 0x3, 0x3d, 0x4, 0x3d, 0x2, 0x3a, 0x1, 0x1, 0x5, 0x2, 0x2, 0x1, 0x2, 0x9, 0x2, 0x2b, 0x2, 0x3a, 0x3, 0x5, 0x3, 0x1, 0x3, 0xa, 0x1, 0x2a, 0x2, 0x4b, 0x3, 0x6, 0x8, 0x12, 0x2, 0x81, 0x4a, 0x2, 0x3f, 0x1, 0x80, 0xab, 0x2, 0x4, 0x1, 0x6, 0x1, 0x2, 0x2, 0x19, 0x2, 0xa, 0x3, 0x2, 0x7, 0x15, 0x2, 0x2, 0x6, 0x2, 0x1, 0xa, 0x3, 0x87, 0x19, 0x1, 0x7, 0x8, 0x1, 0x2, 0x81, 0x5a, 0x4, 0x2, 0x3, 0x4, 0x2, 0x1, 0x6, 0x77, 0x11, 0x7, 0x2, 0x4f, 0x2, 0x3a, 0x1, 0x1, 0x1, 0x9, 0x1, 0x1, 0x2, 0x8, 0x6, 0x80, 0x91, 0x1, 0x30, 0x1, 0x5, 0x1, 0x1, 0x5, 0x1, 0x2, 0x3d, 0x1, 0x1e, 0x1, 0x4, 0x2, 0x2, 0x1, 0x1, 0x2, 0x39, 0x1, 0x2, 0x3, 0x1, 0x1, 0x3, 0x2, 0x30, 0x8, 0x8, 0x2, 0x80, 0xab, 0x1, 0x10, 0x2, 0x93, 0x3a, 0x2, 0xa0, 0x77, 0xf3, 0x2, 0x2, 0x1, 0x58, 0x2, 0x32, 0x10, 0x80, 0x8e, 0x2, 0x2f, 0x1, 0x30, 0x2, 0x4, 0x2, 0x1, 0x4, 0x6e, 0x2, 0x2, 0x2, 0x18, 0x1, 0x2d, 0x1, 0x6f, 0x1, 0x2, 0x2, 0x5, 0x1, 0x80, 0xed, 0x2, 0x1, 0x2, 0x1, 0x2, 0x1, 0x1, 0xa0, 0x64, 0x13, 0x1, 0x1, 0x1, 0x7f, 0x1, 0x2d, 0x3, 0x4, 0x2, 0x73, 0x1, 0x55, 0x1, 0x30, 0x3, 0x9, 0x2, 0x84, 0xeb, 0x1, 0x1, 0x2, 0x6, 0x1, 0xa0, 0x58, 0x9a, 0x2e, 0xa0, 0x61, 0xe6, 0x2, 0x6, 0x6];
+_T Lo = [0x80, 0xaa, 0x1, 0xf, 0x1, 0x81, 0x0, 0x1, 0x4, 0x4, 0x80, 0xd0, 0x1, 0x83, 0x3b, 0x1b, 0x5, 0x3, 0x2d, 0x20, 0x1, 0xa, 0x23, 0x2, 0x1, 0x63, 0x1, 0x1, 0x18, 0x2, 0xa, 0x3, 0x2, 0x1, 0x10, 0x1, 0x1, 0x1e, 0x1d, 0x59, 0xb, 0x1, 0x18, 0x21, 0x15, 0x16, 0x2a, 0x19, 0x47, 0x1, 0x1, 0xb, 0x57, 0x36, 0x3, 0x1, 0x12, 0x1, 0x7, 0xa, 0x10, 0x6, 0x1, 0x7, 0x5, 0x8, 0x2, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x1, 0x3, 0x4, 0x3, 0x1, 0x10, 0x1, 0xd, 0x2, 0x1, 0x3, 0xe, 0x2, 0x13, 0x6, 0x4, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x2, 0x1, 0x2, 0x1f, 0x4, 0x1, 0x1, 0x13, 0x3, 0x10, 0x9, 0x1, 0x3, 0x1, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x5, 0x3, 0x1, 0x12, 0x1, 0xf, 0x2, 0x23, 0x8, 0x2, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x5, 0x3, 0x1, 0x1e, 0x2, 0x1, 0x3, 0xf, 0x1, 0x11, 0x1, 0x1, 0x6, 0x3, 0x3, 0x1, 0x4, 0x3, 0x2, 0x1, 0x1, 0x1, 0x2, 0x3, 0x2, 0x3, 0x3, 0x3, 0xc, 0x16, 0x1, 0x34, 0x8, 0x1, 0x3, 0x1, 0x17, 0x1, 0xa, 0x1, 0x5, 0x3, 0x1, 0x1a, 0x2, 0x6, 0x2, 0x23, 0x8, 0x1, 0x3, 0x1, 0x17, 0x1, 0xa, 0x1, 0x5, 0x3, 0x1, 0x20, 0x1, 0x1, 0x2, 0xf, 0x2, 0x12, 0x8, 0x1, 0x3, 0x1, 0x29, 0x2, 0x1, 0x10, 0x1, 0x11, 0x2, 0x18, 0x6, 0x5, 0x12, 0x3, 0x18, 0x1, 0x9, 0x1, 0x1, 0x2, 0x7, 0x3a, 0x30, 0x1, 0x2, 0xc, 0x6, 0x3b, 0x2, 0x1, 0x1, 0x2, 0x2, 0x1, 0x1, 0x2, 0x1, 0x6, 0x4, 0x1, 0x7, 0x1, 0x3, 0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0x1, 0x4, 0x1, 0x2, 0x9, 0x1, 0x2, 0x5, 0x17, 0x4, 0x20, 0x1, 0x3f, 0x8, 0x1, 0x24, 0x1b, 0x5, 0x73, 0x2b, 0x14, 0x1, 0x10, 0x6, 0x4, 0x4, 0x3, 0x1, 0x3, 0x2, 0x7, 0x3, 0x4, 0xd, 0xc, 0x1, 0x41, 0x2b, 0x2, 0x81, 0x4c, 0x1, 0x4, 0x2, 0x7, 0x1, 0x1, 0x1, 0x4, 0x2, 0x29, 0x1, 0x4, 0x2, 0x21, 0x1, 0x4, 0x2, 0x7, 0x1, 0x1, 0x1, 0x4, 0x2, 0xf, 0x1, 0x39, 0x1, 0x4, 0x2, 0x43, 0x25, 0x10, 0x10, 0x55, 0xc, 0x82, 0x6c, 0x2, 0x11, 0x1, 0x1a, 0x5, 0x4b, 0x15, 0xd, 0x1, 0x4, 0xe, 0x12, 0xe, 0x12, 0xe, 0xd, 0x1, 0x3, 0xf, 0x34, 0x28, 0x1, 0x43, 0x23, 0x1, 0x34, 0x8, 0x29, 0x1, 0x1, 0x5, 0x46, 0xa, 0x1d, 0x33, 0x1e, 0x2, 0x5, 0xb, 0x2c, 0x15, 0x7, 0x38, 0x17, 0x9, 0x35, 0x80, 0xb0, 0x2f, 0x11, 0x7, 0x37, 0x1e, 0xd, 0x2, 0xa, 0x2c, 0x1a, 0x24, 0x29, 0x3, 0xa, 0x1e, 0x71, 0x4, 0x1, 0x4, 0x3, 0x2, 0x84, 0x3e, 0x4, 0x8b, 0xf7, 0x38, 0x18, 0x17, 0x9, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x82, 0x27, 0x1, 0x35, 0x1, 0x4, 0x56, 0x8, 0x1, 0x1, 0x5a, 0x4, 0x1, 0x5, 0x29, 0x3, 0x5e, 0x11, 0x1b, 0x35, 0x10, 0x82, 0x0, 0x99, 0xb6, 0x4a, 0xa0, 0x51, 0xcd, 0x33, 0x15, 0x1, 0x84, 0x77, 0x43, 0x28, 0x8, 0x81, 0xc, 0x4, 0x10, 0xa, 0x2, 0x42, 0x1, 0x31, 0x46, 0x81, 0x15, 0x7, 0x1, 0x3, 0x1, 0x4, 0x1, 0x17, 0x1d, 0x34, 0xe, 0x32, 0x3e, 0x6, 0x3, 0x1, 0xe, 0x1c, 0xa, 0x17, 0x19, 0x1d, 0x7, 0x2f, 0x4d, 0x29, 0x17, 0x3, 0x1, 0x8, 0x14, 0x10, 0x1, 0x6, 0x3, 0x1, 0x5, 0x30, 0x1, 0x1, 0x3, 0x2, 0x2, 0x5, 0x2, 0x1, 0x1, 0x1, 0x18, 0x2, 0x3, 0xb, 0x7, 0x1, 0xe, 0x6, 0x2, 0x6, 0x2, 0x6, 0x9, 0x7, 0x1, 0x7, 0x80, 0x91, 0x23, 0x1d, 0xa0, 0x2b, 0xa4, 0xc, 0x17, 0x4, 0x31, 0xa0, 0x21, 0x4, 0x81, 0x6e, 0x2, 0x6a, 0x43, 0x1, 0x1, 0xa, 0x1, 0xd, 0x1, 0x5, 0x1, 0x1, 0x1, 0x2, 0x1, 0x2, 0x1, 0x6c, 0x21, 0x81, 0x6b, 0x12, 0x40, 0x2, 0x36, 0x28, 0xc, 0x74, 0x5, 0x1, 0x80, 0x87, 0x69, 0xa, 0x1, 0x2d, 0x2, 0x1f, 0x3, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x3, 0x23, 0xc, 0x1, 0x1a, 0x1, 0x13, 0x1, 0x2, 0x1, 0xf, 0x2, 0xe, 0x22, 0x7b, 0x81, 0x85, 0x1d, 0x3, 0x31, 0x2f, 0x1f, 0x11, 0x11, 0x1, 0x8, 0x36, 0x1e, 0x2, 0x24, 0x4, 0x8, 0x80, 0x80, 0x4e, 0x83, 0x62, 0x6, 0x2, 0x1, 0x1, 0x2c, 0x1, 0x2, 0x3, 0x1, 0x2, 0x17, 0x80, 0xaa, 0x16, 0xa, 0x1a, 0x46, 0x38, 0x6, 0x2, 0x40, 0x1, 0xf, 0x4, 0x1, 0x3, 0x1, 0x1b, 0x2c, 0x1d, 0x80, 0x83, 0x36, 0xa, 0x16, 0xa, 0x13, 0x80, 0x8d, 0x49, 0x83, 0xba, 0x35, 0x4b, 0x2d, 0x20, 0x19, 0x1a, 0x24, 0x5c, 0x30, 0xe, 0x4, 0x84, 0xbb, 0x2b, 0x89, 0x55, 0x83, 0x6f, 0x8c, 0x91, 0x84, 0x2f, 0xa0, 0x33, 0xd1, 0x82, 0x39, 0x84, 0xc7, 0x45, 0xb, 0x1, 0xa0, 0x40, 0xaf, 0x2, 0xa0, 0x3d, 0xfe, 0x4, 0x1, 0x1b, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0xa, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x6, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x3, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x2, 0x4, 0x1, 0x7, 0x1, 0x4, 0x1, 0x4, 0x1, 0x1, 0x1, 0xa, 0x1, 0x11, 0x5, 0x3, 0x1, 0x5, 0x1, 0x11, 0x91, 0x44, 0xa0, 0xa6, 0xd7, 0x29, 0x90, 0x35, 0xb, 0x80, 0xde, 0xa0, 0x3f, 0xe2, 0x82, 0x1e];
+_T Me = [0x84, 0x88, 0x2, 0x9c, 0x53, 0x4, 0x1, 0x3, 0xa0, 0x85, 0x8b, 0x3];
+_T ID_Start = [0x41, 0x1a, 0x6, 0x1a, 0x2f, 0x1, 0xa, 0x1, 0x4, 0x1, 0x5, 0x17, 0x1, 0x1f, 0x1, 0x81, 0xca, 0x4, 0xc, 0xe, 0x5, 0x7, 0x1, 0x1, 0x1, 0x80, 0x81, 0x5, 0x1, 0x2, 0x2, 0x4, 0x8, 0x1, 0x1, 0x3, 0x1, 0x1, 0x1, 0x14, 0x1, 0x53, 0x1, 0x80, 0x8b, 0x8, 0x80, 0x9e, 0x9, 0x26, 0x2, 0x1, 0x7, 0x27, 0x48, 0x1b, 0x5, 0x3, 0x2d, 0x2b, 0x23, 0x2, 0x1, 0x63, 0x1, 0x1, 0xf, 0x2, 0x7, 0x2, 0xa, 0x3, 0x2, 0x1, 0x10, 0x1, 0x1, 0x1e, 0x1d, 0x59, 0xb, 0x1, 0x18, 0x21, 0x9, 0x2, 0x4, 0x1, 0x5, 0x16, 0x4, 0x1, 0x9, 0x1, 0x3, 0x1, 0x17, 0x19, 0x47, 0x1, 0x1, 0xb, 0x57, 0x36, 0x3, 0x1, 0x12, 0x1, 0x7, 0xa, 0xf, 0x7, 0x1, 0x7, 0x5, 0x8, 0x2, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x1, 0x3, 0x4, 0x3, 0x1, 0x10, 0x1, 0xd, 0x2, 0x1, 0x3, 0xe, 0x2, 0x13, 0x6, 0x4, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x2, 0x1, 0x2, 0x1f, 0x4, 0x1, 0x1, 0x13, 0x3, 0x10, 0x9, 0x1, 0x3, 0x1, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x5, 0x3, 0x1, 0x12, 0x1, 0xf, 0x2, 0x23, 0x8, 0x2, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x5, 0x3, 0x1, 0x1e, 0x2, 0x1, 0x3, 0xf, 0x1, 0x11, 0x1, 0x1, 0x6, 0x3, 0x3, 0x1, 0x4, 0x3, 0x2, 0x1, 0x1, 0x1, 0x2, 0x3, 0x2, 0x3, 0x3, 0x3, 0xc, 0x16, 0x1, 0x34, 0x8, 0x1, 0x3, 0x1, 0x17, 0x1, 0xa, 0x1, 0x5, 0x3, 0x1, 0x1a, 0x2, 0x6, 0x2, 0x23, 0x8, 0x1, 0x3, 0x1, 0x17, 0x1, 0xa, 0x1, 0x5, 0x3, 0x1, 0x20, 0x1, 0x1, 0x2, 0xf, 0x2, 0x12, 0x8, 0x1, 0x3, 0x1, 0x29, 0x2, 0x1, 0x10, 0x1, 0x11, 0x2, 0x18, 0x6, 0x5, 0x12, 0x3, 0x18, 0x1, 0x9, 0x1, 0x1, 0x2, 0x7, 0x3a, 0x30, 0x1, 0x2, 0xc, 0x7, 0x3a, 0x2, 0x1, 0x1, 0x2, 0x2, 0x1, 0x1, 0x2, 0x1, 0x6, 0x4, 0x1, 0x7, 0x1, 0x3, 0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0x1, 0x4, 0x1, 0x2, 0x9, 0x1, 0x2, 0x5, 0x1, 0x1, 0x15, 0x4, 0x20, 0x1, 0x3f, 0x8, 0x1, 0x24, 0x1b, 0x5, 0x73, 0x2b, 0x14, 0x1, 0x10, 0x6, 0x4, 0x4, 0x3, 0x1, 0x3, 0x2, 0x7, 0x3, 0x4, 0xd, 0xc, 0x1, 0x11, 0x26, 0x1, 0x1, 0x5, 0x1, 0x2, 0x2b, 0x1, 0x81, 0x4d, 0x1, 0x4, 0x2, 0x7, 0x1, 0x1, 0x1, 0x4, 0x2, 0x29, 0x1, 0x4, 0x2, 0x21, 0x1, 0x4, 0x2, 0x7, 0x1, 0x1, 0x1, 0x4, 0x2, 0xf, 0x1, 0x39, 0x1, 0x4, 0x2, 0x43, 0x25, 0x10, 0x10, 0x55, 0xc, 0x82, 0x6c, 0x2, 0x11, 0x1, 0x1a, 0x5, 0x4b, 0x3, 0x3, 0xf, 0xd, 0x1, 0x4, 0xe, 0x12, 0xe, 0x12, 0xe, 0xd, 0x1, 0x3, 0xf, 0x34, 0x23, 0x1, 0x4, 0x1, 0x43, 0x58, 0x8, 0x29, 0x1, 0x1, 0x5, 0x46, 0xa, 0x1d, 0x33, 0x1e, 0x2, 0x5, 0xb, 0x2c, 0x15, 0x7, 0x38, 0x17, 0x9, 0x35, 0x52, 0x1, 0x5d, 0x2f, 0x11, 0x7, 0x37, 0x1e, 0xd, 0x2, 0xa, 0x2c, 0x1a, 0x24, 0x29, 0x3, 0xa, 0x24, 0x6b, 0x4, 0x1, 0x4, 0x3, 0x2, 0x9, 0x80, 0xc0, 0x40, 0x81, 0x16, 0x2, 0x6, 0x2, 0x26, 0x2, 0x6, 0x2, 0x8, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1f, 0x2, 0x35, 0x1, 0x7, 0x1, 0x1, 0x3, 0x3, 0x1, 0x7, 0x3, 0x4, 0x2, 0x6, 0x4, 0xd, 0x5, 0x3, 0x1, 0x7, 0x74, 0x1, 0xd, 0x1, 0x10, 0xd, 0x65, 0x1, 0x4, 0x1, 0x2, 0xa, 0x1, 0x1, 0x2, 0x6, 0x6, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x10, 0x2, 0x4, 0x5, 0x5, 0x4, 0x1, 0x11, 0x29, 0x8a, 0x77, 0x2f, 0x1, 0x2f, 0x1, 0x80, 0x85, 0x6, 0x4, 0x3, 0x2, 0xc, 0x26, 0x1, 0x1, 0x5, 0x1, 0x2, 0x38, 0x7, 0x1, 0x10, 0x17, 0x9, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x82, 0x26, 0x3, 0x19, 0x9, 0x7, 0x5, 0x2, 0x5, 0x4, 0x56, 0x4, 0x5, 0x1, 0x5a, 0x1, 0x4, 0x5, 0x29, 0x3, 0x5e, 0x11, 0x1b, 0x35, 0x10, 0x82, 0x0, 0x99, 0xb6, 0x4a, 0xa0, 0x51, 0xcd, 0x33, 0x84, 0x8d, 0x43, 0x2e, 0x2, 0x81, 0xd, 0x3, 0x10, 0xa, 0x2, 0x14, 0x2f, 0x10, 0x19, 0x8, 0x50, 0x27, 0x9, 0x2, 0x67, 0x2, 0x4, 0x1, 0x4, 0xc, 0xb, 0x4d, 0xa, 0x1, 0x3, 0x1, 0x4, 0x1, 0x17, 0x1d, 0x34, 0xe, 0x32, 0x3e, 0x6, 0x3, 0x1, 0xe, 0x1c, 0xa, 0x17, 0x19, 0x1d, 0x7, 0x2f, 0x1c, 0x1, 0x30, 0x29, 0x17, 0x3, 0x1, 0x8, 0x14, 0x17, 0x3, 0x1, 0x5, 0x30, 0x1, 0x1, 0x3, 0x2, 0x2, 0x5, 0x2, 0x1, 0x1, 0x1, 0x18, 0x3, 0x2, 0xb, 0x7, 0x3, 0xc, 0x6, 0x2, 0x6, 0x2, 0x6, 0x9, 0x7, 0x1, 0x7, 0x80, 0x91, 0x23, 0x1d, 0xa0, 0x2b, 0xa4, 0xc, 0x17, 0x4, 0x31, 0xa0, 0x21, 0x4, 0x81, 0x6e, 0x2, 0x6a, 0x26, 0x7, 0xc, 0x5, 0x5, 0x1, 0x1, 0xa, 0x1, 0xd, 0x1, 0x5, 0x1, 0x1, 0x1, 0x2, 0x1, 0x2, 0x1, 0x6c, 0x21, 0x81, 0x6b, 0x12, 0x40, 0x2, 0x36, 0x28, 0xc, 0x74, 0x5, 0x1, 0x80, 0x87, 0x24, 0x1a, 0x6, 0x1a, 0xb, 0x59, 0x3, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x3, 0x23, 0xc, 0x1, 0x1a, 0x1, 0x13, 0x1, 0x2, 0x1, 0xf, 0x2, 0xe, 0x22, 0x7b, 0x45, 0x35, 0x81, 0xb, 0x1d, 0x3, 0x31, 0x2f, 0x1f, 0x11, 0x1b, 0x35, 0x1e, 0x2, 0x24, 0x4, 0x8, 0x1, 0x5, 0x2a, 0x80, 0x9e, 0x83, 0x62, 0x6, 0x2, 0x1, 0x1, 0x2c, 0x1, 0x2, 0x3, 0x1, 0x2, 0x17, 0x80, 0xaa, 0x16, 0xa, 0x1a, 0x46, 0x38, 0x6, 0x2, 0x40, 0x1, 0xf, 0x4, 0x1, 0x3, 0x1, 0x1b, 0x2c, 0x1d, 0x80, 0x83, 0x36, 0xa, 0x16, 0xa, 0x13, 0x80, 0x8d, 0x49, 0x83, 0xba, 0x35, 0x4b, 0x2d, 0x20, 0x19, 0x1a, 0x24, 0x5c, 0x30, 0xe, 0x4, 0x84, 0xbb, 0x2b, 0x89, 0x55, 0x83, 0x6f, 0x80, 0x91, 0x63, 0x8b, 0x9d, 0x84, 0x2f, 0xa0, 0x33, 0xd1, 0x82, 0x39, 0x84, 0xc7, 0x45, 0xb, 0x1, 0x42, 0xd, 0xa0, 0x40, 0x60, 0x2, 0xa0, 0x23, 0xfe, 0x55, 0x1, 0x47, 0x1, 0x2, 0x2, 0x1, 0x2, 0x2, 0x2, 0x4, 0x1, 0xc, 0x1, 0x1, 0x1, 0x7, 0x1, 0x41, 0x1, 0x4, 0x2, 0x8, 0x1, 0x7, 0x1, 0x1c, 0x1, 0x4, 0x1, 0x5, 0x1, 0x1, 0x3, 0x7, 0x1, 0x81, 0x54, 0x2, 0x19, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x8, 0x96, 0x34, 0x4, 0x1, 0x1b, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0xa, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x6, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x3, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x2, 0x4, 0x1, 0x7, 0x1, 0x4, 0x1, 0x4, 0x1, 0x1, 0x1, 0xa, 0x1, 0x11, 0x5, 0x3, 0x1, 0x5, 0x1, 0x11, 0x91, 0x44, 0xa0, 0xa6, 0xd7, 0x29, 0x90, 0x35, 0xb, 0x80, 0xde, 0xa0, 0x3f, 0xe2, 0x82, 0x1e];
+_T Other_Grapheme_Extend = [0x89, 0xbe, 0x1, 0x18, 0x1, 0x81, 0x66, 0x1, 0x18, 0x1, 0x66, 0x1, 0x18, 0x1, 0x80, 0xea, 0x1, 0x12, 0x2, 0x67, 0x1, 0x18, 0x1, 0x77, 0x1, 0xf, 0x1, 0x92, 0x2c, 0x2, 0x90, 0x20, 0x2, 0xa0, 0xcf, 0x6e, 0x2, 0xa0, 0xd1, 0xc5, 0x1, 0x8, 0x5];
+_T Lt = [0x81, 0xc5, 0x1, 0x2, 0x1, 0x2, 0x1, 0x26, 0x1, 0x9d, 0x95, 0x8, 0x8, 0x8, 0x8, 0x8, 0xc, 0x1, 0xf, 0x1, 0x2f, 0x1];
+_T Pattern_White_Space = [0x9, 0x5, 0x12, 0x1, 0x64, 0x1, 0x9f, 0x88, 0x2, 0x18, 0x2];
+_T Cased = [0x41, 0x1a, 0x6, 0x1a, 0x2f, 0x1, 0xa, 0x1, 0x4, 0x1, 0x5, 0x17, 0x1, 0x1f, 0x1, 0x80, 0xc3, 0x1, 0x4, 0x4, 0x80, 0xd0, 0x1, 0x24, 0x7, 0x2, 0x1e, 0x5, 0x60, 0x1, 0x2a, 0x4, 0x2, 0x2, 0x2, 0x4, 0x8, 0x1, 0x1, 0x3, 0x1, 0x1, 0x1, 0x14, 0x1, 0x53, 0x1, 0x80, 0x8b, 0x8, 0x80, 0x9e, 0x9, 0x26, 0xa, 0x27, 0x8b, 0x18, 0x26, 0x1, 0x1, 0x5, 0x1, 0x8c, 0x32, 0x80, 0xc0, 0x40, 0x81, 0x16, 0x2, 0x6, 0x2, 0x26, 0x2, 0x6, 0x2, 0x8, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1f, 0x2, 0x35, 0x1, 0x7, 0x1, 0x1, 0x3, 0x3, 0x1, 0x7, 0x3, 0x4, 0x2, 0x6, 0x4, 0xd, 0x5, 0x3, 0x1, 0x7, 0x74, 0x1, 0xd, 0x1, 0x10, 0xd, 0x65, 0x1, 0x4, 0x1, 0x2, 0xa, 0x1, 0x1, 0x3, 0x5, 0x6, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x1, 0x6, 0x4, 0x1, 0x2, 0x4, 0x5, 0x5, 0x4, 0x1, 0x11, 0x20, 0x3, 0x2, 0x83, 0x31, 0x34, 0x87, 0x16, 0x2f, 0x1, 0x2f, 0x1, 0x80, 0x85, 0x6, 0x4, 0x3, 0x2, 0xc, 0x26, 0x1, 0x1, 0x5, 0x1, 0xa0, 0x79, 0x12, 0x2e, 0x12, 0x18, 0x80, 0x8a, 0x66, 0x3, 0x4, 0x1, 0x4, 0xc, 0xb, 0x4d, 0x3, 0xa0, 0x53, 0x5, 0x7, 0xc, 0x5, 0x84, 0x9, 0x1a, 0x6, 0x1a, 0x84, 0xa5, 0x50, 0xa0, 0xcf, 0xb0, 0x55, 0x1, 0x47, 0x1, 0x2, 0x2, 0x1, 0x2, 0x2, 0x2, 0x4, 0x1, 0xc, 0x1, 0x1, 0x1, 0x7, 0x1, 0x41, 0x1, 0x4, 0x2, 0x8, 0x1, 0x7, 0x1, 0x1c, 0x1, 0x4, 0x1, 0x5, 0x1, 0x1, 0x3, 0x7, 0x1, 0x81, 0x54, 0x2, 0x19, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x8];
+_T Mn = [0x83, 0x0, 0x70, 0x81, 0x13, 0x5, 0x81, 0x9, 0x2d, 0x1, 0x1, 0x1, 0x2, 0x1, 0x2, 0x1, 0x1, 0x48, 0xb, 0x30, 0x15, 0x10, 0x1, 0x65, 0x7, 0x2, 0x6, 0x2, 0x2, 0x1, 0x4, 0x23, 0x1, 0x1e, 0x1b, 0x5b, 0xb, 0x3a, 0x9, 0x22, 0x4, 0x1, 0x9, 0x1, 0x3, 0x1, 0x5, 0x2b, 0x3, 0x80, 0x88, 0x1b, 0x1, 0x3, 0x37, 0x1, 0x1, 0x1, 0x4, 0x8, 0x4, 0x1, 0x3, 0x7, 0xa, 0x2, 0x1d, 0x1, 0x3a, 0x1, 0x4, 0x4, 0x8, 0x1, 0x14, 0x2, 0x1d, 0x2, 0x39, 0x1, 0x4, 0x2, 0x4, 0x2, 0x2, 0x3, 0x3, 0x1, 0x1e, 0x2, 0x3, 0x1, 0xb, 0x2, 0x39, 0x1, 0x4, 0x5, 0x1, 0x2, 0x4, 0x1, 0x14, 0x2, 0x1d, 0x1, 0x3a, 0x1, 0x2, 0x1, 0x1, 0x4, 0x8, 0x1, 0x8, 0x1, 0xb, 0x2, 0x1e, 0x1, 0x3d, 0x1, 0xc, 0x1, 0x70, 0x3, 0x5, 0x3, 0x1, 0x4, 0x7, 0x2, 0xb, 0x2, 0x58, 0x1, 0x2, 0x1, 0x6, 0x1, 0x5, 0x2, 0x14, 0x2, 0x5d, 0x4, 0x8, 0x1, 0x14, 0x2, 0x66, 0x1, 0x7, 0x3, 0x1, 0x1, 0x5a, 0x1, 0x2, 0x7, 0xc, 0x8, 0x62, 0x1, 0x2, 0x6, 0x1, 0x2, 0xb, 0x6, 0x4a, 0x2, 0x1b, 0x1, 0x1, 0x1, 0x1, 0x1, 0x37, 0xe, 0x1, 0x5, 0x1, 0x2, 0x5, 0xb, 0x1, 0x24, 0x9, 0x1, 0x66, 0x4, 0x1, 0x6, 0x1, 0x2, 0x2, 0x2, 0x19, 0x2, 0x4, 0x3, 0x10, 0x4, 0xd, 0x1, 0x2, 0x2, 0x6, 0x1, 0xf, 0x1, 0x82, 0xbf, 0x3, 0x83, 0xb2, 0x3, 0x1d, 0x3, 0x1d, 0x2, 0x1e, 0x2, 0x40, 0x2, 0x1, 0x7, 0x8, 0x1, 0x2, 0xb, 0x9, 0x1, 0x2d, 0x3, 0x80, 0x9b, 0x1, 0x76, 0x3, 0x4, 0x2, 0x9, 0x1, 0x6, 0x3, 0x80, 0xdb, 0x2, 0x2, 0x1, 0x3a, 0x1, 0x1, 0x7, 0x1, 0x1, 0x1, 0x1, 0x2, 0x8, 0x6, 0xa, 0x2, 0x1, 0x80, 0x80, 0x4, 0x30, 0x1, 0x1, 0x5, 0x1, 0x1, 0x5, 0x1, 0x28, 0x9, 0xc, 0x2, 0x20, 0x4, 0x2, 0x2, 0x1, 0x1, 0x3a, 0x1, 0x1, 0x2, 0x3, 0x1, 0x1, 0x3, 0x3a, 0x8, 0x2, 0x2, 0x80, 0x98, 0x3, 0x1, 0xd, 0x1, 0x7, 0x4, 0x1, 0x6, 0x1, 0x80, 0xcb, 0x27, 0x15, 0x4, 0x82, 0xd0, 0xd, 0x4, 0x1, 0x3, 0xc, 0x8b, 0xfe, 0x3, 0x80, 0x8d, 0x1, 0x60, 0x20, 0x82, 0x2a, 0x4, 0x6b, 0x2, 0xa0, 0x75, 0xd4, 0x1, 0x4, 0xa, 0x21, 0x1, 0x50, 0x2, 0x81, 0x10, 0x1, 0x3, 0x1, 0x4, 0x1, 0x19, 0x2, 0x80, 0x9d, 0x1, 0x1b, 0x12, 0x34, 0x8, 0x19, 0xb, 0x2e, 0x3, 0x30, 0x1, 0x2, 0x4, 0x2, 0x1, 0x6c, 0x6, 0x2, 0x2, 0x2, 0x2, 0xc, 0x1, 0x8, 0x1, 0x63, 0x1, 0x1, 0x3, 0x2, 0x2, 0x5, 0x2, 0x1, 0x1, 0x2a, 0x2, 0x8, 0x1, 0x80, 0xee, 0x1, 0x2, 0x1, 0x4, 0x1, 0xa0, 0x4f, 0x30, 0x1, 0x82, 0xe1, 0x10, 0x10, 0x7, 0x83, 0xd6, 0x1, 0x88, 0x3, 0x3, 0x1, 0x2, 0x5, 0x4, 0x28, 0x3, 0x4, 0x1, 0x85, 0xc1, 0x1, 0x36, 0xf, 0x39, 0x2, 0x31, 0x4, 0x2, 0x2, 0x45, 0x3, 0x24, 0x5, 0x1, 0x8, 0x4b, 0x2, 0x34, 0x9, 0x84, 0xec, 0x1, 0x1, 0x1, 0x2, 0x6, 0x1, 0x1, 0xa0, 0x58, 0xd7, 0x4, 0xa0, 0x61, 0xd4, 0x3, 0x11, 0x8, 0x2, 0x7, 0x1e, 0x4, 0x80, 0x94, 0x3, 0xac, 0x2e, 0xbb, 0x80, 0xf0];
+_T Dash = [0x2d, 0x1, 0x85, 0x5c, 0x1, 0x33, 0x1, 0x8e, 0x41, 0x1, 0x84, 0x5, 0x1, 0x88, 0x9, 0x6, 0x3d, 0x1, 0x27, 0x1, 0xf, 0x1, 0x81, 0x86, 0x1, 0x8c, 0x4, 0x1, 0x2, 0x1, 0x1f, 0x2, 0x81, 0xe0, 0x1, 0x13, 0x1, 0x6f, 0x1, 0xa0, 0xcd, 0x90, 0x2, 0x25, 0x1, 0xa, 0x1, 0x80, 0xa9, 0x1];
+_T ID_Continue = [0x30, 0xa, 0x7, 0x1a, 0x4, 0x1, 0x1, 0x1a, 0x2f, 0x1, 0xa, 0x1, 0x1, 0x1, 0x2, 0x1, 0x5, 0x17, 0x1, 0x1f, 0x1, 0x81, 0xca, 0x4, 0xc, 0xe, 0x5, 0x7, 0x1, 0x1, 0x1, 0x11, 0x75, 0x1, 0x2, 0x2, 0x4, 0x8, 0x5, 0x1, 0x1, 0x1, 0x14, 0x1, 0x53, 0x1, 0x80, 0x8b, 0x1, 0x5, 0x2, 0x80, 0x9e, 0x9, 0x26, 0x2, 0x1, 0x7, 0x27, 0x9, 0x2d, 0x1, 0x1, 0x1, 0x2, 0x1, 0x2, 0x1, 0x1, 0x8, 0x1b, 0x5, 0x3, 0x1d, 0xb, 0x5, 0x4a, 0x4, 0x66, 0x1, 0x8, 0x2, 0xa, 0x1, 0x13, 0x2, 0x1, 0x10, 0x3b, 0x2, 0x65, 0xe, 0x36, 0x4, 0x1, 0x5, 0x2e, 0x12, 0x1c, 0x44, 0x1, 0x1, 0xb, 0x37, 0x1b, 0x1, 0x64, 0x2, 0xa, 0x1, 0x7, 0x1, 0x7, 0x1, 0x3, 0x1, 0x8, 0x2, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x1, 0x3, 0x4, 0x2, 0x9, 0x2, 0x2, 0x2, 0x4, 0x8, 0x1, 0x4, 0x2, 0x1, 0x5, 0x2, 0xc, 0xf, 0x3, 0x1, 0x6, 0x4, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x2, 0x1, 0x2, 0x2, 0x1, 0x1, 0x5, 0x4, 0x2, 0x2, 0x3, 0x3, 0x1, 0x7, 0x4, 0x1, 0x1, 0x7, 0x10, 0xb, 0x3, 0x1, 0x9, 0x1, 0x3, 0x1, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x5, 0x2, 0xa, 0x1, 0x3, 0x1, 0x3, 0x2, 0x1, 0xf, 0x4, 0x2, 0xa, 0x11, 0x3, 0x1, 0x8, 0x2, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x5, 0x2, 0x9, 0x2, 0x2, 0x2, 0x3, 0x8, 0x2, 0x4, 0x2, 0x1, 0x5, 0x2, 0xa, 0x1, 0x1, 0x10, 0x2, 0x1, 0x6, 0x3, 0x3, 0x1, 0x4, 0x3, 0x2, 0x1, 0x1, 0x1, 0x2, 0x3, 0x2, 0x3, 0x3, 0x3, 0xc, 0x4, 0x5, 0x3, 0x3, 0x1, 0x4, 0x2, 0x1, 0x6, 0x1, 0xe, 0xa, 0x11, 0x3, 0x1, 0x8, 0x1, 0x3, 0x1, 0x17, 0x1, 0xa, 0x1, 0x5, 0x3, 0x8, 0x1, 0x3, 0x1, 0x4, 0x7, 0x2, 0x1, 0x2, 0x6, 0x4, 0x2, 0xa, 0x12, 0x2, 0x1, 0x8, 0x1, 0x3, 0x1, 0x17, 0x1, 0xa, 0x1, 0x5, 0x2, 0x9, 0x1, 0x3, 0x1, 0x4, 0x7, 0x2, 0x7, 0x1, 0x1, 0x4, 0x2, 0xa, 0x1, 0x2, 0xf, 0x2, 0x1, 0x8, 0x1, 0x3, 0x1, 0x29, 0x2, 0x8, 0x1, 0x3, 0x1, 0x5, 0x8, 0x1, 0x8, 0x4, 0x2, 0xa, 0xa, 0x6, 0x2, 0x2, 0x1, 0x12, 0x3, 0x18, 0x1, 0x9, 0x1, 0x1, 0x2, 0x7, 0x3, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x8, 0x12, 0x2, 0xd, 0x3a, 0x5, 0xf, 0x1, 0xa, 0x27, 0x2, 0x1, 0x1, 0x2, 0x2, 0x1, 0x1, 0x2, 0x1, 0x6, 0x4, 0x1, 0x7, 0x1, 0x3, 0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0x1, 0xd, 0x1, 0x3, 0x2, 0x5, 0x1, 0x1, 0x1, 0x6, 0x2, 0xa, 0x2, 0x4, 0x20, 0x1, 0x17, 0x2, 0x6, 0xa, 0xb, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0xa, 0x1, 0x24, 0x4, 0x14, 0x1, 0x12, 0x1, 0x24, 0x9, 0x1, 0x39, 0x4a, 0x6, 0x4e, 0x2, 0x26, 0x1, 0x1, 0x5, 0x1, 0x2, 0x2b, 0x1, 0x81, 0x4d, 0x1, 0x4, 0x2, 0x7, 0x1, 0x1, 0x1, 0x4, 0x2, 0x29, 0x1, 0x4, 0x2, 0x21, 0x1, 0x4, 0x2, 0x7, 0x1, 0x1, 0x1, 0x4, 0x2, 0xf, 0x1, 0x39, 0x1, 0x4, 0x2, 0x43, 0x2, 0x3, 0x9, 0x9, 0xe, 0x10, 0x10, 0x55, 0xc, 0x82, 0x6c, 0x2, 0x11, 0x1, 0x1a, 0x5, 0x4b, 0x3, 0x3, 0xf, 0xd, 0x1, 0x7, 0xb, 0x15, 0xb, 0x14, 0xc, 0xd, 0x1, 0x3, 0x1, 0x2, 0xc, 0x54, 0x3, 0x1, 0x4, 0x2, 0x2, 0xa, 0x21, 0x3, 0x2, 0xa, 0x6, 0x58, 0x8, 0x2b, 0x5, 0x46, 0xa, 0x1d, 0x3, 0xc, 0x4, 0xc, 0xa, 0x28, 0x2, 0x5, 0xb, 0x2c, 0x4, 0x1a, 0x6, 0xb, 0x25, 0x1c, 0x4, 0x3f, 0x1, 0x1d, 0x2, 0xb, 0x6, 0xa, 0xd, 0x1, 0x58, 0x4c, 0x4, 0xa, 0x11, 0x9, 0xc, 0x74, 0xc, 0x38, 0x8, 0xa, 0x3, 0x31, 0x52, 0x3, 0x1, 0x23, 0x9, 0x80, 0xe7, 0x15, 0x81, 0x1a, 0x2, 0x6, 0x2, 0x26, 0x2, 0x6, 0x2, 0x8, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1f, 0x2, 0x35, 0x1, 0x7, 0x1, 0x1, 0x3, 0x3, 0x1, 0x7, 0x3, 0x4, 0x2, 0x6, 0x4, 0xd, 0x5, 0x3, 0x1, 0x7, 0x42, 0x2, 0x13, 0x1, 0x1c, 0x1, 0xd, 0x1, 0x10, 0xd, 0x33, 0xd, 0x4, 0x1, 0x3, 0xc, 0x11, 0x1, 0x4, 0x1, 0x2, 0xa, 0x1, 0x1, 0x2, 0x6, 0x6, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x10, 0x2, 0x4, 0x5, 0x5, 0x4, 0x1, 0x11, 0x29, 0x8a, 0x77, 0x2f, 0x1, 0x2f, 0x1, 0x80, 0x85, 0x6, 0x9, 0xc, 0x26, 0x1, 0x1, 0x5, 0x1, 0x2, 0x38, 0x7, 0x1, 0xf, 0x18, 0x9, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x20, 0x82, 0x5, 0x3, 0x19, 0xf, 0x1, 0x5, 0x2, 0x5, 0x4, 0x56, 0x2, 0x7, 0x1, 0x5a, 0x1, 0x4, 0x5, 0x29, 0x3, 0x5e, 0x11, 0x1b, 0x35, 0x10, 0x82, 0x0, 0x99, 0xb6, 0x4a, 0xa0, 0x51, 0xcd, 0x33, 0x84, 0x8d, 0x43, 0x2e, 0x2, 0x81, 0xd, 0x3, 0x1c, 0x14, 0x30, 0x4, 0xa, 0x1, 0x19, 0x7, 0x53, 0x25, 0x9, 0x2, 0x67, 0x2, 0x4, 0x1, 0x4, 0xc, 0xb, 0x4d, 0x30, 0x18, 0x34, 0xc, 0x45, 0xb, 0xa, 0x6, 0x18, 0x3, 0x1, 0x4, 0x2e, 0x2, 0x24, 0xc, 0x1d, 0x3, 0x41, 0xe, 0xb, 0x26, 0x37, 0x9, 0xe, 0x2, 0xa, 0x6, 0x17, 0x3, 0x2, 0x4, 0x43, 0x18, 0x3, 0x2, 0x10, 0x2, 0x5, 0xa, 0x6, 0x2, 0x6, 0x2, 0x6, 0x9, 0x7, 0x1, 0x7, 0x80, 0x91, 0x2b, 0x1, 0x2, 0x2, 0xa, 0x6, 0xa0, 0x2b, 0xa4, 0xc, 0x17, 0x4, 0x31, 0xa0, 0x21, 0x4, 0x81, 0x6e, 0x2, 0x6a, 0x26, 0x7, 0xc, 0x5, 0x5, 0xc, 0x1, 0xd, 0x1, 0x5, 0x1, 0x1, 0x1, 0x2, 0x1, 0x2, 0x1, 0x6c, 0x21, 0x81, 0x6b, 0x12, 0x40, 0x2, 0x36, 0x28, 0xc, 0x4, 0x10, 0x10, 0x7, 0xc, 0x2, 0x18, 0x3, 0x20, 0x5, 0x1, 0x80, 0x87, 0x13, 0xa, 0x7, 0x1a, 0x4, 0x1, 0x1, 0x1a, 0xb, 0x59, 0x3, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x3, 0x23, 0xc, 0x1, 0x1a, 0x1, 0x13, 0x1, 0x2, 0x1, 0xf, 0x2, 0xe, 0x22, 0x7b, 0x45, 0x35, 0x80, 0x88, 0x1, 0x80, 0x82, 0x1d, 0x3, 0x31, 0x2f, 0x1f, 0x11, 0x1b, 0x35, 0x1e, 0x2, 0x24, 0x4, 0x8, 0x1, 0x5, 0x2a, 0x80, 0x9e, 0x2, 0xa, 0x83, 0x56, 0x6, 0x2, 0x1, 0x1, 0x2c, 0x1, 0x2, 0x3, 0x1, 0x2, 0x17, 0x80, 0xaa, 0x16, 0xa, 0x1a, 0x46, 0x38, 0x6, 0x2, 0x40, 0x4, 0x1, 0x2, 0x5, 0x8, 0x1, 0x3, 0x1, 0x1b, 0x4, 0x3, 0x4, 0x1, 0x20, 0x1d, 0x80, 0x83, 0x36, 0xa, 0x16, 0xa, 0x13, 0x80, 0x8d, 0x49, 0x83, 0xb7, 0x47, 0x1f, 0xa, 0x10, 0x3b, 0x15, 0x19, 0x7, 0xa, 0x6, 0x35, 0x1, 0xa, 0x40, 0x45, 0xb, 0xa, 0x84, 0xa6, 0x38, 0x8, 0xa, 0x89, 0x36, 0x83, 0x6f, 0x80, 0x91, 0x63, 0x8b, 0x9d, 0x84, 0x2f, 0xa0, 0x33, 0xd1, 0x82, 0x39, 0x84, 0xc7, 0x45, 0xb, 0x2f, 0x10, 0x11, 0xa0, 0x40, 0x60, 0x2, 0xa0, 0x21, 0x63, 0x5, 0x3, 0x6, 0x8, 0x8, 0x2, 0x7, 0x1e, 0x4, 0x80, 0x94, 0x3, 0x81, 0xbb, 0x55, 0x1, 0x47, 0x1, 0x2, 0x2, 0x1, 0x2, 0x2, 0x2, 0x4, 0x1, 0xc, 0x1, 0x1, 0x1, 0x7, 0x1, 0x41, 0x1, 0x4, 0x2, 0x8, 0x1, 0x7, 0x1, 0x1c, 0x1, 0x4, 0x1, 0x5, 0x1, 0x1, 0x3, 0x7, 0x1, 0x81, 0x54, 0x2, 0x19, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x8, 0x2, 0x32, 0x96, 0x0, 0x4, 0x1, 0x1b, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0xa, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x6, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x3, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x2, 0x4, 0x1, 0x7, 0x1, 0x4, 0x1, 0x4, 0x1, 0x1, 0x1, 0xa, 0x1, 0x11, 0x5, 0x3, 0x1, 0x5, 0x1, 0x11, 0x91, 0x44, 0xa0, 0xa6, 0xd7, 0x29, 0x90, 0x35, 0xb, 0x80, 0xde, 0xa0, 0x3f, 0xe2, 0x82, 0x1e, 0xab, 0x6, 0xe2, 0x80, 0xf0];
+_T White_Space = [0x9, 0x5, 0x12, 0x1, 0x64, 0x1, 0x1a, 0x1, 0x95, 0xdf, 0x1, 0x89, 0x7f, 0xb, 0x1d, 0x2, 0x5, 0x1, 0x2f, 0x1, 0x8f, 0xa0, 0x1];
+_T Grapheme_Link = [0x89, 0x4d, 0x1, 0x7f, 0x1, 0x7f, 0x1, 0x7f, 0x1, 0x7f, 0x1, 0x7f, 0x1, 0x7f, 0x1, 0x7f, 0x1, 0x7f, 0x1, 0x7c, 0x1, 0x6f, 0x1, 0x81, 0x49, 0x1, 0x80, 0xb4, 0x2, 0x86, 0xd9, 0x1, 0x1f, 0x1, 0x80, 0x9d, 0x1, 0x82, 0x8d, 0x1, 0x80, 0xe3, 0x1, 0x65, 0x2, 0x46, 0x2, 0x91, 0x8b, 0x1, 0xa0, 0x7a, 0x86, 0x1, 0x80, 0xbd, 0x1, 0x80, 0x8e, 0x1, 0x6c, 0x1, 0x81, 0x35, 0x1, 0x80, 0xf6, 0x1, 0xa0, 0x5e, 0x51, 0x1, 0x86, 0x6, 0x1, 0x72, 0x1, 0x79, 0x2, 0x80, 0x8b, 0x1, 0x84, 0xf5, 0x1];
+_T Ll = [0x61, 0x1a, 0x3a, 0x1, 0x29, 0x18, 0x1, 0x8, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x3, 0x2, 0x1, 0x1, 0x1, 0x2, 0x1, 0x3, 0x2, 0x4, 0x1, 0x2, 0x1, 0x3, 0x3, 0x2, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x3, 0x1, 0x1, 0x1, 0x2, 0x2, 0x2, 0x3, 0x6, 0x1, 0x2, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0x1, 0x1, 0x1, 0x3, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x7, 0x2, 0x1, 0x2, 0x2, 0x1, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x45, 0x1, 0x1b, 0x80, 0xc1, 0x1, 0x1, 0x1, 0x3, 0x1, 0x3, 0x3, 0x12, 0x1, 0x1b, 0x23, 0x1, 0x2, 0x3, 0x3, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x5, 0x1, 0x1, 0x2, 0x1, 0x2, 0x2, 0x33, 0x30, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x9, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x39, 0x27, 0x97, 0x78, 0x2c, 0x3f, 0xd, 0x1, 0x22, 0x66, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x9, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x9, 0x8, 0x6, 0xa, 0x8, 0x8, 0x8, 0x8, 0x6, 0xa, 0x8, 0x8, 0x8, 0x8, 0xe, 0x2, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x5, 0x1, 0x2, 0x6, 0x1, 0x3, 0x3, 0x1, 0x2, 0x8, 0x4, 0x2, 0x2, 0x8, 0x8, 0xa, 0x3, 0x1, 0x2, 0x81, 0x12, 0x1, 0x3, 0x2, 0x3, 0x1, 0x1b, 0x1, 0x4, 0x1, 0x4, 0x1, 0x2, 0x2, 0x8, 0x4, 0x4, 0x1, 0x35, 0x1, 0x8a, 0xab, 0x2f, 0x2, 0x1, 0x3, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x1, 0x1, 0x2, 0x1, 0x6, 0x5, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x7, 0x1, 0x1, 0x1, 0x4, 0x1, 0xc, 0x26, 0x1, 0x1, 0x5, 0x1, 0xa0, 0x79, 0x13, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x13, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x80, 0x8b, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x3, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x8, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0xd, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x50, 0x1, 0xa0, 0x53, 0x5, 0x7, 0xc, 0x5, 0x84, 0x29, 0x1a, 0x84, 0xcd, 0x28, 0xa0, 0xcf, 0xca, 0x1a, 0x1a, 0x7, 0x1, 0x12, 0x1a, 0x1a, 0x1a, 0x4, 0x1, 0x1, 0x1, 0x7, 0x1, 0xb, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1c, 0x1c, 0x19, 0x1, 0x6, 0x1a, 0x19, 0x1, 0x6, 0x1a, 0x19, 0x1, 0x6, 0x1a, 0x19, 0x1, 0x6, 0x1a, 0x19, 0x1, 0x6, 0x1, 0x1];
+_T Cc = [0x0, 0x20, 0x5f, 0x21];
+_T Pattern_Syntax = [0x21, 0xf, 0xa, 0x7, 0x1a, 0x4, 0x1, 0x1, 0x1a, 0x4, 0x22, 0x7, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x2, 0x4, 0x1, 0x4, 0x1, 0x3, 0x1, 0x17, 0x1, 0x1f, 0x1, 0x9f, 0x18, 0x18, 0x8, 0xf, 0x2, 0x13, 0x1, 0xa, 0x81, 0x31, 0x82, 0xd0, 0x80, 0xa0, 0x82, 0x76, 0x1e, 0x84, 0x6c, 0x82, 0x0, 0x80, 0x80, 0x81, 0x81, 0x3, 0x4, 0x19, 0xf, 0x1, 0xa0, 0xcd, 0xd, 0x2, 0x81, 0x5, 0x2];
+_T XID_Continue = [0x30, 0xa, 0x7, 0x1a, 0x4, 0x1, 0x1, 0x1a, 0x2f, 0x1, 0xa, 0x1, 0x1, 0x1, 0x2, 0x1, 0x5, 0x17, 0x1, 0x1f, 0x1, 0x81, 0xca, 0x4, 0xc, 0xe, 0x5, 0x7, 0x1, 0x1, 0x1, 0x11, 0x75, 0x1, 0x2, 0x3, 0x3, 0x8, 0x5, 0x1, 0x1, 0x1, 0x14, 0x1, 0x53, 0x1, 0x80, 0x8b, 0x1, 0x5, 0x2, 0x80, 0x9e, 0x9, 0x26, 0x2, 0x1, 0x7, 0x27, 0x9, 0x2d, 0x1, 0x1, 0x1, 0x2, 0x1, 0x2, 0x1, 0x1, 0x8, 0x1b, 0x5, 0x3, 0x1d, 0xb, 0x5, 0x4a, 0x4, 0x66, 0x1, 0x8, 0x2, 0xa, 0x1, 0x13, 0x2, 0x1, 0x10, 0x3b, 0x2, 0x65, 0xe, 0x36, 0x4, 0x1, 0x5, 0x2e, 0x12, 0x1c, 0x44, 0x1, 0x1, 0xb, 0x37, 0x1b, 0x1, 0x64, 0x2, 0xa, 0x1, 0x7, 0x1, 0x7, 0x1, 0x3, 0x1, 0x8, 0x2, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x1, 0x3, 0x4, 0x2, 0x9, 0x2, 0x2, 0x2, 0x4, 0x8, 0x1, 0x4, 0x2, 0x1, 0x5, 0x2, 0xc, 0xf, 0x3, 0x1, 0x6, 0x4, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x2, 0x1, 0x2, 0x2, 0x1, 0x1, 0x5, 0x4, 0x2, 0x2, 0x3, 0x3, 0x1, 0x7, 0x4, 0x1, 0x1, 0x7, 0x10, 0xb, 0x3, 0x1, 0x9, 0x1, 0x3, 0x1, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x5, 0x2, 0xa, 0x1, 0x3, 0x1, 0x3, 0x2, 0x1, 0xf, 0x4, 0x2, 0xa, 0x11, 0x3, 0x1, 0x8, 0x2, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x5, 0x2, 0x9, 0x2, 0x2, 0x2, 0x3, 0x8, 0x2, 0x4, 0x2, 0x1, 0x5, 0x2, 0xa, 0x1, 0x1, 0x10, 0x2, 0x1, 0x6, 0x3, 0x3, 0x1, 0x4, 0x3, 0x2, 0x1, 0x1, 0x1, 0x2, 0x3, 0x2, 0x3, 0x3, 0x3, 0xc, 0x4, 0x5, 0x3, 0x3, 0x1, 0x4, 0x2, 0x1, 0x6, 0x1, 0xe, 0xa, 0x11, 0x3, 0x1, 0x8, 0x1, 0x3, 0x1, 0x17, 0x1, 0xa, 0x1, 0x5, 0x3, 0x8, 0x1, 0x3, 0x1, 0x4, 0x7, 0x2, 0x1, 0x2, 0x6, 0x4, 0x2, 0xa, 0x12, 0x2, 0x1, 0x8, 0x1, 0x3, 0x1, 0x17, 0x1, 0xa, 0x1, 0x5, 0x2, 0x9, 0x1, 0x3, 0x1, 0x4, 0x7, 0x2, 0x7, 0x1, 0x1, 0x4, 0x2, 0xa, 0x1, 0x2, 0xf, 0x2, 0x1, 0x8, 0x1, 0x3, 0x1, 0x29, 0x2, 0x8, 0x1, 0x3, 0x1, 0x5, 0x8, 0x1, 0x8, 0x4, 0x2, 0xa, 0xa, 0x6, 0x2, 0x2, 0x1, 0x12, 0x3, 0x18, 0x1, 0x9, 0x1, 0x1, 0x2, 0x7, 0x3, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x8, 0x12, 0x2, 0xd, 0x3a, 0x5, 0xf, 0x1, 0xa, 0x27, 0x2, 0x1, 0x1, 0x2, 0x2, 0x1, 0x1, 0x2, 0x1, 0x6, 0x4, 0x1, 0x7, 0x1, 0x3, 0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0x1, 0xd, 0x1, 0x3, 0x2, 0x5, 0x1, 0x1, 0x1, 0x6, 0x2, 0xa, 0x2, 0x4, 0x20, 0x1, 0x17, 0x2, 0x6, 0xa, 0xb, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0xa, 0x1, 0x24, 0x4, 0x14, 0x1, 0x12, 0x1, 0x24, 0x9, 0x1, 0x39, 0x4a, 0x6, 0x4e, 0x2, 0x26, 0x1, 0x1, 0x5, 0x1, 0x2, 0x2b, 0x1, 0x81, 0x4d, 0x1, 0x4, 0x2, 0x7, 0x1, 0x1, 0x1, 0x4, 0x2, 0x29, 0x1, 0x4, 0x2, 0x21, 0x1, 0x4, 0x2, 0x7, 0x1, 0x1, 0x1, 0x4, 0x2, 0xf, 0x1, 0x39, 0x1, 0x4, 0x2, 0x43, 0x2, 0x3, 0x9, 0x9, 0xe, 0x10, 0x10, 0x55, 0xc, 0x82, 0x6c, 0x2, 0x11, 0x1, 0x1a, 0x5, 0x4b, 0x3, 0x3, 0xf, 0xd, 0x1, 0x7, 0xb, 0x15, 0xb, 0x14, 0xc, 0xd, 0x1, 0x3, 0x1, 0x2, 0xc, 0x54, 0x3, 0x1, 0x4, 0x2, 0x2, 0xa, 0x21, 0x3, 0x2, 0xa, 0x6, 0x58, 0x8, 0x2b, 0x5, 0x46, 0xa, 0x1d, 0x3, 0xc, 0x4, 0xc, 0xa, 0x28, 0x2, 0x5, 0xb, 0x2c, 0x4, 0x1a, 0x6, 0xb, 0x25, 0x1c, 0x4, 0x3f, 0x1, 0x1d, 0x2, 0xb, 0x6, 0xa, 0xd, 0x1, 0x58, 0x4c, 0x4, 0xa, 0x11, 0x9, 0xc, 0x74, 0xc, 0x38, 0x8, 0xa, 0x3, 0x31, 0x52, 0x3, 0x1, 0x23, 0x9, 0x80, 0xe7, 0x15, 0x81, 0x1a, 0x2, 0x6, 0x2, 0x26, 0x2, 0x6, 0x2, 0x8, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1f, 0x2, 0x35, 0x1, 0x7, 0x1, 0x1, 0x3, 0x3, 0x1, 0x7, 0x3, 0x4, 0x2, 0x6, 0x4, 0xd, 0x5, 0x3, 0x1, 0x7, 0x42, 0x2, 0x13, 0x1, 0x1c, 0x1, 0xd, 0x1, 0x10, 0xd, 0x33, 0xd, 0x4, 0x1, 0x3, 0xc, 0x11, 0x1, 0x4, 0x1, 0x2, 0xa, 0x1, 0x1, 0x2, 0x6, 0x6, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x10, 0x2, 0x4, 0x5, 0x5, 0x4, 0x1, 0x11, 0x29, 0x8a, 0x77, 0x2f, 0x1, 0x2f, 0x1, 0x80, 0x85, 0x6, 0x9, 0xc, 0x26, 0x1, 0x1, 0x5, 0x1, 0x2, 0x38, 0x7, 0x1, 0xf, 0x18, 0x9, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x20, 0x82, 0x5, 0x3, 0x19, 0xf, 0x1, 0x5, 0x2, 0x5, 0x4, 0x56, 0x2, 0x2, 0x2, 0x3, 0x1, 0x5a, 0x1, 0x4, 0x5, 0x29, 0x3, 0x5e, 0x11, 0x1b, 0x35, 0x10, 0x82, 0x0, 0x99, 0xb6, 0x4a, 0xa0, 0x51, 0xcd, 0x33, 0x84, 0x8d, 0x43, 0x2e, 0x2, 0x81, 0xd, 0x3, 0x1c, 0x14, 0x30, 0x4, 0xa, 0x1, 0x19, 0x7, 0x53, 0x25, 0x9, 0x2, 0x67, 0x2, 0x4, 0x1, 0x4, 0xc, 0xb, 0x4d, 0x30, 0x18, 0x34, 0xc, 0x45, 0xb, 0xa, 0x6, 0x18, 0x3, 0x1, 0x4, 0x2e, 0x2, 0x24, 0xc, 0x1d, 0x3, 0x41, 0xe, 0xb, 0x26, 0x37, 0x9, 0xe, 0x2, 0xa, 0x6, 0x17, 0x3, 0x2, 0x4, 0x43, 0x18, 0x3, 0x2, 0x10, 0x2, 0x5, 0xa, 0x6, 0x2, 0x6, 0x2, 0x6, 0x9, 0x7, 0x1, 0x7, 0x80, 0x91, 0x2b, 0x1, 0x2, 0x2, 0xa, 0x6, 0xa0, 0x2b, 0xa4, 0xc, 0x17, 0x4, 0x31, 0xa0, 0x21, 0x4, 0x81, 0x6e, 0x2, 0x6a, 0x26, 0x7, 0xc, 0x5, 0x5, 0xc, 0x1, 0xd, 0x1, 0x5, 0x1, 0x1, 0x1, 0x2, 0x1, 0x2, 0x1, 0x6c, 0x21, 0x80, 0x8b, 0x6, 0x80, 0xda, 0x12, 0x40, 0x2, 0x36, 0x28, 0xa, 0x6, 0x10, 0x10, 0x7, 0xc, 0x2, 0x18, 0x3, 0x21, 0x1, 0x1, 0x1, 0x3, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x7e, 0x13, 0xa, 0x7, 0x1a, 0x4, 0x1, 0x1, 0x1a, 0xb, 0x59, 0x3, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x3, 0x23, 0xc, 0x1, 0x1a, 0x1, 0x13, 0x1, 0x2, 0x1, 0xf, 0x2, 0xe, 0x22, 0x7b, 0x45, 0x35, 0x80, 0x88, 0x1, 0x80, 0x82, 0x1d, 0x3, 0x31, 0x2f, 0x1f, 0x11, 0x1b, 0x35, 0x1e, 0x2, 0x24, 0x4, 0x8, 0x1, 0x5, 0x2a, 0x80, 0x9e, 0x2, 0xa, 0x83, 0x56, 0x6, 0x2, 0x1, 0x1, 0x2c, 0x1, 0x2, 0x3, 0x1, 0x2, 0x17, 0x80, 0xaa, 0x16, 0xa, 0x1a, 0x46, 0x38, 0x6, 0x2, 0x40, 0x4, 0x1, 0x2, 0x5, 0x8, 0x1, 0x3, 0x1, 0x1b, 0x4, 0x3, 0x4, 0x1, 0x20, 0x1d, 0x80, 0x83, 0x36, 0xa, 0x16, 0xa, 0x13, 0x80, 0x8d, 0x49, 0x83, 0xb7, 0x47, 0x1f, 0xa, 0x10, 0x3b, 0x15, 0x19, 0x7, 0xa, 0x6, 0x35, 0x1, 0xa, 0x40, 0x45, 0xb, 0xa, 0x84, 0xa6, 0x38, 0x8, 0xa, 0x89, 0x36, 0x83, 0x6f, 0x80, 0x91, 0x63, 0x8b, 0x9d, 0x84, 0x2f, 0xa0, 0x33, 0xd1, 0x82, 0x39, 0x84, 0xc7, 0x45, 0xb, 0x2f, 0x10, 0x11, 0xa0, 0x40, 0x60, 0x2, 0xa0, 0x21, 0x63, 0x5, 0x3, 0x6, 0x8, 0x8, 0x2, 0x7, 0x1e, 0x4, 0x80, 0x94, 0x3, 0x81, 0xbb, 0x55, 0x1, 0x47, 0x1, 0x2, 0x2, 0x1, 0x2, 0x2, 0x2, 0x4, 0x1, 0xc, 0x1, 0x1, 0x1, 0x7, 0x1, 0x41, 0x1, 0x4, 0x2, 0x8, 0x1, 0x7, 0x1, 0x1c, 0x1, 0x4, 0x1, 0x5, 0x1, 0x1, 0x3, 0x7, 0x1, 0x81, 0x54, 0x2, 0x19, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x8, 0x2, 0x32, 0x96, 0x0, 0x4, 0x1, 0x1b, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0xa, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x6, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x3, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x2, 0x4, 0x1, 0x7, 0x1, 0x4, 0x1, 0x4, 0x1, 0x1, 0x1, 0xa, 0x1, 0x11, 0x5, 0x3, 0x1, 0x5, 0x1, 0x11, 0x91, 0x44, 0xa0, 0xa6, 0xd7, 0x29, 0x90, 0x35, 0xb, 0x80, 0xde, 0xa0, 0x3f, 0xe2, 0x82, 0x1e, 0xab, 0x6, 0xe2, 0x80, 0xf0];
+_T Lowercase = [0x61, 0x1a, 0x2f, 0x1, 0xa, 0x1, 0x4, 0x1, 0x24, 0x18, 0x1, 0x8, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x3, 0x2, 0x1, 0x1, 0x1, 0x2, 0x1, 0x3, 0x2, 0x4, 0x1, 0x2, 0x1, 0x3, 0x3, 0x2, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x3, 0x1, 0x1, 0x1, 0x2, 0x2, 0x2, 0x3, 0x6, 0x1, 0x2, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0x1, 0x1, 0x1, 0x3, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x7, 0x2, 0x1, 0x2, 0x2, 0x1, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x45, 0x1, 0x24, 0x7, 0x2, 0x1e, 0x5, 0x60, 0x1, 0x2b, 0x1, 0x1, 0x1, 0x3, 0x1, 0x2, 0x4, 0x12, 0x1, 0x1b, 0x23, 0x1, 0x2, 0x3, 0x3, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x5, 0x1, 0x1, 0x2, 0x1, 0x2, 0x2, 0x33, 0x30, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x9, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x39, 0x27, 0x97, 0x78, 0x80, 0xc0, 0x41, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x9, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x9, 0x8, 0x6, 0xa, 0x8, 0x8, 0x8, 0x8, 0x6, 0xa, 0x8, 0x8, 0x8, 0x8, 0xe, 0x2, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x5, 0x1, 0x2, 0x6, 0x1, 0x3, 0x3, 0x1, 0x2, 0x8, 0x4, 0x2, 0x2, 0x8, 0x8, 0xa, 0x3, 0x1, 0x2, 0x79, 0x1, 0xd, 0x1, 0x10, 0xd, 0x6d, 0x1, 0x3, 0x2, 0x3, 0x1, 0x1b, 0x1, 0x4, 0x1, 0x4, 0x1, 0x2, 0x2, 0x8, 0x4, 0x4, 0x1, 0x21, 0x10, 0x4, 0x1, 0x83, 0x4b, 0x1a, 0x87, 0x46, 0x2f, 0x2, 0x1, 0x3, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x1, 0x1, 0x2, 0x1, 0x8, 0x3, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x7, 0x1, 0x1, 0x1, 0x4, 0x1, 0xc, 0x26, 0x1, 0x1, 0x5, 0x1, 0xa0, 0x79, 0x13, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x13, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x80, 0x8b, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x3, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0xa, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0xd, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4e, 0x3, 0xa0, 0x53, 0x5, 0x7, 0xc, 0x5, 0x84, 0x29, 0x1a, 0x84, 0xcd, 0x28, 0xa0, 0xcf, 0xca, 0x1a, 0x1a, 0x7, 0x1, 0x12, 0x1a, 0x1a, 0x1a, 0x4, 0x1, 0x1, 0x1, 0x7, 0x1, 0xb, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1c, 0x1c, 0x19, 0x1, 0x6, 0x1a, 0x19, 0x1, 0x6, 0x1a, 0x19, 0x1, 0x6, 0x1a, 0x19, 0x1, 0x6, 0x1a, 0x19, 0x1, 0x6, 0x1, 0x1];
+_T Zl = [0xa0, 0x20, 0x28, 0x1];
+_T Zp = [0xa0, 0x20, 0x29, 0x1];
+_T Radical = [0xa0, 0x2e, 0x80, 0x1a, 0x1, 0x59, 0xc, 0x80, 0xd6];
+_T Extender = [0x80, 0xb7, 0x1, 0x82, 0x18, 0x2, 0x83, 0x6e, 0x1, 0x81, 0xb9, 0x1, 0x86, 0x4b, 0x1, 0x7f, 0x1, 0x89, 0x43, 0x1, 0x38, 0x1, 0x82, 0x63, 0x1, 0x81, 0x8e, 0x1, 0x44, 0x1, 0x93, 0x89, 0x1, 0x2b, 0x5, 0x67, 0x2, 0x5d, 0x3, 0xa0, 0x6f, 0x16, 0x1, 0x85, 0xf6, 0x1, 0x83, 0xc2, 0x1, 0x80, 0xa0, 0x1, 0x6c, 0x1, 0x15, 0x2, 0xa0, 0x54, 0x7b, 0x1];
+_T Co = [0xa0, 0xe0, 0x0, 0x99, 0x0, 0xae, 0x7, 0x0, 0xa0, 0xff, 0xfe, 0x2, 0xa0, 0xff, 0xfe];
+_T Unified_Ideograph = [0xa0, 0x34, 0x0, 0x99, 0xb6, 0x4a, 0xa0, 0x51, 0xcd, 0xa0, 0x5a, 0x41, 0x2, 0x1, 0x1, 0x1, 0x2, 0xa, 0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0x3, 0xa1, 0x5, 0xd6, 0xa0, 0xa6, 0xd7, 0x29, 0x90, 0x35, 0xb, 0x80, 0xde];
+_T Pc = [0x5f, 0x1, 0x9f, 0xdf, 0x2, 0x13, 0x1, 0xa0, 0xdd, 0xde, 0x2, 0x18, 0x3, 0x80, 0xef, 0x1];
+_T Cs = [0xa0, 0xd8, 0x0, 0x88, 0x0];
+_T Noncharacter_Code_Point = [0xa0, 0xfd, 0xd0, 0x20, 0x82, 0xe, 0x2, 0xa0, 0xff, 0xfe, 0x2, 0xa0, 0xff, 0xfe, 0x2, 0xa0, 0xff, 0xfe, 0x2, 0xa0, 0xff, 0xfe, 0x2, 0xa0, 0xff, 0xfe, 0x2, 0xa0, 0xff, 0xfe, 0x2, 0xa0, 0xff, 0xfe, 0x2, 0xa0, 0xff, 0xfe, 0x2, 0xa0, 0xff, 0xfe, 0x2, 0xa0, 0xff, 0xfe, 0x2, 0xa0, 0xff, 0xfe, 0x2, 0xa0, 0xff, 0xfe, 0x2, 0xa0, 0xff, 0xfe, 0x2, 0xa0, 0xff, 0xfe, 0x2, 0xa0, 0xff, 0xfe, 0x2, 0xa0, 0xff, 0xfe];
+_T Uppercase = [0x41, 0x1a, 0x65, 0x17, 0x1, 0x7, 0x21, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x3, 0x2, 0x1, 0x1, 0x1, 0x2, 0x1, 0x3, 0x2, 0x4, 0x1, 0x2, 0x1, 0x3, 0x3, 0x2, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x3, 0x1, 0x1, 0x1, 0x2, 0x3, 0x1, 0x7, 0x1, 0x2, 0x1, 0x2, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x2, 0x1, 0x1, 0x3, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x7, 0x2, 0x1, 0x2, 0x2, 0x1, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x81, 0x21, 0x1, 0x1, 0x1, 0x3, 0x1, 0xf, 0x1, 0x1, 0x3, 0x1, 0x1, 0x1, 0x2, 0x1, 0x11, 0x1, 0x9, 0x23, 0x1, 0x2, 0x3, 0x3, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x5, 0x1, 0x2, 0x1, 0x1, 0x2, 0x2, 0x33, 0x30, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x9, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0xa, 0x26, 0x8b, 0x49, 0x26, 0x1, 0x1, 0x5, 0x1, 0x8d, 0x32, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x9, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x9, 0x8, 0x8, 0x6, 0xa, 0x8, 0x8, 0x8, 0x8, 0x6, 0xb, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x8, 0x8, 0x48, 0x4, 0xc, 0x4, 0xc, 0x4, 0xc, 0x5, 0xb, 0x4, 0x81, 0x6, 0x1, 0x4, 0x1, 0x3, 0x3, 0x2, 0x3, 0x2, 0x1, 0x3, 0x5, 0x6, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x2, 0x4, 0xa, 0x2, 0x5, 0x1, 0x1a, 0x10, 0x13, 0x1, 0x83, 0x32, 0x1a, 0x87, 0x30, 0x2f, 0x31, 0x1, 0x1, 0x3, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x1, 0x1, 0x2, 0x1, 0x8, 0x3, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x8, 0x1, 0x1, 0x1, 0x4, 0x1, 0xa0, 0x79, 0x4d, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x13, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x80, 0x8b, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x3, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0xa, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x4, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0xd, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0xa0, 0x57, 0x76, 0x1a, 0x84, 0xc5, 0x28, 0xa0, 0xcf, 0xd8, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1, 0x1, 0x2, 0x2, 0x1, 0x2, 0x2, 0x2, 0x4, 0x1, 0x8, 0x1a, 0x1a, 0x1a, 0x2, 0x1, 0x4, 0x2, 0x8, 0x1, 0x7, 0x1b, 0x2, 0x1, 0x4, 0x1, 0x5, 0x1, 0x1, 0x3, 0x7, 0x1b, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1e, 0x19, 0x21, 0x19, 0x21, 0x19, 0x21, 0x19, 0x21, 0x19, 0x21, 0x1];
+_T IDS_Trinary_Operator = [0xa0, 0x2f, 0xf2, 0x2];
+_T Logical_Order_Exception = [0x8e, 0x40, 0x5, 0x7b, 0x5, 0xa0, 0x9b, 0xf0, 0x2, 0x2, 0x1, 0x1, 0x2];
+_T Pi = [0x80, 0xab, 0x1, 0x9f, 0x6c, 0x1, 0x2, 0x2, 0x2, 0x1, 0x19, 0x1, 0x8d, 0xc8, 0x1, 0x1, 0x1, 0x4, 0x1, 0x2, 0x1, 0xf, 0x1, 0x3, 0x1];
+_T Soft_Dotted = [0x69, 0x2, 0x80, 0xc4, 0x1, 0x81, 0x19, 0x1, 0x1e, 0x1, 0x34, 0x1, 0x14, 0x1, 0x81, 0x40, 0x1, 0x62, 0x1, 0x1, 0x1, 0x99, 0x9, 0x1, 0x33, 0x1, 0xd, 0x1, 0x3, 0x1, 0x80, 0x84, 0x1, 0x80, 0x9d, 0x1, 0x81, 0xa5, 0x1, 0x80, 0xd6, 0x2, 0x8b, 0x32, 0x1, 0xa1, 0xa7, 0xa5, 0x2, 0x32, 0x2, 0x32, 0x2, 0x32, 0x2, 0x32, 0x2, 0x32, 0x2, 0x32, 0x2, 0x32, 0x2, 0x32, 0x2, 0x32, 0x2, 0x32, 0x2, 0x32, 0x2, 0x32, 0x2];
+_T Po = [0x21, 0x3, 0x1, 0x3, 0x2, 0x1, 0x1, 0x1, 0x1, 0x2, 0xa, 0x2, 0x3, 0x2, 0x1b, 0x1, 0x44, 0x1, 0x5, 0x1, 0xe, 0x2, 0x7, 0x1, 0x82, 0xbe, 0x1, 0x8, 0x1, 0x81, 0xd2, 0x6, 0x29, 0x1, 0x36, 0x1, 0x2, 0x1, 0x2, 0x1, 0x2c, 0x2, 0x14, 0x2, 0x1, 0x2, 0xd, 0x1, 0x2, 0x2, 0x4a, 0x4, 0x66, 0x1, 0x2b, 0xe, 0x80, 0xe9, 0x3, 0x36, 0xf, 0x1f, 0x1, 0x81, 0x5, 0x2, 0xa, 0x1, 0x81, 0x7f, 0x1, 0x83, 0x3, 0x1, 0x5a, 0x1, 0xa, 0x2, 0x80, 0xa8, 0xf, 0x1, 0x1, 0x70, 0x1, 0x4a, 0x5, 0x4, 0x2, 0x6f, 0x6, 0x80, 0xab, 0x1, 0x82, 0x64, 0x9, 0x83, 0x4, 0x2, 0x7c, 0x3, 0x47, 0x2, 0x80, 0x9d, 0x3, 0x1, 0x3, 0x25, 0x6, 0x1, 0x4, 0x81, 0x39, 0x2, 0x80, 0xd8, 0x2, 0x80, 0x80, 0x7, 0x1, 0x6, 0x80, 0xac, 0x7, 0x80, 0x9b, 0x4, 0x3b, 0x5, 0x3e, 0x2, 0x40, 0x8, 0xb, 0x1, 0x83, 0x42, 0x2, 0x8, 0x8, 0x8, 0x9, 0x2, 0x4, 0x2, 0x3, 0x3, 0xb, 0x1, 0x1, 0x1, 0xa, 0x8c, 0x9a, 0x4, 0x1, 0x2, 0x70, 0x1, 0x80, 0x8f, 0x2, 0x4, 0x3, 0x2, 0x1, 0x2, 0x9, 0x1, 0x2, 0x1, 0x1, 0x2, 0x2, 0xa, 0x5, 0x1, 0xa, 0x81, 0xc7, 0x3, 0x39, 0x1, 0x80, 0xbd, 0x1, 0xa0, 0x74, 0x2, 0x2, 0x81, 0xd, 0x3, 0x63, 0x1, 0xa, 0x1, 0x73, 0x6, 0x81, 0x7c, 0x4, 0x56, 0x2, 0x28, 0x3, 0x33, 0x2, 0x2f, 0x1, 0x61, 0xd, 0x10, 0x2, 0x7c, 0x4, 0x7e, 0x2, 0x10, 0x2, 0x80, 0xf9, 0x1, 0xa0, 0x52, 0x24, 0x7, 0x2, 0x1, 0x16, 0x1, 0x14, 0x2, 0x2, 0x4, 0x3, 0x3, 0x1, 0x4, 0x7, 0x3, 0x6, 0x1, 0x1, 0x2, 0x80, 0x95, 0x3, 0x1, 0x3, 0x2, 0x1, 0x1, 0x1, 0x1, 0x2, 0xa, 0x2, 0x3, 0x2, 0x1b, 0x1, 0x24, 0x1, 0x2, 0x2, 0x81, 0x9a, 0x3, 0x82, 0x9c, 0x1, 0x30, 0x1, 0x84, 0x86, 0x1, 0x80, 0xc7, 0x1, 0x1f, 0x1, 0x81, 0x10, 0x9, 0x26, 0x1, 0x80, 0xb9, 0x7, 0x85, 0x7, 0x7, 0x6d, 0x2, 0x1, 0x4, 0x7e, 0x4, 0x80, 0x81, 0x4, 0x92, 0xa7, 0x4];
+_T Cn = [0x83, 0x78, 0x2, 0x5, 0x5, 0x7, 0x1, 0x1, 0x1, 0x14, 0x1, 0x81, 0x85, 0x9, 0x26, 0x2, 0x7, 0x1, 0x27, 0x1, 0x2, 0x4, 0x1, 0x1, 0x37, 0x8, 0x1b, 0x5, 0x5, 0xb, 0x5, 0x1, 0x17, 0x1, 0x80, 0xf0, 0x1, 0x3c, 0x2, 0x65, 0xe, 0x3b, 0x5, 0x2e, 0x2, 0xf, 0x1, 0x1c, 0x2, 0x1, 0x41, 0x1, 0x1, 0xb, 0x37, 0x1b, 0x1, 0x78, 0x1, 0x7, 0x1, 0x3, 0x1, 0x8, 0x2, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x1, 0x3, 0x4, 0x2, 0x9, 0x2, 0x2, 0x2, 0x4, 0x8, 0x1, 0x4, 0x2, 0x1, 0x5, 0x2, 0x16, 0x5, 0x3, 0x1, 0x6, 0x4, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x2, 0x1, 0x2, 0x2, 0x1, 0x1, 0x5, 0x4, 0x2, 0x2, 0x3, 0x3, 0x1, 0x7, 0x4, 0x1, 0x1, 0x7, 0x10, 0xb, 0x3, 0x1, 0x9, 0x1, 0x3, 0x1, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x5, 0x2, 0xa, 0x1, 0x3, 0x1, 0x3, 0x2, 0x1, 0xf, 0x4, 0x2, 0xc, 0xf, 0x3, 0x1, 0x8, 0x2, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x5, 0x2, 0x9, 0x2, 0x2, 0x2, 0x3, 0x8, 0x2, 0x4, 0x2, 0x1, 0x5, 0x2, 0x12, 0xa, 0x2, 0x1, 0x6, 0x3, 0x3, 0x1, 0x4, 0x3, 0x2, 0x1, 0x1, 0x1, 0x2, 0x3, 0x2, 0x3, 0x3, 0x3, 0xc, 0x4, 0x5, 0x3, 0x3, 0x1, 0x4, 0x2, 0x1, 0x6, 0x1, 0xe, 0x15, 0x6, 0x3, 0x1, 0x8, 0x1, 0x3, 0x1, 0x17, 0x1, 0xa, 0x1, 0x5, 0x3, 0x8, 0x1, 0x3, 0x1, 0x4, 0x7, 0x2, 0x1, 0x2, 0x6, 0x4, 0x2, 0xa, 0x8, 0x8, 0x2, 0x2, 0x1, 0x8, 0x1, 0x3, 0x1, 0x17, 0x1, 0xa, 0x1, 0x5, 0x2, 0x9, 0x1, 0x3, 0x1, 0x4, 0x7, 0x2, 0x7, 0x1, 0x1, 0x4, 0x2, 0xa, 0x1, 0x2, 0xf, 0x2, 0x1, 0x8, 0x1, 0x3, 0x1, 0x29, 0x2, 0x8, 0x1, 0x3, 0x1, 0x5, 0x8, 0x1, 0x8, 0x4, 0x2, 0x10, 0x3, 0x7, 0x2, 0x2, 0x1, 0x12, 0x3, 0x18, 0x1, 0x9, 0x1, 0x1, 0x2, 0x7, 0x3, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x8, 0x12, 0x3, 0xc, 0x3a, 0x4, 0x1d, 0x25, 0x2, 0x1, 0x1, 0x2, 0x2, 0x1, 0x1, 0x2, 0x1, 0x6, 0x4, 0x1, 0x7, 0x1, 0x3, 0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0x1, 0xd, 0x1, 0x3, 0x2, 0x5, 0x1, 0x1, 0x1, 0x6, 0x2, 0xa, 0x2, 0x4, 0x20, 0x48, 0x1, 0x24, 0x4, 0x27, 0x1, 0x24, 0x1, 0xf, 0x1, 0xd, 0x25, 0x80, 0xc6, 0x1, 0x1, 0x5, 0x1, 0x2, 0x81, 0x79, 0x1, 0x4, 0x2, 0x7, 0x1, 0x1, 0x1, 0x4, 0x2, 0x29, 0x1, 0x4, 0x2, 0x21, 0x1, 0x4, 0x2, 0x7, 0x1, 0x1, 0x1, 0x4, 0x2, 0xf, 0x1, 0x39, 0x1, 0x4, 0x2, 0x43, 0x2, 0x20, 0x3, 0x1a, 0x6, 0x55, 0xb, 0x82, 0x9d, 0x3, 0x51, 0xf, 0xd, 0x1, 0x7, 0xb, 0x17, 0x9, 0x14, 0xc, 0xd, 0x1, 0x3, 0x1, 0x2, 0xc, 0x5e, 0x2, 0xa, 0x6, 0xa, 0x6, 0xf, 0x1, 0xa, 0x6, 0x58, 0x8, 0x2b, 0x5, 0x46, 0xa, 0x1d, 0x3, 0xc, 0x4, 0xc, 0x4, 0x1, 0x3, 0x2a, 0x2, 0x5, 0xb, 0x2c, 0x4, 0x1a, 0x6, 0xb, 0x3, 0x3e, 0x2, 0x41, 0x1, 0x1d, 0x2, 0xb, 0x6, 0xa, 0x6, 0xe, 0x52, 0x4c, 0x4, 0x2d, 0x3, 0x74, 0x8, 0x3c, 0x3, 0xf, 0x3, 0x33, 0x40, 0x8, 0x8, 0x27, 0x9, 0x80, 0xe7, 0x15, 0x81, 0x1a, 0x2, 0x6, 0x2, 0x26, 0x2, 0x6, 0x2, 0x8, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1f, 0x2, 0x35, 0x1, 0xf, 0x1, 0xe, 0x2, 0x6, 0x1, 0x13, 0x2, 0x3, 0x1, 0x9, 0x1, 0x65, 0x1, 0xc, 0x2, 0x1b, 0x1, 0xd, 0x3, 0x1b, 0x15, 0x21, 0xf, 0x80, 0x8a, 0x6, 0x82, 0x64, 0xc, 0x27, 0x19, 0xb, 0x15, 0x82, 0xa0, 0x1, 0x84, 0x4c, 0x3, 0xa, 0x80, 0xa6, 0x2f, 0x1, 0x2f, 0x1, 0x80, 0x94, 0x5, 0x2d, 0x1, 0x1, 0x5, 0x1, 0x2, 0x38, 0x7, 0x2, 0xe, 0x18, 0x9, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x5c, 0x44, 0x1a, 0x1, 0x59, 0xc, 0x80, 0xd6, 0x1a, 0xc, 0x4, 0x40, 0x1, 0x56, 0x2, 0x67, 0x5, 0x29, 0x3, 0x5e, 0x1, 0x2b, 0x5, 0x24, 0xc, 0x2f, 0x1, 0x80, 0xdf, 0x1, 0x9a, 0xb6, 0xa, 0xa0, 0x52, 0xd, 0x33, 0x84, 0x8d, 0x3, 0x37, 0x9, 0x81, 0x5c, 0x14, 0x58, 0x7, 0x59, 0x8, 0x80, 0x8f, 0x1, 0x4, 0xc, 0xb, 0x4d, 0x34, 0x4, 0xa, 0x6, 0x38, 0x8, 0x45, 0x9, 0xc, 0x6, 0x1c, 0x4, 0x54, 0xb, 0x1e, 0x3, 0x4e, 0x1, 0xb, 0x4, 0x2, 0x20, 0x37, 0x9, 0xe, 0x2, 0xa, 0x2, 0x20, 0x4, 0x43, 0x18, 0x1c, 0xa, 0x6, 0x2, 0x6, 0x2, 0x6, 0x9, 0x7, 0x1, 0x7, 0x80, 0x91, 0x2e, 0x2, 0xa, 0x6, 0xa0, 0x2b, 0xa4, 0xc, 0x17, 0x4, 0x31, 0x4, 0xa0, 0x22, 0x6e, 0x2, 0x6a, 0x26, 0x7, 0xc, 0x5, 0x5, 0x1a, 0x1, 0x5, 0x1, 0x1, 0x1, 0x2, 0x1, 0x2, 0x1, 0x7c, 0x11, 0x81, 0x6d, 0x10, 0x40, 0x2, 0x36, 0x28, 0xe, 0x2, 0x1a, 0x6, 0x7, 0x9, 0x23, 0x1, 0x13, 0x1, 0x4, 0x4, 0x5, 0x1, 0x80, 0x87, 0x2, 0x1, 0x1, 0x80, 0xbe, 0x3, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x3, 0x3, 0x7, 0x1, 0x7, 0xa, 0x5, 0x2, 0xc, 0x1, 0x1a, 0x1, 0x13, 0x1, 0x2, 0x1, 0xf, 0x2, 0xe, 0x22, 0x7b, 0x5, 0x3, 0x4, 0x2d, 0x3, 0x54, 0x5, 0xc, 0x34, 0x2e, 0x80, 0x82, 0x1d, 0x3, 0x31, 0x2f, 0x1f, 0x1, 0x4, 0xc, 0x1b, 0x35, 0x1e, 0x1, 0x25, 0x4, 0xe, 0x2a, 0x80, 0x9e, 0x2, 0xa, 0x83, 0x56, 0x6, 0x2, 0x1, 0x1, 0x2c, 0x1, 0x2, 0x3, 0x1, 0x2, 0x17, 0x1, 0x9, 0x80, 0xa0, 0x1c, 0x3, 0x1b, 0x5, 0x1, 0x40, 0x38, 0x6, 0x2, 0x40, 0x4, 0x1, 0x2, 0x5, 0x8, 0x1, 0x3, 0x1, 0x1b, 0x4, 0x3, 0x4, 0x9, 0x8, 0x9, 0x7, 0x20, 0x80, 0x80, 0x36, 0x3, 0x1d, 0x2, 0x1b, 0x5, 0x8, 0x80, 0x80, 0x49, 0x82, 0x17, 0x1f, 0x81, 0x81, 0x4e, 0x4, 0x1e, 0x10, 0x42, 0xe, 0x19, 0x7, 0xa, 0x6, 0x35, 0x1, 0xe, 0x3c, 0x49, 0x7, 0xa, 0x84, 0xa6, 0x38, 0x8, 0xa, 0x89, 0x36, 0x83, 0x6f, 0x80, 0x91, 0x63, 0xd, 0x4, 0x8b, 0x8c, 0x84, 0x2f, 0xa0, 0x33, 0xd1, 0x82, 0x39, 0x84, 0xc7, 0x45, 0xb, 0x2f, 0x10, 0x11, 0xa0, 0x40, 0x60, 0x2, 0x9f, 0xfe, 0x80, 0xf6, 0xa, 0x27, 0x2, 0x80, 0xb5, 0x22, 0x46, 0x80, 0xba, 0x57, 0x9, 0x12, 0x80, 0x8e, 0x55, 0x1, 0x47, 0x1, 0x2, 0x2, 0x1, 0x2, 0x2, 0x2, 0x4, 0x1, 0xc, 0x1, 0x1, 0x1, 0x7, 0x1, 0x41, 0x1, 0x4, 0x2, 0x8, 0x1, 0x7, 0x1, 0x1c, 0x1, 0x4, 0x1, 0x5, 0x1, 0x1, 0x3, 0x7, 0x1, 0x81, 0x54, 0x2, 0x81, 0x24, 0x2, 0x32, 0x96, 0x0, 0x4, 0x1, 0x1b, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0xa, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x6, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x3, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x2, 0x4, 0x1, 0x7, 0x1, 0x4, 0x1, 0x4, 0x1, 0x1, 0x1, 0xa, 0x1, 0x11, 0x5, 0x3, 0x1, 0x5, 0x1, 0x11, 0x34, 0x2, 0x81, 0xe, 0x2c, 0x4, 0x64, 0xc, 0xf, 0x2, 0xe, 0x2, 0xf, 0x1, 0xf, 0x20, 0xb, 0x5, 0x1f, 0x1, 0x3c, 0x4, 0x2b, 0x4b, 0x1d, 0xd, 0x2b, 0x5, 0x9, 0x7, 0x2, 0x80, 0xae, 0x21, 0xf, 0x6, 0x1, 0x46, 0x3, 0x14, 0xc, 0x25, 0x1, 0x5, 0x15, 0x11, 0xf, 0x3f, 0x1, 0x1, 0x1, 0x80, 0xb6, 0x1, 0x4, 0x3, 0x3e, 0x2, 0x4, 0xc, 0x18, 0x80, 0x93, 0x46, 0x4, 0xb, 0x30, 0x46, 0x3a, 0x74, 0x88, 0x8c, 0xa0, 0xa6, 0xd7, 0x29, 0x90, 0x35, 0xb, 0x80, 0xde, 0xa0, 0x3f, 0xe2, 0x82, 0x1e, 0xab, 0x5, 0xe3, 0x1, 0x1e, 0x60, 0x80, 0x80, 0x80, 0xf0, 0xa0, 0xfe, 0x10, 0xa0, 0xff, 0xfe, 0x2, 0xa0, 0xff, 0xfe];
+_T Ps = [0x28, 0x1, 0x32, 0x1, 0x1f, 0x1, 0x8e, 0xbe, 0x1, 0x1, 0x1, 0x87, 0x5e, 0x1, 0x89, 0x7e, 0x1, 0x3, 0x1, 0x26, 0x1, 0x37, 0x1, 0xf, 0x1, 0x82, 0x7a, 0x1, 0x1, 0x1, 0x1e, 0x1, 0x84, 0x3e, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x50, 0x1, 0x20, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x81, 0x94, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x40, 0x1, 0x1, 0x1, 0x21, 0x1, 0x84, 0x25, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x81, 0xdf, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x3, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0xa0, 0xcd, 0x20, 0x1, 0x80, 0xd8, 0x1, 0x1d, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x3, 0x1, 0x11, 0x1, 0x1, 0x1, 0x1, 0x1, 0x80, 0xaa, 0x1, 0x32, 0x1, 0x1f, 0x1, 0x3, 0x1, 0x2, 0x1];
+_T ASCII_Hex_Digit = [0x30, 0xa, 0x7, 0x6, 0x1a, 0x6];
+_T No = [0x80, 0xb2, 0x2, 0x5, 0x1, 0x2, 0x3, 0x89, 0x35, 0x6, 0x81, 0x78, 0x6, 0x78, 0x3, 0x80, 0x85, 0x7, 0x80, 0xf1, 0x6, 0x81, 0xb4, 0xa, 0x84, 0x35, 0x14, 0x84, 0x73, 0xa, 0x81, 0xe0, 0x1, 0x86, 0x95, 0x1, 0x3, 0x6, 0x6, 0xa, 0x80, 0xc6, 0x10, 0x29, 0x1, 0x82, 0xd6, 0x3c, 0x4e, 0x16, 0x82, 0x76, 0x1e, 0x85, 0x69, 0x1, 0x84, 0x94, 0x4, 0x80, 0x8a, 0xa, 0x1e, 0x8, 0x1, 0xf, 0x20, 0xa, 0x27, 0xf, 0xa0, 0x75, 0x70, 0x6, 0xa0, 0x58, 0xd1, 0x2d, 0x41, 0x4, 0x11, 0x1, 0x81, 0x95, 0x4, 0x85, 0x34, 0x8, 0x80, 0xb6, 0x6, 0x81, 0x24, 0x8, 0x35, 0x2, 0x80, 0xd9, 0x8, 0x18, 0x8, 0x82, 0xe0, 0x1f, 0x81, 0xd3, 0x14, 0xa0, 0xc2, 0xfa, 0x12, 0x9d, 0x8e, 0xb];
+_T Sm = [0x2b, 0x1, 0x10, 0x3, 0x3d, 0x1, 0x1, 0x1, 0x2d, 0x1, 0x4, 0x1, 0x25, 0x1, 0x1f, 0x1, 0x82, 0xfe, 0x1, 0x82, 0xf, 0x3, 0x9a, 0x3b, 0x1, 0xd, 0x1, 0x27, 0x3, 0xd, 0x3, 0x80, 0x8b, 0x1, 0x27, 0x5, 0x6, 0x1, 0x44, 0x5, 0x5, 0x2, 0x4, 0x1, 0x2, 0x1, 0x2, 0x1, 0x7, 0x1, 0x1f, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1f, 0x81, 0xc, 0x20, 0x2, 0x5a, 0x1, 0x1e, 0x19, 0x28, 0x6, 0x81, 0xd5, 0x1, 0x9, 0x1, 0x36, 0x8, 0x6f, 0x1, 0x81, 0x50, 0x5, 0x2, 0x1f, 0xa, 0x10, 0x81, 0x0, 0x80, 0x83, 0x16, 0x3f, 0x4, 0x20, 0x2, 0x81, 0x2, 0x30, 0x15, 0x2, 0x6, 0xa0, 0xcf, 0xdc, 0x1, 0x83, 0x38, 0x1, 0x1, 0x3, 0x80, 0xa4, 0x1, 0x10, 0x3, 0x3d, 0x1, 0x1, 0x1, 0x80, 0x83, 0x1, 0x6, 0x4, 0xa0, 0xd6, 0xd4, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x97, 0x2c, 0x2];
+_T Other_Math = [0x5e, 0x1, 0x83, 0x71, 0x3, 0x2, 0x1, 0x1a, 0x2, 0x2, 0x2, 0x9c, 0x20, 0x1, 0x1b, 0x3, 0xb, 0x1, 0x20, 0x4, 0x18, 0x2, 0xe, 0x2, 0x41, 0xd, 0x4, 0x1, 0x3, 0x2, 0x4, 0x5, 0x12, 0x1, 0x4, 0x1, 0x2, 0xa, 0x1, 0x1, 0x3, 0x5, 0x6, 0x1, 0x3, 0x2, 0x2, 0x2, 0x1, 0x3, 0x1, 0x6, 0x3, 0x4, 0x5, 0x5, 0x4b, 0x5, 0x2, 0x4, 0x1, 0x2, 0x1, 0x2, 0x1, 0x1, 0x1, 0x5, 0x2, 0x2, 0x4, 0x2, 0x4, 0x12, 0x2, 0x2, 0x1, 0x1, 0x1, 0x7, 0x1, 0x1, 0x6, 0x2, 0x81, 0x22, 0x4, 0x80, 0xa8, 0x2, 0x1, 0x1, 0x18, 0x1, 0x11, 0x1, 0x81, 0xbd, 0x2, 0xc, 0x9, 0x5, 0x5, 0x5, 0x2, 0x2, 0x2, 0x3, 0x5, 0xe, 0x1, 0x1, 0x1, 0x2, 0x6, 0x18, 0x2, 0x39, 0x1, 0x1, 0x1, 0x1d, 0x4, 0x9, 0x2, 0x81, 0x56, 0x2, 0x1f, 0xa, 0x81, 0x93, 0x16, 0x3f, 0x4, 0x20, 0x2, 0xa0, 0xd4, 0x63, 0x1, 0x1, 0x1, 0x4, 0x1, 0x80, 0xd3, 0x1, 0x1, 0x1, 0xa0, 0xd4, 0xc1, 0x55, 0x1, 0x47, 0x1, 0x2, 0x2, 0x1, 0x2, 0x2, 0x2, 0x4, 0x1, 0xc, 0x1, 0x1, 0x1, 0x7, 0x1, 0x41, 0x1, 0x4, 0x2, 0x8, 0x1, 0x7, 0x1, 0x1c, 0x1, 0x4, 0x1, 0x5, 0x1, 0x1, 0x3, 0x7, 0x1, 0x81, 0x54, 0x2, 0x19, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x1f, 0x1, 0x19, 0x1, 0x8, 0x2, 0x32, 0x96, 0x0, 0x4, 0x1, 0x1b, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0xa, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x6, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x3, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x2, 0x4, 0x1, 0x7, 0x1, 0x4, 0x1, 0x4, 0x1, 0x1, 0x1, 0xa, 0x1, 0x11, 0x5, 0x3, 0x1, 0x5, 0x1, 0x11];
+_T Join_Control = [0xa0, 0x20, 0xc, 0x2];
+_T Cf = [0x80, 0xad, 0x1, 0x85, 0x52, 0x5, 0x17, 0x1, 0x80, 0xc0, 0x1, 0x31, 0x1, 0x90, 0xfe, 0x1, 0x87, 0xfc, 0x5, 0x1a, 0x5, 0x31, 0x5, 0x1, 0xa, 0xa0, 0xde, 0x8f, 0x1, 0x80, 0xf9, 0x3, 0x90, 0xc1, 0x1, 0xa0, 0xc0, 0xb5, 0x8, 0xac, 0x2e, 0x86, 0x1, 0x1e, 0x60];
+_T Ideographic = [0xa0, 0x30, 0x6, 0x2, 0x19, 0x9, 0xe, 0x3, 0x83, 0xc5, 0x99, 0xb6, 0x4a, 0xa0, 0x51, 0xcd, 0xa0, 0x59, 0x33, 0x81, 0x6e, 0x2, 0x6a, 0xa1, 0x5, 0x26, 0xa0, 0xa6, 0xd7, 0x29, 0x90, 0x35, 0xb, 0x80, 0xde, 0xa0, 0x3f, 0xe2, 0x82, 0x1e];
+_T Sc = [0x24, 0x1, 0x7d, 0x4, 0x84, 0xe9, 0x1, 0x7b, 0x1, 0x83, 0xe6, 0x2, 0x7, 0x1, 0x80, 0xf5, 0x1, 0x81, 0x7, 0x1, 0x82, 0x45, 0x1, 0x89, 0x9b, 0x1, 0x88, 0xc4, 0x1b, 0xa0, 0x87, 0x7d, 0x1, 0xa0, 0x55, 0xc3, 0x1, 0x6c, 0x1, 0x80, 0x9a, 0x1, 0x80, 0xdb, 0x2, 0x3, 0x2];
+_T Nd = [0x30, 0xa, 0x86, 0x26, 0xa, 0x80, 0x86, 0xa, 0x80, 0xc6, 0xa, 0x81, 0x9c, 0xa, 0x76, 0xa, 0x76, 0xa, 0x76, 0xa, 0x76, 0xa, 0x76, 0xa, 0x76, 0xa, 0x76, 0xa, 0x76, 0xa, 0x80, 0xe0, 0xa, 0x76, 0xa, 0x46, 0xa, 0x81, 0x16, 0xa, 0x46, 0xa, 0x87, 0x46, 0xa, 0x26, 0xa, 0x81, 0x2c, 0xa, 0x80, 0x80, 0xa, 0x80, 0xa6, 0xa, 0x6, 0xa, 0x80, 0xb6, 0xa, 0x56, 0xa, 0x80, 0x86, 0xa, 0x6, 0xa, 0xa0, 0x89, 0xc6, 0xa, 0x82, 0xa6, 0xa, 0x26, 0xa, 0x80, 0xc6, 0xa, 0x76, 0xa, 0x81, 0x96, 0xa, 0xa0, 0x53, 0x16, 0xa, 0x85, 0x86, 0xa, 0x8b, 0xbc, 0xa, 0x80, 0x80, 0xa, 0x3c, 0xa, 0x80, 0x90, 0xa, 0x84, 0xe6, 0xa, 0xa0, 0xc1, 0x4, 0x32];
+_T Default_Ignorable_Code_Point = [0x80, 0xad, 0x1, 0x82, 0xa1, 0x1, 0x82, 0xcc, 0x1, 0x8b, 0x42, 0x2, 0x86, 0x53, 0x2, 0x55, 0x4, 0x87, 0xfc, 0x5, 0x1a, 0x5, 0x31, 0x10, 0x90, 0xf4, 0x1, 0xa0, 0xcc, 0x9b, 0x10, 0x80, 0xef, 0x1, 0x80, 0xa0, 0x1, 0x4f, 0x9, 0xa0, 0xd1, 0x7a, 0x8, 0xac, 0x2e, 0x85, 0x90, 0x0];
+_T Other_ID_Continue = [0x80, 0xb7, 0x1, 0x82, 0xcf, 0x1, 0x8f, 0xe1, 0x9, 0x86, 0x68, 0x1];
+_T Pd = [0x2d, 0x1, 0x85, 0x5c, 0x1, 0x33, 0x1, 0x8e, 0x41, 0x1, 0x84, 0x5, 0x1, 0x88, 0x9, 0x6, 0x8e, 0x1, 0x1, 0x2, 0x1, 0x1f, 0x2, 0x81, 0xe0, 0x1, 0x13, 0x1, 0x6f, 0x1, 0xa0, 0xcd, 0x90, 0x2, 0x25, 0x1, 0xa, 0x1, 0x80, 0xa9, 0x1];
+_T Deprecated = [0x81, 0x49, 0x1, 0x85, 0x29, 0x1, 0x89, 0x3, 0x1, 0x1, 0x1, 0x88, 0x29, 0x2, 0x88, 0xc5, 0x6, 0x82, 0xb9, 0x2, 0xad, 0xdc, 0xd6, 0x1, 0x1e, 0x60];
+_T Grapheme_Extend = [0x83, 0x0, 0x70, 0x81, 0x13, 0x7, 0x81, 0x7, 0x2d, 0x1, 0x1, 0x1, 0x2, 0x1, 0x2, 0x1, 0x1, 0x48, 0xb, 0x30, 0x15, 0x10, 0x1, 0x65, 0x7, 0x2, 0x6, 0x2, 0x2, 0x1, 0x4, 0x23, 0x1, 0x1e, 0x1b, 0x5b, 0xb, 0x3a, 0x9, 0x22, 0x4, 0x1, 0x9, 0x1, 0x3, 0x1, 0x5, 0x2b, 0x3, 0x80, 0x88, 0x1b, 0x1, 0x3, 0x37, 0x1, 0x1, 0x1, 0x4, 0x8, 0x4, 0x1, 0x3, 0x7, 0xa, 0x2, 0x1d, 0x1, 0x3a, 0x1, 0x1, 0x1, 0x2, 0x4, 0x8, 0x1, 0x9, 0x1, 0xa, 0x2, 0x1d, 0x2, 0x39, 0x1, 0x4, 0x2, 0x4, 0x2, 0x2, 0x3, 0x3, 0x1, 0x1e, 0x2, 0x3, 0x1, 0xb, 0x2, 0x39, 0x1, 0x4, 0x5, 0x1, 0x2, 0x4, 0x1, 0x14, 0x2, 0x1d, 0x1, 0x3a, 0x1, 0x1, 0x2, 0x1, 0x4, 0x8, 0x1, 0x8, 0x2, 0xa, 0x2, 0x1e, 0x1, 0x3b, 0x1, 0x1, 0x1, 0xc, 0x1, 0x9, 0x1, 0x66, 0x3, 0x5, 0x3, 0x1, 0x4, 0x7, 0x2, 0xb, 0x2, 0x58, 0x1, 0x2, 0x1, 0x2, 0x1, 0x3, 0x1, 0x5, 0x2, 0x7, 0x2, 0xb, 0x2, 0x5a, 0x1, 0x2, 0x4, 0x8, 0x1, 0x9, 0x1, 0xa, 0x2, 0x66, 0x1, 0x4, 0x1, 0x2, 0x3, 0x1, 0x1, 0x8, 0x1, 0x51, 0x1, 0x2, 0x7, 0xc, 0x8, 0x62, 0x1, 0x2, 0x6, 0x1, 0x2, 0xb, 0x6, 0x4a, 0x2, 0x1b, 0x1, 0x1, 0x1, 0x1, 0x1, 0x37, 0xe, 0x1, 0x5, 0x1, 0x2, 0x5, 0xb, 0x1, 0x24, 0x9, 0x1, 0x66, 0x4, 0x1, 0x6, 0x1, 0x2, 0x2, 0x2, 0x19, 0x2, 0x4, 0x3, 0x10, 0x4, 0xd, 0x1, 0x2, 0x2, 0x6, 0x1, 0xf, 0x1, 0x82, 0xbf, 0x3, 0x83, 0xb2, 0x3, 0x1d, 0x3, 0x1d, 0x2, 0x1e, 0x2, 0x40, 0x2, 0x1, 0x7, 0x8, 0x1, 0x2, 0xb, 0x9, 0x1, 0x2d, 0x3, 0x80, 0x9b, 0x1, 0x76, 0x3, 0x4, 0x2, 0x9, 0x1, 0x6, 0x3, 0x80, 0xdb, 0x2, 0x2, 0x1, 0x3a, 0x1, 0x1, 0x7, 0x1, 0x1, 0x1, 0x1, 0x2, 0x8, 0x6, 0xa, 0x2, 0x1, 0x80, 0x80, 0x4, 0x30, 0x1, 0x1, 0x5, 0x1, 0x1, 0x5, 0x1, 0x28, 0x9, 0xc, 0x2, 0x20, 0x4, 0x2, 0x2, 0x1, 0x1, 0x3a, 0x1, 0x1, 0x2, 0x3, 0x1, 0x1, 0x3, 0x3a, 0x8, 0x2, 0x2, 0x80, 0x98, 0x3, 0x1, 0xd, 0x1, 0x7, 0x4, 0x1, 0x6, 0x1, 0x80, 0xcb, 0x27, 0x15, 0x4, 0x82, 0xc, 0x2, 0x80, 0xc2, 0x21, 0x8b, 0xfe, 0x3, 0x80, 0x8d, 0x1, 0x60, 0x20, 0x82, 0x2a, 0x6, 0x69, 0x2, 0xa0, 0x75, 0xd4, 0x4, 0x1, 0xa, 0x21, 0x1, 0x50, 0x2, 0x81, 0x10, 0x1, 0x3, 0x1, 0x4, 0x1, 0x19, 0x2, 0x80, 0x9d, 0x1, 0x1b, 0x12, 0x34, 0x8, 0x19, 0xb, 0x2e, 0x3, 0x30, 0x1, 0x2, 0x4, 0x2, 0x1, 0x6c, 0x6, 0x2, 0x2, 0x2, 0x2, 0xc, 0x1, 0x8, 0x1, 0x63, 0x1, 0x1, 0x3, 0x2, 0x2, 0x5, 0x2, 0x1, 0x1, 0x2a, 0x2, 0x8, 0x1, 0x80, 0xee, 0x1, 0x2, 0x1, 0x4, 0x1, 0xa0, 0x4f, 0x30, 0x1, 0x82, 0xe1, 0x10, 0x10, 0x7, 0x81, 0x77, 0x2, 0x82, 0x5d, 0x1, 0x88, 0x3, 0x3, 0x1, 0x2, 0x5, 0x4, 0x28, 0x3, 0x4, 0x1, 0x85, 0xc1, 0x1, 0x36, 0xf, 0x39, 0x2, 0x31, 0x4, 0x2, 0x2, 0x45, 0x3, 0x24, 0x5, 0x1, 0x8, 0x4b, 0x2, 0x34, 0x9, 0x84, 0xec, 0x1, 0x1, 0x1, 0x2, 0x6, 0x1, 0x1, 0xa0, 0x58, 0xd7, 0x4, 0xa0, 0x61, 0xd2, 0x1, 0x1, 0x3, 0x4, 0x5, 0x8, 0x8, 0x2, 0x7, 0x1e, 0x4, 0x80, 0x94, 0x3, 0xac, 0x2e, 0xbb, 0x80, 0xf0];
+_T Hyphen = [0x2d, 0x1, 0x7f, 0x1, 0x84, 0xdc, 0x1, 0x92, 0x7b, 0x1, 0x88, 0x9, 0x2, 0x8e, 0x5, 0x1, 0x82, 0xe3, 0x1, 0xa0, 0xcd, 0x67, 0x1, 0x80, 0xa9, 0x1, 0x57, 0x1];
+_T Pe = [0x29, 0x1, 0x33, 0x1, 0x1f, 0x1, 0x8e, 0xbd, 0x1, 0x1, 0x1, 0x87, 0x5e, 0x1, 0x89, 0xa9, 0x1, 0x37, 0x1, 0xf, 0x1, 0x82, 0x7a, 0x1, 0x1, 0x1, 0x1e, 0x1, 0x84, 0x3e, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x50, 0x1, 0x20, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x81, 0x94, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x40, 0x1, 0x1, 0x1, 0x21, 0x1, 0x84, 0x25, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x81, 0xdf, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x3, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0xa0, 0xcd, 0x1f, 0x1, 0x80, 0xd8, 0x1, 0x1d, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x3, 0x1, 0x11, 0x1, 0x1, 0x1, 0x1, 0x1, 0x80, 0xaa, 0x1, 0x33, 0x1, 0x1f, 0x1, 0x2, 0x1, 0x2, 0x1];
+_U[] _tab = [
+_U("Alphabetic", Alphabetic),
+_U("ASCII_Hex_Digit", ASCII_Hex_Digit),
+_U("Bidi_Control", Bidi_Control),
+_U("Cased", Cased),
+_U("Case_Ignorable", Case_Ignorable),
+_U("Cc", Cc),
+_U("Cf", Cf),
+_U("Close_Punctuation", Pe),
+_U("Cn", Cn),
+_U("Co", Co),
+_U("Connector_Punctuation", Pc),
+_U("Control", Cc),
+_U("Cs", Cs),
+_U("Currency_Symbol", Sc),
+_U("Dash", Dash),
+_U("Dash_Punctuation", Pd),
+_U("Decimal_Number", Nd),
+_U("Default_Ignorable_Code_Point", Default_Ignorable_Code_Point),
+_U("Deprecated", Deprecated),
+_U("Diacritic", Diacritic),
+_U("Enclosing_Mark", Me),
+_U("Extender", Extender),
+_U("Final_Punctuation", Pf),
+_U("Format", Cf),
+_U("Grapheme_Base", Grapheme_Base),
+_U("Grapheme_Extend", Grapheme_Extend),
+_U("Grapheme_Link", Grapheme_Link),
+_U("Hex_Digit", Hex_Digit),
+_U("Hyphen", Hyphen),
+_U("ID_Continue", ID_Continue),
+_U("Ideographic", Ideographic),
+_U("IDS_Binary_Operator", IDS_Binary_Operator),
+_U("ID_Start", ID_Start),
+_U("IDS_Trinary_Operator", IDS_Trinary_Operator),
+_U("Initial_Punctuation", Pi),
+_U("Join_Control", Join_Control),
+_U("Letter_Number", Nl),
+_U("Line_Separator", Zl),
+_U("Ll", Ll),
+_U("Lm", Lm),
+_U("Lo", Lo),
+_U("Logical_Order_Exception", Logical_Order_Exception),
+_U("Lowercase", Lowercase),
+_U("Lowercase_Letter", Ll),
+_U("Lt", Lt),
+_U("Lu", Lu),
+_U("Math", Math),
+_U("Math_Symbol", Sm),
+_U("Mc", Mc),
+_U("Me", Me),
+_U("Mn", Mn),
+_U("Modifier_Letter", Lm),
+_U("Modifier_Symbol", Sk),
+_U("Nd", Nd),
+_U("Nl", Nl),
+_U("No", No),
+_U("Noncharacter_Code_Point", Noncharacter_Code_Point),
+_U("Nonspacing_Mark", Mn),
+_U("Open_Punctuation", Ps),
+_U("Other_Alphabetic", Other_Alphabetic),
+_U("Other_Default_Ignorable_Code_Point", Other_Default_Ignorable_Code_Point),
+_U("Other_Grapheme_Extend", Other_Grapheme_Extend),
+_U("Other_ID_Continue", Other_ID_Continue),
+_U("Other_ID_Start", Other_ID_Start),
+_U("Other_Letter", Lo),
+_U("Other_Lowercase", Other_Lowercase),
+_U("Other_Math", Other_Math),
+_U("Other_Number", No),
+_U("Other_Punctuation", Po),
+_U("Other_Symbol", So),
+_U("Other_Uppercase", Other_Uppercase),
+_U("Paragraph_Separator", Zp),
+_U("Pattern_Syntax", Pattern_Syntax),
+_U("Pattern_White_Space", Pattern_White_Space),
+_U("Pc", Pc),
+_U("Pd", Pd),
+_U("Pe", Pe),
+_U("Pf", Pf),
+_U("Pi", Pi),
+_U("Po", Po),
+_U("Private_Use", Co),
+_U("Ps", Ps),
+_U("Quotation_Mark", Quotation_Mark),
+_U("Radical", Radical),
+_U("Sc", Sc),
+_U("Sk", Sk),
+_U("Sm", Sm),
+_U("So", So),
+_U("Soft_Dotted", Soft_Dotted),
+_U("Space_Separator", Zs),
+_U("Spacing_Mark", Mc),
+_U("STerm", STerm),
+_U("Surrogate", Cs),
+_U("Terminal_Punctuation", Terminal_Punctuation),
+_U("Titlecase_Letter", Lt),
+_U("Unassigned", Cn),
+_U("Unified_Ideograph", Unified_Ideograph),
+_U("Uppercase", Uppercase),
+_U("Uppercase_Letter", Lu),
+_U("Variation_Selector", Variation_Selector),
+_U("White_Space", White_Space),
+_U("XID_Continue", XID_Continue),
+_U("XID_Start", XID_Start),
+_U("Zl", Zl),
+_U("Zp", Zp),
+_U("Zs", Zs),
+];
+}
+
+struct blocks
+{
+private alias _U = immutable(UnicodeProperty);
+@property static _U[] tab() { return _tab; }
+static immutable:
+private alias _T = ubyte[];
+_T Number_Forms = [0xa0, 0x21, 0x50, 0x40];
+_T Sinhala = [0x8d, 0x80, 0x80, 0x80];
+_T Domino_Tiles = [0xa1, 0xf0, 0x30, 0x70];
+_T Oriya = [0x8b, 0x0, 0x80, 0x80];
+_T Thaana = [0x87, 0x80, 0x40];
+_T New_Tai_Lue = [0x99, 0x80, 0x60];
+_T Byzantine_Musical_Symbols = [0xa1, 0xd0, 0x0, 0x81, 0x0];
+_T Cham = [0xa0, 0xaa, 0x0, 0x60];
+_T IPA_Extensions = [0x82, 0x50, 0x60];
+_T Bopomofo = [0xa0, 0x31, 0x0, 0x30];
+_T Katakana_Phonetic_Extensions = [0xa0, 0x31, 0xf0, 0x10];
+_T Khmer_Symbols = [0x99, 0xe0, 0x20];
+_T Hebrew = [0x85, 0x90, 0x70];
+_T Saurashtra = [0xa0, 0xa8, 0x80, 0x60];
+_T Inscriptional_Parthian = [0xa1, 0xb, 0x40, 0x20];
+_T Lisu = [0xa0, 0xa4, 0xd0, 0x30];
+_T Latin_1_Supplement = [0x80, 0x80, 0x80, 0x80];
+_T Arabic_Extended_A = [0x88, 0xa0, 0x60];
+_T Tai_Tham = [0x9a, 0x20, 0x80, 0x90];
+_T Latin_Extended_A = [0x81, 0x0, 0x80, 0x80];
+_T Latin_Extended_B = [0x81, 0x80, 0x80, 0xd0];
+_T Latin_Extended_C = [0xa0, 0x2c, 0x60, 0x20];
+_T Latin_Extended_D = [0xa0, 0xa7, 0x20, 0x80, 0xe0];
+_T CJK_Radicals_Supplement = [0xa0, 0x2e, 0x80, 0x80, 0x80];
+_T Meroitic_Hieroglyphs = [0xa1, 0x9, 0x80, 0x20];
+_T Linear_B_Syllabary = [0xa1, 0x0, 0x0, 0x80, 0x80];
+_T Phonetic_Extensions_Supplement = [0x9d, 0x80, 0x40];
+_T Meroitic_Cursive = [0xa1, 0x9, 0xa0, 0x60];
+_T Enclosed_Ideographic_Supplement = [0xa1, 0xf2, 0x0, 0x81, 0x0];
+_T Halfwidth_and_Fullwidth_Forms = [0xa0, 0xff, 0x0, 0x80, 0xf0];
+_T Takri = [0xa1, 0x16, 0x80, 0x50];
+_T Supplemental_Punctuation = [0xa0, 0x2e, 0x0, 0x80, 0x80];
+_T Malayalam = [0x8d, 0x0, 0x80, 0x80];
+_T Lepcha = [0x9c, 0x0, 0x50];
+_T Miscellaneous_Symbols_And_Pictographs = [0xa1, 0xf3, 0x0, 0x83, 0x0];
+_T Arabic_Presentation_Forms_A = [0xa0, 0xfb, 0x50, 0x82, 0xb0];
+_T Sora_Sompeng = [0xa1, 0x10, 0xd0, 0x30];
+_T Lydian = [0xa1, 0x9, 0x20, 0x20];
+_T Hangul_Jamo_Extended_B = [0xa0, 0xd7, 0xb0, 0x50];
+_T Private_Use_Area = [0xa0, 0xe0, 0x0, 0x99, 0x0];
+_T Coptic = [0xa0, 0x2c, 0x80, 0x80, 0x80];
+_T Phaistos_Disc = [0xa1, 0x1, 0xd0, 0x30];
+_T Batak = [0x9b, 0xc0, 0x40];
+_T Khmer = [0x97, 0x80, 0x80, 0x80];
+_T Counting_Rod_Numerals = [0xa1, 0xd3, 0x60, 0x20];
+_T Old_South_Arabian = [0xa1, 0xa, 0x60, 0x20];
+_T Kannada = [0x8c, 0x80, 0x80, 0x80];
+_T Arrows = [0xa0, 0x21, 0x90, 0x70];
+_T CJK_Compatibility_Ideographs_Supplement = [0xa2, 0xf8, 0x0, 0x82, 0x20];
+_T Combining_Half_Marks = [0xa0, 0xfe, 0x20, 0x10];
+_T Miscellaneous_Technical = [0xa0, 0x23, 0x0, 0x81, 0x0];
+_T Thai = [0x8e, 0x0, 0x80, 0x80];
+_T Alphabetic_Presentation_Forms = [0xa0, 0xfb, 0x0, 0x50];
+_T CJK_Unified_Ideographs = [0xa0, 0x4e, 0x0, 0xa0, 0x52, 0x0];
+_T Phonetic_Extensions = [0x9d, 0x0, 0x80, 0x80];
+_T Kayah_Li = [0xa0, 0xa9, 0x0, 0x30];
+_T Supplementary_Private_Use_Area_B = [0xb0, 0x0, 0x0];
+_T Gujarati = [0x8a, 0x80, 0x80, 0x80];
+_T Unified_Canadian_Aboriginal_Syllabics_Extended = [0x98, 0xb0, 0x50];
+_T Hangul_Syllables = [0xa0, 0xac, 0x0, 0xa0, 0x2b, 0xb0];
+_T Vertical_Forms = [0xa0, 0xfe, 0x10, 0x10];
+_T Inscriptional_Pahlavi = [0xa1, 0xb, 0x60, 0x20];
+_T Control_Pictures = [0xa0, 0x24, 0x0, 0x40];
+_T Carian = [0xa1, 0x2, 0xa0, 0x40];
+_T Mahjong_Tiles = [0xa1, 0xf0, 0x0, 0x30];
+_T Geometric_Shapes = [0xa0, 0x25, 0xa0, 0x60];
+_T Cherokee = [0x93, 0xa0, 0x60];
+_T Imperial_Aramaic = [0xa1, 0x8, 0x40, 0x20];
+_T Rumi_Numeral_Symbols = [0xa1, 0xe, 0x60, 0x20];
+_T Combining_Diacritical_Marks = [0x83, 0x0, 0x70];
+_T Specials = [0xa0, 0xff, 0xf0, 0x10];
+_T Greek_Extended = [0x9f, 0x0, 0x81, 0x0];
+_T Ethiopic_Supplement = [0x93, 0x80, 0x20];
+_T Limbu = [0x99, 0x0, 0x50];
+_T Basic_Latin = [0x0, 0x80, 0x80];
+_T Enclosed_Alphanumeric_Supplement = [0xa1, 0xf1, 0x0, 0x81, 0x0];
+_T Cyrillic_Supplement = [0x85, 0x0, 0x30];
+_T Hangul_Compatibility_Jamo = [0xa0, 0x31, 0x30, 0x60];
+_T Supplemental_Arrows_A = [0xa0, 0x27, 0xf0, 0x10];
+_T Supplemental_Arrows_B = [0xa0, 0x29, 0x0, 0x80, 0x80];
+_T Katakana = [0xa0, 0x30, 0xa0, 0x60];
+_T Ancient_Greek_Musical_Notation = [0xa1, 0xd2, 0x0, 0x50];
+_T CJK_Compatibility = [0xa0, 0x33, 0x0, 0x81, 0x0];
+_T Old_Persian = [0xa1, 0x3, 0xa0, 0x40];
+_T Small_Form_Variants = [0xa0, 0xfe, 0x50, 0x20];
+_T General_Punctuation = [0xa0, 0x20, 0x0, 0x70];
+_T Miscellaneous_Mathematical_Symbols_A = [0xa0, 0x27, 0xc0, 0x30];
+_T Latin_Extended_Additional = [0x9e, 0x0, 0x81, 0x0];
+_T Playing_Cards = [0xa1, 0xf0, 0xa0, 0x60];
+_T Syriac = [0x87, 0x0, 0x50];
+_T Alchemical_Symbols = [0xa1, 0xf7, 0x0, 0x80, 0x80];
+_T Tibetan = [0x8f, 0x0, 0x81, 0x0];
+_T CJK_Strokes = [0xa0, 0x31, 0xc0, 0x30];
+_T Tamil = [0x8b, 0x80, 0x80, 0x80];
+_T Balinese = [0x9b, 0x0, 0x80, 0x80];
+_T Shavian = [0xa1, 0x4, 0x50, 0x30];
+_T Greek_and_Coptic = [0x83, 0x70, 0x80, 0x90];
+_T Telugu = [0x8c, 0x0, 0x80, 0x80];
+_T Runic = [0x96, 0xa0, 0x60];
+_T Javanese = [0xa0, 0xa9, 0x80, 0x60];
+_T Bopomofo_Extended = [0xa0, 0x31, 0xa0, 0x20];
+_T Ideographic_Description_Characters = [0xa0, 0x2f, 0xf0, 0x10];
+_T Old_Turkic = [0xa1, 0xc, 0x0, 0x50];
+_T Unified_Canadian_Aboriginal_Syllabics = [0x94, 0x0, 0x82, 0x80];
+_T Ugaritic = [0xa1, 0x3, 0x80, 0x20];
+_T Egyptian_Hieroglyphs = [0xa1, 0x30, 0x0, 0x84, 0x30];
+_T Buginese = [0x9a, 0x0, 0x20];
+_T Kangxi_Radicals = [0xa0, 0x2f, 0x0, 0x80, 0xe0];
+_T Cuneiform = [0xa1, 0x20, 0x0, 0x84, 0x0];
+_T NKo = [0x87, 0xc0, 0x40];
+_T Sundanese_Supplement = [0x9c, 0xc0, 0x10];
+_T Buhid = [0x97, 0x40, 0x20];
+_T Modifier_Tone_Letters = [0xa0, 0xa7, 0x0, 0x20];
+_T Kanbun = [0xa0, 0x31, 0x90, 0x10];
+_T Superscripts_and_Subscripts = [0xa0, 0x20, 0x70, 0x30];
+_T Lao = [0x8e, 0x80, 0x80, 0x80];
+_T Ol_Chiki = [0x9c, 0x50, 0x30];
+_T Common_Indic_Number_Forms = [0xa0, 0xa8, 0x30, 0x10];
+_T Hangul_Jamo_Extended_A = [0xa0, 0xa9, 0x60, 0x20];
+_T Arabic_Presentation_Forms_B = [0xa0, 0xfe, 0x70, 0x80, 0x90];
+_T Sharada = [0xa1, 0x11, 0x80, 0x60];
+_T Miscellaneous_Symbols = [0xa0, 0x26, 0x0, 0x81, 0x0];
+_T Variation_Selectors_Supplement = [0xae, 0x1, 0x0, 0x80, 0xf0];
+_T Rejang = [0xa0, 0xa9, 0x30, 0x30];
+_T Georgian_Supplement = [0xa0, 0x2d, 0x0, 0x30];
+_T Braille_Patterns = [0xa0, 0x28, 0x0, 0x81, 0x0];
+_T Lycian = [0xa1, 0x2, 0x80, 0x20];
+_T Tai_Le = [0x99, 0x50, 0x30];
+_T Miscellaneous_Mathematical_Symbols_B = [0xa0, 0x29, 0x80, 0x80, 0x80];
+_T Musical_Symbols = [0xa1, 0xd1, 0x0, 0x81, 0x0];
+_T Avestan = [0xa1, 0xb, 0x0, 0x40];
+_T Ethiopic = [0x92, 0x0, 0x81, 0x80];
+_T Arabic_Supplement = [0x87, 0x50, 0x30];
+_T Samaritan = [0x88, 0x0, 0x40];
+_T Cuneiform_Numbers_and_Punctuation = [0xa1, 0x24, 0x0, 0x80, 0x80];
+_T Mongolian = [0x98, 0x0, 0x80, 0xb0];
+_T Arabic = [0x86, 0x0, 0x81, 0x0];
+_T Vai = [0xa0, 0xa5, 0x0, 0x81, 0x40];
+_T Tifinagh = [0xa0, 0x2d, 0x30, 0x50];
+_T Bamum_Supplement = [0xa1, 0x68, 0x0, 0x82, 0x40];
+_T Tai_Viet = [0xa0, 0xaa, 0x80, 0x60];
+_T Mandaic = [0x88, 0x40, 0x20];
+_T Sundanese = [0x9b, 0x80, 0x40];
+_T Block_Elements = [0xa0, 0x25, 0x80, 0x20];
+_T Phoenician = [0xa1, 0x9, 0x0, 0x20];
+_T Hanunoo = [0x97, 0x20, 0x20];
+_T Supplemental_Mathematical_Operators = [0xa0, 0x2a, 0x0, 0x81, 0x0];
+_T Deseret = [0xa1, 0x4, 0x0, 0x50];
+_T Brahmi = [0xa1, 0x10, 0x0, 0x80, 0x80];
+_T Devanagari_Extended = [0xa0, 0xa8, 0xe0, 0x20];
+_T Supplementary_Private_Use_Area_A = [0xaf, 0x0, 0x0, 0xa1, 0x0, 0x0];
+_T Box_Drawing = [0xa0, 0x25, 0x0, 0x80, 0x80];
+_T Mathematical_Operators = [0xa0, 0x22, 0x0, 0x81, 0x0];
+_T Ogham = [0x96, 0x80, 0x20];
+_T Meetei_Mayek_Extensions = [0xa0, 0xaa, 0xe0, 0x20];
+_T Hangul_Jamo = [0x91, 0x0, 0x81, 0x0];
+_T Miao = [0xa1, 0x6f, 0x0, 0x80, 0xa0];
+_T Emoticons = [0xa1, 0xf6, 0x0, 0x50];
+_T Tags = [0xae, 0x0, 0x0, 0x80, 0x80];
+_T Yi_Syllables = [0xa0, 0xa0, 0x0, 0x84, 0x90];
+_T Gurmukhi = [0x8a, 0x0, 0x80, 0x80];
+_T Syloti_Nagri = [0xa0, 0xa8, 0x0, 0x30];
+_T Spacing_Modifier_Letters = [0x82, 0xb0, 0x50];
+_T Yi_Radicals = [0xa0, 0xa4, 0x90, 0x40];
+_T Ancient_Greek_Numbers = [0xa1, 0x1, 0x40, 0x50];
+_T Glagolitic = [0xa0, 0x2c, 0x0, 0x60];
+_T Georgian = [0x90, 0xa0, 0x60];
+_T Osmanya = [0xa1, 0x4, 0x80, 0x30];
+_T Variation_Selectors = [0xa0, 0xfe, 0x0, 0x10];
+_T Mathematical_Alphanumeric_Symbols = [0xa1, 0xd4, 0x0, 0x84, 0x0];
+_T Yijing_Hexagram_Symbols = [0xa0, 0x4d, 0xc0, 0x40];
+_T Ethiopic_Extended = [0xa0, 0x2d, 0x80, 0x60];
+_T Transport_And_Map_Symbols = [0xa1, 0xf6, 0x80, 0x80, 0x80];
+_T High_Private_Use_Surrogates = [0xa0, 0xdb, 0x80, 0x80, 0x80];
+_T Meetei_Mayek = [0xa0, 0xab, 0xc0, 0x40];
+_T CJK_Compatibility_Forms = [0xa0, 0xfe, 0x30, 0x20];
+_T Enclosed_Alphanumerics = [0xa0, 0x24, 0x60, 0x80, 0xa0];
+_T Ancient_Symbols = [0xa1, 0x1, 0x90, 0x40];
+_T Ethiopic_Extended_A = [0xa0, 0xab, 0x0, 0x30];
+_T Bengali = [0x89, 0x80, 0x80, 0x80];
+_T Currency_Symbols = [0xa0, 0x20, 0xa0, 0x30];
+_T Myanmar = [0x90, 0x0, 0x80, 0xa0];
+_T Cyrillic_Extended_A = [0xa0, 0x2d, 0xe0, 0x20];
+_T Cyrillic_Extended_B = [0xa0, 0xa6, 0x40, 0x60];
+_T Myanmar_Extended_A = [0xa0, 0xaa, 0x60, 0x20];
+_T Hiragana = [0xa0, 0x30, 0x40, 0x60];
+_T Dingbats = [0xa0, 0x27, 0x0, 0x80, 0xc0];
+_T Armenian = [0x85, 0x30, 0x60];
+_T Tai_Xuan_Jing_Symbols = [0xa1, 0xd3, 0x0, 0x60];
+_T Linear_B_Ideograms = [0xa1, 0x0, 0x80, 0x80, 0x80];
+_T Kharoshthi = [0xa1, 0xa, 0x0, 0x60];
+_T Optical_Character_Recognition = [0xa0, 0x24, 0x40, 0x20];
+_T Enclosed_CJK_Letters_and_Months = [0xa0, 0x32, 0x0, 0x81, 0x0];
+_T Cypriot_Syllabary = [0xa1, 0x8, 0x0, 0x40];
+_T Vedic_Extensions = [0x9c, 0xd0, 0x30];
+_T Kaithi = [0xa1, 0x10, 0x80, 0x50];
+_T Low_Surrogates = [0xa0, 0xdc, 0x0, 0x84, 0x0];
+_T Letterlike_Symbols = [0xa0, 0x21, 0x0, 0x50];
+_T Combining_Diacritical_Marks_for_Symbols = [0xa0, 0x20, 0xd0, 0x30];
+_T Aegean_Numbers = [0xa1, 0x1, 0x0, 0x40];
+_T High_Surrogates = [0xa0, 0xd8, 0x0, 0x83, 0x80];
+_T CJK_Compatibility_Ideographs = [0xa0, 0xf9, 0x0, 0x82, 0x0];
+_T CJK_Symbols_and_Punctuation = [0xa0, 0x30, 0x0, 0x40];
+_T Gothic = [0xa1, 0x3, 0x30, 0x20];
+_T Combining_Diacritical_Marks_Supplement = [0x9d, 0xc0, 0x40];
+_T Phags_pa = [0xa0, 0xa8, 0x40, 0x40];
+_T Miscellaneous_Symbols_and_Arrows = [0xa0, 0x2b, 0x0, 0x81, 0x0];
+_T Bamum = [0xa0, 0xa6, 0xa0, 0x60];
+_T Chakma = [0xa1, 0x11, 0x0, 0x50];
+_T Kana_Supplement = [0xa1, 0xb0, 0x0, 0x81, 0x0];
+_T Tagalog = [0x97, 0x0, 0x20];
+_T Tagbanwa = [0x97, 0x60, 0x20];
+_T Devanagari = [0x89, 0x0, 0x80, 0x80];
+_T Old_Italic = [0xa1, 0x3, 0x0, 0x30];
+_T Arabic_Mathematical_Alphabetic_Symbols = [0xa1, 0xee, 0x0, 0x81, 0x0];
+_T CJK_Unified_Ideographs_Extension_D = [0xa2, 0xb7, 0x40, 0x80, 0xe0];
+_T CJK_Unified_Ideographs_Extension_A = [0xa0, 0x34, 0x0, 0x99, 0xc0];
+_T CJK_Unified_Ideographs_Extension_B = [0xa2, 0x0, 0x0, 0xa0, 0xa6, 0xe0];
+_T CJK_Unified_Ideographs_Extension_C = [0xa2, 0xa7, 0x0, 0x90, 0x40];
+_T Cyrillic = [0x84, 0x0, 0x81, 0x0];
+_U[] _tab = [
+_U("Aegean Numbers", Aegean_Numbers),
+_U("Alchemical Symbols", Alchemical_Symbols),
+_U("Alphabetic Presentation Forms", Alphabetic_Presentation_Forms),
+_U("Ancient Greek Musical Notation", Ancient_Greek_Musical_Notation),
+_U("Ancient Greek Numbers", Ancient_Greek_Numbers),
+_U("Ancient Symbols", Ancient_Symbols),
+_U("Arabic", Arabic),
+_U("Arabic Extended-A", Arabic_Extended_A),
+_U("Arabic Mathematical Alphabetic Symbols", Arabic_Mathematical_Alphabetic_Symbols),
+_U("Arabic Presentation Forms-A", Arabic_Presentation_Forms_A),
+_U("Arabic Presentation Forms-B", Arabic_Presentation_Forms_B),
+_U("Arabic Supplement", Arabic_Supplement),
+_U("Armenian", Armenian),
+_U("Arrows", Arrows),
+_U("Avestan", Avestan),
+_U("Balinese", Balinese),
+_U("Bamum", Bamum),
+_U("Bamum Supplement", Bamum_Supplement),
+_U("Basic Latin", Basic_Latin),
+_U("Batak", Batak),
+_U("Bengali", Bengali),
+_U("Block Elements", Block_Elements),
+_U("Bopomofo", Bopomofo),
+_U("Bopomofo Extended", Bopomofo_Extended),
+_U("Box Drawing", Box_Drawing),
+_U("Brahmi", Brahmi),
+_U("Braille Patterns", Braille_Patterns),
+_U("Buginese", Buginese),
+_U("Buhid", Buhid),
+_U("Byzantine Musical Symbols", Byzantine_Musical_Symbols),
+_U("Carian", Carian),
+_U("Chakma", Chakma),
+_U("Cham", Cham),
+_U("Cherokee", Cherokee),
+_U("CJK Compatibility", CJK_Compatibility),
+_U("CJK Compatibility Forms", CJK_Compatibility_Forms),
+_U("CJK Compatibility Ideographs", CJK_Compatibility_Ideographs),
+_U("CJK Compatibility Ideographs Supplement", CJK_Compatibility_Ideographs_Supplement),
+_U("CJK Radicals Supplement", CJK_Radicals_Supplement),
+_U("CJK Strokes", CJK_Strokes),
+_U("CJK Symbols and Punctuation", CJK_Symbols_and_Punctuation),
+_U("CJK Unified Ideographs", CJK_Unified_Ideographs),
+_U("CJK Unified Ideographs Extension A", CJK_Unified_Ideographs_Extension_A),
+_U("CJK Unified Ideographs Extension B", CJK_Unified_Ideographs_Extension_B),
+_U("CJK Unified Ideographs Extension C", CJK_Unified_Ideographs_Extension_C),
+_U("CJK Unified Ideographs Extension D", CJK_Unified_Ideographs_Extension_D),
+_U("Combining Diacritical Marks", Combining_Diacritical_Marks),
+_U("Combining Diacritical Marks for Symbols", Combining_Diacritical_Marks_for_Symbols),
+_U("Combining Diacritical Marks Supplement", Combining_Diacritical_Marks_Supplement),
+_U("Combining Half Marks", Combining_Half_Marks),
+_U("Common Indic Number Forms", Common_Indic_Number_Forms),
+_U("Control Pictures", Control_Pictures),
+_U("Coptic", Coptic),
+_U("Counting Rod Numerals", Counting_Rod_Numerals),
+_U("Cuneiform", Cuneiform),
+_U("Cuneiform Numbers and Punctuation", Cuneiform_Numbers_and_Punctuation),
+_U("Currency Symbols", Currency_Symbols),
+_U("Cypriot Syllabary", Cypriot_Syllabary),
+_U("Cyrillic", Cyrillic),
+_U("Cyrillic Extended-A", Cyrillic_Extended_A),
+_U("Cyrillic Extended-B", Cyrillic_Extended_B),
+_U("Cyrillic Supplement", Cyrillic_Supplement),
+_U("Deseret", Deseret),
+_U("Devanagari", Devanagari),
+_U("Devanagari Extended", Devanagari_Extended),
+_U("Dingbats", Dingbats),
+_U("Domino Tiles", Domino_Tiles),
+_U("Egyptian Hieroglyphs", Egyptian_Hieroglyphs),
+_U("Emoticons", Emoticons),
+_U("Enclosed Alphanumerics", Enclosed_Alphanumerics),
+_U("Enclosed Alphanumeric Supplement", Enclosed_Alphanumeric_Supplement),
+_U("Enclosed CJK Letters and Months", Enclosed_CJK_Letters_and_Months),
+_U("Enclosed Ideographic Supplement", Enclosed_Ideographic_Supplement),
+_U("Ethiopic", Ethiopic),
+_U("Ethiopic Extended", Ethiopic_Extended),
+_U("Ethiopic Extended-A", Ethiopic_Extended_A),
+_U("Ethiopic Supplement", Ethiopic_Supplement),
+_U("General Punctuation", General_Punctuation),
+_U("Geometric Shapes", Geometric_Shapes),
+_U("Georgian", Georgian),
+_U("Georgian Supplement", Georgian_Supplement),
+_U("Glagolitic", Glagolitic),
+_U("Gothic", Gothic),
+_U("Greek and Coptic", Greek_and_Coptic),
+_U("Greek Extended", Greek_Extended),
+_U("Gujarati", Gujarati),
+_U("Gurmukhi", Gurmukhi),
+_U("Halfwidth and Fullwidth Forms", Halfwidth_and_Fullwidth_Forms),
+_U("Hangul Compatibility Jamo", Hangul_Compatibility_Jamo),
+_U("Hangul Jamo", Hangul_Jamo),
+_U("Hangul Jamo Extended-A", Hangul_Jamo_Extended_A),
+_U("Hangul Jamo Extended-B", Hangul_Jamo_Extended_B),
+_U("Hangul Syllables", Hangul_Syllables),
+_U("Hanunoo", Hanunoo),
+_U("Hebrew", Hebrew),
+_U("High Private Use Surrogates", High_Private_Use_Surrogates),
+_U("High Surrogates", High_Surrogates),
+_U("Hiragana", Hiragana),
+_U("Ideographic Description Characters", Ideographic_Description_Characters),
+_U("Imperial Aramaic", Imperial_Aramaic),
+_U("Inscriptional Pahlavi", Inscriptional_Pahlavi),
+_U("Inscriptional Parthian", Inscriptional_Parthian),
+_U("IPA Extensions", IPA_Extensions),
+_U("Javanese", Javanese),
+_U("Kaithi", Kaithi),
+_U("Kana Supplement", Kana_Supplement),
+_U("Kanbun", Kanbun),
+_U("Kangxi Radicals", Kangxi_Radicals),
+_U("Kannada", Kannada),
+_U("Katakana", Katakana),
+_U("Katakana Phonetic Extensions", Katakana_Phonetic_Extensions),
+_U("Kayah Li", Kayah_Li),
+_U("Kharoshthi", Kharoshthi),
+_U("Khmer", Khmer),
+_U("Khmer Symbols", Khmer_Symbols),
+_U("Lao", Lao),
+_U("Latin-1 Supplement", Latin_1_Supplement),
+_U("Latin Extended-A", Latin_Extended_A),
+_U("Latin Extended Additional", Latin_Extended_Additional),
+_U("Latin Extended-B", Latin_Extended_B),
+_U("Latin Extended-C", Latin_Extended_C),
+_U("Latin Extended-D", Latin_Extended_D),
+_U("Lepcha", Lepcha),
+_U("Letterlike Symbols", Letterlike_Symbols),
+_U("Limbu", Limbu),
+_U("Linear B Ideograms", Linear_B_Ideograms),
+_U("Linear B Syllabary", Linear_B_Syllabary),
+_U("Lisu", Lisu),
+_U("Low Surrogates", Low_Surrogates),
+_U("Lycian", Lycian),
+_U("Lydian", Lydian),
+_U("Mahjong Tiles", Mahjong_Tiles),
+_U("Malayalam", Malayalam),
+_U("Mandaic", Mandaic),
+_U("Mathematical Alphanumeric Symbols", Mathematical_Alphanumeric_Symbols),
+_U("Mathematical Operators", Mathematical_Operators),
+_U("Meetei Mayek", Meetei_Mayek),
+_U("Meetei Mayek Extensions", Meetei_Mayek_Extensions),
+_U("Meroitic Cursive", Meroitic_Cursive),
+_U("Meroitic Hieroglyphs", Meroitic_Hieroglyphs),
+_U("Miao", Miao),
+_U("Miscellaneous Mathematical Symbols-A", Miscellaneous_Mathematical_Symbols_A),
+_U("Miscellaneous Mathematical Symbols-B", Miscellaneous_Mathematical_Symbols_B),
+_U("Miscellaneous Symbols", Miscellaneous_Symbols),
+_U("Miscellaneous Symbols and Arrows", Miscellaneous_Symbols_and_Arrows),
+_U("Miscellaneous Symbols And Pictographs", Miscellaneous_Symbols_And_Pictographs),
+_U("Miscellaneous Technical", Miscellaneous_Technical),
+_U("Modifier Tone Letters", Modifier_Tone_Letters),
+_U("Mongolian", Mongolian),
+_U("Musical Symbols", Musical_Symbols),
+_U("Myanmar", Myanmar),
+_U("Myanmar Extended-A", Myanmar_Extended_A),
+_U("New Tai Lue", New_Tai_Lue),
+_U("NKo", NKo),
+_U("Number Forms", Number_Forms),
+_U("Ogham", Ogham),
+_U("Ol Chiki", Ol_Chiki),
+_U("Old Italic", Old_Italic),
+_U("Old Persian", Old_Persian),
+_U("Old South Arabian", Old_South_Arabian),
+_U("Old Turkic", Old_Turkic),
+_U("Optical Character Recognition", Optical_Character_Recognition),
+_U("Oriya", Oriya),
+_U("Osmanya", Osmanya),
+_U("Phags-pa", Phags_pa),
+_U("Phaistos Disc", Phaistos_Disc),
+_U("Phoenician", Phoenician),
+_U("Phonetic Extensions", Phonetic_Extensions),
+_U("Phonetic Extensions Supplement", Phonetic_Extensions_Supplement),
+_U("Playing Cards", Playing_Cards),
+_U("Private Use Area", Private_Use_Area),
+_U("Rejang", Rejang),
+_U("Rumi Numeral Symbols", Rumi_Numeral_Symbols),
+_U("Runic", Runic),
+_U("Samaritan", Samaritan),
+_U("Saurashtra", Saurashtra),
+_U("Sharada", Sharada),
+_U("Shavian", Shavian),
+_U("Sinhala", Sinhala),
+_U("Small Form Variants", Small_Form_Variants),
+_U("Sora Sompeng", Sora_Sompeng),
+_U("Spacing Modifier Letters", Spacing_Modifier_Letters),
+_U("Specials", Specials),
+_U("Sundanese", Sundanese),
+_U("Sundanese Supplement", Sundanese_Supplement),
+_U("Superscripts and Subscripts", Superscripts_and_Subscripts),
+_U("Supplemental Arrows-A", Supplemental_Arrows_A),
+_U("Supplemental Arrows-B", Supplemental_Arrows_B),
+_U("Supplemental Mathematical Operators", Supplemental_Mathematical_Operators),
+_U("Supplemental Punctuation", Supplemental_Punctuation),
+_U("Supplementary Private Use Area-A", Supplementary_Private_Use_Area_A),
+_U("Supplementary Private Use Area-B", Supplementary_Private_Use_Area_B),
+_U("Syloti Nagri", Syloti_Nagri),
+_U("Syriac", Syriac),
+_U("Tagalog", Tagalog),
+_U("Tagbanwa", Tagbanwa),
+_U("Tags", Tags),
+_U("Tai Le", Tai_Le),
+_U("Tai Tham", Tai_Tham),
+_U("Tai Viet", Tai_Viet),
+_U("Tai Xuan Jing Symbols", Tai_Xuan_Jing_Symbols),
+_U("Takri", Takri),
+_U("Tamil", Tamil),
+_U("Telugu", Telugu),
+_U("Thaana", Thaana),
+_U("Thai", Thai),
+_U("Tibetan", Tibetan),
+_U("Tifinagh", Tifinagh),
+_U("Transport And Map Symbols", Transport_And_Map_Symbols),
+_U("Ugaritic", Ugaritic),
+_U("Unified Canadian Aboriginal Syllabics", Unified_Canadian_Aboriginal_Syllabics),
+_U("Unified Canadian Aboriginal Syllabics Extended", Unified_Canadian_Aboriginal_Syllabics_Extended),
+_U("Vai", Vai),
+_U("Variation Selectors", Variation_Selectors),
+_U("Variation Selectors Supplement", Variation_Selectors_Supplement),
+_U("Vedic Extensions", Vedic_Extensions),
+_U("Vertical Forms", Vertical_Forms),
+_U("Yijing Hexagram Symbols", Yijing_Hexagram_Symbols),
+_U("Yi Radicals", Yi_Radicals),
+_U("Yi Syllables", Yi_Syllables),
+];
+}
+
+struct scripts
+{
+private alias _U = immutable(UnicodeProperty);
+@property static _U[] tab() { return _tab; }
+static immutable:
+private alias _T = ubyte[];
+_T Buhid = [0x97, 0x40, 0x14];
+_T Sinhala = [0x8d, 0x82, 0x2, 0x1, 0x12, 0x3, 0x18, 0x1, 0x9, 0x1, 0x1, 0x2, 0x7, 0x3, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x8, 0x12, 0x3];
+_T Phags_Pa = [0xa0, 0xa8, 0x40, 0x38];
+_T Old_Turkic = [0xa1, 0xc, 0x0, 0x49];
+_T Oriya = [0x8b, 0x1, 0x3, 0x1, 0x8, 0x2, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x5, 0x2, 0x9, 0x2, 0x2, 0x2, 0x3, 0x8, 0x2, 0x4, 0x2, 0x1, 0x5, 0x2, 0x12];
+_T Thaana = [0x87, 0x80, 0x32];
+_T Inherited = [0x83, 0x0, 0x70, 0x81, 0x15, 0x2, 0x81, 0xc4, 0xb, 0x1a, 0x1, 0x82, 0xe0, 0x2, 0x93, 0x7d, 0x3, 0x1, 0xd, 0x1, 0x7, 0x4, 0x1, 0x6, 0x1, 0x80, 0xcb, 0x27, 0x15, 0x4, 0x82, 0xc, 0x2, 0x80, 0xc2, 0x21, 0x8f, 0x39, 0x4, 0x6b, 0x2, 0xa0, 0xcd, 0x65, 0x10, 0x10, 0x7, 0x83, 0xd6, 0x1, 0xa0, 0xcf, 0x69, 0x3, 0x11, 0x8, 0x2, 0x7, 0x1e, 0x4, 0xac, 0x2f, 0x52, 0x80, 0xf0];
+_T Sharada = [0xa1, 0x11, 0x80, 0x49, 0x7, 0xa];
+_T Rejang = [0xa0, 0xa9, 0x30, 0x24, 0xb, 0x1];
+_T Imperial_Aramaic = [0xa1, 0x8, 0x40, 0x16, 0x1, 0x9];
+_T Cham = [0xa0, 0xaa, 0x0, 0x37, 0x9, 0xe, 0x2, 0xa, 0x2, 0x4];
+_T Kaithi = [0xa1, 0x10, 0x80, 0x42];
+_T Bopomofo = [0x82, 0xea, 0x2, 0xa0, 0x2e, 0x19, 0x29, 0x72, 0x1b];
+_T Deseret = [0xa1, 0x4, 0x0, 0x50];
+_T Syloti_Nagri = [0xa0, 0xa8, 0x0, 0x2c];
+_T Lycian = [0xa1, 0x2, 0x80, 0x1d];
+_T Linear_B = [0xa1, 0x0, 0x0, 0xc, 0x1, 0x1a, 0x1, 0x13, 0x1, 0x2, 0x1, 0xf, 0x2, 0xe, 0x22, 0x7b];
+_T Hebrew = [0x85, 0x91, 0x37, 0x8, 0x1b, 0x5, 0x5, 0xa0, 0xf5, 0x28, 0x1a, 0x1, 0x5, 0x1, 0x1, 0x1, 0x2, 0x1, 0x2, 0x1, 0xa];
+_T Saurashtra = [0xa0, 0xa8, 0x80, 0x45, 0x9, 0xc];
+_T Avestan = [0xa1, 0xb, 0x0, 0x36, 0x3, 0x7];
+_T Ethiopic = [0x92, 0x0, 0x49, 0x1, 0x4, 0x2, 0x7, 0x1, 0x1, 0x1, 0x4, 0x2, 0x29, 0x1, 0x4, 0x2, 0x21, 0x1, 0x4, 0x2, 0x7, 0x1, 0x1, 0x1, 0x4, 0x2, 0xf, 0x1, 0x39, 0x1, 0x4, 0x2, 0x43, 0x2, 0x20, 0x3, 0x1a, 0x99, 0xe6, 0x17, 0x9, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0x1, 0x7, 0xa0, 0x7d, 0x22, 0x6, 0x2, 0x6, 0x2, 0x6, 0x9, 0x7, 0x1, 0x7];
+_T Braille = [0xa0, 0x28, 0x0, 0x81, 0x0];
+_T Lisu = [0xa0, 0xa4, 0xd0, 0x30];
+_T Samaritan = [0x88, 0x0, 0x2e, 0x2, 0xf];
+_T Mongolian = [0x98, 0x0, 0x2, 0x2, 0x1, 0x1, 0x9, 0x1, 0xa, 0x6, 0x58, 0x8, 0x2b];
+_T Hangul = [0x91, 0x0, 0x81, 0x0, 0x9e, 0x2e, 0x2, 0x81, 0x1, 0x5e, 0x71, 0x1f, 0x41, 0x1f, 0xa0, 0x76, 0xe1, 0x1d, 0x82, 0x83, 0xa0, 0x2b, 0xa4, 0xc, 0x17, 0x4, 0x31, 0xa0, 0x27, 0xa4, 0x1f, 0x3, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x3];
+_T Takri = [0xa1, 0x16, 0x80, 0x38, 0x8, 0xa];
+_T Phoenician = [0xa1, 0x9, 0x0, 0x1c, 0x3, 0x1];
+_T Vai = [0xa0, 0xa5, 0x0, 0x81, 0x2c];
+_T Batak = [0x9b, 0xc0, 0x34, 0x8, 0x4];
+_T Yi = [0xa0, 0xa0, 0x0, 0x84, 0x8d, 0x3, 0x37];
+_T Tifinagh = [0xa0, 0x2d, 0x30, 0x38, 0x7, 0x2, 0xe, 0x1];
+_T Glagolitic = [0xa0, 0x2c, 0x0, 0x2f, 0x1, 0x2f];
+_T Tai_Tham = [0x9a, 0x20, 0x3f, 0x1, 0x1d, 0x2, 0xb, 0x6, 0xa, 0x6, 0xe];
+_T Canadian_Aboriginal = [0x94, 0x0, 0x82, 0x80, 0x82, 0x30, 0x46];
+_T Meetei_Mayek = [0xa0, 0xaa, 0xe0, 0x17, 0x80, 0xc9, 0x2e, 0x2, 0xa];
+_T Balinese = [0x9b, 0x0, 0x4c, 0x4, 0x2d];
+_T Kayah_Li = [0xa0, 0xa9, 0x0, 0x30];
+_T Kharoshthi = [0xa1, 0xa, 0x0, 0x4, 0x1, 0x2, 0x5, 0x8, 0x1, 0x3, 0x1, 0x1b, 0x4, 0x3, 0x4, 0x9, 0x8, 0x9];
+_T Lepcha = [0x9c, 0x0, 0x38, 0x3, 0xf, 0x3, 0x3];
+_T New_Tai_Lue = [0x99, 0x80, 0x2c, 0x4, 0x1a, 0x6, 0xb, 0x3, 0x2];
+_T Sora_Sompeng = [0xa1, 0x10, 0xd0, 0x19, 0x7, 0xa];
+_T Arabic = [0x86, 0x0, 0x5, 0x1, 0x6, 0x1, 0xe, 0x1, 0x1, 0x1, 0x1, 0x1, 0x20, 0x1, 0xa, 0xb, 0xa, 0xa, 0x6, 0x1, 0x6c, 0x1, 0x22, 0x50, 0x30, 0x81, 0x20, 0x1, 0x1, 0xb, 0x37, 0x1b, 0xa0, 0xf2, 0x51, 0x72, 0x11, 0x81, 0x6b, 0x12, 0x40, 0x2, 0x36, 0x28, 0xd, 0x73, 0x5, 0x1, 0x80, 0x87, 0x8f, 0x63, 0x1f, 0xa0, 0xdf, 0x81, 0x4, 0x1, 0x1b, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0xa, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x6, 0x1, 0x4, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x3, 0x1, 0x2, 0x1, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2, 0x1, 0x1, 0x2, 0x4, 0x1, 0x7, 0x1, 0x4, 0x1, 0x4, 0x1, 0x1, 0x1, 0xa, 0x1, 0x11, 0x5, 0x3, 0x1, 0x5, 0x1, 0x11, 0x34, 0x2];
+_T Hanunoo = [0x97, 0x20, 0x15];
+_T Lydian = [0xa1, 0x9, 0x20, 0x1a, 0x5, 0x1];
+_T Tai_Viet = [0xa0, 0xaa, 0x80, 0x43, 0x18, 0x5];
+_T Coptic = [0x83, 0xe2, 0xe, 0xa0, 0x28, 0x90, 0x74, 0x5, 0x7];
+_T Brahmi = [0xa1, 0x10, 0x0, 0x4e, 0x4, 0x1e];
+_T Runic = [0x96, 0xa0, 0x4b, 0x3, 0x3];
+_T Egyptian_Hieroglyphs = [0xa1, 0x30, 0x0, 0x84, 0x2f];
+_T Khmer = [0x97, 0x80, 0x5e, 0x2, 0xa, 0x6, 0xa, 0x81, 0xe6, 0x20];
+_T Ogham = [0x96, 0x80, 0x1d];
+_T Gothic = [0xa1, 0x3, 0x30, 0x1b];
+_T Katakana = [0xa0, 0x30, 0xa1, 0x5a, 0x2, 0x3, 0x80, 0xf0, 0x10, 0x80, 0xd0, 0x2f, 0x1, 0x58, 0xa0, 0xcc, 0xe, 0xa, 0x1, 0x2d, 0xa0, 0xb0, 0x62, 0x1];
+_T Miao = [0xa1, 0x6f, 0x0, 0x45, 0xb, 0x2f, 0x10, 0x11];
+_T Meroitic_Hieroglyphs = [0xa1, 0x9, 0x80, 0x20];
+_T Thai = [0x8e, 0x1, 0x3a, 0x5, 0x1c];
+_T Cypriot = [0xa1, 0x8, 0x0, 0x6, 0x2, 0x1, 0x1, 0x2c, 0x1, 0x2, 0x3, 0x1, 0x2, 0x1];
+_T Meroitic_Cursive = [0xa1, 0x9, 0xa0, 0x18, 0x6, 0x2];
+_T Gujarati = [0x8a, 0x81, 0x3, 0x1, 0x9, 0x1, 0x3, 0x1, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x5, 0x2, 0xa, 0x1, 0x3, 0x1, 0x3, 0x2, 0x1, 0xf, 0x4, 0x2, 0xc];
+_T Lao = [0x8e, 0x81, 0x2, 0x1, 0x1, 0x2, 0x2, 0x1, 0x1, 0x2, 0x1, 0x6, 0x4, 0x1, 0x7, 0x1, 0x3, 0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0x1, 0xd, 0x1, 0x3, 0x2, 0x5, 0x1, 0x1, 0x1, 0x6, 0x2, 0xa, 0x2, 0x4];
+_T Georgian = [0x90, 0xa0, 0x26, 0x1, 0x1, 0x5, 0x1, 0x2, 0x2b, 0x1, 0x4, 0x9c, 0x0, 0x26, 0x1, 0x1, 0x5, 0x1];
+_T Osmanya = [0xa1, 0x4, 0x80, 0x1e, 0x2, 0xa];
+_T Inscriptional_Pahlavi = [0xa1, 0xb, 0x60, 0x13, 0x5, 0x8];
+_T Shavian = [0xa1, 0x4, 0x50, 0x30];
+_T Carian = [0xa1, 0x2, 0xa0, 0x31];
+_T Cherokee = [0x93, 0xa0, 0x55];
+_T Mandaic = [0x88, 0x40, 0x1c, 0x2, 0x1];
+_T Han = [0xa0, 0x2e, 0x80, 0x1a, 0x1, 0x59, 0xc, 0x80, 0xd6, 0x2f, 0x1, 0x1, 0x1, 0x19, 0x9, 0xe, 0x4, 0x83, 0xc4, 0x99, 0xb6, 0x4a, 0xa0, 0x51, 0xcd, 0xa0, 0x59, 0x33, 0x81, 0x6e, 0x2, 0x6a, 0xa1, 0x5, 0x26, 0xa0, 0xa6, 0xd7, 0x29, 0x90, 0x35, 0xb, 0x80, 0xde, 0xa0, 0x3f, 0xe2, 0x82, 0x1e];
+_T Latin = [0x41, 0x1a, 0x6, 0x1a, 0x2f, 0x1, 0xf, 0x1, 0x5, 0x17, 0x1, 0x1f, 0x1, 0x81, 0xc1, 0x27, 0x5, 0x9a, 0x1b, 0x26, 0x6, 0x31, 0x5, 0x4, 0x5, 0xd, 0x1, 0x46, 0x41, 0x81, 0x0, 0x81, 0x71, 0x1, 0xd, 0x1, 0x10, 0xd, 0x80, 0x8d, 0x2, 0x6, 0x1, 0x1b, 0x1, 0x11, 0x29, 0x8a, 0xd7, 0x20, 0xa0, 0x7a, 0xa2, 0x66, 0x3, 0x4, 0x1, 0x4, 0xc, 0xb, 0x4d, 0x8, 0xa0, 0x53, 0x0, 0x7, 0x84, 0x1a, 0x1a, 0x6, 0x1a];
+_T Limbu = [0x99, 0x0, 0x1d, 0x3, 0xc, 0x4, 0xc, 0x4, 0x1, 0x3, 0xc];
+_T Ol_Chiki = [0x9c, 0x50, 0x30];
+_T Bengali = [0x89, 0x81, 0x3, 0x1, 0x8, 0x2, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x1, 0x3, 0x4, 0x2, 0x9, 0x2, 0x2, 0x2, 0x4, 0x8, 0x1, 0x4, 0x2, 0x1, 0x5, 0x2, 0x16];
+_T Myanmar = [0x90, 0x0, 0x80, 0xa0, 0xa0, 0x99, 0xc0, 0x1c];
+_T Malayalam = [0x8d, 0x2, 0x2, 0x1, 0x8, 0x1, 0x3, 0x1, 0x29, 0x2, 0x8, 0x1, 0x3, 0x1, 0x5, 0x8, 0x1, 0x8, 0x4, 0x2, 0x10, 0x3, 0x7];
+_T Hiragana = [0xa0, 0x30, 0x41, 0x56, 0x6, 0x3, 0xa1, 0x7f, 0x61, 0x1, 0xa0, 0x41, 0xfe, 0x1];
+_T Kannada = [0x8c, 0x82, 0x2, 0x1, 0x8, 0x1, 0x3, 0x1, 0x17, 0x1, 0xa, 0x1, 0x5, 0x2, 0x9, 0x1, 0x3, 0x1, 0x4, 0x7, 0x2, 0x7, 0x1, 0x1, 0x4, 0x2, 0xa, 0x1, 0x2];
+_T Armenian = [0x85, 0x31, 0x26, 0x2, 0x7, 0x1, 0x27, 0x2, 0x1, 0x4, 0x1, 0xa0, 0xf5, 0x83, 0x5];
+_T Common = [0x0, 0x41, 0x1a, 0x6, 0x1a, 0x2f, 0x1, 0xf, 0x1, 0x5, 0x17, 0x1, 0x1f, 0x1, 0x81, 0xc1, 0x27, 0x5, 0x5, 0x2, 0x14, 0x74, 0x1, 0x9, 0x1, 0x6, 0x1, 0x1, 0x1, 0x82, 0x1, 0x1, 0x80, 0x82, 0x1, 0xe, 0x1, 0x3, 0x1, 0x20, 0x1, 0x1f, 0xa, 0x73, 0x1, 0x82, 0x86, 0x2, 0x84, 0xd9, 0x1, 0x81, 0x95, 0x4, 0x81, 0x22, 0x1, 0x85, 0xef, 0x3, 0x47, 0x2, 0x80, 0xcb, 0x2, 0x1, 0x1, 0x84, 0xcd, 0x1, 0xd, 0x1, 0x7, 0x4, 0x1, 0x6, 0x1, 0x2, 0x83, 0x9, 0xc, 0x2, 0x57, 0x1, 0xb, 0x3, 0xb, 0x1, 0xf, 0x11, 0x1b, 0x45, 0x26, 0x1, 0x3, 0x2, 0x6, 0x1, 0x1b, 0x1, 0x11, 0x29, 0x1, 0x6, 0x82, 0x64, 0xc, 0x27, 0x19, 0xb, 0x15, 0x82, 0xa0, 0x1, 0x80, 0xff, 0x81, 0x0, 0x82, 0x4d, 0x3, 0xa, 0x82, 0xa6, 0x3c, 0x81, 0xb4, 0xc, 0x4, 0x5, 0x1, 0x1, 0x1, 0x19, 0xf, 0x8, 0x4, 0x4, 0x5b, 0x2, 0x3, 0x1, 0x5a, 0x2, 0x80, 0x93, 0x10, 0x20, 0x24, 0x3c, 0x40, 0x1f, 0x51, 0x80, 0x88, 0x80, 0xa8, 0x99, 0xc0, 0x40, 0xa0, 0x59, 0x0, 0x22, 0x66, 0x3, 0x80, 0xa5, 0xa, 0x81, 0x95, 0x1, 0xa0, 0x53, 0x6e, 0x2, 0x80, 0xbd, 0x1, 0x12, 0xa, 0x16, 0x23, 0x1, 0x13, 0x1, 0x4, 0x80, 0x93, 0x1, 0x1, 0x20, 0x1a, 0x6, 0x1a, 0xb, 0xa, 0x1, 0x2d, 0x2, 0x40, 0x7, 0x1, 0x7, 0xa, 0x5, 0x81, 0x2, 0x3, 0x4, 0x2d, 0x3, 0x9, 0x50, 0xc, 0x34, 0x2d, 0xa0, 0xce, 0x3, 0x80, 0xf6, 0xa, 0x27, 0x2, 0x3e, 0x3, 0x11, 0x8, 0x2, 0x7, 0x1e, 0x4, 0x30, 0x81, 0x22, 0x57, 0x9, 0x12, 0x80, 0x8e, 0x55, 0x1, 0x47, 0x1, 0x2, 0x2, 0x1, 0x2, 0x2, 0x2, 0x4, 0x1, 0xc, 0x1, 0x1, 0x1, 0x7, 0x1, 0x41, 0x1, 0x4, 0x2, 0x8, 0x1, 0x7, 0x1, 0x1c, 0x1, 0x4, 0x1, 0x5, 0x1, 0x1, 0x3, 0x7, 0x1, 0x81, 0x54, 0x2, 0x81, 0x24, 0x2, 0x32, 0x98, 0x0, 0x2c, 0x4, 0x64, 0xc, 0xf, 0x2, 0xe, 0x2, 0xf, 0x1, 0xf, 0x20, 0xb, 0x5, 0x1f, 0x1, 0x3c, 0x4, 0x2b, 0x4b, 0x1a, 0x1, 0x2, 0xd, 0x2b, 0x5, 0x9, 0x7, 0x2, 0x80, 0xae, 0x21, 0xf, 0x6, 0x1, 0x46, 0x3, 0x14, 0xc, 0x25, 0x1, 0x5, 0x15, 0x11, 0xf, 0x3f, 0x1, 0x1, 0x1, 0x80, 0xb6, 0x1, 0x4, 0x3, 0x3e, 0x2, 0x4, 0xc, 0x18, 0x80, 0x93, 0x46, 0x4, 0xb, 0x30, 0x46, 0x3a, 0x74, 0xac, 0x8, 0x8d, 0x1, 0x1e, 0x60];
+_T Old_Italic = [0xa1, 0x3, 0x0, 0x1f, 0x1, 0x4];
+_T Old_Persian = [0xa1, 0x3, 0xa0, 0x24, 0x4, 0xe];
+_T Greek = [0x83, 0x70, 0x4, 0x1, 0x3, 0x2, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, 0x3, 0x1, 0x1, 0x1, 0x14, 0x1, 0x3f, 0xe, 0x10, 0x99, 0x26, 0x5, 0x32, 0x5, 0x4, 0x5, 0x54, 0x1, 0x81, 0x40, 0x16, 0x2, 0x6, 0x2, 0x26, 0x2, 0x6, 0x2, 0x8, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1f, 0x2, 0x35, 0x1, 0xf, 0x1, 0xe, 0x2, 0x6, 0x1, 0x13, 0x2, 0x3, 0x1, 0x9, 0x81, 0x27, 0x1, 0xa0, 0xe0, 0x19, 0x4b, 0xa0, 0xd0, 0x75, 0x46];
+_T Sundanese = [0x9b, 0x80, 0x40, 0x81, 0x0, 0x8];
+_T Syriac = [0x87, 0x0, 0xe, 0x1, 0x3c, 0x2, 0x3];
+_T Gurmukhi = [0x8a, 0x1, 0x3, 0x1, 0x6, 0x4, 0x2, 0x2, 0x16, 0x1, 0x7, 0x1, 0x2, 0x1, 0x2, 0x1, 0x2, 0x2, 0x1, 0x1, 0x5, 0x4, 0x2, 0x2, 0x3, 0x3, 0x1, 0x7, 0x4, 0x1, 0x1, 0x7, 0x10];
+_T Tibetan = [0x8f, 0x0, 0x48, 0x1, 0x24, 0x4, 0x27, 0x1, 0x24, 0x1, 0xf, 0x1, 0x7, 0x4, 0x2];
+_T Tamil = [0x8b, 0x82, 0x2, 0x1, 0x6, 0x3, 0x3, 0x1, 0x4, 0x3, 0x2, 0x1, 0x1, 0x1, 0x2, 0x3, 0x2, 0x3, 0x3, 0x3, 0xc, 0x4, 0x5, 0x3, 0x3, 0x1, 0x4, 0x2, 0x1, 0x6, 0x1, 0xe, 0x15];
+_T Telugu = [0x8c, 0x1, 0x3, 0x1, 0x8, 0x1, 0x3, 0x1, 0x17, 0x1, 0xa, 0x1, 0x5, 0x3, 0x8, 0x1, 0x3, 0x1, 0x4, 0x7, 0x2, 0x1, 0x2, 0x6, 0x4, 0x2, 0xa, 0x8, 0x8];
+_T Inscriptional_Parthian = [0xa1, 0xb, 0x40, 0x16, 0x2, 0x8];
+_T Nko = [0x87, 0xc0, 0x3b];
+_T Javanese = [0xa0, 0xa9, 0x80, 0x4e, 0x2, 0xa, 0x4, 0x2];
+_T Tai_Le = [0x99, 0x50, 0x1e, 0x2, 0x5];
+_T Old_South_Arabian = [0xa1, 0xa, 0x60, 0x20];
+_T Bamum = [0xa0, 0xa6, 0xa0, 0x58, 0xa0, 0xc1, 0x8, 0x82, 0x39];
+_T Chakma = [0xa1, 0x11, 0x0, 0x35, 0x1, 0xe];
+_T Ugaritic = [0xa1, 0x3, 0x80, 0x1e, 0x1, 0x1];
+_T Tagalog = [0x97, 0x0, 0xd, 0x1, 0x7];
+_T Tagbanwa = [0x97, 0x60, 0xd, 0x1, 0x3, 0x1, 0x2];
+_T Devanagari = [0x89, 0x0, 0x51, 0x2, 0x11, 0x2, 0x12, 0x1, 0x7, 0xa0, 0x9f, 0x60, 0x1c];
+_T Buginese = [0x9a, 0x0, 0x1c, 0x2, 0x2];
+_T Cuneiform = [0xa1, 0x20, 0x0, 0x83, 0x6f, 0x80, 0x91, 0x63, 0xd, 0x4];
+_T Cyrillic = [0x84, 0x0, 0x80, 0x85, 0x2, 0x80, 0xa1, 0x98, 0x3, 0x1, 0x4c, 0x1, 0x90, 0x67, 0x20, 0xa0, 0x78, 0x40, 0x58, 0x7, 0x1];
+_U[] _tab = [
+_U("Arabic", Arabic),
+_U("Armenian", Armenian),
+_U("Avestan", Avestan),
+_U("Balinese", Balinese),
+_U("Bamum", Bamum),
+_U("Batak", Batak),
+_U("Bengali", Bengali),
+_U("Bopomofo", Bopomofo),
+_U("Brahmi", Brahmi),
+_U("Braille", Braille),
+_U("Buginese", Buginese),
+_U("Buhid", Buhid),
+_U("Canadian_Aboriginal", Canadian_Aboriginal),
+_U("Carian", Carian),
+_U("Chakma", Chakma),
+_U("Cham", Cham),
+_U("Cherokee", Cherokee),
+_U("Common", Common),
+_U("Coptic", Coptic),
+_U("Cuneiform", Cuneiform),
+_U("Cypriot", Cypriot),
+_U("Cyrillic", Cyrillic),
+_U("Deseret", Deseret),
+_U("Devanagari", Devanagari),
+_U("Egyptian_Hieroglyphs", Egyptian_Hieroglyphs),
+_U("Ethiopic", Ethiopic),
+_U("Georgian", Georgian),
+_U("Glagolitic", Glagolitic),
+_U("Gothic", Gothic),
+_U("Greek", Greek),
+_U("Gujarati", Gujarati),
+_U("Gurmukhi", Gurmukhi),
+_U("Han", Han),
+_U("Hangul", Hangul),
+_U("Hanunoo", Hanunoo),
+_U("Hebrew", Hebrew),
+_U("Hiragana", Hiragana),
+_U("Imperial_Aramaic", Imperial_Aramaic),
+_U("Inherited", Inherited),
+_U("Inscriptional_Pahlavi", Inscriptional_Pahlavi),
+_U("Inscriptional_Parthian", Inscriptional_Parthian),
+_U("Javanese", Javanese),
+_U("Kaithi", Kaithi),
+_U("Kannada", Kannada),
+_U("Katakana", Katakana),
+_U("Kayah_Li", Kayah_Li),
+_U("Kharoshthi", Kharoshthi),
+_U("Khmer", Khmer),
+_U("Lao", Lao),
+_U("Latin", Latin),
+_U("Lepcha", Lepcha),
+_U("Limbu", Limbu),
+_U("Linear_B", Linear_B),
+_U("Lisu", Lisu),
+_U("Lycian", Lycian),
+_U("Lydian", Lydian),
+_U("Malayalam", Malayalam),
+_U("Mandaic", Mandaic),
+_U("Meetei_Mayek", Meetei_Mayek),
+_U("Meroitic_Cursive", Meroitic_Cursive),
+_U("Meroitic_Hieroglyphs", Meroitic_Hieroglyphs),
+_U("Miao", Miao),
+_U("Mongolian", Mongolian),
+_U("Myanmar", Myanmar),
+_U("New_Tai_Lue", New_Tai_Lue),
+_U("Nko", Nko),
+_U("Ogham", Ogham),
+_U("Ol_Chiki", Ol_Chiki),
+_U("Old_Italic", Old_Italic),
+_U("Old_Persian", Old_Persian),
+_U("Old_South_Arabian", Old_South_Arabian),
+_U("Old_Turkic", Old_Turkic),
+_U("Oriya", Oriya),
+_U("Osmanya", Osmanya),
+_U("Phags_Pa", Phags_Pa),
+_U("Phoenician", Phoenician),
+_U("Rejang", Rejang),
+_U("Runic", Runic),
+_U("Samaritan", Samaritan),
+_U("Saurashtra", Saurashtra),
+_U("Sharada", Sharada),
+_U("Shavian", Shavian),
+_U("Sinhala", Sinhala),
+_U("Sora_Sompeng", Sora_Sompeng),
+_U("Sundanese", Sundanese),
+_U("Syloti_Nagri", Syloti_Nagri),
+_U("Syriac", Syriac),
+_U("Tagalog", Tagalog),
+_U("Tagbanwa", Tagbanwa),
+_U("Tai_Le", Tai_Le),
+_U("Tai_Tham", Tai_Tham),
+_U("Tai_Viet", Tai_Viet),
+_U("Takri", Takri),
+_U("Tamil", Tamil),
+_U("Telugu", Telugu),
+_U("Thaana", Thaana),
+_U("Thai", Thai),
+_U("Tibetan", Tibetan),
+_U("Tifinagh", Tifinagh),
+_U("Ugaritic", Ugaritic),
+_U("Vai", Vai),
+_U("Yi", Yi),
+];
+}
+
+struct hangul
+{
+private alias _U = immutable(UnicodeProperty);
+@property static _U[] tab() { return _tab; }
+static immutable:
+private alias _T = ubyte[];
+_T LVT = [0xa0, 0xac, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b];
+_T T = [0x91, 0xa8, 0x58, 0xa0, 0xc5, 0xcb, 0x31];
+_T V = [0x91, 0x60, 0x48, 0xa0, 0xc6, 0x8, 0x17];
+_T LV = [0xa0, 0xac, 0x0, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1, 0x1b, 0x1];
+_T L = [0x91, 0x0, 0x60, 0xa0, 0x98, 0x0, 0x1d];
+_U[] _tab = [
+_U("L", L),
+_U("Leading_Jamo", L),
+_U("LV", LV),
+_U("LV_Syllable", LV),
+_U("LVT", LVT),
+_U("LVT_Syllable", LVT),
+_U("T", T),
+_U("Trailing_Jamo", T),
+_U("V", V),
+_U("Vowel_Jamo", V),
+];
+}
+bool isFormatGen(dchar ch) @safe pure nothrow
+{
+    if(ch < 8288)
+    {
+        if(ch < 1807)
+        {
+            if(ch < 1564)
+            {
+                if(ch == 173) return true;
+                if(ch < 1536) return false;
+                if(ch < 1541) return true;
+                return false;
+            }
+            else if (ch < 1565) return true;
+            else
+            {
+                if(ch == 1757) return true;
+                return false;
+            }
+        }
+        else if (ch < 1808) return true;
+        else
+        {
+            if(ch < 8203)
+            {
+                if(ch == 6158) return true;
+                return false;
+            }
+            else if (ch < 8208) return true;
+            else
+            {
+                if(ch < 8234) return false;
+                if(ch < 8239) return true;
+                return false;
+            }
+        }
+    }
+    else if (ch < 8293) return true;
+    else
+    {
+        if(ch < 69821)
+        {
+            if(ch < 65279)
+            {
+                if(ch < 8294) return false;
+                if(ch < 8304) return true;
+                return false;
+            }
+            else if (ch < 65280) return true;
+            else
+            {
+                if(ch < 65529) return false;
+                if(ch < 65532) return true;
+                return false;
+            }
+        }
+        else if (ch < 69822) return true;
+        else
+        {
+            if(ch < 917505)
+            {
+                if(ch < 119155) return false;
+                if(ch < 119163) return true;
+                return false;
+            }
+            else if (ch < 917506) return true;
+            else
+            {
+                if(ch < 917536) return false;
+                if(ch < 917632) return true;
+                return false;
+            }
+        }
+    }
+}
+
+bool isControlGen(dchar ch) @safe pure nothrow
+{
+    if(ch < 32) return true;
+    if(ch < 127) return false;
+    if(ch < 160) return true;
+    return false;
+}
+
+bool isSpaceGen(dchar ch) @safe pure nothrow
+{
+    if(ch < 160)
+    {
+        if(ch == 32) return true;
+        return false;
+    }
+    else if (ch < 161) return true;
+    else
+    {
+        if(ch < 8239)
+        {
+            if(ch == 5760) return true;
+            if(ch < 8192) return false;
+            if(ch < 8203) return true;
+            return false;
+        }
+        else if (ch < 8240) return true;
+        else
+        {
+            if(ch == 8287) return true;
+            if(ch == 12288) return true;
+            return false;
+        }
+    }
+}
+
+bool isWhiteGen(dchar ch) @safe pure nothrow
+{
+    if(ch < 133)
+    {
+        if(ch < 9) return false;
+        if(ch < 14) return true;
+        if(ch == 32) return true;
+        return false;
+    }
+    else if (ch < 134) return true;
+    else
+    {
+        if(ch < 8232)
+        {
+            if(ch < 5760)
+            {
+                if(ch == 160) return true;
+                return false;
+            }
+            else if (ch < 5761) return true;
+            else
+            {
+                if(ch < 8192) return false;
+                if(ch < 8203) return true;
+                return false;
+            }
+        }
+        else if (ch < 8234) return true;
+        else
+        {
+            if(ch < 8287)
+            {
+                if(ch == 8239) return true;
+                return false;
+            }
+            else if (ch < 8288) return true;
+            else
+            {
+                if(ch == 12288) return true;
+                return false;
+            }
+        }
+    }
+}
+
+bool isHangL(dchar ch) @safe pure nothrow
+{
+    if(ch < 4352) return false;
+    if(ch < 4448) return true;
+    if(ch < 43360) return false;
+    if(ch < 43389) return true;
+    return false;
+}
+
+bool isHangV(dchar ch) @safe pure nothrow
+{
+    if(ch < 4448) return false;
+    if(ch < 4520) return true;
+    if(ch < 55216) return false;
+    if(ch < 55239) return true;
+    return false;
+}
+
+bool isHangT(dchar ch) @safe pure nothrow
+{
+    if(ch < 4520) return false;
+    if(ch < 4608) return true;
+    if(ch < 55243) return false;
+    if(ch < 55292) return true;
+    return false;
+}
+
+
+static if(size_t.sizeof == 8) {
+//1536 bytes
+enum lowerCaseTrieEntries = TrieEntry!(bool, 8, 4, 9)([ 0x0,  0x20,  0x40], [ 0x100,  0x80,  0x2000], [ 0x402030202020100,  0x206020202020205,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3000200010000,  0x3000300030003,  0x3000300030003,  0x5000400030003,  0x3000700030006,  0x3000800030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x9000300030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0xb0003000a0003,  0x3000c00030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0xe000d00030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x0,  0x7fffffe00000000,  0x420040000000000,  0xff7fffff80000000,  0x55aaaaaaaaaaaaaa,  0xd4aaaaaaaaaaab55,  0xe6512d2a4e243129,  0xaa29aaaab5555240,  0x93faaaaaaaaaaaaa,  0xffffffffffffaa85,  0x1ffffffffefffff,  0x1f00000003,  0x0,  0x3c8a000000000020,  0xfffff00000010000,  0x192faaaaaae37fff,  0xffff000000000000,  0xaaaaaaaaffffffff,  0xaaaaaaaaaaaaa802,  0xaaaaaaaaaaaad554,  0xaaaaaaaaaa,  0xfffffffe00000000,  0xff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x0,  0xaaaaaaaaaaaaaaaa,  0xaaaaaaaaaaaaaaaa,  0xaaaaaaaabfeaaaaa,  0xaaaaaaaaaaaaaaaa,  0xff00ff003f00ff,  0x3fff00ff00ff003f,  0x40df00ff00ff00ff,  0xdc00ff00cf00dc,  0x0,  0x8002000000000000,  0x1fff0000,  0x0,  0x321080000008c400,  0xffff0000000043c0,  0x10,  0x0,  0x0,  0x0,  0x0,  0x3ffffff0000,  0x0,  0x0,  0x0,  0x0,  0xffff000000000000,  0x3fda15627fffffff,  0xaaaaaaaaaaaaaaaa,  0x8501aaaaaaaaa,  0x20bfffffffff,  0x0,  0x0,  0x0,  0x0,  0x2aaaaaaaaaaa,  0xaaaaaa,  0x0,  0xaaabaaa800000000,  0x95ffaaaaaaaaaaaa,  0x2aa000a50aa,  0x700000000000000,  0x0,  0x0,  0x0,  0x0,  0xf8007f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7fffffe,  0x0,  0x0,  0xffffff0000000000,  0xffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffc000000,  0xffffdfc000,  0xebc000000ffffffc,  0xfffffc000000ffef,  0xffffffc000000f,  0xffffffc0000,  0xfc000000ffffffc0,  0xffffc000000fffff,  0xffffffc000000ff,  0xffffffc00000,  0x3ffffffc00,  0xf0000003f7fffffc,  0xffc000000fdfffff,  0xffff0000003f7fff,  0xfffffc000000fdff,  0xbf7,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//1472 bytes
+enum upperCaseTrieEntries = TrieEntry!(bool, 8, 4, 9)([ 0x0,  0x20,  0x40], [ 0x100,  0x80,  0x1e00], [ 0x402030202020100,  0x206020202020205,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3000200010000,  0x3000300030003,  0x3000300030004,  0x5000300030003,  0x3000700030006,  0x3000800030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x9000300030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0xa000300030003,  0x3000b00030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0xd000c00030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x3000300030003,  0x0,  0x7fffffe,  0x0,  0x7f7fffff,  0xaa55555555555555,  0x2b555555555554aa,  0x11aed2d5b1dbced6,  0x55d255554aaaa490,  0x6c05555555555555,  0x557a,  0x0,  0x0,  0x0,  0x45000000000000,  0xffbfffed740,  0xe6905555551c8000,  0xffffffffffff,  0x5555555500000000,  0x5555555555555401,  0x5555555555552aab,  0xfffe005555555555,  0x7fffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff00000000,  0x20bf,  0x0,  0x0,  0x0,  0x0,  0x5555555555555555,  0x5555555555555555,  0x5555555540155555,  0x5555555555555555,  0xff00ff003f00ff00,  0xff00aa003f00,  0xf00000000000000,  0xf001f000f000f00,  0x0,  0x0,  0x0,  0x0,  0xc00f3d503e273884,  0xffff00000020,  0x8,  0x0,  0x0,  0x0,  0xffc0000000000000,  0xffff,  0x0,  0x0,  0x0,  0x0,  0x7fffffffffff,  0xc025ea9d00000000,  0x5555555555555555,  0x4280555555555,  0x0,  0x0,  0x0,  0x0,  0x0,  0x155555555555,  0x555555,  0x0,  0x5554555400000000,  0x6a00555555555555,  0x55500052855,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7fffffe00000000,  0x0,  0x0,  0x0,  0xffffffffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xfff0000003ffffff,  0xffffff0000003fff,  0x3fde64d0000003,  0x3ffffff0000,  0x7b0000001fdfe7b0,  0xfffff0000001fc5f,  0x3ffffff0000003f,  0x3ffffff00000,  0xf0000003ffffff00,  0xffff0000003fffff,  0xffffff00000003ff,  0x7fffffc00000001,  0x1ffffff0000000,  0x7fffffc00000,  0x1ffffff0000,  0x400,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//8704 bytes
+enum simpleCaseTrieEntries = TrieEntry!(ushort, 8, 7, 6)([ 0x0,  0x20,  0x100], [ 0x100,  0x380,  0xd00], [ 0x402030202020100,  0x202020202020205,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x3000200010000,  0x7000600050004,  0xa00090008,  0xd000c000b0000,  0x110010000f000e,  0x1400130012,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x16001500000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x170000,  0x1b001a00190018,  0x1f001e001d001c,  0x0,  0x2200210020,  0x0,  0x0,  0x24002300000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x28002700260025,  0x29,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2b002a0000,  0x2e002d002c,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x30002f,  0x0,  0x0,  0x0,  0x0,  0x320031,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x2400220020ffff,  0x2c002a00280026,  0x72f00320030002e,  0x3d003b00390037,  0x1b000430041003f,  0x4e004c004a0048,  0xffff005400520050,  0xffffffffffffffff,  0x2500230021ffff,  0x2d002b00290027,  0x73000330031002f,  0x3e003c003a0038,  0x1b1004400420040,  0x4f004d004b0049,  0xffff005500530051,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff043fffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xcc049800c800c6,  0xd500d3014904aa,  0xdd00db00d900d7,  0xe500e300e100df,  0xed00eb00e900e7,  0xffff00f300f100ef,  0xfb00f900f700f5,  0x6be010100ff00fd,  0xcd049900c900c7,  0xd600d4014a04ab,  0xde00dc00da00d8,  0xe600e400e200e0,  0xee00ec00ea00e8,  0xffff00f400f200f0,  0xfc00fa00f800f6,  0x1a80102010000fe,  0x118011701160115,  0x11e011d011c011b,  0x12401230120011f,  0x128012701260125,  0x12e012d012c012b,  0x13401330130012f,  0x138013701360135,  0x13c013b013a0139,  0x140013f013e013d,  0x144014301420141,  0x148014701460145,  0x14f014e014d014c,  0x1510150ffffffff,  0x155015401530152,  0x15801570156ffff,  0x15e015d015c0159,  0x16201610160015f,  0x166016501640163,  0x1690168ffff0167,  0x16d016c016b016a,  0x1710170016f016e,  0x175017401730172,  0x179017801770176,  0x17d017c017b017a,  0x1830182017f017e,  0x18b018a01870186,  0x1930192018f018e,  0x19b019a01970196,  0x1a301a2019f019e,  0x1a701a601a501a4,  0x1ac01ab01aa01a9,  0x1b201af01ae01ad,  0x1b601b501b3028b,  0x1bd01bb01ba01b9,  0x1c301c101bf01be,  0x1c701c5ffff01c4,  0x1cd01cc01cb01c9,  0x1d301d1023b01cf,  0xffff028301d601d5,  0x1db026901d901d7,  0x1e001df01de01dd,  0x1e501e301e201e1,  0xffffffff01e701e6,  0x1ed01eb01ea01e9,  0x1f301f101ef01ee,  0x1f701f601f501f4,  0xffffffff01fa01f9,  0x23dffff01fc01fb,  0xffffffffffffffff,  0x206020202010200,  0x20d020c02080207,  0x2110210020f020e,  0x215021402130212,  0x219021802170216,  0x21d021c021b021a,  0x220021f01c6021e,  0x226022502240223,  0x22a022902280227,  0x22e022d022c022b,  0x23202310230022f,  0x23802370236ffff,  0x23e023c023a0239,  0x24402430240023f,  0x248024702460245,  0x24c024b024a0249,  0x250024f024e024d,  0x254025302520251,  0x258025702560255,  0x25c025b025a0259,  0x260025f025e025d,  0x264026302620261,  0x268026702660265,  0x26c026bffff026a,  0x270026f026e026d,  0x274027302720271,  0x278027702760275,  0x27c027b027a0279,  0xffffffffffffffff,  0x281027fffffffff,  0x2d7028502840282,  0x28c028802870482,  0x2920291028f028d,  0x296029502940293,  0x29c029b02980297,  0x1b402b70466046a,  0x1c201c0ffff01bc,  0x1caffff01c8ffff,  0xffffffffffffffff,  0x1d0ffffffff01ce,  0xffff05fa0748ffff,  0x528ffff01d201d4,  0x1d8ffffffffffff,  0xffff01da02b3ffff,  0xffffffff01dcffff,  0xffffffffffffffff,  0xffffffff02a3ffff,  0x1e8ffffffff01e4,  0xffffffffffffffff,  0x1f201f0028e01ec,  0xffffffffffff0290,  0xffff01f8ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff083affff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x320031f031e031d,  0x3240323ffffffff,  0x3d5ffffffffffff,  0xffffffff03d903d7,  0xffffffffffffffff,  0xffff0329ffffffff,  0xffff0331032f032d,  0x3370335ffff0333,  0x33e03950339ffff,  0x347034503cc0340,  0x35403c2083b03c8,  0x35d035b03590440,  0x388ffff03c5039f,  0x36f039c036a0368,  0x378037607100371,  0x3320330032e032a,  0x33f0396033affff,  0x348034603cd0341,  0x35503c3083c03c9,  0x35e035c035a0441,  0x38a038903c603a0,  0x370039d036b0369,  0x379037707110372,  0x393033803360334,  0xffffffff03ca0397,  0x39403a1039effff,  0x3a703a603a303a2,  0x3ab03aa03a903a8,  0x3af03ae03ad03ac,  0x3b503b403b103b0,  0x3bd03bc03b903b8,  0x3c103c003bf03be,  0xffff03d103c703c4,  0x3cfffff03ce03cb,  0x3d403d303d203d0,  0x3da03d803d6ffff,  0x3e103df03dd03db,  0x3e903e703e503e3,  0x3f103ef03ed03eb,  0x3f903f703f503f3,  0x40103ff03fd03fb,  0x409040704050403,  0x411040f040d040b,  0x419041704150413,  0x421041f041d041b,  0x429042704250423,  0x431042f042d042b,  0x439043704350433,  0x402040003fe03fc,  0x40a040804060404,  0x4120410040e040c,  0x41a041804160414,  0x4220420041e041c,  0x42a042804260424,  0x4320430042e042c,  0x43a043804360434,  0x3e203e003de03dc,  0x3ea03e803e603e4,  0x3f203f003ee03ec,  0x3fa03f803f603f4,  0x453045204510450,  0x459045804570456,  0x4610460045d045c,  0x469046804650464,  0x4710470046d046c,  0x477047604730472,  0x47b047a04790478,  0x4810480047d047c,  0xffffffff04850484,  0xffffffffffffffff,  0x4950494ffffffff,  0x49b049a04970496,  0x49f049e049d049c,  0x4a704a604a304a2,  0x4ad04ac04a904a8,  0x4b304b204b104b0,  0x4b904b804b704b6,  0x4bf04be04bb04ba,  0x4c504c404c104c0,  0x4cd04cc04c904c8,  0x4d304d204cf04ce,  0x4d704d604d504d4,  0x4df04de04db04da,  0x4e704e604e304e2,  0x4f004ed04ec04ea,  0x4f804f504f404f1,  0x50004fd04fc04f9,  0x4eb050505040501,  0x50d050c050b050a,  0x5130512050f050e,  0x519051805170516,  0x51f051e051d051c,  0x525052405210520,  0x52b052a05270526,  0x52f052e052d052c,  0x537053605330532,  0x53d053c05390538,  0x5410540053f053e,  0x547054605430542,  0x54b054a05490548,  0x54f054e054d054c,  0x555055405510550,  0x559055805570556,  0x55d055c055b055a,  0x5630562055f055e,  0x567056605650564,  0x56b056a05690568,  0x5730572056f056e,  0x577057605750574,  0x57b057a05790578,  0xffffffffffffffff,  0xffffffffffffffff,  0x58405820580ffff,  0x58c058a05880586,  0x59405920590058e,  0x59c059a05980596,  0x5a405a205a0059e,  0x5ac05aa05a805a6,  0x5b405b205b005ae,  0x5bc05ba05b805b6,  0x5c405c205c005be,  0xffff05ca05c805c6,  0xffffffffffffffff,  0xffffffffffffffff,  0x58505830581ffff,  0x58d058b05890587,  0x59505930591058f,  0x59d059b05990597,  0x5a505a305a1059f,  0x5ad05ab05a905a7,  0x5b505b305b105af,  0x5bd05bb05b905b7,  0x5c505c305c105bf,  0xffff05cb05c905c7,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x8c008a00880086,  0x9400920090008e,  0x9c009a00980096,  0xa400a200a0009e,  0xac00aa00a800a6,  0xb400b200b000ae,  0xbc00ba00b800b6,  0xc400c200c000be,  0x4a000ca048e0486,  0x4c6ffff04b400ce,  0xffffffffffffffff,  0xffffffff0508ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff07e8ffff,  0xffffffff0454ffff,  0x5ff05fe05fd05fc,  0x605060406010600,  0x60b060a06090608,  0x6110610060f060e,  0x617061606130612,  0x61d061c06190618,  0x6210620061f061e,  0x627062606230622,  0x62b062a06290628,  0x62f062e062d062c,  0x635063406310630,  0x639063806370636,  0x63d063c063b063a,  0x6430642063f063e,  0x647064606450644,  0x64b064a06490648,  0x6510650064d064c,  0x655065406530652,  0x65d065c06590658,  0x6630662065f065e,  0x667066606650664,  0x66b066a06690668,  0x6710670066d066c,  0x675067406730672,  0x67a067906bc06bb,  0x680067f067c067b,  0x684068306820681,  0x688068706860685,  0x68e068d068a0689,  0x69206910690068f,  0x698069706960695,  0x69e069d069a0699,  0x6a206a106a0069f,  0x6a606a506a406a3,  0x6ac06ab06a806a7,  0x6b006af06ae06ad,  0x6b406b306b206b1,  0xffffffff06b606b5,  0x6bdffffffffffff,  0xffff06bfffffffff,  0x6c306c206c106c0,  0x6c906c806c506c4,  0x6cd06cc06cb06ca,  0x6d106d006cf06ce,  0x6d706d606d506d4,  0x6dd06dc06db06da,  0x6e106e006df06de,  0x6e506e406e306e2,  0x6eb06ea06e906e8,  0x6f106f006ef06ee,  0x6f506f406f306f2,  0x6f906f806f706f6,  0x6fd06fc06fb06fa,  0x701070006ff06fe,  0x705070407030702,  0x709070807070706,  0x70d070c070b070a,  0x7140713070f070e,  0x718071707160715,  0x71e071d071c071b,  0x72207210720071f,  0x726072507240723,  0x72a072907280727,  0x7330732072e072d,  0x73c073a07380736,  0x74407420740073e,  0x73d073b07390737,  0x74507430741073f,  0x750074e074c074a,  0xffffffff07540752,  0x751074f074d074b,  0xffffffff07550753,  0x76a076807660764,  0x7720770076e076c,  0x76b076907670765,  0x7730771076f076d,  0x78a078807860784,  0x7920790078e078c,  0x78b078907870785,  0x7930791078f078d,  0x7a207a0079e079c,  0xffffffff07a607a4,  0x7a307a1079f079d,  0xffffffff07a707a5,  0x7baffff07b6ffff,  0x7c2ffff07beffff,  0x7bbffff07b7ffff,  0x7c3ffff07bfffff,  0x7d607d407d207d0,  0x7de07dc07da07d8,  0x7d707d507d307d1,  0x7df07dd07db07d9,  0x840083e08360834,  0x84e084c08440842,  0x858085608620860,  0xffffffff08660864,  0x7fa07f807f607f4,  0x802080007fe07fc,  0x7fb07f907f707f5,  0x803080107ff07fd,  0x80e080c080a0808,  0x816081408120810,  0x80f080d080b0809,  0x817081508130811,  0x826082408220820,  0x82e082c082a0828,  0x827082508230821,  0x82f082d082b0829,  0x838ffff08320830,  0xffffffffffffffff,  0x837083508330831,  0xffff083dffff0839,  0x846ffffffffffff,  0xffffffffffffffff,  0x84508430841083f,  0xffffffffffff0847,  0xffffffff084a0848,  0xffffffffffffffff,  0x84f084d084b0849,  0xffffffffffffffff,  0xffffffff08540852,  0xffffffff085affff,  0x859085708550853,  0xffffffffffff085b,  0x868ffffffffffff,  0xffffffffffffffff,  0x867086508630861,  0xffffffffffff0869,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff0712ffffffff,  0x14b0731ffffffff,  0xffffffffffffffff,  0xffff0530ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff0531ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x18402af0180029f,  0x18c005e018802c1,  0x194006c01900064,  0x19c007e01980076,  0x18502b0018102a0,  0x18d005f018902c2,  0x195006d01910065,  0x19d007f01990077,  0x1b7ffffffffffff,  0xffffffffffff01b8,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x4d80444ffffffff,  0x4e0044c04dc0446,  0x4e8047404e4045e,  0x204ee02d3086a,  0x6e04f606c604f2,  0x10d04fe037a04fa,  0x51a0506061a0502,  0x4dd044704d90445,  0x4e5045f04e1044d,  0x2d4086b04e90475,  0x6c704f3000304ef,  0x37b04fb006f04f7,  0x61b0503010e04ff,  0xffffffff051b0507,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xa000800040000,  0x160010000e000c,  0x2bb001c001a0018,  0x5602e702d102c7,  0x66006200600058,  0x7800740070006a,  0x29900820080007c,  0x6020084000607e0,  0x5d005ce02a7057c,  0x1070105010305de,  0x1190113010f0109,  0xffff013101290121,  0xb000900050001,  0x170011000f000d,  0x2bc001d001b0019,  0x5702e802d202c8,  0x67006300610059,  0x7900750071006b,  0x29a00830081007d,  0x6030085000707e1,  0x5d105cf02a8057d,  0x1080106010405df,  0x11a01140110010a,  0xffff0132012a0122,  0x455052904c304c2,  0x45a0286028002a4,  0x46202aa02a9045b,  0x46b02b404670463,  0x2ba02b9ffff02b8,  0xffff02c002bfffff,  0xffffffffffffffff,  0x48302d8ffffffff,  0x489048802e202e1,  0x48d048c048b048a,  0x2fe02fd04910490,  0x30e030d03040303,  0x31a031903160315,  0x328032703260325,  0x6ed06ec02fc02fb,  0x383038203810380,  0x392039103870386,  0x3b303b203a503a4,  0x5cd05cc056d056c,  0x5ed05ec05db05da,  0x6570656060d060c,  0x6e706e6043e043d,  0x7830782072c072b,  0x694069307e307e2,  0x150014065b065a,  0x4bd04bc005d005c,  0x5d505d404d104d0,  0x511051001a101a0,  0x535053405230522,  0x553055205450544,  0x571057005610560,  0x15b015a057f057e,  0x3bb03ba037d037c,  0xffffffffffffffff,  0x5d2ffffffffffff,  0xffff05d905d805d3,  0x5e305e2ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x8d008b00890087,  0x9500930091008f,  0x9d009b00990097,  0xa500a300a1009f,  0xad00ab00a900a7,  0xb500b300b100af,  0xbd00bb00b900b7,  0xc500c300c100bf,  0x4a100cb048f0487,  0x4c7ffff04b500cf,  0xffffffffffffffff,  0xffffffff0509ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x5d705d602c402c3,  0x5e105e005dd05dc,  0x5e905e805e705e6,  0x5ef05ee05eb05ea,  0x5f505f405f105f0,  0x308030705f905f8,  0x625062406150614,  0x641064006330632,  0x6610660064f064e,  0x67e067d066f066e,  0x69c069b068c068b,  0xffffffff06aa06a9,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x69006807350734,  0x75f075e027e027d,  0x390038f07770776,  0x7b107b0001f001e,  0x2a202a107c707c6,  0x6b806b707e507e4,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x7590758ffffffff,  0x7610760075d075c,  0x2e002df02d602d5,  0x2ee02ed02e602e5,  0x7790778ffffffff,  0x7810780077d077c,  0x3140313030c030b,  0x322032103180317,  0x797079607950794,  0x79b079a07990798,  0x3850384037f037e,  0x7a907a8038e038d,  0x7ad07ac07ab07aa,  0x7b307b207af07ae,  0x7b907b807b507b4,  0x7c107c007bd07bc,  0x7c907c807c507c4,  0x7cf07ce07cd07cc,  0x47f047e046f046e,  0x4a504a404930492,  0xffffffffffffffff,  0xffffffffffffffff,  0x7e605150514ffff,  0x7eb07ea07e907e7,  0x7ef07ee07ed07ec,  0x7f307f207f107f0,  0x5f2ffffffffffff,  0xffffffff074905f3,  0x807080608050804,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x81b081a08190818,  0x81f081e081d081c,  0xffff05fb05f705f6,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x75a02c50756ffff,  0x76202cf02cd02cb,  0x2e3071902db06d2,  0x2f107ca02e90448,  0x77a02f502f30774,  0x3050221077e02f9,  0xffff043b030f007a,  0xffffffffffffffff,  0x75b02c60757ffff,  0x76302d002ce02cc,  0x2e4071a02dc06d3,  0x2f207cb02ea0449,  0x77b02f602f40775,  0x3060222077f02fa,  0xffff043c0310007b,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x72005a085c0012,  0x11106b9032b0311,  0x2dd029d02ab05e4,  0x10b060602ef085e,  0x4ca028902d902a5,  0x2c902bd02b502ad,  0x30902f702eb0746,  0x38b02b10241031b,  0x442053a044a03b6,  0x85004ae06d8044e,  0x73005b085d0013,  0x11206ba032c0312,  0x2de029e02ac05e5,  0x10c060702f0085f,  0x4cb028a02da02a6,  0x2ca02be02b602ae,  0x30a02f802ec0747,  0x38c02b20242031c,  0x443053b044b03b7,  0x85104af06d9044f,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff]);
+//8832 bytes
+enum fullCaseTrieEntries = TrieEntry!(ushort, 8, 7, 6)([ 0x0,  0x20,  0x100], [ 0x100,  0x380,  0xd40], [ 0x402030202020100,  0x202020202020205,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x3000200010000,  0x7000600050004,  0xa00090008,  0xd000c000b0000,  0x110010000f000e,  0x1400130012,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x16001500000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x170000,  0x1b001a00190018,  0x1f001e001d001c,  0x0,  0x2200210020,  0x0,  0x0,  0x24002300000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x28002700260025,  0x29,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2b002a0000,  0x2e002d002c,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2f,  0x0,  0x0,  0x0,  0x310030,  0x0,  0x0,  0x0,  0x0,  0x330032,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x2400220020ffff,  0x2c002a00280026,  0x78100320030002e,  0x3d003b00390037,  0x1b900430041003f,  0x4e004c004a0048,  0xffff005400520050,  0xffffffffffffffff,  0x2500230021ffff,  0x2d002b00290027,  0x78200330031002f,  0x3e003c003a0038,  0x1ba004400420040,  0x4f004d004b0049,  0xffff005500530051,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff0470ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xcc04c900c800c6,  0xd500d3014e04db,  0xdd00db00d900d7,  0xe500e300e100df,  0xed00eb00e900e7,  0xffff00f300f100ef,  0xfb00f900f700f5,  0x70f010100ff00fd,  0xcd04ca00c900c7,  0xd600d4014f04dc,  0xde00dc00da00d8,  0xe600e400e200e0,  0xee00ec00ea00e8,  0xffff00f400f200f0,  0xfc00fa00f800f6,  0x1b10102010000fe,  0x11b011a01190118,  0x1210120011f011e,  0x127012601230122,  0x12b012a01290128,  0x1310130012f012e,  0x137013601330132,  0x13b013a01390138,  0x13f013e013d013c,  0x143014201410140,  0x149014801470146,  0x14d014c014b014a,  0x154015301520151,  0x1580157ffff0155,  0x15c015b015a0159,  0x15f015e015dffff,  0x165016401630160,  0x169016801670166,  0x16d016c016b016a,  0x1720171016f016e,  0x176017501740173,  0x17a017901780177,  0x17e017d017c017b,  0x18201810180017f,  0x186018501840183,  0x18c018b01880187,  0x19401930190018f,  0x19c019b01980197,  0x1a401a301a0019f,  0x1ac01ab01a801a7,  0x1b001af01ae01ad,  0x1b501b401b301b2,  0x1bb01b801b701b6,  0x1bf01be01bc029c,  0x1c601c401c301c2,  0x1cc01ca01c801c7,  0x1d001ceffff01cd,  0x1d601d501d401d2,  0x1dc01da024801d8,  0xffff029401df01de,  0x1e6027801e201e0,  0x1eb01ea01e901e8,  0x1f001ee01ed01ec,  0xffffffff01f201f1,  0x1f801f601f501f4,  0x1fe01fc01fa01f9,  0x2020201020001ff,  0xffffffff02050204,  0x24affff02070206,  0xffffffffffffffff,  0x211020d020c020b,  0x218021702130212,  0x21c021b021a0219,  0x220021f021e021d,  0x224022302220221,  0x228022702260225,  0x22b022a01cf0229,  0x2310230022f022e,  0x235023402330232,  0x239023802370236,  0x23d023c023b023a,  0x24502440243023e,  0x24b024902470246,  0x2510250024d024c,  0x255025402530252,  0x259025802570256,  0x25d025c025b025a,  0x263026202610260,  0x267026602650264,  0x26b026a02690268,  0x26f026e026d026c,  0x273027202710270,  0x277027602750274,  0x27b027affff0279,  0x27f027e027d027c,  0x285028402810280,  0x289028802870286,  0x28d028c028b028a,  0xffffffffffffffff,  0x2920290ffffffff,  0x2ec029602950293,  0x29d0299029804b3,  0x2a302a202a0029e,  0x2a702a602a502a4,  0x2ad02ac02a902a8,  0x1bd02ca0497049b,  0x1cb01c9ffff01c5,  0x1d3ffff01d1ffff,  0xffffffffffffffff,  0x1d9ffffffff01d7,  0xffff0643079affff,  0x559ffff01db01dd,  0x1e1ffffffffffff,  0xffff01e302c6ffff,  0xffffffff01e7ffff,  0xffffffffffffffff,  0xffffffff02b4ffff,  0x1f3ffffffff01ef,  0xffffffffffffffff,  0x1fd01fb029f01f7,  0xffffffffffff02a1,  0xffff0203ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff08e4ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x347034603450344,  0x34b034affffffff,  0x406ffffffffffff,  0xffffffff040a0408,  0xffffffffffffffff,  0xffff0350ffffffff,  0xffff035803560354,  0x35e035cffff035a,  0x36803c203630902,  0x371036f03fd036a,  0x37e03f308e503f9,  0x387038503830471,  0x3b5ffff03f603cc,  0x39903c903940392,  0x3a203a00762039b,  0x359035703550351,  0x36903c303640915,  0x372037003fe036b,  0x37f03f408e603fa,  0x388038603840472,  0x3b703b603f703cd,  0x39a03ca03950393,  0x3a303a10763039c,  0x3c0035f035d035b,  0xffffffff03fb03c4,  0x3c103ce03cbffff,  0x3d403d303d003cf,  0x3d803d703d603d5,  0x3de03dd03da03d9,  0x3e403e303e003df,  0x3ec03eb03e803e7,  0x3f203f103ee03ed,  0xffff040203f803f5,  0x400ffff03ff03fc,  0x405040404030401,  0x40b04090407ffff,  0x4120410040e040c,  0x41a041804160414,  0x4220420041e041c,  0x42a042804260424,  0x4320430042e042c,  0x43a043804360434,  0x4420440043e043c,  0x44a044804460444,  0x4520450044e044c,  0x45a045804560454,  0x4620460045e045c,  0x46a046804660464,  0x4330431042f042d,  0x43b043904370435,  0x4430441043f043d,  0x44b044904470445,  0x4530451044f044d,  0x45b045904570455,  0x4630461045f045d,  0x46b046904670465,  0x4130411040f040d,  0x41b041904170415,  0x4230421041f041d,  0x42b042904270425,  0x484048304820481,  0x48a048904880487,  0x4920491048e048d,  0x49a049904960495,  0x4a204a1049e049d,  0x4a804a704a404a3,  0x4ac04ab04aa04a9,  0x4b204b104ae04ad,  0xffffffff04b604b5,  0xffffffffffffffff,  0x4c604c5ffffffff,  0x4cc04cb04c804c7,  0x4d004cf04ce04cd,  0x4d804d704d404d3,  0x4de04dd04da04d9,  0x4e404e304e204e1,  0x4ea04e904e804e7,  0x4f004ef04ec04eb,  0x4f604f504f204f1,  0x4fe04fd04fa04f9,  0x5040503050004ff,  0x508050705060505,  0x510050f050c050b,  0x518051705140513,  0x521051e051d051b,  0x529052605250522,  0x531052e052d052a,  0x51c053605350532,  0x53e053d053c053b,  0x54405430540053f,  0x54a054905480547,  0x550054f054e054d,  0x556055505520551,  0x55c055b05580557,  0x560055f055e055d,  0x568056705640563,  0x56e056d056a0569,  0x57205710570056f,  0x578057705740573,  0x57c057b057a0579,  0x5820581057e057d,  0x588058705840583,  0x58c058b058a0589,  0x5920591058e058d,  0x598059705940593,  0x59c059b059a0599,  0x5a205a1059e059d,  0x5aa05a905a605a5,  0x5ae05ad05ac05ab,  0x5b405b305b005af,  0xffffffffffffffff,  0xffffffffffffffff,  0x5bd05bb05b9ffff,  0x5c505c305c105bf,  0x5cd05cb05c905c7,  0x5d505d305d105cf,  0x5dd05db05d905d7,  0x5e505e305e105df,  0x5ed05eb05e905e7,  0x5f505f305f105ef,  0x5fd05fb05f905f7,  0xffff0603060105ff,  0xffffffffffffffff,  0xffffffffffffffff,  0x5be05bc05baffff,  0x5c605c405c205c0,  0x5ce05cc05ca05c8,  0x5d605d405d205d0,  0x5de05dc05da05d8,  0x5e605e405e205e0,  0x5ee05ec05ea05e8,  0x5f605f405f205f0,  0x5fe05fc05fa05f8,  0x613060406020600,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x8c008a00880086,  0x9400920090008e,  0x9c009a00980096,  0xa400a200a0009e,  0xac00aa00a800a6,  0xb400b200b000ae,  0xbc00ba00b800b6,  0xc400c200c000be,  0x4d100ca04bf04b7,  0x4f7ffff04e500ce,  0xffffffffffffffff,  0xffffffff0539ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff083affff,  0xffffffff0485ffff,  0x648064706460645,  0x64e064d064a0649,  0x654065306520651,  0x65a065906580657,  0x660065f065c065b,  0x666066506620661,  0x66a066906680667,  0x670066f066c066b,  0x674067306720671,  0x678067706760675,  0x67e067d067a0679,  0x68206810680067f,  0x686068506840683,  0x68c068b06880687,  0x690068f068e068d,  0x694069306920691,  0x69a069906960695,  0x69e069d069c069b,  0x6a606a506a206a1,  0x6ac06ab06a806a7,  0x6b006af06ae06ad,  0x6b406b306b206b1,  0x6ba06b906b606b5,  0x6be06bd06bc06bb,  0x6c306c2070d070c,  0x6cb06ca06c706c6,  0x6cf06ce06cd06cc,  0x6d306d206d106d0,  0x6d906d806d506d4,  0x6dd06dc06db06da,  0x6e306e206e106e0,  0x6e906e806e506e4,  0x6ed06ec06eb06ea,  0x6f106f006ef06ee,  0x6f706f606f306f2,  0x6fb06fa06f906f8,  0x6ff06fe06fd06fc,  0x704070207010700,  0x70e070a07080706,  0xffff0710ffffffff,  0x715071407130712,  0x71b071a07170716,  0x71f071e071d071c,  0x723072207210720,  0x729072807270726,  0x72f072e072d072c,  0x733073207310730,  0x737073607350734,  0x73d073c073b073a,  0x743074207410740,  0x747074607450744,  0x74b074a07490748,  0x74f074e074d074c,  0x753075207510750,  0x757075607550754,  0x75b075a07590758,  0x75f075e075d075c,  0x766076507610760,  0x76a076907680767,  0x770076f076e076d,  0x774077307720771,  0x778077707760775,  0x77c077b077a0779,  0x78507840780077f,  0x78e078c078a0788,  0x796079407920790,  0x78f078d078b0789,  0x797079507930791,  0x7a207a0079e079c,  0xffffffff07a607a4,  0x7a307a1079f079d,  0xffffffff07a707a5,  0x7bc07ba07b807b6,  0x7c407c207c007be,  0x7bd07bb07b907b7,  0x7c507c307c107bf,  0x7dc07da07d807d6,  0x7e407e207e007de,  0x7dd07db07d907d7,  0x7e507e307e107df,  0x7f407f207f007ee,  0xffffffff07f807f6,  0x7f507f307f107ef,  0xffffffff07f907f7,  0x80c07fe080807fc,  0x814080408100800,  0x80dffff0809ffff,  0x815ffff0811ffff,  0x828082608240822,  0x830082e082c082a,  0x829082708250823,  0x831082f082d082b,  0x8f708f508df08dd,  0x90f090d08fb08f9,  0x924092209370935,  0xffffffff093b0939,  0x85f085c08590856,  0x86b086808650862,  0x860085d085a0857,  0x86c086908660863,  0x88f088c08890886,  0x89b089808950892,  0x890088d088a0887,  0x89c089908960893,  0x8bf08bc08b908b6,  0x8cb08c808c508c2,  0x8c008bd08ba08b7,  0x8cc08c908c608c3,  0x8e108ce08db08d9,  0x8d708d5ffff08d3,  0x8e008de08dc08da,  0xffff08e7ffff08e2,  0x8fd08e8ffffffff,  0x8f308f1ffff08ed,  0x8fc08fa08f808f6,  0xffffffffffff08fe,  0x9030900090b0909,  0x9070905ffffffff,  0x910090e090c090a,  0xffffffffffffffff,  0x91609130920091e,  0x91c091a09260918,  0x92509230921091f,  0xffffffffffff0927,  0x93d092affffffff,  0x9330931ffff092f,  0x93c093a09380936,  0xffffffffffff093e,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff0764ffffffff,  0x1500783ffffffff,  0xffffffffffffffff,  0xffff0561ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff0562ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x18d02c2018902b0,  0x195005e019102d6,  0x19d006c01990064,  0x1a5007e01a10076,  0x18e02c3018a02b1,  0x196005f019202d7,  0x19e006d019a0065,  0x1a6007f01a20077,  0x1c0ffffffffffff,  0xffffffffffff01c1,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x5090475ffffffff,  0x511047d050d0477,  0x51904a50515048f,  0x2051f02e80940,  0x6e052707180523,  0x110052f03a4052b,  0x54b053706630533,  0x50e0478050a0476,  0x51604900512047e,  0x2e90941051a04a6,  0x719052400030520,  0x3a5052c006f0528,  0x664053401110530,  0xffffffff054c0538,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xa000800040000,  0x160010000e000c,  0x2ce001c001a0018,  0x56030802e602dc,  0x66006200600058,  0x7800740070006a,  0x2aa00820080007c,  0x64b008400060832,  0x60d060902b805b5,  0x10801060629061d,  0x11c01160112010a,  0xffff0134012c0124,  0xb000900050001,  0x170011000f000d,  0x2cf001d001b0019,  0x57030902e702dd,  0x67006300610059,  0x7900750071006b,  0x2ab00830081007d,  0x64c008500070833,  0x60e060a02b905b6,  0x1090107062a061e,  0x11d01170113010b,  0xffff0135012d0125,  0x486055a04f404f3,  0x48b0297029102b5,  0x49302bb02ba048c,  0x49c02c704980494,  0x2cd02ccffff02cb,  0xffff02d502d4ffff,  0xffffffffffffffff,  0x4b402edffffffff,  0x4ba04b902f902f8,  0x4be04bd04bc04bb,  0x325032404c204c1,  0x3350334032b032a,  0x3410340033d033c,  0x34f034e034d034c,  0x73f073e03230322,  0x3b003af03ae03ad,  0x3bf03be03b403b3,  0x3e203e103d203d1,  0x606060505a405a3,  0x6320631061a0619,  0x6a0069f06560655,  0x7390738046f046e,  0x7d507d4077e077d,  0x6df06de08350834,  0x15001406a406a3,  0x4ee04ed005d005c,  0x612061105020501,  0x542054101aa01a9,  0x566056505540553,  0x586058505760575,  0x5a805a705960595,  0x162016105b805b7,  0x3ea03e903a703a6,  0xffffffffffffffff,  0x60fffffffffffff,  0xffff061806170610,  0x6240623ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x8d008b00890087,  0x9500930091008f,  0x9d009b00990097,  0xa500a300a1009f,  0xad00ab00a900a7,  0xb500b300b100af,  0xbd00bb00b900b7,  0xc500c300c100bf,  0x4d200cb04c004b8,  0x4f8ffff04e600cf,  0xffffffffffffffff,  0xffffffff053affff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x616061502d902d8,  0x6220621061c061b,  0x1e501e406280627,  0x6340633062e062d,  0x63e063d06380637,  0x32f032e06420641,  0x66e066d065e065d,  0x68a0689067c067b,  0x6aa06a906980697,  0x6c906c806b806b7,  0x6e706e606d706d6,  0xffffffff06f506f4,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x69006807870786,  0x7b107b0028f028e,  0x3bd03bc07c907c8,  0x8030802001f001e,  0x2b302b208190818,  0x2d302d208370836,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x7ab07aaffffffff,  0x7b307b207af07ae,  0x2f502f402eb02ea,  0x311031003070306,  0x7cb07caffffffff,  0x7d307d207cf07ce,  0x33b033a03330332,  0x3490348033f033e,  0x7e907e807e707e6,  0x7ed07ec07eb07ea,  0x3b203b103ac03ab,  0x7fb07fa03bb03ba,  0x3f003ef03dc03db,  0x28302820620061f,  0x80b080a08070806,  0x8130812080f080e,  0x81b081a08170816,  0x8210820081f081e,  0x4b004af04a0049f,  0x4d604d504c404c3,  0xffffffffffffffff,  0xffffffffffffffff,  0x83805460545ffff,  0x83d083c083b0839,  0x590058f0580057f,  0x5b205b105a0059f,  0x63bffffffffffff,  0xffffffff079b063c,  0x60c060b06080607,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x630062f062c062b,  0x63a063906360635,  0xffff06440640063f,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x2fc02fa025e02f6,  0xffff0304030302fe,  0xffffffffffffffff,  0xffffffffffffffff,  0x30cffffffffffff,  0x314031202c0030e,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x7ac02da07a8ffff,  0x7b402e402e202e0,  0x144076b02f00724,  0x318081c030a0479,  0x7cc031c031a07c6,  0x32c022c07d00320,  0xffff046c0336007a,  0xffffffffffffffff,  0x7ad02db07a9ffff,  0x7b502e502e302e1,  0x145076c02f10725,  0x319081d030b047a,  0x7cd031d031b07c7,  0x32d022d07d10321,  0xffff046d0337007b,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x72005a09280012,  0x114010c03520338,  0x2f202ae02bc0625,  0x10e064f031608ef,  0x4fb029a02ee02b6,  0x2de02d002c802be,  0x330031e047f0798,  0x3b802c4024e0342,  0x473056b047b03e5,  0x91104df072a06c4,  0x73005b09290013,  0x115010d03530339,  0x2f302af02bd0626,  0x10f0650031708f0,  0x4fc029b02ef02b7,  0x2df02d102c902bf,  0x331031f04800799,  0x3b902c5024f0343,  0x474056c047c03e6,  0x91204e0072b06c5,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff]);
+//4000 bytes
+enum alphaTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x20,  0xb0], [ 0x100,  0x240,  0x5100], [ 0x706050403020100,  0xe0d0c0a0b0a0908,  0x100a0f0303030303,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3000200010000,  0x7000600050004,  0xb000a00090008,  0xf000e000d000c,  0x12001100010010,  0x15001400010013,  0x19001800170016,  0x1c0001001b001a,  0x1f001f001e001d,  0x1f001f001f0020,  0x1f001f001f001f,  0x1f002300220021,  0x1f001f00250024,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100260001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x27000100010001,  0x1000100010001,  0x2a002900010028,  0x2e002d002c002b,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x2f000100010001,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x3100300001001f,  0x34003300320001,  0x38003700360035,  0x1f001f001f0039,  0x3d003c003b003a,  0x1f001f001f003e,  0x1f001f0040003f,  0x1f0041001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x42000100010001,  0x1f001f001f0043,  0x1f001f001f001f,  0x1f001f001f001f,  0x1000100010001,  0x1f001f001f0044,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f004500010001,  0x46001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f0047,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x4b004a00490048,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f004c001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1000100010001,  0x1004d00010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x4e000100010001,  0x1f001f001f004f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f004f00010001,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x1f001f001f001f,  0x0,  0x7fffffe07fffffe,  0x420040000000000,  0xff7fffffff7fffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x501f0003ffc3,  0x0,  0x3cdf000000000020,  0xfffffffbffffd740,  0xffbfffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xfffffffffffffc03,  0xffffffffffffffff,  0xfffe00ffffffffff,  0xfffffffe027fffff,  0xbfff0000000000ff,  0x707ffffff00b6,  0xffffffff07ff0000,  0xffffc000feffffff,  0xffffffffffffffff,  0x9c00e1fe1fefffff,  0xffffffffffff0000,  0xffffffffffffe000,  0x3ffffffffffff,  0x43007fffffffc00,  0x1ffffcffffff,  0x1ffffff,  0x1ffd00000000,  0x7fff03f000000000,  0xefffffffffffffff,  0xfefe000fffe1dfff,  0xe3c5fdfffff99fee,  0x3000fb080599f,  0xc36dfdfffff987ee,  0x3f00005e021987,  0xe3edfdfffffbbfee,  0xf00011bbf,  0xe3edfdfffff99fee,  0x2000fb0c0199f,  0xc3ffc718d63dc7ec,  0x811dc7,  0xe3effdfffffddfee,  0xf03601ddf,  0xe3effdfffffddfec,  0x6000f40601ddf,  0xe7fffffffffddfec,  0xfc00000f00805ddf,  0x2ffbfffffc7fffec,  0xc0000ff5f807f,  0x7fffffffffffffe,  0x207f,  0x3bffecaefef02596,  0xf000205f,  0x1,  0xfffe1ffffffffeff,  0x1ffffffffeffff03,  0x0,  0xf97fffffffffffff,  0xffffc1e7ffff0000,  0xffffffff3000407f,  0xf7ffffffffff20bf,  0xffffffffffffffff,  0xffffffff3d7f3dff,  0x7f3dffffffff3dff,  0xffffffffff7fff3d,  0xffffffffff3dffff,  0x87ffffff,  0xffffffff0000ffff,  0x1fffffffffffff,  0xfffffffffffffffe,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff9fffffffffff,  0xffffffff07fffffe,  0x1c7ffffffffff,  0xfffff000fdfff,  0xddfff000fffff,  0xffcfffffffffffff,  0x108001ff,  0xffffffff00000000,  0xffffffffffffff,  0xffff07ffffffffff,  0x3fffffffffffff,  0x1ff0fff1fffffff,  0x1f3fffffff0000,  0xffff0fffffffffff,  0x3ff,  0xffffffff0fffffff,  0x1ffffe7fffffff,  0x8000000000,  0x0,  0xffefffffffffffff,  0xfef,  0xfc00f3ffffffffff,  0x3ffbfffffffff,  0x3fffffffffffff,  0x3ffffffffc00e000,  0x0,  0x6fde0000000000,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x0,  0xffffffff3f3fffff,  0x3fffffffaaff3f3f,  0x5fdfffffffffffff,  0x1fdc1fff0fcf1fdc,  0x0,  0x8002000000000000,  0x1fff0000,  0x0,  0xf3ffbd503e2ffc84,  0xffffffff000043e0,  0x1ff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffc0000000000000,  0x3ffffffffff,  0xffff7fffffffffff,  0xffffffff7fffffff,  0xffffffffffffffff,  0xc781fffffffff,  0xffff20bfffffffff,  0x80ffffffffff,  0x7f7f7f7f007fffff,  0xffffffff7f7f7f7f,  0x800000000000,  0x0,  0x0,  0x0,  0x1f3e03fe000000e0,  0xfffffffffffffffe,  0xfffffffee07fffff,  0xf7ffffffffffffff,  0xfffe3fffffffffe0,  0xffffffffffffffff,  0x7ffffff00007fff,  0xffff000000000000,  0xffffffffffffffff,  0xffffffffffffffff,  0x3fffffffffffff,  0x0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x1fff,  0xffffffffffffffff,  0xffffffffffffffff,  0x1fff,  0x3fffffffffff0000,  0xc00ffff1fff,  0x8ff07fffffffffff,  0xffffffff80ffffff,  0xffffffffffff,  0xfffffffcff800000,  0xffffffffffffffff,  0x7ff000f79ff,  0xff00000000000000,  0xfffffff7bb,  0xfffffffffffff,  0xffffffffffffffff,  0x8fc00000000000f,  0xffff07fffffffc00,  0x1fffffff0007ffff,  0xfff7ffffffffffff,  0x8000,  0x7fffffffffffff,  0x47fffff00003fff,  0x7fffffffffffffff,  0x3cffff38000005,  0x7f7f007e7e7e,  0x0,  0x0,  0x7ffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff000fffffffff,  0xffffffffffff87f,  0xffffffffffffffff,  0xffff3fffffffffff,  0xffffffffffffffff,  0x3ffffff,  0x5f7ffdffe0f8007f,  0xffffffffffffffdb,  0x3ffffffffffff,  0xfffffffffff80000,  0x3fffffffffffffff,  0xffffffffffff0000,  0xfffffffffffcffff,  0xfff0000000000ff,  0x0,  0xffdf000000000000,  0xffffffffffffffff,  0x1fffffffffffffff,  0x7fffffe00000000,  0xffffffc007fffffe,  0x7fffffffffffffff,  0x1cfcfcfc,  0xb7ffff7fffffefff,  0x3fff3fff,  0xffffffffffffffff,  0x7ffffffffffffff,  0x0,  0x1fffffffffffff,  0x0,  0x0,  0x0,  0x0,  0xffffffff1fffffff,  0x1ffff,  0xffff00007fffffff,  0x7ff,  0xffffffff3fffffff,  0x3eff0f,  0xffffffffffffffff,  0xffffffffffffffff,  0x3fffffff,  0x0,  0x91bffffffffffd3f,  0x3fffff,  0x0,  0x0,  0x3ffffff003fffff,  0x0,  0xc0ffffffffffffff,  0x0,  0xffffffeeff06f,  0x1fffffff00000000,  0x0,  0x0,  0x3fffffffffffff,  0x7ffff003fffff,  0x0,  0x0,  0xffffffffffffffff,  0x1ff,  0x0,  0x0,  0xffffffffffffffff,  0x3f,  0x1fffffffffffffc,  0x1ffffff0000,  0x7ffffffffffff,  0x0,  0xffffffffffffffff,  0x1e,  0x0,  0x0,  0x3fffffffffffff,  0x0,  0xffffffffffffffff,  0x7fffffffffff,  0x0,  0x0,  0xffffffffffffffff,  0x7ffffffff,  0x0,  0x0,  0x7fffffffffff,  0x0,  0x0,  0x0,  0x1ffffffffffffff,  0x0,  0x0,  0x0,  0xffffffffffffffff,  0x7fffffffffff001f,  0xfff80000,  0x0,  0x3,  0x0,  0x0,  0x0,  0xffffffffffffffff,  0xffffffffffdfffff,  0xebffde64dfffffff,  0xffffffffffffffef,  0x7bffffffdfdfe7bf,  0xfffffffffffdfc5f,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffff3fffffffff,  0xf7fffffff7fffffd,  0xffdfffffffdfffff,  0xffff7fffffff7fff,  0xfffffdfffffffdff,  0xff7,  0xaf7fe96ffffffef,  0x5ef7f796aa96ea84,  0xffffbee0ffffbff,  0x0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x7fffff,  0x1fffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x3fffffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//2304 bytes
+enum markTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x20,  0x70], [ 0x100,  0x140,  0x2c00], [ 0x402030202020100,  0x207020206020205,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020208,  0x202020202020202,  0x202020202020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1000000000000,  0x5000400030002,  0x9000800070006,  0xd000c000b000a,  0xf00000000000e,  0x10000000000000,  0x14001300120011,  0x160015,  0x17,  0x0,  0x0,  0x190018,  0x1a,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1b00000000,  0x1f001e001d001c,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x20000000000000,  0x2100000000,  0x220000,  0x0,  0x2300000000,  0x0,  0x250024,  0x2600000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x27000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2900280000,  0x0,  0x0,  0x0,  0x2a0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffffffffffff,  0xffffffffffff,  0x0,  0x0,  0x0,  0x0,  0x3f8,  0x0,  0x0,  0x0,  0xbffffffffffe0000,  0xb6,  0x7ff0000,  0x10000fffff800,  0x0,  0x3d9f9fc00000,  0xffff000000020000,  0x7ff,  0x1ffc000000000,  0xff80000000000,  0x3eeffbc00000,  0xe000000,  0x0,  0x7ffffff000000000,  0xdc0000000000000f,  0xc00feffff,  0xd00000000000000e,  0xc0080399f,  0xd00000000000000e,  0x23000000023987,  0xd00000000000000e,  0xc00003bbf,  0xd00000000000000e,  0xc00c0399f,  0xc000000000000004,  0x803dc7,  0xc00000000000000e,  0xc00603ddf,  0xd00000000000000c,  0xc00603ddf,  0xc00000000000000c,  0xc00803ddf,  0xc,  0xc0000ff5f8400,  0x7f2000000000000,  0x7f80,  0x1bf2000000000000,  0x3f00,  0xc2a0000003000000,  0xfffe000000000000,  0x1ffffffffeffe0df,  0x40,  0x7ffff80000000000,  0x1e3f9dc3c00000,  0x3c00bffc,  0x0,  0x0,  0xe0000000,  0x0,  0x0,  0x1c0000001c0000,  0xc0000000c0000,  0xfff0000000000000,  0x200fffff,  0x3800,  0x0,  0x20000000000,  0x0,  0xfff0fff00000000,  0x0,  0xffff000000000000,  0x301,  0xf800000,  0x9fffffff7fe00000,  0x0,  0x0,  0xfff000000000001f,  0xff8000000001f,  0x3ffe00000007,  0xfffc000000000,  0xfffff000000000,  0x0,  0x0,  0x1c21fffff70000,  0x0,  0x0,  0x0,  0xf000007fffffffff,  0x0,  0x0,  0x0,  0x1ffffffff0000,  0x0,  0x0,  0x0,  0x3800000000000,  0x0,  0x8000000000000000,  0x0,  0xffffffff00000000,  0xfc0000000000,  0x0,  0x6000000,  0x0,  0x0,  0x3ff7800000000000,  0x80000000,  0x3000000000000,  0xf800000844,  0x0,  0xfff0000000000003,  0x3ffff0000001f,  0x3fc000000000,  0xfff80,  0xfff800000000000f,  0x1,  0x7ffe0000000000,  0x800000000003008,  0xc19d000000000000,  0x60f80000000002,  0x0,  0x0,  0x0,  0x37f800000000,  0x40000000,  0x0,  0x0,  0x0,  0x7f0000ffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2000000000000000,  0x870000000000f06e,  0x0,  0x0,  0x0,  0xff00000000000007,  0x7f,  0x7ff000000000007,  0x0,  0x1fff8000000007,  0x0,  0xfff8000000000007,  0x1,  0x0,  0x0,  0xfff80000000000,  0x0,  0x0,  0x7ffffffffffe0000,  0x78000,  0x0,  0x0,  0xf807e3e000000000,  0x3c0000000fe7,  0x0,  0x0,  0x1c,  0x0,  0x0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffff,  0x0,  0x0,  0x0,  0x0]);
+//2384 bytes
+enum numberTrieEntries = TrieEntry!(bool, 8, 6, 7)([ 0x0,  0x20,  0xc0], [ 0x100,  0x280,  0x1a80], [ 0x402030202020100,  0x807020202020605,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2000200010000,  0x2000200020002,  0x2000200020002,  0x5000200040003,  0x7000600020002,  0x9000800060006,  0x2000b0006000a,  0x2000d000c000c,  0x20002000e0005,  0x2000f00020002,  0x2000200020002,  0x11000200100002,  0x1300120002000e,  0xc00140002,  0x2000200020015,  0x2000200020002,  0x19001800170016,  0x2000200020002,  0x20002001b001a,  0x1d001c00020002,  0x2000200020002,  0x2000200020002,  0x20002001e0002,  0x2000200020002,  0x2000020002001f,  0x2000200220021,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200060023,  0xc0017000c0024,  0x400020002000c,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000e00020002,  0x26002500020002,  0x28002700020002,  0x2000200230002,  0x2000200020002,  0x2002a00020029,  0x2002c0002002b,  0x2000200020002,  0x200020002002d,  0xc002f0004002e,  0x2000200020002,  0x2000200020002,  0x2000200050002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020030,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2003100020002,  0x2000200020002,  0x32000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2003300020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x2000200020002,  0x3ff000000000000,  0x0,  0x720c000000000000,  0x0,  0x0,  0x0,  0x0,  0x3ff00000000,  0x0,  0x3ff000000000000,  0x0,  0x3ff,  0x0,  0xffc000000000,  0x0,  0x3f0ffc000000000,  0x0,  0xfcffc000000000,  0x0,  0x7ffc000000000,  0x0,  0x7f00ffc000000000,  0x0,  0x3fffc000000000,  0x0,  0x3ff0000,  0xfffff00000000,  0x0,  0x3ff0000,  0x0,  0x0,  0x1ffffe0000000000,  0x0,  0x1c00000000000,  0x0,  0x3ff03ff00000000,  0x0,  0xffc0,  0x0,  0x7ff0000,  0x3ff03ff,  0x0,  0x0,  0x3ff03ff,  0x0,  0x3f1000000000000,  0x3ff,  0x0,  0x0,  0xffffffffffff0000,  0x3e7,  0x0,  0x0,  0xffffffff00000000,  0xfffffff,  0xfffffc0000000000,  0x0,  0xffc0000000000000,  0xfffff,  0x0,  0x0,  0x2000000000000000,  0x70003fe00000080,  0x0,  0x3c0000,  0x0,  0x3ff00000000,  0xfffeff00,  0xfffe0000000003ff,  0x0,  0x3ff00000000,  0x0,  0x3f000000000000,  0x0,  0xfffffffffff80,  0x1ffffffffffffff,  0x400,  0x0,  0xf00000000,  0x402,  0x0,  0x3e0000,  0x0,  0xff000000,  0xfc00000,  0x0,  0x0,  0x60000000000000ff,  0x0,  0xff000000ff000000,  0x0,  0x7fffffff00000000,  0x0,  0xfffffffc0000,  0xffc0000000000000,  0x0,  0xffffffffffffffff,  0x7ffffffff,  0x0,  0x3ffff00000000,  0x0,  0xffffffffffffc000,  0x7ff,  0x0,  0x0,  0x0]);
+//2336 bytes
+enum punctuationTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x20,  0x60], [ 0x100,  0x100,  0x3100], [ 0x402030202020100,  0x202020202020605,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2000100010000,  0x5000400030001,  0x1000800070006,  0xb000a00090001,  0xd00010001000c,  0x10000f0001000e,  0x14001300120011,  0x1000100010015,  0x17000100010016,  0x18000100010001,  0x1000100190001,  0x1001c001b001a,  0x100010001001d,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1001f0001001e,  0x23002200210020,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x26002500240001,  0x28000100270001,  0x1000100010001,  0x2c002b002a0029,  0x1000100010001,  0x10001002e002d,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x100010001002f,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x8c00f7ee00000000,  0x28000000b8000001,  0x88c0088200000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x4000000000000000,  0x80,  0x0,  0x0,  0xfc000000,  0x4000000000000600,  0x18000000000049,  0xc8003600,  0x3c0000000000,  0x0,  0x100000,  0x3fff,  0x0,  0x0,  0x380000000000000,  0x7fff000000000000,  0x40000000,  0x0,  0x0,  0x0,  0x1003000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1000000000000,  0x0,  0x0,  0x0,  0x10000000000000,  0x0,  0xc008000,  0x0,  0x0,  0x3c0000000017fff0,  0x0,  0x20,  0x61f0000,  0x0,  0xfc00,  0x0,  0x800000000000000,  0x0,  0x1ff00000000,  0x0,  0x0,  0x1,  0x0,  0x0,  0x0,  0x0,  0x600000000000,  0x18000000,  0x380000000000,  0x60000000000000,  0x0,  0x0,  0x7700000,  0x7ff,  0x0,  0x0,  0x0,  0x0,  0x30,  0x0,  0x0,  0xc0000000,  0x0,  0x3f7f00000000,  0x0,  0x0,  0x1fc000000,  0x0,  0xf000000000000000,  0xf800000000000000,  0xc000000000000000,  0x0,  0x800ff,  0xffff00ffffff0000,  0x600000007ffbffef,  0x6000,  0x0,  0x60000000f00,  0x0,  0x0,  0x0,  0x0,  0x3fff0000000000,  0x0,  0xffc000000060,  0x0,  0x0,  0x1fffff8,  0x300000000f000000,  0x0,  0x0,  0x0,  0xde00000000000000,  0x0,  0x1000000000000,  0x0,  0x0,  0xfff7fffffffffff,  0x0,  0x0,  0x0,  0x20010000fff3ff0e,  0x0,  0x100000000,  0x800000000000000,  0x0,  0x0,  0x0,  0xc000000000000000,  0xe000,  0x4008000000000000,  0x0,  0xfc000000000000,  0x0,  0xf0000000000000,  0x0,  0x70000000000c000,  0xc00000000000,  0x80000000,  0x0,  0xc0003ffe,  0x0,  0xf0000000,  0x0,  0x30000c0000000,  0x0,  0x0,  0x0,  0x80000000000,  0xc000000000000000,  0x0,  0x0,  0x0,  0xffff000003ff0000,  0xd0bfff7ffff,  0x0,  0x0,  0xb80000018c00f7ee,  0x3fa8000000,  0x0,  0x0,  0x7,  0x0,  0x0,  0x0,  0x0,  0x0,  0x80000000,  0x10000,  0x0,  0x800000,  0x0,  0x0,  0x8000000080000000,  0x0,  0x0,  0x0,  0x0,  0x8000000001ff0000,  0x0,  0x0,  0xfe00000000000000,  0x0,  0x0,  0x0,  0x0,  0x3f80,  0xd800000000000000,  0x3,  0x0,  0xf,  0x0,  0x1e0,  0x0,  0xf000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//2848 bytes
+enum symbolTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x20,  0x70], [ 0x100,  0x140,  0x3d00], [ 0x503040303020100,  0x807030303030306,  0x303030303030303,  0x303030303030303,  0x303030303030303,  0x303030303030303,  0x303030303030303,  0x303030303030303,  0x303030303030303,  0x303030303030303,  0x303030303030303,  0x303030303030303,  0x303030303030303,  0x303030303030303,  0x303030303030303,  0x303030303030303,  0x303030303030303,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3000200010000,  0x7000600050004,  0xa000900080001,  0xe000d000c000b,  0x1000010001000f,  0x11000100010001,  0x13000100120001,  0x14000100010001,  0x18001700160015,  0x1a001700170019,  0x1c0017001b0017,  0x1f001e0001001d,  0x17002200210020,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100230001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x25000100010024,  0x1002700010026,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x28000100010001,  0x2b002a00290001,  0x10001002c0001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x30002f002e002d,  0x32003100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1003300010001,  0x37003600350034,  0x3b003a00390038,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x7000081000000000,  0x5000000140000000,  0x113d37c00000000,  0x80000000800000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffafe0fffc003c,  0x0,  0x20000000000000,  0x30,  0x40000000000000,  0x0,  0x0,  0x4,  0x0,  0x0,  0x0,  0x8000,  0x0,  0xc9c0,  0x0,  0x0,  0x6000020040000000,  0x0,  0x0,  0x0,  0x40000000000000,  0x0,  0x0,  0x0,  0xc0c000000000000,  0x0,  0x0,  0x0,  0x2000000000000,  0x0,  0x1000000000000,  0x0,  0x7f8000000000000,  0x0,  0x8000000000000000,  0x0,  0x0,  0x0,  0x200000000000000,  0x0,  0x0,  0x8000000000000000,  0x0,  0x0,  0x0,  0x1500000fce8000e,  0x0,  0xc000000000000000,  0x1e0dfbf,  0x0,  0x0,  0xc0000000,  0x0,  0x0,  0x0,  0x3ff0000,  0x0,  0x0,  0x0,  0x0,  0x8000000,  0x0,  0x1,  0x0,  0xffffffffc0000000,  0x0,  0x1ff007fe00000000,  0x0,  0x0,  0x0,  0x0,  0xa000000000000000,  0x6000e000e000e003,  0x0,  0x1c00000000040010,  0x7ffffff00001c00,  0x0,  0xc0042afc1d0037b,  0xbc1f,  0xffffffffffff0000,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xfffff9fffffff0ff,  0xffffffffffffffff,  0xffffffffffffffff,  0xfffffffffffff,  0x7fffffffff,  0x7ff,  0xfffffffff0000000,  0x3ffffffffff,  0xfffffffffffffffe,  0xffffffffff,  0xfffffffffff00000,  0xffff003fffffff9f,  0xffffffffffffffff,  0xffffffffffffffff,  0xfffffffffe000007,  0xcffffffff0ffffff,  0xffffffffffffffff,  0x3ff1fff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7e000000000,  0x0,  0x0,  0xfffffffffbffffff,  0xfffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xfff0000003fffff,  0xc0c00001000c0010,  0x0,  0x18000000,  0x0,  0x0,  0x0,  0xffc30000,  0xfffffffff,  0xfffffc007fffffff,  0xffffffff000100ff,  0x1fffffffffc00,  0x7fffffffffffffff,  0x0,  0x0,  0x0,  0xffffffffffffffff,  0x0,  0x0,  0xffffffffffff0000,  0x7f,  0x3007fffff,  0x0,  0x600,  0x0,  0x3c00f0000000000,  0x0,  0x0,  0x0,  0x0,  0x380000000000000,  0x0,  0x0,  0x20000000000,  0x0,  0xfffc000000000000,  0x3,  0x0,  0x0,  0x0,  0x3000000000000000,  0x0,  0x27400000000,  0x0,  0x0,  0x4000000070000810,  0x50000001,  0x0,  0x30007f7f00000000,  0xff80000000000000,  0xfe00000000000000,  0xfff03ff,  0x1fffffffffff0000,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x3fffffffffffff,  0xfffffe7fffffffff,  0x1c1fffffffff,  0xffffc3fffffff018,  0x3fffffff,  0xffffffffffffffff,  0x23,  0x0,  0x0,  0xffffffffffffffff,  0x7fffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x800000008000002,  0x20000000200000,  0x800000008000,  0x20000000200,  0x8,  0x0,  0x0,  0x0,  0x3000000000000,  0xffff0fffffffffff,  0xffffffffffffffff,  0x7ffe7fff000fffff,  0xfffefffe,  0xffff7fffffff0000,  0xffff0fffffffffff,  0x7ffffff,  0xffffffc000000000,  0x7ffffffffff0007,  0x301ff,  0x0,  0x0,  0xffbf0001ffffffff,  0x1fffffffffffffff,  0xffffffff000fffff,  0x1ffff000007df,  0x7fffffffffffffff,  0xfffffffffffffffd,  0xffffffffffffffff,  0x1effffffffffffff,  0x3fffffffffffffff,  0xffffff000f,  0x0,  0xf800000000000000,  0xffffffffffffffff,  0xffe1,  0xffffffffffffffff,  0x3f,  0xffffffffffffffff,  0xfffffffffffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//4576 bytes
+enum graphicalTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x20,  0xb8], [ 0x100,  0x260,  0x6100], [ 0x706050403020100,  0xe0d0c0a0b0a0908,  0x100a0f0303030303,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a11,  0xa0a0a0a0a0a0a0a,  0xa0a0a0a0a0a0a0a,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2000100010000,  0x5000400030001,  0x9000800070006,  0xd000c000b000a,  0x10000f0001000e,  0x12001100010001,  0x16001500140013,  0x19000100180017,  0x1c0001001b001a,  0x1e00010001001d,  0x1f000100010001,  0x23002200210020,  0x1002600250024,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100270001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x28000100010001,  0x1000100010001,  0x2b002a00010029,  0x2f002e002d002c,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x30000100010001,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x33003200010031,  0x36003500340001,  0x3a003900380037,  0x3100310031003b,  0x3f003e003d003c,  0x31004100310040,  0x31003100430042,  0x31004400310031,  0x31003100310031,  0x31003100310031,  0x45000100010001,  0x31003100310046,  0x31003100310031,  0x31003100310031,  0x1000100010001,  0x31003100310047,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31004800010001,  0x49003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x3100310031004a,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x4e004d004c004b,  0x5200510050004f,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31005300310031,  0x57005600550054,  0x5b005a00590058,  0x31003100310031,  0x31003100310031,  0x1000100010001,  0x1005c00010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x5d000100010001,  0x3100310031005e,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31005e00010001,  0x31003100310031,  0x310031005f0031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0x31003100310031,  0xffffffff00000000,  0x7fffffffffffffff,  0xffffdfff00000000,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x7cffffffffffffff,  0xfffffffbffffd7f0,  0xffffffffffffffff,  0xfffe00ffffffffff,  0xfffffffefe7fffff,  0xfffffffffffe86ff,  0x1f07ffffff00ff,  0xffffffffcfffffc0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffdfffffff,  0xffffffffffff3fff,  0xffffffffffffe7ff,  0x3ffffffffffff,  0x7ffffffffffffff,  0x7fff3fffffffffff,  0x4fffffff,  0x1ffd00000000,  0x7ffffff000000000,  0xffffffffffffffff,  0xfeffffffffffffff,  0xf3c5fdfffff99fee,  0xfffffcfb080799f,  0xd36dfdfffff987ee,  0x3fffc05e023987,  0xf3edfdfffffbbfee,  0x3ffcf00013bbf,  0xf3edfdfffff99fee,  0xffffcfb0c0399f,  0xc3ffc718d63dc7ec,  0x7ffffc000813dc7,  0xe3effdfffffddfee,  0xff00ffcf03603ddf,  0xf3effdfffffddfec,  0x6ffcf40603ddf,  0xe7fffffffffddfec,  0xfe3fffcf00807ddf,  0x2ffbfffffc7fffec,  0x1c0000ff5f847f,  0x87fffffffffffffe,  0xfffffff,  0x3bffecaefef02596,  0xf3ff3f5f,  0xffffffffffffffff,  0xfffe1ffffffffeff,  0xdffffffffeffffff,  0x7ffdfff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffff20bf,  0xffffffffffffffff,  0xffffffff3d7f3dff,  0x7f3dffffffff3dff,  0xffffffffff7fff3d,  0xffffffffff3dffff,  0x1fffffffe7ffffff,  0xffffffff03ffffff,  0x1fffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff1fffffff,  0x1ffffffffffff,  0x7fffff001fdfff,  0xddfff000fffff,  0xffffffffffffffff,  0x3ff03ff3fffffff,  0xffffffff03ff3fff,  0xffffffffffffff,  0xffff07ffffffffff,  0x3fffffffffffff,  0xfff0fff1fffffff,  0x1f3ffffffffff1,  0xffff0fffffffffff,  0xffffffffc7ff03ff,  0xffffffffcfffffff,  0x9fffffff7fffffff,  0x3fff03ff03ff,  0x0,  0xffffffffffffffff,  0x1fffffffffff0fff,  0xffffffffffffffff,  0xf00fffffffffffff,  0xf8ffffffffffffff,  0xffffffffffffe3ff,  0x0,  0x7fffffffff00ff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xf000007fffffffff,  0xffffffff3f3fffff,  0x3fffffffaaff3f3f,  0xffdfffffffffffff,  0x7fdcffffefcfffdf,  0xffff80ffffff07ff,  0xfff30000ffffffff,  0x7ffffff1fff7fff,  0x1ffffffff0000,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffff03ff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xfffffffffffff,  0x7fffffffff,  0xffffffff000007ff,  0xffffffffffffffff,  0xffffffffffffffff,  0xfffffffffffffffe,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x3ff1fff,  0x0,  0x0,  0xffff7fffffffffff,  0xffffffff7fffffff,  0xffffffffffffffff,  0xfe0fffffffffffff,  0xffff20bfffffffff,  0x800180ffffffffff,  0x7f7f7f7f007fffff,  0xffffffff7f7f7f7f,  0xfffffffffffffff,  0x0,  0xfffffffffbffffff,  0xfffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xfff0000003fffff,  0xffffffffffffffff,  0xfffffffffffffffe,  0xfffffffffe7fffff,  0xffffffffffffffff,  0xfffe3fffffffffe0,  0xffffffffffffffff,  0x7ffffffffff7fff,  0xffff000fffffffff,  0xffffffff7fffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x7fffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x3fffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x1fff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffff1fff,  0xffffffffffff007f,  0xfffffffffff,  0xffffffffffffffff,  0xffffffff80ffffff,  0xffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x7ff000f7fff,  0xff00000000000000,  0x3ff0fffffffffff,  0xffffffffffffff,  0xffffffffffffffff,  0xfffffff03ffc01f,  0xffffffffffffffff,  0x1fffffff800fffff,  0xffffffffffffffff,  0xc3ffbfff,  0x7fffffffffffff,  0xffffffff3ff3fff,  0xffffffffffffffff,  0x7ffffff8000007,  0x7f7f007e7e7e,  0x0,  0x0,  0x3ff3fffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff000fffffffff,  0xffffffffffff87f,  0x0,  0x0,  0x0,  0x0,  0xffffffffffffffff,  0xffff3fffffffffff,  0xffffffffffffffff,  0x3ffffff,  0x5f7fffffe0f8007f,  0xffffffffffffffdb,  0xffffffffffffffff,  0xfffffffffff80003,  0xffffffffffffffff,  0xffffffffffff0000,  0xfffffffffffcffff,  0x3fff0000000000ff,  0xffff007f03ffffff,  0xffdf0f7ffff7ffff,  0xffffffffffffffff,  0x1fffffffffffffff,  0xfffffffffffffffe,  0xffffffffffffffff,  0x7fffffffffffffff,  0x30007f7f1cfcfcfc,  0xb7ffff7fffffefff,  0x3fff3fff,  0xffffffffffffffff,  0x7ffffffffffffff,  0xff8fffffffffff87,  0xffffffffffffffff,  0xfff07ff,  0x3fffffffffff0000,  0x0,  0x0,  0xffffffff1fffffff,  0x1ffff,  0xffff000f7fffffff,  0x7ff,  0xffffffffbfffffff,  0x3fff0f,  0xffffffffffffffff,  0xffffffffffffffff,  0x3ff3fffffff,  0x0,  0x91bffffffffffd3f,  0xffbfffff,  0x0,  0x0,  0x83ffffff8fffffff,  0x0,  0xc0ffffffffffffff,  0x0,  0x870ffffffeeff06f,  0xffffffff01ff00ff,  0x0,  0x0,  0xfe3fffffffffffff,  0xff07ffffff3fffff,  0x0,  0x0,  0xffffffffffffffff,  0x1ff,  0x0,  0x0,  0x0,  0x7fffffff00000000,  0x0,  0x0,  0xffffffffffffffff,  0xfffffffc3fff,  0xdfffffffffffffff,  0x3ff01ffffff0003,  0xffdfffffffffffff,  0xf,  0xffffffffffffffff,  0x3ff01ff,  0x0,  0x0,  0xffffffffffffff,  0x3ff,  0xffffffffffffffff,  0x7fffffffffff,  0x0,  0x0,  0xffffffffffffffff,  0xf0007ffffffff,  0x0,  0x0,  0x7fffffffffff,  0x0,  0x0,  0x0,  0x1ffffffffffffff,  0x0,  0x0,  0x0,  0xffffffffffffffff,  0x7fffffffffff001f,  0xffff8000,  0x0,  0x3,  0x0,  0x0,  0x0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x3fffffffffffff,  0xfffffe7fffffffff,  0xf807ffffffffffff,  0xffffffffffffffff,  0x3fffffff,  0xffffffffffffffff,  0x3f,  0x0,  0x0,  0xffffffffffffffff,  0x3ffff007fffff,  0x0,  0x0,  0xffffffffffffffff,  0xffffffffffdfffff,  0xebffde64dfffffff,  0xffffffffffffffef,  0x7bffffffdfdfe7bf,  0xfffffffffffdfc5f,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffff3fffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffcfff,  0xaf7fe96ffffffef,  0x5ef7f796aa96ea84,  0xffffbee0ffffbff,  0x3000000000000,  0xffff0fffffffffff,  0xffffffffffffffff,  0x7ffe7fff000fffff,  0xfffefffe,  0xffff7fffffff07ff,  0xffff0fffffffffff,  0x7ffffff,  0xffffffc000000000,  0x7ffffffffff0007,  0x301ff,  0x0,  0x0,  0xffbf0001ffffffff,  0x1fffffffffffffff,  0xffffffff000fffff,  0x1ffff000007df,  0x7fffffffffffffff,  0xfffffffffffffffd,  0xffffffffffffffff,  0x1effffffffffffff,  0x3fffffffffffffff,  0xffffff000f,  0x0,  0xf800000000000000,  0xffffffffffffffff,  0xffe1,  0xffffffffffffffff,  0x3f,  0xffffffffffffffff,  0xfffffffffffff,  0x0,  0x0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x7fffff,  0x1fffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x3fffffff,  0x0,  0x0,  0x0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffff,  0x0,  0x0,  0x0,  0x0]);
+//3664 bytes
+enum nonCharacterTrieEntries = TrieEntry!(bool, 7, 4, 4, 6)([ 0x0,  0x10,  0x4c,  0x104], [ 0x80,  0xf0,  0x2e0,  0x3180], [ 0x706050403020100,  0xb0b0b0b0a090808,  0xb0b0b0b0b0b0b0b,  0xb0b0b0b0b0b0b0b,  0xb0b0b0b0b0b0b0b,  0xb0b0b0b0b0b0b0b,  0xb0b0b0b0b0b0b0b,  0xd0808080b0b0b0c,  0xd080808,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3000200010000,  0x7000600050004,  0xb000a00090008,  0xd000d000d000c,  0xe000d000d000d,  0xd000d000d000d,  0xd000d000d000d,  0xd000d000d000d,  0xd000d000d000d,  0xf000d000d000d,  0xd00110010000d,  0xd000d000d000d,  0xd000d000d000d,  0xd000d0012000d,  0xd000d000d000d,  0x140013000d000d,  0x18001700160015,  0x1b001b001a0019,  0x1b001b001d001c,  0x1b001b001e000d,  0x1b001b001b001b,  0x1b001b001b001b,  0x20001f001b001b,  0x1b001b001b001b,  0x1b001b001b001b,  0x1b001b001b001b,  0x1b001b001b001b,  0x1b001b001b0021,  0x1b001b001b001b,  0x1b001b00230022,  0x24001b001b001b,  0x1b001b00260025,  0xd000d000d000d,  0xd000d000d000d,  0xd000d000d000d,  0xd000d000d000d,  0xd000d000d000d,  0xd000d000d000d,  0xd000d0027000d,  0x1b00290028000d,  0x1b001b001b001b,  0x1b001b001b001b,  0x1b001b001b001b,  0x1b002a001b001b,  0x1b001b001b001b,  0x1b001b001b001b,  0x1b001b001b001b,  0x1b001b001b001b,  0x1b001b001b002b,  0x1b001b001b001b,  0x1b001b001b001b,  0x1b001b001b001b,  0xd000d000d000d,  0xd000d000d000d,  0xd000d000d000d,  0x2c000d000d000d,  0xd000d000d000d,  0xd000d000d000d,  0xd000d000d000d,  0x2c000d000d000d,  0x0,  0x0,  0x0,  0x200010000,  0x0,  0x6000500040003,  0x7,  0xb000a00090008,  0xf000e000d000c,  0x12001100100000,  0x16001500140013,  0x1a001900180017,  0x1e001d001c001b,  0x2200210020001f,  0x26002500240023,  0x29002800270000,  0x2a000000000000,  0x0,  0x2d002c002b0000,  0x310030002f002e,  0x0,  0x0,  0x33003200000000,  0x36000000350034,  0x3a003900380037,  0x3e003d003c003b,  0x4200410040003f,  0x44000000430000,  0x47004200460045,  0x48000000000000,  0x0,  0x4c004b004a0049,  0x4f004e004d0000,  0x5000000000,  0x0,  0x51000000000000,  0x530052,  0x0,  0x0,  0x54,  0x0,  0x0,  0x0,  0x42004200550000,  0x58000000570056,  0x5c005b005a0059,  0x51005e0042005d,  0x5f000000000000,  0x6000540000,  0x63006200000061,  0x64000000000057,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3a00000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x65000000000000,  0x67006600000000,  0x0,  0x38006900000068,  0x6b006a00000000,  0x6d00000038006c,  0x6f0000006e0000,  0x72000000710070,  0x74004200420073,  0x0,  0x0,  0x0,  0x75006300000000,  0x0,  0x0,  0x77000000760000,  0x7a000000790078,  0x0,  0x7d007c007b0000,  0x800000007f007e,  0x81006400000054,  0xb000000830082,  0x86008500000084,  0x87003200420042,  0x8b008a00890088,  0x42008c00000000,  0x42004200420042,  0x42004200420042,  0x42004200420042,  0x420042008e008d,  0x4200900042008f,  0x42004200920091,  0x42004200940093,  0x42004200950000,  0x42004200420042,  0x42004200960042,  0x42004200420042,  0x98000000970000,  0x9a00000099004b,  0x42004200420042,  0x42004200420042,  0x42004200420042,  0x42004200420042,  0x9b003800420042,  0x42004200420042,  0x42004200420042,  0x42004200420042,  0x42004200420042,  0x42004200420042,  0x0,  0x0,  0x0,  0x420042009c0000,  0x420042009d0000,  0x42004200420042,  0x42004200420042,  0x42004200420042,  0x4200420042009c,  0x42004200420042,  0x42004200420042,  0x42004200420042,  0x0,  0x0,  0x4200420042009e,  0x42004200420042,  0x42004200420042,  0x42004200420042,  0x42004200420042,  0x4200a0009f0000,  0x420042004200a1,  0x42004200420042,  0x42004200420042,  0x42004200420042,  0x3a000000000000,  0xa30000000000a2,  0x42004200a40000,  0x42004200a50000,  0xa800a700a60000,  0xaa00a9,  0xab00000000,  0xac000000000000,  0x42004200420042,  0x42004200420042,  0xb000af00ae00ad,  0x42004200420042,  0xb200b10000003d,  0xb500b4003d00b3,  0x42004200b700b6,  0xbb00ba00b900b8,  0xbd000000bc0064,  0xc0004200bf00be,  0xa4000000c10000,  0x42004200510000,  0x0,  0x0,  0xc2000000000000,  0x0,  0x0,  0x0,  0x0,  0x31,  0x420042004200a3,  0x42004200420042,  0x42004200420042,  0x42004200420042,  0x0,  0x0,  0x420042004200a3,  0x42004200420042,  0x420042000000c3,  0xc4000000000000,  0x42004200420042,  0x42004200420042,  0x0,  0x0,  0x0,  0xbe000000000000,  0x0,  0x0,  0x0,  0xbe000000000000,  0x0,  0x8300000000000000,  0x40000280f,  0x1ff0000000000,  0x101800000,  0x17900,  0xffe0f8000000ff00,  0x20000020,  0x4000,  0x1800,  0xfffc000000000000,  0xf800000000000000,  0x8000c00000000000,  0xffffffffb0000000,  0xffffe002ffffffff,  0x8000000fffffffff,  0x100000000000000,  0xc3a020000066011,  0xf00000304f7f8660,  0x2c92020000067811,  0xffc0003fa1fdc678,  0xc12020000044011,  0xfffc0030fffec440,  0xc12020000066011,  0xff0000304f3fc660,  0x3c0038e729c23813,  0xf800003fff7ec238,  0x1c10020000022011,  0xff0030fc9fc220,  0xc10020000022013,  0xfff90030bf9fc220,  0x1800000000022013,  0x1c00030ff7f8220,  0xd004000003800013,  0xffe3ffff00a07b80,  0x7800000000000001,  0xfffffffff0000000,  0xc4001351010fda69,  0xffffffff0c00c0a0,  0x1e00000000100,  0x2000000001000000,  0xfffffffff8002000,  0xdf40,  0xc280c200,  0x80c200000000c200,  0x8000c2,  0xc20000,  0xe000000018000000,  0xfc000000,  0xffe0000000000000,  0xe0000000,  0xfffe000000000000,  0xff800000ffe02000,  0xfff22000fff00000,  0xfc00fc00c0000000,  0xfc008000,  0xff00000000000000,  0xf80000000000,  0xffc0000000000000,  0xf000f000e0000000,  0xffe0c0000000000e,  0xf00000000000,  0x3800fc00,  0x30000000,  0x6000000080000000,  0xffffc000fc00fc00,  0xffffffffffffffff,  0xe00000000000f000,  0xff0000000000000,  0x700000000000000,  0x1c00,  0xff8000000000ff00,  0xfffff8000000000,  0xc0c00000,  0xc00000005500c0c0,  0x20000000000000,  0x8023000010300020,  0xc002000000000,  0xf8000000e0008000,  0xfffe00000000ffff,  0xfc00,  0xfff0000000000000,  0xffffff8000000000,  0xfffff800,  0x1,  0xfffffffffc00e000,  0x800000000000,  0x80000000,  0x1f0000000000000,  0xdf4000000000,  0x7ffe7f0000000000,  0x80808080ff800000,  0x80808080,  0xf000000000000000,  0x4000000,  0xf000ffffffc00000,  0x1800000,  0x1c0000000001f,  0xf800000000008000,  0xfff000000000,  0x8000000000000000,  0xffffffffffffe000,  0xe000,  0xff80,  0xfffff00000000000,  0x7f000000,  0xfffff800fff08000,  0xffffffffffffff,  0xfc00f00000000000,  0xf0000000fc003fe0,  0xe00000007ff00000,  0xffffffff3c004000,  0xff80000000000000,  0xf00000000c00c000,  0xff80000007fffff8,  0xffff8080ff818181,  0xfc00c00000000000,  0xf000000000000780,  0xc00000000000,  0xfffffffffc000000,  0xa08000001f07ff80,  0x24,  0x7fffc,  0xffff,  0x30000,  0xc000ffffffffff00,  0xff80fc000000,  0x20f08000080000,  0x6000000000000000,  0xc1ff8080e3030303,  0x4800008000001000,  0xffffffffc000c000,  0x70000000000078,  0xfffffffff000f800,  0xc00000000000ffff,  0xfffffffffffe0000,  0xfff080000000,  0xfffffffffffff800,  0x40000000,  0xffffffffffc000f0,  0xfffffc00c0000000,  0x6e400000000002c0,  0xffffffff00400000,  0x7c00000070000000,  0x3f00000000000000,  0x78f0000001100f90,  0xfe00ff00,  0x1c0000000000000,  0xf8000000c00000,  0xfffffffffffffe00,  0x80000000ffffffff,  0xffff00000003c000,  0xfc00fe000000fffc,  0xfffffffffffffff0,  0xfffffffffc00fe00,  0xfffffffffffffc00,  0xffff800000000000,  0xfff0fff800000000,  0xfe00000000000000,  0x800000000000ffe0,  0xffffffff00007fff,  0xfffffffffffffffc,  0x18000000000,  0xffffffffc0000000,  0xffffffffffffffc0,  0xfffc0000ff800000,  0x200000,  0x1400219b20000000,  0x10,  0x8400000020201840,  0x203a0,  0xc000000000,  0x3000,  0xf508016900000010,  0xa10808695569157b,  0xf0000411f0000400,  0xfffcffffffffffff,  0x80018000fff00000,  0xffffffff00010001,  0x80000000f800,  0xfffffffff8000000,  0x3fffffffff,  0xf80000000000fff8,  0xfffffffffffcfe00,  0x40fffe00000000,  0xe000000000000000,  0xfff00000,  0xfffe0000fffff820,  0x2,  0xe100000000000000,  0xc000000000000000,  0xffffff000000fff0,  0x7ffffffffffffff,  0xffffffffffff001e,  0xffffffffff800000,  0xfffffffd,  0xffff000000000000,  0xc000000000000000]);
+enum MAX_SIMPLE_LOWER = 1043;
+enum MAX_SIMPLE_UPPER = 1051;
+enum MAX_SIMPLE_TITLE = 1055;
+//8192 bytes
+enum toUpperIndexTrieEntries = TrieEntry!(ushort, 8, 7, 6)([ 0x0,  0x20,  0x100], [ 0x100,  0x380,  0xc00], [ 0x402030202020100,  0x202020202020205,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x3000200010000,  0x7000600050004,  0xa00090008,  0xd000c000b0000,  0x110010000f000e,  0x1400130012,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x150000,  0x19001800170016,  0x1d001c001b001a,  0x0,  0x1f001e0000,  0x0,  0x0,  0x20000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x24002300220021,  0x25,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2700260000,  0x2a00290028,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2b,  0x0,  0x0,  0x0,  0x2c0000,  0x0,  0x0,  0x0,  0x0,  0x2e002d,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x200010000ffff,  0x6000500040003,  0xa000900080007,  0xe000d000c000b,  0x1200110010000f,  0x16001500140013,  0xffff001900180017,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff001affff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x41bffffffffffff,  0x1e001d001c001b,  0x2200210020001f,  0x26002500240023,  0x2a002900280027,  0x2e002d002c002b,  0xffff00310030002f,  0x35003400330032,  0x39003800370036,  0x3bffff003affff,  0x3dffff003cffff,  0x3fffff003effff,  0x41ffff0040ffff,  0x43ffff0042ffff,  0x45ffff0044ffff,  0x47ffff0046ffff,  0x49ffff0048ffff,  0x4bffff004affff,  0x4dffff004cffff,  0x4fffff004effff,  0x51ffff0050ffff,  0x53ffff0052041d,  0x55ffff0054ffff,  0xffff0056ffffffff,  0xffff0058ffff0057,  0xffff005affff0059,  0xffff005cffff005b,  0x5effff043a005d,  0x60ffff005fffff,  0x62ffff0061ffff,  0x64ffff0063ffff,  0x66ffff0065ffff,  0x68ffff0067ffff,  0x6affff0069ffff,  0x6cffff006bffff,  0x6effff006dffff,  0x70ffff006fffff,  0x72ffff0071ffff,  0x74ffff0073ffff,  0xffff0075ffffffff,  0x780077ffff0076,  0x7affffffff0079,  0xffffffff007bffff,  0xffffffffffff007c,  0xffffffffffff007d,  0xffff007effffffff,  0xffffffff007fffff,  0xffff00810080ffff,  0xffff0082ffffffff,  0x84ffff0083ffff,  0xffffffff0085ffff,  0xffffffffffff0086,  0xffffffff0087ffff,  0xffffffffffff0088,  0xffff008affff0089,  0xffffffff008bffff,  0x8dffff008cffff,  0xffffffffffffffff,  0xffff008f008effff,  0x92ffff00910090,  0xffff0094ffff0093,  0xffff0096ffff0095,  0xffff0098ffff0097,  0xffff009affff0099,  0x9dffff009c009b,  0x9fffff009effff,  0xa1ffff00a0ffff,  0xa3ffff00a2ffff,  0xa5ffff00a4ffff,  0xa700a6ffff0442,  0xffffffff00a8ffff,  0xaaffff00a9ffff,  0xacffff00abffff,  0xaeffff00adffff,  0xb0ffff00afffff,  0xb2ffff00b1ffff,  0xb4ffff00b3ffff,  0xb6ffff00b5ffff,  0xb8ffff00b7ffff,  0xbaffff00b9ffff,  0xbcffff00bbffff,  0xbdffffffffffff,  0xbfffff00beffff,  0xc1ffff00c0ffff,  0xc3ffff00c2ffff,  0xc5ffff00c4ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xc7ffffffff00c6,  0xffff00c9ffff00c8,  0xcaffffffffffff,  0xccffff00cbffff,  0xceffff00cdffff,  0xd200d100d000cf,  0xd500d4ffff00d3,  0xd7ffff00d6ffff,  0xffffffffffffffff,  0xd9ffffffff00d8,  0xffff00db00daffff,  0xdeffff00dd00dc,  0xdfffffffffffff,  0xffff00e100e0ffff,  0xffffffff00e2ffff,  0xffffffffffffffff,  0xffffffff00e3ffff,  0xe5ffffffff00e4,  0xffffffffffffffff,  0xe900e800e700e6,  0xffffffffffff00ea,  0xffff00ebffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff00ecffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xeeffff00edffff,  0xefffffffffffff,  0xf0ffffffffffff,  0xffffffff00f200f1,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffff043c,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xf600f500f400f3,  0xf900f800f7043f,  0xfd00fc00fb00fa,  0x101010000ff00fe,  0x105010401030102,  0x109010801070106,  0x10d010c010b010a,  0x1110110010f010e,  0xffff011401130112,  0xffffffff01160115,  0x11901180117ffff,  0x11bffff011affff,  0x11dffff011cffff,  0x11fffff011effff,  0x121ffff0120ffff,  0x123ffff0122ffff,  0x125ffff0124ffff,  0xffff012801270126,  0xffffffff0129ffff,  0x12bffffffff012a,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x12f012e012d012c,  0x133013201310130,  0x137013601350134,  0x13b013a01390138,  0x13f013e013d013c,  0x143014201410140,  0x147014601450144,  0x14b014a01490148,  0x14f014e014d014c,  0x153015201510150,  0x157015601550154,  0x15b015a01590158,  0x15dffff015cffff,  0x15fffff015effff,  0x161ffff0160ffff,  0x163ffff0162ffff,  0x165ffff0164ffff,  0x167ffff0166ffff,  0x169ffff0168ffff,  0x16bffff016affff,  0xffffffff016cffff,  0xffffffffffffffff,  0x16dffffffffffff,  0x16fffff016effff,  0x171ffff0170ffff,  0x173ffff0172ffff,  0x175ffff0174ffff,  0x177ffff0176ffff,  0x179ffff0178ffff,  0x17bffff017affff,  0x17dffff017cffff,  0x17fffff017effff,  0x181ffff0180ffff,  0x183ffff0182ffff,  0x185ffff0184ffff,  0x187ffff0186ffff,  0xffff0188ffffffff,  0xffff018affff0189,  0xffff018cffff018b,  0x18f018effff018d,  0x191ffff0190ffff,  0x193ffff0192ffff,  0x195ffff0194ffff,  0x197ffff0196ffff,  0x199ffff0198ffff,  0x19bffff019affff,  0x19dffff019cffff,  0x19fffff019effff,  0x1a1ffff01a0ffff,  0x1a3ffff01a2ffff,  0x1a5ffff01a4ffff,  0x1a7ffff01a6ffff,  0x1a9ffff01a8ffff,  0x1abffff01aaffff,  0x1adffff01acffff,  0x1afffff01aeffff,  0x1b1ffff01b0ffff,  0x1b3ffff01b2ffff,  0x1b5ffff01b4ffff,  0x1b7ffff01b6ffff,  0x1b9ffff01b8ffff,  0x1bbffff01baffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x1be01bd01bcffff,  0x1c201c101c001bf,  0x1c601c501c401c3,  0x1ca01c901c801c7,  0x1ce01cd01cc01cb,  0x1d201d101d001cf,  0x1d601d501d401d3,  0x1da01d901d801d7,  0x1de01dd01dc01db,  0x42e01e101e001df,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff01e2ffff,  0xffffffff01e3ffff,  0x1e5ffff01e4ffff,  0x1e7ffff01e6ffff,  0x1e9ffff01e8ffff,  0x1ebffff01eaffff,  0x1edffff01ecffff,  0x1efffff01eeffff,  0x1f1ffff01f0ffff,  0x1f3ffff01f2ffff,  0x1f5ffff01f4ffff,  0x1f7ffff01f6ffff,  0x1f9ffff01f8ffff,  0x1fbffff01faffff,  0x1fdffff01fcffff,  0x1ffffff01feffff,  0x201ffff0200ffff,  0x203ffff0202ffff,  0x205ffff0204ffff,  0x207ffff0206ffff,  0x209ffff0208ffff,  0x20bffff020affff,  0x20dffff020cffff,  0x20fffff020effff,  0x211ffff0210ffff,  0x213ffff0212ffff,  0x215ffff0214ffff,  0x217ffff0216ffff,  0x219ffff0218ffff,  0x21bffff021affff,  0x21dffff021cffff,  0x21fffff021effff,  0x221ffff0220ffff,  0x223ffff0222ffff,  0x225ffff0224ffff,  0x227ffff0226ffff,  0x229ffff0228ffff,  0x22bffff022affff,  0x22dffff022cffff,  0x4460444022effff,  0x22f044c044a0448,  0xffffffffffffffff,  0x231ffff0230ffff,  0x233ffff0232ffff,  0x235ffff0234ffff,  0x237ffff0236ffff,  0x239ffff0238ffff,  0x23bffff023affff,  0x23dffff023cffff,  0x23fffff023effff,  0x241ffff0240ffff,  0x243ffff0242ffff,  0x245ffff0244ffff,  0x247ffff0246ffff,  0x249ffff0248ffff,  0x24bffff024affff,  0x24dffff024cffff,  0x24fffff024effff,  0x251ffff0250ffff,  0x253ffff0252ffff,  0x255ffff0254ffff,  0x257ffff0256ffff,  0x259ffff0258ffff,  0x25bffff025affff,  0x25dffff025cffff,  0x25fffff025effff,  0x263026202610260,  0x267026602650264,  0xffffffffffffffff,  0xffffffffffffffff,  0x26b026a02690268,  0xffffffff026d026c,  0xffffffffffffffff,  0xffffffffffffffff,  0x2710270026f026e,  0x275027402730272,  0xffffffffffffffff,  0xffffffffffffffff,  0x279027802770276,  0x27d027c027b027a,  0xffffffffffffffff,  0xffffffffffffffff,  0x2810280027f027e,  0xffffffff02830282,  0xffffffffffffffff,  0xffffffffffffffff,  0x28504500284044e,  0x287045602860453,  0xffffffffffffffff,  0xffffffffffffffff,  0x28b028a02890288,  0x28f028e028d028c,  0xffffffffffffffff,  0xffffffffffffffff,  0x293029202910290,  0x297029602950294,  0x29b029a02990298,  0xffffffff029d029c,  0x47d047b04790477,  0x48504830481047f,  0x48d048b04890487,  0x49504930491048f,  0x49d049b04990497,  0x4a504a304a1049f,  0x4ad04ab04a904a7,  0x4b504b304b104af,  0x4bd04bb04b904b7,  0x4c504c304c104bf,  0x4cd04cb04c904c7,  0x4d504d304d104cf,  0x4d704e302b702b6,  0x4ef0459ffff04e5,  0xffffffffffffffff,  0xffff02b9ffff04d9,  0x4db04e7ffffffff,  0x4f2045bffff04e9,  0xffffffffffffffff,  0xffffffffffff04dd,  0x460045d02bc02bb,  0x4650463ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x46b046802be02bd,  0x472047002bf046e,  0xffffffffffffffff,  0xffffffffffffffff,  0x4df04ebffffffff,  0x4f50475ffff04ed,  0xffffffffffffffff,  0xffffffffffff04e1,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff02c1ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x2c502c402c302c2,  0x2c902c802c702c6,  0x2cd02cc02cb02ca,  0x2d102d002cf02ce,  0xffffffffffffffff,  0xffffffffffff02d2,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x2d602d502d402d3,  0x2da02d902d802d7,  0x2de02dd02dc02db,  0x2e202e102e002df,  0x2e602e502e402e3,  0x2ea02e902e802e7,  0xffffffff02ec02eb,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x2f002ef02ee02ed,  0x2f402f302f202f1,  0x2f802f702f602f5,  0x2fc02fb02fa02f9,  0x30002ff02fe02fd,  0x304030303020301,  0x308030703060305,  0x30c030b030a0309,  0x310030f030e030d,  0x314031303120311,  0x318031703160315,  0xffff031b031a0319,  0xffffffff031cffff,  0xffff031e031dffff,  0xffff0320ffff031f,  0xffffffffffff0321,  0x322ffffffffffff,  0xffff0323ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x325ffff0324ffff,  0x327ffff0326ffff,  0x329ffff0328ffff,  0x32bffff032affff,  0x32dffff032cffff,  0x32fffff032effff,  0x331ffff0330ffff,  0x333ffff0332ffff,  0x335ffff0334ffff,  0x337ffff0336ffff,  0x339ffff0338ffff,  0x33bffff033affff,  0x33dffff033cffff,  0x33fffff033effff,  0x341ffff0340ffff,  0x343ffff0342ffff,  0x345ffff0344ffff,  0x347ffff0346ffff,  0x349ffff0348ffff,  0x34bffff034affff,  0x34dffff034cffff,  0x34fffff034effff,  0x351ffff0350ffff,  0x353ffff0352ffff,  0x355ffff0354ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff0357ffff0356,  0x358ffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x35c035b035a0359,  0x360035f035e035d,  0x364036303620361,  0x368036703660365,  0x36c036b036a0369,  0x370036f036e036d,  0x374037303720371,  0x378037703760375,  0x37c037b037a0379,  0x37fffff037e037d,  0xffffffffffffffff,  0xffffffff0380ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x382ffff0381ffff,  0x384ffff0383ffff,  0x386ffff0385ffff,  0x388ffff0387ffff,  0x38affff0389ffff,  0x38cffff038bffff,  0x38effff038dffff,  0x390ffff038fffff,  0x392ffff0391ffff,  0x394ffff0393ffff,  0x396ffff0395ffff,  0xffffffff0397ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x399ffff0398ffff,  0x39bffff039affff,  0x39dffff039cffff,  0x39fffff039effff,  0x3a1ffff03a0ffff,  0x3a3ffff03a2ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x3a4ffffffffffff,  0x3a6ffff03a5ffff,  0x3a8ffff03a7ffff,  0x3aaffff03a9ffff,  0x3abffffffffffff,  0x3adffff03acffff,  0x3afffff03aeffff,  0x3b1ffff03b0ffff,  0x3b3ffff03b2ffff,  0x3b5ffff03b4ffff,  0x3b7ffff03b6ffff,  0x3b9ffff03b8ffff,  0x3bbffff03baffff,  0x3bdffff03bcffff,  0x3bfffff03beffff,  0x3c1ffff03c0ffff,  0x3c3ffff03c2ffff,  0x3c5ffff03c4ffff,  0x3c7ffff03c6ffff,  0x3c9ffff03c8ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff03caffffffff,  0x3ccffffffff03cb,  0x3ceffff03cdffff,  0x3d0ffff03cfffff,  0xffffffffffffffff,  0xffffffffffff03d1,  0x3d3ffff03d2ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x3d5ffff03d4ffff,  0x3d7ffff03d6ffff,  0xffffffff03d8ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x42404220420041e,  0xffff042c042a0427,  0xffffffffffffffff,  0xffffffffffffffff,  0x430ffffffffffff,  0x438043604340432,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x3db03da03d9ffff,  0x3df03de03dd03dc,  0x3e303e203e103e0,  0x3e703e603e503e4,  0x3eb03ea03e903e8,  0x3ef03ee03ed03ec,  0xffff03f203f103f0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x3f603f503f403f3,  0x3fa03f903f803f7,  0x3fe03fd03fc03fb,  0x4020401040003ff,  0x406040504040403,  0x40a040904080407,  0x40e040d040c040b,  0x41204110410040f,  0x416041504140413,  0x41a041904180417,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff]);
+//8064 bytes
+enum toLowerIndexTrieEntries = TrieEntry!(ushort, 8, 7, 6)([ 0x0,  0x20,  0x100], [ 0x100,  0x380,  0xbc0], [ 0x402030202020100,  0x202020202020205,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x2000000010000,  0x6000500040003,  0x80007,  0xb000a00090000,  0xf000e000d000c,  0x1200110010,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x14001300000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18001700160015,  0x1c001b001a0019,  0x0,  0x1f001e001d,  0x0,  0x0,  0x21002000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x25002400230022,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2700260000,  0x2a00290028,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2b,  0x0,  0x0,  0x0,  0x2c,  0x0,  0x0,  0x0,  0x0,  0x2d,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x200010000ffff,  0x6000500040003,  0xa000900080007,  0xe000d000c000b,  0x1200110010000f,  0x16001500140013,  0xffff001900180017,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x1d001c001b001a,  0x210020001f001e,  0x25002400230022,  0x29002800270026,  0x2d002c002b002a,  0xffff0030002f002e,  0x34003300320031,  0x413003700360035,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff0039ffff0038,  0xffff003bffff003a,  0xffff003dffff003c,  0xffff003fffff003e,  0xffff0041ffff0040,  0xffff0043ffff0042,  0xffff0045ffff0044,  0xffff0047ffff0046,  0xffff0049ffff0048,  0xffff004bffff004a,  0xffff004dffff004c,  0xffff004fffff004e,  0xffff0051ffff0414,  0xffff0053ffff0052,  0x55ffff0054ffff,  0x57ffff0056ffff,  0x59ffff0058ffff,  0x5bffff005affff,  0xffff005c0423ffff,  0xffff005effff005d,  0xffff0060ffff005f,  0xffff0062ffff0061,  0xffff0064ffff0063,  0xffff0066ffff0065,  0xffff0068ffff0067,  0xffff006affff0069,  0xffff006cffff006b,  0xffff006effff006d,  0xffff0070ffff006f,  0xffff0072ffff0071,  0x75ffff00740073,  0xffffffff0076ffff,  0xffff00780077ffff,  0x7b007affff0079,  0x7e007d007cffff,  0x80007fffffffff,  0x83ffff00820081,  0x860085ffff0084,  0xffffffffffff0087,  0x8affff00890088,  0xffff008cffff008b,  0x8f008effff008d,  0xffffffff0090ffff,  0x930092ffff0091,  0x9600950094ffff,  0x98ffff0097ffff,  0xffffffffffff0099,  0xffffffffffff009a,  0xffffffffffffffff,  0x9dffff009c009b,  0xa0009fffff009e,  0xa2ffff00a1ffff,  0xa4ffff00a3ffff,  0xa6ffff00a5ffff,  0xa8ffff00a7ffff,  0xffff00a9ffffffff,  0xffff00abffff00aa,  0xffff00adffff00ac,  0xffff00afffff00ae,  0xffff00b1ffff00b0,  0xffff00b300b20426,  0xb600b5ffff00b4,  0xffff00b8ffff00b7,  0xffff00baffff00b9,  0xffff00bcffff00bb,  0xffff00beffff00bd,  0xffff00c0ffff00bf,  0xffff00c2ffff00c1,  0xffff00c4ffff00c3,  0xffff00c6ffff00c5,  0xffff00c8ffff00c7,  0xffff00caffff00c9,  0xffff00ccffff00cb,  0xffff00ceffff00cd,  0xffff00d0ffff00cf,  0xffff00d2ffff00d1,  0xffff00d4ffff00d3,  0xffffffffffffffff,  0xd600d5ffffffff,  0xffff00d800d7ffff,  0xdaffff00d9ffff,  0xffff00dd00dc00db,  0xffff00dfffff00de,  0xffff00e1ffff00e0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff00e3ffff00e2,  0xffff00e4ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff00e5ffffffff,  0xffff00e800e700e6,  0xeb00eaffff00e9,  0xee00ed00ec0424,  0xf200f100f000ef,  0xf600f500f400f3,  0xfa00f900f800f7,  0xfdffff00fc00fb,  0x101010000ff00fe,  0x105010401030102,  0xffffffffffffffff,  0xffffffffffff0425,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x106ffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff0108ffff0107,  0xffff010affff0109,  0xffff010cffff010b,  0xffff010effff010d,  0xffff0110ffff010f,  0xffff0112ffff0111,  0xffffffffffffffff,  0x114ffffffff0113,  0xffff01160115ffff,  0x11901180117ffff,  0x11d011c011b011a,  0x1210120011f011e,  0x125012401230122,  0x129012801270126,  0x12d012c012b012a,  0x1310130012f012e,  0x135013401330132,  0x139013801370136,  0x13d013c013b013a,  0x1410140013f013e,  0x145014401430142,  0x149014801470146,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff014bffff014a,  0xffff014dffff014c,  0xffff014fffff014e,  0xffff0151ffff0150,  0xffff0153ffff0152,  0xffff0155ffff0154,  0xffff0157ffff0156,  0xffff0159ffff0158,  0xffffffffffff015a,  0xffffffffffffffff,  0xffff015bffffffff,  0xffff015dffff015c,  0xffff015fffff015e,  0xffff0161ffff0160,  0xffff0163ffff0162,  0xffff0165ffff0164,  0xffff0167ffff0166,  0xffff0169ffff0168,  0xffff016bffff016a,  0xffff016dffff016c,  0xffff016fffff016e,  0xffff0171ffff0170,  0xffff0173ffff0172,  0xffff0175ffff0174,  0x178ffff01770176,  0x17affff0179ffff,  0x17cffff017bffff,  0xffffffff017dffff,  0xffff017fffff017e,  0xffff0181ffff0180,  0xffff0183ffff0182,  0xffff0185ffff0184,  0xffff0187ffff0186,  0xffff0189ffff0188,  0xffff018bffff018a,  0xffff018dffff018c,  0xffff018fffff018e,  0xffff0191ffff0190,  0xffff0193ffff0192,  0xffff0195ffff0194,  0xffff0197ffff0196,  0xffff0199ffff0198,  0xffff019bffff019a,  0xffff019dffff019c,  0xffff019fffff019e,  0xffff01a1ffff01a0,  0xffff01a3ffff01a2,  0xffff01a5ffff01a4,  0xffff01a7ffff01a6,  0xffff01a9ffff01a8,  0xffffffffffffffff,  0xffffffffffffffff,  0x1ac01ab01aaffff,  0x1b001af01ae01ad,  0x1b401b301b201b1,  0x1b801b701b601b5,  0x1bc01bb01ba01b9,  0x1c001bf01be01bd,  0x1c401c301c201c1,  0x1c801c701c601c5,  0x1cc01cb01ca01c9,  0xffff01cf01ce01cd,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x41dffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x1d301d201d101d0,  0x1d701d601d501d4,  0x1db01da01d901d8,  0x1df01de01dd01dc,  0x1e301e201e101e0,  0x1e701e601e501e4,  0x1eb01ea01e901e8,  0x1ef01ee01ed01ec,  0x1f301f201f101f0,  0x1f6ffff01f501f4,  0xffffffffffffffff,  0xffffffff01f7ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff01f9ffff01f8,  0xffff01fbffff01fa,  0xffff01fdffff01fc,  0xffff01ffffff01fe,  0xffff0201ffff0200,  0xffff0203ffff0202,  0xffff0205ffff0204,  0xffff0207ffff0206,  0xffff0209ffff0208,  0xffff020bffff020a,  0xffff020dffff020c,  0xffff020fffff020e,  0xffff0211ffff0210,  0xffff0213ffff0212,  0xffff0215ffff0214,  0xffff0217ffff0216,  0xffff0219ffff0218,  0xffff021bffff021a,  0xffff021dffff021c,  0xffff021fffff021e,  0xffff0221ffff0220,  0xffff0223ffff0222,  0xffff0225ffff0224,  0xffff0227ffff0226,  0xffff0229ffff0228,  0xffff022bffff022a,  0xffff022dffff022c,  0xffff022fffff022e,  0xffff0231ffff0230,  0xffff0233ffff0232,  0xffff0235ffff0234,  0xffff0237ffff0236,  0xffff0239ffff0238,  0xffff023bffff023a,  0xffff023dffff023c,  0xffff023fffff023e,  0xffff0241ffff0240,  0x4280427ffff0242,  0xffff042b042a0429,  0xffff0243ffffffff,  0xffff0245ffff0244,  0xffff0247ffff0246,  0xffff0249ffff0248,  0xffff024bffff024a,  0xffff024dffff024c,  0xffff024fffff024e,  0xffff0251ffff0250,  0xffff0253ffff0252,  0xffff0255ffff0254,  0xffff0257ffff0256,  0xffff0259ffff0258,  0xffff025bffff025a,  0xffff025dffff025c,  0xffff025fffff025e,  0xffff0261ffff0260,  0xffff0263ffff0262,  0xffff0265ffff0264,  0xffff0267ffff0266,  0xffff0269ffff0268,  0xffff026bffff026a,  0xffff026dffff026c,  0xffff026fffff026e,  0xffff0271ffff0270,  0xffff0273ffff0272,  0xffffffffffffffff,  0xffffffffffffffff,  0x277027602750274,  0x27b027a02790278,  0xffffffffffffffff,  0xffffffffffffffff,  0x27f027e027d027c,  0xffffffff02810280,  0xffffffffffffffff,  0xffffffffffffffff,  0x285028402830282,  0x289028802870286,  0xffffffffffffffff,  0xffffffffffffffff,  0x28d028c028b028a,  0x2910290028f028e,  0xffffffffffffffff,  0xffffffffffffffff,  0x295029402930292,  0xffffffff02970296,  0xffff042dffff042c,  0xffff042fffff042e,  0x299ffff0298ffff,  0x29bffff029affff,  0xffffffffffffffff,  0xffffffffffffffff,  0x29f029e029d029c,  0x2a302a202a102a0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x43f043e043d043c,  0x443044204410440,  0x447044604450444,  0x44b044a04490448,  0x44f044e044d044c,  0x453045204510450,  0x457045604550454,  0x45b045a04590458,  0x45f045e045d045c,  0x463046204610460,  0x467046604650464,  0x46b046a04690468,  0x46c0472ffffffff,  0x4780430ffff0473,  0x2bf02be02bd02bc,  0xffffffffffff046d,  0x46e0474ffffffff,  0x4790431ffff0475,  0x2c402c302c202c1,  0xffffffffffff046f,  0x4330432ffffffff,  0x4350434ffffffff,  0x2c902c802c702c6,  0xffffffffffffffff,  0x4370436ffffffff,  0x43a0439ffff0438,  0x2cd02cc02cb02ca,  0xffffffffffff02ce,  0x4700476ffffffff,  0x47a043bffff0477,  0x2d202d102d002cf,  0xffffffffffff0471,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff02d4ffffffff,  0x2d602d5ffffffff,  0xffffffffffffffff,  0xffff02d7ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x2db02da02d902d8,  0x2df02de02dd02dc,  0x2e302e202e102e0,  0x2e702e602e502e4,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x2e8ffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x2ea02e9ffffffff,  0x2ee02ed02ec02eb,  0x2f202f102f002ef,  0x2f602f502f402f3,  0x2fa02f902f802f7,  0x2fe02fd02fc02fb,  0x3020301030002ff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x306030503040303,  0x30a030903080307,  0x30e030d030c030b,  0x31203110310030f,  0x316031503140313,  0x31a031903180317,  0x31e031d031c031b,  0x32203210320031f,  0x326032503240323,  0x32a032903280327,  0x32e032d032c032b,  0xffff03310330032f,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x3340333ffff0332,  0x336ffffffff0335,  0x338ffff0337ffff,  0x33b033a0339ffff,  0xffff033dffff033c,  0xffffffff033effff,  0xffffffffffffffff,  0x340033fffffffff,  0xffff0342ffff0341,  0xffff0344ffff0343,  0xffff0346ffff0345,  0xffff0348ffff0347,  0xffff034affff0349,  0xffff034cffff034b,  0xffff034effff034d,  0xffff0350ffff034f,  0xffff0352ffff0351,  0xffff0354ffff0353,  0xffff0356ffff0355,  0xffff0358ffff0357,  0xffff035affff0359,  0xffff035cffff035b,  0xffff035effff035d,  0xffff0360ffff035f,  0xffff0362ffff0361,  0xffff0364ffff0363,  0xffff0366ffff0365,  0xffff0368ffff0367,  0xffff036affff0369,  0xffff036cffff036b,  0xffff036effff036d,  0xffff0370ffff036f,  0xffff0372ffff0371,  0xffffffffffffffff,  0x373ffffffffffff,  0xffffffff0374ffff,  0xffff0375ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff0377ffff0376,  0xffff0379ffff0378,  0xffff037bffff037a,  0xffff037dffff037c,  0xffff037fffff037e,  0xffff0381ffff0380,  0xffff0383ffff0382,  0xffff0385ffff0384,  0xffff0387ffff0386,  0xffff0389ffff0388,  0xffff038bffff038a,  0xffffffffffff038c,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff038effff038d,  0xffff0390ffff038f,  0xffff0392ffff0391,  0xffff0394ffff0393,  0xffff0396ffff0395,  0xffff0398ffff0397,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff0399ffffffff,  0xffff039bffff039a,  0xffff039dffff039c,  0xffff039fffff039e,  0xffff03a0ffffffff,  0xffff03a2ffff03a1,  0xffff03a4ffff03a3,  0xffff03a6ffff03a5,  0xffff03a8ffff03a7,  0xffff03aaffff03a9,  0xffff03acffff03ab,  0xffff03aeffff03ad,  0xffff03b0ffff03af,  0xffff03b2ffff03b1,  0xffff03b4ffff03b3,  0xffff03b6ffff03b5,  0xffff03b8ffff03b7,  0xffff03baffff03b9,  0xffff03bcffff03bb,  0xffff03beffff03bd,  0xffffffffffffffff,  0xffffffffffffffff,  0x3c0ffff03bfffff,  0xffff03c203c1ffff,  0xffff03c4ffff03c3,  0xffff03c6ffff03c5,  0x3c7ffffffffffff,  0xffffffff03c8ffff,  0xffff03caffff03c9,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff03ccffff03cb,  0xffff03ceffff03cd,  0xffff03d0ffff03cf,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x419041804170416,  0xffff041c041b041a,  0xffffffffffffffff,  0xffffffffffffffff,  0x41effffffffffff,  0x42204210420041f,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x3d303d203d1ffff,  0x3d703d603d503d4,  0x3db03da03d903d8,  0x3df03de03dd03dc,  0x3e303e203e103e0,  0x3e703e603e503e4,  0xffff03ea03e903e8,  0xffffffffffffffff,  0x3ee03ed03ec03eb,  0x3f203f103f003ef,  0x3f603f503f403f3,  0x3fa03f903f803f7,  0x3fe03fd03fc03fb,  0x4020401040003ff,  0x406040504040403,  0x40a040904080407,  0x40e040d040c040b,  0x41204110410040f,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff]);
+//8192 bytes
+enum toTitleIndexTrieEntries = TrieEntry!(ushort, 8, 7, 6)([ 0x0,  0x20,  0x100], [ 0x100,  0x380,  0xc00], [ 0x402030202020100,  0x202020202020205,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x3000200010000,  0x7000600050004,  0xa00090008,  0xd000c000b0000,  0x110010000f000e,  0x1400130012,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x150000,  0x19001800170016,  0x1d001c001b001a,  0x0,  0x1f001e0000,  0x0,  0x0,  0x20000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x24002300220021,  0x25,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2700260000,  0x2a00290028,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2b,  0x0,  0x0,  0x0,  0x2c0000,  0x0,  0x0,  0x0,  0x0,  0x2e002d,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x200010000ffff,  0x6000500040003,  0xa000900080007,  0xe000d000c000b,  0x1200110010000f,  0x16001500140013,  0xffff001900180017,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff001affff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x41fffffffffffff,  0x1e001d001c001b,  0x2200210020001f,  0x26002500240023,  0x2a002900280027,  0x2e002d002c002b,  0xffff00310030002f,  0x35003400330032,  0x39003800370036,  0x3bffff003affff,  0x3dffff003cffff,  0x3fffff003effff,  0x41ffff0040ffff,  0x43ffff0042ffff,  0x45ffff0044ffff,  0x47ffff0046ffff,  0x49ffff0048ffff,  0x4bffff004affff,  0x4dffff004cffff,  0x4fffff004effff,  0x51ffff0050ffff,  0x53ffff00520421,  0x55ffff0054ffff,  0xffff0056ffffffff,  0xffff0058ffff0057,  0xffff005affff0059,  0xffff005cffff005b,  0x5effff043e005d,  0x60ffff005fffff,  0x62ffff0061ffff,  0x64ffff0063ffff,  0x66ffff0065ffff,  0x68ffff0067ffff,  0x6affff0069ffff,  0x6cffff006bffff,  0x6effff006dffff,  0x70ffff006fffff,  0x72ffff0071ffff,  0x74ffff0073ffff,  0xffff0075ffffffff,  0x780077ffff0076,  0x7affffffff0079,  0xffffffff007bffff,  0xffffffffffff007c,  0xffffffffffff007d,  0xffff007effffffff,  0xffffffff007fffff,  0xffff00810080ffff,  0xffff0082ffffffff,  0x84ffff0083ffff,  0xffffffff0085ffff,  0xffffffffffff0086,  0xffffffff0087ffff,  0xffffffffffff0088,  0xffff008affff0089,  0xffffffff008bffff,  0x8dffff008cffff,  0xffffffffffffffff,  0x910090008f008e,  0x95009400930092,  0xffff0097ffff0096,  0xffff0099ffff0098,  0xffff009bffff009a,  0xffff009dffff009c,  0xa0ffff009f009e,  0xa2ffff00a1ffff,  0xa4ffff00a3ffff,  0xa6ffff00a5ffff,  0xa8ffff00a7ffff,  0xab00aa00a90446,  0xffffffff00acffff,  0xaeffff00adffff,  0xb0ffff00afffff,  0xb2ffff00b1ffff,  0xb4ffff00b3ffff,  0xb6ffff00b5ffff,  0xb8ffff00b7ffff,  0xbaffff00b9ffff,  0xbcffff00bbffff,  0xbeffff00bdffff,  0xc0ffff00bfffff,  0xc1ffffffffffff,  0xc3ffff00c2ffff,  0xc5ffff00c4ffff,  0xc7ffff00c6ffff,  0xc9ffff00c8ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xcbffffffff00ca,  0xffff00cdffff00cc,  0xceffffffffffff,  0xd0ffff00cfffff,  0xd2ffff00d1ffff,  0xd600d500d400d3,  0xd900d8ffff00d7,  0xdbffff00daffff,  0xffffffffffffffff,  0xddffffffff00dc,  0xffff00df00deffff,  0xe2ffff00e100e0,  0xe3ffffffffffff,  0xffff00e500e4ffff,  0xffffffff00e6ffff,  0xffffffffffffffff,  0xffffffff00e7ffff,  0xe9ffffffff00e8,  0xffffffffffffffff,  0xed00ec00eb00ea,  0xffffffffffff00ee,  0xffff00efffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff00f0ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xf2ffff00f1ffff,  0xf3ffffffffffff,  0xf4ffffffffffff,  0xffffffff00f600f5,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffff0440,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xfa00f900f800f7,  0xfd00fc00fb0443,  0x101010000ff00fe,  0x105010401030102,  0x109010801070106,  0x10d010c010b010a,  0x1110110010f010e,  0x115011401130112,  0xffff011801170116,  0xffffffff011a0119,  0x11d011c011bffff,  0x11fffff011effff,  0x121ffff0120ffff,  0x123ffff0122ffff,  0x125ffff0124ffff,  0x127ffff0126ffff,  0x129ffff0128ffff,  0xffff012c012b012a,  0xffffffff012dffff,  0x12fffffffff012e,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x133013201310130,  0x137013601350134,  0x13b013a01390138,  0x13f013e013d013c,  0x143014201410140,  0x147014601450144,  0x14b014a01490148,  0x14f014e014d014c,  0x153015201510150,  0x157015601550154,  0x15b015a01590158,  0x15f015e015d015c,  0x161ffff0160ffff,  0x163ffff0162ffff,  0x165ffff0164ffff,  0x167ffff0166ffff,  0x169ffff0168ffff,  0x16bffff016affff,  0x16dffff016cffff,  0x16fffff016effff,  0xffffffff0170ffff,  0xffffffffffffffff,  0x171ffffffffffff,  0x173ffff0172ffff,  0x175ffff0174ffff,  0x177ffff0176ffff,  0x179ffff0178ffff,  0x17bffff017affff,  0x17dffff017cffff,  0x17fffff017effff,  0x181ffff0180ffff,  0x183ffff0182ffff,  0x185ffff0184ffff,  0x187ffff0186ffff,  0x189ffff0188ffff,  0x18bffff018affff,  0xffff018cffffffff,  0xffff018effff018d,  0xffff0190ffff018f,  0x1930192ffff0191,  0x195ffff0194ffff,  0x197ffff0196ffff,  0x199ffff0198ffff,  0x19bffff019affff,  0x19dffff019cffff,  0x19fffff019effff,  0x1a1ffff01a0ffff,  0x1a3ffff01a2ffff,  0x1a5ffff01a4ffff,  0x1a7ffff01a6ffff,  0x1a9ffff01a8ffff,  0x1abffff01aaffff,  0x1adffff01acffff,  0x1afffff01aeffff,  0x1b1ffff01b0ffff,  0x1b3ffff01b2ffff,  0x1b5ffff01b4ffff,  0x1b7ffff01b6ffff,  0x1b9ffff01b8ffff,  0x1bbffff01baffff,  0x1bdffff01bcffff,  0x1bfffff01beffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x1c201c101c0ffff,  0x1c601c501c401c3,  0x1ca01c901c801c7,  0x1ce01cd01cc01cb,  0x1d201d101d001cf,  0x1d601d501d401d3,  0x1da01d901d801d7,  0x1de01dd01dc01db,  0x1e201e101e001df,  0x43201e501e401e3,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffff01e6ffff,  0xffffffff01e7ffff,  0x1e9ffff01e8ffff,  0x1ebffff01eaffff,  0x1edffff01ecffff,  0x1efffff01eeffff,  0x1f1ffff01f0ffff,  0x1f3ffff01f2ffff,  0x1f5ffff01f4ffff,  0x1f7ffff01f6ffff,  0x1f9ffff01f8ffff,  0x1fbffff01faffff,  0x1fdffff01fcffff,  0x1ffffff01feffff,  0x201ffff0200ffff,  0x203ffff0202ffff,  0x205ffff0204ffff,  0x207ffff0206ffff,  0x209ffff0208ffff,  0x20bffff020affff,  0x20dffff020cffff,  0x20fffff020effff,  0x211ffff0210ffff,  0x213ffff0212ffff,  0x215ffff0214ffff,  0x217ffff0216ffff,  0x219ffff0218ffff,  0x21bffff021affff,  0x21dffff021cffff,  0x21fffff021effff,  0x221ffff0220ffff,  0x223ffff0222ffff,  0x225ffff0224ffff,  0x227ffff0226ffff,  0x229ffff0228ffff,  0x22bffff022affff,  0x22dffff022cffff,  0x22fffff022effff,  0x231ffff0230ffff,  0x44a04480232ffff,  0x2330450044e044c,  0xffffffffffffffff,  0x235ffff0234ffff,  0x237ffff0236ffff,  0x239ffff0238ffff,  0x23bffff023affff,  0x23dffff023cffff,  0x23fffff023effff,  0x241ffff0240ffff,  0x243ffff0242ffff,  0x245ffff0244ffff,  0x247ffff0246ffff,  0x249ffff0248ffff,  0x24bffff024affff,  0x24dffff024cffff,  0x24fffff024effff,  0x251ffff0250ffff,  0x253ffff0252ffff,  0x255ffff0254ffff,  0x257ffff0256ffff,  0x259ffff0258ffff,  0x25bffff025affff,  0x25dffff025cffff,  0x25fffff025effff,  0x261ffff0260ffff,  0x263ffff0262ffff,  0x267026602650264,  0x26b026a02690268,  0xffffffffffffffff,  0xffffffffffffffff,  0x26f026e026d026c,  0xffffffff02710270,  0xffffffffffffffff,  0xffffffffffffffff,  0x275027402730272,  0x279027802770276,  0xffffffffffffffff,  0xffffffffffffffff,  0x27d027c027b027a,  0x2810280027f027e,  0xffffffffffffffff,  0xffffffffffffffff,  0x285028402830282,  0xffffffff02870286,  0xffffffffffffffff,  0xffffffffffffffff,  0x289045402880452,  0x28b045a028a0457,  0xffffffffffffffff,  0xffffffffffffffff,  0x28f028e028d028c,  0x293029202910290,  0xffffffffffffffff,  0xffffffffffffffff,  0x297029602950294,  0x29b029a02990298,  0x29f029e029d029c,  0xffffffff02a102a0,  0x47e047d047c047b,  0x48204810480047f,  0x486048504840483,  0x48a048904880487,  0x48e048d048c048b,  0x49204910490048f,  0x496049504940493,  0x49a049904980497,  0x49e049d049c049b,  0x4a204a104a0049f,  0x4a604a504a404a3,  0x4aa04a904a804a7,  0x4ab04b102bb02ba,  0x4bd045dffff04b3,  0xffffffffffffffff,  0xffff02bdffff04ac,  0x4ad04b5ffffffff,  0x4c0045fffff04b7,  0xffffffffffffffff,  0xffffffffffff04ae,  0x464046102c002bf,  0x4690467ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x46f046c02c202c1,  0x476047402c30472,  0xffffffffffffffff,  0xffffffffffffffff,  0x4af04b9ffffffff,  0x4c30479ffff04bb,  0xffffffffffffffff,  0xffffffffffff04b0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff02c5ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x2c902c802c702c6,  0x2cd02cc02cb02ca,  0x2d102d002cf02ce,  0x2d502d402d302d2,  0xffffffffffffffff,  0xffffffffffff02d6,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x2da02d902d802d7,  0x2de02dd02dc02db,  0x2e202e102e002df,  0x2e602e502e402e3,  0x2ea02e902e802e7,  0x2ee02ed02ec02eb,  0xffffffff02f002ef,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x2f402f302f202f1,  0x2f802f702f602f5,  0x2fc02fb02fa02f9,  0x30002ff02fe02fd,  0x304030303020301,  0x308030703060305,  0x30c030b030a0309,  0x310030f030e030d,  0x314031303120311,  0x318031703160315,  0x31c031b031a0319,  0xffff031f031e031d,  0xffffffff0320ffff,  0xffff03220321ffff,  0xffff0324ffff0323,  0xffffffffffff0325,  0x326ffffffffffff,  0xffff0327ffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x329ffff0328ffff,  0x32bffff032affff,  0x32dffff032cffff,  0x32fffff032effff,  0x331ffff0330ffff,  0x333ffff0332ffff,  0x335ffff0334ffff,  0x337ffff0336ffff,  0x339ffff0338ffff,  0x33bffff033affff,  0x33dffff033cffff,  0x33fffff033effff,  0x341ffff0340ffff,  0x343ffff0342ffff,  0x345ffff0344ffff,  0x347ffff0346ffff,  0x349ffff0348ffff,  0x34bffff034affff,  0x34dffff034cffff,  0x34fffff034effff,  0x351ffff0350ffff,  0x353ffff0352ffff,  0x355ffff0354ffff,  0x357ffff0356ffff,  0x359ffff0358ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff035bffff035a,  0x35cffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x360035f035e035d,  0x364036303620361,  0x368036703660365,  0x36c036b036a0369,  0x370036f036e036d,  0x374037303720371,  0x378037703760375,  0x37c037b037a0379,  0x380037f037e037d,  0x383ffff03820381,  0xffffffffffffffff,  0xffffffff0384ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x386ffff0385ffff,  0x388ffff0387ffff,  0x38affff0389ffff,  0x38cffff038bffff,  0x38effff038dffff,  0x390ffff038fffff,  0x392ffff0391ffff,  0x394ffff0393ffff,  0x396ffff0395ffff,  0x398ffff0397ffff,  0x39affff0399ffff,  0xffffffff039bffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x39dffff039cffff,  0x39fffff039effff,  0x3a1ffff03a0ffff,  0x3a3ffff03a2ffff,  0x3a5ffff03a4ffff,  0x3a7ffff03a6ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x3a8ffffffffffff,  0x3aaffff03a9ffff,  0x3acffff03abffff,  0x3aeffff03adffff,  0x3afffffffffffff,  0x3b1ffff03b0ffff,  0x3b3ffff03b2ffff,  0x3b5ffff03b4ffff,  0x3b7ffff03b6ffff,  0x3b9ffff03b8ffff,  0x3bbffff03baffff,  0x3bdffff03bcffff,  0x3bfffff03beffff,  0x3c1ffff03c0ffff,  0x3c3ffff03c2ffff,  0x3c5ffff03c4ffff,  0x3c7ffff03c6ffff,  0x3c9ffff03c8ffff,  0x3cbffff03caffff,  0x3cdffff03ccffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff03ceffffffff,  0x3d0ffffffff03cf,  0x3d2ffff03d1ffff,  0x3d4ffff03d3ffff,  0xffffffffffffffff,  0xffffffffffff03d5,  0x3d7ffff03d6ffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x3d9ffff03d8ffff,  0x3dbffff03daffff,  0xffffffff03dcffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x428042604240422,  0xffff0430042e042b,  0xffffffffffffffff,  0xffffffffffffffff,  0x434ffffffffffff,  0x43c043a04380436,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x3df03de03ddffff,  0x3e303e203e103e0,  0x3e703e603e503e4,  0x3eb03ea03e903e8,  0x3ef03ee03ed03ec,  0x3f303f203f103f0,  0xffff03f603f503f4,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x3fa03f903f803f7,  0x3fe03fd03fc03fb,  0x4020401040003ff,  0x406040504040403,  0x40a040904080407,  0x40e040d040c040b,  0x41204110410040f,  0x416041504140413,  0x41a041904180417,  0x41e041d041c041b,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff]);
+@property
+{
+private alias _IUA = immutable(uint[]);
+_IUA toUpperTable() { static _IUA t = [ 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,  0x39c,  0xc0,  0xc1,  0xc2,  0xc3,  0xc4,  0xc5,  0xc6,  0xc7,  0xc8,  0xc9,  0xca,  0xcb,  0xcc,  0xcd,  0xce,  0xcf,  0xd0,  0xd1,  0xd2,  0xd3,  0xd4,  0xd5,  0xd6,  0xd8,  0xd9,  0xda,  0xdb,  0xdc,  0xdd,  0xde,  0x178,  0x100,  0x102,  0x104,  0x106,  0x108,  0x10a,  0x10c,  0x10e,  0x110,  0x112,  0x114,  0x116,  0x118,  0x11a,  0x11c,  0x11e,  0x120,  0x122,  0x124,  0x126,  0x128,  0x12a,  0x12c,  0x12e,  0x49,  0x132,  0x134,  0x136,  0x139,  0x13b,  0x13d,  0x13f,  0x141,  0x143,  0x145,  0x147,  0x14a,  0x14c,  0x14e,  0x150,  0x152,  0x154,  0x156,  0x158,  0x15a,  0x15c,  0x15e,  0x160,  0x162,  0x164,  0x166,  0x168,  0x16a,  0x16c,  0x16e,  0x170,  0x172,  0x174,  0x176,  0x179,  0x17b,  0x17d,  0x53,  0x243,  0x182,  0x184,  0x187,  0x18b,  0x191,  0x1f6,  0x198,  0x23d,  0x220,  0x1a0,  0x1a2,  0x1a4,  0x1a7,  0x1ac,  0x1af,  0x1b3,  0x1b5,  0x1b8,  0x1bc,  0x1f7,  0x1c4,  0x1c4,  0x1c7,  0x1c7,  0x1ca,  0x1ca,  0x1cd,  0x1cf,  0x1d1,  0x1d3,  0x1d5,  0x1d7,  0x1d9,  0x1db,  0x18e,  0x1de,  0x1e0,  0x1e2,  0x1e4,  0x1e6,  0x1e8,  0x1ea,  0x1ec,  0x1ee,  0x1f1,  0x1f1,  0x1f4,  0x1f8,  0x1fa,  0x1fc,  0x1fe,  0x200,  0x202,  0x204,  0x206,  0x208,  0x20a,  0x20c,  0x20e,  0x210,  0x212,  0x214,  0x216,  0x218,  0x21a,  0x21c,  0x21e,  0x222,  0x224,  0x226,  0x228,  0x22a,  0x22c,  0x22e,  0x230,  0x232,  0x23b,  0x2c7e,  0x2c7f,  0x241,  0x246,  0x248,  0x24a,  0x24c,  0x24e,  0x2c6f,  0x2c6d,  0x2c70,  0x181,  0x186,  0x189,  0x18a,  0x18f,  0x190,  0x193,  0x194,  0xa78d,  0xa7aa,  0x197,  0x196,  0x2c62,  0x19c,  0x2c6e,  0x19d,  0x19f,  0x2c64,  0x1a6,  0x1a9,  0x1ae,  0x244,  0x1b1,  0x1b2,  0x245,  0x1b7,  0x399,  0x370,  0x372,  0x376,  0x3fd,  0x3fe,  0x3ff,  0x386,  0x388,  0x389,  0x38a,  0x391,  0x392,  0x393,  0x394,  0x395,  0x396,  0x397,  0x398,  0x399,  0x39a,  0x39b,  0x39c,  0x39d,  0x39e,  0x39f,  0x3a0,  0x3a1,  0x3a3,  0x3a3,  0x3a4,  0x3a5,  0x3a6,  0x3a7,  0x3a8,  0x3a9,  0x3aa,  0x3ab,  0x38c,  0x38e,  0x38f,  0x392,  0x398,  0x3a6,  0x3a0,  0x3cf,  0x3d8,  0x3da,  0x3dc,  0x3de,  0x3e0,  0x3e2,  0x3e4,  0x3e6,  0x3e8,  0x3ea,  0x3ec,  0x3ee,  0x39a,  0x3a1,  0x3f9,  0x395,  0x3f7,  0x3fa,  0x410,  0x411,  0x412,  0x413,  0x414,  0x415,  0x416,  0x417,  0x418,  0x419,  0x41a,  0x41b,  0x41c,  0x41d,  0x41e,  0x41f,  0x420,  0x421,  0x422,  0x423,  0x424,  0x425,  0x426,  0x427,  0x428,  0x429,  0x42a,  0x42b,  0x42c,  0x42d,  0x42e,  0x42f,  0x400,  0x401,  0x402,  0x403,  0x404,  0x405,  0x406,  0x407,  0x408,  0x409,  0x40a,  0x40b,  0x40c,  0x40d,  0x40e,  0x40f,  0x460,  0x462,  0x464,  0x466,  0x468,  0x46a,  0x46c,  0x46e,  0x470,  0x472,  0x474,  0x476,  0x478,  0x47a,  0x47c,  0x47e,  0x480,  0x48a,  0x48c,  0x48e,  0x490,  0x492,  0x494,  0x496,  0x498,  0x49a,  0x49c,  0x49e,  0x4a0,  0x4a2,  0x4a4,  0x4a6,  0x4a8,  0x4aa,  0x4ac,  0x4ae,  0x4b0,  0x4b2,  0x4b4,  0x4b6,  0x4b8,  0x4ba,  0x4bc,  0x4be,  0x4c1,  0x4c3,  0x4c5,  0x4c7,  0x4c9,  0x4cb,  0x4cd,  0x4c0,  0x4d0,  0x4d2,  0x4d4,  0x4d6,  0x4d8,  0x4da,  0x4dc,  0x4de,  0x4e0,  0x4e2,  0x4e4,  0x4e6,  0x4e8,  0x4ea,  0x4ec,  0x4ee,  0x4f0,  0x4f2,  0x4f4,  0x4f6,  0x4f8,  0x4fa,  0x4fc,  0x4fe,  0x500,  0x502,  0x504,  0x506,  0x508,  0x50a,  0x50c,  0x50e,  0x510,  0x512,  0x514,  0x516,  0x518,  0x51a,  0x51c,  0x51e,  0x520,  0x522,  0x524,  0x526,  0x531,  0x532,  0x533,  0x534,  0x535,  0x536,  0x537,  0x538,  0x539,  0x53a,  0x53b,  0x53c,  0x53d,  0x53e,  0x53f,  0x540,  0x541,  0x542,  0x543,  0x544,  0x545,  0x546,  0x547,  0x548,  0x549,  0x54a,  0x54b,  0x54c,  0x54d,  0x54e,  0x54f,  0x550,  0x551,  0x552,  0x553,  0x554,  0x555,  0x556,  0xa77d,  0x2c63,  0x1e00,  0x1e02,  0x1e04,  0x1e06,  0x1e08,  0x1e0a,  0x1e0c,  0x1e0e,  0x1e10,  0x1e12,  0x1e14,  0x1e16,  0x1e18,  0x1e1a,  0x1e1c,  0x1e1e,  0x1e20,  0x1e22,  0x1e24,  0x1e26,  0x1e28,  0x1e2a,  0x1e2c,  0x1e2e,  0x1e30,  0x1e32,  0x1e34,  0x1e36,  0x1e38,  0x1e3a,  0x1e3c,  0x1e3e,  0x1e40,  0x1e42,  0x1e44,  0x1e46,  0x1e48,  0x1e4a,  0x1e4c,  0x1e4e,  0x1e50,  0x1e52,  0x1e54,  0x1e56,  0x1e58,  0x1e5a,  0x1e5c,  0x1e5e,  0x1e60,  0x1e62,  0x1e64,  0x1e66,  0x1e68,  0x1e6a,  0x1e6c,  0x1e6e,  0x1e70,  0x1e72,  0x1e74,  0x1e76,  0x1e78,  0x1e7a,  0x1e7c,  0x1e7e,  0x1e80,  0x1e82,  0x1e84,  0x1e86,  0x1e88,  0x1e8a,  0x1e8c,  0x1e8e,  0x1e90,  0x1e92,  0x1e94,  0x1e60,  0x1ea0,  0x1ea2,  0x1ea4,  0x1ea6,  0x1ea8,  0x1eaa,  0x1eac,  0x1eae,  0x1eb0,  0x1eb2,  0x1eb4,  0x1eb6,  0x1eb8,  0x1eba,  0x1ebc,  0x1ebe,  0x1ec0,  0x1ec2,  0x1ec4,  0x1ec6,  0x1ec8,  0x1eca,  0x1ecc,  0x1ece,  0x1ed0,  0x1ed2,  0x1ed4,  0x1ed6,  0x1ed8,  0x1eda,  0x1edc,  0x1ede,  0x1ee0,  0x1ee2,  0x1ee4,  0x1ee6,  0x1ee8,  0x1eea,  0x1eec,  0x1eee,  0x1ef0,  0x1ef2,  0x1ef4,  0x1ef6,  0x1ef8,  0x1efa,  0x1efc,  0x1efe,  0x1f08,  0x1f09,  0x1f0a,  0x1f0b,  0x1f0c,  0x1f0d,  0x1f0e,  0x1f0f,  0x1f18,  0x1f19,  0x1f1a,  0x1f1b,  0x1f1c,  0x1f1d,  0x1f28,  0x1f29,  0x1f2a,  0x1f2b,  0x1f2c,  0x1f2d,  0x1f2e,  0x1f2f,  0x1f38,  0x1f39,  0x1f3a,  0x1f3b,  0x1f3c,  0x1f3d,  0x1f3e,  0x1f3f,  0x1f48,  0x1f49,  0x1f4a,  0x1f4b,  0x1f4c,  0x1f4d,  0x1f59,  0x1f5b,  0x1f5d,  0x1f5f,  0x1f68,  0x1f69,  0x1f6a,  0x1f6b,  0x1f6c,  0x1f6d,  0x1f6e,  0x1f6f,  0x1fba,  0x1fbb,  0x1fc8,  0x1fc9,  0x1fca,  0x1fcb,  0x1fda,  0x1fdb,  0x1ff8,  0x1ff9,  0x1fea,  0x1feb,  0x1ffa,  0x1ffb,  0x1f88,  0x1f89,  0x1f8a,  0x1f8b,  0x1f8c,  0x1f8d,  0x1f8e,  0x1f8f,  0x1f98,  0x1f99,  0x1f9a,  0x1f9b,  0x1f9c,  0x1f9d,  0x1f9e,  0x1f9f,  0x1fa8,  0x1fa9,  0x1faa,  0x1fab,  0x1fac,  0x1fad,  0x1fae,  0x1faf,  0x1fb8,  0x1fb9,  0x1fbc,  0x399,  0x1fcc,  0x1fd8,  0x1fd9,  0x1fe8,  0x1fe9,  0x1fec,  0x1ffc,  0x2132,  0x2160,  0x2161,  0x2162,  0x2163,  0x2164,  0x2165,  0x2166,  0x2167,  0x2168,  0x2169,  0x216a,  0x216b,  0x216c,  0x216d,  0x216e,  0x216f,  0x2183,  0x24b6,  0x24b7,  0x24b8,  0x24b9,  0x24ba,  0x24bb,  0x24bc,  0x24bd,  0x24be,  0x24bf,  0x24c0,  0x24c1,  0x24c2,  0x24c3,  0x24c4,  0x24c5,  0x24c6,  0x24c7,  0x24c8,  0x24c9,  0x24ca,  0x24cb,  0x24cc,  0x24cd,  0x24ce,  0x24cf,  0x2c00,  0x2c01,  0x2c02,  0x2c03,  0x2c04,  0x2c05,  0x2c06,  0x2c07,  0x2c08,  0x2c09,  0x2c0a,  0x2c0b,  0x2c0c,  0x2c0d,  0x2c0e,  0x2c0f,  0x2c10,  0x2c11,  0x2c12,  0x2c13,  0x2c14,  0x2c15,  0x2c16,  0x2c17,  0x2c18,  0x2c19,  0x2c1a,  0x2c1b,  0x2c1c,  0x2c1d,  0x2c1e,  0x2c1f,  0x2c20,  0x2c21,  0x2c22,  0x2c23,  0x2c24,  0x2c25,  0x2c26,  0x2c27,  0x2c28,  0x2c29,  0x2c2a,  0x2c2b,  0x2c2c,  0x2c2d,  0x2c2e,  0x2c60,  0x23a,  0x23e,  0x2c67,  0x2c69,  0x2c6b,  0x2c72,  0x2c75,  0x2c80,  0x2c82,  0x2c84,  0x2c86,  0x2c88,  0x2c8a,  0x2c8c,  0x2c8e,  0x2c90,  0x2c92,  0x2c94,  0x2c96,  0x2c98,  0x2c9a,  0x2c9c,  0x2c9e,  0x2ca0,  0x2ca2,  0x2ca4,  0x2ca6,  0x2ca8,  0x2caa,  0x2cac,  0x2cae,  0x2cb0,  0x2cb2,  0x2cb4,  0x2cb6,  0x2cb8,  0x2cba,  0x2cbc,  0x2cbe,  0x2cc0,  0x2cc2,  0x2cc4,  0x2cc6,  0x2cc8,  0x2cca,  0x2ccc,  0x2cce,  0x2cd0,  0x2cd2,  0x2cd4,  0x2cd6,  0x2cd8,  0x2cda,  0x2cdc,  0x2cde,  0x2ce0,  0x2ce2,  0x2ceb,  0x2ced,  0x2cf2,  0x10a0,  0x10a1,  0x10a2,  0x10a3,  0x10a4,  0x10a5,  0x10a6,  0x10a7,  0x10a8,  0x10a9,  0x10aa,  0x10ab,  0x10ac,  0x10ad,  0x10ae,  0x10af,  0x10b0,  0x10b1,  0x10b2,  0x10b3,  0x10b4,  0x10b5,  0x10b6,  0x10b7,  0x10b8,  0x10b9,  0x10ba,  0x10bb,  0x10bc,  0x10bd,  0x10be,  0x10bf,  0x10c0,  0x10c1,  0x10c2,  0x10c3,  0x10c4,  0x10c5,  0x10c7,  0x10cd,  0xa640,  0xa642,  0xa644,  0xa646,  0xa648,  0xa64a,  0xa64c,  0xa64e,  0xa650,  0xa652,  0xa654,  0xa656,  0xa658,  0xa65a,  0xa65c,  0xa65e,  0xa660,  0xa662,  0xa664,  0xa666,  0xa668,  0xa66a,  0xa66c,  0xa680,  0xa682,  0xa684,  0xa686,  0xa688,  0xa68a,  0xa68c,  0xa68e,  0xa690,  0xa692,  0xa694,  0xa696,  0xa722,  0xa724,  0xa726,  0xa728,  0xa72a,  0xa72c,  0xa72e,  0xa732,  0xa734,  0xa736,  0xa738,  0xa73a,  0xa73c,  0xa73e,  0xa740,  0xa742,  0xa744,  0xa746,  0xa748,  0xa74a,  0xa74c,  0xa74e,  0xa750,  0xa752,  0xa754,  0xa756,  0xa758,  0xa75a,  0xa75c,  0xa75e,  0xa760,  0xa762,  0xa764,  0xa766,  0xa768,  0xa76a,  0xa76c,  0xa76e,  0xa779,  0xa77b,  0xa77e,  0xa780,  0xa782,  0xa784,  0xa786,  0xa78b,  0xa790,  0xa792,  0xa7a0,  0xa7a2,  0xa7a4,  0xa7a6,  0xa7a8,  0xff21,  0xff22,  0xff23,  0xff24,  0xff25,  0xff26,  0xff27,  0xff28,  0xff29,  0xff2a,  0xff2b,  0xff2c,  0xff2d,  0xff2e,  0xff2f,  0xff30,  0xff31,  0xff32,  0xff33,  0xff34,  0xff35,  0xff36,  0xff37,  0xff38,  0xff39,  0xff3a,  0x10400,  0x10401,  0x10402,  0x10403,  0x10404,  0x10405,  0x10406,  0x10407,  0x10408,  0x10409,  0x1040a,  0x1040b,  0x1040c,  0x1040d,  0x1040e,  0x1040f,  0x10410,  0x10411,  0x10412,  0x10413,  0x10414,  0x10415,  0x10416,  0x10417,  0x10418,  0x10419,  0x1041a,  0x1041b,  0x1041c,  0x1041d,  0x1041e,  0x1041f,  0x10420,  0x10421,  0x10422,  0x10423,  0x10424,  0x10425,  0x10426,  0x10427,  0x2000053,  0x53,  0x130,  0x2000046,  0x46,  0x2000046,  0x49,  0x2000046,  0x4c,  0x3000046,  0x46,  0x49,  0x3000046,  0x46,  0x4c,  0x2000053,  0x54,  0x2000053,  0x54,  0x2000535,  0x552,  0x2000544,  0x546,  0x2000544,  0x535,  0x2000544,  0x53b,  0x200054e,  0x546,  0x2000544,  0x53d,  0x20002bc,  0x4e,  0x3000399,  0x308,  0x301,  0x30003a5,  0x308,  0x301,  0x200004a,  0x30c,  0x2000048,  0x331,  0x2000054,  0x308,  0x2000057,  0x30a,  0x2000059,  0x30a,  0x2000041,  0x2be,  0x20003a5,  0x313,  0x30003a5,  0x313,  0x300,  0x30003a5,  0x313,  0x301,  0x30003a5,  0x313,  0x342,  0x2000391,  0x342,  0x2000397,  0x342,  0x3000399,  0x308,  0x300,  0x3000399,  0x308,  0x301,  0x2000399,  0x342,  0x3000399,  0x308,  0x342,  0x30003a5,  0x308,  0x300,  0x30003a5,  0x308,  0x301,  0x20003a1,  0x313,  0x20003a5,  0x342,  0x30003a5,  0x308,  0x342,  0x20003a9,  0x342,  0x2001f08,  0x399,  0x2001f09,  0x399,  0x2001f0a,  0x399,  0x2001f0b,  0x399,  0x2001f0c,  0x399,  0x2001f0d,  0x399,  0x2001f0e,  0x399,  0x2001f0f,  0x399,  0x2001f08,  0x399,  0x2001f09,  0x399,  0x2001f0a,  0x399,  0x2001f0b,  0x399,  0x2001f0c,  0x399,  0x2001f0d,  0x399,  0x2001f0e,  0x399,  0x2001f0f,  0x399,  0x2001f28,  0x399,  0x2001f29,  0x399,  0x2001f2a,  0x399,  0x2001f2b,  0x399,  0x2001f2c,  0x399,  0x2001f2d,  0x399,  0x2001f2e,  0x399,  0x2001f2f,  0x399,  0x2001f28,  0x399,  0x2001f29,  0x399,  0x2001f2a,  0x399,  0x2001f2b,  0x399,  0x2001f2c,  0x399,  0x2001f2d,  0x399,  0x2001f2e,  0x399,  0x2001f2f,  0x399,  0x2001f68,  0x399,  0x2001f69,  0x399,  0x2001f6a,  0x399,  0x2001f6b,  0x399,  0x2001f6c,  0x399,  0x2001f6d,  0x399,  0x2001f6e,  0x399,  0x2001f6f,  0x399,  0x2001f68,  0x399,  0x2001f69,  0x399,  0x2001f6a,  0x399,  0x2001f6b,  0x399,  0x2001f6c,  0x399,  0x2001f6d,  0x399,  0x2001f6e,  0x399,  0x2001f6f,  0x399,  0x2000391,  0x399,  0x2000391,  0x399,  0x2000397,  0x399,  0x2000397,  0x399,  0x20003a9,  0x399,  0x20003a9,  0x399,  0x2001fba,  0x399,  0x2000386,  0x399,  0x2001fca,  0x399,  0x2000389,  0x399,  0x2001ffa,  0x399,  0x200038f,  0x399,  0x3000391,  0x342,  0x399,  0x3000397,  0x342,  0x399,  0x30003a9,  0x342,  0x399]; return t; }
+_IUA toLowerTable() { static _IUA t = [ 0x61,  0x62,  0x63,  0x64,  0x65,  0x66,  0x67,  0x68,  0x69,  0x6a,  0x6b,  0x6c,  0x6d,  0x6e,  0x6f,  0x70,  0x71,  0x72,  0x73,  0x74,  0x75,  0x76,  0x77,  0x78,  0x79,  0x7a,  0xe0,  0xe1,  0xe2,  0xe3,  0xe4,  0xe5,  0xe6,  0xe7,  0xe8,  0xe9,  0xea,  0xeb,  0xec,  0xed,  0xee,  0xef,  0xf0,  0xf1,  0xf2,  0xf3,  0xf4,  0xf5,  0xf6,  0xf8,  0xf9,  0xfa,  0xfb,  0xfc,  0xfd,  0xfe,  0x101,  0x103,  0x105,  0x107,  0x109,  0x10b,  0x10d,  0x10f,  0x111,  0x113,  0x115,  0x117,  0x119,  0x11b,  0x11d,  0x11f,  0x121,  0x123,  0x125,  0x127,  0x129,  0x12b,  0x12d,  0x12f,  0x69,  0x133,  0x135,  0x137,  0x13a,  0x13c,  0x13e,  0x140,  0x142,  0x144,  0x146,  0x148,  0x14b,  0x14d,  0x14f,  0x151,  0x153,  0x155,  0x157,  0x159,  0x15b,  0x15d,  0x15f,  0x161,  0x163,  0x165,  0x167,  0x169,  0x16b,  0x16d,  0x16f,  0x171,  0x173,  0x175,  0x177,  0xff,  0x17a,  0x17c,  0x17e,  0x253,  0x183,  0x185,  0x254,  0x188,  0x256,  0x257,  0x18c,  0x1dd,  0x259,  0x25b,  0x192,  0x260,  0x263,  0x269,  0x268,  0x199,  0x26f,  0x272,  0x275,  0x1a1,  0x1a3,  0x1a5,  0x280,  0x1a8,  0x283,  0x1ad,  0x288,  0x1b0,  0x28a,  0x28b,  0x1b4,  0x1b6,  0x292,  0x1b9,  0x1bd,  0x1c6,  0x1c6,  0x1c9,  0x1c9,  0x1cc,  0x1cc,  0x1ce,  0x1d0,  0x1d2,  0x1d4,  0x1d6,  0x1d8,  0x1da,  0x1dc,  0x1df,  0x1e1,  0x1e3,  0x1e5,  0x1e7,  0x1e9,  0x1eb,  0x1ed,  0x1ef,  0x1f3,  0x1f3,  0x1f5,  0x195,  0x1bf,  0x1f9,  0x1fb,  0x1fd,  0x1ff,  0x201,  0x203,  0x205,  0x207,  0x209,  0x20b,  0x20d,  0x20f,  0x211,  0x213,  0x215,  0x217,  0x219,  0x21b,  0x21d,  0x21f,  0x19e,  0x223,  0x225,  0x227,  0x229,  0x22b,  0x22d,  0x22f,  0x231,  0x233,  0x2c65,  0x23c,  0x19a,  0x2c66,  0x242,  0x180,  0x289,  0x28c,  0x247,  0x249,  0x24b,  0x24d,  0x24f,  0x371,  0x373,  0x377,  0x3ac,  0x3ad,  0x3ae,  0x3af,  0x3cc,  0x3cd,  0x3ce,  0x3b1,  0x3b2,  0x3b3,  0x3b4,  0x3b5,  0x3b6,  0x3b7,  0x3b8,  0x3b9,  0x3ba,  0x3bb,  0x3bc,  0x3bd,  0x3be,  0x3bf,  0x3c0,  0x3c1,  0x3c3,  0x3c4,  0x3c5,  0x3c6,  0x3c7,  0x3c8,  0x3c9,  0x3ca,  0x3cb,  0x3d7,  0x3d9,  0x3db,  0x3dd,  0x3df,  0x3e1,  0x3e3,  0x3e5,  0x3e7,  0x3e9,  0x3eb,  0x3ed,  0x3ef,  0x3b8,  0x3f8,  0x3f2,  0x3fb,  0x37b,  0x37c,  0x37d,  0x450,  0x451,  0x452,  0x453,  0x454,  0x455,  0x456,  0x457,  0x458,  0x459,  0x45a,  0x45b,  0x45c,  0x45d,  0x45e,  0x45f,  0x430,  0x431,  0x432,  0x433,  0x434,  0x435,  0x436,  0x437,  0x438,  0x439,  0x43a,  0x43b,  0x43c,  0x43d,  0x43e,  0x43f,  0x440,  0x441,  0x442,  0x443,  0x444,  0x445,  0x446,  0x447,  0x448,  0x449,  0x44a,  0x44b,  0x44c,  0x44d,  0x44e,  0x44f,  0x461,  0x463,  0x465,  0x467,  0x469,  0x46b,  0x46d,  0x46f,  0x471,  0x473,  0x475,  0x477,  0x479,  0x47b,  0x47d,  0x47f,  0x481,  0x48b,  0x48d,  0x48f,  0x491,  0x493,  0x495,  0x497,  0x499,  0x49b,  0x49d,  0x49f,  0x4a1,  0x4a3,  0x4a5,  0x4a7,  0x4a9,  0x4ab,  0x4ad,  0x4af,  0x4b1,  0x4b3,  0x4b5,  0x4b7,  0x4b9,  0x4bb,  0x4bd,  0x4bf,  0x4cf,  0x4c2,  0x4c4,  0x4c6,  0x4c8,  0x4ca,  0x4cc,  0x4ce,  0x4d1,  0x4d3,  0x4d5,  0x4d7,  0x4d9,  0x4db,  0x4dd,  0x4df,  0x4e1,  0x4e3,  0x4e5,  0x4e7,  0x4e9,  0x4eb,  0x4ed,  0x4ef,  0x4f1,  0x4f3,  0x4f5,  0x4f7,  0x4f9,  0x4fb,  0x4fd,  0x4ff,  0x501,  0x503,  0x505,  0x507,  0x509,  0x50b,  0x50d,  0x50f,  0x511,  0x513,  0x515,  0x517,  0x519,  0x51b,  0x51d,  0x51f,  0x521,  0x523,  0x525,  0x527,  0x561,  0x562,  0x563,  0x564,  0x565,  0x566,  0x567,  0x568,  0x569,  0x56a,  0x56b,  0x56c,  0x56d,  0x56e,  0x56f,  0x570,  0x571,  0x572,  0x573,  0x574,  0x575,  0x576,  0x577,  0x578,  0x579,  0x57a,  0x57b,  0x57c,  0x57d,  0x57e,  0x57f,  0x580,  0x581,  0x582,  0x583,  0x584,  0x585,  0x586,  0x2d00,  0x2d01,  0x2d02,  0x2d03,  0x2d04,  0x2d05,  0x2d06,  0x2d07,  0x2d08,  0x2d09,  0x2d0a,  0x2d0b,  0x2d0c,  0x2d0d,  0x2d0e,  0x2d0f,  0x2d10,  0x2d11,  0x2d12,  0x2d13,  0x2d14,  0x2d15,  0x2d16,  0x2d17,  0x2d18,  0x2d19,  0x2d1a,  0x2d1b,  0x2d1c,  0x2d1d,  0x2d1e,  0x2d1f,  0x2d20,  0x2d21,  0x2d22,  0x2d23,  0x2d24,  0x2d25,  0x2d27,  0x2d2d,  0x1e01,  0x1e03,  0x1e05,  0x1e07,  0x1e09,  0x1e0b,  0x1e0d,  0x1e0f,  0x1e11,  0x1e13,  0x1e15,  0x1e17,  0x1e19,  0x1e1b,  0x1e1d,  0x1e1f,  0x1e21,  0x1e23,  0x1e25,  0x1e27,  0x1e29,  0x1e2b,  0x1e2d,  0x1e2f,  0x1e31,  0x1e33,  0x1e35,  0x1e37,  0x1e39,  0x1e3b,  0x1e3d,  0x1e3f,  0x1e41,  0x1e43,  0x1e45,  0x1e47,  0x1e49,  0x1e4b,  0x1e4d,  0x1e4f,  0x1e51,  0x1e53,  0x1e55,  0x1e57,  0x1e59,  0x1e5b,  0x1e5d,  0x1e5f,  0x1e61,  0x1e63,  0x1e65,  0x1e67,  0x1e69,  0x1e6b,  0x1e6d,  0x1e6f,  0x1e71,  0x1e73,  0x1e75,  0x1e77,  0x1e79,  0x1e7b,  0x1e7d,  0x1e7f,  0x1e81,  0x1e83,  0x1e85,  0x1e87,  0x1e89,  0x1e8b,  0x1e8d,  0x1e8f,  0x1e91,  0x1e93,  0x1e95,  0xdf,  0x1ea1,  0x1ea3,  0x1ea5,  0x1ea7,  0x1ea9,  0x1eab,  0x1ead,  0x1eaf,  0x1eb1,  0x1eb3,  0x1eb5,  0x1eb7,  0x1eb9,  0x1ebb,  0x1ebd,  0x1ebf,  0x1ec1,  0x1ec3,  0x1ec5,  0x1ec7,  0x1ec9,  0x1ecb,  0x1ecd,  0x1ecf,  0x1ed1,  0x1ed3,  0x1ed5,  0x1ed7,  0x1ed9,  0x1edb,  0x1edd,  0x1edf,  0x1ee1,  0x1ee3,  0x1ee5,  0x1ee7,  0x1ee9,  0x1eeb,  0x1eed,  0x1eef,  0x1ef1,  0x1ef3,  0x1ef5,  0x1ef7,  0x1ef9,  0x1efb,  0x1efd,  0x1eff,  0x1f00,  0x1f01,  0x1f02,  0x1f03,  0x1f04,  0x1f05,  0x1f06,  0x1f07,  0x1f10,  0x1f11,  0x1f12,  0x1f13,  0x1f14,  0x1f15,  0x1f20,  0x1f21,  0x1f22,  0x1f23,  0x1f24,  0x1f25,  0x1f26,  0x1f27,  0x1f30,  0x1f31,  0x1f32,  0x1f33,  0x1f34,  0x1f35,  0x1f36,  0x1f37,  0x1f40,  0x1f41,  0x1f42,  0x1f43,  0x1f44,  0x1f45,  0x1f51,  0x1f53,  0x1f55,  0x1f57,  0x1f60,  0x1f61,  0x1f62,  0x1f63,  0x1f64,  0x1f65,  0x1f66,  0x1f67,  0x1f80,  0x1f81,  0x1f82,  0x1f83,  0x1f84,  0x1f85,  0x1f86,  0x1f87,  0x1f90,  0x1f91,  0x1f92,  0x1f93,  0x1f94,  0x1f95,  0x1f96,  0x1f97,  0x1fa0,  0x1fa1,  0x1fa2,  0x1fa3,  0x1fa4,  0x1fa5,  0x1fa6,  0x1fa7,  0x1fb0,  0x1fb1,  0x1f70,  0x1f71,  0x1fb3,  0x1f72,  0x1f73,  0x1f74,  0x1f75,  0x1fc3,  0x1fd0,  0x1fd1,  0x1f76,  0x1f77,  0x1fe0,  0x1fe1,  0x1f7a,  0x1f7b,  0x1fe5,  0x1f78,  0x1f79,  0x1f7c,  0x1f7d,  0x1ff3,  0x3c9,  0x6b,  0xe5,  0x214e,  0x2170,  0x2171,  0x2172,  0x2173,  0x2174,  0x2175,  0x2176,  0x2177,  0x2178,  0x2179,  0x217a,  0x217b,  0x217c,  0x217d,  0x217e,  0x217f,  0x2184,  0x24d0,  0x24d1,  0x24d2,  0x24d3,  0x24d4,  0x24d5,  0x24d6,  0x24d7,  0x24d8,  0x24d9,  0x24da,  0x24db,  0x24dc,  0x24dd,  0x24de,  0x24df,  0x24e0,  0x24e1,  0x24e2,  0x24e3,  0x24e4,  0x24e5,  0x24e6,  0x24e7,  0x24e8,  0x24e9,  0x2c30,  0x2c31,  0x2c32,  0x2c33,  0x2c34,  0x2c35,  0x2c36,  0x2c37,  0x2c38,  0x2c39,  0x2c3a,  0x2c3b,  0x2c3c,  0x2c3d,  0x2c3e,  0x2c3f,  0x2c40,  0x2c41,  0x2c42,  0x2c43,  0x2c44,  0x2c45,  0x2c46,  0x2c47,  0x2c48,  0x2c49,  0x2c4a,  0x2c4b,  0x2c4c,  0x2c4d,  0x2c4e,  0x2c4f,  0x2c50,  0x2c51,  0x2c52,  0x2c53,  0x2c54,  0x2c55,  0x2c56,  0x2c57,  0x2c58,  0x2c59,  0x2c5a,  0x2c5b,  0x2c5c,  0x2c5d,  0x2c5e,  0x2c61,  0x26b,  0x1d7d,  0x27d,  0x2c68,  0x2c6a,  0x2c6c,  0x251,  0x271,  0x250,  0x252,  0x2c73,  0x2c76,  0x23f,  0x240,  0x2c81,  0x2c83,  0x2c85,  0x2c87,  0x2c89,  0x2c8b,  0x2c8d,  0x2c8f,  0x2c91,  0x2c93,  0x2c95,  0x2c97,  0x2c99,  0x2c9b,  0x2c9d,  0x2c9f,  0x2ca1,  0x2ca3,  0x2ca5,  0x2ca7,  0x2ca9,  0x2cab,  0x2cad,  0x2caf,  0x2cb1,  0x2cb3,  0x2cb5,  0x2cb7,  0x2cb9,  0x2cbb,  0x2cbd,  0x2cbf,  0x2cc1,  0x2cc3,  0x2cc5,  0x2cc7,  0x2cc9,  0x2ccb,  0x2ccd,  0x2ccf,  0x2cd1,  0x2cd3,  0x2cd5,  0x2cd7,  0x2cd9,  0x2cdb,  0x2cdd,  0x2cdf,  0x2ce1,  0x2ce3,  0x2cec,  0x2cee,  0x2cf3,  0xa641,  0xa643,  0xa645,  0xa647,  0xa649,  0xa64b,  0xa64d,  0xa64f,  0xa651,  0xa653,  0xa655,  0xa657,  0xa659,  0xa65b,  0xa65d,  0xa65f,  0xa661,  0xa663,  0xa665,  0xa667,  0xa669,  0xa66b,  0xa66d,  0xa681,  0xa683,  0xa685,  0xa687,  0xa689,  0xa68b,  0xa68d,  0xa68f,  0xa691,  0xa693,  0xa695,  0xa697,  0xa723,  0xa725,  0xa727,  0xa729,  0xa72b,  0xa72d,  0xa72f,  0xa733,  0xa735,  0xa737,  0xa739,  0xa73b,  0xa73d,  0xa73f,  0xa741,  0xa743,  0xa745,  0xa747,  0xa749,  0xa74b,  0xa74d,  0xa74f,  0xa751,  0xa753,  0xa755,  0xa757,  0xa759,  0xa75b,  0xa75d,  0xa75f,  0xa761,  0xa763,  0xa765,  0xa767,  0xa769,  0xa76b,  0xa76d,  0xa76f,  0xa77a,  0xa77c,  0x1d79,  0xa77f,  0xa781,  0xa783,  0xa785,  0xa787,  0xa78c,  0x265,  0xa791,  0xa793,  0xa7a1,  0xa7a3,  0xa7a5,  0xa7a7,  0xa7a9,  0x266,  0xff41,  0xff42,  0xff43,  0xff44,  0xff45,  0xff46,  0xff47,  0xff48,  0xff49,  0xff4a,  0xff4b,  0xff4c,  0xff4d,  0xff4e,  0xff4f,  0xff50,  0xff51,  0xff52,  0xff53,  0xff54,  0xff55,  0xff56,  0xff57,  0xff58,  0xff59,  0xff5a,  0x10428,  0x10429,  0x1042a,  0x1042b,  0x1042c,  0x1042d,  0x1042e,  0x1042f,  0x10430,  0x10431,  0x10432,  0x10433,  0x10434,  0x10435,  0x10436,  0x10437,  0x10438,  0x10439,  0x1043a,  0x1043b,  0x1043c,  0x1043d,  0x1043e,  0x1043f,  0x10440,  0x10441,  0x10442,  0x10443,  0x10444,  0x10445,  0x10446,  0x10447,  0x10448,  0x10449,  0x1044a,  0x1044b,  0x1044c,  0x1044d,  0x1044e,  0x1044f,  0xdf,  0x2000069,  0x307,  0xfb00,  0xfb01,  0xfb02,  0xfb03,  0xfb04,  0xfb05,  0xfb06,  0x587,  0xfb13,  0xfb14,  0xfb15,  0xfb16,  0xfb17,  0x149,  0x390,  0x3b0,  0x1f0,  0x1e96,  0x1e97,  0x1e98,  0x1e99,  0x1e9a,  0x1f50,  0x1f52,  0x1f54,  0x1f56,  0x1fb6,  0x1fc6,  0x1fd2,  0x1fd3,  0x1fd6,  0x1fd7,  0x1fe2,  0x1fe3,  0x1fe4,  0x1fe6,  0x1fe7,  0x1ff6,  0x1f80,  0x1f81,  0x1f82,  0x1f83,  0x1f84,  0x1f85,  0x1f86,  0x1f87,  0x1f80,  0x1f81,  0x1f82,  0x1f83,  0x1f84,  0x1f85,  0x1f86,  0x1f87,  0x1f90,  0x1f91,  0x1f92,  0x1f93,  0x1f94,  0x1f95,  0x1f96,  0x1f97,  0x1f90,  0x1f91,  0x1f92,  0x1f93,  0x1f94,  0x1f95,  0x1f96,  0x1f97,  0x1fa0,  0x1fa1,  0x1fa2,  0x1fa3,  0x1fa4,  0x1fa5,  0x1fa6,  0x1fa7,  0x1fa0,  0x1fa1,  0x1fa2,  0x1fa3,  0x1fa4,  0x1fa5,  0x1fa6,  0x1fa7,  0x1fb3,  0x1fb3,  0x1fc3,  0x1fc3,  0x1ff3,  0x1ff3,  0x1fb2,  0x1fb4,  0x1fc2,  0x1fc4,  0x1ff2,  0x1ff4,  0x1fb7,  0x1fc7,  0x1ff7]; return t; }
+_IUA toTitleTable() { static _IUA t = [ 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,  0x39c,  0xc0,  0xc1,  0xc2,  0xc3,  0xc4,  0xc5,  0xc6,  0xc7,  0xc8,  0xc9,  0xca,  0xcb,  0xcc,  0xcd,  0xce,  0xcf,  0xd0,  0xd1,  0xd2,  0xd3,  0xd4,  0xd5,  0xd6,  0xd8,  0xd9,  0xda,  0xdb,  0xdc,  0xdd,  0xde,  0x178,  0x100,  0x102,  0x104,  0x106,  0x108,  0x10a,  0x10c,  0x10e,  0x110,  0x112,  0x114,  0x116,  0x118,  0x11a,  0x11c,  0x11e,  0x120,  0x122,  0x124,  0x126,  0x128,  0x12a,  0x12c,  0x12e,  0x49,  0x132,  0x134,  0x136,  0x139,  0x13b,  0x13d,  0x13f,  0x141,  0x143,  0x145,  0x147,  0x14a,  0x14c,  0x14e,  0x150,  0x152,  0x154,  0x156,  0x158,  0x15a,  0x15c,  0x15e,  0x160,  0x162,  0x164,  0x166,  0x168,  0x16a,  0x16c,  0x16e,  0x170,  0x172,  0x174,  0x176,  0x179,  0x17b,  0x17d,  0x53,  0x243,  0x182,  0x184,  0x187,  0x18b,  0x191,  0x1f6,  0x198,  0x23d,  0x220,  0x1a0,  0x1a2,  0x1a4,  0x1a7,  0x1ac,  0x1af,  0x1b3,  0x1b5,  0x1b8,  0x1bc,  0x1f7,  0x1c5,  0x1c5,  0x1c5,  0x1c8,  0x1c8,  0x1c8,  0x1cb,  0x1cb,  0x1cb,  0x1cd,  0x1cf,  0x1d1,  0x1d3,  0x1d5,  0x1d7,  0x1d9,  0x1db,  0x18e,  0x1de,  0x1e0,  0x1e2,  0x1e4,  0x1e6,  0x1e8,  0x1ea,  0x1ec,  0x1ee,  0x1f2,  0x1f2,  0x1f2,  0x1f4,  0x1f8,  0x1fa,  0x1fc,  0x1fe,  0x200,  0x202,  0x204,  0x206,  0x208,  0x20a,  0x20c,  0x20e,  0x210,  0x212,  0x214,  0x216,  0x218,  0x21a,  0x21c,  0x21e,  0x222,  0x224,  0x226,  0x228,  0x22a,  0x22c,  0x22e,  0x230,  0x232,  0x23b,  0x2c7e,  0x2c7f,  0x241,  0x246,  0x248,  0x24a,  0x24c,  0x24e,  0x2c6f,  0x2c6d,  0x2c70,  0x181,  0x186,  0x189,  0x18a,  0x18f,  0x190,  0x193,  0x194,  0xa78d,  0xa7aa,  0x197,  0x196,  0x2c62,  0x19c,  0x2c6e,  0x19d,  0x19f,  0x2c64,  0x1a6,  0x1a9,  0x1ae,  0x244,  0x1b1,  0x1b2,  0x245,  0x1b7,  0x399,  0x370,  0x372,  0x376,  0x3fd,  0x3fe,  0x3ff,  0x386,  0x388,  0x389,  0x38a,  0x391,  0x392,  0x393,  0x394,  0x395,  0x396,  0x397,  0x398,  0x399,  0x39a,  0x39b,  0x39c,  0x39d,  0x39e,  0x39f,  0x3a0,  0x3a1,  0x3a3,  0x3a3,  0x3a4,  0x3a5,  0x3a6,  0x3a7,  0x3a8,  0x3a9,  0x3aa,  0x3ab,  0x38c,  0x38e,  0x38f,  0x392,  0x398,  0x3a6,  0x3a0,  0x3cf,  0x3d8,  0x3da,  0x3dc,  0x3de,  0x3e0,  0x3e2,  0x3e4,  0x3e6,  0x3e8,  0x3ea,  0x3ec,  0x3ee,  0x39a,  0x3a1,  0x3f9,  0x395,  0x3f7,  0x3fa,  0x410,  0x411,  0x412,  0x413,  0x414,  0x415,  0x416,  0x417,  0x418,  0x419,  0x41a,  0x41b,  0x41c,  0x41d,  0x41e,  0x41f,  0x420,  0x421,  0x422,  0x423,  0x424,  0x425,  0x426,  0x427,  0x428,  0x429,  0x42a,  0x42b,  0x42c,  0x42d,  0x42e,  0x42f,  0x400,  0x401,  0x402,  0x403,  0x404,  0x405,  0x406,  0x407,  0x408,  0x409,  0x40a,  0x40b,  0x40c,  0x40d,  0x40e,  0x40f,  0x460,  0x462,  0x464,  0x466,  0x468,  0x46a,  0x46c,  0x46e,  0x470,  0x472,  0x474,  0x476,  0x478,  0x47a,  0x47c,  0x47e,  0x480,  0x48a,  0x48c,  0x48e,  0x490,  0x492,  0x494,  0x496,  0x498,  0x49a,  0x49c,  0x49e,  0x4a0,  0x4a2,  0x4a4,  0x4a6,  0x4a8,  0x4aa,  0x4ac,  0x4ae,  0x4b0,  0x4b2,  0x4b4,  0x4b6,  0x4b8,  0x4ba,  0x4bc,  0x4be,  0x4c1,  0x4c3,  0x4c5,  0x4c7,  0x4c9,  0x4cb,  0x4cd,  0x4c0,  0x4d0,  0x4d2,  0x4d4,  0x4d6,  0x4d8,  0x4da,  0x4dc,  0x4de,  0x4e0,  0x4e2,  0x4e4,  0x4e6,  0x4e8,  0x4ea,  0x4ec,  0x4ee,  0x4f0,  0x4f2,  0x4f4,  0x4f6,  0x4f8,  0x4fa,  0x4fc,  0x4fe,  0x500,  0x502,  0x504,  0x506,  0x508,  0x50a,  0x50c,  0x50e,  0x510,  0x512,  0x514,  0x516,  0x518,  0x51a,  0x51c,  0x51e,  0x520,  0x522,  0x524,  0x526,  0x531,  0x532,  0x533,  0x534,  0x535,  0x536,  0x537,  0x538,  0x539,  0x53a,  0x53b,  0x53c,  0x53d,  0x53e,  0x53f,  0x540,  0x541,  0x542,  0x543,  0x544,  0x545,  0x546,  0x547,  0x548,  0x549,  0x54a,  0x54b,  0x54c,  0x54d,  0x54e,  0x54f,  0x550,  0x551,  0x552,  0x553,  0x554,  0x555,  0x556,  0xa77d,  0x2c63,  0x1e00,  0x1e02,  0x1e04,  0x1e06,  0x1e08,  0x1e0a,  0x1e0c,  0x1e0e,  0x1e10,  0x1e12,  0x1e14,  0x1e16,  0x1e18,  0x1e1a,  0x1e1c,  0x1e1e,  0x1e20,  0x1e22,  0x1e24,  0x1e26,  0x1e28,  0x1e2a,  0x1e2c,  0x1e2e,  0x1e30,  0x1e32,  0x1e34,  0x1e36,  0x1e38,  0x1e3a,  0x1e3c,  0x1e3e,  0x1e40,  0x1e42,  0x1e44,  0x1e46,  0x1e48,  0x1e4a,  0x1e4c,  0x1e4e,  0x1e50,  0x1e52,  0x1e54,  0x1e56,  0x1e58,  0x1e5a,  0x1e5c,  0x1e5e,  0x1e60,  0x1e62,  0x1e64,  0x1e66,  0x1e68,  0x1e6a,  0x1e6c,  0x1e6e,  0x1e70,  0x1e72,  0x1e74,  0x1e76,  0x1e78,  0x1e7a,  0x1e7c,  0x1e7e,  0x1e80,  0x1e82,  0x1e84,  0x1e86,  0x1e88,  0x1e8a,  0x1e8c,  0x1e8e,  0x1e90,  0x1e92,  0x1e94,  0x1e60,  0x1ea0,  0x1ea2,  0x1ea4,  0x1ea6,  0x1ea8,  0x1eaa,  0x1eac,  0x1eae,  0x1eb0,  0x1eb2,  0x1eb4,  0x1eb6,  0x1eb8,  0x1eba,  0x1ebc,  0x1ebe,  0x1ec0,  0x1ec2,  0x1ec4,  0x1ec6,  0x1ec8,  0x1eca,  0x1ecc,  0x1ece,  0x1ed0,  0x1ed2,  0x1ed4,  0x1ed6,  0x1ed8,  0x1eda,  0x1edc,  0x1ede,  0x1ee0,  0x1ee2,  0x1ee4,  0x1ee6,  0x1ee8,  0x1eea,  0x1eec,  0x1eee,  0x1ef0,  0x1ef2,  0x1ef4,  0x1ef6,  0x1ef8,  0x1efa,  0x1efc,  0x1efe,  0x1f08,  0x1f09,  0x1f0a,  0x1f0b,  0x1f0c,  0x1f0d,  0x1f0e,  0x1f0f,  0x1f18,  0x1f19,  0x1f1a,  0x1f1b,  0x1f1c,  0x1f1d,  0x1f28,  0x1f29,  0x1f2a,  0x1f2b,  0x1f2c,  0x1f2d,  0x1f2e,  0x1f2f,  0x1f38,  0x1f39,  0x1f3a,  0x1f3b,  0x1f3c,  0x1f3d,  0x1f3e,  0x1f3f,  0x1f48,  0x1f49,  0x1f4a,  0x1f4b,  0x1f4c,  0x1f4d,  0x1f59,  0x1f5b,  0x1f5d,  0x1f5f,  0x1f68,  0x1f69,  0x1f6a,  0x1f6b,  0x1f6c,  0x1f6d,  0x1f6e,  0x1f6f,  0x1fba,  0x1fbb,  0x1fc8,  0x1fc9,  0x1fca,  0x1fcb,  0x1fda,  0x1fdb,  0x1ff8,  0x1ff9,  0x1fea,  0x1feb,  0x1ffa,  0x1ffb,  0x1f88,  0x1f89,  0x1f8a,  0x1f8b,  0x1f8c,  0x1f8d,  0x1f8e,  0x1f8f,  0x1f98,  0x1f99,  0x1f9a,  0x1f9b,  0x1f9c,  0x1f9d,  0x1f9e,  0x1f9f,  0x1fa8,  0x1fa9,  0x1faa,  0x1fab,  0x1fac,  0x1fad,  0x1fae,  0x1faf,  0x1fb8,  0x1fb9,  0x1fbc,  0x399,  0x1fcc,  0x1fd8,  0x1fd9,  0x1fe8,  0x1fe9,  0x1fec,  0x1ffc,  0x2132,  0x2160,  0x2161,  0x2162,  0x2163,  0x2164,  0x2165,  0x2166,  0x2167,  0x2168,  0x2169,  0x216a,  0x216b,  0x216c,  0x216d,  0x216e,  0x216f,  0x2183,  0x24b6,  0x24b7,  0x24b8,  0x24b9,  0x24ba,  0x24bb,  0x24bc,  0x24bd,  0x24be,  0x24bf,  0x24c0,  0x24c1,  0x24c2,  0x24c3,  0x24c4,  0x24c5,  0x24c6,  0x24c7,  0x24c8,  0x24c9,  0x24ca,  0x24cb,  0x24cc,  0x24cd,  0x24ce,  0x24cf,  0x2c00,  0x2c01,  0x2c02,  0x2c03,  0x2c04,  0x2c05,  0x2c06,  0x2c07,  0x2c08,  0x2c09,  0x2c0a,  0x2c0b,  0x2c0c,  0x2c0d,  0x2c0e,  0x2c0f,  0x2c10,  0x2c11,  0x2c12,  0x2c13,  0x2c14,  0x2c15,  0x2c16,  0x2c17,  0x2c18,  0x2c19,  0x2c1a,  0x2c1b,  0x2c1c,  0x2c1d,  0x2c1e,  0x2c1f,  0x2c20,  0x2c21,  0x2c22,  0x2c23,  0x2c24,  0x2c25,  0x2c26,  0x2c27,  0x2c28,  0x2c29,  0x2c2a,  0x2c2b,  0x2c2c,  0x2c2d,  0x2c2e,  0x2c60,  0x23a,  0x23e,  0x2c67,  0x2c69,  0x2c6b,  0x2c72,  0x2c75,  0x2c80,  0x2c82,  0x2c84,  0x2c86,  0x2c88,  0x2c8a,  0x2c8c,  0x2c8e,  0x2c90,  0x2c92,  0x2c94,  0x2c96,  0x2c98,  0x2c9a,  0x2c9c,  0x2c9e,  0x2ca0,  0x2ca2,  0x2ca4,  0x2ca6,  0x2ca8,  0x2caa,  0x2cac,  0x2cae,  0x2cb0,  0x2cb2,  0x2cb4,  0x2cb6,  0x2cb8,  0x2cba,  0x2cbc,  0x2cbe,  0x2cc0,  0x2cc2,  0x2cc4,  0x2cc6,  0x2cc8,  0x2cca,  0x2ccc,  0x2cce,  0x2cd0,  0x2cd2,  0x2cd4,  0x2cd6,  0x2cd8,  0x2cda,  0x2cdc,  0x2cde,  0x2ce0,  0x2ce2,  0x2ceb,  0x2ced,  0x2cf2,  0x10a0,  0x10a1,  0x10a2,  0x10a3,  0x10a4,  0x10a5,  0x10a6,  0x10a7,  0x10a8,  0x10a9,  0x10aa,  0x10ab,  0x10ac,  0x10ad,  0x10ae,  0x10af,  0x10b0,  0x10b1,  0x10b2,  0x10b3,  0x10b4,  0x10b5,  0x10b6,  0x10b7,  0x10b8,  0x10b9,  0x10ba,  0x10bb,  0x10bc,  0x10bd,  0x10be,  0x10bf,  0x10c0,  0x10c1,  0x10c2,  0x10c3,  0x10c4,  0x10c5,  0x10c7,  0x10cd,  0xa640,  0xa642,  0xa644,  0xa646,  0xa648,  0xa64a,  0xa64c,  0xa64e,  0xa650,  0xa652,  0xa654,  0xa656,  0xa658,  0xa65a,  0xa65c,  0xa65e,  0xa660,  0xa662,  0xa664,  0xa666,  0xa668,  0xa66a,  0xa66c,  0xa680,  0xa682,  0xa684,  0xa686,  0xa688,  0xa68a,  0xa68c,  0xa68e,  0xa690,  0xa692,  0xa694,  0xa696,  0xa722,  0xa724,  0xa726,  0xa728,  0xa72a,  0xa72c,  0xa72e,  0xa732,  0xa734,  0xa736,  0xa738,  0xa73a,  0xa73c,  0xa73e,  0xa740,  0xa742,  0xa744,  0xa746,  0xa748,  0xa74a,  0xa74c,  0xa74e,  0xa750,  0xa752,  0xa754,  0xa756,  0xa758,  0xa75a,  0xa75c,  0xa75e,  0xa760,  0xa762,  0xa764,  0xa766,  0xa768,  0xa76a,  0xa76c,  0xa76e,  0xa779,  0xa77b,  0xa77e,  0xa780,  0xa782,  0xa784,  0xa786,  0xa78b,  0xa790,  0xa792,  0xa7a0,  0xa7a2,  0xa7a4,  0xa7a6,  0xa7a8,  0xff21,  0xff22,  0xff23,  0xff24,  0xff25,  0xff26,  0xff27,  0xff28,  0xff29,  0xff2a,  0xff2b,  0xff2c,  0xff2d,  0xff2e,  0xff2f,  0xff30,  0xff31,  0xff32,  0xff33,  0xff34,  0xff35,  0xff36,  0xff37,  0xff38,  0xff39,  0xff3a,  0x10400,  0x10401,  0x10402,  0x10403,  0x10404,  0x10405,  0x10406,  0x10407,  0x10408,  0x10409,  0x1040a,  0x1040b,  0x1040c,  0x1040d,  0x1040e,  0x1040f,  0x10410,  0x10411,  0x10412,  0x10413,  0x10414,  0x10415,  0x10416,  0x10417,  0x10418,  0x10419,  0x1041a,  0x1041b,  0x1041c,  0x1041d,  0x1041e,  0x1041f,  0x10420,  0x10421,  0x10422,  0x10423,  0x10424,  0x10425,  0x10426,  0x10427,  0x2000053,  0x73,  0x130,  0x2000046,  0x66,  0x2000046,  0x69,  0x2000046,  0x6c,  0x3000046,  0x66,  0x69,  0x3000046,  0x66,  0x6c,  0x2000053,  0x74,  0x2000053,  0x74,  0x2000535,  0x582,  0x2000544,  0x576,  0x2000544,  0x565,  0x2000544,  0x56b,  0x200054e,  0x576,  0x2000544,  0x56d,  0x20002bc,  0x4e,  0x3000399,  0x308,  0x301,  0x30003a5,  0x308,  0x301,  0x200004a,  0x30c,  0x2000048,  0x331,  0x2000054,  0x308,  0x2000057,  0x30a,  0x2000059,  0x30a,  0x2000041,  0x2be,  0x20003a5,  0x313,  0x30003a5,  0x313,  0x300,  0x30003a5,  0x313,  0x301,  0x30003a5,  0x313,  0x342,  0x2000391,  0x342,  0x2000397,  0x342,  0x3000399,  0x308,  0x300,  0x3000399,  0x308,  0x301,  0x2000399,  0x342,  0x3000399,  0x308,  0x342,  0x30003a5,  0x308,  0x300,  0x30003a5,  0x308,  0x301,  0x20003a1,  0x313,  0x20003a5,  0x342,  0x30003a5,  0x308,  0x342,  0x20003a9,  0x342,  0x1f88,  0x1f89,  0x1f8a,  0x1f8b,  0x1f8c,  0x1f8d,  0x1f8e,  0x1f8f,  0x1f88,  0x1f89,  0x1f8a,  0x1f8b,  0x1f8c,  0x1f8d,  0x1f8e,  0x1f8f,  0x1f98,  0x1f99,  0x1f9a,  0x1f9b,  0x1f9c,  0x1f9d,  0x1f9e,  0x1f9f,  0x1f98,  0x1f99,  0x1f9a,  0x1f9b,  0x1f9c,  0x1f9d,  0x1f9e,  0x1f9f,  0x1fa8,  0x1fa9,  0x1faa,  0x1fab,  0x1fac,  0x1fad,  0x1fae,  0x1faf,  0x1fa8,  0x1fa9,  0x1faa,  0x1fab,  0x1fac,  0x1fad,  0x1fae,  0x1faf,  0x1fbc,  0x1fbc,  0x1fcc,  0x1fcc,  0x1ffc,  0x1ffc,  0x2001fba,  0x345,  0x2000386,  0x345,  0x2001fca,  0x345,  0x2000389,  0x345,  0x2001ffa,  0x345,  0x200038f,  0x345,  0x3000391,  0x342,  0x345,  0x3000397,  0x342,  0x345,  0x30003a9,  0x342,  0x345]; return t; }
+}
+
+}
+
+
+static if(size_t.sizeof == 4) {
+//1536 bytes
+enum lowerCaseTrieEntries = TrieEntry!(bool, 8, 4, 9)([ 0x0,  0x40,  0x80], [ 0x100,  0x80,  0x2000], [ 0x2020100,  0x4020302,  0x2020205,  0x2060202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000,  0x30002,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x50004,  0x30006,  0x30007,  0x30003,  0x30008,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x90003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0xa0003,  0xb0003,  0x30003,  0x3000c,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0xe000d,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x0,  0x0,  0x0,  0x7fffffe,  0x0,  0x4200400,  0x80000000,  0xff7fffff,  0xaaaaaaaa,  0x55aaaaaa,  0xaaaaab55,  0xd4aaaaaa,  0x4e243129,  0xe6512d2a,  0xb5555240,  0xaa29aaaa,  0xaaaaaaaa,  0x93faaaaa,  0xffffaa85,  0xffffffff,  0xffefffff,  0x1ffffff,  0x3,  0x1f,  0x0,  0x0,  0x20,  0x3c8a0000,  0x10000,  0xfffff000,  0xaae37fff,  0x192faaaa,  0x0,  0xffff0000,  0xffffffff,  0xaaaaaaaa,  0xaaaaa802,  0xaaaaaaaa,  0xaaaad554,  0xaaaaaaaa,  0xaaaaaaaa,  0xaa,  0x0,  0xfffffffe,  0xff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x0,  0x0,  0xaaaaaaaa,  0xaaaaaaaa,  0xaaaaaaaa,  0xaaaaaaaa,  0xbfeaaaaa,  0xaaaaaaaa,  0xaaaaaaaa,  0xaaaaaaaa,  0x3f00ff,  0xff00ff,  0xff003f,  0x3fff00ff,  0xff00ff,  0x40df00ff,  0xcf00dc,  0xdc00ff,  0x0,  0x0,  0x0,  0x80020000,  0x1fff0000,  0x0,  0x0,  0x0,  0x8c400,  0x32108000,  0x43c0,  0xffff0000,  0x10,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffff0000,  0x3ff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffff0000,  0x7fffffff,  0x3fda1562,  0xaaaaaaaa,  0xaaaaaaaa,  0xaaaaaaaa,  0x8501a,  0xffffffff,  0x20bf,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xaaaaaaaa,  0x2aaa,  0xaaaaaa,  0x0,  0x0,  0x0,  0x0,  0xaaabaaa8,  0xaaaaaaaa,  0x95ffaaaa,  0xa50aa,  0x2aa,  0x0,  0x7000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xf8007f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7fffffe,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffff00,  0xffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xfc000000,  0xfffff,  0xffdfc000,  0xff,  0xffffffc,  0xebc00000,  0xffef,  0xfffffc00,  0xc000000f,  0xffffff,  0xfffc0000,  0xfff,  0xffffffc0,  0xfc000000,  0xfffff,  0xffffc000,  0xff,  0xffffffc,  0xffc00000,  0xffff,  0xfffffc00,  0x3f,  0xf7fffffc,  0xf0000003,  0xfdfffff,  0xffc00000,  0x3f7fff,  0xffff0000,  0xfdff,  0xfffffc00,  0xbf7,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//1472 bytes
+enum upperCaseTrieEntries = TrieEntry!(bool, 8, 4, 9)([ 0x0,  0x40,  0x80], [ 0x100,  0x80,  0x1e00], [ 0x2020100,  0x4020302,  0x2020205,  0x2060202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000,  0x30002,  0x30003,  0x30003,  0x30004,  0x30003,  0x30003,  0x50003,  0x30006,  0x30007,  0x30003,  0x30008,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x90003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0xa0003,  0x30003,  0x3000b,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0xd000c,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x30003,  0x0,  0x0,  0x7fffffe,  0x0,  0x0,  0x0,  0x7f7fffff,  0x0,  0x55555555,  0xaa555555,  0x555554aa,  0x2b555555,  0xb1dbced6,  0x11aed2d5,  0x4aaaa490,  0x55d25555,  0x55555555,  0x6c055555,  0x557a,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x450000,  0xfffed740,  0xffb,  0x551c8000,  0xe6905555,  0xffffffff,  0xffff,  0x0,  0x55555555,  0x55555401,  0x55555555,  0x55552aab,  0x55555555,  0x55555555,  0xfffe0055,  0x7fffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0x20bf,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x55555555,  0x55555555,  0x55555555,  0x55555555,  0x40155555,  0x55555555,  0x55555555,  0x55555555,  0x3f00ff00,  0xff00ff00,  0xaa003f00,  0xff00,  0x0,  0xf000000,  0xf000f00,  0xf001f00,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3e273884,  0xc00f3d50,  0x20,  0xffff,  0x8,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffc00000,  0xffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0x7fff,  0x0,  0xc025ea9d,  0x55555555,  0x55555555,  0x55555555,  0x42805,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x55555555,  0x1555,  0x555555,  0x0,  0x0,  0x0,  0x0,  0x55545554,  0x55555555,  0x6a005555,  0x52855,  0x555,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7fffffe,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3ffffff,  0xfff00000,  0x3fff,  0xffffff00,  0xd0000003,  0x3fde64,  0xffff0000,  0x3ff,  0x1fdfe7b0,  0x7b000000,  0x1fc5f,  0xfffff000,  0x3f,  0x3ffffff,  0xfff00000,  0x3fff,  0xffffff00,  0xf0000003,  0x3fffff,  0xffff0000,  0x3ff,  0xffffff00,  0x1,  0x7fffffc,  0xf0000000,  0x1fffff,  0xffc00000,  0x7fff,  0xffff0000,  0x1ff,  0x400,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//8704 bytes
+enum simpleCaseTrieEntries = TrieEntry!(ushort, 8, 7, 6)([ 0x0,  0x40,  0x200], [ 0x100,  0x380,  0xd00], [ 0x2020100,  0x4020302,  0x2020205,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x10000,  0x30002,  0x50004,  0x70006,  0x90008,  0xa,  0xb0000,  0xd000c,  0xf000e,  0x110010,  0x130012,  0x14,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x160015,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x170000,  0x0,  0x190018,  0x1b001a,  0x1d001c,  0x1f001e,  0x0,  0x0,  0x210020,  0x22,  0x0,  0x0,  0x0,  0x0,  0x0,  0x240023,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x260025,  0x280027,  0x29,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2a0000,  0x2b,  0x2d002c,  0x2e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x30002f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x320031,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x20ffff,  0x240022,  0x280026,  0x2c002a,  0x30002e,  0x72f0032,  0x390037,  0x3d003b,  0x41003f,  0x1b00043,  0x4a0048,  0x4e004c,  0x520050,  0xffff0054,  0xffffffff,  0xffffffff,  0x21ffff,  0x250023,  0x290027,  0x2d002b,  0x31002f,  0x7300033,  0x3a0038,  0x3e003c,  0x420040,  0x1b10044,  0x4b0049,  0x4f004d,  0x530051,  0xffff0055,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x43fffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xc800c6,  0xcc0498,  0x14904aa,  0xd500d3,  0xd900d7,  0xdd00db,  0xe100df,  0xe500e3,  0xe900e7,  0xed00eb,  0xf100ef,  0xffff00f3,  0xf700f5,  0xfb00f9,  0xff00fd,  0x6be0101,  0xc900c7,  0xcd0499,  0x14a04ab,  0xd600d4,  0xda00d8,  0xde00dc,  0xe200e0,  0xe600e4,  0xea00e8,  0xee00ec,  0xf200f0,  0xffff00f4,  0xf800f6,  0xfc00fa,  0x10000fe,  0x1a80102,  0x1160115,  0x1180117,  0x11c011b,  0x11e011d,  0x120011f,  0x1240123,  0x1260125,  0x1280127,  0x12c012b,  0x12e012d,  0x130012f,  0x1340133,  0x1360135,  0x1380137,  0x13a0139,  0x13c013b,  0x13e013d,  0x140013f,  0x1420141,  0x1440143,  0x1460145,  0x1480147,  0x14d014c,  0x14f014e,  0xffffffff,  0x1510150,  0x1530152,  0x1550154,  0x156ffff,  0x1580157,  0x15c0159,  0x15e015d,  0x160015f,  0x1620161,  0x1640163,  0x1660165,  0xffff0167,  0x1690168,  0x16b016a,  0x16d016c,  0x16f016e,  0x1710170,  0x1730172,  0x1750174,  0x1770176,  0x1790178,  0x17b017a,  0x17d017c,  0x17f017e,  0x1830182,  0x1870186,  0x18b018a,  0x18f018e,  0x1930192,  0x1970196,  0x19b019a,  0x19f019e,  0x1a301a2,  0x1a501a4,  0x1a701a6,  0x1aa01a9,  0x1ac01ab,  0x1ae01ad,  0x1b201af,  0x1b3028b,  0x1b601b5,  0x1ba01b9,  0x1bd01bb,  0x1bf01be,  0x1c301c1,  0xffff01c4,  0x1c701c5,  0x1cb01c9,  0x1cd01cc,  0x23b01cf,  0x1d301d1,  0x1d601d5,  0xffff0283,  0x1d901d7,  0x1db0269,  0x1de01dd,  0x1e001df,  0x1e201e1,  0x1e501e3,  0x1e701e6,  0xffffffff,  0x1ea01e9,  0x1ed01eb,  0x1ef01ee,  0x1f301f1,  0x1f501f4,  0x1f701f6,  0x1fa01f9,  0xffffffff,  0x1fc01fb,  0x23dffff,  0xffffffff,  0xffffffff,  0x2010200,  0x2060202,  0x2080207,  0x20d020c,  0x20f020e,  0x2110210,  0x2130212,  0x2150214,  0x2170216,  0x2190218,  0x21b021a,  0x21d021c,  0x1c6021e,  0x220021f,  0x2240223,  0x2260225,  0x2280227,  0x22a0229,  0x22c022b,  0x22e022d,  0x230022f,  0x2320231,  0x236ffff,  0x2380237,  0x23a0239,  0x23e023c,  0x240023f,  0x2440243,  0x2460245,  0x2480247,  0x24a0249,  0x24c024b,  0x24e024d,  0x250024f,  0x2520251,  0x2540253,  0x2560255,  0x2580257,  0x25a0259,  0x25c025b,  0x25e025d,  0x260025f,  0x2620261,  0x2640263,  0x2660265,  0x2680267,  0xffff026a,  0x26c026b,  0x26e026d,  0x270026f,  0x2720271,  0x2740273,  0x2760275,  0x2780277,  0x27a0279,  0x27c027b,  0xffffffff,  0xffffffff,  0xffffffff,  0x281027f,  0x2840282,  0x2d70285,  0x2870482,  0x28c0288,  0x28f028d,  0x2920291,  0x2940293,  0x2960295,  0x2980297,  0x29c029b,  0x466046a,  0x1b402b7,  0xffff01bc,  0x1c201c0,  0x1c8ffff,  0x1caffff,  0xffffffff,  0xffffffff,  0xffff01ce,  0x1d0ffff,  0x748ffff,  0xffff05fa,  0x1d201d4,  0x528ffff,  0xffffffff,  0x1d8ffff,  0x2b3ffff,  0xffff01da,  0x1dcffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2a3ffff,  0xffffffff,  0xffff01e4,  0x1e8ffff,  0xffffffff,  0xffffffff,  0x28e01ec,  0x1f201f0,  0xffff0290,  0xffffffff,  0xffffffff,  0xffff01f8,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x83affff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x31e031d,  0x320031f,  0xffffffff,  0x3240323,  0xffffffff,  0x3d5ffff,  0x3d903d7,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0329,  0x32f032d,  0xffff0331,  0xffff0333,  0x3370335,  0x339ffff,  0x33e0395,  0x3cc0340,  0x3470345,  0x83b03c8,  0x35403c2,  0x3590440,  0x35d035b,  0x3c5039f,  0x388ffff,  0x36a0368,  0x36f039c,  0x7100371,  0x3780376,  0x32e032a,  0x3320330,  0x33affff,  0x33f0396,  0x3cd0341,  0x3480346,  0x83c03c9,  0x35503c3,  0x35a0441,  0x35e035c,  0x3c603a0,  0x38a0389,  0x36b0369,  0x370039d,  0x7110372,  0x3790377,  0x3360334,  0x3930338,  0x3ca0397,  0xffffffff,  0x39effff,  0x39403a1,  0x3a303a2,  0x3a703a6,  0x3a903a8,  0x3ab03aa,  0x3ad03ac,  0x3af03ae,  0x3b103b0,  0x3b503b4,  0x3b903b8,  0x3bd03bc,  0x3bf03be,  0x3c103c0,  0x3c703c4,  0xffff03d1,  0x3ce03cb,  0x3cfffff,  0x3d203d0,  0x3d403d3,  0x3d6ffff,  0x3da03d8,  0x3dd03db,  0x3e103df,  0x3e503e3,  0x3e903e7,  0x3ed03eb,  0x3f103ef,  0x3f503f3,  0x3f903f7,  0x3fd03fb,  0x40103ff,  0x4050403,  0x4090407,  0x40d040b,  0x411040f,  0x4150413,  0x4190417,  0x41d041b,  0x421041f,  0x4250423,  0x4290427,  0x42d042b,  0x431042f,  0x4350433,  0x4390437,  0x3fe03fc,  0x4020400,  0x4060404,  0x40a0408,  0x40e040c,  0x4120410,  0x4160414,  0x41a0418,  0x41e041c,  0x4220420,  0x4260424,  0x42a0428,  0x42e042c,  0x4320430,  0x4360434,  0x43a0438,  0x3de03dc,  0x3e203e0,  0x3e603e4,  0x3ea03e8,  0x3ee03ec,  0x3f203f0,  0x3f603f4,  0x3fa03f8,  0x4510450,  0x4530452,  0x4570456,  0x4590458,  0x45d045c,  0x4610460,  0x4650464,  0x4690468,  0x46d046c,  0x4710470,  0x4730472,  0x4770476,  0x4790478,  0x47b047a,  0x47d047c,  0x4810480,  0x4850484,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x4950494,  0x4970496,  0x49b049a,  0x49d049c,  0x49f049e,  0x4a304a2,  0x4a704a6,  0x4a904a8,  0x4ad04ac,  0x4b104b0,  0x4b304b2,  0x4b704b6,  0x4b904b8,  0x4bb04ba,  0x4bf04be,  0x4c104c0,  0x4c504c4,  0x4c904c8,  0x4cd04cc,  0x4cf04ce,  0x4d304d2,  0x4d504d4,  0x4d704d6,  0x4db04da,  0x4df04de,  0x4e304e2,  0x4e704e6,  0x4ec04ea,  0x4f004ed,  0x4f404f1,  0x4f804f5,  0x4fc04f9,  0x50004fd,  0x5040501,  0x4eb0505,  0x50b050a,  0x50d050c,  0x50f050e,  0x5130512,  0x5170516,  0x5190518,  0x51d051c,  0x51f051e,  0x5210520,  0x5250524,  0x5270526,  0x52b052a,  0x52d052c,  0x52f052e,  0x5330532,  0x5370536,  0x5390538,  0x53d053c,  0x53f053e,  0x5410540,  0x5430542,  0x5470546,  0x5490548,  0x54b054a,  0x54d054c,  0x54f054e,  0x5510550,  0x5550554,  0x5570556,  0x5590558,  0x55b055a,  0x55d055c,  0x55f055e,  0x5630562,  0x5650564,  0x5670566,  0x5690568,  0x56b056a,  0x56f056e,  0x5730572,  0x5750574,  0x5770576,  0x5790578,  0x57b057a,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x580ffff,  0x5840582,  0x5880586,  0x58c058a,  0x590058e,  0x5940592,  0x5980596,  0x59c059a,  0x5a0059e,  0x5a405a2,  0x5a805a6,  0x5ac05aa,  0x5b005ae,  0x5b405b2,  0x5b805b6,  0x5bc05ba,  0x5c005be,  0x5c405c2,  0x5c805c6,  0xffff05ca,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x581ffff,  0x5850583,  0x5890587,  0x58d058b,  0x591058f,  0x5950593,  0x5990597,  0x59d059b,  0x5a1059f,  0x5a505a3,  0x5a905a7,  0x5ad05ab,  0x5b105af,  0x5b505b3,  0x5b905b7,  0x5bd05bb,  0x5c105bf,  0x5c505c3,  0x5c905c7,  0xffff05cb,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x880086,  0x8c008a,  0x90008e,  0x940092,  0x980096,  0x9c009a,  0xa0009e,  0xa400a2,  0xa800a6,  0xac00aa,  0xb000ae,  0xb400b2,  0xb800b6,  0xbc00ba,  0xc000be,  0xc400c2,  0x48e0486,  0x4a000ca,  0x4b400ce,  0x4c6ffff,  0xffffffff,  0xffffffff,  0x508ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x7e8ffff,  0xffffffff,  0x454ffff,  0xffffffff,  0x5fd05fc,  0x5ff05fe,  0x6010600,  0x6050604,  0x6090608,  0x60b060a,  0x60f060e,  0x6110610,  0x6130612,  0x6170616,  0x6190618,  0x61d061c,  0x61f061e,  0x6210620,  0x6230622,  0x6270626,  0x6290628,  0x62b062a,  0x62d062c,  0x62f062e,  0x6310630,  0x6350634,  0x6370636,  0x6390638,  0x63b063a,  0x63d063c,  0x63f063e,  0x6430642,  0x6450644,  0x6470646,  0x6490648,  0x64b064a,  0x64d064c,  0x6510650,  0x6530652,  0x6550654,  0x6590658,  0x65d065c,  0x65f065e,  0x6630662,  0x6650664,  0x6670666,  0x6690668,  0x66b066a,  0x66d066c,  0x6710670,  0x6730672,  0x6750674,  0x6bc06bb,  0x67a0679,  0x67c067b,  0x680067f,  0x6820681,  0x6840683,  0x6860685,  0x6880687,  0x68a0689,  0x68e068d,  0x690068f,  0x6920691,  0x6960695,  0x6980697,  0x69a0699,  0x69e069d,  0x6a0069f,  0x6a206a1,  0x6a406a3,  0x6a606a5,  0x6a806a7,  0x6ac06ab,  0x6ae06ad,  0x6b006af,  0x6b206b1,  0x6b406b3,  0x6b606b5,  0xffffffff,  0xffffffff,  0x6bdffff,  0xffffffff,  0xffff06bf,  0x6c106c0,  0x6c306c2,  0x6c506c4,  0x6c906c8,  0x6cb06ca,  0x6cd06cc,  0x6cf06ce,  0x6d106d0,  0x6d506d4,  0x6d706d6,  0x6db06da,  0x6dd06dc,  0x6df06de,  0x6e106e0,  0x6e306e2,  0x6e506e4,  0x6e906e8,  0x6eb06ea,  0x6ef06ee,  0x6f106f0,  0x6f306f2,  0x6f506f4,  0x6f706f6,  0x6f906f8,  0x6fb06fa,  0x6fd06fc,  0x6ff06fe,  0x7010700,  0x7030702,  0x7050704,  0x7070706,  0x7090708,  0x70b070a,  0x70d070c,  0x70f070e,  0x7140713,  0x7160715,  0x7180717,  0x71c071b,  0x71e071d,  0x720071f,  0x7220721,  0x7240723,  0x7260725,  0x7280727,  0x72a0729,  0x72e072d,  0x7330732,  0x7380736,  0x73c073a,  0x740073e,  0x7440742,  0x7390737,  0x73d073b,  0x741073f,  0x7450743,  0x74c074a,  0x750074e,  0x7540752,  0xffffffff,  0x74d074b,  0x751074f,  0x7550753,  0xffffffff,  0x7660764,  0x76a0768,  0x76e076c,  0x7720770,  0x7670765,  0x76b0769,  0x76f076d,  0x7730771,  0x7860784,  0x78a0788,  0x78e078c,  0x7920790,  0x7870785,  0x78b0789,  0x78f078d,  0x7930791,  0x79e079c,  0x7a207a0,  0x7a607a4,  0xffffffff,  0x79f079d,  0x7a307a1,  0x7a707a5,  0xffffffff,  0x7b6ffff,  0x7baffff,  0x7beffff,  0x7c2ffff,  0x7b7ffff,  0x7bbffff,  0x7bfffff,  0x7c3ffff,  0x7d207d0,  0x7d607d4,  0x7da07d8,  0x7de07dc,  0x7d307d1,  0x7d707d5,  0x7db07d9,  0x7df07dd,  0x8360834,  0x840083e,  0x8440842,  0x84e084c,  0x8620860,  0x8580856,  0x8660864,  0xffffffff,  0x7f607f4,  0x7fa07f8,  0x7fe07fc,  0x8020800,  0x7f707f5,  0x7fb07f9,  0x7ff07fd,  0x8030801,  0x80a0808,  0x80e080c,  0x8120810,  0x8160814,  0x80b0809,  0x80f080d,  0x8130811,  0x8170815,  0x8220820,  0x8260824,  0x82a0828,  0x82e082c,  0x8230821,  0x8270825,  0x82b0829,  0x82f082d,  0x8320830,  0x838ffff,  0xffffffff,  0xffffffff,  0x8330831,  0x8370835,  0xffff0839,  0xffff083d,  0xffffffff,  0x846ffff,  0xffffffff,  0xffffffff,  0x841083f,  0x8450843,  0xffff0847,  0xffffffff,  0x84a0848,  0xffffffff,  0xffffffff,  0xffffffff,  0x84b0849,  0x84f084d,  0xffffffff,  0xffffffff,  0x8540852,  0xffffffff,  0x85affff,  0xffffffff,  0x8550853,  0x8590857,  0xffff085b,  0xffffffff,  0xffffffff,  0x868ffff,  0xffffffff,  0xffffffff,  0x8630861,  0x8670865,  0xffff0869,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0712,  0xffffffff,  0x14b0731,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0530,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0531,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x180029f,  0x18402af,  0x18802c1,  0x18c005e,  0x1900064,  0x194006c,  0x1980076,  0x19c007e,  0x18102a0,  0x18502b0,  0x18902c2,  0x18d005f,  0x1910065,  0x195006d,  0x1990077,  0x19d007f,  0xffffffff,  0x1b7ffff,  0xffff01b8,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x4d80444,  0x4dc0446,  0x4e0044c,  0x4e4045e,  0x4e80474,  0x2d3086a,  0x204ee,  0x6c604f2,  0x6e04f6,  0x37a04fa,  0x10d04fe,  0x61a0502,  0x51a0506,  0x4d90445,  0x4dd0447,  0x4e1044d,  0x4e5045f,  0x4e90475,  0x2d4086b,  0x304ef,  0x6c704f3,  0x6f04f7,  0x37b04fb,  0x10e04ff,  0x61b0503,  0x51b0507,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x40000,  0xa0008,  0xe000c,  0x160010,  0x1a0018,  0x2bb001c,  0x2d102c7,  0x5602e7,  0x600058,  0x660062,  0x70006a,  0x780074,  0x80007c,  0x2990082,  0x607e0,  0x6020084,  0x2a7057c,  0x5d005ce,  0x10305de,  0x1070105,  0x10f0109,  0x1190113,  0x1290121,  0xffff0131,  0x50001,  0xb0009,  0xf000d,  0x170011,  0x1b0019,  0x2bc001d,  0x2d202c8,  0x5702e8,  0x610059,  0x670063,  0x71006b,  0x790075,  0x81007d,  0x29a0083,  0x707e1,  0x6030085,  0x2a8057d,  0x5d105cf,  0x10405df,  0x1080106,  0x110010a,  0x11a0114,  0x12a0122,  0xffff0132,  0x4c304c2,  0x4550529,  0x28002a4,  0x45a0286,  0x2a9045b,  0x46202aa,  0x4670463,  0x46b02b4,  0xffff02b8,  0x2ba02b9,  0x2bfffff,  0xffff02c0,  0xffffffff,  0xffffffff,  0xffffffff,  0x48302d8,  0x2e202e1,  0x4890488,  0x48b048a,  0x48d048c,  0x4910490,  0x2fe02fd,  0x3040303,  0x30e030d,  0x3160315,  0x31a0319,  0x3260325,  0x3280327,  0x2fc02fb,  0x6ed06ec,  0x3810380,  0x3830382,  0x3870386,  0x3920391,  0x3a503a4,  0x3b303b2,  0x56d056c,  0x5cd05cc,  0x5db05da,  0x5ed05ec,  0x60d060c,  0x6570656,  0x43e043d,  0x6e706e6,  0x72c072b,  0x7830782,  0x7e307e2,  0x6940693,  0x65b065a,  0x150014,  0x5d005c,  0x4bd04bc,  0x4d104d0,  0x5d505d4,  0x1a101a0,  0x5110510,  0x5230522,  0x5350534,  0x5450544,  0x5530552,  0x5610560,  0x5710570,  0x57f057e,  0x15b015a,  0x37d037c,  0x3bb03ba,  0xffffffff,  0xffffffff,  0xffffffff,  0x5d2ffff,  0x5d805d3,  0xffff05d9,  0xffffffff,  0x5e305e2,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x890087,  0x8d008b,  0x91008f,  0x950093,  0x990097,  0x9d009b,  0xa1009f,  0xa500a3,  0xa900a7,  0xad00ab,  0xb100af,  0xb500b3,  0xb900b7,  0xbd00bb,  0xc100bf,  0xc500c3,  0x48f0487,  0x4a100cb,  0x4b500cf,  0x4c7ffff,  0xffffffff,  0xffffffff,  0x509ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2c402c3,  0x5d705d6,  0x5dd05dc,  0x5e105e0,  0x5e705e6,  0x5e905e8,  0x5eb05ea,  0x5ef05ee,  0x5f105f0,  0x5f505f4,  0x5f905f8,  0x3080307,  0x6150614,  0x6250624,  0x6330632,  0x6410640,  0x64f064e,  0x6610660,  0x66f066e,  0x67e067d,  0x68c068b,  0x69c069b,  0x6aa06a9,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x7350734,  0x690068,  0x27e027d,  0x75f075e,  0x7770776,  0x390038f,  0x1f001e,  0x7b107b0,  0x7c707c6,  0x2a202a1,  0x7e507e4,  0x6b806b7,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x7590758,  0x75d075c,  0x7610760,  0x2d602d5,  0x2e002df,  0x2e602e5,  0x2ee02ed,  0xffffffff,  0x7790778,  0x77d077c,  0x7810780,  0x30c030b,  0x3140313,  0x3180317,  0x3220321,  0x7950794,  0x7970796,  0x7990798,  0x79b079a,  0x37f037e,  0x3850384,  0x38e038d,  0x7a907a8,  0x7ab07aa,  0x7ad07ac,  0x7af07ae,  0x7b307b2,  0x7b507b4,  0x7b907b8,  0x7bd07bc,  0x7c107c0,  0x7c507c4,  0x7c907c8,  0x7cd07cc,  0x7cf07ce,  0x46f046e,  0x47f047e,  0x4930492,  0x4a504a4,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x514ffff,  0x7e60515,  0x7e907e7,  0x7eb07ea,  0x7ed07ec,  0x7ef07ee,  0x7f107f0,  0x7f307f2,  0xffffffff,  0x5f2ffff,  0x74905f3,  0xffffffff,  0x8050804,  0x8070806,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x8190818,  0x81b081a,  0x81d081c,  0x81f081e,  0x5f705f6,  0xffff05fb,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x756ffff,  0x75a02c5,  0x2cd02cb,  0x76202cf,  0x2db06d2,  0x2e30719,  0x2e90448,  0x2f107ca,  0x2f30774,  0x77a02f5,  0x77e02f9,  0x3050221,  0x30f007a,  0xffff043b,  0xffffffff,  0xffffffff,  0x757ffff,  0x75b02c6,  0x2ce02cc,  0x76302d0,  0x2dc06d3,  0x2e4071a,  0x2ea0449,  0x2f207cb,  0x2f40775,  0x77b02f6,  0x77f02fa,  0x3060222,  0x310007b,  0xffff043c,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x85c0012,  0x72005a,  0x32b0311,  0x11106b9,  0x2ab05e4,  0x2dd029d,  0x2ef085e,  0x10b0606,  0x2d902a5,  0x4ca0289,  0x2b502ad,  0x2c902bd,  0x2eb0746,  0x30902f7,  0x241031b,  0x38b02b1,  0x44a03b6,  0x442053a,  0x6d8044e,  0x85004ae,  0x85d0013,  0x73005b,  0x32c0312,  0x11206ba,  0x2ac05e5,  0x2de029e,  0x2f0085f,  0x10c0607,  0x2da02a6,  0x4cb028a,  0x2b602ae,  0x2ca02be,  0x2ec0747,  0x30a02f8,  0x242031c,  0x38c02b2,  0x44b03b7,  0x443053b,  0x6d9044f,  0x85104af,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff]);
+//8832 bytes
+enum fullCaseTrieEntries = TrieEntry!(ushort, 8, 7, 6)([ 0x0,  0x40,  0x200], [ 0x100,  0x380,  0xd40], [ 0x2020100,  0x4020302,  0x2020205,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x10000,  0x30002,  0x50004,  0x70006,  0x90008,  0xa,  0xb0000,  0xd000c,  0xf000e,  0x110010,  0x130012,  0x14,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x160015,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x170000,  0x0,  0x190018,  0x1b001a,  0x1d001c,  0x1f001e,  0x0,  0x0,  0x210020,  0x22,  0x0,  0x0,  0x0,  0x0,  0x0,  0x240023,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x260025,  0x280027,  0x29,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2a0000,  0x2b,  0x2d002c,  0x2e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x310030,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x330032,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x20ffff,  0x240022,  0x280026,  0x2c002a,  0x30002e,  0x7810032,  0x390037,  0x3d003b,  0x41003f,  0x1b90043,  0x4a0048,  0x4e004c,  0x520050,  0xffff0054,  0xffffffff,  0xffffffff,  0x21ffff,  0x250023,  0x290027,  0x2d002b,  0x31002f,  0x7820033,  0x3a0038,  0x3e003c,  0x420040,  0x1ba0044,  0x4b0049,  0x4f004d,  0x530051,  0xffff0055,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x470ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xc800c6,  0xcc04c9,  0x14e04db,  0xd500d3,  0xd900d7,  0xdd00db,  0xe100df,  0xe500e3,  0xe900e7,  0xed00eb,  0xf100ef,  0xffff00f3,  0xf700f5,  0xfb00f9,  0xff00fd,  0x70f0101,  0xc900c7,  0xcd04ca,  0x14f04dc,  0xd600d4,  0xda00d8,  0xde00dc,  0xe200e0,  0xe600e4,  0xea00e8,  0xee00ec,  0xf200f0,  0xffff00f4,  0xf800f6,  0xfc00fa,  0x10000fe,  0x1b10102,  0x1190118,  0x11b011a,  0x11f011e,  0x1210120,  0x1230122,  0x1270126,  0x1290128,  0x12b012a,  0x12f012e,  0x1310130,  0x1330132,  0x1370136,  0x1390138,  0x13b013a,  0x13d013c,  0x13f013e,  0x1410140,  0x1430142,  0x1470146,  0x1490148,  0x14b014a,  0x14d014c,  0x1520151,  0x1540153,  0xffff0155,  0x1580157,  0x15a0159,  0x15c015b,  0x15dffff,  0x15f015e,  0x1630160,  0x1650164,  0x1670166,  0x1690168,  0x16b016a,  0x16d016c,  0x16f016e,  0x1720171,  0x1740173,  0x1760175,  0x1780177,  0x17a0179,  0x17c017b,  0x17e017d,  0x180017f,  0x1820181,  0x1840183,  0x1860185,  0x1880187,  0x18c018b,  0x190018f,  0x1940193,  0x1980197,  0x19c019b,  0x1a0019f,  0x1a401a3,  0x1a801a7,  0x1ac01ab,  0x1ae01ad,  0x1b001af,  0x1b301b2,  0x1b501b4,  0x1b701b6,  0x1bb01b8,  0x1bc029c,  0x1bf01be,  0x1c301c2,  0x1c601c4,  0x1c801c7,  0x1cc01ca,  0xffff01cd,  0x1d001ce,  0x1d401d2,  0x1d601d5,  0x24801d8,  0x1dc01da,  0x1df01de,  0xffff0294,  0x1e201e0,  0x1e60278,  0x1e901e8,  0x1eb01ea,  0x1ed01ec,  0x1f001ee,  0x1f201f1,  0xffffffff,  0x1f501f4,  0x1f801f6,  0x1fa01f9,  0x1fe01fc,  0x20001ff,  0x2020201,  0x2050204,  0xffffffff,  0x2070206,  0x24affff,  0xffffffff,  0xffffffff,  0x20c020b,  0x211020d,  0x2130212,  0x2180217,  0x21a0219,  0x21c021b,  0x21e021d,  0x220021f,  0x2220221,  0x2240223,  0x2260225,  0x2280227,  0x1cf0229,  0x22b022a,  0x22f022e,  0x2310230,  0x2330232,  0x2350234,  0x2370236,  0x2390238,  0x23b023a,  0x23d023c,  0x243023e,  0x2450244,  0x2470246,  0x24b0249,  0x24d024c,  0x2510250,  0x2530252,  0x2550254,  0x2570256,  0x2590258,  0x25b025a,  0x25d025c,  0x2610260,  0x2630262,  0x2650264,  0x2670266,  0x2690268,  0x26b026a,  0x26d026c,  0x26f026e,  0x2710270,  0x2730272,  0x2750274,  0x2770276,  0xffff0279,  0x27b027a,  0x27d027c,  0x27f027e,  0x2810280,  0x2850284,  0x2870286,  0x2890288,  0x28b028a,  0x28d028c,  0xffffffff,  0xffffffff,  0xffffffff,  0x2920290,  0x2950293,  0x2ec0296,  0x29804b3,  0x29d0299,  0x2a0029e,  0x2a302a2,  0x2a502a4,  0x2a702a6,  0x2a902a8,  0x2ad02ac,  0x497049b,  0x1bd02ca,  0xffff01c5,  0x1cb01c9,  0x1d1ffff,  0x1d3ffff,  0xffffffff,  0xffffffff,  0xffff01d7,  0x1d9ffff,  0x79affff,  0xffff0643,  0x1db01dd,  0x559ffff,  0xffffffff,  0x1e1ffff,  0x2c6ffff,  0xffff01e3,  0x1e7ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2b4ffff,  0xffffffff,  0xffff01ef,  0x1f3ffff,  0xffffffff,  0xffffffff,  0x29f01f7,  0x1fd01fb,  0xffff02a1,  0xffffffff,  0xffffffff,  0xffff0203,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x8e4ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3450344,  0x3470346,  0xffffffff,  0x34b034a,  0xffffffff,  0x406ffff,  0x40a0408,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0350,  0x3560354,  0xffff0358,  0xffff035a,  0x35e035c,  0x3630902,  0x36803c2,  0x3fd036a,  0x371036f,  0x8e503f9,  0x37e03f3,  0x3830471,  0x3870385,  0x3f603cc,  0x3b5ffff,  0x3940392,  0x39903c9,  0x762039b,  0x3a203a0,  0x3550351,  0x3590357,  0x3640915,  0x36903c3,  0x3fe036b,  0x3720370,  0x8e603fa,  0x37f03f4,  0x3840472,  0x3880386,  0x3f703cd,  0x3b703b6,  0x3950393,  0x39a03ca,  0x763039c,  0x3a303a1,  0x35d035b,  0x3c0035f,  0x3fb03c4,  0xffffffff,  0x3cbffff,  0x3c103ce,  0x3d003cf,  0x3d403d3,  0x3d603d5,  0x3d803d7,  0x3da03d9,  0x3de03dd,  0x3e003df,  0x3e403e3,  0x3e803e7,  0x3ec03eb,  0x3ee03ed,  0x3f203f1,  0x3f803f5,  0xffff0402,  0x3ff03fc,  0x400ffff,  0x4030401,  0x4050404,  0x407ffff,  0x40b0409,  0x40e040c,  0x4120410,  0x4160414,  0x41a0418,  0x41e041c,  0x4220420,  0x4260424,  0x42a0428,  0x42e042c,  0x4320430,  0x4360434,  0x43a0438,  0x43e043c,  0x4420440,  0x4460444,  0x44a0448,  0x44e044c,  0x4520450,  0x4560454,  0x45a0458,  0x45e045c,  0x4620460,  0x4660464,  0x46a0468,  0x42f042d,  0x4330431,  0x4370435,  0x43b0439,  0x43f043d,  0x4430441,  0x4470445,  0x44b0449,  0x44f044d,  0x4530451,  0x4570455,  0x45b0459,  0x45f045d,  0x4630461,  0x4670465,  0x46b0469,  0x40f040d,  0x4130411,  0x4170415,  0x41b0419,  0x41f041d,  0x4230421,  0x4270425,  0x42b0429,  0x4820481,  0x4840483,  0x4880487,  0x48a0489,  0x48e048d,  0x4920491,  0x4960495,  0x49a0499,  0x49e049d,  0x4a204a1,  0x4a404a3,  0x4a804a7,  0x4aa04a9,  0x4ac04ab,  0x4ae04ad,  0x4b204b1,  0x4b604b5,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x4c604c5,  0x4c804c7,  0x4cc04cb,  0x4ce04cd,  0x4d004cf,  0x4d404d3,  0x4d804d7,  0x4da04d9,  0x4de04dd,  0x4e204e1,  0x4e404e3,  0x4e804e7,  0x4ea04e9,  0x4ec04eb,  0x4f004ef,  0x4f204f1,  0x4f604f5,  0x4fa04f9,  0x4fe04fd,  0x50004ff,  0x5040503,  0x5060505,  0x5080507,  0x50c050b,  0x510050f,  0x5140513,  0x5180517,  0x51d051b,  0x521051e,  0x5250522,  0x5290526,  0x52d052a,  0x531052e,  0x5350532,  0x51c0536,  0x53c053b,  0x53e053d,  0x540053f,  0x5440543,  0x5480547,  0x54a0549,  0x54e054d,  0x550054f,  0x5520551,  0x5560555,  0x5580557,  0x55c055b,  0x55e055d,  0x560055f,  0x5640563,  0x5680567,  0x56a0569,  0x56e056d,  0x570056f,  0x5720571,  0x5740573,  0x5780577,  0x57a0579,  0x57c057b,  0x57e057d,  0x5820581,  0x5840583,  0x5880587,  0x58a0589,  0x58c058b,  0x58e058d,  0x5920591,  0x5940593,  0x5980597,  0x59a0599,  0x59c059b,  0x59e059d,  0x5a205a1,  0x5a605a5,  0x5aa05a9,  0x5ac05ab,  0x5ae05ad,  0x5b005af,  0x5b405b3,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x5b9ffff,  0x5bd05bb,  0x5c105bf,  0x5c505c3,  0x5c905c7,  0x5cd05cb,  0x5d105cf,  0x5d505d3,  0x5d905d7,  0x5dd05db,  0x5e105df,  0x5e505e3,  0x5e905e7,  0x5ed05eb,  0x5f105ef,  0x5f505f3,  0x5f905f7,  0x5fd05fb,  0x60105ff,  0xffff0603,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x5baffff,  0x5be05bc,  0x5c205c0,  0x5c605c4,  0x5ca05c8,  0x5ce05cc,  0x5d205d0,  0x5d605d4,  0x5da05d8,  0x5de05dc,  0x5e205e0,  0x5e605e4,  0x5ea05e8,  0x5ee05ec,  0x5f205f0,  0x5f605f4,  0x5fa05f8,  0x5fe05fc,  0x6020600,  0x6130604,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x880086,  0x8c008a,  0x90008e,  0x940092,  0x980096,  0x9c009a,  0xa0009e,  0xa400a2,  0xa800a6,  0xac00aa,  0xb000ae,  0xb400b2,  0xb800b6,  0xbc00ba,  0xc000be,  0xc400c2,  0x4bf04b7,  0x4d100ca,  0x4e500ce,  0x4f7ffff,  0xffffffff,  0xffffffff,  0x539ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x83affff,  0xffffffff,  0x485ffff,  0xffffffff,  0x6460645,  0x6480647,  0x64a0649,  0x64e064d,  0x6520651,  0x6540653,  0x6580657,  0x65a0659,  0x65c065b,  0x660065f,  0x6620661,  0x6660665,  0x6680667,  0x66a0669,  0x66c066b,  0x670066f,  0x6720671,  0x6740673,  0x6760675,  0x6780677,  0x67a0679,  0x67e067d,  0x680067f,  0x6820681,  0x6840683,  0x6860685,  0x6880687,  0x68c068b,  0x68e068d,  0x690068f,  0x6920691,  0x6940693,  0x6960695,  0x69a0699,  0x69c069b,  0x69e069d,  0x6a206a1,  0x6a606a5,  0x6a806a7,  0x6ac06ab,  0x6ae06ad,  0x6b006af,  0x6b206b1,  0x6b406b3,  0x6b606b5,  0x6ba06b9,  0x6bc06bb,  0x6be06bd,  0x70d070c,  0x6c306c2,  0x6c706c6,  0x6cb06ca,  0x6cd06cc,  0x6cf06ce,  0x6d106d0,  0x6d306d2,  0x6d506d4,  0x6d906d8,  0x6db06da,  0x6dd06dc,  0x6e106e0,  0x6e306e2,  0x6e506e4,  0x6e906e8,  0x6eb06ea,  0x6ed06ec,  0x6ef06ee,  0x6f106f0,  0x6f306f2,  0x6f706f6,  0x6f906f8,  0x6fb06fa,  0x6fd06fc,  0x6ff06fe,  0x7010700,  0x7040702,  0x7080706,  0x70e070a,  0xffffffff,  0xffff0710,  0x7130712,  0x7150714,  0x7170716,  0x71b071a,  0x71d071c,  0x71f071e,  0x7210720,  0x7230722,  0x7270726,  0x7290728,  0x72d072c,  0x72f072e,  0x7310730,  0x7330732,  0x7350734,  0x7370736,  0x73b073a,  0x73d073c,  0x7410740,  0x7430742,  0x7450744,  0x7470746,  0x7490748,  0x74b074a,  0x74d074c,  0x74f074e,  0x7510750,  0x7530752,  0x7550754,  0x7570756,  0x7590758,  0x75b075a,  0x75d075c,  0x75f075e,  0x7610760,  0x7660765,  0x7680767,  0x76a0769,  0x76e076d,  0x770076f,  0x7720771,  0x7740773,  0x7760775,  0x7780777,  0x77a0779,  0x77c077b,  0x780077f,  0x7850784,  0x78a0788,  0x78e078c,  0x7920790,  0x7960794,  0x78b0789,  0x78f078d,  0x7930791,  0x7970795,  0x79e079c,  0x7a207a0,  0x7a607a4,  0xffffffff,  0x79f079d,  0x7a307a1,  0x7a707a5,  0xffffffff,  0x7b807b6,  0x7bc07ba,  0x7c007be,  0x7c407c2,  0x7b907b7,  0x7bd07bb,  0x7c107bf,  0x7c507c3,  0x7d807d6,  0x7dc07da,  0x7e007de,  0x7e407e2,  0x7d907d7,  0x7dd07db,  0x7e107df,  0x7e507e3,  0x7f007ee,  0x7f407f2,  0x7f807f6,  0xffffffff,  0x7f107ef,  0x7f507f3,  0x7f907f7,  0xffffffff,  0x80807fc,  0x80c07fe,  0x8100800,  0x8140804,  0x809ffff,  0x80dffff,  0x811ffff,  0x815ffff,  0x8240822,  0x8280826,  0x82c082a,  0x830082e,  0x8250823,  0x8290827,  0x82d082b,  0x831082f,  0x8df08dd,  0x8f708f5,  0x8fb08f9,  0x90f090d,  0x9370935,  0x9240922,  0x93b0939,  0xffffffff,  0x8590856,  0x85f085c,  0x8650862,  0x86b0868,  0x85a0857,  0x860085d,  0x8660863,  0x86c0869,  0x8890886,  0x88f088c,  0x8950892,  0x89b0898,  0x88a0887,  0x890088d,  0x8960893,  0x89c0899,  0x8b908b6,  0x8bf08bc,  0x8c508c2,  0x8cb08c8,  0x8ba08b7,  0x8c008bd,  0x8c608c3,  0x8cc08c9,  0x8db08d9,  0x8e108ce,  0xffff08d3,  0x8d708d5,  0x8dc08da,  0x8e008de,  0xffff08e2,  0xffff08e7,  0xffffffff,  0x8fd08e8,  0xffff08ed,  0x8f308f1,  0x8f808f6,  0x8fc08fa,  0xffff08fe,  0xffffffff,  0x90b0909,  0x9030900,  0xffffffff,  0x9070905,  0x90c090a,  0x910090e,  0xffffffff,  0xffffffff,  0x920091e,  0x9160913,  0x9260918,  0x91c091a,  0x921091f,  0x9250923,  0xffff0927,  0xffffffff,  0xffffffff,  0x93d092a,  0xffff092f,  0x9330931,  0x9380936,  0x93c093a,  0xffff093e,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0764,  0xffffffff,  0x1500783,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0561,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0562,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x18902b0,  0x18d02c2,  0x19102d6,  0x195005e,  0x1990064,  0x19d006c,  0x1a10076,  0x1a5007e,  0x18a02b1,  0x18e02c3,  0x19202d7,  0x196005f,  0x19a0065,  0x19e006d,  0x1a20077,  0x1a6007f,  0xffffffff,  0x1c0ffff,  0xffff01c1,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x5090475,  0x50d0477,  0x511047d,  0x515048f,  0x51904a5,  0x2e80940,  0x2051f,  0x7180523,  0x6e0527,  0x3a4052b,  0x110052f,  0x6630533,  0x54b0537,  0x50a0476,  0x50e0478,  0x512047e,  0x5160490,  0x51a04a6,  0x2e90941,  0x30520,  0x7190524,  0x6f0528,  0x3a5052c,  0x1110530,  0x6640534,  0x54c0538,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x40000,  0xa0008,  0xe000c,  0x160010,  0x1a0018,  0x2ce001c,  0x2e602dc,  0x560308,  0x600058,  0x660062,  0x70006a,  0x780074,  0x80007c,  0x2aa0082,  0x60832,  0x64b0084,  0x2b805b5,  0x60d0609,  0x629061d,  0x1080106,  0x112010a,  0x11c0116,  0x12c0124,  0xffff0134,  0x50001,  0xb0009,  0xf000d,  0x170011,  0x1b0019,  0x2cf001d,  0x2e702dd,  0x570309,  0x610059,  0x670063,  0x71006b,  0x790075,  0x81007d,  0x2ab0083,  0x70833,  0x64c0085,  0x2b905b6,  0x60e060a,  0x62a061e,  0x1090107,  0x113010b,  0x11d0117,  0x12d0125,  0xffff0135,  0x4f404f3,  0x486055a,  0x29102b5,  0x48b0297,  0x2ba048c,  0x49302bb,  0x4980494,  0x49c02c7,  0xffff02cb,  0x2cd02cc,  0x2d4ffff,  0xffff02d5,  0xffffffff,  0xffffffff,  0xffffffff,  0x4b402ed,  0x2f902f8,  0x4ba04b9,  0x4bc04bb,  0x4be04bd,  0x4c204c1,  0x3250324,  0x32b032a,  0x3350334,  0x33d033c,  0x3410340,  0x34d034c,  0x34f034e,  0x3230322,  0x73f073e,  0x3ae03ad,  0x3b003af,  0x3b403b3,  0x3bf03be,  0x3d203d1,  0x3e203e1,  0x5a405a3,  0x6060605,  0x61a0619,  0x6320631,  0x6560655,  0x6a0069f,  0x46f046e,  0x7390738,  0x77e077d,  0x7d507d4,  0x8350834,  0x6df06de,  0x6a406a3,  0x150014,  0x5d005c,  0x4ee04ed,  0x5020501,  0x6120611,  0x1aa01a9,  0x5420541,  0x5540553,  0x5660565,  0x5760575,  0x5860585,  0x5960595,  0x5a805a7,  0x5b805b7,  0x1620161,  0x3a703a6,  0x3ea03e9,  0xffffffff,  0xffffffff,  0xffffffff,  0x60fffff,  0x6170610,  0xffff0618,  0xffffffff,  0x6240623,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x890087,  0x8d008b,  0x91008f,  0x950093,  0x990097,  0x9d009b,  0xa1009f,  0xa500a3,  0xa900a7,  0xad00ab,  0xb100af,  0xb500b3,  0xb900b7,  0xbd00bb,  0xc100bf,  0xc500c3,  0x4c004b8,  0x4d200cb,  0x4e600cf,  0x4f8ffff,  0xffffffff,  0xffffffff,  0x53affff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2d902d8,  0x6160615,  0x61c061b,  0x6220621,  0x6280627,  0x1e501e4,  0x62e062d,  0x6340633,  0x6380637,  0x63e063d,  0x6420641,  0x32f032e,  0x65e065d,  0x66e066d,  0x67c067b,  0x68a0689,  0x6980697,  0x6aa06a9,  0x6b806b7,  0x6c906c8,  0x6d706d6,  0x6e706e6,  0x6f506f4,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x7870786,  0x690068,  0x28f028e,  0x7b107b0,  0x7c907c8,  0x3bd03bc,  0x1f001e,  0x8030802,  0x8190818,  0x2b302b2,  0x8370836,  0x2d302d2,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x7ab07aa,  0x7af07ae,  0x7b307b2,  0x2eb02ea,  0x2f502f4,  0x3070306,  0x3110310,  0xffffffff,  0x7cb07ca,  0x7cf07ce,  0x7d307d2,  0x3330332,  0x33b033a,  0x33f033e,  0x3490348,  0x7e707e6,  0x7e907e8,  0x7eb07ea,  0x7ed07ec,  0x3ac03ab,  0x3b203b1,  0x3bb03ba,  0x7fb07fa,  0x3dc03db,  0x3f003ef,  0x620061f,  0x2830282,  0x8070806,  0x80b080a,  0x80f080e,  0x8130812,  0x8170816,  0x81b081a,  0x81f081e,  0x8210820,  0x4a0049f,  0x4b004af,  0x4c404c3,  0x4d604d5,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x545ffff,  0x8380546,  0x83b0839,  0x83d083c,  0x580057f,  0x590058f,  0x5a0059f,  0x5b205b1,  0xffffffff,  0x63bffff,  0x79b063c,  0xffffffff,  0x6080607,  0x60c060b,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x62c062b,  0x630062f,  0x6360635,  0x63a0639,  0x640063f,  0xffff0644,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x25e02f6,  0x2fc02fa,  0x30302fe,  0xffff0304,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x30cffff,  0x2c0030e,  0x3140312,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x7a8ffff,  0x7ac02da,  0x2e202e0,  0x7b402e4,  0x2f00724,  0x144076b,  0x30a0479,  0x318081c,  0x31a07c6,  0x7cc031c,  0x7d00320,  0x32c022c,  0x336007a,  0xffff046c,  0xffffffff,  0xffffffff,  0x7a9ffff,  0x7ad02db,  0x2e302e1,  0x7b502e5,  0x2f10725,  0x145076c,  0x30b047a,  0x319081d,  0x31b07c7,  0x7cd031d,  0x7d10321,  0x32d022d,  0x337007b,  0xffff046d,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x9280012,  0x72005a,  0x3520338,  0x114010c,  0x2bc0625,  0x2f202ae,  0x31608ef,  0x10e064f,  0x2ee02b6,  0x4fb029a,  0x2c802be,  0x2de02d0,  0x47f0798,  0x330031e,  0x24e0342,  0x3b802c4,  0x47b03e5,  0x473056b,  0x72a06c4,  0x91104df,  0x9290013,  0x73005b,  0x3530339,  0x115010d,  0x2bd0626,  0x2f302af,  0x31708f0,  0x10f0650,  0x2ef02b7,  0x4fc029b,  0x2c902bf,  0x2df02d1,  0x4800799,  0x331031f,  0x24f0343,  0x3b902c5,  0x47c03e6,  0x474056c,  0x72b06c5,  0x91204e0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff]);
+//4000 bytes
+enum alphaTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x40,  0x160], [ 0x100,  0x240,  0x5100], [ 0x3020100,  0x7060504,  0xb0a0908,  0xe0d0c0a,  0x3030303,  0x100a0f03,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000,  0x30002,  0x50004,  0x70006,  0x90008,  0xb000a,  0xd000c,  0xf000e,  0x10010,  0x120011,  0x10013,  0x150014,  0x170016,  0x190018,  0x1b001a,  0x1c0001,  0x1e001d,  0x1f001f,  0x1f0020,  0x1f001f,  0x1f001f,  0x1f001f,  0x220021,  0x1f0023,  0x250024,  0x1f001f,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x260001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x270001,  0x10001,  0x10001,  0x10028,  0x2a0029,  0x2c002b,  0x2e002d,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x2f0001,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1001f,  0x310030,  0x320001,  0x340033,  0x360035,  0x380037,  0x1f0039,  0x1f001f,  0x3b003a,  0x3d003c,  0x1f003e,  0x1f001f,  0x40003f,  0x1f001f,  0x1f001f,  0x1f0041,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x10001,  0x420001,  0x1f0043,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x10001,  0x10001,  0x1f0044,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x10001,  0x1f0045,  0x1f001f,  0x46001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f0047,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x490048,  0x4b004a,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f004c,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x10001,  0x10001,  0x10001,  0x1004d,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x4e0001,  0x1f004f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x10001,  0x1f004f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x1f001f,  0x0,  0x0,  0x7fffffe,  0x7fffffe,  0x0,  0x4200400,  0xff7fffff,  0xff7fffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3ffc3,  0x501f,  0x0,  0x0,  0x20,  0x3cdf0000,  0xffffd740,  0xfffffffb,  0xffffffff,  0xffbfffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xfffffc03,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xfffe00ff,  0x27fffff,  0xfffffffe,  0xff,  0xbfff0000,  0xffff00b6,  0x707ff,  0x7ff0000,  0xffffffff,  0xfeffffff,  0xffffc000,  0xffffffff,  0xffffffff,  0x1fefffff,  0x9c00e1fe,  0xffff0000,  0xffffffff,  0xffffe000,  0xffffffff,  0xffffffff,  0x3ffff,  0xfffffc00,  0x43007ff,  0xfcffffff,  0x1fff,  0x1ffffff,  0x0,  0x0,  0x1ffd,  0x0,  0x7fff03f0,  0xffffffff,  0xefffffff,  0xffe1dfff,  0xfefe000f,  0xfff99fee,  0xe3c5fdff,  0xb080599f,  0x3000f,  0xfff987ee,  0xc36dfdff,  0x5e021987,  0x3f0000,  0xfffbbfee,  0xe3edfdff,  0x11bbf,  0xf,  0xfff99fee,  0xe3edfdff,  0xb0c0199f,  0x2000f,  0xd63dc7ec,  0xc3ffc718,  0x811dc7,  0x0,  0xfffddfee,  0xe3effdff,  0x3601ddf,  0xf,  0xfffddfec,  0xe3effdff,  0x40601ddf,  0x6000f,  0xfffddfec,  0xe7ffffff,  0x805ddf,  0xfc00000f,  0xfc7fffec,  0x2ffbffff,  0xff5f807f,  0xc0000,  0xfffffffe,  0x7ffffff,  0x207f,  0x0,  0xfef02596,  0x3bffecae,  0xf000205f,  0x0,  0x1,  0x0,  0xfffffeff,  0xfffe1fff,  0xfeffff03,  0x1fffffff,  0x0,  0x0,  0xffffffff,  0xf97fffff,  0xffff0000,  0xffffc1e7,  0x3000407f,  0xffffffff,  0xffff20bf,  0xf7ffffff,  0xffffffff,  0xffffffff,  0x3d7f3dff,  0xffffffff,  0xffff3dff,  0x7f3dffff,  0xff7fff3d,  0xffffffff,  0xff3dffff,  0xffffffff,  0x87ffffff,  0x0,  0xffff,  0xffffffff,  0xffffffff,  0x1fffff,  0xfffffffe,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff9fff,  0x7fffffe,  0xffffffff,  0xffffffff,  0x1c7ff,  0xfdfff,  0xfffff,  0xfffff,  0xddfff,  0xffffffff,  0xffcfffff,  0x108001ff,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffff,  0xffffffff,  0xffff07ff,  0xffffffff,  0x3fffff,  0x1fffffff,  0x1ff0fff,  0xffff0000,  0x1f3fff,  0xffffffff,  0xffff0fff,  0x3ff,  0x0,  0xfffffff,  0xffffffff,  0x7fffffff,  0x1ffffe,  0x0,  0x80,  0x0,  0x0,  0xffffffff,  0xffefffff,  0xfef,  0x0,  0xffffffff,  0xfc00f3ff,  0xffffffff,  0x3ffbf,  0xffffffff,  0x3fffff,  0xfc00e000,  0x3fffffff,  0x0,  0x0,  0x0,  0x6fde00,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x0,  0x0,  0x3f3fffff,  0xffffffff,  0xaaff3f3f,  0x3fffffff,  0xffffffff,  0x5fdfffff,  0xfcf1fdc,  0x1fdc1fff,  0x0,  0x0,  0x0,  0x80020000,  0x1fff0000,  0x0,  0x0,  0x0,  0x3e2ffc84,  0xf3ffbd50,  0x43e0,  0xffffffff,  0x1ff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffc00000,  0xffffffff,  0x3ff,  0xffffffff,  0xffff7fff,  0x7fffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xc781f,  0xffffffff,  0xffff20bf,  0xffffffff,  0x80ff,  0x7fffff,  0x7f7f7f7f,  0x7f7f7f7f,  0xffffffff,  0x0,  0x8000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe0,  0x1f3e03fe,  0xfffffffe,  0xffffffff,  0xe07fffff,  0xfffffffe,  0xffffffff,  0xf7ffffff,  0xffffffe0,  0xfffe3fff,  0xffffffff,  0xffffffff,  0x7fff,  0x7ffffff,  0x0,  0xffff0000,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3fffff,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x1fff,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x1fff,  0x0,  0xffff0000,  0x3fffffff,  0xffff1fff,  0xc00,  0xffffffff,  0x8ff07fff,  0x80ffffff,  0xffffffff,  0xffffffff,  0xffff,  0xff800000,  0xfffffffc,  0xffffffff,  0xffffffff,  0xf79ff,  0x7ff,  0x0,  0xff000000,  0xfffff7bb,  0xff,  0xffffffff,  0xfffff,  0xffffffff,  0xffffffff,  0xf,  0x8fc0000,  0xfffffc00,  0xffff07ff,  0x7ffff,  0x1fffffff,  0xffffffff,  0xfff7ffff,  0x8000,  0x0,  0xffffffff,  0x7fffff,  0x3fff,  0x47fffff,  0xffffffff,  0x7fffffff,  0x38000005,  0x3cffff,  0x7e7e7e,  0x7f7f,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0x7ff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff000f,  0xfffff87f,  0xfffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff3fff,  0xffffffff,  0xffffffff,  0x3ffffff,  0x0,  0xe0f8007f,  0x5f7ffdff,  0xffffffdb,  0xffffffff,  0xffffffff,  0x3ffff,  0xfff80000,  0xffffffff,  0xffffffff,  0x3fffffff,  0xffff0000,  0xffffffff,  0xfffcffff,  0xffffffff,  0xff,  0xfff0000,  0x0,  0x0,  0x0,  0xffdf0000,  0xffffffff,  0xffffffff,  0xffffffff,  0x1fffffff,  0x0,  0x7fffffe,  0x7fffffe,  0xffffffc0,  0xffffffff,  0x7fffffff,  0x1cfcfcfc,  0x0,  0xffffefff,  0xb7ffff7f,  0x3fff3fff,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0x7ffffff,  0x0,  0x0,  0xffffffff,  0x1fffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1fffffff,  0xffffffff,  0x1ffff,  0x0,  0x7fffffff,  0xffff0000,  0x7ff,  0x0,  0x3fffffff,  0xffffffff,  0x3eff0f,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3fffffff,  0x0,  0x0,  0x0,  0xfffffd3f,  0x91bfffff,  0x3fffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3fffff,  0x3ffffff,  0x0,  0x0,  0xffffffff,  0xc0ffffff,  0x0,  0x0,  0xfeeff06f,  0xfffff,  0x0,  0x1fffffff,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0x3fffff,  0x3fffff,  0x7ffff,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0x1ff,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0x3f,  0x0,  0xfffffffc,  0x1ffffff,  0xffff0000,  0x1ff,  0xffffffff,  0x7ffff,  0x0,  0x0,  0xffffffff,  0xffffffff,  0x1e,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0x3fffff,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0x7fff,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0x7,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0x7fff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0x1ffffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffff001f,  0x7fffffff,  0xfff80000,  0x0,  0x0,  0x0,  0x3,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffdfffff,  0xffffffff,  0xdfffffff,  0xebffde64,  0xffffffef,  0xffffffff,  0xdfdfe7bf,  0x7bffffff,  0xfffdfc5f,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffff3f,  0xf7fffffd,  0xf7ffffff,  0xffdfffff,  0xffdfffff,  0xffff7fff,  0xffff7fff,  0xfffffdff,  0xfffffdff,  0xff7,  0x0,  0xffffffef,  0xaf7fe96,  0xaa96ea84,  0x5ef7f796,  0xffffbff,  0xffffbee,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x7fffff,  0x0,  0xffffffff,  0x1fffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3fffffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//2304 bytes
+enum markTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x40,  0xe0], [ 0x100,  0x140,  0x2c00], [ 0x2020100,  0x4020302,  0x6020205,  0x2070202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020208,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000,  0x30002,  0x50004,  0x70006,  0x90008,  0xb000a,  0xd000c,  0xe,  0xf0000,  0x0,  0x100000,  0x120011,  0x140013,  0x160015,  0x0,  0x17,  0x0,  0x0,  0x0,  0x0,  0x0,  0x190018,  0x0,  0x1a,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1b,  0x1d001c,  0x1f001e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x200000,  0x0,  0x21,  0x220000,  0x0,  0x0,  0x0,  0x0,  0x23,  0x0,  0x0,  0x250024,  0x0,  0x0,  0x26,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x270000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x280000,  0x29,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2a0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3f8,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xfffe0000,  0xbfffffff,  0xb6,  0x0,  0x7ff0000,  0x0,  0xfffff800,  0x10000,  0x0,  0x0,  0x9fc00000,  0x3d9f,  0x20000,  0xffff0000,  0x7ff,  0x0,  0x0,  0x1ffc0,  0x0,  0xff800,  0xfbc00000,  0x3eef,  0xe000000,  0x0,  0x0,  0x0,  0x0,  0x7ffffff0,  0xf,  0xdc000000,  0xfeffff,  0xc,  0xe,  0xd0000000,  0x80399f,  0xc,  0xe,  0xd0000000,  0x23987,  0x230000,  0xe,  0xd0000000,  0x3bbf,  0xc,  0xe,  0xd0000000,  0xc0399f,  0xc,  0x4,  0xc0000000,  0x803dc7,  0x0,  0xe,  0xc0000000,  0x603ddf,  0xc,  0xc,  0xd0000000,  0x603ddf,  0xc,  0xc,  0xc0000000,  0x803ddf,  0xc,  0xc,  0x0,  0xff5f8400,  0xc0000,  0x0,  0x7f20000,  0x7f80,  0x0,  0x0,  0x1bf20000,  0x3f00,  0x0,  0x3000000,  0xc2a00000,  0x0,  0xfffe0000,  0xfeffe0df,  0x1fffffff,  0x40,  0x0,  0x0,  0x7ffff800,  0xc3c00000,  0x1e3f9d,  0x3c00bffc,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe0000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1c0000,  0x1c0000,  0xc0000,  0xc0000,  0x0,  0xfff00000,  0x200fffff,  0x0,  0x3800,  0x0,  0x0,  0x0,  0x0,  0x200,  0x0,  0x0,  0x0,  0xfff0fff,  0x0,  0x0,  0x0,  0xffff0000,  0x301,  0x0,  0xf800000,  0x0,  0x7fe00000,  0x9fffffff,  0x0,  0x0,  0x0,  0x0,  0x1f,  0xfff00000,  0x1f,  0xff800,  0x7,  0x3ffe,  0x0,  0xfffc0,  0x0,  0xfffff0,  0x0,  0x0,  0x0,  0x0,  0xfff70000,  0x1c21ff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xf000007f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffff0000,  0x1ffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x38000,  0x0,  0x0,  0x0,  0x80000000,  0x0,  0x0,  0x0,  0xffffffff,  0x0,  0xfc00,  0x0,  0x0,  0x6000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3ff78000,  0x80000000,  0x0,  0x0,  0x30000,  0x844,  0xf8,  0x0,  0x0,  0x3,  0xfff00000,  0x1f,  0x3ffff,  0x0,  0x3fc0,  0xfff80,  0x0,  0xf,  0xfff80000,  0x1,  0x0,  0x0,  0x7ffe00,  0x3008,  0x8000000,  0x0,  0xc19d0000,  0x2,  0x60f800,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x37f8,  0x40000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffff,  0x7f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x20000000,  0xf06e,  0x87000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7,  0xff000000,  0x7f,  0x0,  0x7,  0x7ff0000,  0x0,  0x0,  0x7,  0x1fff80,  0x0,  0x0,  0x7,  0xfff80000,  0x1,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xfff800,  0x0,  0x0,  0x0,  0x0,  0xfffe0000,  0x7fffffff,  0x78000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xf807e3e0,  0xfe7,  0x3c00,  0x0,  0x0,  0x0,  0x0,  0x1c,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//2384 bytes
+enum numberTrieEntries = TrieEntry!(bool, 8, 6, 7)([ 0x0,  0x40,  0x180], [ 0x100,  0x280,  0x1a80], [ 0x2020100,  0x4020302,  0x2020605,  0x8070202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x40003,  0x50002,  0x20002,  0x70006,  0x60006,  0x90008,  0x6000a,  0x2000b,  0xc000c,  0x2000d,  0xe0005,  0x20002,  0x20002,  0x2000f,  0x20002,  0x20002,  0x100002,  0x110002,  0x2000e,  0x130012,  0x140002,  0xc,  0x20015,  0x20002,  0x20002,  0x20002,  0x170016,  0x190018,  0x20002,  0x20002,  0x1b001a,  0x20002,  0x20002,  0x1d001c,  0x20002,  0x20002,  0x20002,  0x20002,  0x1e0002,  0x20002,  0x20002,  0x20002,  0x2001f,  0x200002,  0x220021,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x60023,  0x20002,  0xc0024,  0xc0017,  0x2000c,  0x40002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x2000e,  0x20002,  0x260025,  0x20002,  0x280027,  0x230002,  0x20002,  0x20002,  0x20002,  0x20029,  0x2002a,  0x2002b,  0x2002c,  0x20002,  0x20002,  0x2002d,  0x20002,  0x4002e,  0xc002f,  0x20002,  0x20002,  0x20002,  0x20002,  0x50002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20030,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20031,  0x20002,  0x20002,  0x20002,  0x320002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20033,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x20002,  0x0,  0x3ff0000,  0x0,  0x0,  0x0,  0x720c0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3ff,  0x0,  0x0,  0x0,  0x3ff0000,  0x0,  0x0,  0x3ff,  0x0,  0x0,  0x0,  0x0,  0xffc0,  0x0,  0x0,  0x0,  0x3f0ffc0,  0x0,  0x0,  0x0,  0xfcffc0,  0x0,  0x0,  0x0,  0x7ffc0,  0x0,  0x0,  0x0,  0x7f00ffc0,  0x0,  0x0,  0x0,  0x3fffc0,  0x0,  0x0,  0x3ff0000,  0x0,  0x0,  0xfffff,  0x0,  0x0,  0x3ff0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1ffffe00,  0x0,  0x0,  0x0,  0x1c000,  0x0,  0x0,  0x0,  0x3ff03ff,  0x0,  0x0,  0xffc0,  0x0,  0x0,  0x0,  0x7ff0000,  0x0,  0x3ff03ff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3ff03ff,  0x0,  0x0,  0x0,  0x0,  0x3f10000,  0x3ff,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffff0000,  0xffffffff,  0x3e7,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xfffffff,  0x0,  0x0,  0xfffffc00,  0x0,  0x0,  0x0,  0xffc00000,  0xfffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x20000000,  0x80,  0x70003fe,  0x0,  0x0,  0x3c0000,  0x0,  0x0,  0x0,  0x0,  0x3ff,  0xfffeff00,  0x0,  0x3ff,  0xfffe0000,  0x0,  0x0,  0x0,  0x3ff,  0x0,  0x0,  0x0,  0x3f0000,  0x0,  0x0,  0xffffff80,  0xfffff,  0xffffffff,  0x1ffffff,  0x400,  0x0,  0x0,  0x0,  0x0,  0xf,  0x402,  0x0,  0x0,  0x0,  0x3e0000,  0x0,  0x0,  0x0,  0xff000000,  0x0,  0xfc00000,  0x0,  0x0,  0x0,  0x0,  0x0,  0xff,  0x60000000,  0x0,  0x0,  0xff000000,  0xff000000,  0x0,  0x0,  0x0,  0x7fffffff,  0x0,  0x0,  0xfffc0000,  0xffff,  0x0,  0xffc00000,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0x7,  0x0,  0x0,  0x0,  0x3ffff,  0x0,  0x0,  0xffffc000,  0xffffffff,  0x7ff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//2336 bytes
+enum punctuationTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x40,  0xc0], [ 0x100,  0x100,  0x3100], [ 0x2020100,  0x4020302,  0x2020605,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000,  0x20001,  0x30001,  0x50004,  0x70006,  0x10008,  0x90001,  0xb000a,  0x1000c,  0xd0001,  0x1000e,  0x10000f,  0x120011,  0x140013,  0x10015,  0x10001,  0x10016,  0x170001,  0x10001,  0x180001,  0x190001,  0x10001,  0x1b001a,  0x1001c,  0x1001d,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x1001e,  0x1001f,  0x210020,  0x230022,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x240001,  0x260025,  0x270001,  0x280001,  0x10001,  0x10001,  0x2a0029,  0x2c002b,  0x10001,  0x10001,  0x2e002d,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x1002f,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x0,  0x8c00f7ee,  0xb8000001,  0x28000000,  0x0,  0x88c00882,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x40000000,  0x80,  0x0,  0x0,  0x0,  0x0,  0x0,  0xfc000000,  0x0,  0x600,  0x40000000,  0x49,  0x180000,  0xc8003600,  0x0,  0x0,  0x3c00,  0x0,  0x0,  0x100000,  0x0,  0x3fff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3800000,  0x0,  0x7fff0000,  0x40000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10030,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x100000,  0x0,  0x0,  0xc008000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x17fff0,  0x3c000000,  0x0,  0x0,  0x20,  0x0,  0x61f0000,  0x0,  0x0,  0x0,  0xfc00,  0x0,  0x0,  0x0,  0x0,  0x8000000,  0x0,  0x0,  0x0,  0x1ff,  0x0,  0x0,  0x0,  0x0,  0x1,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x6000,  0x18000000,  0x0,  0x0,  0x3800,  0x0,  0x600000,  0x0,  0x0,  0x0,  0x0,  0x7700000,  0x0,  0x7ff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x30,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc0000000,  0x0,  0x0,  0x0,  0x0,  0x3f7f,  0x0,  0x0,  0x0,  0x0,  0xfc000000,  0x1,  0x0,  0x0,  0x0,  0xf0000000,  0x0,  0xf8000000,  0x0,  0xc0000000,  0x0,  0x0,  0x800ff,  0x0,  0xffff0000,  0xffff00ff,  0x7ffbffef,  0x60000000,  0x6000,  0x0,  0x0,  0x0,  0xf00,  0x600,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3fff00,  0x0,  0x0,  0x60,  0xffc0,  0x0,  0x0,  0x0,  0x0,  0x1fffff8,  0x0,  0xf000000,  0x30000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xde000000,  0x0,  0x0,  0x0,  0x10000,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xfff7fff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xfff3ff0e,  0x20010000,  0x0,  0x0,  0x0,  0x1,  0x0,  0x8000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc0000000,  0xe000,  0x0,  0x0,  0x40080000,  0x0,  0x0,  0x0,  0xfc0000,  0x0,  0x0,  0x0,  0xf00000,  0x0,  0x0,  0xc000,  0x7000000,  0x0,  0xc000,  0x80000000,  0x0,  0x0,  0x0,  0xc0003ffe,  0x0,  0x0,  0x0,  0xf0000000,  0x0,  0x0,  0x0,  0xc0000000,  0x30000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x800,  0x0,  0xc0000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3ff0000,  0xffff0000,  0xfff7ffff,  0xd0b,  0x0,  0x0,  0x0,  0x0,  0x8c00f7ee,  0xb8000001,  0xa8000000,  0x3f,  0x0,  0x0,  0x0,  0x0,  0x7,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x80000000,  0x0,  0x10000,  0x0,  0x0,  0x0,  0x800000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x80000000,  0x80000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1ff0000,  0x80000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0xfe000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3f80,  0x0,  0x0,  0xd8000000,  0x3,  0x0,  0x0,  0x0,  0xf,  0x0,  0x0,  0x0,  0x1e0,  0x0,  0x0,  0x0,  0x0,  0xf0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//2848 bytes
+enum symbolTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x40,  0xe0], [ 0x100,  0x140,  0x3d00], [ 0x3020100,  0x5030403,  0x3030306,  0x8070303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x3030303,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000,  0x30002,  0x50004,  0x70006,  0x80001,  0xa0009,  0xc000b,  0xe000d,  0x1000f,  0x100001,  0x10001,  0x110001,  0x120001,  0x130001,  0x10001,  0x140001,  0x160015,  0x180017,  0x170019,  0x1a0017,  0x1b0017,  0x1c0017,  0x1001d,  0x1f001e,  0x210020,  0x170022,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x230001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10024,  0x250001,  0x10026,  0x10027,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x280001,  0x290001,  0x2b002a,  0x2c0001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x2e002d,  0x30002f,  0x10001,  0x320031,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10033,  0x350034,  0x370036,  0x390038,  0x3b003a,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x0,  0x70000810,  0x40000000,  0x50000001,  0x0,  0x113d37c,  0x800000,  0x800000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xfffc003c,  0xffffafe0,  0x0,  0x0,  0x0,  0x200000,  0x30,  0x0,  0x0,  0x400000,  0x0,  0x0,  0x0,  0x0,  0x4,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x8000,  0x0,  0x0,  0x0,  0xc9c0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x40000000,  0x60000200,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x400000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc0c0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x20000,  0x0,  0x0,  0x0,  0x10000,  0x0,  0x0,  0x0,  0x7f80000,  0x0,  0x0,  0x0,  0x80000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x80000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xfce8000e,  0x1500000,  0x0,  0x0,  0x0,  0xc0000000,  0x1e0dfbf,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc0000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3ff0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x8000000,  0x0,  0x0,  0x0,  0x1,  0x0,  0x0,  0x0,  0xc0000000,  0xffffffff,  0x0,  0x0,  0x0,  0x1ff007fe,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xa0000000,  0xe000e003,  0x6000e000,  0x0,  0x0,  0x40010,  0x1c000000,  0x1c00,  0x7ffffff,  0x0,  0x0,  0xc1d0037b,  0xc0042af,  0xbc1f,  0x0,  0xffff0000,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xfffff0ff,  0xfffff9ff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xfffff,  0xffffffff,  0x7f,  0x7ff,  0x0,  0xf0000000,  0xffffffff,  0xffffffff,  0x3ff,  0xfffffffe,  0xffffffff,  0xffffffff,  0xff,  0xfff00000,  0xffffffff,  0xffffff9f,  0xffff003f,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xfe000007,  0xffffffff,  0xf0ffffff,  0xcfffffff,  0xffffffff,  0xffffffff,  0x3ff1fff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7e0,  0x0,  0x0,  0x0,  0x0,  0xfbffffff,  0xffffffff,  0xffffffff,  0xfffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3fffff,  0xfff0000,  0xc0010,  0xc0c00001,  0x0,  0x0,  0x18000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffc30000,  0x0,  0xffffffff,  0xf,  0x7fffffff,  0xfffffc00,  0x100ff,  0xffffffff,  0xfffffc00,  0x1ffff,  0xffffffff,  0x7fffffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0x0,  0x0,  0x0,  0x0,  0xffff0000,  0xffffffff,  0x7f,  0x0,  0x7fffff,  0x3,  0x0,  0x0,  0x600,  0x0,  0x0,  0x0,  0x0,  0x3c00f00,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3800000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x200,  0x0,  0x0,  0x0,  0xfffc0000,  0x3,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x30000000,  0x0,  0x0,  0x0,  0x274,  0x0,  0x0,  0x0,  0x0,  0x70000810,  0x40000000,  0x50000001,  0x0,  0x0,  0x0,  0x0,  0x30007f7f,  0x0,  0xff800000,  0x0,  0xfe000000,  0xfff03ff,  0x0,  0xffff0000,  0x1fffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3fffff,  0xffffffff,  0xfffffe7f,  0xffffffff,  0x1c1f,  0xfffff018,  0xffffc3ff,  0x3fffffff,  0x0,  0xffffffff,  0xffffffff,  0x23,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0x7fffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x8000002,  0x8000000,  0x200000,  0x200000,  0x8000,  0x8000,  0x200,  0x200,  0x8,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x30000,  0xffffffff,  0xffff0fff,  0xffffffff,  0xffffffff,  0xfffff,  0x7ffe7fff,  0xfffefffe,  0x0,  0xffff0000,  0xffff7fff,  0xffffffff,  0xffff0fff,  0x7ffffff,  0x0,  0x0,  0xffffffc0,  0xffff0007,  0x7ffffff,  0x301ff,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffbf0001,  0xffffffff,  0x1fffffff,  0xfffff,  0xffffffff,  0x7df,  0x1ffff,  0xffffffff,  0x7fffffff,  0xfffffffd,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x1effffff,  0xffffffff,  0x3fffffff,  0xffff000f,  0xff,  0x0,  0x0,  0x0,  0xf8000000,  0xffffffff,  0xffffffff,  0xffe1,  0x0,  0xffffffff,  0xffffffff,  0x3f,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xfffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//4576 bytes
+enum graphicalTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x40,  0x170], [ 0x100,  0x260,  0x6100], [ 0x3020100,  0x7060504,  0xb0a0908,  0xe0d0c0a,  0x3030303,  0x100a0f03,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a11,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0xa0a0a0a,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000,  0x20001,  0x30001,  0x50004,  0x70006,  0x90008,  0xb000a,  0xd000c,  0x1000e,  0x10000f,  0x10001,  0x120011,  0x140013,  0x160015,  0x180017,  0x190001,  0x1b001a,  0x1c0001,  0x1001d,  0x1e0001,  0x10001,  0x1f0001,  0x210020,  0x230022,  0x250024,  0x10026,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x270001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x280001,  0x10001,  0x10001,  0x10029,  0x2b002a,  0x2d002c,  0x2f002e,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x300001,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x10031,  0x330032,  0x340001,  0x360035,  0x380037,  0x3a0039,  0x31003b,  0x310031,  0x3d003c,  0x3f003e,  0x310040,  0x310041,  0x430042,  0x310031,  0x310031,  0x310044,  0x310031,  0x310031,  0x310031,  0x310031,  0x10001,  0x450001,  0x310046,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x10001,  0x10001,  0x310047,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x10001,  0x310048,  0x310031,  0x490031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x31004a,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x4c004b,  0x4e004d,  0x50004f,  0x520051,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310053,  0x550054,  0x570056,  0x590058,  0x5b005a,  0x310031,  0x310031,  0x310031,  0x310031,  0x10001,  0x10001,  0x10001,  0x1005c,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x5d0001,  0x31005e,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x10001,  0x31005e,  0x310031,  0x310031,  0x5f0031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x310031,  0x0,  0xffffffff,  0xffffffff,  0x7fffffff,  0x0,  0xffffdfff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x7cffffff,  0xffffd7f0,  0xfffffffb,  0xffffffff,  0xffffffff,  0xffffffff,  0xfffe00ff,  0xfe7fffff,  0xfffffffe,  0xfffe86ff,  0xffffffff,  0xffff00ff,  0x1f07ff,  0xcfffffc0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xdfffffff,  0xffffffff,  0xffff3fff,  0xffffffff,  0xffffe7ff,  0xffffffff,  0xffffffff,  0x3ffff,  0xffffffff,  0x7ffffff,  0xffffffff,  0x7fff3fff,  0x4fffffff,  0x0,  0x0,  0x1ffd,  0x0,  0x7ffffff0,  0xffffffff,  0xffffffff,  0xffffffff,  0xfeffffff,  0xfff99fee,  0xf3c5fdff,  0xb080799f,  0xfffffcf,  0xfff987ee,  0xd36dfdff,  0x5e023987,  0x3fffc0,  0xfffbbfee,  0xf3edfdff,  0x13bbf,  0x3ffcf,  0xfff99fee,  0xf3edfdff,  0xb0c0399f,  0xffffcf,  0xd63dc7ec,  0xc3ffc718,  0x813dc7,  0x7ffffc0,  0xfffddfee,  0xe3effdff,  0x3603ddf,  0xff00ffcf,  0xfffddfec,  0xf3effdff,  0x40603ddf,  0x6ffcf,  0xfffddfec,  0xe7ffffff,  0x807ddf,  0xfe3fffcf,  0xfc7fffec,  0x2ffbffff,  0xff5f847f,  0x1c0000,  0xfffffffe,  0x87ffffff,  0xfffffff,  0x0,  0xfef02596,  0x3bffecae,  0xf3ff3f5f,  0x0,  0xffffffff,  0xffffffff,  0xfffffeff,  0xfffe1fff,  0xfeffffff,  0xdfffffff,  0x7ffdfff,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff20bf,  0xffffffff,  0xffffffff,  0xffffffff,  0x3d7f3dff,  0xffffffff,  0xffff3dff,  0x7f3dffff,  0xff7fff3d,  0xffffffff,  0xff3dffff,  0xffffffff,  0xe7ffffff,  0x1fffffff,  0x3ffffff,  0xffffffff,  0xffffffff,  0x1fffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x1fffffff,  0xffffffff,  0xffffffff,  0x1ffff,  0x1fdfff,  0x7fffff,  0xfffff,  0xddfff,  0xffffffff,  0xffffffff,  0x3fffffff,  0x3ff03ff,  0x3ff3fff,  0xffffffff,  0xffffffff,  0xffffff,  0xffffffff,  0xffff07ff,  0xffffffff,  0x3fffff,  0x1fffffff,  0xfff0fff,  0xfffffff1,  0x1f3fff,  0xffffffff,  0xffff0fff,  0xc7ff03ff,  0xffffffff,  0xcfffffff,  0xffffffff,  0x7fffffff,  0x9fffffff,  0x3ff03ff,  0x3fff,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffff0fff,  0x1fffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xf00fffff,  0xffffffff,  0xf8ffffff,  0xffffe3ff,  0xffffffff,  0x0,  0x0,  0xffff00ff,  0x7fffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xf000007f,  0x3f3fffff,  0xffffffff,  0xaaff3f3f,  0x3fffffff,  0xffffffff,  0xffdfffff,  0xefcfffdf,  0x7fdcffff,  0xffff07ff,  0xffff80ff,  0xffffffff,  0xfff30000,  0x1fff7fff,  0x7ffffff,  0xffff0000,  0x1ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff03ff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xfffff,  0xffffffff,  0x7f,  0x7ff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xfffffffe,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3ff1fff,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffff7fff,  0x7fffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xfe0fffff,  0xffffffff,  0xffff20bf,  0xffffffff,  0x800180ff,  0x7fffff,  0x7f7f7f7f,  0x7f7f7f7f,  0xffffffff,  0xffffffff,  0xfffffff,  0x0,  0x0,  0xfbffffff,  0xffffffff,  0xffffffff,  0xfffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3fffff,  0xfff0000,  0xffffffff,  0xffffffff,  0xfffffffe,  0xffffffff,  0xfe7fffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffe0,  0xfffe3fff,  0xffffffff,  0xffffffff,  0xffff7fff,  0x7ffffff,  0xffffffff,  0xffff000f,  0x7fffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x7fffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3fffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x1fff,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff1fff,  0xffffffff,  0xffff007f,  0xffffffff,  0xffffffff,  0xfff,  0xffffffff,  0xffffffff,  0x80ffffff,  0xffffffff,  0xffffffff,  0xffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xf7fff,  0x7ff,  0x0,  0xff000000,  0xffffffff,  0x3ff0fff,  0xffffffff,  0xffffff,  0xffffffff,  0xffffffff,  0x3ffc01f,  0xfffffff,  0xffffffff,  0xffffffff,  0x800fffff,  0x1fffffff,  0xffffffff,  0xffffffff,  0xc3ffbfff,  0x0,  0xffffffff,  0x7fffff,  0xf3ff3fff,  0xfffffff,  0xffffffff,  0xffffffff,  0xf8000007,  0x7fffff,  0x7e7e7e,  0x7f7f,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0x3ff3fff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff000f,  0xfffff87f,  0xfffffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff3fff,  0xffffffff,  0xffffffff,  0x3ffffff,  0x0,  0xe0f8007f,  0x5f7fffff,  0xffffffdb,  0xffffffff,  0xffffffff,  0xffffffff,  0xfff80003,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0000,  0xffffffff,  0xfffcffff,  0xffffffff,  0xff,  0x3fff0000,  0x3ffffff,  0xffff007f,  0xfff7ffff,  0xffdf0f7f,  0xffffffff,  0xffffffff,  0xffffffff,  0x1fffffff,  0xfffffffe,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x7fffffff,  0x1cfcfcfc,  0x30007f7f,  0xffffefff,  0xb7ffff7f,  0x3fff3fff,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0x7ffffff,  0xffffff87,  0xff8fffff,  0xffffffff,  0xffffffff,  0xfff07ff,  0x0,  0xffff0000,  0x3fffffff,  0x0,  0x0,  0x0,  0x0,  0x1fffffff,  0xffffffff,  0x1ffff,  0x0,  0x7fffffff,  0xffff000f,  0x7ff,  0x0,  0xbfffffff,  0xffffffff,  0x3fff0f,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3fffffff,  0x3ff,  0x0,  0x0,  0xfffffd3f,  0x91bfffff,  0xffbfffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x8fffffff,  0x83ffffff,  0x0,  0x0,  0xffffffff,  0xc0ffffff,  0x0,  0x0,  0xfeeff06f,  0x870fffff,  0x1ff00ff,  0xffffffff,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xfe3fffff,  0xff3fffff,  0xff07ffff,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0x1ff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7fffffff,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xfffc3fff,  0xffff,  0xffffffff,  0xdfffffff,  0xffff0003,  0x3ff01ff,  0xffffffff,  0xffdfffff,  0xf,  0x0,  0xffffffff,  0xffffffff,  0x3ff01ff,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffff,  0x3ff,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0x7fff,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xf0007,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0x7fff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0x1ffffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffff001f,  0x7fffffff,  0xffff8000,  0x0,  0x0,  0x0,  0x3,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3fffff,  0xffffffff,  0xfffffe7f,  0xffffffff,  0xf807ffff,  0xffffffff,  0xffffffff,  0x3fffffff,  0x0,  0xffffffff,  0xffffffff,  0x3f,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0x7fffff,  0x3ffff,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffdfffff,  0xffffffff,  0xdfffffff,  0xebffde64,  0xffffffef,  0xffffffff,  0xdfdfe7bf,  0x7bffffff,  0xfffdfc5f,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffff3f,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffcfff,  0xffffffff,  0xffffffef,  0xaf7fe96,  0xaa96ea84,  0x5ef7f796,  0xffffbff,  0xffffbee,  0x0,  0x30000,  0xffffffff,  0xffff0fff,  0xffffffff,  0xffffffff,  0xfffff,  0x7ffe7fff,  0xfffefffe,  0x0,  0xffff07ff,  0xffff7fff,  0xffffffff,  0xffff0fff,  0x7ffffff,  0x0,  0x0,  0xffffffc0,  0xffff0007,  0x7ffffff,  0x301ff,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffbf0001,  0xffffffff,  0x1fffffff,  0xfffff,  0xffffffff,  0x7df,  0x1ffff,  0xffffffff,  0x7fffffff,  0xfffffffd,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x1effffff,  0xffffffff,  0x3fffffff,  0xffff000f,  0xff,  0x0,  0x0,  0x0,  0xf8000000,  0xffffffff,  0xffffffff,  0xffe1,  0x0,  0xffffffff,  0xffffffff,  0x3f,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xfffff,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x7fffff,  0x0,  0xffffffff,  0x1fffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3fffffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//3664 bytes
+enum nonCharacterTrieEntries = TrieEntry!(bool, 7, 4, 4, 6)([ 0x0,  0x20,  0x98,  0x208], [ 0x80,  0xf0,  0x2e0,  0x3180], [ 0x3020100,  0x7060504,  0xa090808,  0xb0b0b0b,  0xb0b0b0b,  0xb0b0b0b,  0xb0b0b0b,  0xb0b0b0b,  0xb0b0b0b,  0xb0b0b0b,  0xb0b0b0b,  0xb0b0b0b,  0xb0b0b0b,  0xb0b0b0b,  0xb0b0b0c,  0xd080808,  0xd080808,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000,  0x30002,  0x50004,  0x70006,  0x90008,  0xb000a,  0xd000c,  0xd000d,  0xd000d,  0xe000d,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0xf000d,  0x10000d,  0xd0011,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0x12000d,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0x140013,  0x160015,  0x180017,  0x1a0019,  0x1b001b,  0x1d001c,  0x1b001b,  0x1e000d,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b001b,  0x20001f,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b0021,  0x1b001b,  0x1b001b,  0x1b001b,  0x230022,  0x1b001b,  0x1b001b,  0x24001b,  0x260025,  0x1b001b,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0x27000d,  0xd000d,  0x28000d,  0x1b0029,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b002a,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b002b,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b001b,  0x1b001b,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0x2c000d,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0xd000d,  0x2c000d,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000,  0x2,  0x0,  0x0,  0x40003,  0x60005,  0x7,  0x0,  0x90008,  0xb000a,  0xd000c,  0xf000e,  0x100000,  0x120011,  0x140013,  0x160015,  0x180017,  0x1a0019,  0x1c001b,  0x1e001d,  0x20001f,  0x220021,  0x240023,  0x260025,  0x270000,  0x290028,  0x0,  0x2a0000,  0x0,  0x0,  0x2b0000,  0x2d002c,  0x2f002e,  0x310030,  0x0,  0x0,  0x0,  0x0,  0x0,  0x330032,  0x350034,  0x360000,  0x380037,  0x3a0039,  0x3c003b,  0x3e003d,  0x40003f,  0x420041,  0x430000,  0x440000,  0x460045,  0x470042,  0x0,  0x480000,  0x0,  0x0,  0x4a0049,  0x4c004b,  0x4d0000,  0x4f004e,  0x0,  0x50,  0x0,  0x0,  0x0,  0x510000,  0x530052,  0x0,  0x0,  0x0,  0x0,  0x0,  0x54,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x550000,  0x420042,  0x570056,  0x580000,  0x5a0059,  0x5c005b,  0x42005d,  0x51005e,  0x0,  0x5f0000,  0x540000,  0x60,  0x61,  0x630062,  0x57,  0x640000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3a,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x650000,  0x0,  0x670066,  0x0,  0x0,  0x68,  0x380069,  0x0,  0x6b006a,  0x38006c,  0x6d0000,  0x6e0000,  0x6f0000,  0x710070,  0x720000,  0x420073,  0x740042,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x750063,  0x0,  0x0,  0x0,  0x0,  0x760000,  0x770000,  0x790078,  0x7a0000,  0x0,  0x0,  0x7b0000,  0x7d007c,  0x7f007e,  0x800000,  0x54,  0x810064,  0x830082,  0xb0000,  0x84,  0x860085,  0x420042,  0x870032,  0x890088,  0x8b008a,  0x0,  0x42008c,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x8e008d,  0x420042,  0x42008f,  0x420090,  0x920091,  0x420042,  0x940093,  0x420042,  0x950000,  0x420042,  0x420042,  0x420042,  0x960042,  0x420042,  0x420042,  0x420042,  0x970000,  0x980000,  0x99004b,  0x9a0000,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x9b0038,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x9c0000,  0x420042,  0x9d0000,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x42009c,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x0,  0x0,  0x0,  0x0,  0x42009e,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x9f0000,  0x4200a0,  0x4200a1,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x0,  0x3a0000,  0xa2,  0xa30000,  0xa40000,  0x420042,  0xa50000,  0x420042,  0xa60000,  0xa800a7,  0xaa00a9,  0x0,  0x0,  0xab,  0x0,  0xac0000,  0x420042,  0x420042,  0x420042,  0x420042,  0xae00ad,  0xb000af,  0x420042,  0x420042,  0x3d,  0xb200b1,  0x3d00b3,  0xb500b4,  0xb700b6,  0x420042,  0xb900b8,  0xbb00ba,  0xbc0064,  0xbd0000,  0xbf00be,  0xc00042,  0xc10000,  0xa40000,  0x510000,  0x420042,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc20000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x31,  0x0,  0x4200a3,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x420042,  0x0,  0x0,  0x0,  0x0,  0x4200a3,  0x420042,  0x420042,  0x420042,  0xc3,  0x420042,  0x0,  0xc40000,  0x420042,  0x420042,  0x420042,  0x420042,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xbe0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xbe0000,  0x0,  0x0,  0x0,  0x83000000,  0x280f,  0x4,  0x0,  0x1ff00,  0x1800000,  0x1,  0x17900,  0x0,  0xff00,  0xffe0f800,  0x20000020,  0x0,  0x4000,  0x0,  0x1800,  0x0,  0x0,  0xfffc0000,  0x0,  0xf8000000,  0x0,  0x8000c000,  0xb0000000,  0xffffffff,  0xffffffff,  0xffffe002,  0xffffffff,  0x8000000f,  0x0,  0x1000000,  0x66011,  0xc3a0200,  0x4f7f8660,  0xf0000030,  0x67811,  0x2c920200,  0xa1fdc678,  0xffc0003f,  0x44011,  0xc120200,  0xfffec440,  0xfffc0030,  0x66011,  0xc120200,  0x4f3fc660,  0xff000030,  0x29c23813,  0x3c0038e7,  0xff7ec238,  0xf800003f,  0x22011,  0x1c100200,  0xfc9fc220,  0xff0030,  0x22013,  0xc100200,  0xbf9fc220,  0xfff90030,  0x22013,  0x18000000,  0xff7f8220,  0x1c00030,  0x3800013,  0xd0040000,  0xa07b80,  0xffe3ffff,  0x1,  0x78000000,  0xf0000000,  0xffffffff,  0x10fda69,  0xc4001351,  0xc00c0a0,  0xffffffff,  0x100,  0x1e000,  0x1000000,  0x20000000,  0xf8002000,  0xffffffff,  0xdf40,  0x0,  0xc280c200,  0x0,  0xc200,  0x80c20000,  0x8000c2,  0x0,  0xc20000,  0x0,  0x18000000,  0xe0000000,  0xfc000000,  0x0,  0x0,  0xffe00000,  0xe0000000,  0x0,  0x0,  0xfffe0000,  0xffe02000,  0xff800000,  0xfff00000,  0xfff22000,  0xc0000000,  0xfc00fc00,  0xfc008000,  0x0,  0x0,  0xff000000,  0x0,  0xf800,  0x0,  0xffc00000,  0xe0000000,  0xf000f000,  0xe,  0xffe0c000,  0x0,  0xf000,  0x3800fc00,  0x0,  0x30000000,  0x0,  0x80000000,  0x60000000,  0xfc00fc00,  0xffffc000,  0xffffffff,  0xffffffff,  0xf000,  0xe0000000,  0x0,  0xff00000,  0x0,  0x7000000,  0x1c00,  0x0,  0xff00,  0xff800000,  0x0,  0xfffff80,  0xc0c00000,  0x0,  0x5500c0c0,  0xc0000000,  0x0,  0x200000,  0x10300020,  0x80230000,  0x0,  0xc0020,  0xe0008000,  0xf8000000,  0xffff,  0xfffe0000,  0xfc00,  0x0,  0x0,  0xfff00000,  0x0,  0xffffff80,  0xfffff800,  0x0,  0x1,  0x0,  0xfc00e000,  0xffffffff,  0x0,  0x8000,  0x80000000,  0x0,  0x0,  0x1f00000,  0x0,  0xdf40,  0x0,  0x7ffe7f00,  0xff800000,  0x80808080,  0x80808080,  0x0,  0x0,  0xf0000000,  0x4000000,  0x0,  0xffc00000,  0xf000ffff,  0x1800000,  0x0,  0x1f,  0x1c000,  0x8000,  0xf8000000,  0x0,  0xfff0,  0x0,  0x80000000,  0xffffe000,  0xffffffff,  0xe000,  0x0,  0xff80,  0x0,  0x0,  0xfffff000,  0x7f000000,  0x0,  0xfff08000,  0xfffff800,  0xffffffff,  0xffffff,  0x0,  0xfc00f000,  0xfc003fe0,  0xf0000000,  0x7ff00000,  0xe0000000,  0x3c004000,  0xffffffff,  0x0,  0xff800000,  0xc00c000,  0xf0000000,  0x7fffff8,  0xff800000,  0xff818181,  0xffff8080,  0x0,  0xfc00c000,  0x780,  0xf0000000,  0x0,  0xc000,  0xfc000000,  0xffffffff,  0x1f07ff80,  0xa0800000,  0x24,  0x0,  0x7fffc,  0x0,  0xffff,  0x0,  0x30000,  0x0,  0xffffff00,  0xc000ffff,  0xfc000000,  0xff80,  0x80000,  0x20f080,  0x0,  0x60000000,  0xe3030303,  0xc1ff8080,  0x1000,  0x48000080,  0xc000c000,  0xffffffff,  0x78,  0x700000,  0xf000f800,  0xffffffff,  0xffff,  0xc0000000,  0xfffe0000,  0xffffffff,  0x80000000,  0xfff0,  0xfffff800,  0xffffffff,  0x40000000,  0x0,  0xffc000f0,  0xffffffff,  0xc0000000,  0xfffffc00,  0x2c0,  0x6e400000,  0x400000,  0xffffffff,  0x70000000,  0x7c000000,  0x0,  0x3f000000,  0x1100f90,  0x78f00000,  0xfe00ff00,  0x0,  0x0,  0x1c00000,  0xc00000,  0xf80000,  0xfffffe00,  0xffffffff,  0xffffffff,  0x80000000,  0x3c000,  0xffff0000,  0xfffc,  0xfc00fe00,  0xfffffff0,  0xffffffff,  0xfc00fe00,  0xffffffff,  0xfffffc00,  0xffffffff,  0x0,  0xffff8000,  0x0,  0xfff0fff8,  0x0,  0xfe000000,  0xffe0,  0x80000000,  0x7fff,  0xffffffff,  0xfffffffc,  0xffffffff,  0x0,  0x180,  0xc0000000,  0xffffffff,  0xffffffc0,  0xffffffff,  0xff800000,  0xfffc0000,  0x200000,  0x0,  0x20000000,  0x1400219b,  0x10,  0x0,  0x20201840,  0x84000000,  0x203a0,  0x0,  0x0,  0xc0,  0x3000,  0x0,  0x10,  0xf5080169,  0x5569157b,  0xa1080869,  0xf0000400,  0xf0000411,  0xffffffff,  0xfffcffff,  0xfff00000,  0x80018000,  0x10001,  0xffffffff,  0xf800,  0x8000,  0xf8000000,  0xffffffff,  0xffffffff,  0x3f,  0xfff8,  0xf8000000,  0xfffcfe00,  0xffffffff,  0x0,  0x40fffe,  0x0,  0xe0000000,  0xfff00000,  0x0,  0xfffff820,  0xfffe0000,  0x2,  0x0,  0x0,  0xe1000000,  0x0,  0xc0000000,  0xfff0,  0xffffff00,  0xffffffff,  0x7ffffff,  0xffff001e,  0xffffffff,  0xff800000,  0xffffffff,  0xfffffffd,  0x0,  0x0,  0xffff0000,  0x0,  0xc0000000]);
+enum MAX_SIMPLE_LOWER = 1043;
+enum MAX_SIMPLE_UPPER = 1051;
+enum MAX_SIMPLE_TITLE = 1055;
+//8192 bytes
+enum toUpperIndexTrieEntries = TrieEntry!(ushort, 8, 7, 6)([ 0x0,  0x40,  0x200], [ 0x100,  0x380,  0xc00], [ 0x2020100,  0x4020302,  0x2020205,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x10000,  0x30002,  0x50004,  0x70006,  0x90008,  0xa,  0xb0000,  0xd000c,  0xf000e,  0x110010,  0x130012,  0x14,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x150000,  0x0,  0x170016,  0x190018,  0x1b001a,  0x1d001c,  0x0,  0x0,  0x1e0000,  0x1f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x200000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x220021,  0x240023,  0x25,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x260000,  0x27,  0x290028,  0x2a,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2b,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2c0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2e002d,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff,  0x20001,  0x40003,  0x60005,  0x80007,  0xa0009,  0xc000b,  0xe000d,  0x10000f,  0x120011,  0x140013,  0x160015,  0x180017,  0xffff0019,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x1affff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x41bffff,  0x1c001b,  0x1e001d,  0x20001f,  0x220021,  0x240023,  0x260025,  0x280027,  0x2a0029,  0x2c002b,  0x2e002d,  0x30002f,  0xffff0031,  0x330032,  0x350034,  0x370036,  0x390038,  0x3affff,  0x3bffff,  0x3cffff,  0x3dffff,  0x3effff,  0x3fffff,  0x40ffff,  0x41ffff,  0x42ffff,  0x43ffff,  0x44ffff,  0x45ffff,  0x46ffff,  0x47ffff,  0x48ffff,  0x49ffff,  0x4affff,  0x4bffff,  0x4cffff,  0x4dffff,  0x4effff,  0x4fffff,  0x50ffff,  0x51ffff,  0x52041d,  0x53ffff,  0x54ffff,  0x55ffff,  0xffffffff,  0xffff0056,  0xffff0057,  0xffff0058,  0xffff0059,  0xffff005a,  0xffff005b,  0xffff005c,  0x43a005d,  0x5effff,  0x5fffff,  0x60ffff,  0x61ffff,  0x62ffff,  0x63ffff,  0x64ffff,  0x65ffff,  0x66ffff,  0x67ffff,  0x68ffff,  0x69ffff,  0x6affff,  0x6bffff,  0x6cffff,  0x6dffff,  0x6effff,  0x6fffff,  0x70ffff,  0x71ffff,  0x72ffff,  0x73ffff,  0x74ffff,  0xffffffff,  0xffff0075,  0xffff0076,  0x780077,  0xffff0079,  0x7affff,  0x7bffff,  0xffffffff,  0xffff007c,  0xffffffff,  0xffff007d,  0xffffffff,  0xffffffff,  0xffff007e,  0x7fffff,  0xffffffff,  0x80ffff,  0xffff0081,  0xffffffff,  0xffff0082,  0x83ffff,  0x84ffff,  0x85ffff,  0xffffffff,  0xffff0086,  0xffffffff,  0x87ffff,  0xffffffff,  0xffff0088,  0xffffffff,  0xffff0089,  0xffff008a,  0x8bffff,  0xffffffff,  0x8cffff,  0x8dffff,  0xffffffff,  0xffffffff,  0x8effff,  0xffff008f,  0x910090,  0x92ffff,  0xffff0093,  0xffff0094,  0xffff0095,  0xffff0096,  0xffff0097,  0xffff0098,  0xffff0099,  0xffff009a,  0x9c009b,  0x9dffff,  0x9effff,  0x9fffff,  0xa0ffff,  0xa1ffff,  0xa2ffff,  0xa3ffff,  0xa4ffff,  0xa5ffff,  0xffff0442,  0xa700a6,  0xa8ffff,  0xffffffff,  0xa9ffff,  0xaaffff,  0xabffff,  0xacffff,  0xadffff,  0xaeffff,  0xafffff,  0xb0ffff,  0xb1ffff,  0xb2ffff,  0xb3ffff,  0xb4ffff,  0xb5ffff,  0xb6ffff,  0xb7ffff,  0xb8ffff,  0xb9ffff,  0xbaffff,  0xbbffff,  0xbcffff,  0xffffffff,  0xbdffff,  0xbeffff,  0xbfffff,  0xc0ffff,  0xc1ffff,  0xc2ffff,  0xc3ffff,  0xc4ffff,  0xc5ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff00c6,  0xc7ffff,  0xffff00c8,  0xffff00c9,  0xffffffff,  0xcaffff,  0xcbffff,  0xccffff,  0xcdffff,  0xceffff,  0xd000cf,  0xd200d1,  0xffff00d3,  0xd500d4,  0xd6ffff,  0xd7ffff,  0xffffffff,  0xffffffff,  0xffff00d8,  0xd9ffff,  0xdaffff,  0xffff00db,  0xdd00dc,  0xdeffff,  0xffffffff,  0xdfffff,  0xe0ffff,  0xffff00e1,  0xe2ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xe3ffff,  0xffffffff,  0xffff00e4,  0xe5ffff,  0xffffffff,  0xffffffff,  0xe700e6,  0xe900e8,  0xffff00ea,  0xffffffff,  0xffffffff,  0xffff00eb,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xecffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xedffff,  0xeeffff,  0xffffffff,  0xefffff,  0xffffffff,  0xf0ffff,  0xf200f1,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff043c,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xf400f3,  0xf600f5,  0xf7043f,  0xf900f8,  0xfb00fa,  0xfd00fc,  0xff00fe,  0x1010100,  0x1030102,  0x1050104,  0x1070106,  0x1090108,  0x10b010a,  0x10d010c,  0x10f010e,  0x1110110,  0x1130112,  0xffff0114,  0x1160115,  0xffffffff,  0x117ffff,  0x1190118,  0x11affff,  0x11bffff,  0x11cffff,  0x11dffff,  0x11effff,  0x11fffff,  0x120ffff,  0x121ffff,  0x122ffff,  0x123ffff,  0x124ffff,  0x125ffff,  0x1270126,  0xffff0128,  0x129ffff,  0xffffffff,  0xffff012a,  0x12bffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x12d012c,  0x12f012e,  0x1310130,  0x1330132,  0x1350134,  0x1370136,  0x1390138,  0x13b013a,  0x13d013c,  0x13f013e,  0x1410140,  0x1430142,  0x1450144,  0x1470146,  0x1490148,  0x14b014a,  0x14d014c,  0x14f014e,  0x1510150,  0x1530152,  0x1550154,  0x1570156,  0x1590158,  0x15b015a,  0x15cffff,  0x15dffff,  0x15effff,  0x15fffff,  0x160ffff,  0x161ffff,  0x162ffff,  0x163ffff,  0x164ffff,  0x165ffff,  0x166ffff,  0x167ffff,  0x168ffff,  0x169ffff,  0x16affff,  0x16bffff,  0x16cffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x16dffff,  0x16effff,  0x16fffff,  0x170ffff,  0x171ffff,  0x172ffff,  0x173ffff,  0x174ffff,  0x175ffff,  0x176ffff,  0x177ffff,  0x178ffff,  0x179ffff,  0x17affff,  0x17bffff,  0x17cffff,  0x17dffff,  0x17effff,  0x17fffff,  0x180ffff,  0x181ffff,  0x182ffff,  0x183ffff,  0x184ffff,  0x185ffff,  0x186ffff,  0x187ffff,  0xffffffff,  0xffff0188,  0xffff0189,  0xffff018a,  0xffff018b,  0xffff018c,  0xffff018d,  0x18f018e,  0x190ffff,  0x191ffff,  0x192ffff,  0x193ffff,  0x194ffff,  0x195ffff,  0x196ffff,  0x197ffff,  0x198ffff,  0x199ffff,  0x19affff,  0x19bffff,  0x19cffff,  0x19dffff,  0x19effff,  0x19fffff,  0x1a0ffff,  0x1a1ffff,  0x1a2ffff,  0x1a3ffff,  0x1a4ffff,  0x1a5ffff,  0x1a6ffff,  0x1a7ffff,  0x1a8ffff,  0x1a9ffff,  0x1aaffff,  0x1abffff,  0x1acffff,  0x1adffff,  0x1aeffff,  0x1afffff,  0x1b0ffff,  0x1b1ffff,  0x1b2ffff,  0x1b3ffff,  0x1b4ffff,  0x1b5ffff,  0x1b6ffff,  0x1b7ffff,  0x1b8ffff,  0x1b9ffff,  0x1baffff,  0x1bbffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x1bcffff,  0x1be01bd,  0x1c001bf,  0x1c201c1,  0x1c401c3,  0x1c601c5,  0x1c801c7,  0x1ca01c9,  0x1cc01cb,  0x1ce01cd,  0x1d001cf,  0x1d201d1,  0x1d401d3,  0x1d601d5,  0x1d801d7,  0x1da01d9,  0x1dc01db,  0x1de01dd,  0x1e001df,  0x42e01e1,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x1e2ffff,  0xffffffff,  0x1e3ffff,  0xffffffff,  0x1e4ffff,  0x1e5ffff,  0x1e6ffff,  0x1e7ffff,  0x1e8ffff,  0x1e9ffff,  0x1eaffff,  0x1ebffff,  0x1ecffff,  0x1edffff,  0x1eeffff,  0x1efffff,  0x1f0ffff,  0x1f1ffff,  0x1f2ffff,  0x1f3ffff,  0x1f4ffff,  0x1f5ffff,  0x1f6ffff,  0x1f7ffff,  0x1f8ffff,  0x1f9ffff,  0x1faffff,  0x1fbffff,  0x1fcffff,  0x1fdffff,  0x1feffff,  0x1ffffff,  0x200ffff,  0x201ffff,  0x202ffff,  0x203ffff,  0x204ffff,  0x205ffff,  0x206ffff,  0x207ffff,  0x208ffff,  0x209ffff,  0x20affff,  0x20bffff,  0x20cffff,  0x20dffff,  0x20effff,  0x20fffff,  0x210ffff,  0x211ffff,  0x212ffff,  0x213ffff,  0x214ffff,  0x215ffff,  0x216ffff,  0x217ffff,  0x218ffff,  0x219ffff,  0x21affff,  0x21bffff,  0x21cffff,  0x21dffff,  0x21effff,  0x21fffff,  0x220ffff,  0x221ffff,  0x222ffff,  0x223ffff,  0x224ffff,  0x225ffff,  0x226ffff,  0x227ffff,  0x228ffff,  0x229ffff,  0x22affff,  0x22bffff,  0x22cffff,  0x22dffff,  0x22effff,  0x4460444,  0x44a0448,  0x22f044c,  0xffffffff,  0xffffffff,  0x230ffff,  0x231ffff,  0x232ffff,  0x233ffff,  0x234ffff,  0x235ffff,  0x236ffff,  0x237ffff,  0x238ffff,  0x239ffff,  0x23affff,  0x23bffff,  0x23cffff,  0x23dffff,  0x23effff,  0x23fffff,  0x240ffff,  0x241ffff,  0x242ffff,  0x243ffff,  0x244ffff,  0x245ffff,  0x246ffff,  0x247ffff,  0x248ffff,  0x249ffff,  0x24affff,  0x24bffff,  0x24cffff,  0x24dffff,  0x24effff,  0x24fffff,  0x250ffff,  0x251ffff,  0x252ffff,  0x253ffff,  0x254ffff,  0x255ffff,  0x256ffff,  0x257ffff,  0x258ffff,  0x259ffff,  0x25affff,  0x25bffff,  0x25cffff,  0x25dffff,  0x25effff,  0x25fffff,  0x2610260,  0x2630262,  0x2650264,  0x2670266,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2690268,  0x26b026a,  0x26d026c,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x26f026e,  0x2710270,  0x2730272,  0x2750274,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2770276,  0x2790278,  0x27b027a,  0x27d027c,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x27f027e,  0x2810280,  0x2830282,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x284044e,  0x2850450,  0x2860453,  0x2870456,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2890288,  0x28b028a,  0x28d028c,  0x28f028e,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2910290,  0x2930292,  0x2950294,  0x2970296,  0x2990298,  0x29b029a,  0x29d029c,  0xffffffff,  0x4790477,  0x47d047b,  0x481047f,  0x4850483,  0x4890487,  0x48d048b,  0x491048f,  0x4950493,  0x4990497,  0x49d049b,  0x4a1049f,  0x4a504a3,  0x4a904a7,  0x4ad04ab,  0x4b104af,  0x4b504b3,  0x4b904b7,  0x4bd04bb,  0x4c104bf,  0x4c504c3,  0x4c904c7,  0x4cd04cb,  0x4d104cf,  0x4d504d3,  0x2b702b6,  0x4d704e3,  0xffff04e5,  0x4ef0459,  0xffffffff,  0xffffffff,  0xffff04d9,  0xffff02b9,  0xffffffff,  0x4db04e7,  0xffff04e9,  0x4f2045b,  0xffffffff,  0xffffffff,  0xffff04dd,  0xffffffff,  0x2bc02bb,  0x460045d,  0xffffffff,  0x4650463,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2be02bd,  0x46b0468,  0x2bf046e,  0x4720470,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x4df04eb,  0xffff04ed,  0x4f50475,  0xffffffff,  0xffffffff,  0xffff04e1,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff02c1,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2c302c2,  0x2c502c4,  0x2c702c6,  0x2c902c8,  0x2cb02ca,  0x2cd02cc,  0x2cf02ce,  0x2d102d0,  0xffffffff,  0xffffffff,  0xffff02d2,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2d402d3,  0x2d602d5,  0x2d802d7,  0x2da02d9,  0x2dc02db,  0x2de02dd,  0x2e002df,  0x2e202e1,  0x2e402e3,  0x2e602e5,  0x2e802e7,  0x2ea02e9,  0x2ec02eb,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2ee02ed,  0x2f002ef,  0x2f202f1,  0x2f402f3,  0x2f602f5,  0x2f802f7,  0x2fa02f9,  0x2fc02fb,  0x2fe02fd,  0x30002ff,  0x3020301,  0x3040303,  0x3060305,  0x3080307,  0x30a0309,  0x30c030b,  0x30e030d,  0x310030f,  0x3120311,  0x3140313,  0x3160315,  0x3180317,  0x31a0319,  0xffff031b,  0x31cffff,  0xffffffff,  0x31dffff,  0xffff031e,  0xffff031f,  0xffff0320,  0xffff0321,  0xffffffff,  0xffffffff,  0x322ffff,  0xffffffff,  0xffff0323,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x324ffff,  0x325ffff,  0x326ffff,  0x327ffff,  0x328ffff,  0x329ffff,  0x32affff,  0x32bffff,  0x32cffff,  0x32dffff,  0x32effff,  0x32fffff,  0x330ffff,  0x331ffff,  0x332ffff,  0x333ffff,  0x334ffff,  0x335ffff,  0x336ffff,  0x337ffff,  0x338ffff,  0x339ffff,  0x33affff,  0x33bffff,  0x33cffff,  0x33dffff,  0x33effff,  0x33fffff,  0x340ffff,  0x341ffff,  0x342ffff,  0x343ffff,  0x344ffff,  0x345ffff,  0x346ffff,  0x347ffff,  0x348ffff,  0x349ffff,  0x34affff,  0x34bffff,  0x34cffff,  0x34dffff,  0x34effff,  0x34fffff,  0x350ffff,  0x351ffff,  0x352ffff,  0x353ffff,  0x354ffff,  0x355ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0356,  0xffff0357,  0xffffffff,  0x358ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x35a0359,  0x35c035b,  0x35e035d,  0x360035f,  0x3620361,  0x3640363,  0x3660365,  0x3680367,  0x36a0369,  0x36c036b,  0x36e036d,  0x370036f,  0x3720371,  0x3740373,  0x3760375,  0x3780377,  0x37a0379,  0x37c037b,  0x37e037d,  0x37fffff,  0xffffffff,  0xffffffff,  0x380ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x381ffff,  0x382ffff,  0x383ffff,  0x384ffff,  0x385ffff,  0x386ffff,  0x387ffff,  0x388ffff,  0x389ffff,  0x38affff,  0x38bffff,  0x38cffff,  0x38dffff,  0x38effff,  0x38fffff,  0x390ffff,  0x391ffff,  0x392ffff,  0x393ffff,  0x394ffff,  0x395ffff,  0x396ffff,  0x397ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x398ffff,  0x399ffff,  0x39affff,  0x39bffff,  0x39cffff,  0x39dffff,  0x39effff,  0x39fffff,  0x3a0ffff,  0x3a1ffff,  0x3a2ffff,  0x3a3ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3a4ffff,  0x3a5ffff,  0x3a6ffff,  0x3a7ffff,  0x3a8ffff,  0x3a9ffff,  0x3aaffff,  0xffffffff,  0x3abffff,  0x3acffff,  0x3adffff,  0x3aeffff,  0x3afffff,  0x3b0ffff,  0x3b1ffff,  0x3b2ffff,  0x3b3ffff,  0x3b4ffff,  0x3b5ffff,  0x3b6ffff,  0x3b7ffff,  0x3b8ffff,  0x3b9ffff,  0x3baffff,  0x3bbffff,  0x3bcffff,  0x3bdffff,  0x3beffff,  0x3bfffff,  0x3c0ffff,  0x3c1ffff,  0x3c2ffff,  0x3c3ffff,  0x3c4ffff,  0x3c5ffff,  0x3c6ffff,  0x3c7ffff,  0x3c8ffff,  0x3c9ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff03ca,  0xffff03cb,  0x3ccffff,  0x3cdffff,  0x3ceffff,  0x3cfffff,  0x3d0ffff,  0xffffffff,  0xffffffff,  0xffff03d1,  0xffffffff,  0x3d2ffff,  0x3d3ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3d4ffff,  0x3d5ffff,  0x3d6ffff,  0x3d7ffff,  0x3d8ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x420041e,  0x4240422,  0x42a0427,  0xffff042c,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x430ffff,  0x4340432,  0x4380436,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3d9ffff,  0x3db03da,  0x3dd03dc,  0x3df03de,  0x3e103e0,  0x3e303e2,  0x3e503e4,  0x3e703e6,  0x3e903e8,  0x3eb03ea,  0x3ed03ec,  0x3ef03ee,  0x3f103f0,  0xffff03f2,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3f403f3,  0x3f603f5,  0x3f803f7,  0x3fa03f9,  0x3fc03fb,  0x3fe03fd,  0x40003ff,  0x4020401,  0x4040403,  0x4060405,  0x4080407,  0x40a0409,  0x40c040b,  0x40e040d,  0x410040f,  0x4120411,  0x4140413,  0x4160415,  0x4180417,  0x41a0419,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff]);
+//8064 bytes
+enum toLowerIndexTrieEntries = TrieEntry!(ushort, 8, 7, 6)([ 0x0,  0x40,  0x200], [ 0x100,  0x380,  0xbc0], [ 0x2020100,  0x4020302,  0x2020205,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x10000,  0x20000,  0x40003,  0x60005,  0x80007,  0x0,  0x90000,  0xb000a,  0xd000c,  0xf000e,  0x110010,  0x12,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x140013,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x160015,  0x180017,  0x1a0019,  0x1c001b,  0x0,  0x0,  0x1e001d,  0x1f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x210020,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x230022,  0x250024,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x260000,  0x27,  0x290028,  0x2a,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2b,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2c,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2d,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff,  0x20001,  0x40003,  0x60005,  0x80007,  0xa0009,  0xc000b,  0xe000d,  0x10000f,  0x120011,  0x140013,  0x160015,  0x180017,  0xffff0019,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x1b001a,  0x1d001c,  0x1f001e,  0x210020,  0x230022,  0x250024,  0x270026,  0x290028,  0x2b002a,  0x2d002c,  0x2f002e,  0xffff0030,  0x320031,  0x340033,  0x360035,  0x4130037,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0038,  0xffff0039,  0xffff003a,  0xffff003b,  0xffff003c,  0xffff003d,  0xffff003e,  0xffff003f,  0xffff0040,  0xffff0041,  0xffff0042,  0xffff0043,  0xffff0044,  0xffff0045,  0xffff0046,  0xffff0047,  0xffff0048,  0xffff0049,  0xffff004a,  0xffff004b,  0xffff004c,  0xffff004d,  0xffff004e,  0xffff004f,  0xffff0414,  0xffff0051,  0xffff0052,  0xffff0053,  0x54ffff,  0x55ffff,  0x56ffff,  0x57ffff,  0x58ffff,  0x59ffff,  0x5affff,  0x5bffff,  0x423ffff,  0xffff005c,  0xffff005d,  0xffff005e,  0xffff005f,  0xffff0060,  0xffff0061,  0xffff0062,  0xffff0063,  0xffff0064,  0xffff0065,  0xffff0066,  0xffff0067,  0xffff0068,  0xffff0069,  0xffff006a,  0xffff006b,  0xffff006c,  0xffff006d,  0xffff006e,  0xffff006f,  0xffff0070,  0xffff0071,  0xffff0072,  0x740073,  0x75ffff,  0x76ffff,  0xffffffff,  0x77ffff,  0xffff0078,  0xffff0079,  0x7b007a,  0x7cffff,  0x7e007d,  0xffffffff,  0x80007f,  0x820081,  0x83ffff,  0xffff0084,  0x860085,  0xffff0087,  0xffffffff,  0x890088,  0x8affff,  0xffff008b,  0xffff008c,  0xffff008d,  0x8f008e,  0x90ffff,  0xffffffff,  0xffff0091,  0x930092,  0x94ffff,  0x960095,  0x97ffff,  0x98ffff,  0xffff0099,  0xffffffff,  0xffff009a,  0xffffffff,  0xffffffff,  0xffffffff,  0x9c009b,  0x9dffff,  0xffff009e,  0xa0009f,  0xa1ffff,  0xa2ffff,  0xa3ffff,  0xa4ffff,  0xa5ffff,  0xa6ffff,  0xa7ffff,  0xa8ffff,  0xffffffff,  0xffff00a9,  0xffff00aa,  0xffff00ab,  0xffff00ac,  0xffff00ad,  0xffff00ae,  0xffff00af,  0xffff00b0,  0xffff00b1,  0xb20426,  0xffff00b3,  0xffff00b4,  0xb600b5,  0xffff00b7,  0xffff00b8,  0xffff00b9,  0xffff00ba,  0xffff00bb,  0xffff00bc,  0xffff00bd,  0xffff00be,  0xffff00bf,  0xffff00c0,  0xffff00c1,  0xffff00c2,  0xffff00c3,  0xffff00c4,  0xffff00c5,  0xffff00c6,  0xffff00c7,  0xffff00c8,  0xffff00c9,  0xffff00ca,  0xffff00cb,  0xffff00cc,  0xffff00cd,  0xffff00ce,  0xffff00cf,  0xffff00d0,  0xffff00d1,  0xffff00d2,  0xffff00d3,  0xffff00d4,  0xffffffff,  0xffffffff,  0xffffffff,  0xd600d5,  0xd7ffff,  0xffff00d8,  0xd9ffff,  0xdaffff,  0xdc00db,  0xffff00dd,  0xffff00de,  0xffff00df,  0xffff00e0,  0xffff00e1,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff00e2,  0xffff00e3,  0xffffffff,  0xffff00e4,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff00e5,  0xe700e6,  0xffff00e8,  0xffff00e9,  0xeb00ea,  0xec0424,  0xee00ed,  0xf000ef,  0xf200f1,  0xf400f3,  0xf600f5,  0xf800f7,  0xfa00f9,  0xfc00fb,  0xfdffff,  0xff00fe,  0x1010100,  0x1030102,  0x1050104,  0xffffffff,  0xffffffff,  0xffff0425,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x106ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0107,  0xffff0108,  0xffff0109,  0xffff010a,  0xffff010b,  0xffff010c,  0xffff010d,  0xffff010e,  0xffff010f,  0xffff0110,  0xffff0111,  0xffff0112,  0xffffffff,  0xffffffff,  0xffff0113,  0x114ffff,  0x115ffff,  0xffff0116,  0x117ffff,  0x1190118,  0x11b011a,  0x11d011c,  0x11f011e,  0x1210120,  0x1230122,  0x1250124,  0x1270126,  0x1290128,  0x12b012a,  0x12d012c,  0x12f012e,  0x1310130,  0x1330132,  0x1350134,  0x1370136,  0x1390138,  0x13b013a,  0x13d013c,  0x13f013e,  0x1410140,  0x1430142,  0x1450144,  0x1470146,  0x1490148,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff014a,  0xffff014b,  0xffff014c,  0xffff014d,  0xffff014e,  0xffff014f,  0xffff0150,  0xffff0151,  0xffff0152,  0xffff0153,  0xffff0154,  0xffff0155,  0xffff0156,  0xffff0157,  0xffff0158,  0xffff0159,  0xffff015a,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff015b,  0xffff015c,  0xffff015d,  0xffff015e,  0xffff015f,  0xffff0160,  0xffff0161,  0xffff0162,  0xffff0163,  0xffff0164,  0xffff0165,  0xffff0166,  0xffff0167,  0xffff0168,  0xffff0169,  0xffff016a,  0xffff016b,  0xffff016c,  0xffff016d,  0xffff016e,  0xffff016f,  0xffff0170,  0xffff0171,  0xffff0172,  0xffff0173,  0xffff0174,  0xffff0175,  0x1770176,  0x178ffff,  0x179ffff,  0x17affff,  0x17bffff,  0x17cffff,  0x17dffff,  0xffffffff,  0xffff017e,  0xffff017f,  0xffff0180,  0xffff0181,  0xffff0182,  0xffff0183,  0xffff0184,  0xffff0185,  0xffff0186,  0xffff0187,  0xffff0188,  0xffff0189,  0xffff018a,  0xffff018b,  0xffff018c,  0xffff018d,  0xffff018e,  0xffff018f,  0xffff0190,  0xffff0191,  0xffff0192,  0xffff0193,  0xffff0194,  0xffff0195,  0xffff0196,  0xffff0197,  0xffff0198,  0xffff0199,  0xffff019a,  0xffff019b,  0xffff019c,  0xffff019d,  0xffff019e,  0xffff019f,  0xffff01a0,  0xffff01a1,  0xffff01a2,  0xffff01a3,  0xffff01a4,  0xffff01a5,  0xffff01a6,  0xffff01a7,  0xffff01a8,  0xffff01a9,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x1aaffff,  0x1ac01ab,  0x1ae01ad,  0x1b001af,  0x1b201b1,  0x1b401b3,  0x1b601b5,  0x1b801b7,  0x1ba01b9,  0x1bc01bb,  0x1be01bd,  0x1c001bf,  0x1c201c1,  0x1c401c3,  0x1c601c5,  0x1c801c7,  0x1ca01c9,  0x1cc01cb,  0x1ce01cd,  0xffff01cf,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x41dffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x1d101d0,  0x1d301d2,  0x1d501d4,  0x1d701d6,  0x1d901d8,  0x1db01da,  0x1dd01dc,  0x1df01de,  0x1e101e0,  0x1e301e2,  0x1e501e4,  0x1e701e6,  0x1e901e8,  0x1eb01ea,  0x1ed01ec,  0x1ef01ee,  0x1f101f0,  0x1f301f2,  0x1f501f4,  0x1f6ffff,  0xffffffff,  0xffffffff,  0x1f7ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff01f8,  0xffff01f9,  0xffff01fa,  0xffff01fb,  0xffff01fc,  0xffff01fd,  0xffff01fe,  0xffff01ff,  0xffff0200,  0xffff0201,  0xffff0202,  0xffff0203,  0xffff0204,  0xffff0205,  0xffff0206,  0xffff0207,  0xffff0208,  0xffff0209,  0xffff020a,  0xffff020b,  0xffff020c,  0xffff020d,  0xffff020e,  0xffff020f,  0xffff0210,  0xffff0211,  0xffff0212,  0xffff0213,  0xffff0214,  0xffff0215,  0xffff0216,  0xffff0217,  0xffff0218,  0xffff0219,  0xffff021a,  0xffff021b,  0xffff021c,  0xffff021d,  0xffff021e,  0xffff021f,  0xffff0220,  0xffff0221,  0xffff0222,  0xffff0223,  0xffff0224,  0xffff0225,  0xffff0226,  0xffff0227,  0xffff0228,  0xffff0229,  0xffff022a,  0xffff022b,  0xffff022c,  0xffff022d,  0xffff022e,  0xffff022f,  0xffff0230,  0xffff0231,  0xffff0232,  0xffff0233,  0xffff0234,  0xffff0235,  0xffff0236,  0xffff0237,  0xffff0238,  0xffff0239,  0xffff023a,  0xffff023b,  0xffff023c,  0xffff023d,  0xffff023e,  0xffff023f,  0xffff0240,  0xffff0241,  0xffff0242,  0x4280427,  0x42a0429,  0xffff042b,  0xffffffff,  0xffff0243,  0xffff0244,  0xffff0245,  0xffff0246,  0xffff0247,  0xffff0248,  0xffff0249,  0xffff024a,  0xffff024b,  0xffff024c,  0xffff024d,  0xffff024e,  0xffff024f,  0xffff0250,  0xffff0251,  0xffff0252,  0xffff0253,  0xffff0254,  0xffff0255,  0xffff0256,  0xffff0257,  0xffff0258,  0xffff0259,  0xffff025a,  0xffff025b,  0xffff025c,  0xffff025d,  0xffff025e,  0xffff025f,  0xffff0260,  0xffff0261,  0xffff0262,  0xffff0263,  0xffff0264,  0xffff0265,  0xffff0266,  0xffff0267,  0xffff0268,  0xffff0269,  0xffff026a,  0xffff026b,  0xffff026c,  0xffff026d,  0xffff026e,  0xffff026f,  0xffff0270,  0xffff0271,  0xffff0272,  0xffff0273,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2750274,  0x2770276,  0x2790278,  0x27b027a,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x27d027c,  0x27f027e,  0x2810280,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2830282,  0x2850284,  0x2870286,  0x2890288,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x28b028a,  0x28d028c,  0x28f028e,  0x2910290,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2930292,  0x2950294,  0x2970296,  0xffffffff,  0xffff042c,  0xffff042d,  0xffff042e,  0xffff042f,  0x298ffff,  0x299ffff,  0x29affff,  0x29bffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x29d029c,  0x29f029e,  0x2a102a0,  0x2a302a2,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x43d043c,  0x43f043e,  0x4410440,  0x4430442,  0x4450444,  0x4470446,  0x4490448,  0x44b044a,  0x44d044c,  0x44f044e,  0x4510450,  0x4530452,  0x4550454,  0x4570456,  0x4590458,  0x45b045a,  0x45d045c,  0x45f045e,  0x4610460,  0x4630462,  0x4650464,  0x4670466,  0x4690468,  0x46b046a,  0xffffffff,  0x46c0472,  0xffff0473,  0x4780430,  0x2bd02bc,  0x2bf02be,  0xffff046d,  0xffffffff,  0xffffffff,  0x46e0474,  0xffff0475,  0x4790431,  0x2c202c1,  0x2c402c3,  0xffff046f,  0xffffffff,  0xffffffff,  0x4330432,  0xffffffff,  0x4350434,  0x2c702c6,  0x2c902c8,  0xffffffff,  0xffffffff,  0xffffffff,  0x4370436,  0xffff0438,  0x43a0439,  0x2cb02ca,  0x2cd02cc,  0xffff02ce,  0xffffffff,  0xffffffff,  0x4700476,  0xffff0477,  0x47a043b,  0x2d002cf,  0x2d202d1,  0xffff0471,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff02d4,  0xffffffff,  0x2d602d5,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff02d7,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2d902d8,  0x2db02da,  0x2dd02dc,  0x2df02de,  0x2e102e0,  0x2e302e2,  0x2e502e4,  0x2e702e6,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2e8ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2ea02e9,  0x2ec02eb,  0x2ee02ed,  0x2f002ef,  0x2f202f1,  0x2f402f3,  0x2f602f5,  0x2f802f7,  0x2fa02f9,  0x2fc02fb,  0x2fe02fd,  0x30002ff,  0x3020301,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3040303,  0x3060305,  0x3080307,  0x30a0309,  0x30c030b,  0x30e030d,  0x310030f,  0x3120311,  0x3140313,  0x3160315,  0x3180317,  0x31a0319,  0x31c031b,  0x31e031d,  0x320031f,  0x3220321,  0x3240323,  0x3260325,  0x3280327,  0x32a0329,  0x32c032b,  0x32e032d,  0x330032f,  0xffff0331,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0332,  0x3340333,  0xffff0335,  0x336ffff,  0x337ffff,  0x338ffff,  0x339ffff,  0x33b033a,  0xffff033c,  0xffff033d,  0x33effff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x340033f,  0xffff0341,  0xffff0342,  0xffff0343,  0xffff0344,  0xffff0345,  0xffff0346,  0xffff0347,  0xffff0348,  0xffff0349,  0xffff034a,  0xffff034b,  0xffff034c,  0xffff034d,  0xffff034e,  0xffff034f,  0xffff0350,  0xffff0351,  0xffff0352,  0xffff0353,  0xffff0354,  0xffff0355,  0xffff0356,  0xffff0357,  0xffff0358,  0xffff0359,  0xffff035a,  0xffff035b,  0xffff035c,  0xffff035d,  0xffff035e,  0xffff035f,  0xffff0360,  0xffff0361,  0xffff0362,  0xffff0363,  0xffff0364,  0xffff0365,  0xffff0366,  0xffff0367,  0xffff0368,  0xffff0369,  0xffff036a,  0xffff036b,  0xffff036c,  0xffff036d,  0xffff036e,  0xffff036f,  0xffff0370,  0xffff0371,  0xffff0372,  0xffffffff,  0xffffffff,  0xffffffff,  0x373ffff,  0x374ffff,  0xffffffff,  0xffffffff,  0xffff0375,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0376,  0xffff0377,  0xffff0378,  0xffff0379,  0xffff037a,  0xffff037b,  0xffff037c,  0xffff037d,  0xffff037e,  0xffff037f,  0xffff0380,  0xffff0381,  0xffff0382,  0xffff0383,  0xffff0384,  0xffff0385,  0xffff0386,  0xffff0387,  0xffff0388,  0xffff0389,  0xffff038a,  0xffff038b,  0xffff038c,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff038d,  0xffff038e,  0xffff038f,  0xffff0390,  0xffff0391,  0xffff0392,  0xffff0393,  0xffff0394,  0xffff0395,  0xffff0396,  0xffff0397,  0xffff0398,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0399,  0xffff039a,  0xffff039b,  0xffff039c,  0xffff039d,  0xffff039e,  0xffff039f,  0xffffffff,  0xffff03a0,  0xffff03a1,  0xffff03a2,  0xffff03a3,  0xffff03a4,  0xffff03a5,  0xffff03a6,  0xffff03a7,  0xffff03a8,  0xffff03a9,  0xffff03aa,  0xffff03ab,  0xffff03ac,  0xffff03ad,  0xffff03ae,  0xffff03af,  0xffff03b0,  0xffff03b1,  0xffff03b2,  0xffff03b3,  0xffff03b4,  0xffff03b5,  0xffff03b6,  0xffff03b7,  0xffff03b8,  0xffff03b9,  0xffff03ba,  0xffff03bb,  0xffff03bc,  0xffff03bd,  0xffff03be,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3bfffff,  0x3c0ffff,  0x3c1ffff,  0xffff03c2,  0xffff03c3,  0xffff03c4,  0xffff03c5,  0xffff03c6,  0xffffffff,  0x3c7ffff,  0x3c8ffff,  0xffffffff,  0xffff03c9,  0xffff03ca,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff03cb,  0xffff03cc,  0xffff03cd,  0xffff03ce,  0xffff03cf,  0xffff03d0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x4170416,  0x4190418,  0x41b041a,  0xffff041c,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x41effff,  0x420041f,  0x4220421,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3d1ffff,  0x3d303d2,  0x3d503d4,  0x3d703d6,  0x3d903d8,  0x3db03da,  0x3dd03dc,  0x3df03de,  0x3e103e0,  0x3e303e2,  0x3e503e4,  0x3e703e6,  0x3e903e8,  0xffff03ea,  0xffffffff,  0xffffffff,  0x3ec03eb,  0x3ee03ed,  0x3f003ef,  0x3f203f1,  0x3f403f3,  0x3f603f5,  0x3f803f7,  0x3fa03f9,  0x3fc03fb,  0x3fe03fd,  0x40003ff,  0x4020401,  0x4040403,  0x4060405,  0x4080407,  0x40a0409,  0x40c040b,  0x40e040d,  0x410040f,  0x4120411,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff]);
+//8192 bytes
+enum toTitleIndexTrieEntries = TrieEntry!(ushort, 8, 7, 6)([ 0x0,  0x40,  0x200], [ 0x100,  0x380,  0xc00], [ 0x2020100,  0x4020302,  0x2020205,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x10000,  0x30002,  0x50004,  0x70006,  0x90008,  0xa,  0xb0000,  0xd000c,  0xf000e,  0x110010,  0x130012,  0x14,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x150000,  0x0,  0x170016,  0x190018,  0x1b001a,  0x1d001c,  0x0,  0x0,  0x1e0000,  0x1f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x200000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x220021,  0x240023,  0x25,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x260000,  0x27,  0x290028,  0x2a,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2b,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2c0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2e002d,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff,  0x20001,  0x40003,  0x60005,  0x80007,  0xa0009,  0xc000b,  0xe000d,  0x10000f,  0x120011,  0x140013,  0x160015,  0x180017,  0xffff0019,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x1affff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x41fffff,  0x1c001b,  0x1e001d,  0x20001f,  0x220021,  0x240023,  0x260025,  0x280027,  0x2a0029,  0x2c002b,  0x2e002d,  0x30002f,  0xffff0031,  0x330032,  0x350034,  0x370036,  0x390038,  0x3affff,  0x3bffff,  0x3cffff,  0x3dffff,  0x3effff,  0x3fffff,  0x40ffff,  0x41ffff,  0x42ffff,  0x43ffff,  0x44ffff,  0x45ffff,  0x46ffff,  0x47ffff,  0x48ffff,  0x49ffff,  0x4affff,  0x4bffff,  0x4cffff,  0x4dffff,  0x4effff,  0x4fffff,  0x50ffff,  0x51ffff,  0x520421,  0x53ffff,  0x54ffff,  0x55ffff,  0xffffffff,  0xffff0056,  0xffff0057,  0xffff0058,  0xffff0059,  0xffff005a,  0xffff005b,  0xffff005c,  0x43e005d,  0x5effff,  0x5fffff,  0x60ffff,  0x61ffff,  0x62ffff,  0x63ffff,  0x64ffff,  0x65ffff,  0x66ffff,  0x67ffff,  0x68ffff,  0x69ffff,  0x6affff,  0x6bffff,  0x6cffff,  0x6dffff,  0x6effff,  0x6fffff,  0x70ffff,  0x71ffff,  0x72ffff,  0x73ffff,  0x74ffff,  0xffffffff,  0xffff0075,  0xffff0076,  0x780077,  0xffff0079,  0x7affff,  0x7bffff,  0xffffffff,  0xffff007c,  0xffffffff,  0xffff007d,  0xffffffff,  0xffffffff,  0xffff007e,  0x7fffff,  0xffffffff,  0x80ffff,  0xffff0081,  0xffffffff,  0xffff0082,  0x83ffff,  0x84ffff,  0x85ffff,  0xffffffff,  0xffff0086,  0xffffffff,  0x87ffff,  0xffffffff,  0xffff0088,  0xffffffff,  0xffff0089,  0xffff008a,  0x8bffff,  0xffffffff,  0x8cffff,  0x8dffff,  0xffffffff,  0xffffffff,  0x8f008e,  0x910090,  0x930092,  0x950094,  0xffff0096,  0xffff0097,  0xffff0098,  0xffff0099,  0xffff009a,  0xffff009b,  0xffff009c,  0xffff009d,  0x9f009e,  0xa0ffff,  0xa1ffff,  0xa2ffff,  0xa3ffff,  0xa4ffff,  0xa5ffff,  0xa6ffff,  0xa7ffff,  0xa8ffff,  0xa90446,  0xab00aa,  0xacffff,  0xffffffff,  0xadffff,  0xaeffff,  0xafffff,  0xb0ffff,  0xb1ffff,  0xb2ffff,  0xb3ffff,  0xb4ffff,  0xb5ffff,  0xb6ffff,  0xb7ffff,  0xb8ffff,  0xb9ffff,  0xbaffff,  0xbbffff,  0xbcffff,  0xbdffff,  0xbeffff,  0xbfffff,  0xc0ffff,  0xffffffff,  0xc1ffff,  0xc2ffff,  0xc3ffff,  0xc4ffff,  0xc5ffff,  0xc6ffff,  0xc7ffff,  0xc8ffff,  0xc9ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff00ca,  0xcbffff,  0xffff00cc,  0xffff00cd,  0xffffffff,  0xceffff,  0xcfffff,  0xd0ffff,  0xd1ffff,  0xd2ffff,  0xd400d3,  0xd600d5,  0xffff00d7,  0xd900d8,  0xdaffff,  0xdbffff,  0xffffffff,  0xffffffff,  0xffff00dc,  0xddffff,  0xdeffff,  0xffff00df,  0xe100e0,  0xe2ffff,  0xffffffff,  0xe3ffff,  0xe4ffff,  0xffff00e5,  0xe6ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xe7ffff,  0xffffffff,  0xffff00e8,  0xe9ffff,  0xffffffff,  0xffffffff,  0xeb00ea,  0xed00ec,  0xffff00ee,  0xffffffff,  0xffffffff,  0xffff00ef,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xf0ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xf1ffff,  0xf2ffff,  0xffffffff,  0xf3ffff,  0xffffffff,  0xf4ffff,  0xf600f5,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff0440,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xf800f7,  0xfa00f9,  0xfb0443,  0xfd00fc,  0xff00fe,  0x1010100,  0x1030102,  0x1050104,  0x1070106,  0x1090108,  0x10b010a,  0x10d010c,  0x10f010e,  0x1110110,  0x1130112,  0x1150114,  0x1170116,  0xffff0118,  0x11a0119,  0xffffffff,  0x11bffff,  0x11d011c,  0x11effff,  0x11fffff,  0x120ffff,  0x121ffff,  0x122ffff,  0x123ffff,  0x124ffff,  0x125ffff,  0x126ffff,  0x127ffff,  0x128ffff,  0x129ffff,  0x12b012a,  0xffff012c,  0x12dffff,  0xffffffff,  0xffff012e,  0x12fffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x1310130,  0x1330132,  0x1350134,  0x1370136,  0x1390138,  0x13b013a,  0x13d013c,  0x13f013e,  0x1410140,  0x1430142,  0x1450144,  0x1470146,  0x1490148,  0x14b014a,  0x14d014c,  0x14f014e,  0x1510150,  0x1530152,  0x1550154,  0x1570156,  0x1590158,  0x15b015a,  0x15d015c,  0x15f015e,  0x160ffff,  0x161ffff,  0x162ffff,  0x163ffff,  0x164ffff,  0x165ffff,  0x166ffff,  0x167ffff,  0x168ffff,  0x169ffff,  0x16affff,  0x16bffff,  0x16cffff,  0x16dffff,  0x16effff,  0x16fffff,  0x170ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x171ffff,  0x172ffff,  0x173ffff,  0x174ffff,  0x175ffff,  0x176ffff,  0x177ffff,  0x178ffff,  0x179ffff,  0x17affff,  0x17bffff,  0x17cffff,  0x17dffff,  0x17effff,  0x17fffff,  0x180ffff,  0x181ffff,  0x182ffff,  0x183ffff,  0x184ffff,  0x185ffff,  0x186ffff,  0x187ffff,  0x188ffff,  0x189ffff,  0x18affff,  0x18bffff,  0xffffffff,  0xffff018c,  0xffff018d,  0xffff018e,  0xffff018f,  0xffff0190,  0xffff0191,  0x1930192,  0x194ffff,  0x195ffff,  0x196ffff,  0x197ffff,  0x198ffff,  0x199ffff,  0x19affff,  0x19bffff,  0x19cffff,  0x19dffff,  0x19effff,  0x19fffff,  0x1a0ffff,  0x1a1ffff,  0x1a2ffff,  0x1a3ffff,  0x1a4ffff,  0x1a5ffff,  0x1a6ffff,  0x1a7ffff,  0x1a8ffff,  0x1a9ffff,  0x1aaffff,  0x1abffff,  0x1acffff,  0x1adffff,  0x1aeffff,  0x1afffff,  0x1b0ffff,  0x1b1ffff,  0x1b2ffff,  0x1b3ffff,  0x1b4ffff,  0x1b5ffff,  0x1b6ffff,  0x1b7ffff,  0x1b8ffff,  0x1b9ffff,  0x1baffff,  0x1bbffff,  0x1bcffff,  0x1bdffff,  0x1beffff,  0x1bfffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x1c0ffff,  0x1c201c1,  0x1c401c3,  0x1c601c5,  0x1c801c7,  0x1ca01c9,  0x1cc01cb,  0x1ce01cd,  0x1d001cf,  0x1d201d1,  0x1d401d3,  0x1d601d5,  0x1d801d7,  0x1da01d9,  0x1dc01db,  0x1de01dd,  0x1e001df,  0x1e201e1,  0x1e401e3,  0x43201e5,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x1e6ffff,  0xffffffff,  0x1e7ffff,  0xffffffff,  0x1e8ffff,  0x1e9ffff,  0x1eaffff,  0x1ebffff,  0x1ecffff,  0x1edffff,  0x1eeffff,  0x1efffff,  0x1f0ffff,  0x1f1ffff,  0x1f2ffff,  0x1f3ffff,  0x1f4ffff,  0x1f5ffff,  0x1f6ffff,  0x1f7ffff,  0x1f8ffff,  0x1f9ffff,  0x1faffff,  0x1fbffff,  0x1fcffff,  0x1fdffff,  0x1feffff,  0x1ffffff,  0x200ffff,  0x201ffff,  0x202ffff,  0x203ffff,  0x204ffff,  0x205ffff,  0x206ffff,  0x207ffff,  0x208ffff,  0x209ffff,  0x20affff,  0x20bffff,  0x20cffff,  0x20dffff,  0x20effff,  0x20fffff,  0x210ffff,  0x211ffff,  0x212ffff,  0x213ffff,  0x214ffff,  0x215ffff,  0x216ffff,  0x217ffff,  0x218ffff,  0x219ffff,  0x21affff,  0x21bffff,  0x21cffff,  0x21dffff,  0x21effff,  0x21fffff,  0x220ffff,  0x221ffff,  0x222ffff,  0x223ffff,  0x224ffff,  0x225ffff,  0x226ffff,  0x227ffff,  0x228ffff,  0x229ffff,  0x22affff,  0x22bffff,  0x22cffff,  0x22dffff,  0x22effff,  0x22fffff,  0x230ffff,  0x231ffff,  0x232ffff,  0x44a0448,  0x44e044c,  0x2330450,  0xffffffff,  0xffffffff,  0x234ffff,  0x235ffff,  0x236ffff,  0x237ffff,  0x238ffff,  0x239ffff,  0x23affff,  0x23bffff,  0x23cffff,  0x23dffff,  0x23effff,  0x23fffff,  0x240ffff,  0x241ffff,  0x242ffff,  0x243ffff,  0x244ffff,  0x245ffff,  0x246ffff,  0x247ffff,  0x248ffff,  0x249ffff,  0x24affff,  0x24bffff,  0x24cffff,  0x24dffff,  0x24effff,  0x24fffff,  0x250ffff,  0x251ffff,  0x252ffff,  0x253ffff,  0x254ffff,  0x255ffff,  0x256ffff,  0x257ffff,  0x258ffff,  0x259ffff,  0x25affff,  0x25bffff,  0x25cffff,  0x25dffff,  0x25effff,  0x25fffff,  0x260ffff,  0x261ffff,  0x262ffff,  0x263ffff,  0x2650264,  0x2670266,  0x2690268,  0x26b026a,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x26d026c,  0x26f026e,  0x2710270,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2730272,  0x2750274,  0x2770276,  0x2790278,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x27b027a,  0x27d027c,  0x27f027e,  0x2810280,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2830282,  0x2850284,  0x2870286,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2880452,  0x2890454,  0x28a0457,  0x28b045a,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x28d028c,  0x28f028e,  0x2910290,  0x2930292,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2950294,  0x2970296,  0x2990298,  0x29b029a,  0x29d029c,  0x29f029e,  0x2a102a0,  0xffffffff,  0x47c047b,  0x47e047d,  0x480047f,  0x4820481,  0x4840483,  0x4860485,  0x4880487,  0x48a0489,  0x48c048b,  0x48e048d,  0x490048f,  0x4920491,  0x4940493,  0x4960495,  0x4980497,  0x49a0499,  0x49c049b,  0x49e049d,  0x4a0049f,  0x4a204a1,  0x4a404a3,  0x4a604a5,  0x4a804a7,  0x4aa04a9,  0x2bb02ba,  0x4ab04b1,  0xffff04b3,  0x4bd045d,  0xffffffff,  0xffffffff,  0xffff04ac,  0xffff02bd,  0xffffffff,  0x4ad04b5,  0xffff04b7,  0x4c0045f,  0xffffffff,  0xffffffff,  0xffff04ae,  0xffffffff,  0x2c002bf,  0x4640461,  0xffffffff,  0x4690467,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2c202c1,  0x46f046c,  0x2c30472,  0x4760474,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x4af04b9,  0xffff04bb,  0x4c30479,  0xffffffff,  0xffffffff,  0xffff04b0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff02c5,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2c702c6,  0x2c902c8,  0x2cb02ca,  0x2cd02cc,  0x2cf02ce,  0x2d102d0,  0x2d302d2,  0x2d502d4,  0xffffffff,  0xffffffff,  0xffff02d6,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2d802d7,  0x2da02d9,  0x2dc02db,  0x2de02dd,  0x2e002df,  0x2e202e1,  0x2e402e3,  0x2e602e5,  0x2e802e7,  0x2ea02e9,  0x2ec02eb,  0x2ee02ed,  0x2f002ef,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x2f202f1,  0x2f402f3,  0x2f602f5,  0x2f802f7,  0x2fa02f9,  0x2fc02fb,  0x2fe02fd,  0x30002ff,  0x3020301,  0x3040303,  0x3060305,  0x3080307,  0x30a0309,  0x30c030b,  0x30e030d,  0x310030f,  0x3120311,  0x3140313,  0x3160315,  0x3180317,  0x31a0319,  0x31c031b,  0x31e031d,  0xffff031f,  0x320ffff,  0xffffffff,  0x321ffff,  0xffff0322,  0xffff0323,  0xffff0324,  0xffff0325,  0xffffffff,  0xffffffff,  0x326ffff,  0xffffffff,  0xffff0327,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x328ffff,  0x329ffff,  0x32affff,  0x32bffff,  0x32cffff,  0x32dffff,  0x32effff,  0x32fffff,  0x330ffff,  0x331ffff,  0x332ffff,  0x333ffff,  0x334ffff,  0x335ffff,  0x336ffff,  0x337ffff,  0x338ffff,  0x339ffff,  0x33affff,  0x33bffff,  0x33cffff,  0x33dffff,  0x33effff,  0x33fffff,  0x340ffff,  0x341ffff,  0x342ffff,  0x343ffff,  0x344ffff,  0x345ffff,  0x346ffff,  0x347ffff,  0x348ffff,  0x349ffff,  0x34affff,  0x34bffff,  0x34cffff,  0x34dffff,  0x34effff,  0x34fffff,  0x350ffff,  0x351ffff,  0x352ffff,  0x353ffff,  0x354ffff,  0x355ffff,  0x356ffff,  0x357ffff,  0x358ffff,  0x359ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff035a,  0xffff035b,  0xffffffff,  0x35cffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x35e035d,  0x360035f,  0x3620361,  0x3640363,  0x3660365,  0x3680367,  0x36a0369,  0x36c036b,  0x36e036d,  0x370036f,  0x3720371,  0x3740373,  0x3760375,  0x3780377,  0x37a0379,  0x37c037b,  0x37e037d,  0x380037f,  0x3820381,  0x383ffff,  0xffffffff,  0xffffffff,  0x384ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x385ffff,  0x386ffff,  0x387ffff,  0x388ffff,  0x389ffff,  0x38affff,  0x38bffff,  0x38cffff,  0x38dffff,  0x38effff,  0x38fffff,  0x390ffff,  0x391ffff,  0x392ffff,  0x393ffff,  0x394ffff,  0x395ffff,  0x396ffff,  0x397ffff,  0x398ffff,  0x399ffff,  0x39affff,  0x39bffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x39cffff,  0x39dffff,  0x39effff,  0x39fffff,  0x3a0ffff,  0x3a1ffff,  0x3a2ffff,  0x3a3ffff,  0x3a4ffff,  0x3a5ffff,  0x3a6ffff,  0x3a7ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3a8ffff,  0x3a9ffff,  0x3aaffff,  0x3abffff,  0x3acffff,  0x3adffff,  0x3aeffff,  0xffffffff,  0x3afffff,  0x3b0ffff,  0x3b1ffff,  0x3b2ffff,  0x3b3ffff,  0x3b4ffff,  0x3b5ffff,  0x3b6ffff,  0x3b7ffff,  0x3b8ffff,  0x3b9ffff,  0x3baffff,  0x3bbffff,  0x3bcffff,  0x3bdffff,  0x3beffff,  0x3bfffff,  0x3c0ffff,  0x3c1ffff,  0x3c2ffff,  0x3c3ffff,  0x3c4ffff,  0x3c5ffff,  0x3c6ffff,  0x3c7ffff,  0x3c8ffff,  0x3c9ffff,  0x3caffff,  0x3cbffff,  0x3ccffff,  0x3cdffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff03ce,  0xffff03cf,  0x3d0ffff,  0x3d1ffff,  0x3d2ffff,  0x3d3ffff,  0x3d4ffff,  0xffffffff,  0xffffffff,  0xffff03d5,  0xffffffff,  0x3d6ffff,  0x3d7ffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3d8ffff,  0x3d9ffff,  0x3daffff,  0x3dbffff,  0x3dcffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x4240422,  0x4280426,  0x42e042b,  0xffff0430,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x434ffff,  0x4380436,  0x43c043a,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3ddffff,  0x3df03de,  0x3e103e0,  0x3e303e2,  0x3e503e4,  0x3e703e6,  0x3e903e8,  0x3eb03ea,  0x3ed03ec,  0x3ef03ee,  0x3f103f0,  0x3f303f2,  0x3f503f4,  0xffff03f6,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3f803f7,  0x3fa03f9,  0x3fc03fb,  0x3fe03fd,  0x40003ff,  0x4020401,  0x4040403,  0x4060405,  0x4080407,  0x40a0409,  0x40c040b,  0x40e040d,  0x410040f,  0x4120411,  0x4140413,  0x4160415,  0x4180417,  0x41a0419,  0x41c041b,  0x41e041d,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff]);
+@property
+{
+private alias _IUA = immutable(uint[]);
+_IUA toUpperTable() { static _IUA t = [ 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,  0x39c,  0xc0,  0xc1,  0xc2,  0xc3,  0xc4,  0xc5,  0xc6,  0xc7,  0xc8,  0xc9,  0xca,  0xcb,  0xcc,  0xcd,  0xce,  0xcf,  0xd0,  0xd1,  0xd2,  0xd3,  0xd4,  0xd5,  0xd6,  0xd8,  0xd9,  0xda,  0xdb,  0xdc,  0xdd,  0xde,  0x178,  0x100,  0x102,  0x104,  0x106,  0x108,  0x10a,  0x10c,  0x10e,  0x110,  0x112,  0x114,  0x116,  0x118,  0x11a,  0x11c,  0x11e,  0x120,  0x122,  0x124,  0x126,  0x128,  0x12a,  0x12c,  0x12e,  0x49,  0x132,  0x134,  0x136,  0x139,  0x13b,  0x13d,  0x13f,  0x141,  0x143,  0x145,  0x147,  0x14a,  0x14c,  0x14e,  0x150,  0x152,  0x154,  0x156,  0x158,  0x15a,  0x15c,  0x15e,  0x160,  0x162,  0x164,  0x166,  0x168,  0x16a,  0x16c,  0x16e,  0x170,  0x172,  0x174,  0x176,  0x179,  0x17b,  0x17d,  0x53,  0x243,  0x182,  0x184,  0x187,  0x18b,  0x191,  0x1f6,  0x198,  0x23d,  0x220,  0x1a0,  0x1a2,  0x1a4,  0x1a7,  0x1ac,  0x1af,  0x1b3,  0x1b5,  0x1b8,  0x1bc,  0x1f7,  0x1c4,  0x1c4,  0x1c7,  0x1c7,  0x1ca,  0x1ca,  0x1cd,  0x1cf,  0x1d1,  0x1d3,  0x1d5,  0x1d7,  0x1d9,  0x1db,  0x18e,  0x1de,  0x1e0,  0x1e2,  0x1e4,  0x1e6,  0x1e8,  0x1ea,  0x1ec,  0x1ee,  0x1f1,  0x1f1,  0x1f4,  0x1f8,  0x1fa,  0x1fc,  0x1fe,  0x200,  0x202,  0x204,  0x206,  0x208,  0x20a,  0x20c,  0x20e,  0x210,  0x212,  0x214,  0x216,  0x218,  0x21a,  0x21c,  0x21e,  0x222,  0x224,  0x226,  0x228,  0x22a,  0x22c,  0x22e,  0x230,  0x232,  0x23b,  0x2c7e,  0x2c7f,  0x241,  0x246,  0x248,  0x24a,  0x24c,  0x24e,  0x2c6f,  0x2c6d,  0x2c70,  0x181,  0x186,  0x189,  0x18a,  0x18f,  0x190,  0x193,  0x194,  0xa78d,  0xa7aa,  0x197,  0x196,  0x2c62,  0x19c,  0x2c6e,  0x19d,  0x19f,  0x2c64,  0x1a6,  0x1a9,  0x1ae,  0x244,  0x1b1,  0x1b2,  0x245,  0x1b7,  0x399,  0x370,  0x372,  0x376,  0x3fd,  0x3fe,  0x3ff,  0x386,  0x388,  0x389,  0x38a,  0x391,  0x392,  0x393,  0x394,  0x395,  0x396,  0x397,  0x398,  0x399,  0x39a,  0x39b,  0x39c,  0x39d,  0x39e,  0x39f,  0x3a0,  0x3a1,  0x3a3,  0x3a3,  0x3a4,  0x3a5,  0x3a6,  0x3a7,  0x3a8,  0x3a9,  0x3aa,  0x3ab,  0x38c,  0x38e,  0x38f,  0x392,  0x398,  0x3a6,  0x3a0,  0x3cf,  0x3d8,  0x3da,  0x3dc,  0x3de,  0x3e0,  0x3e2,  0x3e4,  0x3e6,  0x3e8,  0x3ea,  0x3ec,  0x3ee,  0x39a,  0x3a1,  0x3f9,  0x395,  0x3f7,  0x3fa,  0x410,  0x411,  0x412,  0x413,  0x414,  0x415,  0x416,  0x417,  0x418,  0x419,  0x41a,  0x41b,  0x41c,  0x41d,  0x41e,  0x41f,  0x420,  0x421,  0x422,  0x423,  0x424,  0x425,  0x426,  0x427,  0x428,  0x429,  0x42a,  0x42b,  0x42c,  0x42d,  0x42e,  0x42f,  0x400,  0x401,  0x402,  0x403,  0x404,  0x405,  0x406,  0x407,  0x408,  0x409,  0x40a,  0x40b,  0x40c,  0x40d,  0x40e,  0x40f,  0x460,  0x462,  0x464,  0x466,  0x468,  0x46a,  0x46c,  0x46e,  0x470,  0x472,  0x474,  0x476,  0x478,  0x47a,  0x47c,  0x47e,  0x480,  0x48a,  0x48c,  0x48e,  0x490,  0x492,  0x494,  0x496,  0x498,  0x49a,  0x49c,  0x49e,  0x4a0,  0x4a2,  0x4a4,  0x4a6,  0x4a8,  0x4aa,  0x4ac,  0x4ae,  0x4b0,  0x4b2,  0x4b4,  0x4b6,  0x4b8,  0x4ba,  0x4bc,  0x4be,  0x4c1,  0x4c3,  0x4c5,  0x4c7,  0x4c9,  0x4cb,  0x4cd,  0x4c0,  0x4d0,  0x4d2,  0x4d4,  0x4d6,  0x4d8,  0x4da,  0x4dc,  0x4de,  0x4e0,  0x4e2,  0x4e4,  0x4e6,  0x4e8,  0x4ea,  0x4ec,  0x4ee,  0x4f0,  0x4f2,  0x4f4,  0x4f6,  0x4f8,  0x4fa,  0x4fc,  0x4fe,  0x500,  0x502,  0x504,  0x506,  0x508,  0x50a,  0x50c,  0x50e,  0x510,  0x512,  0x514,  0x516,  0x518,  0x51a,  0x51c,  0x51e,  0x520,  0x522,  0x524,  0x526,  0x531,  0x532,  0x533,  0x534,  0x535,  0x536,  0x537,  0x538,  0x539,  0x53a,  0x53b,  0x53c,  0x53d,  0x53e,  0x53f,  0x540,  0x541,  0x542,  0x543,  0x544,  0x545,  0x546,  0x547,  0x548,  0x549,  0x54a,  0x54b,  0x54c,  0x54d,  0x54e,  0x54f,  0x550,  0x551,  0x552,  0x553,  0x554,  0x555,  0x556,  0xa77d,  0x2c63,  0x1e00,  0x1e02,  0x1e04,  0x1e06,  0x1e08,  0x1e0a,  0x1e0c,  0x1e0e,  0x1e10,  0x1e12,  0x1e14,  0x1e16,  0x1e18,  0x1e1a,  0x1e1c,  0x1e1e,  0x1e20,  0x1e22,  0x1e24,  0x1e26,  0x1e28,  0x1e2a,  0x1e2c,  0x1e2e,  0x1e30,  0x1e32,  0x1e34,  0x1e36,  0x1e38,  0x1e3a,  0x1e3c,  0x1e3e,  0x1e40,  0x1e42,  0x1e44,  0x1e46,  0x1e48,  0x1e4a,  0x1e4c,  0x1e4e,  0x1e50,  0x1e52,  0x1e54,  0x1e56,  0x1e58,  0x1e5a,  0x1e5c,  0x1e5e,  0x1e60,  0x1e62,  0x1e64,  0x1e66,  0x1e68,  0x1e6a,  0x1e6c,  0x1e6e,  0x1e70,  0x1e72,  0x1e74,  0x1e76,  0x1e78,  0x1e7a,  0x1e7c,  0x1e7e,  0x1e80,  0x1e82,  0x1e84,  0x1e86,  0x1e88,  0x1e8a,  0x1e8c,  0x1e8e,  0x1e90,  0x1e92,  0x1e94,  0x1e60,  0x1ea0,  0x1ea2,  0x1ea4,  0x1ea6,  0x1ea8,  0x1eaa,  0x1eac,  0x1eae,  0x1eb0,  0x1eb2,  0x1eb4,  0x1eb6,  0x1eb8,  0x1eba,  0x1ebc,  0x1ebe,  0x1ec0,  0x1ec2,  0x1ec4,  0x1ec6,  0x1ec8,  0x1eca,  0x1ecc,  0x1ece,  0x1ed0,  0x1ed2,  0x1ed4,  0x1ed6,  0x1ed8,  0x1eda,  0x1edc,  0x1ede,  0x1ee0,  0x1ee2,  0x1ee4,  0x1ee6,  0x1ee8,  0x1eea,  0x1eec,  0x1eee,  0x1ef0,  0x1ef2,  0x1ef4,  0x1ef6,  0x1ef8,  0x1efa,  0x1efc,  0x1efe,  0x1f08,  0x1f09,  0x1f0a,  0x1f0b,  0x1f0c,  0x1f0d,  0x1f0e,  0x1f0f,  0x1f18,  0x1f19,  0x1f1a,  0x1f1b,  0x1f1c,  0x1f1d,  0x1f28,  0x1f29,  0x1f2a,  0x1f2b,  0x1f2c,  0x1f2d,  0x1f2e,  0x1f2f,  0x1f38,  0x1f39,  0x1f3a,  0x1f3b,  0x1f3c,  0x1f3d,  0x1f3e,  0x1f3f,  0x1f48,  0x1f49,  0x1f4a,  0x1f4b,  0x1f4c,  0x1f4d,  0x1f59,  0x1f5b,  0x1f5d,  0x1f5f,  0x1f68,  0x1f69,  0x1f6a,  0x1f6b,  0x1f6c,  0x1f6d,  0x1f6e,  0x1f6f,  0x1fba,  0x1fbb,  0x1fc8,  0x1fc9,  0x1fca,  0x1fcb,  0x1fda,  0x1fdb,  0x1ff8,  0x1ff9,  0x1fea,  0x1feb,  0x1ffa,  0x1ffb,  0x1f88,  0x1f89,  0x1f8a,  0x1f8b,  0x1f8c,  0x1f8d,  0x1f8e,  0x1f8f,  0x1f98,  0x1f99,  0x1f9a,  0x1f9b,  0x1f9c,  0x1f9d,  0x1f9e,  0x1f9f,  0x1fa8,  0x1fa9,  0x1faa,  0x1fab,  0x1fac,  0x1fad,  0x1fae,  0x1faf,  0x1fb8,  0x1fb9,  0x1fbc,  0x399,  0x1fcc,  0x1fd8,  0x1fd9,  0x1fe8,  0x1fe9,  0x1fec,  0x1ffc,  0x2132,  0x2160,  0x2161,  0x2162,  0x2163,  0x2164,  0x2165,  0x2166,  0x2167,  0x2168,  0x2169,  0x216a,  0x216b,  0x216c,  0x216d,  0x216e,  0x216f,  0x2183,  0x24b6,  0x24b7,  0x24b8,  0x24b9,  0x24ba,  0x24bb,  0x24bc,  0x24bd,  0x24be,  0x24bf,  0x24c0,  0x24c1,  0x24c2,  0x24c3,  0x24c4,  0x24c5,  0x24c6,  0x24c7,  0x24c8,  0x24c9,  0x24ca,  0x24cb,  0x24cc,  0x24cd,  0x24ce,  0x24cf,  0x2c00,  0x2c01,  0x2c02,  0x2c03,  0x2c04,  0x2c05,  0x2c06,  0x2c07,  0x2c08,  0x2c09,  0x2c0a,  0x2c0b,  0x2c0c,  0x2c0d,  0x2c0e,  0x2c0f,  0x2c10,  0x2c11,  0x2c12,  0x2c13,  0x2c14,  0x2c15,  0x2c16,  0x2c17,  0x2c18,  0x2c19,  0x2c1a,  0x2c1b,  0x2c1c,  0x2c1d,  0x2c1e,  0x2c1f,  0x2c20,  0x2c21,  0x2c22,  0x2c23,  0x2c24,  0x2c25,  0x2c26,  0x2c27,  0x2c28,  0x2c29,  0x2c2a,  0x2c2b,  0x2c2c,  0x2c2d,  0x2c2e,  0x2c60,  0x23a,  0x23e,  0x2c67,  0x2c69,  0x2c6b,  0x2c72,  0x2c75,  0x2c80,  0x2c82,  0x2c84,  0x2c86,  0x2c88,  0x2c8a,  0x2c8c,  0x2c8e,  0x2c90,  0x2c92,  0x2c94,  0x2c96,  0x2c98,  0x2c9a,  0x2c9c,  0x2c9e,  0x2ca0,  0x2ca2,  0x2ca4,  0x2ca6,  0x2ca8,  0x2caa,  0x2cac,  0x2cae,  0x2cb0,  0x2cb2,  0x2cb4,  0x2cb6,  0x2cb8,  0x2cba,  0x2cbc,  0x2cbe,  0x2cc0,  0x2cc2,  0x2cc4,  0x2cc6,  0x2cc8,  0x2cca,  0x2ccc,  0x2cce,  0x2cd0,  0x2cd2,  0x2cd4,  0x2cd6,  0x2cd8,  0x2cda,  0x2cdc,  0x2cde,  0x2ce0,  0x2ce2,  0x2ceb,  0x2ced,  0x2cf2,  0x10a0,  0x10a1,  0x10a2,  0x10a3,  0x10a4,  0x10a5,  0x10a6,  0x10a7,  0x10a8,  0x10a9,  0x10aa,  0x10ab,  0x10ac,  0x10ad,  0x10ae,  0x10af,  0x10b0,  0x10b1,  0x10b2,  0x10b3,  0x10b4,  0x10b5,  0x10b6,  0x10b7,  0x10b8,  0x10b9,  0x10ba,  0x10bb,  0x10bc,  0x10bd,  0x10be,  0x10bf,  0x10c0,  0x10c1,  0x10c2,  0x10c3,  0x10c4,  0x10c5,  0x10c7,  0x10cd,  0xa640,  0xa642,  0xa644,  0xa646,  0xa648,  0xa64a,  0xa64c,  0xa64e,  0xa650,  0xa652,  0xa654,  0xa656,  0xa658,  0xa65a,  0xa65c,  0xa65e,  0xa660,  0xa662,  0xa664,  0xa666,  0xa668,  0xa66a,  0xa66c,  0xa680,  0xa682,  0xa684,  0xa686,  0xa688,  0xa68a,  0xa68c,  0xa68e,  0xa690,  0xa692,  0xa694,  0xa696,  0xa722,  0xa724,  0xa726,  0xa728,  0xa72a,  0xa72c,  0xa72e,  0xa732,  0xa734,  0xa736,  0xa738,  0xa73a,  0xa73c,  0xa73e,  0xa740,  0xa742,  0xa744,  0xa746,  0xa748,  0xa74a,  0xa74c,  0xa74e,  0xa750,  0xa752,  0xa754,  0xa756,  0xa758,  0xa75a,  0xa75c,  0xa75e,  0xa760,  0xa762,  0xa764,  0xa766,  0xa768,  0xa76a,  0xa76c,  0xa76e,  0xa779,  0xa77b,  0xa77e,  0xa780,  0xa782,  0xa784,  0xa786,  0xa78b,  0xa790,  0xa792,  0xa7a0,  0xa7a2,  0xa7a4,  0xa7a6,  0xa7a8,  0xff21,  0xff22,  0xff23,  0xff24,  0xff25,  0xff26,  0xff27,  0xff28,  0xff29,  0xff2a,  0xff2b,  0xff2c,  0xff2d,  0xff2e,  0xff2f,  0xff30,  0xff31,  0xff32,  0xff33,  0xff34,  0xff35,  0xff36,  0xff37,  0xff38,  0xff39,  0xff3a,  0x10400,  0x10401,  0x10402,  0x10403,  0x10404,  0x10405,  0x10406,  0x10407,  0x10408,  0x10409,  0x1040a,  0x1040b,  0x1040c,  0x1040d,  0x1040e,  0x1040f,  0x10410,  0x10411,  0x10412,  0x10413,  0x10414,  0x10415,  0x10416,  0x10417,  0x10418,  0x10419,  0x1041a,  0x1041b,  0x1041c,  0x1041d,  0x1041e,  0x1041f,  0x10420,  0x10421,  0x10422,  0x10423,  0x10424,  0x10425,  0x10426,  0x10427,  0x2000053,  0x53,  0x130,  0x2000046,  0x46,  0x2000046,  0x49,  0x2000046,  0x4c,  0x3000046,  0x46,  0x49,  0x3000046,  0x46,  0x4c,  0x2000053,  0x54,  0x2000053,  0x54,  0x2000535,  0x552,  0x2000544,  0x546,  0x2000544,  0x535,  0x2000544,  0x53b,  0x200054e,  0x546,  0x2000544,  0x53d,  0x20002bc,  0x4e,  0x3000399,  0x308,  0x301,  0x30003a5,  0x308,  0x301,  0x200004a,  0x30c,  0x2000048,  0x331,  0x2000054,  0x308,  0x2000057,  0x30a,  0x2000059,  0x30a,  0x2000041,  0x2be,  0x20003a5,  0x313,  0x30003a5,  0x313,  0x300,  0x30003a5,  0x313,  0x301,  0x30003a5,  0x313,  0x342,  0x2000391,  0x342,  0x2000397,  0x342,  0x3000399,  0x308,  0x300,  0x3000399,  0x308,  0x301,  0x2000399,  0x342,  0x3000399,  0x308,  0x342,  0x30003a5,  0x308,  0x300,  0x30003a5,  0x308,  0x301,  0x20003a1,  0x313,  0x20003a5,  0x342,  0x30003a5,  0x308,  0x342,  0x20003a9,  0x342,  0x2001f08,  0x399,  0x2001f09,  0x399,  0x2001f0a,  0x399,  0x2001f0b,  0x399,  0x2001f0c,  0x399,  0x2001f0d,  0x399,  0x2001f0e,  0x399,  0x2001f0f,  0x399,  0x2001f08,  0x399,  0x2001f09,  0x399,  0x2001f0a,  0x399,  0x2001f0b,  0x399,  0x2001f0c,  0x399,  0x2001f0d,  0x399,  0x2001f0e,  0x399,  0x2001f0f,  0x399,  0x2001f28,  0x399,  0x2001f29,  0x399,  0x2001f2a,  0x399,  0x2001f2b,  0x399,  0x2001f2c,  0x399,  0x2001f2d,  0x399,  0x2001f2e,  0x399,  0x2001f2f,  0x399,  0x2001f28,  0x399,  0x2001f29,  0x399,  0x2001f2a,  0x399,  0x2001f2b,  0x399,  0x2001f2c,  0x399,  0x2001f2d,  0x399,  0x2001f2e,  0x399,  0x2001f2f,  0x399,  0x2001f68,  0x399,  0x2001f69,  0x399,  0x2001f6a,  0x399,  0x2001f6b,  0x399,  0x2001f6c,  0x399,  0x2001f6d,  0x399,  0x2001f6e,  0x399,  0x2001f6f,  0x399,  0x2001f68,  0x399,  0x2001f69,  0x399,  0x2001f6a,  0x399,  0x2001f6b,  0x399,  0x2001f6c,  0x399,  0x2001f6d,  0x399,  0x2001f6e,  0x399,  0x2001f6f,  0x399,  0x2000391,  0x399,  0x2000391,  0x399,  0x2000397,  0x399,  0x2000397,  0x399,  0x20003a9,  0x399,  0x20003a9,  0x399,  0x2001fba,  0x399,  0x2000386,  0x399,  0x2001fca,  0x399,  0x2000389,  0x399,  0x2001ffa,  0x399,  0x200038f,  0x399,  0x3000391,  0x342,  0x399,  0x3000397,  0x342,  0x399,  0x30003a9,  0x342,  0x399]; return t; }
+_IUA toLowerTable() { static _IUA t = [ 0x61,  0x62,  0x63,  0x64,  0x65,  0x66,  0x67,  0x68,  0x69,  0x6a,  0x6b,  0x6c,  0x6d,  0x6e,  0x6f,  0x70,  0x71,  0x72,  0x73,  0x74,  0x75,  0x76,  0x77,  0x78,  0x79,  0x7a,  0xe0,  0xe1,  0xe2,  0xe3,  0xe4,  0xe5,  0xe6,  0xe7,  0xe8,  0xe9,  0xea,  0xeb,  0xec,  0xed,  0xee,  0xef,  0xf0,  0xf1,  0xf2,  0xf3,  0xf4,  0xf5,  0xf6,  0xf8,  0xf9,  0xfa,  0xfb,  0xfc,  0xfd,  0xfe,  0x101,  0x103,  0x105,  0x107,  0x109,  0x10b,  0x10d,  0x10f,  0x111,  0x113,  0x115,  0x117,  0x119,  0x11b,  0x11d,  0x11f,  0x121,  0x123,  0x125,  0x127,  0x129,  0x12b,  0x12d,  0x12f,  0x69,  0x133,  0x135,  0x137,  0x13a,  0x13c,  0x13e,  0x140,  0x142,  0x144,  0x146,  0x148,  0x14b,  0x14d,  0x14f,  0x151,  0x153,  0x155,  0x157,  0x159,  0x15b,  0x15d,  0x15f,  0x161,  0x163,  0x165,  0x167,  0x169,  0x16b,  0x16d,  0x16f,  0x171,  0x173,  0x175,  0x177,  0xff,  0x17a,  0x17c,  0x17e,  0x253,  0x183,  0x185,  0x254,  0x188,  0x256,  0x257,  0x18c,  0x1dd,  0x259,  0x25b,  0x192,  0x260,  0x263,  0x269,  0x268,  0x199,  0x26f,  0x272,  0x275,  0x1a1,  0x1a3,  0x1a5,  0x280,  0x1a8,  0x283,  0x1ad,  0x288,  0x1b0,  0x28a,  0x28b,  0x1b4,  0x1b6,  0x292,  0x1b9,  0x1bd,  0x1c6,  0x1c6,  0x1c9,  0x1c9,  0x1cc,  0x1cc,  0x1ce,  0x1d0,  0x1d2,  0x1d4,  0x1d6,  0x1d8,  0x1da,  0x1dc,  0x1df,  0x1e1,  0x1e3,  0x1e5,  0x1e7,  0x1e9,  0x1eb,  0x1ed,  0x1ef,  0x1f3,  0x1f3,  0x1f5,  0x195,  0x1bf,  0x1f9,  0x1fb,  0x1fd,  0x1ff,  0x201,  0x203,  0x205,  0x207,  0x209,  0x20b,  0x20d,  0x20f,  0x211,  0x213,  0x215,  0x217,  0x219,  0x21b,  0x21d,  0x21f,  0x19e,  0x223,  0x225,  0x227,  0x229,  0x22b,  0x22d,  0x22f,  0x231,  0x233,  0x2c65,  0x23c,  0x19a,  0x2c66,  0x242,  0x180,  0x289,  0x28c,  0x247,  0x249,  0x24b,  0x24d,  0x24f,  0x371,  0x373,  0x377,  0x3ac,  0x3ad,  0x3ae,  0x3af,  0x3cc,  0x3cd,  0x3ce,  0x3b1,  0x3b2,  0x3b3,  0x3b4,  0x3b5,  0x3b6,  0x3b7,  0x3b8,  0x3b9,  0x3ba,  0x3bb,  0x3bc,  0x3bd,  0x3be,  0x3bf,  0x3c0,  0x3c1,  0x3c3,  0x3c4,  0x3c5,  0x3c6,  0x3c7,  0x3c8,  0x3c9,  0x3ca,  0x3cb,  0x3d7,  0x3d9,  0x3db,  0x3dd,  0x3df,  0x3e1,  0x3e3,  0x3e5,  0x3e7,  0x3e9,  0x3eb,  0x3ed,  0x3ef,  0x3b8,  0x3f8,  0x3f2,  0x3fb,  0x37b,  0x37c,  0x37d,  0x450,  0x451,  0x452,  0x453,  0x454,  0x455,  0x456,  0x457,  0x458,  0x459,  0x45a,  0x45b,  0x45c,  0x45d,  0x45e,  0x45f,  0x430,  0x431,  0x432,  0x433,  0x434,  0x435,  0x436,  0x437,  0x438,  0x439,  0x43a,  0x43b,  0x43c,  0x43d,  0x43e,  0x43f,  0x440,  0x441,  0x442,  0x443,  0x444,  0x445,  0x446,  0x447,  0x448,  0x449,  0x44a,  0x44b,  0x44c,  0x44d,  0x44e,  0x44f,  0x461,  0x463,  0x465,  0x467,  0x469,  0x46b,  0x46d,  0x46f,  0x471,  0x473,  0x475,  0x477,  0x479,  0x47b,  0x47d,  0x47f,  0x481,  0x48b,  0x48d,  0x48f,  0x491,  0x493,  0x495,  0x497,  0x499,  0x49b,  0x49d,  0x49f,  0x4a1,  0x4a3,  0x4a5,  0x4a7,  0x4a9,  0x4ab,  0x4ad,  0x4af,  0x4b1,  0x4b3,  0x4b5,  0x4b7,  0x4b9,  0x4bb,  0x4bd,  0x4bf,  0x4cf,  0x4c2,  0x4c4,  0x4c6,  0x4c8,  0x4ca,  0x4cc,  0x4ce,  0x4d1,  0x4d3,  0x4d5,  0x4d7,  0x4d9,  0x4db,  0x4dd,  0x4df,  0x4e1,  0x4e3,  0x4e5,  0x4e7,  0x4e9,  0x4eb,  0x4ed,  0x4ef,  0x4f1,  0x4f3,  0x4f5,  0x4f7,  0x4f9,  0x4fb,  0x4fd,  0x4ff,  0x501,  0x503,  0x505,  0x507,  0x509,  0x50b,  0x50d,  0x50f,  0x511,  0x513,  0x515,  0x517,  0x519,  0x51b,  0x51d,  0x51f,  0x521,  0x523,  0x525,  0x527,  0x561,  0x562,  0x563,  0x564,  0x565,  0x566,  0x567,  0x568,  0x569,  0x56a,  0x56b,  0x56c,  0x56d,  0x56e,  0x56f,  0x570,  0x571,  0x572,  0x573,  0x574,  0x575,  0x576,  0x577,  0x578,  0x579,  0x57a,  0x57b,  0x57c,  0x57d,  0x57e,  0x57f,  0x580,  0x581,  0x582,  0x583,  0x584,  0x585,  0x586,  0x2d00,  0x2d01,  0x2d02,  0x2d03,  0x2d04,  0x2d05,  0x2d06,  0x2d07,  0x2d08,  0x2d09,  0x2d0a,  0x2d0b,  0x2d0c,  0x2d0d,  0x2d0e,  0x2d0f,  0x2d10,  0x2d11,  0x2d12,  0x2d13,  0x2d14,  0x2d15,  0x2d16,  0x2d17,  0x2d18,  0x2d19,  0x2d1a,  0x2d1b,  0x2d1c,  0x2d1d,  0x2d1e,  0x2d1f,  0x2d20,  0x2d21,  0x2d22,  0x2d23,  0x2d24,  0x2d25,  0x2d27,  0x2d2d,  0x1e01,  0x1e03,  0x1e05,  0x1e07,  0x1e09,  0x1e0b,  0x1e0d,  0x1e0f,  0x1e11,  0x1e13,  0x1e15,  0x1e17,  0x1e19,  0x1e1b,  0x1e1d,  0x1e1f,  0x1e21,  0x1e23,  0x1e25,  0x1e27,  0x1e29,  0x1e2b,  0x1e2d,  0x1e2f,  0x1e31,  0x1e33,  0x1e35,  0x1e37,  0x1e39,  0x1e3b,  0x1e3d,  0x1e3f,  0x1e41,  0x1e43,  0x1e45,  0x1e47,  0x1e49,  0x1e4b,  0x1e4d,  0x1e4f,  0x1e51,  0x1e53,  0x1e55,  0x1e57,  0x1e59,  0x1e5b,  0x1e5d,  0x1e5f,  0x1e61,  0x1e63,  0x1e65,  0x1e67,  0x1e69,  0x1e6b,  0x1e6d,  0x1e6f,  0x1e71,  0x1e73,  0x1e75,  0x1e77,  0x1e79,  0x1e7b,  0x1e7d,  0x1e7f,  0x1e81,  0x1e83,  0x1e85,  0x1e87,  0x1e89,  0x1e8b,  0x1e8d,  0x1e8f,  0x1e91,  0x1e93,  0x1e95,  0xdf,  0x1ea1,  0x1ea3,  0x1ea5,  0x1ea7,  0x1ea9,  0x1eab,  0x1ead,  0x1eaf,  0x1eb1,  0x1eb3,  0x1eb5,  0x1eb7,  0x1eb9,  0x1ebb,  0x1ebd,  0x1ebf,  0x1ec1,  0x1ec3,  0x1ec5,  0x1ec7,  0x1ec9,  0x1ecb,  0x1ecd,  0x1ecf,  0x1ed1,  0x1ed3,  0x1ed5,  0x1ed7,  0x1ed9,  0x1edb,  0x1edd,  0x1edf,  0x1ee1,  0x1ee3,  0x1ee5,  0x1ee7,  0x1ee9,  0x1eeb,  0x1eed,  0x1eef,  0x1ef1,  0x1ef3,  0x1ef5,  0x1ef7,  0x1ef9,  0x1efb,  0x1efd,  0x1eff,  0x1f00,  0x1f01,  0x1f02,  0x1f03,  0x1f04,  0x1f05,  0x1f06,  0x1f07,  0x1f10,  0x1f11,  0x1f12,  0x1f13,  0x1f14,  0x1f15,  0x1f20,  0x1f21,  0x1f22,  0x1f23,  0x1f24,  0x1f25,  0x1f26,  0x1f27,  0x1f30,  0x1f31,  0x1f32,  0x1f33,  0x1f34,  0x1f35,  0x1f36,  0x1f37,  0x1f40,  0x1f41,  0x1f42,  0x1f43,  0x1f44,  0x1f45,  0x1f51,  0x1f53,  0x1f55,  0x1f57,  0x1f60,  0x1f61,  0x1f62,  0x1f63,  0x1f64,  0x1f65,  0x1f66,  0x1f67,  0x1f80,  0x1f81,  0x1f82,  0x1f83,  0x1f84,  0x1f85,  0x1f86,  0x1f87,  0x1f90,  0x1f91,  0x1f92,  0x1f93,  0x1f94,  0x1f95,  0x1f96,  0x1f97,  0x1fa0,  0x1fa1,  0x1fa2,  0x1fa3,  0x1fa4,  0x1fa5,  0x1fa6,  0x1fa7,  0x1fb0,  0x1fb1,  0x1f70,  0x1f71,  0x1fb3,  0x1f72,  0x1f73,  0x1f74,  0x1f75,  0x1fc3,  0x1fd0,  0x1fd1,  0x1f76,  0x1f77,  0x1fe0,  0x1fe1,  0x1f7a,  0x1f7b,  0x1fe5,  0x1f78,  0x1f79,  0x1f7c,  0x1f7d,  0x1ff3,  0x3c9,  0x6b,  0xe5,  0x214e,  0x2170,  0x2171,  0x2172,  0x2173,  0x2174,  0x2175,  0x2176,  0x2177,  0x2178,  0x2179,  0x217a,  0x217b,  0x217c,  0x217d,  0x217e,  0x217f,  0x2184,  0x24d0,  0x24d1,  0x24d2,  0x24d3,  0x24d4,  0x24d5,  0x24d6,  0x24d7,  0x24d8,  0x24d9,  0x24da,  0x24db,  0x24dc,  0x24dd,  0x24de,  0x24df,  0x24e0,  0x24e1,  0x24e2,  0x24e3,  0x24e4,  0x24e5,  0x24e6,  0x24e7,  0x24e8,  0x24e9,  0x2c30,  0x2c31,  0x2c32,  0x2c33,  0x2c34,  0x2c35,  0x2c36,  0x2c37,  0x2c38,  0x2c39,  0x2c3a,  0x2c3b,  0x2c3c,  0x2c3d,  0x2c3e,  0x2c3f,  0x2c40,  0x2c41,  0x2c42,  0x2c43,  0x2c44,  0x2c45,  0x2c46,  0x2c47,  0x2c48,  0x2c49,  0x2c4a,  0x2c4b,  0x2c4c,  0x2c4d,  0x2c4e,  0x2c4f,  0x2c50,  0x2c51,  0x2c52,  0x2c53,  0x2c54,  0x2c55,  0x2c56,  0x2c57,  0x2c58,  0x2c59,  0x2c5a,  0x2c5b,  0x2c5c,  0x2c5d,  0x2c5e,  0x2c61,  0x26b,  0x1d7d,  0x27d,  0x2c68,  0x2c6a,  0x2c6c,  0x251,  0x271,  0x250,  0x252,  0x2c73,  0x2c76,  0x23f,  0x240,  0x2c81,  0x2c83,  0x2c85,  0x2c87,  0x2c89,  0x2c8b,  0x2c8d,  0x2c8f,  0x2c91,  0x2c93,  0x2c95,  0x2c97,  0x2c99,  0x2c9b,  0x2c9d,  0x2c9f,  0x2ca1,  0x2ca3,  0x2ca5,  0x2ca7,  0x2ca9,  0x2cab,  0x2cad,  0x2caf,  0x2cb1,  0x2cb3,  0x2cb5,  0x2cb7,  0x2cb9,  0x2cbb,  0x2cbd,  0x2cbf,  0x2cc1,  0x2cc3,  0x2cc5,  0x2cc7,  0x2cc9,  0x2ccb,  0x2ccd,  0x2ccf,  0x2cd1,  0x2cd3,  0x2cd5,  0x2cd7,  0x2cd9,  0x2cdb,  0x2cdd,  0x2cdf,  0x2ce1,  0x2ce3,  0x2cec,  0x2cee,  0x2cf3,  0xa641,  0xa643,  0xa645,  0xa647,  0xa649,  0xa64b,  0xa64d,  0xa64f,  0xa651,  0xa653,  0xa655,  0xa657,  0xa659,  0xa65b,  0xa65d,  0xa65f,  0xa661,  0xa663,  0xa665,  0xa667,  0xa669,  0xa66b,  0xa66d,  0xa681,  0xa683,  0xa685,  0xa687,  0xa689,  0xa68b,  0xa68d,  0xa68f,  0xa691,  0xa693,  0xa695,  0xa697,  0xa723,  0xa725,  0xa727,  0xa729,  0xa72b,  0xa72d,  0xa72f,  0xa733,  0xa735,  0xa737,  0xa739,  0xa73b,  0xa73d,  0xa73f,  0xa741,  0xa743,  0xa745,  0xa747,  0xa749,  0xa74b,  0xa74d,  0xa74f,  0xa751,  0xa753,  0xa755,  0xa757,  0xa759,  0xa75b,  0xa75d,  0xa75f,  0xa761,  0xa763,  0xa765,  0xa767,  0xa769,  0xa76b,  0xa76d,  0xa76f,  0xa77a,  0xa77c,  0x1d79,  0xa77f,  0xa781,  0xa783,  0xa785,  0xa787,  0xa78c,  0x265,  0xa791,  0xa793,  0xa7a1,  0xa7a3,  0xa7a5,  0xa7a7,  0xa7a9,  0x266,  0xff41,  0xff42,  0xff43,  0xff44,  0xff45,  0xff46,  0xff47,  0xff48,  0xff49,  0xff4a,  0xff4b,  0xff4c,  0xff4d,  0xff4e,  0xff4f,  0xff50,  0xff51,  0xff52,  0xff53,  0xff54,  0xff55,  0xff56,  0xff57,  0xff58,  0xff59,  0xff5a,  0x10428,  0x10429,  0x1042a,  0x1042b,  0x1042c,  0x1042d,  0x1042e,  0x1042f,  0x10430,  0x10431,  0x10432,  0x10433,  0x10434,  0x10435,  0x10436,  0x10437,  0x10438,  0x10439,  0x1043a,  0x1043b,  0x1043c,  0x1043d,  0x1043e,  0x1043f,  0x10440,  0x10441,  0x10442,  0x10443,  0x10444,  0x10445,  0x10446,  0x10447,  0x10448,  0x10449,  0x1044a,  0x1044b,  0x1044c,  0x1044d,  0x1044e,  0x1044f,  0xdf,  0x2000069,  0x307,  0xfb00,  0xfb01,  0xfb02,  0xfb03,  0xfb04,  0xfb05,  0xfb06,  0x587,  0xfb13,  0xfb14,  0xfb15,  0xfb16,  0xfb17,  0x149,  0x390,  0x3b0,  0x1f0,  0x1e96,  0x1e97,  0x1e98,  0x1e99,  0x1e9a,  0x1f50,  0x1f52,  0x1f54,  0x1f56,  0x1fb6,  0x1fc6,  0x1fd2,  0x1fd3,  0x1fd6,  0x1fd7,  0x1fe2,  0x1fe3,  0x1fe4,  0x1fe6,  0x1fe7,  0x1ff6,  0x1f80,  0x1f81,  0x1f82,  0x1f83,  0x1f84,  0x1f85,  0x1f86,  0x1f87,  0x1f80,  0x1f81,  0x1f82,  0x1f83,  0x1f84,  0x1f85,  0x1f86,  0x1f87,  0x1f90,  0x1f91,  0x1f92,  0x1f93,  0x1f94,  0x1f95,  0x1f96,  0x1f97,  0x1f90,  0x1f91,  0x1f92,  0x1f93,  0x1f94,  0x1f95,  0x1f96,  0x1f97,  0x1fa0,  0x1fa1,  0x1fa2,  0x1fa3,  0x1fa4,  0x1fa5,  0x1fa6,  0x1fa7,  0x1fa0,  0x1fa1,  0x1fa2,  0x1fa3,  0x1fa4,  0x1fa5,  0x1fa6,  0x1fa7,  0x1fb3,  0x1fb3,  0x1fc3,  0x1fc3,  0x1ff3,  0x1ff3,  0x1fb2,  0x1fb4,  0x1fc2,  0x1fc4,  0x1ff2,  0x1ff4,  0x1fb7,  0x1fc7,  0x1ff7]; return t; }
+_IUA toTitleTable() { static _IUA t = [ 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,  0x39c,  0xc0,  0xc1,  0xc2,  0xc3,  0xc4,  0xc5,  0xc6,  0xc7,  0xc8,  0xc9,  0xca,  0xcb,  0xcc,  0xcd,  0xce,  0xcf,  0xd0,  0xd1,  0xd2,  0xd3,  0xd4,  0xd5,  0xd6,  0xd8,  0xd9,  0xda,  0xdb,  0xdc,  0xdd,  0xde,  0x178,  0x100,  0x102,  0x104,  0x106,  0x108,  0x10a,  0x10c,  0x10e,  0x110,  0x112,  0x114,  0x116,  0x118,  0x11a,  0x11c,  0x11e,  0x120,  0x122,  0x124,  0x126,  0x128,  0x12a,  0x12c,  0x12e,  0x49,  0x132,  0x134,  0x136,  0x139,  0x13b,  0x13d,  0x13f,  0x141,  0x143,  0x145,  0x147,  0x14a,  0x14c,  0x14e,  0x150,  0x152,  0x154,  0x156,  0x158,  0x15a,  0x15c,  0x15e,  0x160,  0x162,  0x164,  0x166,  0x168,  0x16a,  0x16c,  0x16e,  0x170,  0x172,  0x174,  0x176,  0x179,  0x17b,  0x17d,  0x53,  0x243,  0x182,  0x184,  0x187,  0x18b,  0x191,  0x1f6,  0x198,  0x23d,  0x220,  0x1a0,  0x1a2,  0x1a4,  0x1a7,  0x1ac,  0x1af,  0x1b3,  0x1b5,  0x1b8,  0x1bc,  0x1f7,  0x1c5,  0x1c5,  0x1c5,  0x1c8,  0x1c8,  0x1c8,  0x1cb,  0x1cb,  0x1cb,  0x1cd,  0x1cf,  0x1d1,  0x1d3,  0x1d5,  0x1d7,  0x1d9,  0x1db,  0x18e,  0x1de,  0x1e0,  0x1e2,  0x1e4,  0x1e6,  0x1e8,  0x1ea,  0x1ec,  0x1ee,  0x1f2,  0x1f2,  0x1f2,  0x1f4,  0x1f8,  0x1fa,  0x1fc,  0x1fe,  0x200,  0x202,  0x204,  0x206,  0x208,  0x20a,  0x20c,  0x20e,  0x210,  0x212,  0x214,  0x216,  0x218,  0x21a,  0x21c,  0x21e,  0x222,  0x224,  0x226,  0x228,  0x22a,  0x22c,  0x22e,  0x230,  0x232,  0x23b,  0x2c7e,  0x2c7f,  0x241,  0x246,  0x248,  0x24a,  0x24c,  0x24e,  0x2c6f,  0x2c6d,  0x2c70,  0x181,  0x186,  0x189,  0x18a,  0x18f,  0x190,  0x193,  0x194,  0xa78d,  0xa7aa,  0x197,  0x196,  0x2c62,  0x19c,  0x2c6e,  0x19d,  0x19f,  0x2c64,  0x1a6,  0x1a9,  0x1ae,  0x244,  0x1b1,  0x1b2,  0x245,  0x1b7,  0x399,  0x370,  0x372,  0x376,  0x3fd,  0x3fe,  0x3ff,  0x386,  0x388,  0x389,  0x38a,  0x391,  0x392,  0x393,  0x394,  0x395,  0x396,  0x397,  0x398,  0x399,  0x39a,  0x39b,  0x39c,  0x39d,  0x39e,  0x39f,  0x3a0,  0x3a1,  0x3a3,  0x3a3,  0x3a4,  0x3a5,  0x3a6,  0x3a7,  0x3a8,  0x3a9,  0x3aa,  0x3ab,  0x38c,  0x38e,  0x38f,  0x392,  0x398,  0x3a6,  0x3a0,  0x3cf,  0x3d8,  0x3da,  0x3dc,  0x3de,  0x3e0,  0x3e2,  0x3e4,  0x3e6,  0x3e8,  0x3ea,  0x3ec,  0x3ee,  0x39a,  0x3a1,  0x3f9,  0x395,  0x3f7,  0x3fa,  0x410,  0x411,  0x412,  0x413,  0x414,  0x415,  0x416,  0x417,  0x418,  0x419,  0x41a,  0x41b,  0x41c,  0x41d,  0x41e,  0x41f,  0x420,  0x421,  0x422,  0x423,  0x424,  0x425,  0x426,  0x427,  0x428,  0x429,  0x42a,  0x42b,  0x42c,  0x42d,  0x42e,  0x42f,  0x400,  0x401,  0x402,  0x403,  0x404,  0x405,  0x406,  0x407,  0x408,  0x409,  0x40a,  0x40b,  0x40c,  0x40d,  0x40e,  0x40f,  0x460,  0x462,  0x464,  0x466,  0x468,  0x46a,  0x46c,  0x46e,  0x470,  0x472,  0x474,  0x476,  0x478,  0x47a,  0x47c,  0x47e,  0x480,  0x48a,  0x48c,  0x48e,  0x490,  0x492,  0x494,  0x496,  0x498,  0x49a,  0x49c,  0x49e,  0x4a0,  0x4a2,  0x4a4,  0x4a6,  0x4a8,  0x4aa,  0x4ac,  0x4ae,  0x4b0,  0x4b2,  0x4b4,  0x4b6,  0x4b8,  0x4ba,  0x4bc,  0x4be,  0x4c1,  0x4c3,  0x4c5,  0x4c7,  0x4c9,  0x4cb,  0x4cd,  0x4c0,  0x4d0,  0x4d2,  0x4d4,  0x4d6,  0x4d8,  0x4da,  0x4dc,  0x4de,  0x4e0,  0x4e2,  0x4e4,  0x4e6,  0x4e8,  0x4ea,  0x4ec,  0x4ee,  0x4f0,  0x4f2,  0x4f4,  0x4f6,  0x4f8,  0x4fa,  0x4fc,  0x4fe,  0x500,  0x502,  0x504,  0x506,  0x508,  0x50a,  0x50c,  0x50e,  0x510,  0x512,  0x514,  0x516,  0x518,  0x51a,  0x51c,  0x51e,  0x520,  0x522,  0x524,  0x526,  0x531,  0x532,  0x533,  0x534,  0x535,  0x536,  0x537,  0x538,  0x539,  0x53a,  0x53b,  0x53c,  0x53d,  0x53e,  0x53f,  0x540,  0x541,  0x542,  0x543,  0x544,  0x545,  0x546,  0x547,  0x548,  0x549,  0x54a,  0x54b,  0x54c,  0x54d,  0x54e,  0x54f,  0x550,  0x551,  0x552,  0x553,  0x554,  0x555,  0x556,  0xa77d,  0x2c63,  0x1e00,  0x1e02,  0x1e04,  0x1e06,  0x1e08,  0x1e0a,  0x1e0c,  0x1e0e,  0x1e10,  0x1e12,  0x1e14,  0x1e16,  0x1e18,  0x1e1a,  0x1e1c,  0x1e1e,  0x1e20,  0x1e22,  0x1e24,  0x1e26,  0x1e28,  0x1e2a,  0x1e2c,  0x1e2e,  0x1e30,  0x1e32,  0x1e34,  0x1e36,  0x1e38,  0x1e3a,  0x1e3c,  0x1e3e,  0x1e40,  0x1e42,  0x1e44,  0x1e46,  0x1e48,  0x1e4a,  0x1e4c,  0x1e4e,  0x1e50,  0x1e52,  0x1e54,  0x1e56,  0x1e58,  0x1e5a,  0x1e5c,  0x1e5e,  0x1e60,  0x1e62,  0x1e64,  0x1e66,  0x1e68,  0x1e6a,  0x1e6c,  0x1e6e,  0x1e70,  0x1e72,  0x1e74,  0x1e76,  0x1e78,  0x1e7a,  0x1e7c,  0x1e7e,  0x1e80,  0x1e82,  0x1e84,  0x1e86,  0x1e88,  0x1e8a,  0x1e8c,  0x1e8e,  0x1e90,  0x1e92,  0x1e94,  0x1e60,  0x1ea0,  0x1ea2,  0x1ea4,  0x1ea6,  0x1ea8,  0x1eaa,  0x1eac,  0x1eae,  0x1eb0,  0x1eb2,  0x1eb4,  0x1eb6,  0x1eb8,  0x1eba,  0x1ebc,  0x1ebe,  0x1ec0,  0x1ec2,  0x1ec4,  0x1ec6,  0x1ec8,  0x1eca,  0x1ecc,  0x1ece,  0x1ed0,  0x1ed2,  0x1ed4,  0x1ed6,  0x1ed8,  0x1eda,  0x1edc,  0x1ede,  0x1ee0,  0x1ee2,  0x1ee4,  0x1ee6,  0x1ee8,  0x1eea,  0x1eec,  0x1eee,  0x1ef0,  0x1ef2,  0x1ef4,  0x1ef6,  0x1ef8,  0x1efa,  0x1efc,  0x1efe,  0x1f08,  0x1f09,  0x1f0a,  0x1f0b,  0x1f0c,  0x1f0d,  0x1f0e,  0x1f0f,  0x1f18,  0x1f19,  0x1f1a,  0x1f1b,  0x1f1c,  0x1f1d,  0x1f28,  0x1f29,  0x1f2a,  0x1f2b,  0x1f2c,  0x1f2d,  0x1f2e,  0x1f2f,  0x1f38,  0x1f39,  0x1f3a,  0x1f3b,  0x1f3c,  0x1f3d,  0x1f3e,  0x1f3f,  0x1f48,  0x1f49,  0x1f4a,  0x1f4b,  0x1f4c,  0x1f4d,  0x1f59,  0x1f5b,  0x1f5d,  0x1f5f,  0x1f68,  0x1f69,  0x1f6a,  0x1f6b,  0x1f6c,  0x1f6d,  0x1f6e,  0x1f6f,  0x1fba,  0x1fbb,  0x1fc8,  0x1fc9,  0x1fca,  0x1fcb,  0x1fda,  0x1fdb,  0x1ff8,  0x1ff9,  0x1fea,  0x1feb,  0x1ffa,  0x1ffb,  0x1f88,  0x1f89,  0x1f8a,  0x1f8b,  0x1f8c,  0x1f8d,  0x1f8e,  0x1f8f,  0x1f98,  0x1f99,  0x1f9a,  0x1f9b,  0x1f9c,  0x1f9d,  0x1f9e,  0x1f9f,  0x1fa8,  0x1fa9,  0x1faa,  0x1fab,  0x1fac,  0x1fad,  0x1fae,  0x1faf,  0x1fb8,  0x1fb9,  0x1fbc,  0x399,  0x1fcc,  0x1fd8,  0x1fd9,  0x1fe8,  0x1fe9,  0x1fec,  0x1ffc,  0x2132,  0x2160,  0x2161,  0x2162,  0x2163,  0x2164,  0x2165,  0x2166,  0x2167,  0x2168,  0x2169,  0x216a,  0x216b,  0x216c,  0x216d,  0x216e,  0x216f,  0x2183,  0x24b6,  0x24b7,  0x24b8,  0x24b9,  0x24ba,  0x24bb,  0x24bc,  0x24bd,  0x24be,  0x24bf,  0x24c0,  0x24c1,  0x24c2,  0x24c3,  0x24c4,  0x24c5,  0x24c6,  0x24c7,  0x24c8,  0x24c9,  0x24ca,  0x24cb,  0x24cc,  0x24cd,  0x24ce,  0x24cf,  0x2c00,  0x2c01,  0x2c02,  0x2c03,  0x2c04,  0x2c05,  0x2c06,  0x2c07,  0x2c08,  0x2c09,  0x2c0a,  0x2c0b,  0x2c0c,  0x2c0d,  0x2c0e,  0x2c0f,  0x2c10,  0x2c11,  0x2c12,  0x2c13,  0x2c14,  0x2c15,  0x2c16,  0x2c17,  0x2c18,  0x2c19,  0x2c1a,  0x2c1b,  0x2c1c,  0x2c1d,  0x2c1e,  0x2c1f,  0x2c20,  0x2c21,  0x2c22,  0x2c23,  0x2c24,  0x2c25,  0x2c26,  0x2c27,  0x2c28,  0x2c29,  0x2c2a,  0x2c2b,  0x2c2c,  0x2c2d,  0x2c2e,  0x2c60,  0x23a,  0x23e,  0x2c67,  0x2c69,  0x2c6b,  0x2c72,  0x2c75,  0x2c80,  0x2c82,  0x2c84,  0x2c86,  0x2c88,  0x2c8a,  0x2c8c,  0x2c8e,  0x2c90,  0x2c92,  0x2c94,  0x2c96,  0x2c98,  0x2c9a,  0x2c9c,  0x2c9e,  0x2ca0,  0x2ca2,  0x2ca4,  0x2ca6,  0x2ca8,  0x2caa,  0x2cac,  0x2cae,  0x2cb0,  0x2cb2,  0x2cb4,  0x2cb6,  0x2cb8,  0x2cba,  0x2cbc,  0x2cbe,  0x2cc0,  0x2cc2,  0x2cc4,  0x2cc6,  0x2cc8,  0x2cca,  0x2ccc,  0x2cce,  0x2cd0,  0x2cd2,  0x2cd4,  0x2cd6,  0x2cd8,  0x2cda,  0x2cdc,  0x2cde,  0x2ce0,  0x2ce2,  0x2ceb,  0x2ced,  0x2cf2,  0x10a0,  0x10a1,  0x10a2,  0x10a3,  0x10a4,  0x10a5,  0x10a6,  0x10a7,  0x10a8,  0x10a9,  0x10aa,  0x10ab,  0x10ac,  0x10ad,  0x10ae,  0x10af,  0x10b0,  0x10b1,  0x10b2,  0x10b3,  0x10b4,  0x10b5,  0x10b6,  0x10b7,  0x10b8,  0x10b9,  0x10ba,  0x10bb,  0x10bc,  0x10bd,  0x10be,  0x10bf,  0x10c0,  0x10c1,  0x10c2,  0x10c3,  0x10c4,  0x10c5,  0x10c7,  0x10cd,  0xa640,  0xa642,  0xa644,  0xa646,  0xa648,  0xa64a,  0xa64c,  0xa64e,  0xa650,  0xa652,  0xa654,  0xa656,  0xa658,  0xa65a,  0xa65c,  0xa65e,  0xa660,  0xa662,  0xa664,  0xa666,  0xa668,  0xa66a,  0xa66c,  0xa680,  0xa682,  0xa684,  0xa686,  0xa688,  0xa68a,  0xa68c,  0xa68e,  0xa690,  0xa692,  0xa694,  0xa696,  0xa722,  0xa724,  0xa726,  0xa728,  0xa72a,  0xa72c,  0xa72e,  0xa732,  0xa734,  0xa736,  0xa738,  0xa73a,  0xa73c,  0xa73e,  0xa740,  0xa742,  0xa744,  0xa746,  0xa748,  0xa74a,  0xa74c,  0xa74e,  0xa750,  0xa752,  0xa754,  0xa756,  0xa758,  0xa75a,  0xa75c,  0xa75e,  0xa760,  0xa762,  0xa764,  0xa766,  0xa768,  0xa76a,  0xa76c,  0xa76e,  0xa779,  0xa77b,  0xa77e,  0xa780,  0xa782,  0xa784,  0xa786,  0xa78b,  0xa790,  0xa792,  0xa7a0,  0xa7a2,  0xa7a4,  0xa7a6,  0xa7a8,  0xff21,  0xff22,  0xff23,  0xff24,  0xff25,  0xff26,  0xff27,  0xff28,  0xff29,  0xff2a,  0xff2b,  0xff2c,  0xff2d,  0xff2e,  0xff2f,  0xff30,  0xff31,  0xff32,  0xff33,  0xff34,  0xff35,  0xff36,  0xff37,  0xff38,  0xff39,  0xff3a,  0x10400,  0x10401,  0x10402,  0x10403,  0x10404,  0x10405,  0x10406,  0x10407,  0x10408,  0x10409,  0x1040a,  0x1040b,  0x1040c,  0x1040d,  0x1040e,  0x1040f,  0x10410,  0x10411,  0x10412,  0x10413,  0x10414,  0x10415,  0x10416,  0x10417,  0x10418,  0x10419,  0x1041a,  0x1041b,  0x1041c,  0x1041d,  0x1041e,  0x1041f,  0x10420,  0x10421,  0x10422,  0x10423,  0x10424,  0x10425,  0x10426,  0x10427,  0x2000053,  0x73,  0x130,  0x2000046,  0x66,  0x2000046,  0x69,  0x2000046,  0x6c,  0x3000046,  0x66,  0x69,  0x3000046,  0x66,  0x6c,  0x2000053,  0x74,  0x2000053,  0x74,  0x2000535,  0x582,  0x2000544,  0x576,  0x2000544,  0x565,  0x2000544,  0x56b,  0x200054e,  0x576,  0x2000544,  0x56d,  0x20002bc,  0x4e,  0x3000399,  0x308,  0x301,  0x30003a5,  0x308,  0x301,  0x200004a,  0x30c,  0x2000048,  0x331,  0x2000054,  0x308,  0x2000057,  0x30a,  0x2000059,  0x30a,  0x2000041,  0x2be,  0x20003a5,  0x313,  0x30003a5,  0x313,  0x300,  0x30003a5,  0x313,  0x301,  0x30003a5,  0x313,  0x342,  0x2000391,  0x342,  0x2000397,  0x342,  0x3000399,  0x308,  0x300,  0x3000399,  0x308,  0x301,  0x2000399,  0x342,  0x3000399,  0x308,  0x342,  0x30003a5,  0x308,  0x300,  0x30003a5,  0x308,  0x301,  0x20003a1,  0x313,  0x20003a5,  0x342,  0x30003a5,  0x308,  0x342,  0x20003a9,  0x342,  0x1f88,  0x1f89,  0x1f8a,  0x1f8b,  0x1f8c,  0x1f8d,  0x1f8e,  0x1f8f,  0x1f88,  0x1f89,  0x1f8a,  0x1f8b,  0x1f8c,  0x1f8d,  0x1f8e,  0x1f8f,  0x1f98,  0x1f99,  0x1f9a,  0x1f9b,  0x1f9c,  0x1f9d,  0x1f9e,  0x1f9f,  0x1f98,  0x1f99,  0x1f9a,  0x1f9b,  0x1f9c,  0x1f9d,  0x1f9e,  0x1f9f,  0x1fa8,  0x1fa9,  0x1faa,  0x1fab,  0x1fac,  0x1fad,  0x1fae,  0x1faf,  0x1fa8,  0x1fa9,  0x1faa,  0x1fab,  0x1fac,  0x1fad,  0x1fae,  0x1faf,  0x1fbc,  0x1fbc,  0x1fcc,  0x1fcc,  0x1ffc,  0x1ffc,  0x2001fba,  0x345,  0x2000386,  0x345,  0x2001fca,  0x345,  0x2000389,  0x345,  0x2001ffa,  0x345,  0x200038f,  0x345,  0x3000391,  0x342,  0x345,  0x3000397,  0x342,  0x345,  0x30003a9,  0x342,  0x345]; return t; }
+}
+
+}
+
diff --git a/std/json.d b/std/json.d
index 90485cf2e..b66328731 100644
--- a/std/json.d
+++ b/std/json.d
@@ -5,7 +5,7 @@ JavaScript Object Notation
 
 Copyright: Copyright Jeremie Pelletier 2008 - 2009.
 License:   Boost License 1.0.
-Authors:   Jeremie Pelletier
+Authors:   Jeremie Pelletier, David Herberth
 References: $(LINK http://json.org/)
 Source:    $(PHOBOSSRC std/_json.d)
 */
@@ -20,8 +20,9 @@ module std.json;
 import std.ascii;
 import std.conv;
 import std.range;
-import std.uni : isControl;
 import std.utf;
+import std.traits;
+import std.exception;
 
 private
 {
@@ -38,7 +39,7 @@ enum JSON_TYPE : byte
     /// Indicates the type of a $(D JSONValue).
     STRING,
     INTEGER, /// ditto
-    UINTEGER,/// integers > 2^63-1
+    UINTEGER,/// ditto
     FLOAT,   /// ditto
     OBJECT,  /// ditto
     ARRAY,   /// ditto
@@ -52,38 +53,302 @@ JSON value node
 */
 struct JSONValue
 {
-    union
+    union Store
     {
-        /// Value when $(D type) is $(D JSON_TYPE.STRING)
         string                          str;
-        /// Value when $(D type) is $(D JSON_TYPE.INTEGER)
         long                            integer;
-        /// Value when $(D type) is $(D JSON_TYPE.UINTEGER)
         ulong                           uinteger;
-        /// Value when $(D type) is $(D JSON_TYPE.FLOAT)
         real                            floating;
-        /// Value when $(D type) is $(D JSON_TYPE.OBJECT)
         JSONValue[string]               object;
-        /// Value when $(D type) is $(D JSON_TYPE.ARRAY)
         JSONValue[]                     array;
     }
-    /// Specifies the _type of the value stored in this structure.
-    JSON_TYPE                               type;
+    private Store store;
+    private JSON_TYPE type_tag;
 
-    /// array syntax for json arrays
-    ref JSONValue opIndex(size_t i)
-    in { assert(type == JSON_TYPE.ARRAY, "json type is not array"); }
-    body
+    /// Specifies the _type of the value stored in this structure.
+    @property JSON_TYPE type() const
     {
-        return array[i];
+        return type_tag;
     }
 
-    /// hash syntax for json objects
-    ref JSONValue opIndex(string k)
-    in { assert(type == JSON_TYPE.OBJECT, "json type is not object"); }
-    body
+    /// Value getter/setter for $(D JSON_TYPE.STRING).
+    /// Throws $(D JSONException) for read access if $(D type) is not $(D JSON_TYPE.STRING).
+    @property inout(string) str() inout
     {
-        return object[k];
+        enforceEx!JSONException(type == JSON_TYPE.STRING,
+                                "JSONValue is not a string");
+        return store.str;
+    }
+    /// ditto
+    @property string str(string v)
+    {
+        assign(v);
+        return store.str;
+    }
+
+    /// Value getter/setter for $(D JSON_TYPE.INTEGER).
+    /// Throws $(D JSONException) for read access if $(D type) is not $(D JSON_TYPE.INTEGER).
+    @property inout(long) integer() inout
+    {
+        enforceEx!JSONException(type == JSON_TYPE.INTEGER,
+                                "JSONValue is not an integer");
+        return store.integer;
+    }
+    /// ditto
+    @property long integer(long v)
+    {
+        assign(v);
+        return store.integer;
+    }
+
+    /// Value getter/setter for $(D JSON_TYPE.UINTEGER).
+    /// Throws $(D JSONException) for read access if $(D type) is not $(D JSON_TYPE.UINTEGER).
+    @property inout(ulong) uinteger() inout
+    {
+        enforceEx!JSONException(type == JSON_TYPE.UINTEGER,
+                                "JSONValue is not an unsigned integer");
+        return store.uinteger;
+    }
+    /// ditto
+    @property ulong uinteger(ulong v)
+    {
+        assign(v);
+        return store.uinteger;
+    }
+
+    /// Value getter/setter for $(D JSON_TYPE.FLOAT).
+    /// Throws $(D JSONException) for read access if $(D type) is not $(D JSON_TYPE.FLOAT).
+    @property inout(real) floating() inout
+    {
+        enforceEx!JSONException(type == JSON_TYPE.FLOAT,
+                                "JSONValue is not a floating type");
+        return store.floating;
+    }
+    /// ditto
+    @property real floating(real v)
+    {
+        assign(v);
+        return store.floating;
+    }
+
+    /// Value getter/setter for $(D JSON_TYPE.OBJECT).
+    /// Throws $(D JSONException) for read access if $(D type) is not $(D JSON_TYPE.OBJECT).
+    @property inout(JSONValue[string]) object() inout
+    {
+        enforceEx!JSONException(type == JSON_TYPE.OBJECT,
+                                "JSONValue is not an object");
+        return store.object;
+    }
+    /// ditto
+    @property JSONValue[string] object(JSONValue[string] v)
+    {
+        assign(v);
+        return store.object;
+    }
+
+    /// Value getter/setter for $(D JSON_TYPE.ARRAY).
+    /// Throws $(D JSONException) for read access if $(D type) is not $(D JSON_TYPE.ARRAY).
+    @property inout(JSONValue[]) array() inout
+    {
+        enforceEx!JSONException(type == JSON_TYPE.ARRAY,
+                                "JSONValue is not an array");
+        return store.array;
+    }
+    /// ditto
+    @property JSONValue[] array(JSONValue[] v)
+    {
+        assign(v);
+        return store.array;
+    }
+
+    private void assign(T)(T arg)
+    {
+        static if(is(T : typeof(null)))
+        {
+            type_tag = JSON_TYPE.NULL;
+        }
+        else static if(is(T : string))
+        {
+            type_tag = JSON_TYPE.STRING;
+            store.str = arg;
+        }
+        else static if(is(T : bool))
+        {
+            type_tag = arg ? JSON_TYPE.TRUE : JSON_TYPE.FALSE;
+        }
+        else static if(is(T : ulong) && isUnsigned!T)
+        {
+            type_tag = JSON_TYPE.UINTEGER;
+            store.uinteger = arg;
+        }
+        else static if(is(T : long))
+        {
+            type_tag = JSON_TYPE.INTEGER;
+            store.integer = arg;
+        }
+        else static if(isFloatingPoint!T)
+        {
+            type_tag = JSON_TYPE.FLOAT;
+            store.floating = arg;
+        }
+        else static if(is(T : Value[Key], Key, Value))
+        {
+            static assert(is(Key : string), "AA key must be string");
+            type_tag = JSON_TYPE.OBJECT;
+            static if(is(Value : JSONValue)) {
+                store.object = arg;
+            }
+            else
+            {
+                JSONValue[string] aa;
+                foreach(key, value; arg)
+                    aa[key] = JSONValue(value);
+                store.object = aa;
+            }
+        }
+        else static if(isArray!T)
+        {
+            type_tag = JSON_TYPE.ARRAY;
+            static if(is(ElementEncodingType!T : JSONValue))
+            {
+                store.array = arg;
+            }
+            else
+            {
+                JSONValue[] new_arg = new JSONValue[arg.length];
+                foreach(i, e; arg)
+                    new_arg[i] = JSONValue(e);
+                store.array = new_arg;
+            }
+        }
+        else static if(is(T : JSONValue))
+        {
+            type_tag = arg.type;
+            store = arg.store;
+        }
+        else
+        {
+            static assert(false, text(`unable to convert type "`, T.stringof, `" to json`));
+        }
+    }
+
+    private void assignRef(T)(ref T arg) if(isStaticArray!T)
+    {
+        type_tag = JSON_TYPE.ARRAY;
+        static if(is(ElementEncodingType!T : JSONValue))
+        {
+            store.array = arg;
+        }
+        else
+        {
+            JSONValue[] new_arg = new JSONValue[arg.length];
+            foreach(i, e; arg)
+                new_arg[i] = JSONValue(e);
+            store.array = new_arg;
+        }
+    }
+
+    /**
+     * Constructor for $(D JSONValue). If $(D arg) is a $(D JSONValue)
+     * its value and type will be copied to the new $(D JSONValue).
+     * Note that this is a shallow copy: if type is $(D JSON_TYPE.OBJECT)
+     * or $(D JSON_TYPE.ARRAY) then only the reference to the data will
+     * be copied.
+     * Otherwise, $(D arg) must be implicitly convertible to one of the
+     * following types: $(D typeof(null)), $(D string), $(D ulong),
+     * $(D long), $(D real), an associative array $(D V[K]) for any $(D V)
+     * and $(D K) i.e. a JSON object, any array or $(D bool). The type will
+     * be set accordingly.
+    */
+    this(T)(T arg) if(!isStaticArray!T)
+    {
+        assign(arg);
+    }
+    /// Ditto
+    this(T)(ref T arg) if(isStaticArray!T)
+    {
+        assignRef(arg);
+    }
+    /// Ditto
+    this(T : JSONValue)(inout T arg) inout
+    {
+        store = arg.store;
+        type_tag = arg.type;
+    }
+
+    void opAssign(T)(T arg) if(!isStaticArray!T && !is(T : JSONValue))
+    {
+        assign(arg);
+    }
+
+    void opAssign(T)(ref T arg) if(isStaticArray!T)
+    {
+        assignRef(arg);
+    }
+
+    /// Array syntax for json arrays.
+    /// Throws $(D JSONException) if $(D type) is not $(D JSON_TYPE.ARRAY).
+    ref inout(JSONValue) opIndex(size_t i) inout
+    {
+        enforceEx!JSONException(type == JSON_TYPE.ARRAY,
+                                "JSONValue is not an array");
+        return store.array[i];
+    }
+
+    /// Hash syntax for json objects.
+    /// Throws $(D JSONException) if $(D type) is not $(D JSON_TYPE.OBJECT).
+    ref inout(JSONValue) opIndex(string k) inout
+    {
+        enforceEx!JSONException(type == JSON_TYPE.OBJECT,
+                                "JSONValue is not an object");
+        return store.object[k];
+    }
+
+    /// Implements the foreach $(D opApply) interface for json arrays.
+    int opApply(int delegate(size_t index, ref JSONValue) dg)
+    {
+        enforceEx!JSONException(type == JSON_TYPE.ARRAY,
+                                "JSONValue is not an array");
+        int result;
+
+        foreach(size_t index, ref value; store.array)
+        {
+            result = dg(index, value);
+            if(result)
+                break;
+        }
+
+        return result;
+    }
+
+    /// Implements the foreach $(D opApply) interface for json objects.
+    int opApply(int delegate(string key, ref JSONValue) dg)
+    {
+        enforceEx!JSONException(type == JSON_TYPE.OBJECT,
+                                "JSONValue is not an object");
+        int result;
+
+        foreach(string key, ref value; store.object)
+        {
+            result = dg(key, value);
+            if(result)
+                break;
+        }
+
+        return result;
+    }
+
+    /// Implicitly calls $(D toJSON) on this JSONValue.
+    string toString()
+    {
+        return toJSON(&this);
+    }
+
+    /// Implicitly calls $(D toJSON) on this JSONValue, like $(D toString), but
+    /// also passes $(I true) as $(I pretty) argument.
+    string toPrettyString()
+    {
+        return toJSON(&this, true);
     }
 }
 
@@ -93,7 +358,7 @@ Parses a serialized string and returns a tree of JSON values.
 JSONValue parseJSON(T)(T json, int maxDepth = -1) if(isInputRange!T)
 {
     JSONValue root = void;
-    root.type = JSON_TYPE.NULL;
+    root.type_tag = JSON_TYPE.NULL;
 
     if(json.empty) return root;
 
@@ -234,8 +499,8 @@ JSONValue parseJSON(T)(T json, int maxDepth = -1) if(isInputRange!T)
         switch(c)
         {
             case '{':
-                value.type = JSON_TYPE.OBJECT;
-                value.object = null;
+                value.type_tag = JSON_TYPE.OBJECT;
+                value.store.object = null;
 
                 if(testChar('}')) break;
 
@@ -246,7 +511,7 @@ JSONValue parseJSON(T)(T json, int maxDepth = -1) if(isInputRange!T)
                     checkChar(':');
                     JSONValue member = void;
                     parseValue(&member);
-                    value.object[name] = member;
+                    value.store.object[name] = member;
                 }
                 while(testChar(','));
 
@@ -254,21 +519,21 @@ JSONValue parseJSON(T)(T json, int maxDepth = -1) if(isInputRange!T)
                 break;
 
             case '[':
-                value.type = JSON_TYPE.ARRAY;
+                value.type_tag = JSON_TYPE.ARRAY;
 
                 if(testChar(']'))
                 {
-                    value.array = cast(JSONValue[]) "";
+                    value.store.array = cast(JSONValue[]) "";
                     break;
                 }
 
-                value.array = null;
+                value.store.array = null;
 
                 do
                 {
                     JSONValue element = void;
                     parseValue(&element);
-                    value.array ~= element;
+                    value.store.array ~= element;
                 }
                 while(testChar(','));
 
@@ -276,8 +541,8 @@ JSONValue parseJSON(T)(T json, int maxDepth = -1) if(isInputRange!T)
                 break;
 
             case '"':
-                value.type = JSON_TYPE.STRING;
-                value.str = parseString();
+                value.type_tag = JSON_TYPE.STRING;
+                value.store.str = parseString();
                 break;
 
             case '0': .. case '9':
@@ -327,22 +592,23 @@ JSONValue parseJSON(T)(T json, int maxDepth = -1) if(isInputRange!T)
                 string data = number.data;
                 if(isFloat)
                 {
-                    value.type = JSON_TYPE.FLOAT;
-                    value.floating = parse!real(data);
+                    value.type_tag = JSON_TYPE.FLOAT;
+                    value.store.floating = parse!real(data);
                 }
                 else
                 {
                     if (isNegative)
-                        value.integer = parse!long(data);
+                        value.store.integer = parse!long(data);
                     else
-                        value.uinteger = parse!ulong(data);
-                    value.type = !isNegative && value.uinteger & (1UL << 63) ? JSON_TYPE.UINTEGER : JSON_TYPE.INTEGER;
+                        value.store.uinteger = parse!ulong(data);
+
+                    value.type_tag = !isNegative && value.store.uinteger & (1UL << 63) ? JSON_TYPE.UINTEGER : JSON_TYPE.INTEGER;
                 }
                 break;
 
             case 't':
             case 'T':
-                value.type = JSON_TYPE.TRUE;
+                value.type_tag = JSON_TYPE.TRUE;
                 checkChar!(false, false)('r');
                 checkChar!(false, false)('u');
                 checkChar!(false, false)('e');
@@ -350,7 +616,7 @@ JSONValue parseJSON(T)(T json, int maxDepth = -1) if(isInputRange!T)
 
             case 'f':
             case 'F':
-                value.type = JSON_TYPE.FALSE;
+                value.type_tag = JSON_TYPE.FALSE;
                 checkChar!(false, false)('a');
                 checkChar!(false, false)('l');
                 checkChar!(false, false)('s');
@@ -359,7 +625,7 @@ JSONValue parseJSON(T)(T json, int maxDepth = -1) if(isInputRange!T)
 
             case 'n':
             case 'N':
-                value.type = JSON_TYPE.NULL;
+                value.type_tag = JSON_TYPE.NULL;
                 checkChar!(false, false)('u');
                 checkChar!(false, false)('l');
                 checkChar!(false, false)('l');
@@ -434,7 +700,7 @@ string toJSON(in JSONValue* root, in bool pretty = false)
         final switch(value.type)
         {
             case JSON_TYPE.OBJECT:
-                if(!value.object.length)
+                if(!value.store.object.length)
                 {
                     json.put("{}");
                 }
@@ -442,7 +708,7 @@ string toJSON(in JSONValue* root, in bool pretty = false)
                 {
                     putCharAndEOL('{');
                     bool first = true;
-                    foreach(name, member; value.object)
+                    foreach(name, member; value.store.object)
                     {
                         if(!first)
                             putCharAndEOL(',');
@@ -461,14 +727,14 @@ string toJSON(in JSONValue* root, in bool pretty = false)
                 break;
 
             case JSON_TYPE.ARRAY:
-                if(value.array.empty)
+                if(value.store.array.empty)
                 {
                     json.put("[]");
                 }
                 else
                 {
                     putCharAndEOL('[');
-                    foreach (i, ref el; value.array)
+                    foreach (i, ref el; value.store.array)
                     {
                         if(i)
                             putCharAndEOL(',');
@@ -482,19 +748,19 @@ string toJSON(in JSONValue* root, in bool pretty = false)
                 break;
 
             case JSON_TYPE.STRING:
-                toString(value.str);
+                toString(value.store.str);
                 break;
 
             case JSON_TYPE.INTEGER:
-                json.put(to!string(value.integer));
+                json.put(to!string(value.store.integer));
                 break;
 
             case JSON_TYPE.UINTEGER:
-                json.put(to!string(value.uinteger));
+                json.put(to!string(value.store.uinteger));
                 break;
 
             case JSON_TYPE.FLOAT:
-                json.put(to!string(value.floating));
+                json.put(to!string(value.store.floating));
                 break;
 
             case JSON_TYPE.TRUE:
@@ -518,6 +784,8 @@ string toJSON(in JSONValue* root, in bool pretty = false)
 private void appendJSONChar(Appender!string* dst, dchar c,
                             scope void delegate(string) error)
 {
+    import std.uni : isControl;
+
     if(isControl(c))
         error("Illegal control character.");
     dst.put(c);
@@ -535,9 +803,114 @@ class JSONException : Exception
         else
             super(msg);
     }
+
+    this(string msg, string file, size_t line)
+    {
+        super(msg, file, line);
+    }
 }
 
-version(unittest) import std.exception;
+
+unittest
+{
+    JSONValue jv = "123";
+    assert(jv.type == JSON_TYPE.STRING);
+    assertNotThrown(jv.str);
+    assertThrown!JSONException(jv.integer);
+    assertThrown!JSONException(jv.uinteger);
+    assertThrown!JSONException(jv.floating);
+    assertThrown!JSONException(jv.object);
+    assertThrown!JSONException(jv.array);
+    assertThrown!JSONException(jv["aa"]);
+    assertThrown!JSONException(jv[2]);
+
+    jv = -3;
+    assert(jv.type == JSON_TYPE.INTEGER);
+    assertNotThrown(jv.integer);
+
+    jv = cast(uint)3;
+    assert(jv.type == JSON_TYPE.UINTEGER);
+    assertNotThrown(jv.uinteger);
+
+    jv = 3.0f;
+    assert(jv.type == JSON_TYPE.FLOAT);
+    assertNotThrown(jv.floating);
+
+    jv = ["key" : "value"];
+    assert(jv.type == JSON_TYPE.OBJECT);
+    assertNotThrown(jv.object);
+    assertNotThrown(jv["key"]);
+    foreach(string key, value; jv)
+    {
+        static assert(is(typeof(value) == JSONValue));
+        assert(key == "key");
+        assert(value.type == JSON_TYPE.STRING);
+        assertNotThrown(value.str);
+        assert(value.str == "value");
+    }
+
+    jv = [3, 4, 5];
+    assert(jv.type == JSON_TYPE.ARRAY);
+    assertNotThrown(jv.array);
+    assertNotThrown(jv[2]);
+    foreach(size_t index, value; jv)
+    {
+        static assert(is(typeof(value) == JSONValue));
+        assert(value.type == JSON_TYPE.INTEGER);
+        assertNotThrown(value.integer);
+        assert(index == (value.integer-3));
+    }
+
+    jv = JSONValue("value");
+    assert(jv.type == JSON_TYPE.STRING);
+    assert(jv.str == "value");
+
+    JSONValue jv2 = JSONValue("value");
+    assert(jv2.type == JSON_TYPE.STRING);
+    assert(jv2.str == "value");
+}
+
+unittest
+{
+    // Bugzilla 11504
+
+    JSONValue jv = 1;
+    assert(jv.type == JSON_TYPE.INTEGER);
+
+    jv.str = "123";
+    assert(jv.type == JSON_TYPE.STRING);
+    assert(jv.str == "123");
+
+    jv.integer = 1;
+    assert(jv.type == JSON_TYPE.INTEGER);
+    assert(jv.integer == 1);
+
+    jv.uinteger = 2u;
+    assert(jv.type == JSON_TYPE.UINTEGER);
+    assert(jv.uinteger == 2u);
+
+    jv.floating = 1.5f;
+    assert(jv.type == JSON_TYPE.FLOAT);
+    assert(jv.floating == 1.5f);
+
+    jv.object = ["key" : JSONValue("value")];
+    assert(jv.type == JSON_TYPE.OBJECT);
+    assert(jv.object == ["key" : JSONValue("value")]);
+
+    jv.array = [JSONValue(1), JSONValue(2), JSONValue(3)];
+    assert(jv.type == JSON_TYPE.ARRAY);
+    assert(jv.array == [JSONValue(1), JSONValue(2), JSONValue(3)]);
+
+    jv = true;
+    assert(jv.type == JSON_TYPE.TRUE);
+
+    jv = false;
+    assert(jv.type == JSON_TYPE.FALSE);
+
+    enum E{True = true}
+    jv = E.True;
+    assert(jv.type == JSON_TYPE.TRUE);
+}
 
 unittest
 {
@@ -555,7 +928,6 @@ unittest
         `0.23`,
         `-0.23`,
         `""`,
-        `1.223e+24`,
         `"hello\nworld"`,
         `"\"\\\/\b\f\n\r\t"`,
         `[]`,
@@ -566,6 +938,11 @@ unittest
         // `{"hello":{"json":"is great","array":[12,null,{}]},"goodbye":[true,"or",false,["test",42,{"nested":{"a":23.54,"b":0.0012}}]]}`
     ];
 
+    version (MinGW)
+        jsons ~= `1.223e+024`;
+    else
+        jsons ~= `1.223e+24`;
+
     JSONValue val;
     string result;
     foreach(json; jsons)
@@ -586,12 +963,16 @@ unittest
     // Should be able to correctly interpret unicode entities
     val = parseJSON(`"\u003C\u003E"`);
     assert(toJSON(&val) == "\"\<\>\"");
+    assert(val.to!string() == "\"\<\>\"");
     val = parseJSON(`"\u0391\u0392\u0393"`);
     assert(toJSON(&val) == "\"\Α\Β\Γ\"");
+    assert(val.to!string() == "\"\Α\Β\Γ\"");
     val = parseJSON(`"\u2660\u2666"`);
     assert(toJSON(&val) == "\"\♠\♦\"");
+    assert(val.to!string() == "\"\♠\♦\"");
 
-    assertNotThrown(parseJSON(`{ "foo": "` ~ "\u007F" ~ `"}`));
+    //0x7F is a control character (see Unicode spec)
+    assertThrown(parseJSON(`{ "foo": "` ~ "\u007F" ~ `"}`));
 
     with(parseJSON(`""`))
         assert(str == "" && str !is null);
diff --git a/std/math.d b/std/math.d
index 35b885ff5..0fcdfaf1c 100644
--- a/std/math.d
+++ b/std/math.d
@@ -47,9 +47,16 @@
  *      HALF = ½
  *
  * Copyright: Copyright Digital Mars 2000 - 2011.
+ *            D implementations of tan, atan, atan2, exp, expm1, exp2, log, log10, log1p,
+ *            log2, floor, ceil and lrint functions are based on the CEPHES math library,
+ *            which is Copyright (C) 2001 Stephen L. Moshier 
+ *            and are incorporated herein by permission of the author.  The author
+ *            reserves the right to distribute this material elsewhere under different
+ *            copying permissions.  These modifications are distributed here under
+ *            the following terms:
  * License:   Boost License 1.0.
  * Authors:   $(WEB digitalmars.com, Walter Bright),
- *                        Don Clugston
+ *                        Don Clugston, Conversion of CEPHES math library to D by Iain Buclaw
  * Source: $(PHOBOSSRC std/_math.d)
  */
 module std.math;
@@ -123,8 +130,8 @@ version(unittest)
         if (isnan(x) || isnan(y))
             return 0;
 
-        char bufx[30];
-        char bufy[30];
+        char[30] bufx;
+        char[30] bufy;
         assert(ndigits < bufx.length);
 
         int ix;
@@ -329,7 +336,7 @@ unittest
     assert(abs(71.6Li) == 71.6L);
     assert(abs(-56) == 56);
     assert(abs(2321312L)  == 2321312L);
-    assert(abs(-1+1i) == sqrt(2.0));
+    assert(abs(-1+1i) == sqrt(2.0L));
 }
 
 /***********************************
@@ -486,8 +493,7 @@ trigerr:
     }
     return real.nan;
 
-Lret:
-    ;
+Lret: {}
     }
     else version(D_InlineAsm_X86_64)
     {
@@ -535,18 +541,78 @@ trigerr:
     }
     return real.nan;
 
-Lret:
-    ;
+Lret: {}
     }
     else
     {
-        return core.stdc.math.tanl(x);
+        // Coefficients for tan(x)
+        static immutable real[3] P = [
+           -1.7956525197648487798769E7L,
+            1.1535166483858741613983E6L,
+           -1.3093693918138377764608E4L,
+        ];
+        static immutable real[5] Q = [
+           -5.3869575592945462988123E7L,
+            2.5008380182335791583922E7L,
+           -1.3208923444021096744731E6L,
+            1.3681296347069295467845E4L,
+            1.0000000000000000000000E0L,
+        ];
+
+        // PI/4 split into three parts.
+        enum real P1 = 7.853981554508209228515625E-1L;
+        enum real P2 = 7.946627356147928367136046290398E-9L;
+        enum real P3 = 3.061616997868382943065164830688E-17L;
+
+        // Special cases.
+        if (x == 0.0 || isNaN(x))
+            return x;
+        if (isInfinity(x))
+            return real.nan;
+
+        // Make argument positive but save the sign.
+        bool sign = false;
+        if (signbit(x))
+        {
+            sign = true;
+            x = -x;
+        }
+
+        // Compute x mod PI/4.
+        real y = floor(x / PI_4);
+        // Strip high bits of integer part.
+        real z = ldexp(y, -4);
+        // Compute y - 16 * (y / 16).
+        z = y - ldexp(floor(z), 4);
+
+        // Integer and fraction part modulo one octant.
+        int j = cast(int)(z);
+
+        // Map zeros and singularities to origin.
+        if (j & 1)
+        {
+            j += 1;
+            y += 1.0;
+        }
+
+        z = ((x - y * P1) - y * P2) - y * P3;
+        real zz = z * z;
+
+        if (zz > 1.0e-20L)
+            y = z + z * (zz * poly(zz, P) / poly(zz, Q));
+        else
+            y = z;
+
+        if (j & 2)
+            y = -1.0 / y;
+
+        return (sign) ? -y : y;
     }
 }
 
 unittest
 {
-    static real vals[][2] =     // angle,tan
+    static real[2][] vals =     // angle,tan
         [
          [   0,   0],
          [   .5,  .5463024898],
@@ -589,7 +655,7 @@ unittest
         r = -r;
         t = tan(x);
         //printf("tan(%Lg) = %Lg, should be %Lg\n", x, t, r);
-        if (!isIdentical(r, t) && !(r!<>=0 && t!<>=0)) assert(fabs(r-t) <= .0000001);
+        if (!isIdentical(r, t) && !(r!=r && t!=t)) assert(fabs(r-t) <= .0000001);
     }
     // overflow
     assert(isNaN(tan(real.infinity)));
@@ -667,7 +733,72 @@ unittest
  *      $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(NAN))       $(TD yes))
  *  )
  */
-real atan(real x) @safe pure nothrow { return atan2(x, 1.0L); }
+real atan(real x) @safe pure nothrow
+{
+    version(InlineAsm_X86_Any)
+    {
+        return atan2(x, 1.0L);
+    }
+    else
+    {
+        // Coefficients for atan(x)
+        static immutable real[5] P = [
+           -5.0894116899623603312185E1L,
+           -9.9988763777265819915721E1L,
+           -6.3976888655834347413154E1L,
+           -1.4683508633175792446076E1L,
+           -8.6863818178092187535440E-1L,
+        ];
+        static immutable real[6] Q = [
+            1.5268235069887081006606E2L,
+            3.9157570175111990631099E2L,
+            3.6144079386152023162701E2L,
+            1.4399096122250781605352E2L,
+            2.2981886733594175366172E1L,
+            1.0000000000000000000000E0L,
+        ];
+
+        // tan(PI/8)
+        enum real TAN_PI_8 = 4.1421356237309504880169e-1L;
+        // tan(3 * PI/8)
+        enum real TAN3_PI_8 = 2.41421356237309504880169L;
+
+        // Special cases.
+        if (x == 0.0)
+            return x;
+        if (isInfinity(x))
+            return copysign(PI_2, x);
+
+        // Make argument positive but save the sign.
+        bool sign = false;
+        if (signbit(x))
+        {
+            sign = true;
+            x = -x;
+        }
+
+        // Range reduction.
+        real y;
+        if (x > TAN3_PI_8)
+        {
+            y = PI_2;
+            x = -(1.0 / x);
+        }
+        else if (x > TAN_PI_8)
+        {
+            y = PI_4;
+            x = (x - 1.0)/(x + 1.0);
+        }
+        else
+            y = 0.0;
+
+        // Rational form in x^^2.
+        real z = x * x;
+        y = y + (poly(z, P) / poly(z, Q)) * z * x + x;
+
+        return (sign) ? -y : y;
+    }
+}
 
 /// ditto
 double atan(double x) @safe pure nothrow { return atan(cast(real)x); }
@@ -726,7 +857,53 @@ real atan2(real y, real x) @trusted pure nothrow
     }
     else
     {
-        return core.stdc.math.atan2l(y,x);
+        // Special cases.
+        if (isNaN(x) || isNaN(y))
+            return real.nan;
+        if (y == 0.0)
+        {
+            if (x >= 0 && !signbit(x))
+                return copysign(0, y);
+            else
+                return copysign(PI, y);
+        }
+        if (x == 0.0)
+            return copysign(PI_2, y);
+        if (isInfinity(x))
+        {
+            if (signbit(x))
+            {
+                if (isInfinity(y))
+                    return copysign(3*PI_4, y);
+                else
+                    return copysign(PI, y);
+            }
+            else
+            {
+                if (isInfinity(y))
+                    return copysign(PI_4, y);
+                else
+                    return copysign(0.0, y);
+            }
+        }
+        if (isInfinity(y))
+            return copysign(PI_2, y);
+
+        // Call atan and determine the quadrant.
+        real z = atan(y / x);
+
+        if (signbit(x))
+        {
+            if (signbit(y))
+                z = z - PI;
+            else
+                z = z + PI;
+        }
+
+        if (z == 0.0)
+            return copysign(z, y);
+
+        return z;
     }
 }
 
@@ -1104,7 +1281,53 @@ real exp(real x) @trusted pure nothrow
     }
     else
     {
-        return core.stdc.math.expl(x);
+        // Coefficients for exp(x)
+        static immutable real[3] P = [
+            9.9999999999999999991025E-1L,
+            3.0299440770744196129956E-2L,
+            1.2617719307481059087798E-4L,
+        ];
+        static immutable real[4] Q = [
+            2.0000000000000000000897E0L,
+            2.2726554820815502876593E-1L,
+            2.5244834034968410419224E-3L,
+            3.0019850513866445504159E-6L,
+        ];
+
+        // C1 + C2 = LN2.
+        enum real C1 = 6.9314575195312500000000E-1L;
+        enum real C2 = 1.428606820309417232121458176568075500134E-6L;
+
+        // Overflow and Underflow limits.
+        enum real OF =  1.1356523406294143949492E4L;
+        enum real UF = -1.1432769596155737933527E4L;
+
+        // Special cases.
+        if (isNaN(x))
+            return x;
+        if (x > OF)
+            return real.infinity;
+        if (x < UF)
+            return 0.0;
+
+        // Express: e^^x = e^^g * 2^^n
+        //   = e^^g * e^^(n * LOG2E)
+        //   = e^^(g + n * LOG2E)
+        int n = cast(int)floor(LOG2E * x + 0.5);
+        x -= n * C1;
+        x -= n * C2;
+
+        // Rational approximation for exponential of the fractional part:
+        //  e^^x = 1 + 2x P(x^^2) / (Q(x^^2) - P(x^^2))
+        real xx = x * x;
+        real px = x * poly(xx, P);
+        x = px / (poly(xx, Q) - px);
+        x = 1.0 + ldexp(x, 1);
+
+        // Scale by power of 2.
+        x = ldexp(x, n);
+
+        return x;
     }
 }
 
@@ -1116,7 +1339,7 @@ float exp(float x)  @safe pure nothrow   { return exp(cast(real)x); }
 
 unittest
 {
-    assert(equalsDigit(exp(3.0), E * E * E, useDigits));
+    assert(equalsDigit(exp(3.0L), E * E * E, useDigits));
 }
 
 /**
@@ -1299,7 +1522,57 @@ L_largenegative:
     }
     else
     {
-        return core.stdc.math.expm1l(x);
+        // Coefficients for exp(x) - 1
+        static immutable real[5] P = [
+           -1.586135578666346600772998894928250240826E4L,
+            2.642771505685952966904660652518429479531E3L,
+           -3.423199068835684263987132888286791620673E2L,
+            1.800826371455042224581246202420972737840E1L,
+           -5.238523121205561042771939008061958820811E-1L,
+        ];
+        static immutable real[6] Q = [
+           -9.516813471998079611319047060563358064497E4L,
+            3.964866271411091674556850458227710004570E4L,
+           -7.207678383830091850230366618190187434796E3L,
+            7.206038318724600171970199625081491823079E2L,
+           -4.002027679107076077238836622982900945173E1L,
+            1.000000000000000000000000000000000000000E0L,
+        ];
+
+        // C1 + C2 = LN2.
+        enum real C1 = 6.9314575195312500000000E-1L;
+        enum real C2 = 1.4286068203094172321215E-6L;
+
+        // Overflow and Underflow limits.
+        enum real OF =  1.1356523406294143949492E4L;
+        enum real UF = -4.5054566736396445112120088E1L;
+
+        // Special cases.
+        if (x > OF)
+            return real.infinity;
+        if (x == 0.0)
+            return x;
+        if (x < UF)
+            return -1.0;
+
+        // Express x = LN2 (n + remainder), remainder not exceeding 1/2.
+        int n = cast(int)floor(0.5 + x / LN2);
+        x -= n * C1;
+        x -= n * C2;
+
+        // Rational approximation:
+        //  exp(x) - 1 = x + 0.5 x^^2 + x^^3 P(x) / Q(x)
+        real px = x * poly(x, P);
+        real qx = poly(x, Q);
+        real xx = x * x;
+        qx = x + (0.5 * xx + xx * px / qx);
+
+        // We have qx = exp(remainder LN2) - 1, so:
+        //  exp(x) - 1 = 2^^n (qx + 1) - 1 = 2^^n qx + 2^^n - 1.
+        px = ldexp(1.0, n);
+        x = px * qx + (px - 1.0);
+
+        return x;
     }
 }
 
@@ -1506,7 +1779,46 @@ L_was_nan:
     }
     else
     {
-        return core.stdc.math.exp2l(x);
+        // Coefficients for exp2(x)
+        static immutable real[3] P = [
+            2.0803843631901852422887E6L,
+            3.0286971917562792508623E4L,
+            6.0614853552242266094567E1L,
+        ];
+        static immutable real[4] Q = [
+            6.0027204078348487957118E6L,
+            3.2772515434906797273099E5L,
+            1.7492876999891839021063E3L,
+            1.0000000000000000000000E0L,
+        ];
+
+        // Overflow and Underflow limits.
+        enum real OF =  16384.0L;
+        enum real UF = -16382.0L;
+
+        // Special cases.
+        if (isNaN(x))
+            return x;
+        if (x > OF)
+            return real.infinity;
+        if (x < UF)
+            return 0.0;
+
+        // Separate into integer and fractional parts.
+        int n = cast(int)floor(x + 0.5);
+        x -= n;
+
+        // Rational approximation:
+        //  exp2(x) = 1.0 + 2x P(x^^2) / (Q(x^^2) - P(x^^2))
+        real xx = x * x;
+        real px = x * poly(xx, P);
+        x = px / (poly(xx, Q) - px);
+        x = 1.0 + ldexp(x, 1);
+
+        // Scale by power of 2.
+        x = ldexp(x, n);
+
+        return x;
     }
 }
 
@@ -1515,7 +1827,6 @@ unittest
     assert(exp2(0.5L)== SQRT2);
     assert(exp2(8.0L) == 256.0);
     assert(exp2(-9.0L)== 1.0L/512.0);
-    assert(exp(3.0L) == E*E*E);
     assert( core.stdc.math.exp2f(0.0f) == 1 );
     assert( core.stdc.math.exp2 (0.0)  == 1 );
     assert( core.stdc.math.exp2l(0.0L) == 1 );
@@ -1570,13 +1881,13 @@ unittest
     resetIeeeFlags();
     x = exp(real.nan);
     f = ieeeFlags;
-    assert(isIdentical(x,real.nan));
+    assert(isIdentical(abs(x), real.nan));
     assert(f.flags == 0);
 
     resetIeeeFlags();
     x = exp(-real.nan);
     f = ieeeFlags;
-    assert(isIdentical(x, -real.nan));
+    assert(isIdentical(abs(x), real.nan));
     assert(f.flags == 0);
 
     x = exp(NaN(0x123));
@@ -1653,7 +1964,7 @@ real frexp(real value, out int exp) @trusted pure nothrow
 {
     ushort* vu = cast(ushort*)&value;
     long* vl = cast(long*)&value;
-    uint ex;
+    int ex;
     alias floatTraits!(real) F;
 
     ex = vu[F.EXPPOS_SHORT] & F.EXPMASK;
@@ -1788,7 +2099,7 @@ real frexp(real value, out int exp) @trusted pure nothrow
 
 unittest
 {
-    static real vals[][3] =     // x,frexp,exp
+    static real[3][] vals =     // x,frexp,exp
         [
          [0.0,   0.0,    0],
          [-0.0,  -0.0,   0],
@@ -1818,7 +2129,7 @@ unittest
 
     static if (real.mant_dig == 64)
     {
-        static real extendedvals[][3] = [ // x,frexp,exp
+        static real[3][] extendedvals = [ // x,frexp,exp
                                           [0x1.a5f1c2eb3fe4efp+73L, 0x1.A5F1C2EB3FE4EFp-1L,   74],    // normal
                                           [0x1.fa01712e8f0471ap-1064L,  0x1.fa01712e8f0471ap-1L,     -1063],
                                           [real.min_normal,  .5,     -16381],
@@ -1929,7 +2240,7 @@ unittest
 
 unittest
 {
-    static real vals[][3] =    // value,exp,ldexp
+    static real[3][] vals =    // value,exp,ldexp
     [
     [    0,    0,    0],
     [    1,    0,    1],
@@ -1985,7 +2296,110 @@ real log(real x) @safe pure nothrow
     version (INLINE_YL2X)
         return yl2x(x, LN2);
     else
-        return core.stdc.math.logl(x);
+    {
+        // Coefficients for log(1 + x)
+        static immutable real[7] P = [
+            2.0039553499201281259648E1L,
+            5.7112963590585538103336E1L,
+            6.0949667980987787057556E1L,
+            2.9911919328553073277375E1L,
+            6.5787325942061044846969E0L,
+            4.9854102823193375972212E-1L,
+            4.5270000862445199635215E-5L,
+        ];
+        static immutable real[7] Q = [
+            6.0118660497603843919306E1L,
+            2.1642788614495947685003E2L,
+            3.0909872225312059774938E2L,
+            2.2176239823732856465394E2L,
+            8.3047565967967209469434E1L,
+            1.5062909083469192043167E1L,
+            1.0000000000000000000000E0L,
+        ];
+
+        // Coefficients for log(x)
+        static immutable real[4] R = [
+           -3.5717684488096787370998E1L,
+            1.0777257190312272158094E1L,
+           -7.1990767473014147232598E-1L,
+            1.9757429581415468984296E-3L,
+        ];
+        static immutable real[4] S = [
+           -4.2861221385716144629696E2L,
+            1.9361891836232102174846E2L,
+           -2.6201045551331104417768E1L,
+            1.0000000000000000000000E0L,
+        ];
+
+        // C1 + C2 = LN2.
+        enum real C1 = 6.9314575195312500000000E-1L;
+        enum real C2 = 1.4286068203094172321215E-6L;
+
+        // Special cases.
+        if (isNaN(x))
+            return x;
+        if (isInfinity(x) && !signbit(x))
+            return x;
+        if (x == 0.0)
+            return -real.infinity;
+        if (x < 0.0)
+            return real.nan;
+
+        // Separate mantissa from exponent.
+        // Note, frexp is used so that denormal numbers will be handled properly.
+        real y, z;
+        int exp;
+
+        x = frexp(x, exp);
+
+        // Logarithm using log(x) = z + z^^3 P(z) / Q(z),
+        // where z = 2(x - 1)/(x + 1)
+        if((exp > 2) || (exp < -2))
+        {
+            if(x < SQRT1_2)
+            {   // 2(2x - 1)/(2x + 1)
+                exp -= 1;
+                z = x - 0.5;
+                y = 0.5 * z + 0.5;
+            }       
+            else
+            {   // 2(x - 1)/(x + 1)
+                z = x - 0.5;
+                z -= 0.5;
+                y = 0.5 * x  + 0.5;
+            }
+            x = z / y;
+            z = x * x;
+            z = x * (z * poly(z, R) / poly(z, S));
+            z += exp * C2;
+            z += x;
+            z += exp * C1;
+
+            return z;
+        }
+
+        // Logarithm using log(1 + x) = x - .5x^^2 + x^^3 P(x) / Q(x)
+        if (x < SQRT1_2)
+        {   // 2x - 1
+            exp -= 1;
+            x = ldexp(x, 1) - 1.0;
+        }
+        else
+        {
+            x = x - 1.0;
+        }
+        z = x * x;
+        y = x * (z * poly(x, P) / poly(x, Q));
+        y += exp * C2;
+        z = y - ldexp(z, -1);
+
+        // Note, the sum of above terms does not exceed x/4,
+        // so it contributes at most about 1/4 lsb to the error.
+        z += x;
+        z += exp * C1;
+
+        return z;
+    }
 }
 
 unittest
@@ -2009,7 +2423,114 @@ real log10(real x) @safe pure nothrow
     version (INLINE_YL2X)
         return yl2x(x, LOG2);
     else
-        return core.stdc.math.log10l(x);
+    {
+        // Coefficients for log(1 + x)
+        static immutable real[7] P = [
+            2.0039553499201281259648E1L,
+            5.7112963590585538103336E1L,
+            6.0949667980987787057556E1L,
+            2.9911919328553073277375E1L,
+            6.5787325942061044846969E0L,
+            4.9854102823193375972212E-1L,
+            4.5270000862445199635215E-5L,
+        ];
+        static immutable real[7] Q = [
+            6.0118660497603843919306E1L,
+            2.1642788614495947685003E2L,
+            3.0909872225312059774938E2L,
+            2.2176239823732856465394E2L,
+            8.3047565967967209469434E1L,
+            1.5062909083469192043167E1L,
+            1.0000000000000000000000E0L,
+        ];
+
+        // Coefficients for log(x)
+        static immutable real[4] R = [
+           -3.5717684488096787370998E1L,
+            1.0777257190312272158094E1L,
+           -7.1990767473014147232598E-1L,
+            1.9757429581415468984296E-3L,
+        ];
+        static immutable real[4] S = [
+           -4.2861221385716144629696E2L,
+            1.9361891836232102174846E2L,
+           -2.6201045551331104417768E1L,
+            1.0000000000000000000000E0L,
+        ];
+
+        // log10(2) split into two parts.
+        enum real L102A =  0.3125L;
+        enum real L102B = -1.14700043360188047862611052755069732318101185E-2L;
+
+        // log10(e) split into two parts.
+        enum real L10EA =  0.5L;
+        enum real L10EB = -6.570551809674817234887108108339491770560299E-2L;
+
+        // Special cases are the same as for log.
+        if (isNaN(x))
+            return x;
+        if (isInfinity(x) && !signbit(x))
+            return x;
+        if (x == 0.0)
+            return -real.infinity;
+        if (x < 0.0)
+            return real.nan;
+
+        // Separate mantissa from exponent.
+        // Note, frexp is used so that denormal numbers will be handled properly.
+        real y, z;
+        int exp;
+
+        x = frexp(x, exp);
+
+        // Logarithm using log(x) = z + z^^3 P(z) / Q(z),
+        // where z = 2(x - 1)/(x + 1)
+        if((exp > 2) || (exp < -2))
+        {
+            if(x < SQRT1_2)
+            {   // 2(2x - 1)/(2x + 1)
+                exp -= 1;
+                z = x - 0.5;
+                y = 0.5 * z + 0.5;
+            }       
+            else
+            {   // 2(x - 1)/(x + 1)
+                z = x - 0.5;
+                z -= 0.5;
+                y = 0.5 * x  + 0.5;
+            }
+            x = z / y;
+            z = x * x;
+            y = x * (z * poly(z, R) / poly(z, S));
+            goto Ldone;
+        }
+
+        // Logarithm using log(1 + x) = x - .5x^^2 + x^^3 P(x) / Q(x)
+        if (x < SQRT1_2)
+        {   // 2x - 1
+            exp -= 1;
+            x = ldexp(x, 1) - 1.0;
+        }
+        else
+            x = x - 1.0;
+
+        z = x * x;
+        y = x * (z * poly(x, P) / poly(x, Q));
+        y = y - ldexp(z, -1);
+
+        // Multiply log of fraction by log10(e) and base 2 exponent by log10(2).
+        // This sequence of operations is critical and it may be horribly
+        // defeated by some compiler optimizers.
+    Ldone:
+        z = y * L10EB;
+        z += x * L10EB;
+        z += exp * L102B;
+        z += y * L10EA;
+        z += x * L10EA;
+        z += exp * L102A;
+
+        return z;
+    }
 }
 
 unittest
@@ -2043,7 +2564,17 @@ real log1p(real x) @safe pure nothrow
     }
     else
     {
-        return core.stdc.math.log1pl(x);
+        // Special cases.
+        if (isNaN(x) || x == 0.0)
+            return x;
+        if (isInfinity(x) && !signbit(x))
+            return x;
+        if (x == -1.0)
+            return -real.infinity;
+        if (x < -1.0)
+            return real.nan;
+
+        return log(x + 1.0);
     }
 }
 
@@ -2063,7 +2594,105 @@ real log2(real x) @safe pure nothrow
     version (INLINE_YL2X)
         return yl2x(x, 1);
     else
-        return core.stdc.math.log2l(x);
+    {
+        // Coefficients for log(1 + x)
+        static immutable real[7] P = [
+            2.0039553499201281259648E1L,
+            5.7112963590585538103336E1L,
+            6.0949667980987787057556E1L,
+            2.9911919328553073277375E1L,
+            6.5787325942061044846969E0L,
+            4.9854102823193375972212E-1L,
+            4.5270000862445199635215E-5L,
+        ];
+        static immutable real[7] Q = [
+            6.0118660497603843919306E1L,
+            2.1642788614495947685003E2L,
+            3.0909872225312059774938E2L,
+            2.2176239823732856465394E2L,
+            8.3047565967967209469434E1L,
+            1.5062909083469192043167E1L,
+            1.0000000000000000000000E0L,
+        ];
+
+        // Coefficients for log(x)
+        static immutable real[4] R = [
+           -3.5717684488096787370998E1L,
+            1.0777257190312272158094E1L,
+           -7.1990767473014147232598E-1L,
+            1.9757429581415468984296E-3L,
+        ];
+        static immutable real[4] S = [
+           -4.2861221385716144629696E2L,
+            1.9361891836232102174846E2L,
+           -2.6201045551331104417768E1L,
+            1.0000000000000000000000E0L,
+        ];
+
+        // Special cases are the same as for log.
+        if (isNaN(x))
+            return x;
+        if (isInfinity(x) && !signbit(x))
+            return x;
+        if (x == 0.0)
+            return -real.infinity;
+        if (x < 0.0)
+            return real.nan;
+
+        // Separate mantissa from exponent.
+        // Note, frexp is used so that denormal numbers will be handled properly.
+        real y, z;
+        int exp;
+
+        x = frexp(x, exp);
+
+        // Logarithm using log(x) = z + z^^3 P(z) / Q(z),
+        // where z = 2(x - 1)/(x + 1)
+        if((exp > 2) || (exp < -2))
+        {
+            if(x < SQRT1_2)
+            {   // 2(2x - 1)/(2x + 1)
+                exp -= 1;
+                z = x - 0.5;
+                y = 0.5 * z + 0.5;
+            }       
+            else
+            {   // 2(x - 1)/(x + 1)
+                z = x - 0.5;
+                z -= 0.5;
+                y = 0.5 * x  + 0.5;
+            }
+            x = z / y;
+            z = x * x;
+            y = x * (z * poly(z, R) / poly(z, S));
+            goto Ldone;
+        }
+
+        // Logarithm using log(1 + x) = x - .5x^^2 + x^^3 P(x) / Q(x)
+        if (x < SQRT1_2)
+        {   // 2x - 1
+            exp -= 1;
+            x = ldexp(x, 1) - 1.0;
+        }
+        else
+            x = x - 1.0;
+
+        z = x * x;
+        y = x * (z * poly(x, P) / poly(x, Q));
+        y = y - ldexp(z, -1);
+
+        // Multiply log of fraction by log10(e) and base 2 exponent by log10(2).
+        // This sequence of operations is critical and it may be horribly
+        // defeated by some compiler optimizers.
+    Ldone:
+        z = y * (LOG2E - 1.0);
+        z += x * (LOG2E - 1.0);
+        z += y;
+        z += x;
+        z += exp;
+
+        return z;
+    }
 }
 
 unittest
@@ -2266,7 +2895,7 @@ real hypot(real x, real y) @safe pure nothrow
 
     real u = fabs(x);
     real v = fabs(y);
-    if (u !>= v)  // check for NaN as well.
+    if (!(u >= v))  // check for NaN as well.
     {
         v = u;
         u = fabs(y);
@@ -2305,7 +2934,7 @@ real hypot(real x, real y) @safe pure nothrow
 
 unittest
 {
-    static real vals[][3] =     // x,y,hypot
+    static real[3][] vals =     // x,y,hypot
         [
             [ 0.0,     0.0,   0.0],
             [ 0.0,    -0.0,   0.0],
@@ -2339,7 +2968,7 @@ unittest
  * Returns the value of x rounded upward to the next integer
  * (toward positive infinity).
  */
-real ceil(real x)  @trusted nothrow
+real ceil(real x)  @trusted pure nothrow
 {
     version (Win64)
     {
@@ -2361,20 +2990,38 @@ real ceil(real x)  @trusted nothrow
         }
     }
     else
-        return core.stdc.math.ceill(x);
+    {
+        // Special cases.
+        if (isNaN(x) || isInfinity(x))
+            return x;
+
+        real y = floor(x);
+        if (y < x)
+            y += 1.0;
+
+        return y;
+    }
 }
 
 unittest
 {
     assert(ceil(+123.456) == +124);
     assert(ceil(-123.456) == -123);
+    assert(ceil(-1.234) == -1);
+    assert(ceil(-0.123) == 0);
+    assert(ceil(0.0) == 0);
+    assert(ceil(+0.123) == 1);
+    assert(ceil(+1.234) == 2);
+    assert(ceil(real.infinity) == real.infinity);
+    assert(isNaN(ceil(real.nan)));
+    assert(isNaN(ceil(real.init)));
 }
 
 /**************************************
  * Returns the value of x rounded downward to the next integer
  * (toward negative infinity).
  */
-real floor(real x) @trusted nothrow
+real floor(real x) @trusted pure nothrow
 {
     version (Win64)
     {
@@ -2396,13 +3043,99 @@ real floor(real x) @trusted nothrow
         }
     }
     else
-        return core.stdc.math.floorl(x);
+    {
+        // Bit clearing masks.
+        static immutable ushort[17] BMASK = [
+            0xffff, 0xfffe, 0xfffc, 0xfff8,
+            0xfff0, 0xffe0, 0xffc0, 0xff80,
+            0xff00, 0xfe00, 0xfc00, 0xf800,
+            0xf000, 0xe000, 0xc000, 0x8000,
+            0x0000,
+        ];
+
+        // Special cases.
+        if (isNaN(x) || isInfinity(x) || x == 0.0)
+            return x;
+
+        alias floatTraits!(real) F;
+        auto vu = *cast(ushort[real.sizeof/2]*)(&x);
+
+        // Find the exponent (power of 2)
+        static if (real.mant_dig == 53)
+        {
+            int exp = ((vu[F.EXPPOS_SHORT] >> 4) & 0x7ff) - 0x3ff;
+
+            version (LittleEndian)
+                int pos = 0;
+            else
+                int pos = 3;
+        }
+        else static if (real.mant_dig == 64)
+        {
+            int exp = (vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+
+            version (LittleEndian)
+                int pos = 0;
+            else
+                int pos = 4;
+        }
+        else if (real.mant_dig == 113)
+        {
+            int exp = (vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+
+            version (LittleEndian)
+                int pos = 0;
+            else
+                int pos = 7;
+        }
+        else
+            static assert(false, "Only 64-bit, 80-bit, and 128-bit reals are supported by floor()");
+
+        if (exp < 0)
+        {
+            if (x < 0.0)
+                return -1.0;
+            else
+                return 0.0;
+        }
+
+        exp = (real.mant_dig - 1) - exp;
+
+        // Clean out 16 bits at a time.
+        while (exp >= 16)
+        {
+            version (LittleEndian)
+                vu[pos++] = 0;
+            else
+                vu[pos--] = 0;
+            exp -= 16;
+        }
+
+        // Clear the remaining bits.
+        if (exp > 0)
+            vu[pos] &= BMASK[exp];
+
+        real y = *cast(real*)(&vu);
+
+        if ((x < 0.0) && (x != y))
+            y -= 1.0;
+
+        return y;
+    }
 }
 
 unittest
 {
     assert(floor(+123.456) == +123);
     assert(floor(-123.456) == -124);
+    assert(floor(-1.234) == -2);
+    assert(floor(-0.123) == -1);
+    assert(floor(0.0) == 0);
+    assert(floor(+0.123) == 0);
+    assert(floor(+1.234) == 1);
+    assert(floor(real.infinity) == real.infinity);
+    assert(isNaN(floor(real.nan)));
+    assert(isNaN(floor(real.init)));
 }
 
 /******************************************
@@ -2470,10 +3203,126 @@ long lrint(real x) @trusted pure nothrow
     }
     else
     {
-        return core.stdc.math.llrintl(x);
+        static if (real.mant_dig == 53)
+        {
+            long result;
+
+            // Rounding limit when casting from real(double) to ulong.
+            enum real OF = 4.50359962737049600000E15L;
+
+            uint* vi = cast(uint*)(&x);
+
+            // Find the exponent and sign
+            uint msb = vi[MANTISSA_MSB];
+            uint lsb = vi[MANTISSA_LSB];
+            int exp = ((msb >> 20) & 0x7ff) - 0x3ff;
+            int sign = msb >> 31;
+            msb &= 0xfffff;
+            msb |= 0x100000;
+
+            if (exp < 63)
+            {
+                if (exp >= 52)
+                    result = (cast(long) msb << (exp - 20)) | (lsb << (exp - 52));
+                else
+                {
+                    // Adjust x and check result.
+                    real j = sign ? -OF : OF;
+                    x = (j + x) - j;
+                    msb = vi[MANTISSA_MSB];
+                    lsb = vi[MANTISSA_LSB];
+                    exp = ((msb >> 20) & 0x7ff) - 0x3ff;
+                    msb &= 0xfffff;
+                    msb |= 0x100000;
+
+                    if (exp < 0)
+                        result = 0;
+                    else if (exp < 20)
+                        result = cast(long) msb >> (20 - exp);
+                    else if (exp == 20)
+                        result = cast(long) msb;
+                    else
+                        result = (cast(long) msb << (exp - 20)) | (lsb >> (52 - exp));
+                }
+            }
+            else
+            {
+                // It is left implementation defined when the number is too large.
+                return cast(long) x;
+            }
+
+            return sign ? -result : result;
+        }
+        else static if (real.mant_dig == 64)
+        {
+            alias floatTraits!(real) F;
+            long result;
+
+            // Rounding limit when casting from real(80-bit) to ulong.
+            enum real OF = 9.22337203685477580800E18L;
+
+            ushort* vu = cast(ushort*)(&x);
+            uint* vi = cast(uint*)(&x);
+
+            // Find the exponent and sign
+            int exp = (vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+            int sign = (vu[F.EXPPOS_SHORT] >> 15) & 1;
+
+            if (exp < 63)
+            {
+                // Adjust x and check result.
+                real j = sign ? -OF : OF;
+                x = (j + x) - j;
+                exp = (vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+
+                version (LittleEndian)
+                {
+                    if (exp < 0)
+                        result = 0;
+                    else if (exp <= 31)
+                        result = vi[1] >> (31 - exp);
+                    else
+                        result = (cast(long) vi[1] << (exp - 31)) | (vi[0] >> (63 - exp));
+                }
+                else
+                {
+                    if (exp < 0)
+                        result = 0;
+                    else if (exp <= 31)
+                        result = vi[1] >> (31 - exp);
+                    else
+                        result = (cast(long) vi[1] << (exp - 31)) | (vi[2] >> (63 - exp));
+                }
+            }
+            else
+            {
+                // It is left implementation defined when the number is too large
+                // to fit in a 64bit long.
+                return cast(long) x;
+            }
+
+            return sign ? -result : result;
+        }
+        else
+        {
+            static assert(false, "Only 64-bit and 80-bit reals are supported by lrint()");
+        }
     }
 }
 
+unittest
+{
+    assert(lrint(4.5) == 4);
+    assert(lrint(5.5) == 6);
+    assert(lrint(-4.5) == -4);
+    assert(lrint(-5.5) == -6);
+
+    assert(lrint(int.max - 0.5) == 2147483646L);
+    assert(lrint(int.max + 0.5) == 2147483648L);
+    assert(lrint(int.min - 0.5) == -2147483648L);
+    assert(lrint(int.min + 0.5) == -2147483648L);
+}
+
 /*******************************************
  * Return the value of x rounded to the nearest integer.
  * If the fractional part of x is exactly 0.5, the return value is rounded to
@@ -2837,7 +3686,7 @@ struct FloatingPointControl
         roundDown      = 0x0400,
         roundUp        = 0x0800,
         roundToZero    = 0x0C00
-    };
+    }
 
     /** IEEE hardware exceptions.
      *  By default, all exceptions are masked (disabled).
@@ -2855,7 +3704,7 @@ struct FloatingPointControl
                              | invalidException,
         allExceptions      = severeExceptions | underflowException
                              | inexactException | subnormalException,
-    };
+    }
 
 private:
     enum ushort EXCEPTION_MASK = 0x3F;
@@ -4089,13 +4938,18 @@ Unqual!(Largest!(F, G)) pow(F, G)(F x, G y) @trusted pure nothrow
 
     static real impl(real x, real y) pure nothrow
     {
+        // Special cases.
         if (isNaN(y))
             return y;
-
-        if (y == 0)
-            return 1;           // even if x is $(NAN)
-        if (isNaN(x) && y != 0)
+        if (isNaN(x) && y != 0.0)
             return x;
+
+        // Even if x is NaN.
+        if (y == 0.0)
+            return 1.0;
+        if (y == 1.0)
+            return x;
+
         if (isInfinity(y))
         {
             if (fabs(x) > 1)
@@ -4120,17 +4974,16 @@ Unqual!(Largest!(F, G)) pow(F, G)(F x, G y) @trusted pure nothrow
         if (isInfinity(x))
         {
             if (signbit(x))
-            {   long i;
-
-                i = cast(long)y;
-                if (y > 0)
+            {
+                long i = cast(long)y;
+                if (y > 0.0)
                 {
                     if (i == y && i & 1)
                         return -F.infinity;
                     else
                         return F.infinity;
                 }
-                else if (y < 0)
+                else if (y < 0.0)
                 {
                     if (i == y && i & 1)
                         return -0.0;
@@ -4140,9 +4993,9 @@ Unqual!(Largest!(F, G)) pow(F, G)(F x, G y) @trusted pure nothrow
             }
             else
             {
-                if (y > 0)
+                if (y > 0.0)
                     return F.infinity;
-                else if (y < 0)
+                else if (y < 0.0)
                     return +0.0;
             }
         }
@@ -4150,17 +5003,16 @@ Unqual!(Largest!(F, G)) pow(F, G)(F x, G y) @trusted pure nothrow
         if (x == 0.0)
         {
             if (signbit(x))
-            {   long i;
-
-                i = cast(long)y;
-                if (y > 0)
+            {
+                long i = cast(long)y;
+                if (y > 0.0)
                 {
                     if (i == y && i & 1)
                         return -0.0;
                     else
                         return +0.0;
                 }
-                else if (y < 0)
+                else if (y < 0.0)
                 {
                     if (i == y && i & 1)
                         return -F.infinity;
@@ -4170,12 +5022,61 @@ Unqual!(Largest!(F, G)) pow(F, G)(F x, G y) @trusted pure nothrow
             }
             else
             {
-                if (y > 0)
+                if (y > 0.0)
                     return +0.0;
-                else if (y < 0)
+                else if (y < 0.0)
                     return F.infinity;
             }
         }
+        if (x == 1.0)
+            return 1.0;
+
+        if (y >= F.max)
+        {
+            if ((x > 0.0 && x < 1.0) || (x > -1.0 && x < 0.0))
+                return 0.0;
+            if (x > 1.0 || x < -1.0)
+                return F.infinity;
+        }
+        if (y <= -F.max)
+        {
+            if ((x > 0.0 && x < 1.0) || (x > -1.0 && x < 0.0))
+                return F.infinity;
+            if (x > 1.0 || x < -1.0)
+                return 0.0;
+        }
+
+        if (x >= F.max)
+        {
+            if (y > 0.0)
+                return F.infinity;
+            else
+                return 0.0;
+        }
+        if (x <= -F.max)
+        {
+            long i = cast(long)y;
+            if (y > 0.0)
+            {
+                if (i == y && i & 1)
+                    return -F.infinity;
+                else
+                    return F.infinity;
+            }
+            else if (y < 0.0)
+            {
+                if (i == y && i & 1)
+                    return -0.0;
+                else
+                    return +0.0;
+            }
+        }
+
+        // Integer power of x.
+        long iy = cast(long)y;
+        if (iy == y && fabs(y) < 32768.0)
+            return pow(x, iy);
+
         double sign = 1.0;
         if (x < 0)
         {
@@ -4201,7 +5102,13 @@ Unqual!(Largest!(F, G)) pow(F, G)(F x, G y) @trusted pure nothrow
         }
         else
         {
-            return sign * core.stdc.math.powl(x, y);
+            // If x > 0, x ^^ y == 2 ^^ ( y * log2(x) )
+            // TODO: This is not accurate in practice. A fast and accurate
+            // (though complicated) method is described in:
+            // "An efficient rounding boundary test for pow(x, y)
+            // in double precision", C.Q. Lauter and V. Lefèvre, INRIA (2007).
+            Float w = exp2(y * log2(x));
+            return sign * w;
         }
     }
     return impl(x, y);
@@ -4445,7 +5352,7 @@ in
 {
     // both x and y must have the same sign, and must not be NaN.
     assert(signbit(x) == signbit(y));
-    assert(x<>=0 && y<>=0);
+    assert(x==x && y==y);
 }
 body
 {
@@ -4579,6 +5486,7 @@ public:
  * Uses Horner's rule A(x) = $(SUB a, 0) + x($(SUB a, 1) + x($(SUB a, 2)
  *                         + x($(SUB a, 3) + ...)))
  * Params:
+ *      x =     the value to evaluate.
  *      A =     array of coefficients $(SUB a, 0), $(SUB a, 1), etc.
  */
 real poly(real x, const real[] A) @trusted pure nothrow
@@ -4725,7 +5633,7 @@ unittest
 {
     debug (math) printf("math.poly.unittest\n");
     real x = 3.1;
-    static real pp[] = [56.1, 32.7, 6];
+    static real[] pp = [56.1, 32.7, 6];
 
     assert( poly(x, pp) == (56.1L + (32.7L + 6L * x) * x) );
 }
@@ -4909,3 +5817,10 @@ unittest
     real r = tan(-2.0L);
     assert(fabs(r - 2.18504f) < .00001);
 }
+
+pure @safe nothrow unittest
+{
+    // issue 6381: floor/ceil should be usable in pure function.
+    auto x = floor(1.2);
+    auto y = ceil(1.2);
+}
diff --git a/std/md5.d b/std/md5.d
index 5ebac2ef7..40939ff57 100644
--- a/std/md5.d
+++ b/std/md5.d
@@ -177,12 +177,14 @@ unittest
  */
 struct MD5_CTX
 {
-    uint state[4] =                                   /* state (ABCD) */
+    private import core.stdc.string : memcpy, memset;
+
+    uint[4] state =                                   /* state (ABCD) */
     /* magic initialization constants */
     [0x67452301,0xefcdab89,0x98badcfe,0x10325476];
 
     ulong count;        /* number of bits, modulo 2^64 */
-    ubyte buffer[64];   /* input buffer */
+    ubyte[64] buffer;   /* input buffer */
 
     static ubyte[64] PADDING =
     [
@@ -269,7 +271,7 @@ struct MD5_CTX
       /* Transform as many times as possible. */
       if (inputLen >= partLen)
       {
-            std.c.string.memcpy(&buffer[index], input.ptr, partLen);
+            core.stdc.string.memcpy(&buffer[index], input.ptr, partLen);
             transform (buffer.ptr);
 
             for (i = partLen; i + 63 < inputLen; i += 64)
@@ -282,7 +284,7 @@ struct MD5_CTX
 
       /* Buffer remaining input */
       if (inputLen - i)
-            std.c.string.memcpy(&buffer[index], &input[i], inputLen-i);
+            core.stdc.string.memcpy(&buffer[index], &input[i], inputLen-i);
     }
 
     /** MD5 finalization. Ends an MD5 message-digest operation, writing the
@@ -290,7 +292,7 @@ struct MD5_CTX
      */
     void finish(ref ubyte[16] digest)         /* message digest */
     {
-      ubyte bits[8] = void;
+      ubyte[8] bits = void;
       uint index, padLen;
 
       /* Save number of bits */
@@ -311,7 +313,7 @@ struct MD5_CTX
       digest[12 .. 16] = nativeToLittleEndian(state[3])[];
 
       /* Zeroize sensitive information. */
-      std.c.string.memset (&this, 0, MD5_CTX.sizeof);
+      core.stdc.string.memset (&this, 0, MD5_CTX.sizeof);
     }
 
     /* MD5 basic transformation. Transforms state based on block.
diff --git a/std/mmfile.d b/std/mmfile.d
index 7af69b035..533baa6a2 100644
--- a/std/mmfile.d
+++ b/std/mmfile.d
@@ -218,7 +218,7 @@ class MmFile
                 assert(0);
             }
 
-            if (filename)
+            if (filename.ptr)
             {
                 auto namez = std.utf.toUTF16z(filename);
                 hFile = CreateFileW(namez,
@@ -228,37 +228,41 @@ class MmFile
                         dwCreationDisposition,
                         FILE_ATTRIBUTE_NORMAL,
                         cast(HANDLE)null);
-                if (hFile == INVALID_HANDLE_VALUE)
-                    goto err1;
             }
             else
                 hFile = null;
 
-            int hi = cast(int)(size>>32);
-            hFileMap = CreateFileMappingA(hFile, null, flProtect,
-                    hi, cast(uint)size, null);
-            if (hFileMap == null)               // mapping failed
-                goto err1;
-
-            if (size == 0)
+            hFileMap = null;
+            if (hFile != INVALID_HANDLE_VALUE)
             {
-                uint sizehi;
-                uint sizelow = GetFileSize(hFile,&sizehi);
-                size = (cast(ulong)sizehi << 32) + sizelow;
+                int hi = cast(int)(size>>32);
+                hFileMap = CreateFileMappingA(hFile, null, flProtect,
+                        hi, cast(uint)size, null);
             }
-            this.size = size;
+            if (hFileMap != null)               // mapping didn't fail
+            {
 
-            size_t initial_map = (window && 2*window 1)
+                        charset = mct.captures[1].idup;
+                }
+
+                if (!m.empty && callback !is null)
+                    callback(fieldName, m.captures[2]);
+                headersIn[fieldName] = m.captures[2].idup;
+            };
+
+            curl.onReceiveHeader = dg;
+        }
     }
 
     private RefCounted!Impl p;
@@ -2151,6 +2225,7 @@ struct HTTP
         p.curl.set(CurlOption.url, url);
     }
 
+    /// Set the CA certificate bundle file to use for SSL peer verification
     @property void caInfo(const(char)[] caFile)
     {
         p.curl.set(CurlOption.cainfo, caFile);
@@ -2551,55 +2626,7 @@ struct HTTP
     @property void onReceiveHeader(void delegate(in char[] key,
                                                  in char[] value) callback)
     {
-        // Wrap incoming callback in order to separate http status line from
-        // http headers.  On redirected requests there may be several such
-        // status lines. The last one is the one recorded.
-        auto dg = (in char[] header)
-        {
-            if (header.empty)
-            {
-                // header delimiter
-                return;
-            }
-            if (header.startsWith("HTTP/"))
-            {
-                string[string] empty;
-                p.headersIn = empty; // clear
-
-                auto m = match(header, regex(r"^HTTP/(\d+)\.(\d+) (\d+) (.*)$"));
-                if (m.empty)
-                {
-                    // Invalid status line
-                }
-                else
-                {
-                    p.status.majorVersion = to!ushort(m.captures[1]);
-                    p.status.minorVersion = to!ushort(m.captures[2]);
-                    p.status.code = to!ushort(m.captures[3]);
-                    p.status.reason = m.captures[4].idup;
-                    if (p.onReceiveStatusLine != null)
-                        p.onReceiveStatusLine(p.status);
-                }
-                return;
-            }
-
-            // Normal http header
-            auto m = match(cast(char[]) header, regex("(.*?): (.*)$"));
-
-            auto fieldName = m.captures[1].toLower().idup;
-            if (fieldName == "content-type")
-            {
-                auto mct = match(cast(char[]) m.captures[2],
-                                 regex("charset=([^;]*)"));
-                if (!mct.empty && mct.captures.length > 1)
-                    p.charset = mct.captures[1].idup;
-            }
-
-            if (!m.empty && callback !is null)
-                callback(fieldName, m.captures[2]);
-            p.headersIn[fieldName] = m.captures[2].idup;
-        };
-        p.curl.onReceiveHeader = dg;
+        p.onReceiveHeader = callback;
     }
 
     /**
@@ -3011,11 +3038,13 @@ struct FTP
         p.curl.set(CurlOption.postquote, p.commands);
     }
 
+    /// Connection encoding. Defaults to ISO-8859-1.
     @property void encoding(string name)
     {
         p.encoding = name;
     }
 
+    /// ditto
     @property string encoding()
     {
         return p.encoding;
@@ -3060,6 +3089,23 @@ struct SMTP
                 curl.shutdown();
         }
         Curl curl;
+
+        @property void message(string msg)
+        {
+            auto _message = msg;
+            /**
+                This delegate reads the message text and copies it.
+            */
+            curl.onSend = delegate size_t(void[] data)
+            {
+                if (!msg.length) return 0;
+                auto m = cast(void[])msg;
+                size_t to_copy = min(data.length, _message.length);
+                data[0..to_copy] = (cast(void[])_message)[0..to_copy];
+                _message = _message[to_copy..$];
+                return to_copy;
+            };
+        }
     }
 
     private RefCounted!Impl p;
@@ -3329,19 +3375,7 @@ struct SMTP
 
     @property void message(string msg)
     {
-        auto _message = msg;
-        /**
-            This delegate reads the message text and copies it.
-        */
-        p.curl.onSend = delegate size_t(void[] data)
-        {
-            if (!msg.length) return 0;
-            auto m = cast(void[])msg;
-            size_t to_copy = min(data.length, _message.length);
-            data[0..to_copy] = (cast(void[])_message)[0..to_copy];
-            _message = _message[to_copy..$];
-            return to_copy;
-        };
+        p.message = msg;
     }
 }
 
@@ -3357,6 +3391,7 @@ class CurlException : Exception
             line = The line number where the exception occurred.
             next = The previous exception in the chain of exceptions, if any.
       +/
+    @safe pure nothrow
     this(string msg,
          string file = __FILE__,
          size_t line = __LINE__,
@@ -3378,6 +3413,7 @@ class CurlTimeoutException : CurlException
             line = The line number where the exception occurred.
             next = The previous exception in the chain of exceptions, if any.
       +/
+    @safe pure nothrow
     this(string msg,
          string file = __FILE__,
          size_t line = __LINE__,
@@ -3394,6 +3430,11 @@ alias CURLcode CurlCode;
   Wrapper to provide a better interface to libcurl than using the plain C API.
   It is recommended to use the $(D HTTP)/$(D FTP) etc. structs instead unless
   raw access to libcurl is needed.
+
+  Warning: This struct uses interior pointers for callbacks. Only allocate it
+  on the stack if you never move or copy it. This also means passing by reference
+  when passing Curl to other functions. Otherwise always allocate on
+  the heap. 
 */
 struct Curl
 {
@@ -3507,6 +3548,8 @@ struct Curl
 
     private string errorString(CurlCode code)
     {
+        import core.stdc.string : strlen;
+
         auto msgZ = curl_easy_strerror(code);
         // doing the following (instead of just using std.conv.to!string) avoids 1 allocation
         return format("%s on handle %s", msgZ[0 .. core.stdc.string.strlen(msgZ)], handle);
diff --git a/std/net/isemail.d b/std/net/isemail.d
index 3324a27f8..225644de9 100644
--- a/std/net/isemail.d
+++ b/std/net/isemail.d
@@ -69,6 +69,7 @@ EmailStatus isEmail (Char) (const(Char)[] email, CheckDns checkDNS = CheckDns.no
 {
     alias const(Char)[] tstring;
 
+    enum defaultThreshold = 16;
     int threshold;
     bool diagnose;
 
@@ -84,7 +85,7 @@ EmailStatus isEmail (Char) (const(Char)[] email, CheckDns checkDNS = CheckDns.no
 
         switch (errorLevel)
         {
-            case EmailStatusCode.warning: threshold = threshold; break;
+            case EmailStatusCode.warning: threshold = defaultThreshold; break;
             case EmailStatusCode.error: threshold = EmailStatusCode.valid; break;
             default: threshold = errorLevel;
         }
@@ -734,7 +735,7 @@ EmailStatus isEmail (Char) (const(Char)[] email, CheckDns checkDNS = CheckDns.no
             returnStatus ~= EmailStatusCode.rfc5321TopLevelDomainNumeric;
     }
 
-    returnStatus = array(std.algorithm.uniq(returnStatus));
+    returnStatus = array(uniq(returnStatus));
     auto finalStatus = returnStatus.max();
 
     if (returnStatus.length != 1)
@@ -1670,8 +1671,6 @@ enum EmailStatusCode
 
 private:
 
-enum threshold = 16;
-
 // Email parts for the isEmail function
 enum EmailPart
 {
@@ -1740,6 +1739,8 @@ enum AsciiToken
  */
 T max (T) (T[] arr)
 {
+    import std.algorithm/* : max*/;
+
     auto max = arr.front;
 
     foreach (i ; 0 .. arr.length - 1)
diff --git a/std/numeric.d b/std/numeric.d
index 63bef31d1..44c044f1d 100644
--- a/std/numeric.d
+++ b/std/numeric.d
@@ -714,7 +714,7 @@ T findRoot(T, R)(scope R delegate(T) f, T a, T b)
 {
     auto r = findRoot(f, a, b, f(a), f(b), (T lo, T hi){ return false; });
     // Return the first value if it is smaller or NaN
-    return fabs(r[2]) !> fabs(r[3]) ? r[0] : r[1];
+    return !(fabs(r[2]) > fabs(r[3])) ? r[0] : r[1];
 }
 
 /** Find root of a real function f(x) by bracketing, allowing the
@@ -753,7 +753,7 @@ T findRoot(T, R)(scope R delegate(T) f, T a, T b)
 Tuple!(T, T, R, R) findRoot(T,R)(scope R delegate(T) f, T ax, T bx, R fax, R fbx,
     scope bool delegate(T lo, T hi) tolerance)
 in {
-    assert(ax<>=0 && bx<>=0, "Limits must not be NaN");
+    assert(!ax.isNaN && !bx.isNaN, "Limits must not be NaN");
     assert(signbit(fax) != signbit(fbx), "Parameters must bracket the root.");
 }
 body {
@@ -777,7 +777,7 @@ body {
     void bracket(T c)
     {
         T fc = f(c);
-        if (fc !<> 0) { // Exact solution, or NaN
+        if (fc == 0 || fc.isNaN) { // Exact solution, or NaN
             a = c;
             fa = fc;
             d = c;
@@ -847,11 +847,11 @@ body {
     }
 
     // On the first iteration we take a secant step:
-    if (fa !<> 0) {
+    if (fa == 0 || fa.isNaN) {
         done = true;
         b = a;
         fb = fa;
-    } else if (fb !<> 0) {
+    } else if (fb == 0 || fb.isNaN) {
         done = true;
         a = b;
         fa = fb;
@@ -891,7 +891,7 @@ whileloop:
                 real d32 = (d31 - q21) * fd / (fd - fa);
                 real q33 = (d32 - q22) * fa / (fe - fa);
                 c = a + (q31 + q32 + q33);
-                if (c!<>=0 || (c <= a) || (c >= b)) {
+                if (c.isNaN || (c <= a) || (c >= b)) {
                     // DAC: If the interpolation predicts a or b, it's
                     // probable that it's the actual root. Only allow this if
                     // we're already close to the root.
@@ -909,7 +909,7 @@ whileloop:
                 // DAC: Alefeld doesn't explain why the number of newton steps
                 // should vary.
                 c = newtonQuadratic(distinct ? 3 : 2);
-                if(c!<>=0 || (c <= a) || (c >= b)) {
+                if(c.isNaN || (c <= a) || (c >= b)) {
                     // Failure, try a secant step:
                     c = secant_interpolate(a, b, fa, fb);
                 }
@@ -936,7 +936,7 @@ whileloop:
         c = u - 2 * (fu / (fb - fa)) * (b - a);
         // DAC: If the secant predicts a value equal to an endpoint, it's
         // probably false.
-        if(c==a || c==b || c!<>=0 || fabs(c - u) > (b - a) / 2) {
+        if(c==a || c==b || c.isNaN || fabs(c - u) > (b - a) / 2) {
             if ((a-b) == a || (b-a) == b) {
                 if ( (a>0 && b<0) || (a<0 && b>0) ) c = 0;
                 else {
@@ -999,7 +999,7 @@ unittest
     void testFindRoot(real delegate(real) f, real x1, real x2) {
         numCalls=0;
         ++numProblems;
-        assert(x1<>=0 && x2<>=0);
+        assert(!x1.isNaN && !x2.isNaN);
         assert(signbit(x1) != signbit(x2));
         auto result = findRoot(f, x1, x2, f(x1), f(x2),
           (real lo, real hi) { return false; });
@@ -2068,7 +2068,7 @@ unittest
             ["nyuk", "I", "have", "no", "chocolate", "giba"],
             ["wyda", "I", "have", "I", "have", "have", "I", "have", "hehe"],
             0.5);
-    double witness[] = [ 7.0, 4.03125, 0, 0 ];
+    double[] witness = [ 7.0, 4.03125, 0, 0 ];
     foreach (e; sim)
     {
         //writeln(e);
@@ -2217,10 +2217,10 @@ private:
             recurseRange.popHalf();
             slowFourier2(recurseRange, buf[$ / 2..$]);
         }
-        
+
         butterfly(buf);
     }
-    
+
     // This algorithm works by performing the even and odd parts of our FFT
     // using the "two for the price of one" method mentioned at
     // http://www.engineeringproductivitytools.com/stuff/T0001/PT10.HTM#Head521
@@ -2232,7 +2232,7 @@ private:
         assert(isPowerOfTwo(range.length));
     } body {
         alias ElementType!R E;
-        
+
         // Converts odd indices of range to the imaginary components of
         // a range half the size.  The even indices become the real components.
         static if(isArray!R && isFloatingPoint!E) {
@@ -2240,57 +2240,57 @@ private:
             // cheap way to convert.  This is a common case, so take advantage.
             auto oddsImag = cast(Complex!E[]) range;
         } else {
-            // General case:  Use a higher order range.  We can assume 
+            // General case:  Use a higher order range.  We can assume
             // source.length is even because it has to be a power of 2.
             static struct OddToImaginary {
                 R source;
                 alias Complex!(CommonType!(E, typeof(buf[0].re))) C;
-                
+
                 @property {
                     C front() {
                         return C(source[0], source[1]);
                     }
-                
+
                     C back() {
                         immutable n = source.length;
                         return C(source[n - 2], source[n - 1]);
                     }
-                    
+
                     typeof(this) save() {
                         return typeof(this)(source.save);
                     }
-                    
+
                     bool empty() {
                         return source.empty;
                     }
-                    
+
                     size_t length() {
                         return source.length / 2;
                     }
                 }
-                
+
                 void popFront() {
                     source.popFront();
                     source.popFront();
                 }
-                
+
                 void popBack() {
                     source.popBack();
                     source.popBack();
                 }
-                
+
                 C opIndex(size_t index) {
                     return C(source[index * 2], source[index * 2 + 1]);
                 }
-                
+
                 typeof(this) opSlice(size_t lower, size_t upper) {
                     return typeof(this)(source[lower * 2..upper * 2]);
                 }
             }
-            
+
             auto oddsImag = OddToImaginary(range);
         }
-        
+
         fft(oddsImag, buf[0..$ / 2]);
         auto evenFft = buf[0..$ / 2];
         auto oddFft = buf[$ / 2..$];
@@ -2299,7 +2299,7 @@ private:
         oddFft[0].im = 0;
         evenFft[0].im = 0;
         // evenFft[0].re is already right b/c it's aliased with buf[0].re.
-        
+
         foreach(k; 1..halfN / 2 + 1) {
             immutable bufk = buf[k];
             immutable bufnk = buf[buf.length / 2 - k];
@@ -2307,7 +2307,7 @@ private:
             evenFft[halfN - k].re = evenFft[k].re;
             evenFft[k].im = 0.5 * (bufk.im - bufnk.im);
             evenFft[halfN - k].im = -evenFft[k].im;
-            
+
             oddFft[k].re = 0.5 * (bufk.im + bufnk.im);
             oddFft[halfN - k].re = oddFft[k].re;
             oddFft[k].im = 0.5 * (bufnk.re - bufk.re);
@@ -2316,8 +2316,8 @@ private:
 
         butterfly(buf);
     }
-    
-    void butterfly(R)(R buf) const 
+
+    void butterfly(R)(R buf) const
     in {
         assert(isPowerOfTwo(buf.length));
     } body {
@@ -2339,9 +2339,9 @@ private:
 
         immutable halfLen = n / 2;
 
-        // This loop is unrolled and the two iterations are nterleaved relative
-        // to the textbook FFT to increase ILP.  This gives roughly 5% speedups
-        // on DMD.
+        // This loop is unrolled and the two iterations are interleaved
+        // relative to the textbook FFT to increase ILP.  This gives roughly 5%
+        // speedups on DMD.
         for(size_t k = 0; k < halfLen; k += 2) {
             immutable cosTwiddle1 = cosFromLookup(k);
             immutable sinTwiddle1 = negSinFromLookup(k);
@@ -2440,8 +2440,8 @@ private:
     }
 
 public:
-    /**Create an $(D Fft) object for computing fast Fourier transforms of 
-     * power of two sizes of $(D size) or smaller.  $(D size) must be a 
+    /**Create an $(D Fft) object for computing fast Fourier transforms of
+     * power of two sizes of $(D size) or smaller.  $(D size) must be a
      * power of two.
      */
     this(size_t size) {
@@ -2464,9 +2464,12 @@ public:
      *
      * Note:  Pure real FFTs are automatically detected and the relevant
      *        optimizations are performed.
-     * 
+     *
      * Returns:  An array of complex numbers representing the transformed data in
      *           the frequency domain.
+     *
+     * Conventions: The exponent is negative and the factor is one,
+     *              i.e., output[j] := sum[ exp(-2 PI i j k / N) input[k] ].
      */
     Complex!F[] fft(F = double, R)(R range) const
     if(isFloatingPoint!F && isRandomAccessRange!R) {
@@ -2506,7 +2509,7 @@ public:
             alias ElementType!R E;
             static if(is(E : real)) {
                 return fftImplPureReal(range, buf);
-            } else {                
+            } else {
                 static if(is(R : Stride!R)) {
                     return fftImpl(range, buf);
                 } else {
@@ -2523,6 +2526,9 @@ public:
      * the same compile-time interface.
      *
      * Returns:  The time-domain signal.
+     *
+     * Conventions: The exponent is positive and the factor is 1/N, i.e.,
+     *              output[j] := (1 / N) sum[ exp(+2 PI i j k / N) input[k] ].
      */
     Complex!F[] inverseFft(F = double, R)(R range) const
     if(isRandomAccessRange!R && isComplexLike!(ElementType!R) && isFloatingPoint!F) {
@@ -2611,13 +2617,13 @@ unittest {
         [36.0, -4, -4, -4, -4, -4, -4, -4]));
     assert(approxEqual(map!"a.im"(fft1),
         [0, 9.6568, 4, 1.6568, 0, -1.6568, -4, -9.6568]));
-    
+
     auto fft1Retro = fft(retro(arr));
     assert(approxEqual(map!"a.re"(fft1Retro),
         [36.0, 4, 4, 4, 4, 4, 4, 4]));
     assert(approxEqual(map!"a.im"(fft1Retro),
-        [0, -9.6568, -4, -1.6568, 0, 1.6568, 4, 9.6568]));  
-        
+        [0, -9.6568, -4, -1.6568, 0, 1.6568, 4, 9.6568]));
+
     auto fft1Float = fft(to!(float[])(arr));
     assert(approxEqual(map!"a.re"(fft1), map!"a.re"(fft1Float)));
     assert(approxEqual(map!"a.im"(fft1), map!"a.im"(fft1Float)));
diff --git a/std/outbuffer.d b/std/outbuffer.d
index 235de7571..774fa475d 100644
--- a/std/outbuffer.d
+++ b/std/outbuffer.d
@@ -37,7 +37,7 @@ private
 
 class OutBuffer
 {
-    ubyte data[];
+    ubyte[] data;
     size_t offset;
 
     invariant()
@@ -310,10 +310,7 @@ class OutBuffer
     {
         version (Win64)
         {
-            va_list ap;
-            ap = cast(va_list)&format;
-            ap += format.sizeof;
-            vprintf(format, ap);
+            vprintf(format, _argptr);
         }
         else version (X86_64)
         {
diff --git a/std/parallelism.d b/std/parallelism.d
index 244babfab..df4138f65 100644
--- a/std/parallelism.d
+++ b/std/parallelism.d
@@ -115,8 +115,8 @@ version(Windows)
             {
                 WORD wProcessorArchitecture;
                 WORD wReserved;
-            };
-        };
+            }
+        }
         DWORD     dwPageSize;
         LPVOID    lpMinimumApplicationAddress;
         LPVOID    lpMaximumApplicationAddress;
@@ -1431,7 +1431,7 @@ public:
     */
     this(size_t nWorkers) @trusted
     {
-        synchronized(TaskPool.classinfo)
+        synchronized(typeid(TaskPool))
         {
             instanceStartIndex = nextInstanceIndex;
 
@@ -3272,7 +3272,7 @@ terminating the main thread.
 
     if(!initialized)
     {
-        synchronized(TaskPool.classinfo)
+        synchronized(typeid(TaskPool))
         {
             if(!pool)
             {
@@ -3364,6 +3364,7 @@ private void submitAndExecute(
 
     alias typeof(scopedTask(doIt)) PTask;
     import core.stdc.stdlib;
+    import core.stdc.string : memcpy;
 
     // The logical thing to do would be to just use alloca() here, but that
     // causes problems on Windows for reasons that I don't understand
@@ -4102,7 +4103,7 @@ unittest
         auto tSlow = task!slowFun();
         pool1.put(tSlow);
         pool1.finish();
-        tSlow.yieldForce();
+        tSlow.yieldForce;
         // Can't assert that pool1.status == PoolState.stopNow because status
         // doesn't change until after the "done" flag is set and the waiting
         // thread is woken up.
diff --git a/std/path.d b/std/path.d
index 113dffd8a..4e2b15aff 100644
--- a/std/path.d
+++ b/std/path.d
@@ -54,6 +54,7 @@ import std.algorithm;
 import std.array;
 import std.conv;
 import std.file: getcwd;
+import std.range;
 import std.string;
 import std.traits;
 
@@ -760,6 +761,9 @@ unittest
     extension is simply appended to the filename.  Including a leading dot
     in $(D ext) is optional.
 
+    If the extension is empty, this function is equivalent to
+    $(LREF stripExtension).
+
     This function normally allocates a new string (the possible exception
     being the case when path is immutable and doesn't already have an
     extension).
@@ -768,6 +772,7 @@ unittest
     ---
     assert (setExtension("file", "ext")      == "file.ext");
     assert (setExtension("file", ".ext")     == "file.ext");
+    assert (setExtension("file.old", "")     == "file");
     assert (setExtension("file.old", "new")  == "file.new");
     assert (setExtension("file.old", ".new") == "file.new");
     ---
@@ -776,10 +781,10 @@ immutable(Unqual!C1)[] setExtension(C1, C2)(in C1[] path, in C2[] ext)
     @trusted pure nothrow
     if (isSomeChar!C1 && !is(C1 == immutable) && is(Unqual!C1 == Unqual!C2))
 {
-    if (ext.length > 0 && ext[0] == '.')
-        return cast(typeof(return))(stripExtension(path)~ext);
-    else
+    if (ext.length > 0 && ext[0] != '.')
         return cast(typeof(return))(stripExtension(path)~'.'~ext);
+    else
+        return cast(typeof(return))(stripExtension(path)~ext);
 }
 
 ///ditto
@@ -787,6 +792,9 @@ immutable(C1)[] setExtension(C1, C2)(immutable(C1)[] path, const(C2)[] ext)
     @trusted pure nothrow
     if (isSomeChar!C1 && is(Unqual!C1 == Unqual!C2))
 {
+    if (ext.length == 0)
+        return stripExtension(path);
+
     // Optimised for the case where path is immutable and has no extension
     if (ext.length > 0 && ext[0] == '.') ext = ext[1 .. $];
     auto i = extSeparatorPos(path);
@@ -829,8 +837,11 @@ unittest
 
     static assert (setExtension("file"w.dup, "ext"w) == "file.ext");
     static assert (setExtension("file.old"d.dup, "new"d) == "file.new");
-}
 
+    // Issue 10601
+    assert (setExtension("file", "") == "file");
+    assert (setExtension("file.ext", "") == "file");
+}
 
 
 
@@ -886,56 +897,113 @@ unittest
 }
 
 
+/** Combines one or more path segments.
 
+    This function takes a set of path segments, given as an input
+    range of string elements or as a set of string arguments,
+    and concatenates them with each other.  Directory separators
+    are inserted between segments if necessary.  If any of the
+    path segments are absolute (as defined by $(LREF isAbsolute)), the
+    preceding segments will be dropped.
 
-/** Combines one or more path components.
-
-    The given path components are concatenated with each other,
-    and if necessary, directory separators are inserted between
-    them. If any of the path components are rooted (as defined by
-    $(LREF isRooted)) the preceding path components will be dropped.
+    On Windows, if one of the path segments are rooted, but not absolute
+    (e.g. $(D `\foo`)), all preceding path segments down to the previous
+    root will be dropped.  (See below for an example.)
 
     This function always allocates memory to hold the resulting path.
+    The variadic overload is guaranteed to only perform a single
+    allocation, as is the range version if $(D paths) is a forward
+    range.
+*/
+immutable(ElementEncodingType!(ElementType!Range))[]
+    buildPath(Range)(Range segments)
+        if (isInputRange!Range && isSomeString!(ElementType!Range))
+{
+    if (segments.empty) return null;
 
-    Examples:
-    ---
+    // If this is a forward range, we can pre-calculate a maximum length.
+    static if (isForwardRange!Range)
+    {
+        auto segments2 = segments.save;
+        size_t precalc = 0;
+        foreach (segment; segments2) precalc += segment.length + 1;
+    }
+    // Otherwise, just venture a guess and resize later if necessary.
+    else size_t precalc = 255;
+
+    auto buf = new Unqual!(ElementEncodingType!(ElementType!Range))[](precalc);
+    size_t pos = 0;
+    foreach (segment; segments)
+    {
+        if (segment.empty) continue;
+        static if (!isForwardRange!Range)
+        {
+            immutable neededLength = pos + segment.length + 1;
+            if (buf.length < neededLength)
+                buf.length = reserve(buf, neededLength + buf.length/2);
+        }
+        if (pos > 0)
+        {
+            if (isRooted(segment))
+            {
+                version (Posix)
+                {
+                    pos = 0;
+                }
+                else version (Windows)
+                {
+                    if (isAbsolute(segment))
+                        pos = 0;
+                    else
+                    {
+                        pos = rootName(buf[0 .. pos]).length;
+                        if (pos > 0 && isDirSeparator(buf[pos-1])) --pos;
+                    }
+                }
+            }
+            else if (!isDirSeparator(buf[pos-1]))
+                buf[pos++] = dirSeparator[0];
+        }
+        buf[pos .. pos + segment.length] = segment[];
+        pos += segment.length;
+    }
+    static U trustedCast(U, V)(V v) @trusted pure nothrow { return cast(U) v; }
+    return trustedCast!(typeof(return))(buf[0 .. pos]);
+}
+
+/// ditto
+immutable(C)[] buildPath(C)(const(C[])[] paths...)
+    @safe pure nothrow
+    if (isSomeChar!C)
+{
+    return buildPath!(typeof(paths))(paths);
+}
+
+///
+unittest
+{
     version (Posix)
     {
         assert (buildPath("foo", "bar", "baz") == "foo/bar/baz");
-        assert (buildPath("/foo/", "bar")      == "/foo/bar");
+        assert (buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
         assert (buildPath("/foo", "/bar")      == "/bar");
     }
 
     version (Windows)
     {
         assert (buildPath("foo", "bar", "baz") == `foo\bar\baz`);
-        assert (buildPath(`c:\foo`, "bar")    == `c:\foo\bar`);
-        assert (buildPath("foo", `d:\bar`)    == `d:\bar`);
-        assert (buildPath("foo", `\bar`)      == `\bar`);
+        assert (buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
+        assert (buildPath("foo", `d:\bar`)     == `d:\bar`);
+        assert (buildPath("foo", `\bar`)       == `\bar`);
+        assert (buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
     }
-    ---
-*/
-immutable(C)[] buildPath(C)(const(C[])[] paths...)
-    @safe pure //TODO: nothrow (because of reduce() and to())
-    if (isSomeChar!C)
-{
-    static typeof(return) joinPaths(const(C)[] lhs, const(C)[] rhs)
-        @trusted pure //TODO: nothrow (because of to())
-    {
-        if (rhs.empty) return to!(typeof(return))(lhs);
-        if (lhs.empty || isRooted(rhs)) return to!(typeof(return))(rhs);
-        if (isDirSeparator(lhs[$-1]) || isDirSeparator(rhs[0]))
-            return cast(typeof(return))(lhs ~ rhs);
-        else
-            return cast(typeof(return))(lhs ~ dirSeparator ~ rhs);
-    }
-
-    return to!(typeof(return))(reduce!joinPaths(paths));
 }
 
-
-unittest
+unittest // non-documented
 {
+    // ir() wraps an array in a plain (i.e. non-forward) input range, so that
+    // we can test both code paths
+    InputRange!(C[]) ir(C)(C[][] p...) { return inputRangeObject(p); }
     version (Posix)
     {
         assert (buildPath("foo") == "foo");
@@ -955,6 +1023,23 @@ unittest
 
         static assert (buildPath("foo", "bar", "baz") == "foo/bar/baz");
         static assert (buildPath("foo", "/bar", "baz") == "/bar/baz");
+
+        // The following are mostly duplicates of the above, except that the
+        // range version does not accept mixed constness.
+        assert (buildPath(ir("foo")) == "foo");
+        assert (buildPath(ir("/foo/")) == "/foo/");
+        assert (buildPath(ir("foo", "bar")) == "foo/bar");
+        assert (buildPath(ir("foo", "bar", "baz")) == "foo/bar/baz");
+        assert (buildPath(ir("foo/".dup, "bar".dup)) == "foo/bar");
+        assert (buildPath(ir("foo///".dup, "bar".dup)) == "foo///bar");
+        assert (buildPath(ir("/foo"w, "bar"w)) == "/foo/bar");
+        assert (buildPath(ir("foo"w.dup, "/bar"w.dup)) == "/bar");
+        assert (buildPath(ir("foo"w.dup, "bar/"w.dup)) == "foo/bar/");
+        assert (buildPath(ir("/"d, "foo"d)) == "/foo");
+        assert (buildPath(ir(""d.dup, "foo"d.dup)) == "foo");
+        assert (buildPath(ir("foo"d, ""d)) == "foo");
+        assert (buildPath(ir("foo", "bar", "baz")) == "foo/bar/baz");
+        assert (buildPath(ir("foo"w.dup, "/bar"w.dup, "baz"w.dup)) == "/bar/baz");
     }
     version (Windows)
     {
@@ -964,10 +1049,32 @@ unittest
         assert (buildPath("foo", `\bar`) == `\bar`);
         assert (buildPath(`c:\foo`, "bar") == `c:\foo\bar`);
         assert (buildPath("foo"w, `d:\bar`w.dup) ==  `d:\bar`);
+        assert (buildPath(`c:\foo\bar`, `\baz`) == `c:\baz`);
+        assert (buildPath(`\\foo\bar\baz`d, `foo`d, `\bar`d) == `\\foo\bar\bar`d);
 
         static assert (buildPath("foo", "bar", "baz") == `foo\bar\baz`);
         static assert (buildPath("foo", `c:\bar`, "baz") == `c:\bar\baz`);
+
+        assert (buildPath(ir("foo")) == "foo");
+        assert (buildPath(ir(`\foo/`)) == `\foo/`);
+        assert (buildPath(ir("foo", "bar", "baz")) == `foo\bar\baz`);
+        assert (buildPath(ir("foo", `\bar`)) == `\bar`);
+        assert (buildPath(ir(`c:\foo`, "bar")) == `c:\foo\bar`);
+        assert (buildPath(ir("foo"w.dup, `d:\bar`w.dup)) ==  `d:\bar`);
+        assert (buildPath(ir(`c:\foo\bar`, `\baz`)) == `c:\baz`);
+        assert (buildPath(ir(`\\foo\bar\baz`d, `foo`d, `\bar`d)) == `\\foo\bar\bar`d);
     }
+
+    // Test that allocation works as it should.
+    auto manyShort = "aaa".repeat(1000).array();
+    auto manyShortCombined = join(manyShort, dirSeparator);
+    assert (buildPath(manyShort) == manyShortCombined);
+    assert (buildPath(ir(manyShort)) == manyShortCombined);
+
+    auto fewLong = 'b'.repeat(500).array().repeat(10).array();
+    auto fewLongCombined = join(fewLong, dirSeparator);
+    assert (buildPath(fewLong) == fewLongCombined);
+    assert (buildPath(ir(fewLong)) == fewLongCombined);
 }
 
 unittest
@@ -985,7 +1092,6 @@ unittest
 }
 
 
-
 /** Performs the same task as $(LREF buildPath),
     while at the same time resolving current/parent directory
     symbols ($(D ".") and $(D "..")) and removing superfluous
@@ -1438,9 +1544,9 @@ auto pathSplitter(C)(const(C)[] path)  @safe pure nothrow
     static struct PathSplitter
     {
     @safe pure nothrow:
-        @property empty() const { return _empty; }
+        @property bool empty() const { return _empty; }
 
-        @property front() const
+        @property const(C)[] front() const
         {
             assert (!empty, "PathSplitter: called front() on empty range");
             return _front;
@@ -1471,7 +1577,7 @@ auto pathSplitter(C)(const(C)[] path)  @safe pure nothrow
             }
         }
 
-        @property back() const
+        @property const(C)[] back() const
         {
             assert (!empty, "PathSplitter: called back() on empty range");
             return _back;
@@ -1624,6 +1730,10 @@ unittest
     {
         assert (equal(pathSplitter("/foo/bar".dup), ["/", "foo", "bar"]));
     });
+
+    // Bugzilla 11691
+    // front should return a mutable array of const elements
+    static assert(is(typeof(pathSplitter!char(null).front) == const(char)[]));
 }
 
 
@@ -1789,6 +1899,7 @@ unittest
         assert (absolutePath(`some\file`, `c:\foo\bar`)    == `c:\foo\bar\some\file`);
         assert (absolutePath(`..\file`, `c:\foo\bar`)      == `c:\foo\bar\..\file`);
         assert (absolutePath(`c:\some\file`, `c:\foo\bar`) == `c:\some\file`);
+        assert (absolutePath(`\file`, `c:\foo\bar`)        == `c:\file`);
     }
     ---
 
@@ -1821,6 +1932,8 @@ unittest
         assert (absolutePath(`some\file`, `c:\foo\bar`)    == `c:\foo\bar\some\file`);
         assert (absolutePath(`..\file`, `c:\foo\bar`)      == `c:\foo\bar\..\file`);
         assert (absolutePath(`c:\some\file`, `c:\foo\bar`) == `c:\some\file`);
+        assert (absolutePath(`\`, `c:\`)                   == `c:\`);
+        assert (absolutePath(`\some\file`, `c:\foo\bar`)   == `c:\some\file`);
         static assert (absolutePath(`some\file`, `c:\foo\bar`) == `c:\foo\bar\some\file`);
     }
 
@@ -2638,6 +2751,9 @@ string expandTilde(string inputPath)
 {
     version(Posix)
     {
+        import core.stdc.string : strlen;
+        import core.stdc.stdlib : getenv, malloc, free;
+
         /*  Joins a path from a C string to the remainder of path.
 
             The last path separator from c_path is discarded. The result
diff --git a/std/process.d b/std/process.d
index 793c66d37..fd41058e2 100644
--- a/std/process.d
+++ b/std/process.d
@@ -118,26 +118,6 @@ version (Win32) version (DigitalMars) version = DMC_RUNTIME;
 private
 {
 
-// Windows API declarations.
-version (Windows)
-{
-    extern(Windows) BOOL GetHandleInformation(HANDLE hObject,
-                                              LPDWORD lpdwFlags);
-    extern(Windows) BOOL SetHandleInformation(HANDLE hObject,
-                                              DWORD dwMask,
-                                              DWORD dwFlags);
-    extern(Windows) BOOL TerminateProcess(HANDLE hProcess,
-                                          UINT uExitCode);
-    extern(Windows) LPWSTR* CommandLineToArgvW(LPCWSTR lpCmdLine,
-                                               int* pNumArgs);
-    enum
-    {
-        HANDLE_FLAG_INHERIT = 0x1,
-        HANDLE_FLAG_PROTECT_FROM_CLOSE = 0x2,
-    }
-    enum CREATE_UNICODE_ENVIRONMENT = 0x400;
-}
-
 // Microsoft Visual C Runtime (MSVCRT) declarations.
 version (Windows)
 {
@@ -173,8 +153,8 @@ version (Posix)
     version (OSX)
     {
         extern(C) char*** _NSGetEnviron() nothrow;
-        private const(char**)* environPtr;
-        extern(C) void std_process_static_this() { environPtr = _NSGetEnviron(); }
+        private __gshared const(char**)* environPtr;
+        extern(C) void std_process_shared_static_this() { environPtr = _NSGetEnviron(); }
         const(char**) environ() @property @trusted nothrow { return *environPtr; }
     }
     else
@@ -182,6 +162,11 @@ version (Posix)
         // Made available by the C runtime:
         extern(C) extern __gshared const char** environ;
     }
+
+    unittest
+    {
+        new Thread({assert(environ !is null);}).start();
+    }
 }
 
 
@@ -287,7 +272,6 @@ least ensure all relevant buffers are flushed.
 Params:
 args    = An array which contains the program name as the zeroth element
           and any command-line arguments in the following elements.
-program = The program name, $(I without) command-line arguments.
 stdin   = The standard input stream of the child process.
           This can be any $(XREF stdio,File) that is opened for reading.
           By default the child process inherits the parent's input
@@ -375,7 +359,9 @@ private Pid spawnProcessImpl(in char[][] args,
                              Config config)
     @trusted // TODO: Should be @safe
 {
-    if (args.empty) throw new RangeError("Command line is empty");
+    import core.exception: RangeError;
+
+    if (args.empty) throw new RangeError();
     const(char)[] name = args[0];
     if (any!isDirSeparator(name))
     {
@@ -479,6 +465,8 @@ private Pid spawnProcessImpl(in char[] commandLine,
                              Config config)
     @trusted
 {
+    import core.exception: RangeError;
+
     if (commandLine.empty) throw new RangeError("Command line is empty");
     auto commandz = toUTFz!(wchar*)(commandLine);
 
@@ -502,18 +490,21 @@ private Pid spawnProcessImpl(in char[] commandLine,
             version (DMC_RUNTIME) handle = _fdToHandle(fileDescriptor);
             else    /* MSVCRT */  handle = _get_osfhandle(fileDescriptor);
         }
+
         DWORD dwFlags;
-        GetHandleInformation(handle, &dwFlags);
-        if (!(dwFlags & HANDLE_FLAG_INHERIT))
+        if (GetHandleInformation(handle, &dwFlags))
         {
-            if (!SetHandleInformation(handle,
-                                      HANDLE_FLAG_INHERIT,
-                                      HANDLE_FLAG_INHERIT))
+            if (!(dwFlags & HANDLE_FLAG_INHERIT))
             {
-                throw new StdioException(
-                    "Failed to make "~which~" stream inheritable by child process ("
-                    ~sysErrorString(GetLastError()) ~ ')',
-                    0);
+                if (!SetHandleInformation(handle,
+                                          HANDLE_FLAG_INHERIT,
+                                          HANDLE_FLAG_INHERIT))
+                {
+                    throw new StdioException(
+                        "Failed to make "~which~" stream inheritable by child process ("
+                        ~sysErrorString(GetLastError()) ~ ')',
+                        0);
+                }
             }
         }
     }
@@ -1273,10 +1264,6 @@ auto pid = spawnProcess("some_app");
 kill(pid, 10);
 assert (wait(pid) == 10);
 ---
-$(RED Warning:) The mechanisms for process termination are
-$(LINK2 http://blogs.msdn.com/b/oldnewthing/archive/2007/05/03/2383346.aspx,
-incredibly badly specified) in the Windows API.  This function may therefore
-produce unexpected results, and should be used with the utmost care.
 
 POSIX_specific:
 A $(LINK2 http://en.wikipedia.org/wiki/Unix_signal,signal) will be sent to
@@ -1601,33 +1588,33 @@ string[] errors;
 foreach (line; pipes.stderr.byLine) errors ~= line.idup;
 ---
 */
-ProcessPipes pipeProcess(string[] args,
-                         Redirect redirectFlags = Redirect.all,
+ProcessPipes pipeProcess(in char[][] args,
+                         Redirect redirect = Redirect.all,
                          const string[string] env = null,
                          Config config = Config.none)
     @trusted //TODO: @safe
 {
-    return pipeProcessImpl!spawnProcess(args, redirectFlags, env, config);
+    return pipeProcessImpl!spawnProcess(args, redirect, env, config);
 }
 
 /// ditto
-ProcessPipes pipeProcess(string program,
-                         Redirect redirectFlags = Redirect.all,
+ProcessPipes pipeProcess(in char[] program,
+                         Redirect redirect = Redirect.all,
                          const string[string] env = null,
                          Config config = Config.none)
     @trusted
 {
-    return pipeProcessImpl!spawnProcess(program, redirectFlags, env, config);
+    return pipeProcessImpl!spawnProcess(program, redirect, env, config);
 }
 
 /// ditto
-ProcessPipes pipeShell(string command,
-                       Redirect redirectFlags = Redirect.all,
+ProcessPipes pipeShell(in char[] command,
+                       Redirect redirect = Redirect.all,
                        const string[string] env = null,
                        Config config = Config.none)
     @safe
 {
-    return pipeProcessImpl!spawnShell(command, redirectFlags, env, config);
+    return pipeProcessImpl!spawnShell(command, redirect, env, config);
 }
 
 // Implementation of the pipeProcess() family of functions.
@@ -1892,11 +1879,11 @@ for the process to complete before returning.  The functions capture
 what the child process prints to both its standard output and
 standard error streams, and return this together with its exit code.
 ---
-auto dmd = execute("dmd", "myapp.d");
+auto dmd = execute(["dmd", "myapp.d"]);
 if (dmd.status != 0) writeln("Compilation failed:\n", dmd.output);
 
 auto ls = executeShell("ls -l");
-if (ls.status == 0) writeln("Failed to retrieve file listing");
+if (ls.status != 0) writeln("Failed to retrieve file listing");
 else writeln(ls.output);
 ---
 
@@ -1935,7 +1922,7 @@ Throws:
 $(LREF ProcessException) on failure to start the process.$(BR)
 $(XREF stdio,StdioException) on failure to capture output.
 */
-auto execute(string[] args,
+auto execute(in char[][] args,
              const string[string] env = null,
              Config config = Config.none,
              size_t maxOutput = size_t.max)
@@ -1945,7 +1932,7 @@ auto execute(string[] args,
 }
 
 /// ditto
-auto execute(string program,
+auto execute(in char[] program,
              const string[string] env = null,
              Config config = Config.none,
              size_t maxOutput = size_t.max)
@@ -1955,7 +1942,7 @@ auto execute(string program,
 }
 
 /// ditto
-auto executeShell(string command,
+auto executeShell(in char[] command,
                   const string[string] env = null,
                   Config config = Config.none,
                   size_t maxOutput = size_t.max)
@@ -1981,7 +1968,7 @@ private auto executeImpl(alias pipeFunc, Cmd)(
     // Store up to maxOutput bytes in a.
     foreach (ubyte[] chunk; p.stdout.byChunk(chunkSize))
     {
-        immutable size_t remain = maxOutput - a.data().length;
+        immutable size_t remain = maxOutput - a.data.length;
 
         if (chunk.length < remain) a.put(chunk);
         else
@@ -2057,8 +2044,8 @@ class ProcessException : Exception
         {
             auto errnoMsg = to!string(std.c.string.strerror(errno));
         }
-        auto msg = customMsg.empty() ? errnoMsg
-                                     : customMsg ~ " (" ~ errnoMsg ~ ')';
+        auto msg = customMsg.empty ? errnoMsg
+                                   : customMsg ~ " (" ~ errnoMsg ~ ')';
         return new ProcessException(msg, file, line);
     }
 
@@ -2069,8 +2056,8 @@ class ProcessException : Exception
                                              size_t line = __LINE__)
     {
         auto lastMsg = sysErrorString(GetLastError());
-        auto msg = customMsg.empty() ? lastMsg
-                                     : customMsg ~ " (" ~ lastMsg ~ ')';
+        auto msg = customMsg.empty ? lastMsg
+                                   : customMsg ~ " (" ~ lastMsg ~ ')';
         return new ProcessException(msg, file, line);
     }
 }
@@ -2214,6 +2201,48 @@ string escapeShellCommand(in char[][] args...)
     return escapeShellCommandString(escapeShellArguments(args));
 }
 
+unittest
+{
+    // This is a simple unit test without any special requirements,
+    // in addition to the unittest_burnin one below which requires
+    // special preparation.
+
+    struct TestVector { string[] args; string windows, posix; }
+    TestVector[] tests =
+    [
+        {
+            args    : ["foo"],
+            windows : `^"foo^"`,
+            posix   : `'foo'`
+        },
+        {
+            args    : ["foo", "hello"],
+            windows : `^"foo^" ^"hello^"`,
+            posix   : `'foo' 'hello'`
+        },
+        {
+            args    : ["foo", "hello world"],
+            windows : `^"foo^" ^"hello world^"`,
+            posix   : `'foo' 'hello world'`
+        },
+        {
+            args    : ["foo", "hello", "world"],
+            windows : `^"foo^" ^"hello^" ^"world^"`,
+            posix   : `'foo' 'hello' 'world'`
+        },
+        {
+            args    : ["foo", `'"^\`],
+            windows : `^"foo^" ^"'\^"^^\\^"`,
+            posix   : `'foo' ''\''"^\'`
+        },
+    ];
+
+    foreach (test; tests)
+        version (Windows)
+            assert(escapeShellCommand(test.args) == test.windows);
+        else
+            assert(escapeShellCommand(test.args) == test.posix  );
+}
 
 private string escapeShellCommandString(string command)
     //TODO: @safe pure nothrow
@@ -2594,7 +2623,7 @@ static:
     See_also:
     $(LREF environment.get), which doesn't throw on failure.
     */
-    string opIndex(string name) @safe
+    string opIndex(in char[] name) @safe
     {
         string value;
         enforce(getImpl(name, value), "Environment variable not found: "~name);
@@ -2622,7 +2651,7 @@ static:
     }
     ---
     */
-    string get(string name, string defaultValue = null) @safe //TODO: nothrow
+    string get(in char[] name, string defaultValue = null) @safe //TODO: nothrow
     {
         string value;
         auto found = getImpl(name, value);
@@ -2643,7 +2672,7 @@ static:
     $(OBJECTREF Exception) if the environment variable could not be added
         (e.g. if the name is invalid).
     */
-    string opIndexAssign(string value, string name) @trusted
+    inout(char)[] opIndexAssign(inout char[] value, in char[] name) @trusted
     {
         version (Posix)
         {
@@ -2676,7 +2705,7 @@ static:
     If the variable isn't in the environment, this function returns
     successfully without doing anything.
     */
-    void remove(string name) @trusted // TODO: @safe nothrow
+    void remove(in char[] name) @trusted // TODO: @safe nothrow
     {
         version (Windows)    SetEnvironmentVariableW(toUTF16z(name), null);
         else version (Posix) core.sys.posix.stdlib.unsetenv(toStringz(name));
@@ -2753,7 +2782,7 @@ private:
     }
 
     // Retrieves the environment variable, returns false on failure.
-    bool getImpl(string name, out string value) @trusted //TODO: nothrow
+    bool getImpl(in char[] name, out string value) @trusted //TODO: nothrow
     {
         version (Windows)
         {
@@ -2902,7 +2931,7 @@ version (unittest)
 
 int system(string command)
 {
-    if (!command) return std.c.process.system(null);
+    if (!command.ptr) return std.c.process.system(null);
     const commandz = toStringz(command);
     immutable status = std.c.process.system(commandz);
     if (status == -1) return status;
diff --git a/std/random.d b/std/random.d
index 021acfb50..05c7146c4 100644
--- a/std/random.d
+++ b/std/random.d
@@ -112,7 +112,6 @@ version(unittest) import std.typetuple;
    email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
 */
 
-
 /**
  * Test if Rng is a random-number generator. The overload
  * taking a ElementType also makes sure that the Rng generates
@@ -184,10 +183,10 @@ unittest
         @property bool empty() {return false;}
         void popFront() {}
     }
-    assert(!isUniformRNG!(NoRng, uint));
-    assert(!isUniformRNG!(NoRng));
-    assert(!isSeedable!(NoRng, uint));
-    assert(!isSeedable!(NoRng));
+    static assert(!isUniformRNG!(NoRng, uint));
+    static assert(!isUniformRNG!(NoRng));
+    static assert(!isSeedable!(NoRng, uint));
+    static assert(!isSeedable!(NoRng));
 
     struct NoRng2
     {
@@ -197,10 +196,10 @@ unittest
 
         enum isUniformRandom = false;
     }
-    assert(!isUniformRNG!(NoRng2, uint));
-    assert(!isUniformRNG!(NoRng2));
-    assert(!isSeedable!(NoRng2, uint));
-    assert(!isSeedable!(NoRng2));
+    static assert(!isUniformRNG!(NoRng2, uint));
+    static assert(!isUniformRNG!(NoRng2));
+    static assert(!isSeedable!(NoRng2, uint));
+    static assert(!isSeedable!(NoRng2));
 
     struct NoRng3
     {
@@ -209,10 +208,10 @@ unittest
 
         enum isUniformRandom = true;
     }
-    assert(!isUniformRNG!(NoRng3, uint));
-    assert(!isUniformRNG!(NoRng3));
-    assert(!isSeedable!(NoRng3, uint));
-    assert(!isSeedable!(NoRng3));
+    static assert(!isUniformRNG!(NoRng3, uint));
+    static assert(!isUniformRNG!(NoRng3));
+    static assert(!isSeedable!(NoRng3, uint));
+    static assert(!isSeedable!(NoRng3));
 
     struct validRng
     {
@@ -222,10 +221,10 @@ unittest
 
         enum isUniformRandom = true;
     }
-    assert(isUniformRNG!(validRng, uint));
-    assert(isUniformRNG!(validRng));
-    assert(!isSeedable!(validRng, uint));
-    assert(!isSeedable!(validRng));
+    static assert(isUniformRNG!(validRng, uint));
+    static assert(isUniformRNG!(validRng));
+    static assert(!isSeedable!(validRng, uint));
+    static assert(!isSeedable!(validRng));
 
     struct seedRng
     {
@@ -235,10 +234,10 @@ unittest
         void seed(uint val){}
         enum isUniformRandom = true;
     }
-    assert(isUniformRNG!(seedRng, uint));
-    assert(isUniformRNG!(seedRng));
-    assert(isSeedable!(seedRng, uint));
-    assert(isSeedable!(seedRng));
+    static assert(isUniformRNG!(seedRng, uint));
+    static assert(isUniformRNG!(seedRng));
+    static assert(isSeedable!(seedRng, uint));
+    static assert(isSeedable!(seedRng));
 }
 
 /**
@@ -456,15 +455,15 @@ alias LinearCongruentialEngine!(uint, 48271, 0, 2147483647) MinstdRand;
 
 unittest
 {
-    assert(isForwardRange!MinstdRand);
-    assert(isUniformRNG!MinstdRand);
-    assert(isUniformRNG!MinstdRand0);
-    assert(isUniformRNG!(MinstdRand, uint));
-    assert(isUniformRNG!(MinstdRand0, uint));
-    assert(isSeedable!MinstdRand);
-    assert(isSeedable!MinstdRand0);
-    assert(isSeedable!(MinstdRand, uint));
-    assert(isSeedable!(MinstdRand0, uint));
+    static assert(isForwardRange!MinstdRand);
+    static assert(isUniformRNG!MinstdRand);
+    static assert(isUniformRNG!MinstdRand0);
+    static assert(isUniformRNG!(MinstdRand, uint));
+    static assert(isUniformRNG!(MinstdRand0, uint));
+    static assert(isSeedable!MinstdRand);
+    static assert(isSeedable!MinstdRand0);
+    static assert(isSeedable!(MinstdRand, uint));
+    static assert(isSeedable!(MinstdRand0, uint));
 
     // The correct numbers are taken from The Database of Integer Sequences
     // http://www.research.att.com/~njas/sequences/eisBTfry00128.txt
@@ -505,6 +504,17 @@ unittest
     rnd.seed();
     popFrontN(rnd, 9999);
     assert(rnd.front == 399268537);
+
+    // Check .save works
+    foreach (Type; TypeTuple!(MinstdRand0, MinstdRand))
+    {
+        auto rnd1 = Type(unpredictableSeed);
+        auto rnd2 = rnd1.save;
+        assert(rnd1 == rnd2);
+        // Enable next test when RNGs are reference types
+        version(none) { assert(rnd1 !is rnd2); }
+        assert(rnd1.take(100).array() == rnd2.take(100).array());
+    }
 }
 
 /**
@@ -628,7 +638,7 @@ Parameter for the generator.
             upperMask = ~((cast(UIntType) 1u <<
                            (UIntType.sizeof * 8 - (w - r))) - 1),
             lowerMask = (cast(UIntType) 1u << r) - 1;
-        static immutable UIntType mag01[2] = [0x0UL, a];
+        static immutable UIntType[2] mag01 = [0x0UL, a];
 
         ulong y = void;
 
@@ -689,7 +699,7 @@ Always $(D false).
  */
     enum bool empty = false;
 
-    private UIntType mt[n];
+    private UIntType[n] mt;
     private size_t mti = size_t.max; /* means mt is not initialized */
     UIntType _y = UIntType.max;
 }
@@ -719,11 +729,11 @@ alias MersenneTwisterEngine!(uint, 32, 624, 397, 31, 0x9908b0df, 11, 7,
 
 unittest
 {
-    assert(isUniformRNG!Mt19937);
-    assert(isUniformRNG!(Mt19937, uint));
-    assert(isSeedable!Mt19937);
-    assert(isSeedable!(Mt19937, uint));
-    assert(isSeedable!(Mt19937, typeof(map!((a) => unpredictableSeed)(repeat(0)))));
+    static assert(isUniformRNG!Mt19937);
+    static assert(isUniformRNG!(Mt19937, uint));
+    static assert(isSeedable!Mt19937);
+    static assert(isSeedable!(Mt19937, uint));
+    static assert(isSeedable!(Mt19937, typeof(map!((a) => unpredictableSeed)(repeat(0)))));
     Mt19937 gen;
     popFrontN(gen, 9999);
     assert(gen.front == 4123659995);
@@ -756,6 +766,20 @@ unittest
     assert(a != b);
 }
 
+unittest
+{
+    // Check .save works
+    foreach(Type; TypeTuple!(Mt19937))
+    {
+        auto gen1 = Type(unpredictableSeed);
+        auto gen2 = gen1.save;
+        assert(gen1 == gen2);  // Danger, Will Robinson -- no opEquals for MT
+        // Enable next test when RNGs are reference types
+        version(none) { assert(gen1 !is gen2); }
+        assert(gen1.take(100).array() == gen2.take(100).array());
+    }
+}
+
 
 /**
  * Xorshift generator using 32bit algorithm.
@@ -776,8 +800,8 @@ struct XorshiftEngine(UIntType, UIntType bits, UIntType a, UIntType b, UIntType
     if(isUnsigned!UIntType)
 {
     static assert(bits == 32 || bits == 64 || bits == 96 || bits == 128 || bits == 160 || bits == 192,
-                  "Supporting bits are 32, 64, 96, 128, 160 and 192. " ~ to!string(bits) ~ " is not supported.");
-
+                  "Xorshift supports only 32, 64, 96, 128, 160 and 192 bit versions. "
+                  ~ to!string(bits) ~ " is not supported.");
 
   public:
     ///Mark this as a Rng
@@ -803,11 +827,16 @@ struct XorshiftEngine(UIntType, UIntType bits, UIntType a, UIntType b, UIntType
         UIntType[size] seeds_ = [123456789, 362436069, 521288629, 88675123];
     else static if (bits == 160)
         UIntType[size] seeds_ = [123456789, 362436069, 521288629, 88675123, 5783321];
-    else
-    { // 192bits
+    else static if (bits == 192)
+    {
         UIntType[size] seeds_ = [123456789, 362436069, 521288629, 88675123, 5783321, 6615241];
         UIntType       value_;
     }
+    else
+    {
+        static assert(false, "Phobos Error: Xorshift has no instantiation rule for "
+                             ~ to!string(bits) ~ " bits.");
+    }
 
 
   public:
@@ -862,7 +891,7 @@ struct XorshiftEngine(UIntType, UIntType bits, UIntType a, UIntType b, UIntType
         static if (bits == 32)
         {
             temp      = seeds_[0] ^ (seeds_[0] << a);
-            temp      = temp >> b;
+            temp      = temp ^ (temp >> b);
             seeds_[0] = temp ^ (temp << c);
         }
         else static if (bits == 64)
@@ -888,15 +917,15 @@ struct XorshiftEngine(UIntType, UIntType bits, UIntType a, UIntType b, UIntType
         }
         else static if (bits == 160)
         {
-            temp      = seeds_[0] ^ (seeds_[0] >> a);
+            temp      = seeds_[0] ^ (seeds_[0] << a);
             seeds_[0] = seeds_[1];
             seeds_[1] = seeds_[2];
             seeds_[2] = seeds_[3];
             seeds_[3] = seeds_[4];
             seeds_[4] = seeds_[4] ^ (seeds_[4] >> c) ^ temp ^ (temp >> b);
         }
-        else
-        { // 192bits
+        else static if (bits == 192)
+        {
             temp      = seeds_[0] ^ (seeds_[0] >> a);
             seeds_[0] = seeds_[1];
             seeds_[1] = seeds_[2];
@@ -905,6 +934,11 @@ struct XorshiftEngine(UIntType, UIntType bits, UIntType a, UIntType b, UIntType
             seeds_[4] = seeds_[4] ^ (seeds_[4] << c) ^ temp ^ (temp << b);
             value_    = seeds_[4] + (seeds_[5] += 362437);
         }
+        else
+        {
+            static assert(false, "Phobos Error: Xorshift has no popFront() update for "
+                                 ~ to!string(bits) ~ " bits.");
+        }
     }
 
 
@@ -969,7 +1003,7 @@ struct XorshiftEngine(UIntType, UIntType bits, UIntType a, UIntType b, UIntType
  * num = rnd.front; // different across runs
  * -----
  */
-alias XorshiftEngine!(uint, 32,  13, 17, 5)  Xorshift32;
+alias XorshiftEngine!(uint, 32,  13, 17, 15)  Xorshift32;
 alias XorshiftEngine!(uint, 64,  10, 13, 10) Xorshift64;   /// ditto
 alias XorshiftEngine!(uint, 96,  10, 5,  26) Xorshift96;   /// ditto
 alias XorshiftEngine!(uint, 128, 11, 8,  19) Xorshift128;  /// ditto
@@ -980,23 +1014,25 @@ alias Xorshift128 Xorshift;                                /// ditto
 
 unittest
 {
-    assert(isForwardRange!Xorshift);
-    assert(isUniformRNG!Xorshift);
-    assert(isUniformRNG!(Xorshift, uint));
-    assert(isSeedable!Xorshift);
-    assert(isSeedable!(Xorshift, uint));
+    static assert(isForwardRange!Xorshift);
+    static assert(isUniformRNG!Xorshift);
+    static assert(isUniformRNG!(Xorshift, uint));
+    static assert(isSeedable!Xorshift);
+    static assert(isSeedable!(Xorshift, uint));
 
     // Result from reference implementation.
     auto checking = [
-        [2463534242UL, 267649, 551450, 53765, 108832, 215250, 435468, 860211, 660133, 263375],
+        [2463534242UL, 901999875, 3371835698, 2675058524, 1053936272, 3811264849, 472493137, 3856898176, 2131710969, 2312157505],
         [362436069UL, 2113136921, 19051112, 3010520417, 951284840, 1213972223, 3173832558, 2611145638, 2515869689, 2245824891],
         [521288629UL, 1950277231, 185954712, 1582725458, 3580567609, 2303633688, 2394948066, 4108622809, 1116800180, 3357585673],
         [88675123UL, 3701687786, 458299110, 2500872618, 3633119408, 516391518, 2377269574, 2599949379, 717229868, 137866584],
-        [5783321UL, 93724048, 491642011, 136638118, 246438988, 238186808, 140181925, 533680092, 285770921, 462053907],
+        [5783321UL, 393427209, 1947109840, 565829276, 1006220149, 971147905, 1436324242, 2800460115, 1484058076, 3823330032],
         [0UL, 246875399, 3690007200, 1264581005, 3906711041, 1866187943, 2481925219, 2464530826, 1604040631, 3653403911]
     ];
 
-    foreach (I, Type; TypeTuple!(Xorshift32, Xorshift64, Xorshift96, Xorshift128, Xorshift160, Xorshift192))
+    alias TypeTuple!(Xorshift32, Xorshift64, Xorshift96, Xorshift128, Xorshift160, Xorshift192) XorshiftTypes;
+
+    foreach (I, Type; XorshiftTypes)
     {
         Type rnd;
 
@@ -1006,6 +1042,48 @@ unittest
             rnd.popFront();
         }
     }
+
+    // Check .save works
+    foreach (Type; XorshiftTypes)
+    {
+        auto rnd1 = Type(unpredictableSeed);
+        auto rnd2 = rnd1.save;
+        assert(rnd1 == rnd2);
+        // Enable next test when RNGs are reference types
+        version(none) { assert(rnd1 !is rnd2); }
+        assert(rnd1.take(100).array() == rnd2.take(100).array());
+    }
+}
+
+
+/* A complete list of all pseudo-random number generators implemented in
+ * std.random.  This can be used to confirm that a given function or
+ * object is compatible with all the pseudo-random number generators
+ * available.  It is enabled only in unittest mode.
+ *
+ * Example:
+ *
+ * ----
+ * foreach(Rng; PseudoRngTypes)
+ * {
+ *     static assert(isUniformRng!Rng);
+ *     auto rng = Rng(unpredictableSeed);
+ *     foo(rng);
+ * }
+ * ----
+ */
+version(unittest)
+{
+    package alias PseudoRngTypes = TypeTuple!(MinstdRand0, MinstdRand, Mt19937, Xorshift32, Xorshift64,
+                                              Xorshift96, Xorshift128, Xorshift160, Xorshift192);
+}
+
+unittest
+{
+    foreach(Rng; PseudoRngTypes)
+    {
+        static assert(isUniformRNG!Rng);
+    }
 }
 
 
@@ -1056,10 +1134,10 @@ alias Mt19937 Random;
 
 unittest
 {
-    assert(isUniformRNG!Random);
-    assert(isUniformRNG!(Random, uint));
-    assert(isSeedable!Random);
-    assert(isSeedable!(Random, uint));
+    static assert(isUniformRNG!Random);
+    static assert(isUniformRNG!(Random, uint));
+    static assert(isSeedable!Random);
+    static assert(isSeedable!(Random, uint));
 }
 
 /**
@@ -1093,7 +1171,7 @@ take $(D urng) uses the default generator $(D rndGen).
 Example:
 
 ----
-Random gen(unpredictableSeed);
+auto gen = Random(unpredictableSeed);
 // Generate an integer in [0, 1023]
 auto a = uniform(0, 1024, gen);
 // Generate a float in [0, 1$(RPAREN)
@@ -1170,57 +1248,119 @@ if (isFloatingPoint!(CommonType!(T1, T2)))
 }
 
 // Implementation of uniform for integral types
-auto uniform(string boundaries = "[)",
-        T1, T2, UniformRandomNumberGenerator)
-(T1 a, T2 b, ref UniformRandomNumberGenerator urng)
+/+ Description of algorithm and suggestion of correctness:
+
+The modulus operator maps an integer to a small, finite space. For instance, `x
+% 3` will map whatever x is into the range [0 .. 3). 0 maps to 0, 1 maps to 1, 2
+maps to 2, 3 maps to 0, and so on infinitely. As long as the integer is
+uniformly chosen from the infinite space of all non-negative integers then `x %
+3` will uniformly fall into that range.
+
+(Non-negative is important in this case because some definitions of modulus,
+namely the one used in computers generally, map negative numbers differently to
+(-3 .. 0]. `uniform` does not use negative number modulus, thus we can safely
+ignore that fact.)
+
+The issue with computers is that integers have a finite space they must fit in,
+and our uniformly chosen random number is picked in that finite space. So, that
+method is not sufficient. You can look at it as the integer space being divided
+into "buckets" and every bucket after the first bucket maps directly into that
+first bucket. `[0, 1, 2]`, `[3, 4, 5]`, ... When integers are finite, then the
+last bucket has the chance to be "incomplete": `[uint.max - 3, uint.max - 2,
+uint.max - 1]`, `[uint.max]` ... (the last bucket only has 1!). The issue here
+is that _every_ bucket maps _completely_ to the first bucket except for that
+last one. The last one doesn't have corresponding mappings to 1 or 2, in this
+case, which makes it unfair.
+
+So, the answer is to simply "reroll" if you're in that last bucket, since it's
+the only unfair one. Eventually you'll roll into a fair bucket. Simply, instead
+of the meaning of the last bucket being "maps to `[0]`", it changes to "maps to
+`[0, 1, 2]`", which is precisely what we want.
+
+To generalize, `upperDist` represents the size of our buckets (and, thus, the
+exclusive upper bound for our desired uniform number). `rnum` is a uniformly
+random number picked from the space of integers that a computer can hold (we'll
+say `UpperType` represents that type).
+
+We'll first try to do the mapping into the first bucket by doing `offset = rnum
+% upperDist`. We can figure out the position of the front of the bucket we're in
+by `bucketFront = rnum - offset`.
+
+If we start at `UpperType.max` and walk backwards `upperDist - 1` spaces, then
+the space we land on is the last acceptable position where a full bucket can
+fit:
+
+```
+   bucketFront     UpperType.max
+      v                 v
+[..., 0, 1, 2, ..., upperDist - 1]
+      ^~~ upperDist - 1 ~~^
+```
+
+If the bucket starts any later, then it must have lost at least one number and
+at least that number won't be represented fairly.
+
+```
+                bucketFront     UpperType.max
+                     v                v
+[..., upperDist - 1, 0, 1, 2, ..., upperDist - 2]
+          ^~~~~~~~ upperDist - 1 ~~~~~~~^
+```
+
+Hence, our condition to reroll is
+`bucketFront > (UpperType.max - (upperDist - 1))`
++/
+auto uniform(string boundaries = "[)", T1, T2, RandomGen)
+(T1 a, T2 b, ref RandomGen rng)
 if (isIntegral!(CommonType!(T1, T2)) || isSomeChar!(CommonType!(T1, T2)))
 {
-    alias Unqual!(CommonType!(T1, T2)) ResultType;
-    // We handle the case "[)' as the common case, and we adjust all
-    // other cases to fit it.
+    alias ResultType = Unqual!(CommonType!(T1, T2));
     static if (boundaries[0] == '(')
     {
-        enforce(cast(ResultType) a < ResultType.max,
+        enforce(a < ResultType.max,
                 text("std.random.uniform(): invalid left bound ", a));
-        ResultType min = cast(ResultType) a + 1;
+        ResultType lower = a + 1;
     }
     else
     {
-        ResultType min = a;
+        ResultType lower = a;
     }
+
     static if (boundaries[1] == ']')
     {
-        enforce(min <= cast(ResultType) b,
+        enforce(lower <= b,
                 text("std.random.uniform(): invalid bounding interval ",
                         boundaries[0], a, ", ", b, boundaries[1]));
-        if (b == ResultType.max && min == ResultType.min)
+        if (b == ResultType.max && lower == ResultType.min)
         {
             // Special case - all bits are occupied
-            return .uniform!ResultType(urng);
+            return std.random.uniform!ResultType(rng);
         }
-        auto count = unsigned(b - min) + 1u;
-        static assert(count.min == 0);
+        auto upperDist = unsigned(b - lower) + 1u;
     }
     else
     {
-        enforce(min < cast(ResultType) b,
+        enforce(lower < b,
                 text("std.random.uniform(): invalid bounding interval ",
                         boundaries[0], a, ", ", b, boundaries[1]));
-        auto count = unsigned(b - min);
-        static assert(count.min == 0);
+        auto upperDist = unsigned(b - lower);
     }
-    assert(count != 0);
-    if (count == 1) return min;
-    alias typeof(count) CountType;
-    static assert(CountType.min == 0);
-    auto bucketSize = 1u + (CountType.max - count + 1) / count;
-    CountType r;
+
+    assert(upperDist != 0);
+
+    alias UpperType = typeof(upperDist);
+    static assert(UpperType.min == 0);
+
+    UpperType offset, rnum, bucketFront;
     do
     {
-        r = cast(CountType) (uniform!CountType(urng) / bucketSize);
-    }
-    while (r >= count);
-    return cast(typeof(return)) (min + r);
+        rnum = uniform!UpperType(rng);
+        offset = rnum % upperDist;
+        bucketFront = rnum - offset;
+    } // while we're in an unfair bucket...
+    while (bucketFront > (UpperType.max - (upperDist - 1)));
+
+    return cast(ResultType)(lower + offset);
 }
 
 unittest
@@ -1235,7 +1375,7 @@ unittest
     auto c = uniform(0.0, 1.0);
     assert(0 <= c && c < 1);
 
-    foreach(T; TypeTuple!(char, wchar, dchar, byte, ubyte, short, ushort,
+    foreach (T; TypeTuple!(char, wchar, dchar, byte, ubyte, short, ushort,
                           int, uint, long, ulong, float, double, real))
     {
         T lo = 0, hi = 100;
@@ -1244,6 +1384,75 @@ unittest
         while (--i && uniform(lo, hi) == init) {}
         assert(i > 0);
     }
+
+    auto reproRng = Xorshift(239842);
+
+    foreach (T; TypeTuple!(char, wchar, dchar, byte, ubyte, short,
+                          ushort, int, uint, long, ulong))
+    {
+        T lo = T.min + 10, hi = T.max - 10;
+        T init = uniform(lo, hi, reproRng);
+        size_t i = 50;
+        while (--i && uniform(lo, hi, reproRng) == init) {}
+        assert(i > 0);
+    }
+
+    {
+        bool sawLB = false, sawUB = false;
+        foreach (i; 0 .. 50)
+        {
+            auto x = uniform!"[]"('a', 'd', reproRng);
+            if (x == 'a') sawLB = true;
+            if (x == 'd') sawUB = true;
+            assert('a' <= x && x <= 'd');
+        }
+        assert(sawLB && sawUB);
+    }
+
+    {
+        bool sawLB = false, sawUB = false;
+        foreach (i; 0 .. 50)
+        {
+            auto x = uniform('a', 'd', reproRng);
+            if (x == 'a') sawLB = true;
+            if (x == 'c') sawUB = true;
+            assert('a' <= x && x < 'd');
+        }
+        assert(sawLB && sawUB);
+    }
+
+    {
+        bool sawLB = false, sawUB = false;
+        foreach (i; 0 .. 50)
+        {
+            immutable int lo = -2, hi = 2;
+            auto x = uniform!"()"(lo, hi, reproRng);
+            if (x == (lo+1)) sawLB = true;
+            if (x == (hi-1)) sawUB = true;
+            assert(lo < x && x < hi);
+        }
+        assert(sawLB && sawUB);
+    }
+
+    {
+        bool sawLB = false, sawUB = false;
+        foreach (i; 0 .. 50)
+        {
+            immutable ubyte lo = 0, hi = 5;
+            auto x = uniform(lo, hi, reproRng);
+            if (x == lo) sawLB = true;
+            if (x == (hi-1)) sawUB = true;
+            assert(lo <= x && x < hi);
+        }
+        assert(sawLB && sawUB);
+    }
+
+    {
+        foreach (i; 0 .. 30)
+        {
+            assert(i == uniform(i, i+1, reproRng));
+        }
+    }
 }
 
 /**
@@ -1350,26 +1559,36 @@ unittest
 
 /**
 Shuffles elements of $(D r) using $(D gen) as a shuffler. $(D r) must be
-a random-access range with length.
+a random-access range with length.  If no RNG is specified, $(D rndGen)
+will be used.
  */
 
-void randomShuffle(Range, RandomGen = Random)(Range r,
-                                              ref RandomGen gen = rndGen)
+void randomShuffle(Range, RandomGen)(Range r, ref RandomGen gen)
     if(isRandomAccessRange!Range && isUniformRNG!RandomGen)
 {
     return partialShuffle!(Range, RandomGen)(r, r.length, gen);
 }
 
+/// ditto
+void randomShuffle(Range)(Range r)
+    if(isRandomAccessRange!Range)
+{
+    return randomShuffle(r, rndGen);
+}
+
 unittest
 {
-    // Also tests partialShuffle indirectly.
-    auto a = ([ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]).dup;
-    auto b = a.dup;
-    Mt19937 gen;
-    randomShuffle(a, gen);
-    assert(a.sort == b.sort);
-    randomShuffle(a);
-    assert(a.sort == b.sort);
+    foreach(RandomGen; PseudoRngTypes)
+    {
+        // Also tests partialShuffle indirectly.
+        auto a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
+        auto b = a.dup;
+        auto gen = RandomGen(unpredictableSeed);
+        randomShuffle(a, gen);
+        assert(a.sort == b);
+        randomShuffle(a);
+        assert(a.sort == b);
+    }
 }
 
 /**
@@ -1381,16 +1600,38 @@ $(D partialShuffle) returns will not be independent of their order before
 $(D partialShuffle) was called.
 
 $(D r) must be a random-access range with length.  $(D n) must be less than
-or equal to $(D r.length).
+or equal to $(D r.length).  If no RNG is specified, $(D rndGen) will be used.
 */
-void partialShuffle(Range, RandomGen = Random)(Range r, size_t n,
-                                              ref RandomGen gen = rndGen)
+void partialShuffle(Range, RandomGen)(Range r, in size_t n, ref RandomGen gen)
     if(isRandomAccessRange!Range && isUniformRNG!RandomGen)
 {
     enforce(n <= r.length, "n must be <= r.length for partialShuffle.");
     foreach (i; 0 .. n)
     {
-        swapAt(r, i, i + uniform(0, r.length - i, gen));
+        swapAt(r, i, i + uniform(0, n - i, gen));
+    }
+}
+
+/// ditto
+void partialShuffle(Range)(Range r, in size_t n)
+    if(isRandomAccessRange!Range)
+{
+    return partialShuffle(r, n, rndGen);
+}
+
+unittest
+{
+    foreach(RandomGen; PseudoRngTypes)
+    {
+        auto a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
+        auto b = a.dup;
+        auto gen = RandomGen(unpredictableSeed);
+        partialShuffle(a, 5, gen);
+        assert(a[5 .. $] == b[5 .. $]);
+        assert(a[0 .. 5].sort == b[0 .. 5]);
+        partialShuffle(a, 6);
+        assert(a[6 .. $] == b[6 .. $]);
+        assert(a[0 .. 6].sort == b[0 .. 6]);
     }
 }
 
@@ -1471,41 +1712,102 @@ Covers a given range $(D r) in a random manner, i.e. goes through each
 element of $(D r) once and only once, just in a random order. $(D r)
 must be a random-access range with length.
 
+If no random number generator is passed to $(D randomCover), the
+thread-global RNG rndGen will be used internally.
+
 Example:
 ----
 int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ];
-auto rnd = Random(unpredictableSeed);
-foreach (e; randomCover(a, rnd))
+foreach (e; randomCover(a))
 {
     writeln(e);
 }
 ----
+
+$(B WARNING:) If an alternative RNG is desired, it is essential for this
+to be a $(I new) RNG seeded in an unpredictable manner. Passing it a RNG
+used elsewhere in the program will result in unintended correlations,
+due to the current implementation of RNGs as value types.
+
+Example:
+----
+int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ];
+foreach (e; randomCover(a, Random(unpredictableSeed)))  // correct!
+{
+    writeln(e);
+}
+
+foreach (e; randomCover(a, rndGen))  // DANGEROUS!! rndGen gets copied by value
+{
+    writeln(e);
+}
+
+foreach (e; randomCover(a, rndGen))  // ... so this second random cover
+{                                    // will output the same sequence as
+    writeln(e);                      // the previous one.
+}
+----
+
+These issues will be resolved in a second-generation std.random that
+re-implements random number generators as reference types.
  */
-struct RandomCover(Range, Random)
-    if(isRandomAccessRange!Range && isUniformRNG!Random)
+struct RandomCover(Range, UniformRNG = void)
+    if (isRandomAccessRange!Range && (isUniformRNG!UniformRNG || is(UniformRNG == void)))
 {
     private Range _input;
-    private Random _rnd;
     private bool[] _chosen;
-    private uint _current;
-    private uint _alreadyChosen;
+    private size_t _current;
+    private size_t _alreadyChosen = 0;
 
-    this(Range input, Random rnd)
+    static if (is(UniformRNG == void))
     {
-        _input = input;
-        _rnd = rnd;
-        _chosen.length = _input.length;
-        popFront();
+        this(Range input)
+        {
+            _input = input;
+            _chosen.length = _input.length;
+            _alreadyChosen = 0;
+        }
+    }
+    else
+    {
+        private UniformRNG _rng;
+
+        this(Range input, ref UniformRNG rng)
+        {
+            _input = input;
+            _rng = rng;
+            _chosen.length = _input.length;
+            _alreadyChosen = 0;
+        }
+
+        this(Range input, UniformRNG rng)
+        {
+            this(input, rng);
+        }
     }
 
     static if (hasLength!Range)
+    {
         @property size_t length()
         {
-            return (1 + _input.length) - _alreadyChosen;
+            if (_alreadyChosen == 0)
+            {
+                return _input.length;
+            }
+            else
+            {
+                return (1 + _input.length) - _alreadyChosen;
+            }
         }
+    }
 
     @property auto ref front()
     {
+        if (_alreadyChosen == 0)
+        {
+            _chosen[] = false;
+            popFront();
+        }
         return _input[_current];
     }
 
@@ -1518,12 +1820,19 @@ struct RandomCover(Range, Random)
             return;
         }
         size_t k = _input.length - _alreadyChosen;
-        uint i;
+        size_t i;
         foreach (e; _input)
         {
             if (_chosen[i]) { ++i; continue; }
             // Roll a dice with k faces
-            auto chooseMe = uniform(0, k, _rnd) == 0;
+            static if (is(UniformRNG == void))
+            {
+                auto chooseMe = uniform(0, k) == 0;
+            }
+            else
+            {
+                auto chooseMe = uniform(0, k, _rng) == 0;
+            }
             assert(k > 1 || chooseMe);
             if (chooseMe)
             {
@@ -1535,43 +1844,67 @@ struct RandomCover(Range, Random)
             --k;
             ++i;
         }
-        assert(false);
     }
 
-    @property typeof(this) save()
+    static if (isForwardRange!UniformRNG)
     {
-        auto ret = this;
-        ret._input = _input.save;
-        ret._rnd = _rnd.save;
-        return ret;
+        @property typeof(this) save()
+        {
+            auto ret = this;
+            ret._input = _input.save;
+            ret._rng = _rng.save;
+            return ret;
+        }
     }
 
     @property bool empty() { return _alreadyChosen > _input.length; }
 }
 
 /// Ditto
-RandomCover!(Range, Random) randomCover(Range, Random)(Range r, Random rnd)
-    if(isRandomAccessRange!Range && isUniformRNG!Random)
+auto randomCover(Range, UniformRNG)(Range r, auto ref UniformRNG rng)
+    if (isRandomAccessRange!Range && isUniformRNG!UniformRNG)
 {
-    return typeof(return)(r, rnd);
+    return RandomCover!(Range, UniformRNG)(r, rng);
+}
+
+/// Ditto
+auto randomCover(Range)(Range r)
+    if (isRandomAccessRange!Range)
+{
+    return RandomCover!(Range, void)(r);
 }
 
 unittest
 {
     int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ];
-    auto rnd = Random(unpredictableSeed);
-    RandomCover!(int[], Random) rc = randomCover(a, rnd);
-    static assert(isForwardRange!(typeof(rc)));
-
-    int[] b = new int[9];
-    uint i;
-    foreach (e; rc)
+    foreach (UniformRNG; TypeTuple!(void, PseudoRngTypes))
     {
-        //writeln(e);
-        b[i++] = e;
+        static if (is(UniformRNG == void))
+        {
+            auto rc = randomCover(a);
+            static assert(isInputRange!(typeof(rc)));
+            static assert(!isForwardRange!(typeof(rc)));
+        }
+        else
+        {
+            auto rng = UniformRNG(unpredictableSeed);
+            auto rc = randomCover(a, rng);
+            static assert(isForwardRange!(typeof(rc)));
+            // check for constructor passed a value-type RNG
+            auto rc2 = RandomCover!(int[], UniformRNG)(a, UniformRNG(unpredictableSeed));
+            static assert(isForwardRange!(typeof(rc2)));
+        }
+
+        int[] b = new int[9];
+        uint i;
+        foreach (e; rc)
+        {
+            //writeln(e);
+            b[i++] = e;
+        }
+        sort(b);
+        assert(a == b, text(b));
     }
-    sort(b);
-    assert(a == b, text(b));
 }
 
 // RandomSample
@@ -1582,10 +1915,22 @@ range. The total length of $(D r) must be known. If $(D total) is
 passed in, the total number of sample is considered to be $(D
 total). Otherwise, $(D RandomSample) uses $(D r.length).
 
-If the number of elements is not exactly $(D total), $(D
-RandomSample) throws an exception. This is because $(D total) is
-essential to computing the probability of selecting elements in the
-range.
+$(D RandomSample) implements Jeffrey Scott Vitter's Algorithm D
+(see Vitter $(WEB dx.doi.org/10.1145/358105.893, 1984), $(WEB
+dx.doi.org/10.1145/23002.23003, 1987)), which selects a sample
+of size $(D n) in O(n) steps and requiring O(n) random variates,
+regardless of the size of the data being sampled.  The exception
+to this is if traversing k elements on the input range is itself
+an O(k) operation (e.g. when sampling lines from an input file),
+in which case the sampling calculation will inevitably be of
+O(total).
+
+RandomSample will throw an exception if $(D total) is verifiably
+less than the total number of elements available in the input,
+or if $(D n > total).
+
+If no random number generator is passed to $(D randomSample), the
+thread-global RNG rndGen will be used internally.
 
 Example:
 ----
@@ -1597,71 +1942,128 @@ foreach (e; randomSample(a, 5))
 }
 ----
 
-$(D RandomSample) implements Jeffrey Scott Vitter's Algorithm D
-(see Vitter $(WEB dx.doi.org/10.1145/358105.893, 1984), $(WEB
-dx.doi.org/10.1145/23002.23003, 1987)), which selects a sample
-of size $(D n) in O(n) steps and requiring O(n) random variates,
-regardless of the size of the data being sampled.
+$(B WARNING:) If an alternative RNG is desired, it is essential for this
+to be a $(I new) RNG seeded in an unpredictable manner. Passing it a RNG
+used elsewhere in the program will result in unintended correlations,
+due to the current implementation of RNGs as value types.
+
+Example:
+----
+int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
+foreach (e; randomSample(a, 5, Random(unpredictableSeed)))  // correct!
+{
+    writeln(e);
+}
+
+foreach (e; randomSample(a, 5, rndGen))  // DANGEROUS!! rndGen gets
+{                                        // copied by value
+    writeln(e);
+}
+
+foreach (e; randomSample(a, 5, rndGen))  // ... so this second random
+{                                        // sample will select the same
+    writeln(e);                          // values as the previous one.
+}
+----
+
+These issues will be resolved in a second-generation std.random that
+re-implements random number generators as reference types.
 */
-struct RandomSample(R, Random = void)
-    if(isInputRange!R && (isUniformRNG!Random || is(Random == void)))
+struct RandomSample(Range, UniformRNG = void)
+    if (isInputRange!Range && (isUniformRNG!UniformRNG || is(UniformRNG == void)))
 {
     private size_t _available, _toSelect;
     private enum ushort _alphaInverse = 13; // Vitter's recommended value.
-    private bool _first, _algorithmA;
     private double _Vprime;
-    private R _input;
+    private Range _input;
     private size_t _index;
+    private enum Skip { None, A, D };
+    private Skip _skip = Skip.None;
 
     // If we're using the default thread-local random number generator then
-    // we shouldn't store a copy of it here.  Random == void is a sentinel
+    // we shouldn't store a copy of it here.  UniformRNG == void is a sentinel
     // for this.  If we're using a user-specified generator then we have no
     // choice but to store a copy.
-    static if(!is(Random == void))
+    static if (is(UniformRNG == void))
     {
-        Random _gen;
-
-        static if (hasLength!R)
+        static if (hasLength!Range)
         {
-            this(R input, size_t howMany, Random gen)
+            this(Range input, size_t howMany)
             {
-                _gen = gen;
                 _input = input;
                 initialize(howMany, input.length);
             }
         }
 
-        this(R input, size_t howMany, size_t total, Random gen)
+        this(Range input, size_t howMany, size_t total)
         {
-            _gen = gen;
             _input = input;
             initialize(howMany, total);
         }
     }
     else
     {
-        static if (hasLength!R)
+        UniformRNG _rng;
+
+        static if (hasLength!Range)
         {
-            this(R input, size_t howMany)
+            this(Range input, size_t howMany, ref UniformRNG rng)
             {
+                _rng = rng;
                 _input = input;
                 initialize(howMany, input.length);
             }
+
+            this(Range input, size_t howMany, UniformRNG rng)
+            {
+                this(input, howMany, rng);
+            }
         }
 
-        this(R input, size_t howMany, size_t total)
+        this(Range input, size_t howMany, size_t total, ref UniformRNG rng)
         {
+            _rng = rng;
             _input = input;
             initialize(howMany, total);
         }
+
+        this(Range input, size_t howMany, size_t total, UniformRNG rng)
+        {
+            this(input, howMany, total, rng);
+        }
     }
 
     private void initialize(size_t howMany, size_t total)
     {
         _available = total;
         _toSelect = howMany;
-        enforce(_toSelect <= _available);
-        _first = true;
+        enforce(_toSelect <= _available,
+                text("RandomSample: cannot sample ", _toSelect,
+                     " items when only ", _available, " are available"));
+        static if (hasLength!Range)
+        {
+            enforce(_available <= _input.length,
+                    text("RandomSample: specified ", _available,
+                         " items as available when input contains only ",
+                         _input.length));
+        }
+    }
+
+    private void initializeFront()
+    {
+        assert(_skip == Skip.None);
+        // We can save ourselves a random variate by checking right
+        // at the beginning if we should use Algorithm A.
+        if ((_alphaInverse * _toSelect) > _available)
+        {
+            _skip = Skip.A;
+        }
+        else
+        {
+            _skip = Skip.D;
+            _Vprime = newVprime(_toSelect);
+        }
+        prime();
     }
 
 /**
@@ -1679,21 +2081,9 @@ struct RandomSample(R, Random = void)
         // having it always correspond to the first element of the
         // input.  The rest of the sample points are determined each
         // time we call popFront().
-        if(_first)
+        if (_skip == Skip.None)
         {
-            // We can save ourselves a random variate by checking right
-            // at the beginning if we should use Algorithm A.
-            if((_alphaInverse * _toSelect) > _available)
-            {
-                _algorithmA = true;
-            }
-            else
-            {
-                _Vprime = newVprime(_toSelect);
-                _algorithmA = false;
-            }
-            prime();
-            _first = false;
+            initializeFront();
         }
         return _input.front;
     }
@@ -1701,6 +2091,13 @@ struct RandomSample(R, Random = void)
 /// Ditto
     void popFront()
     {
+        // First we need to check if the sample has
+        // been initialized in the first place.
+        if (_skip == Skip.None)
+        {
+            initializeFront();
+        }
+
         _input.popFront();
         --_available;
         --_toSelect;
@@ -1709,12 +2106,13 @@ struct RandomSample(R, Random = void)
     }
 
 /// Ditto
-    static if(isForwardRange!R)
+    static if (isForwardRange!Range && isForwardRange!UniformRNG)
     {
         @property typeof(this) save()
         {
             auto ret = this;
             ret._input = _input.save;
+            ret._rng = _rng.save;
             return ret;
         }
     }
@@ -1728,11 +2126,42 @@ struct RandomSample(R, Random = void)
 /**
 Returns the index of the visited record.
  */
-    size_t index()
+    @property size_t index()
     {
+        if (_skip == Skip.None)
+        {
+            initializeFront();
+        }
         return _index;
     }
 
+    private size_t skip()
+    {
+        assert(_skip != Skip.None);
+
+        // Step D1: if the number of points still to select is greater
+        // than a certain proportion of the remaining data points, i.e.
+        // if n >= alpha * N where alpha = 1/13, we carry out the
+        // sampling with Algorithm A.
+        if (_skip == Skip.A)
+        {
+            return skipA();
+        }
+        else if ((_alphaInverse * _toSelect) > _available)
+        {
+            // We shouldn't get here unless the current selected
+            // algorithm is D.
+            assert(_skip == Skip.D);
+            _skip = Skip.A;
+            return skipA();
+        }
+        else
+        {
+            assert(_skip == Skip.D);
+            return skipD();
+        }
+    }
+
 /*
 Vitter's Algorithm A, used when the ratio of needed sample values
 to remaining data values is sufficiently large.
@@ -1742,15 +2171,15 @@ to remaining data values is sufficiently large.
         size_t s;
         double v, quot, top;
 
-        if(_toSelect==1)
+        if (_toSelect==1)
         {
-            static if(is(Random==void))
+            static if (is(UniformRNG == void))
             {
                 s = uniform(0, _available);
             }
             else
             {
-                s = uniform(0, _available, _gen);
+                s = uniform(0, _available, _rng);
             }
         }
         else
@@ -1759,13 +2188,13 @@ to remaining data values is sufficiently large.
             top = _available - _toSelect;
             quot = top / _available;
 
-            static if(is(Random==void))
+            static if (is(UniformRNG == void))
             {
                 v = uniform!"()"(0.0, 1.0);
             }
             else
             {
-                v = uniform!"()"(0.0, 1.0, _gen);
+                v = uniform!"()"(0.0, 1.0, _rng);
             }
 
             while (quot > v)
@@ -1783,13 +2212,13 @@ Randomly reset the value of _Vprime.
 */
     private double newVprime(size_t remaining)
     {
-        static if(is(Random == void))
+        static if (is(UniformRNG == void))
         {
             double r = uniform!"()"(0.0, 1.0);
         }
         else
         {
-            double r = uniform!"()"(0.0, 1.0, _gen);
+            double r = uniform!"()"(0.0, 1.0, _rng);
         }
 
         return r ^^ (1.0 / remaining);
@@ -1807,45 +2236,38 @@ and its rationale, see:
 
 Variable names are chosen to match those in Vitter's paper.
 */
-    private size_t skip()
+    private size_t skipD()
     {
-        // Step D1: if the number of points still to select is greater
-        // than a certain proportion of the remaining data points, i.e.
-        // if n >= alpha * N where alpha = 1/13, we carry out the
-        // sampling with Algorithm A.
-        if(_algorithmA)
-        {
-            return skipA();
-        }
-        else if((_alphaInverse * _toSelect) > _available)
-        {
-            _algorithmA = true;
-            return skipA();
-        }
-        // Otherwise, we use the standard Algorithm D mechanism.
-        else if ( _toSelect > 1 )
+        // Confirm that the check in Step D1 is valid and we
+        // haven't been sent here by mistake
+        assert((_alphaInverse * _toSelect) <= _available);
+
+        // Now it's safe to use the standard Algorithm D mechanism.
+        if (_toSelect > 1)
         {
             size_t s;
             size_t qu1 = 1 + _available - _toSelect;
             double x, y1;
 
-            while(true)
+            assert(!_Vprime.isNaN);
+
+            while (true)
             {
                 // Step D2: set values of x and u.
-                for(x = _available * (1-_Vprime), s = cast(size_t) trunc(x);
-                    s >= qu1;
-                    x = _available * (1-_Vprime), s = cast(size_t) trunc(x))
+                for (x = _available * (1-_Vprime), s = cast(size_t) trunc(x);
+                     s >= qu1;
+                     x = _available * (1-_Vprime), s = cast(size_t) trunc(x))
                 {
                     _Vprime = newVprime(_toSelect);
                 }
 
-                static if(is(Random == void))
+                static if (is(UniformRNG == void))
                 {
                     double u = uniform!"()"(0.0, 1.0);
                 }
                 else
                 {
-                    double u = uniform!"()"(0.0, 1.0, _gen);
+                    double u = uniform!"()"(0.0, 1.0, _rng);
                 }
 
                 y1 = (u * (cast(double) _available) / qu1) ^^ (1.0/(_toSelect - 1));
@@ -1854,12 +2276,12 @@ Variable names are chosen to match those in Vitter's paper.
 
                 // Step D3: if _Vprime <= 1.0 our work is done and we return S.
                 // Otherwise ...
-                if(_Vprime > 1.0)
+                if (_Vprime > 1.0)
                 {
                     size_t top = _available - 1, limit;
                     double y2 = 1.0, bottom;
 
-                    if(_toSelect > (s+1) )
+                    if (_toSelect > (s+1))
                     {
                         bottom = _available - _toSelect;
                         limit = _available - s;
@@ -1870,7 +2292,7 @@ Variable names are chosen to match those in Vitter's paper.
                         limit = qu1;
                     }
 
-                    foreach(size_t t; limit.._available)
+                    foreach (size_t t; limit .. _available)
                     {
                         y2 *= top/bottom;
                         top--;
@@ -1878,10 +2300,10 @@ Variable names are chosen to match those in Vitter's paper.
                     }
 
                     // Step D4: decide whether or not to accept the current value of S.
-                    if( (_available/(_available-x)) < (y1 * (y2 ^^ (1.0/(_toSelect-1)))) )
+                    if (_available/(_available-x) < y1 * (y2 ^^ (1.0/(_toSelect-1))))
                     {
                         // If it's not acceptable, we generate a new value of _Vprime
-                        // and go back to the start of the for(;;) loop.
+                        // and go back to the start of the for (;;) loop.
                         _Vprime = newVprime(_toSelect);
                     }
                     else
@@ -1909,97 +2331,366 @@ Variable names are chosen to match those in Vitter's paper.
 
     private void prime()
     {
-        if (empty) return;
+        if (empty)
+        {
+            return;
+        }
         assert(_available && _available >= _toSelect);
         immutable size_t s = skip();
-        _input.popFrontN(s);
+        assert(s + _toSelect <= _available);
+        static if (hasLength!Range)
+        {
+            assert(s + _toSelect <= _input.length);
+        }
+        assert(!_input.empty);
+        _input.popFrontExactly(s);
         _index += s;
         _available -= s;
         assert(_available > 0);
-        return;
     }
 }
 
 /// Ditto
-auto randomSample(R)(R r, size_t n, size_t total)
-if(isInputRange!R)
+auto randomSample(Range)(Range r, size_t n, size_t total)
+    if (isInputRange!Range)
 {
-    return RandomSample!(R, void)(r, n, total);
+    return RandomSample!(Range, void)(r, n, total);
 }
 
 /// Ditto
-auto randomSample(R)(R r, size_t n)
-    if(isInputRange!R && hasLength!R)
+auto randomSample(Range)(Range r, size_t n)
+    if (isInputRange!Range && hasLength!Range)
 {
-    return RandomSample!(R, void)(r, n, r.length);
+    return RandomSample!(Range, void)(r, n, r.length);
 }
 
 /// Ditto
-auto randomSample(R, Random)(R r, size_t n, size_t total, Random gen)
-if(isInputRange!R && isUniformRNG!Random)
+auto randomSample(Range, UniformRNG)(Range r, size_t n, size_t total, auto ref UniformRNG rng)
+    if (isInputRange!Range && isUniformRNG!UniformRNG)
 {
-    return RandomSample!(R, Random)(r, n, total, gen);
+    return RandomSample!(Range, UniformRNG)(r, n, total, rng);
 }
 
 /// Ditto
-auto randomSample(R, Random)(R r, size_t n, Random gen)
-if (isInputRange!R && hasLength!R && isUniformRNG!Random)
+auto randomSample(Range, UniformRNG)(Range r, size_t n, auto ref UniformRNG rng)
+    if (isInputRange!Range && hasLength!Range && isUniformRNG!UniformRNG)
 {
-    return RandomSample!(R, Random)(r, n, r.length, gen);
+    return RandomSample!(Range, UniformRNG)(r, n, r.length, rng);
 }
 
 unittest
 {
-    Random gen;
-    int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
-    static assert(isForwardRange!(typeof(randomSample(a, 5))));
-    static assert(isForwardRange!(typeof(randomSample(a, 5, gen))));
-
+    // For test purposes, an infinite input range
     struct TestInputRange
     {
-        private int[] arr = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
-        @property bool empty() const { return arr.empty; }
-        @property int front() const { return arr.front; }
-        void popFront() { arr.popFront(); }
+        private auto r = recurrence!"a[n-1] + 1"(0);
+        bool empty() @property const pure nothrow { return r.empty; }
+        auto front() @property pure nothrow { return r.front; }
+        void popFront() pure nothrow { r.popFront(); }
     }
     static assert(isInputRange!TestInputRange);
-    TestInputRange input;
-    static assert(isInputRange!(typeof(randomSample(input, 5, 10))));
-    static assert(isInputRange!(typeof(randomSample(input, 5, 10, gen))));
+    static assert(!isForwardRange!TestInputRange);
 
-    struct TestInputRangeWithLength
+    int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
+
+    foreach (UniformRNG; PseudoRngTypes)
     {
-        private int[] arr = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
-        @property bool empty() const { return arr.empty; }
-        @property int front() const { return arr.front; }
-        void popFront() { arr.popFront(); }
-        @property size_t length() const { return arr.length; }
-    }
-    static assert(isInputRange!TestInputRangeWithLength);
-    static assert(hasLength!TestInputRangeWithLength);
-    TestInputRangeWithLength inputWithLength;
-    static assert(isInputRange!(typeof(randomSample(inputWithLength, 5))));
-    static assert(isInputRange!(typeof(randomSample(inputWithLength, 5, gen))));
+        auto rng = UniformRNG(unpredictableSeed);
+        /* First test the most general case: randomSample of input range, with and
+         * without a specified random number generator.
+         */
+        static assert(isInputRange!(typeof(randomSample(TestInputRange(), 5, 10))));
+        static assert(isInputRange!(typeof(randomSample(TestInputRange(), 5, 10, rng))));
+        static assert(!isForwardRange!(typeof(randomSample(TestInputRange(), 5, 10))));
+        static assert(!isForwardRange!(typeof(randomSample(TestInputRange(), 5, 10, rng))));
+        // test case with range initialized by direct call to struct
+        {
+            auto sample =
+                RandomSample!(TestInputRange, UniformRNG)
+                             (TestInputRange(), 5, 10, UniformRNG(unpredictableSeed));
+            static assert(isInputRange!(typeof(sample)));
+            static assert(!isForwardRange!(typeof(sample)));
+        }
 
-    //int[] a = [ 0, 1, 2 ];
-    assert(randomSample(a, 5).length == 5);
-    assert(randomSample(a, 5, 10).length == 5);
-    assert(randomSample(a, 5, gen).length == 5);
-    uint i;
-    foreach (e; randomSample(randomCover(a, rndGen), 5))
-    {
-        ++i;
-        //writeln(e);
-    }
-    assert(i == 5);
+        /* Now test the case of an input range with length.  We ignore the cases
+         * already covered by the previous tests.
+         */
+        static assert(isInputRange!(typeof(randomSample(TestInputRange().takeExactly(10), 5))));
+        static assert(isInputRange!(typeof(randomSample(TestInputRange().takeExactly(10), 5, rng))));
+        static assert(!isForwardRange!(typeof(randomSample(TestInputRange().takeExactly(10), 5))));
+        static assert(!isForwardRange!(typeof(randomSample(TestInputRange().takeExactly(10), 5, rng))));
+        // test case with range initialized by direct call to struct
+        {
+            auto sample =
+                RandomSample!(typeof(TestInputRange().takeExactly(10)), UniformRNG)
+                             (TestInputRange().takeExactly(10), 5, 10, UniformRNG(unpredictableSeed));
+            static assert(isInputRange!(typeof(sample)));
+            static assert(!isForwardRange!(typeof(sample)));
+        }
 
-    // Bugzilla 8314
-    {
-        auto sample(uint seed) { return randomSample(a, 1, Random(seed)).front; }
+        // Now test the case of providing a forward range as input.
+        static assert(!isForwardRange!(typeof(randomSample(a, 5))));
+        static if (isForwardRange!UniformRNG)
+        {
+            static assert(isForwardRange!(typeof(randomSample(a, 5, rng))));
+            // ... and test with range initialized directly
+            {
+                auto sample =
+                    RandomSample!(int[], UniformRNG)
+                                 (a, 5, UniformRNG(unpredictableSeed));
+                static assert(isForwardRange!(typeof(sample)));
+            }
+        }
+        else
+        {
+            static assert(isInputRange!(typeof(randomSample(a, 5, rng))));
+            static assert(!isForwardRange!(typeof(randomSample(a, 5, rng))));
+            // ... and test with range initialized directly
+            {
+                auto sample =
+                    RandomSample!(int[], UniformRNG)
+                                 (a, 5, UniformRNG(unpredictableSeed));
+                static assert(isInputRange!(typeof(sample)));
+                static assert(!isForwardRange!(typeof(sample)));
+            }
+        }
 
-        immutable fst = sample(0);
-        uint n;
-        while (sample(++n) == fst && n < n.max) {}
-        assert(n < n.max);
+        /* Check that randomSample will throw an error if we claim more
+         * items are available than there actually are, or if we try to
+         * sample more items than are available. */
+        assert(collectExceptionMsg(randomSample(a, 5, 15)) == "RandomSample: specified 15 items as available when input contains only 10");
+        assert(collectExceptionMsg(randomSample(a, 15)) == "RandomSample: cannot sample 15 items when only 10 are available");
+        assert(collectExceptionMsg(randomSample(a, 9, 8)) == "RandomSample: cannot sample 9 items when only 8 are available");
+        assert(collectExceptionMsg(randomSample(TestInputRange(), 12, 11)) == "RandomSample: cannot sample 12 items when only 11 are available");
+
+        /* Check that sampling algorithm never accidentally overruns the end of
+         * the input range.  If input is an InputRange without .length, this
+         * relies on the user specifying the total number of available items
+         * correctly.
+         */
+        {
+            uint i = 0;
+            foreach (e; randomSample(a, a.length))
+            {
+                assert(e == i);
+                ++i;
+            }
+            assert(i == a.length);
+
+            i = 0;
+            foreach (e; randomSample(TestInputRange(), 17, 17))
+            {
+                assert(e == i);
+                ++i;
+            }
+            assert(i == 17);
+        }
+
+
+        // Check length properties of random samples.
+        assert(randomSample(a, 5).length == 5);
+        assert(randomSample(a, 5, 10).length == 5);
+        assert(randomSample(a, 5, rng).length == 5);
+        assert(randomSample(a, 5, 10, rng).length == 5);
+        assert(randomSample(TestInputRange(), 5, 10).length == 5);
+        assert(randomSample(TestInputRange(), 5, 10, rng).length == 5);
+
+        // ... and emptiness!
+        assert(randomSample(a, 0).empty);
+        assert(randomSample(a, 0, 5).empty);
+        assert(randomSample(a, 0, rng).empty);
+        assert(randomSample(a, 0, 5, rng).empty);
+        assert(randomSample(TestInputRange(), 0, 10).empty);
+        assert(randomSample(TestInputRange(), 0, 10, rng).empty);
+
+        /* Test that the (lazy) evaluation of random samples works correctly.
+         *
+         * We cover 2 different cases: a sample where the ratio of sample points
+         * to total points is greater than the threshold for using Algorithm, and
+         * one where the ratio is small enough (< 1/13) for Algorithm D to be used.
+         *
+         * For each, we also cover the case with and without a specified RNG.
+         */
+        {
+            // Small sample/source ratio, no specified RNG.
+            uint i = 0;
+            foreach (e; randomSample(randomCover(a), 5))
+            {
+                ++i;
+            }
+            assert(i == 5);
+
+            // Small sample/source ratio, specified RNG.
+            i = 0;
+            foreach (e; randomSample(randomCover(a), 5, rng))
+            {
+                ++i;
+            }
+            assert(i == 5);
+
+            // Large sample/source ratio, no specified RNG.
+            i = 0;
+            foreach (e; randomSample(TestInputRange(), 123, 123_456))
+            {
+                ++i;
+            }
+            assert(i == 123);
+
+            // Large sample/source ratio, specified RNG.
+            i = 0;
+            foreach (e; randomSample(TestInputRange(), 123, 123_456, rng))
+            {
+                ++i;
+            }
+            assert(i == 123);
+
+            /* Sample/source ratio large enough to start with Algorithm D,
+             * small enough to switch to Algorithm A.
+             */
+            i = 0;
+            foreach (e; randomSample(TestInputRange(), 10, 131))
+            {
+                ++i;
+            }
+            assert(i == 10);
+        }
+
+        // Test that the .index property works correctly
+        {
+            auto sample1 = randomSample(TestInputRange(), 654, 654_321);
+            for (; !sample1.empty; sample1.popFront())
+            {
+                assert(sample1.front == sample1.index);
+            }
+
+            auto sample2 = randomSample(TestInputRange(), 654, 654_321, rng);
+            for (; !sample2.empty; sample2.popFront())
+            {
+                assert(sample2.front == sample2.index);
+            }
+
+            /* Check that it also works if .index is called before .front.
+             * See: http://d.puremagic.com/issues/show_bug.cgi?id=10322
+             */
+            auto sample3 = randomSample(TestInputRange(), 654, 654_321);
+            for (; !sample3.empty; sample3.popFront())
+            {
+                assert(sample3.index == sample3.front);
+            }
+
+            auto sample4 = randomSample(TestInputRange(), 654, 654_321, rng);
+            for (; !sample4.empty; sample4.popFront())
+            {
+                assert(sample4.index == sample4.front);
+            }
+        }
+
+        /* Test behaviour if .popFront() is called before sample is read.
+         * This is a rough-and-ready check that the statistical properties
+         * are in the ballpark -- not a proper validation of statistical
+         * quality!  This incidentally also checks for reference-type
+         * initialization bugs, as the foreach() loop will operate on a
+         * copy of the popFronted (and hence initialized) sample.
+         */
+        {
+            size_t count0, count1, count99;
+            foreach(_; 0 .. 100_000)
+            {
+                auto sample = randomSample(iota(100), 5);
+                sample.popFront();
+                foreach(s; sample)
+                {
+                    if (s == 0)
+                    {
+                        ++count0;
+                    }
+                    else if (s == 1)
+                    {
+                        ++count1;
+                    }
+                    else if (s == 99)
+                    {
+                        ++count99;
+                    }
+                }
+            }
+            /* Statistical assumptions here: this is a sequential sampling process
+             * so (i) 0 can only be the first sample point, so _can't_ be in the
+             * remainder of the sample after .popFront() is called. (ii) By similar
+             * token, 1 can only be in the remainder if it's the 2nd point of the
+             * whole sample, and hence if 0 was the first; probability of 0 being
+             * first and 1 second is 5/100 * 4/99 (thank you, Algorithm S:-) and
+             * so the mean count of 1 should be about 202.  Finally, 99 can only
+             * be the _last_ sample point to be picked, so its probability of
+             * inclusion should be independent of the .popFront() and it should
+             * occur with frequency 5/100, hence its count should be about 5000.
+             * Unfortunately we have to set quite a high tolerance because with
+             * sample size small enough for unittests to run in reasonable time,
+             * the variance can be quite high.
+             */
+            assert(count0 == 0);
+            assert(count1 < 300, text("1: ", count1, " > 300."));
+            assert(4_700 < count99, text("99: ", count99, " < 4700."));
+            assert(count99 < 5_300, text("99: ", count99, " > 5300."));
+        }
+
+        /* Odd corner-cases: RandomSample has 2 constructors that are not called
+         * by the randomSample() helper functions, but that can be used if the
+         * constructor is called directly.  These cover the case of the user
+         * specifying input but not input length.
+         */
+        {
+            auto input1 = TestInputRange().takeExactly(456_789);
+            static assert(hasLength!(typeof(input1)));
+            auto sample1 = RandomSample!(typeof(input1), void)(input1, 789);
+            static assert(isInputRange!(typeof(sample1)));
+            static assert(!isForwardRange!(typeof(sample1)));
+            assert(sample1.length == 789);
+            assert(sample1._available == 456_789);
+            uint i = 0;
+            for (; !sample1.empty; sample1.popFront())
+            {
+                assert(sample1.front == sample1.index);
+                ++i;
+            }
+            assert(i == 789);
+
+            auto input2 = TestInputRange().takeExactly(456_789);
+            static assert(hasLength!(typeof(input2)));
+            auto sample2 = RandomSample!(typeof(input2), typeof(rng))(input2, 789, rng);
+            static assert(isInputRange!(typeof(sample2)));
+            static assert(!isForwardRange!(typeof(sample2)));
+            assert(sample2.length == 789);
+            assert(sample2._available == 456_789);
+            i = 0;
+            for (; !sample2.empty; sample2.popFront())
+            {
+                assert(sample2.front == sample2.index);
+                ++i;
+            }
+            assert(i == 789);
+        }
+
+        /* Test that the save property works where input is a forward range,
+         * and RandomSample is using a (forward range) random number generator
+         * that is not rndGen.
+         */
+        static if (isForwardRange!UniformRNG)
+        {
+            auto sample1 = randomSample(a, 5, rng);
+            auto sample2 = sample1.save;
+            assert(sample1.array() == sample2.array());
+        }
+
+        // Bugzilla 8314
+        {
+            auto sample(RandomGen)(uint seed) { return randomSample(a, 1, RandomGen(seed)).front; }
+
+            // Start from 1 because not all RNGs accept 0 as seed.
+            immutable fst = sample!UniformRNG(1);
+            uint n = 1;
+            while (sample!UniformRNG(++n) == fst && n < n.max) {}
+            assert(n < n.max);
+        }
     }
 }
diff --git a/std/range.d b/std/range.d
index e564d810d..7aa63c5ac 100644
--- a/std/range.d
+++ b/std/range.d
@@ -181,14 +181,14 @@ $(BOOKTABLE ,
         _range.
     ))
     $(TR $(TD $(D $(LREF only)))
-        $(TD Creates a _range that iterates over a single value.
+        $(TD Creates a _range that iterates over the given arguments.
     ))
 )
 
 These _range-construction tools are implemented using templates; but sometimes
 an object-based interface for ranges is needed. For this purpose, this module
 provides a number of object and $(D interface) definitions that can be used to
-wrap around _range objects created by the above templates:
+wrap around _range objects created by the above templates.
 
 $(BOOKTABLE ,
     $(TR $(TD $(D $(LREF InputRange)))
@@ -229,6 +229,9 @@ $(BOOKTABLE ,
         $(TD Class that implements the $(D InputRange) interface and wraps the
         input _range methods in virtual functions.
     ))
+    $(TR $(TD $(D $(LREF RefRange)))
+        $(TD Wrapper around a forward _range that gives it reference semantics.
+    ))
 )
 
 Ranges whose elements are sorted afford better efficiency with certain
@@ -547,77 +550,212 @@ unittest
     static assert( isInputRange!(inout(int)[])); // bug 7824
 }
 
-/**
-Outputs $(D e) to $(D r). The exact effect is dependent upon the two
-types. Several cases are accepted, as described below. The code snippets
-are attempted in order, and the first to compile "wins" and gets
-evaluated.
+/+
+puts the whole raw element $(D t) into $(D r). doPut will not attempt to
+iterate, slice or transcode $(D t) in any way shape or form. It will $(B only)
+call the correct primitive ($(D r.put(t)),  $(D r.front = t) or
+$(D r(0)) once.
 
-$(BOOKTABLE ,
-$(TR $(TH Code Snippet) $(TH Scenario
-))
-$(TR $(TD $(D r.put(e);)) $(TD $(D R) specifically defines a method
-    $(D put) accepting an $(D E).
-))
-$(TR $(TD $(D r.put([ e ]);)) $(TD $(D R) specifically defines a
-    method $(D put) accepting an $(D E[]).
-))
-$(TR $(TD $(D r.front = e; r.popFront();)) $(TD $(D R) is an input
-    range and $(D e) is assignable to $(D r.front).
-))
-$(TR $(TD $(D for (; !e.empty; e.popFront()) put(r, e.front);)) $(TD
-    Copying range $(D E) to range $(D R).
-))
-$(TR $(TD $(D r(e);)) $(TD $(D R) is e.g. a delegate accepting an $(D
-    E).
-))
-$(TR $(TD $(D r([ e ]);)) $(TD $(D R) is e.g. a $(D delegate)
-    accepting an $(D E[]).
-))
-)
- */
-void put(R, E)(ref R r, E e)
+This can be important when $(D t) needs to be placed in $(D r) unchanged.
+Furthermore, it can be useful when working with $(D InputRange)s, as doPut
+guarantees that no more than a single element will be placed.
++/
+package void doPut(R, E)(ref R r, auto ref E e)
 {
     static if(is(PointerTarget!R == struct))
         enum usingPut = hasMember!(PointerTarget!R, "put");
     else
         enum usingPut = hasMember!(R, "put");
 
-    enum usingFront = !usingPut && isInputRange!R;
-    enum usingCall = !usingPut && !usingFront;
-
-    static if (usingPut && is(typeof(r.put(e))))
+    static if (usingPut)
     {
+        static assert(is(typeof(r.put(e))),
+            format("Cannot nativaly put a %s into a %s.", E.stringof, R.stringof));
         r.put(e);
     }
-    else static if (usingPut && is(typeof(r.put((E[]).init))))
-    {
-        r.put((&e)[0..1]);
-    }
-    else static if (usingFront && is(typeof(r.front = e, r.popFront())))
+    else static if (isInputRange!R)
     {
+        static assert(is(typeof(r.front = e)),
+            format("Cannot nativaly put a %s into a %s.", E.stringof, R.stringof));
         r.front = e;
         r.popFront();
     }
-    else static if ((usingPut || usingFront) && isInputRange!E && is(typeof(put(r, e.front))))
-    {
-        for (; !e.empty; e.popFront()) put(r, e.front);
-    }
-    else static if (usingCall && is(typeof(r(e))))
-    {
-        r(e);
-    }
-    else static if (usingCall && is(typeof(r((E[]).init))))
-    {
-        r((&e)[0..1]);
-    }
     else
     {
-        static assert(false,
-                "Cannot put a "~E.stringof~" into a "~R.stringof);
+        static assert(is(typeof(r(e))),
+            format("Cannot nativaly put a %s into a %s.", E.stringof, R.stringof));
+        r(e);
     }
 }
 
+unittest
+{
+    static assert (!isNativeOutputRange!(int,     int));
+    static assert ( isNativeOutputRange!(int[],   int));
+    static assert (!isNativeOutputRange!(int[][], int));
+
+    static assert (!isNativeOutputRange!(int,     int[]));
+    static assert (!isNativeOutputRange!(int[],   int[]));
+    static assert ( isNativeOutputRange!(int[][], int[]));
+
+    static assert (!isNativeOutputRange!(int,     int[][]));
+    static assert (!isNativeOutputRange!(int[],   int[][]));
+    static assert (!isNativeOutputRange!(int[][], int[][]));
+
+    static assert (!isNativeOutputRange!(int[4],   int));
+    static assert ( isNativeOutputRange!(int[4][], int)); //Scary!
+    static assert ( isNativeOutputRange!(int[4][], int[4]));
+
+    static assert (!isNativeOutputRange!( char[],   char));
+    static assert (!isNativeOutputRange!( char[],  dchar));
+    static assert ( isNativeOutputRange!(dchar[],   char));
+    static assert ( isNativeOutputRange!(dchar[],  dchar));
+
+}
+
+/++
+Outputs $(D e) to $(D r). The exact effect is dependent upon the two
+types. Several cases are accepted, as described below. The code snippets
+are attempted in order, and the first to compile "wins" and gets
+evaluated.
+
+In this table "doPut" is a method that places $(D e) into $(D r), using the
+correct primitive: $(D r.put(e)) if $(D R) defines $(D put), $(D r.front = e) if $(D r) is an input
+range (followed by $(D r.popFront()), or $(D r(e)) otherwise.
+
+$(BOOKTABLE ,
+    $(TR
+        $(TH Code Snippet)
+        $(TH Scenario)
+    )
+    $(TR
+        $(TD $(D r.doPut(e);))
+        $(TD $(D R) specifically accepts an $(D E).)
+    )
+    $(TR
+        $(TD $(D r.doPut([ e ]);))
+        $(TD $(D R) specifically accepts an $(D E[]).)
+    )
+    $(TR
+        $(TD $(D r.putChar(e);))
+        $(TD $(D R) accepts some form of string or character. put will
+            transcode the character $(D e) accordingly.)
+    )
+    $(TR
+        $(TD $(D for (; !e.empty; e.popFront()) put(r, e.front);))
+        $(TD Copying range $(D E) into $(D R).)
+    )
+)
+
+Tip: $(D put) should $(I not) be used "UFCS-style", eg $(D r.put(e)).
+Doing this may call $(D R.put) directly, by-passing any transformation
+feature provided by $(D Range.put). $(D put(r, e)) is prefered.
+ +/
+void put(R, E)(ref R r, E e)
+{
+    @property ref E[] EArrayInit(); //@@@9186@@@: Can't use (E[]).init
+
+    //First level: simply straight up put.
+    static if (is(typeof(doPut(r, e))))
+    {
+        doPut(r, e);
+    }
+    //Optional optimization block for straight up array to array copy.
+    else static if (isDynamicArray!R && !isNarrowString!R && isDynamicArray!E && is(typeof(r[] = e[])))
+    {
+        immutable len = e.length;
+        r[0 .. len] = e[];
+        r = r[len .. $];
+    }
+    //Accepts E[] ?
+    else static if (is(typeof(doPut(r, [e]))) && !isDynamicArray!R)
+    {
+        if (__ctfe)
+            doPut(r, [e]);
+        else
+            doPut(r, (&e)[0..1]);
+    }
+    //special case for char to string.
+    else static if (isSomeChar!E && is(typeof(putChar(r, e))))
+    {
+        putChar(r, e);
+    }
+    //Extract each element from the range
+    //We can use "put" here, so we can recursively test a RoR of E.
+    else static if (isInputRange!E && is(typeof(put(r, e.front))))
+    {
+        //Special optimization: If E is a narrow string, and r accepts characters no-wider than the string's
+        //Then simply feed the characters 1 by 1.
+        static if (isNarrowString!E && (
+            (is(E : const  char[]) && is(typeof(doPut(r,  char.max))) && !is(typeof(doPut(r, dchar.max))) && !is(typeof(doPut(r, wchar.max)))) ||
+            (is(E : const wchar[]) && is(typeof(doPut(r, wchar.max))) && !is(typeof(doPut(r, dchar.max)))) ) )
+        {
+            foreach(c; e)
+                doPut(r, c);
+        }
+        else
+        {
+            for (; !e.empty; e.popFront())
+                put(r, e.front);
+        }
+    }
+    else
+        static assert (false, format("Cannot put a %s into a %s.", E.stringof, R.stringof));
+}
+
+//Helper function to handle chars as quickly and as elegantly as possible
+//Assumes r.put(e)/r(e) has already been tested
+private void putChar(R, E)(ref R r, E e)
+if (isSomeChar!E)
+{
+    ////@@@9186@@@: Can't use (E[]).init
+    ref const( char)[] cstringInit();
+    ref const(wchar)[] wstringInit();
+    ref const(dchar)[] dstringInit();
+
+    enum csCond = !isDynamicArray!R && is(typeof(doPut(r, cstringInit())));
+    enum wsCond = !isDynamicArray!R && is(typeof(doPut(r, wstringInit())));
+    enum dsCond = !isDynamicArray!R && is(typeof(doPut(r, dstringInit())));
+
+    //Use "max" to avoid static type demotion
+    enum ccCond = is(typeof(doPut(r,  char.max)));
+    enum wcCond = is(typeof(doPut(r, wchar.max)));
+    //enum dcCond = is(typeof(doPut(r, dchar.max)));
+
+    //Fast transform a narrow char into a wider string
+    static if ((wsCond && E.sizeof < wchar.sizeof) || (dsCond && E.sizeof < dchar.sizeof))
+    {
+        enum w = wsCond && E.sizeof < wchar.sizeof;
+        Select!(w, wchar, dchar) c = e;
+        if (__ctfe)
+            doPut(r, [c]);
+        else
+            doPut(r, (&c)[0..1]);
+    }
+    //Encode a wide char into a narrower string
+    else static if (wsCond || csCond)
+    {
+        import std.utf;
+        /+static+/ Select!(wsCond, wchar[2], char[4]) buf; //static prevents purity.
+        doPut(r, buf.ptr[0 .. encode(buf, e)]); //the word ".ptr" added to enforce un-safety.
+    }
+    //Slowly encode a wide char into a series of narrower chars
+    else static if (wcCond || ccCond)
+    {
+        import std.encoding;
+        alias C = Select!(wcCond, wchar, char);
+        encode!(C, R)(e, r);
+    }
+    else
+        static assert (false, format("Cannot put a %s into a %s.", E.stringof, R.stringof));
+}
+
+pure unittest
+{
+    auto f = delegate (const(char)[]) {};
+    putChar(f, cast(dchar)'a');
+}
+
 unittest
 {
     struct A {}
@@ -678,6 +816,31 @@ unittest
     static assert(!__traits(compiles, put(a, "ABC")));
 }
 
+unittest
+{
+    int[][] a;
+    int[]   b;
+    int     c;
+    static assert( __traits(compiles, put(b, c)));
+    static assert( __traits(compiles, put(a, b)));
+    static assert(!__traits(compiles, put(a, c)));
+}
+
+unittest
+{
+    int[][] a = new int[][](3);
+    int[]   b = [1];
+    auto aa = a;
+    put(aa, b);
+    assert(aa == [[], []]);
+    assert(a  == [[1], [], []]);
+    int[][3] c = [2];
+    aa = a;
+    put(aa, c[]);
+    assert(aa.empty);
+    assert(a == [[2], [2], [2]]);
+}
+
 unittest
 {
     // Test fix for bug 7476.
@@ -697,18 +860,200 @@ unittest
     put(w, r);
 }
 
-/**
+unittest
+{
+    static struct PutC(C)
+    {
+        string result;
+        void put(const(C) c) { result ~= to!string((&c)[0..1]); }
+    }
+    static struct PutS(C)
+    {
+        string result;
+        void put(const(C)[] s) { result ~= to!string(s); }
+    }
+    static struct PutSS(C)
+    {
+        string result;
+        void put(const(C)[][] ss)
+        {
+            foreach(s; ss)
+                result ~= to!string(s);
+        }
+    }
+
+    PutS!char p;
+    putChar(p, cast(dchar)'a');
+
+    //Source Char
+    foreach (SC; TypeTuple!(char, wchar, dchar))
+    {
+        SC ch = 'I';
+        dchar dh = '♥';
+        immutable(SC)[] s = "日本語!";
+        immutable(SC)[][] ss = ["日本語", "が", "好き", "ですか", "?"];
+
+        //Target Char
+        foreach (TC; TypeTuple!(char, wchar, dchar))
+        {
+            //Testing PutC and PutS
+            foreach (Type; TypeTuple!(PutC!TC, PutS!TC))
+            {
+                Type type;
+                auto sink = new Type();
+
+                //Testing put and sink
+                foreach (value ; tuple(type, sink))
+                {
+                    put(value, ch);
+                    assert(value.result == "I");
+                    put(value, dh);
+                    assert(value.result == "I♥");
+                    put(value, s);
+                    assert(value.result == "I♥日本語!");
+                    put(value, ss);
+                    assert(value.result == "I♥日本語!日本語が好きですか?");
+                }
+            }
+        }
+    }
+}
+
+unittest
+{
+    static struct CharRange
+    {
+        char c;
+        enum empty = false;
+        void popFront(){};
+        ref char front() @property
+        {
+            return c;
+        }
+    }
+    CharRange c;
+    put(c, cast(dchar)'H');
+    put(c, "hello"d);
+}
+
+unittest
+{
+    // issue 9823
+    const(char)[] r;
+    void delegate(const(char)[]) dg = (s) { r = s; };
+    put(dg, ["ABC"]);
+    assert(r == "ABC");
+}
+
+unittest
+{
+    // issue 10571
+    import std.format;
+    string buf;
+    formattedWrite((in char[] s) { buf ~= s; }, "%s", "hello");
+    assert(buf == "hello");
+}
+
+unittest
+{
+    import std.format;
+    struct PutC(C)
+    {
+        void put(C){}
+    }
+    struct PutS(C)
+    {
+        void put(const(C)[]){}
+    }
+    struct CallC(C)
+    {
+        void opCall(C){}
+    }
+    struct CallS(C)
+    {
+        void opCall(const(C)[]){}
+    }
+    struct FrontC(C)
+    {
+        enum empty = false;
+        auto front()@property{return C.init;}
+        void front(C)@property{}
+        void popFront(){}
+    }
+    struct FrontS(C)
+    {
+        enum empty = false;
+        auto front()@property{return C[].init;}
+        void front(const(C)[])@property{}
+        void popFront(){}
+    }
+    void foo()
+    {
+        foreach(C; TypeTuple!(char, wchar, dchar))
+        {
+            formattedWrite((C c){},        "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d);
+            formattedWrite((const(C)[]){}, "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d);
+            formattedWrite(PutC!C(),       "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d);
+            formattedWrite(PutS!C(),       "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d);
+            CallC!C callC;
+            CallS!C callS;
+            formattedWrite(callC,          "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d);
+            formattedWrite(callS,          "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d);
+            formattedWrite(FrontC!C(),     "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d);
+            formattedWrite(FrontS!C(),     "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d);
+        }
+        formattedWrite((dchar[]).init,     "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d);
+    }
+}
+
+/+
+Returns $(D true) if $(D R) is a native output range for elements of type
+$(D E). An output range is defined functionally as a range that
+supports the operation $(D doPut(r, e)) as defined above. if $(D doPut(r, e))
+is valid, then $(D put(r,e)) will have the same behavior.
+
+The two guarantees isNativeOutputRange gives over the larger $(D isOutputRange)
+are:
+1: $(D e) is $(B exactly) what will be placed (not $(D [e]), for example).
+2: if $(D E) is a non $(empty) $(D InputRange), then placing $(D e) is
+guaranteed to not overflow the range.
+ +/
+package template isNativeOutputRange(R, E)
+{
+    enum bool isNativeOutputRange = is(typeof(
+    (inout int = 0)
+    {
+        R r = void;
+        E e;
+        doPut(r, e);
+    }));
+}
+//
+unittest
+{
+    int[] r = new int[](4);
+    static assert(isInputRange!(int[]));
+    static assert( isNativeOutputRange!(int[], int));
+    static assert(!isNativeOutputRange!(int[], int[]));
+    static assert( isOutputRange!(int[], int[]));
+
+    if (!r.empty)
+        put(r, 1); //guaranteed to succeed
+    if (!r.empty)
+        put(r, [1, 2]); //May actually error out.
+}
+/++
 Returns $(D true) if $(D R) is an output range for elements of type
 $(D E). An output range is defined functionally as a range that
 supports the operation $(D put(r, e)) as defined above.
- */
+ +/
 template isOutputRange(R, E)
 {
     enum bool isOutputRange = is(typeof(
     (inout int = 0)
     {
         R r = void;
-        E e;
+        E e = void;
         put(r, e);
     }));
 }
@@ -728,6 +1073,9 @@ unittest
     static assert( isOutputRange!(dchar[], char));
     static assert( isOutputRange!(dchar[], wchar));
     static assert( isOutputRange!(dchar[], dchar));
+    static assert( isOutputRange!(dchar[], string));
+    static assert( isOutputRange!(dchar[], wstring));
+    static assert( isOutputRange!(dchar[], dstring));
 
     static assert(!isOutputRange!(const(int)[], int));
     static assert(!isOutputRange!(inout(int)[], int));
@@ -1026,12 +1374,34 @@ $(D void).
  */
 template ElementType(R)
 {
-    static if (is(typeof((inout int = 0){ R r = void; return r.front; }()) T))
+    static if (is(typeof(R.init.front.init) T))
         alias T ElementType;
     else
         alias void ElementType;
 }
 
+///
+unittest
+{
+    // Standard arrays: returns the type of the elements of the array
+    static assert(is(ElementType!(byte[]) == byte));
+    static assert(is(ElementType!(int[]) == int));
+
+    // Accessing .front retrieves the decoded dchar
+    static assert(is(ElementType!(char[])  == dchar)); // rvalue
+    static assert(is(ElementType!(wchar[]) == dchar)); // rvalue
+    static assert(is(ElementType!(dchar[]) == dchar)); // lvalue
+
+    // Ditto
+    static assert(is(ElementType!(string) == dchar));
+    static assert(is(ElementType!(wstring) == dchar));
+    static assert(is(ElementType!(dstring) == immutable(dchar)));
+
+    // For ranges it gets the type of .front.
+    auto range = iota(0, 10);
+    static assert(is(ElementType!(typeof(range)) == int));
+}
+
 unittest
 {
     enum XYZ : string { a = "foo" }
@@ -1039,11 +1409,40 @@ unittest
     immutable char[3] a = "abc";
     int[] i;
     void[] buf;
-    static assert(is(ElementType!(XYZ) : dchar));
-    static assert(is(ElementType!(typeof(a)) : dchar));
-    static assert(is(ElementType!(typeof(i)) : int));
-    static assert(is(ElementType!(typeof(buf)) : void));
-    static assert(is(ElementType!(inout(int)[]) : inout(int)));
+    static assert(is(ElementType!(XYZ) == dchar));
+    static assert(is(ElementType!(typeof(a)) == dchar));
+    static assert(is(ElementType!(typeof(i)) == int));
+    static assert(is(ElementType!(typeof(buf)) == void));
+    static assert(is(ElementType!(inout(int)[]) == inout(int)));
+    static assert(is(ElementType!(inout(int[])) == inout(int)));
+}
+
+unittest
+{
+    static assert(is(ElementType!(int[5]) == int));
+    static assert(is(ElementType!(int[0]) == int));
+    static assert(is(ElementType!(char[5]) == dchar));
+    static assert(is(ElementType!(char[0]) == dchar));
+}
+
+unittest //11336
+{
+    static struct S
+    {
+        this(this) @disable;
+    }
+    static assert(is(ElementType!(S[]) == S));
+}
+
+unittest // 11401
+{
+    // ElementType should also work for non-@propety 'front'
+    struct E { ushort id; }
+    struct R
+    {
+        E front() { return E.init; }
+    }
+    static assert(is(ElementType!R == E));
 }
 
 /**
@@ -1056,11 +1455,31 @@ $(D ElementType).
 template ElementEncodingType(R)
 {
     static if (isNarrowString!R)
-        alias typeof((inout int = 0){ R r = void; return r[0]; }()) ElementEncodingType;
+        alias typeof(*lvalueOf!R.ptr) ElementEncodingType;
     else
         alias ElementType!R ElementEncodingType;
 }
 
+///
+unittest
+{
+    // internally the range stores the encoded type
+    static assert(is(ElementEncodingType!(char[])  == char));
+    static assert(is(ElementEncodingType!(wchar[]) == wchar));
+    static assert(is(ElementEncodingType!(dchar[]) == dchar));
+
+    // ditto
+    static assert(is(ElementEncodingType!(string)  == immutable(char)));
+    static assert(is(ElementEncodingType!(wstring) == immutable(wchar)));
+    static assert(is(ElementEncodingType!(dstring) == immutable(dchar)));
+
+    static assert(is(ElementEncodingType!(byte[]) == byte));
+    static assert(is(ElementEncodingType!(int[])  == int));
+
+    auto range = iota(0, 10);
+    static assert(is(ElementEncodingType!(typeof(range)) == int));
+}
+
 unittest
 {
     enum XYZ : string { a = "foo" }
@@ -1079,6 +1498,14 @@ unittest
     static assert(is(ElementEncodingType!(inout char[]) : inout(char)));
 }
 
+unittest
+{
+    static assert(is(ElementEncodingType!(int[5]) == int));
+    static assert(is(ElementEncodingType!(int[0]) == int));
+    static assert(is(ElementEncodingType!(char[5]) == char));
+    static assert(is(ElementEncodingType!(char[0]) == char));
+}
+
 /**
 Returns $(D true) if $(D R) is a forward range and has swappable
 elements. The following code should compile for any range
@@ -1464,7 +1891,7 @@ if (isBidirectionalRange!(Unqual!Range))
     }
     else
     {
-        static struct Result
+        static struct Result()
         {
             private alias Unqual!Range R;
 
@@ -1561,7 +1988,7 @@ if (isBidirectionalRange!(Unqual!Range))
             }
         }
 
-        return Result(r);
+        return Result!()(r);
     }
 }
 
@@ -1892,7 +2319,7 @@ unittest
     assert(s1[0..0].empty);
     assert(s1[3..3].empty);
     // assert(s1[$ .. $].empty);
-    assert(s1[s1.opDollar() .. s1.opDollar()].empty);
+    assert(s1[s1.opDollar .. s1.opDollar].empty);
 
     auto s2 = stride(arr, 2);
     assert(equal(s2[0..2], [1,3]));
@@ -1902,7 +2329,7 @@ unittest
     assert(s2[0..0].empty);
     assert(s2[3..3].empty);
     // assert(s2[$ .. $].empty);
-    assert(s2[s2.opDollar() .. s2.opDollar()].empty);
+    assert(s2[s2.opDollar .. s2.opDollar].empty);
 
     // Test fix for Bug 5035
     auto m = [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]; // 3 rows, 4 columns
@@ -2069,7 +2496,7 @@ if (Ranges.length > 0 &&
             }
 
 // This is the entire state
-            Tuple!R source;
+            R source;
 // TODO: use a vtable (or more) instead of linear iteration
 
         public:
@@ -2431,6 +2858,14 @@ unittest
     }
 }
 
+unittest
+{
+    class Foo{}
+    immutable(Foo)[] a;
+    immutable(Foo)[] b;
+    auto c = chain(a, b);
+}
+
 /**
 $(D roundRobin(r1, r2, r3)) yields $(D r1.front), then $(D r2.front),
 then $(D r3.front), after which it pops off one element from each and
@@ -2952,6 +3387,28 @@ if (isInputRange!R)
                 {
                     return Result(_input.save, _n);
                 }
+
+            static if (hasMobileElements!R)
+            {
+                auto moveFront()
+                {
+                    assert(!empty,
+                        "Attempting to move the front of an empty "
+                        ~ typeof(this).stringof);
+                    return .moveFront(_input);
+                }
+            }
+
+            static if (hasAssignableElements!R)
+            {
+                @property auto ref front(ElementType!R v)
+                {
+                    assert(!empty,
+                        "Attempting to assign to the front of an empty "
+                        ~ typeof(this).stringof);
+                    return _input.front = v;
+                }
+            }
         }
 
         return Result(range, n);
@@ -3008,11 +3465,31 @@ unittest
 
     foreach(DummyType; AllDummyRanges)
     {
-        DummyType dummy;
-        auto t = takeExactly(dummy, 5);
+        {
+            DummyType dummy;
+            auto t = takeExactly(dummy, 5);
 
-        //Test that takeExactly doesn't wrap the result of takeExactly.
-        assert(takeExactly(t, 4) == takeExactly(dummy, 4));
+            //Test that takeExactly doesn't wrap the result of takeExactly.
+            assert(takeExactly(t, 4) == takeExactly(dummy, 4));
+        }
+
+        static if(hasMobileElements!DummyType)
+        {
+            {
+                auto t = takeExactly(DummyType.init, 4);
+                assert(t.moveFront() == 1);
+                assert(equal(t, [1, 2, 3, 4]));
+            }
+        }
+
+        static if(hasAssignableElements!DummyType)
+        {
+            {
+                auto t = takeExactly(DummyType.init, 4);
+                t.front = 9;
+                assert(equal(t, [9, 2, 3, 4]));
+            }
+        }
     }
 }
 
@@ -3831,11 +4308,7 @@ struct Cycle(Range)
         }
 
         private static struct DollarToken {}
-
-        DollarToken opDollar()
-        {
-            return DollarToken.init;
-        }
+        enum opDollar = DollarToken.init;
 
         auto opSlice(size_t i, size_t j)
         {
@@ -4170,6 +4643,14 @@ struct Zip(Ranges...)
             return result;
         }
 
+    private void emplaceIfCan(T)(T* addr)
+    {
+        static if(__traits(compiles, emplace(addr)))
+            emplace(addr);
+        else
+            throw new Exception("Range with non-default constructable elements exhausted.");
+    }
+
 /**
    Returns the current iterated element.
 */
@@ -4181,7 +4662,7 @@ struct Zip(Ranges...)
             auto addr = cast(Unqual!(typeof(result[i]))*) &result[i];
             if (ranges[i].empty)
             {
-                emplace(addr);
+                emplaceIfCan(addr);
             }
             else
             {
@@ -4225,7 +4706,7 @@ struct Zip(Ranges...)
                 }
                 else
                 {
-                    emplace(addr);
+                    emplaceIfCan(addr);
                 }
             }
             return result;
@@ -4249,7 +4730,7 @@ struct Zip(Ranges...)
                 }
                 else
                 {
-                    emplace(addr);
+                    emplaceIfCan(addr);
                 }
             }
             return result;
@@ -4272,7 +4753,7 @@ struct Zip(Ranges...)
                     }
                     else
                     {
-                        emplace(addr);
+                        emplaceIfCan(addr);
                     }
                 }
                 return result;
@@ -4616,6 +5097,15 @@ unittest
     assert(equal(z2, [tuple(7, 0L)]));
 }
 
+// Text for Issue 11196
+unittest
+{
+    static struct S { @disable this(); }
+    static assert(__traits(compiles, zip((S[5]).init[])));
+    auto z = zip(StoppingPolicy.longest, cast(S[]) null, new int[1]);
+    assertThrown(zip(StoppingPolicy.longest, cast(S[]) null, new int[1]).front);
+}
+
 /*
     Generate lockstep's opApply function as a mixin string.
     If withIndex is true prepend a size_t index to the delegate.
@@ -4637,7 +5127,7 @@ private string lockstepMixin(Ranges...)(bool withIndex)
     
     foreach (idx, Range; Ranges)
     {
-        params ~= format("ref ElementType!(Ranges[%s])", idx);
+        params ~= format("%sElementType!(Ranges[%s])", hasLvalueElements!Range ? "ref " : "", idx);
         emptyChecks ~= format("!ranges[%s].empty", idx);
         dgArgs ~= format("ranges[%s].front", idx);
         popFronts ~= format("ranges[%s].popFront();", idx);
@@ -4826,6 +5316,9 @@ unittest
     auto c = chain(foo2, bar2);
 
     foreach(f, b; lockstep(c, c)) {}
+
+    // Regression 10468
+    foreach (x, y; lockstep(iota(0, 10), iota(0, 10))) { }
 }
 
 /**
@@ -5092,14 +5585,15 @@ if ((isIntegral!(CommonType!(B, E)) || isPointer!(CommonType!(B, E)))
         && isIntegral!S)
 {
     alias CommonType!(Unqual!B, Unqual!E) Value;
+    alias Unqual!S StepType;
     alias typeof(unsigned((end - begin) / step)) IndexType;
 
     static struct Result
     {
         private Value current, pastLast;
-        private S step;
+        private StepType step;
 
-        this(Value current, Value pastLast, S step)
+        this(Value current, Value pastLast, StepType step)
         {
             if ((current < pastLast && step >= 0) ||
                     (current > pastLast && step <= 0))
@@ -5250,7 +5744,7 @@ auto iota(E)(E end)
 auto iota(B, E, S)(B begin, E end, S step)
 if (isFloatingPoint!(CommonType!(B, E, S)))
 {
-    alias CommonType!(B, E, S) Value;
+    alias Unqual!(CommonType!(B, E, S)) Value;
     static struct Result
     {
         private Value start, step;
@@ -6409,7 +6903,7 @@ unittest
 This range iterates over fixed-sized chunks of size $(D chunkSize) of a
 $(D source) range. $(D Source) must be a forward range.
 
-If $(D !isInfinitite!Source) and $(D source.walkLength) is not evenly
+If $(D !isInfinite!Source) and $(D source.walkLength) is not evenly
 divisible by $(D chunkSize), the back element of this range will contain
 fewer than $(D chunkSize) elements.
 
@@ -6621,7 +7115,8 @@ private:
 }
 
 /// Ditto
-Chunks!(Source) chunks(Source)(Source source, size_t chunkSize)
+Chunks!Source chunks(Source)(Source source, size_t chunkSize)
+if (isForwardRange!Source)
 {
     return typeof(return)(source, chunkSize);
 }
@@ -6703,68 +7198,233 @@ unittest
     assert(equal!`equal(a, b)`(oddsByPairs[3 .. $].take(2), [[13, 15], [17, 19]]));
 }
 
-/**
-This range iterates a single element. This is useful when a sole value
-must be passed to an algorithm expecting a range.
-
-Example:
-----
-assert(equal(only('♡'), "♡"));
-assert([1, 2, 3, 4].findSplitBefore(only(3))[0] == [1, 2]);
-
-string title = "The D Programming Language";
-assert(filter!isUpper(title).map!only().join(".") == "T.D.P.L");
-----
- */
-auto only(T)(T value)
+private struct OnlyResult(T, size_t arity)
 {
-    static struct Result
+    private this(Values...)(auto ref Values values)
     {
-        this(T value) { _value = value; }
-
-        @property T front() { assert(!_empty); return _value; }
-        @property T back() { assert(!_empty); return _value; }
-        @property bool empty() const { return _empty; }
-        @property size_t length() const { return !_empty; }
-        @property auto save() { return this; }
-        void popFront() { assert(!_empty); _empty = true; }
-        void popBack() { assert(!_empty); _empty = true; }
-        auto opSlice() { return this; }
-
-        T opIndex(size_t i)
-        {
-            version (assert)
-                if (_empty || i != 0)
-                    throw new RangeError;
-            return _value;
-        }
-
-        auto opSlice(size_t from, size_t to)
-        {
-            version (assert)
-                if (from > to || to > length)
-                    throw new RangeError;
-            Result copy = this;
-            copy._empty = _empty || from == to;
-            return copy;
-        }
-
-        private Unqual!T _value;
-        private bool _empty = false;
+        this.data = [values];
     }
-    return Result(value);
+
+    bool empty() @property
+    {
+        return frontIndex >= backIndex;
+    }
+
+    T front() @property
+    {
+        assert(!empty);
+        return data[frontIndex];
+    }
+
+    void popFront()
+    {
+        assert(!empty);
+        ++frontIndex;
+    }
+
+    T back() @property
+    {
+        assert(!empty);
+        return data[backIndex - 1];
+    }
+
+    void popBack()
+    {
+        assert(!empty);
+        --backIndex;
+    }
+
+    OnlyResult save() @property
+    {
+        return this;
+    }
+
+    size_t length() @property
+    {
+        return backIndex - frontIndex;
+    }
+
+    alias opDollar = length;
+
+    T opIndex(size_t idx)
+    {
+        // data[i + idx] will not throw a RangeError
+        // when i + idx points to elements popped
+        // with popBack
+        version(assert)
+            if(idx >= length)
+                throw new RangeError;
+        return data[frontIndex + idx];
+    }
+
+    OnlyResult opSlice()
+    {
+        return this;
+    }
+
+    OnlyResult opSlice(size_t from, size_t to)
+    {
+        OnlyResult result = this;
+        result.frontIndex += from;
+        result.backIndex = this.frontIndex + to;
+
+        version(assert)
+            if(to < from || to > length)
+                throw new RangeError;
+
+        return result;
+    }
+
+    private size_t frontIndex = 0;
+    private size_t backIndex = arity;
+
+    // @@@BUG@@@ 10643
+    version(none)
+    {
+        static if(hasElaborateAssign!T)
+        	private T[arity] data;
+        else
+        	private T[arity] data = void;
+    }
+    else
+        private T[arity] data;
 }
 
+// Specialize for single-element results
+private struct OnlyResult(T, size_t arity : 1)
+{
+    @property T front() { assert(!_empty); return _value; }
+    @property T back() { assert(!_empty); return _value; }
+    @property bool empty() const { return _empty; }
+    @property size_t length() const { return !_empty; }
+    @property auto save() { return this; }
+    void popFront() { assert(!_empty); _empty = true; }
+    void popBack() { assert(!_empty); _empty = true; }
+    alias opDollar = length;
+
+    T opIndex(size_t i)
+    {
+        version (assert)
+            if (_empty || i != 0)
+                throw new RangeError;
+        return _value;
+    }
+
+    OnlyResult opSlice()
+    {
+        return this;
+    }
+
+    OnlyResult opSlice(size_t from, size_t to)
+    {
+        version (assert)
+            if (from > to || to > length)
+                throw new RangeError;
+        OnlyResult copy = this;
+        copy._empty = _empty || from == to;
+        return copy;
+    }
+
+    private Unqual!T _value;
+    private bool _empty = false;
+}
+
+// Specialize for the empty range
+private struct OnlyResult(T, size_t arity : 0)
+{
+    private static struct EmptyElementType {}
+
+    bool empty() @property { return true; }
+    size_t length() @property { return 0; }
+    alias opDollar = length;
+    EmptyElementType front() @property { assert(false); }
+    void popFront() { assert(false); }
+    EmptyElementType back() @property { assert(false); }
+    void popBack() { assert(false); }
+    OnlyResult save() @property { return this; }
+
+    EmptyElementType opIndex(size_t i)
+    {
+        version(assert) throw new RangeError;
+        assert(false);
+    }
+
+    OnlyResult opSlice() { return this; }
+
+    OnlyResult opSlice(size_t from, size_t to)
+    {
+        version(assert)
+            if(from != 0 || to != 0)
+                throw new RangeError;
+        return this;
+    }
+}
+
+/**
+Assemble $(D values) into a range that carries all its
+elements in-situ.
+
+Useful when a single value or multiple disconnected values
+must be passed to an algorithm expecting a range, without
+having to perform dynamic memory allocation.
+
+As copying the range means copying all elements, it can be
+safely returned from functions. For the same reason, copying
+the returned range may be expensive for a large number of arguments.
+ */
+auto only(Values...)(auto ref Values values)
+    if(!is(CommonType!Values == void) || Values.length == 0)
+{
+    return OnlyResult!(CommonType!Values, Values.length)(values);
+}
+
+///
 unittest
 {
-    // Examples
     assert(equal(only('♡'), "♡"));
     assert([1, 2, 3, 4].findSplitBefore(only(3))[0] == [1, 2]);
 
+    assert(only("one", "two", "three").joiner(" ").equal("one two three"));
+
     import std.uni;
     string title = "The D Programming Language";
     assert(filter!isUpper(title).map!only().join(".") == "T.D.P.L");
+}
 
+version(unittest)
+{
+    // Verify that the same common type and same arity
+    // results in the same template instantiation
+    static assert(is(typeof(only(byte.init, int.init)) ==
+        typeof(only(int.init, byte.init))));
+
+    static assert(is(typeof(only((const(char)[]).init, string.init)) ==
+        typeof(only((const(char)[]).init, (const(char)[]).init))));
+}
+
+// Tests the zero-element result
+unittest
+{
+    auto emptyRange = only();
+
+    alias EmptyRange = typeof(emptyRange);
+    static assert(isInputRange!EmptyRange);
+    static assert(isForwardRange!EmptyRange);
+    static assert(isBidirectionalRange!EmptyRange);
+    static assert(isRandomAccessRange!EmptyRange);
+    static assert(hasLength!EmptyRange);
+    static assert(hasSlicing!EmptyRange);
+
+    assert(emptyRange.empty);
+    assert(emptyRange.length == 0);
+    assert(emptyRange.equal(emptyRange[]));
+    assert(emptyRange.equal(emptyRange.save));
+    assert(emptyRange[0 .. 0].equal(emptyRange));
+}
+
+// Tests the single-element result
+unittest
+{
     foreach (x; tuple(1, '1', 1.0, "1", [1]))
     {
         auto a = only(x);
@@ -6808,6 +7468,93 @@ unittest
     assert(imm[0] == 1);
 }
 
+// Tests multiple-element results
+unittest
+{
+    static assert(!__traits(compiles, only(1, "1")));
+
+    auto nums = only!(byte, uint, long)(1, 2, 3);
+    static assert(is(ElementType!(typeof(nums)) == long));
+    assert(nums.length == 3);
+
+    foreach(i; 0 .. 3)
+        assert(nums[i] == i + 1);
+
+    auto saved = nums.save;
+
+    foreach(i; 1 .. 4)
+    {
+        assert(nums.front == nums[0]);
+        assert(nums.front == i);
+        nums.popFront();
+        assert(nums.length == 3 - i);
+    }
+
+    assert(nums.empty);
+
+    assert(saved.equal(only(1, 2, 3)));
+    assert(saved.equal(saved[]));
+    assert(saved[0 .. 1].equal(only(1)));
+    assert(saved[0 .. 2].equal(only(1, 2)));
+    assert(saved[0 .. 3].equal(saved));
+    assert(saved[1 .. 3].equal(only(2, 3)));
+    assert(saved[2 .. 3].equal(only(3)));
+    assert(saved[0 .. 0].empty);
+    assert(saved[3 .. 3].empty);
+
+    alias data = TypeTuple!("one", "two", "three", "four");
+    static joined =
+        ["one two", "one two three", "one two three four"];
+    string[] joinedRange = joined;
+
+    foreach(argCount; TypeTuple!(2, 3, 4))
+    {
+        auto values = only(data[0 .. argCount]);
+        alias Values = typeof(values);
+        static assert(is(ElementType!Values == string));
+        static assert(isInputRange!Values);
+        static assert(isForwardRange!Values);
+        static assert(isBidirectionalRange!Values);
+        static assert(isRandomAccessRange!Values);
+        static assert(hasSlicing!Values);
+        static assert(hasLength!Values);
+
+        assert(values.length == argCount);
+        assert(values[0 .. $].equal(values[0 .. values.length]));
+        assert(values.joiner(" ").equal(joinedRange.front));
+        joinedRange.popFront();
+    }
+
+    assert(saved.retro.equal(only(3, 2, 1)));
+    assert(saved.length == 3);
+
+    assert(saved.back == 3);
+    saved.popBack();
+    assert(saved.length == 2);
+    assert(saved.back == 2);
+
+    assert(saved.front == 1);
+    saved.popFront();
+    assert(saved.length == 1);
+    assert(saved.front == 2);
+
+    saved.popBack();
+    assert(saved.empty);
+
+    auto imm = only!(immutable int, immutable int)(42, 24);
+    alias Imm = typeof(imm);
+    static assert(is(ElementType!Imm == immutable(int)));
+    assert(imm.front == 42);
+    imm.popFront();
+    assert(imm.front == 24);
+    imm.popFront();
+    assert(imm.empty);
+
+    static struct Test { int* a; }
+    immutable(Test) test;
+    only(test, test); // Works with mutable indirection
+}
+
 /**
    Moves the front of $(D r) out and returns it. Leaves $(D r.front) in a
    destroyable state that does not allocate any resources (usually equal
diff --git a/std/regex.d b/std/regex.d
index 5cfd2d99e..9e0583361 100644
--- a/std/regex.d
+++ b/std/regex.d
@@ -1,12 +1,13 @@
 //Written in the D programming language
 /++
+  $(SECTION Intro)
   $(LUCKY Regular expressions) are a commonly used method of pattern matching
   on strings, with $(I regex) being a catchy word for a pattern in this domain
   specific language. Typical problems usually solved by regular expressions
   include validation of user input and the ubiquitous find & replace
   in text processing utilities.
 
-  Synposis:
+  $(SECTION Synopsis)
   ---
   import std.regex;
   import std.stdio;
@@ -26,7 +27,7 @@
   ...
 
   // Create a static regex at compile-time, which contains fast native code.
-  enum ctr = ctRegex!(`^.*/([^/]+)/?$`);
+  auto ctr = ctRegex!(`^.*/([^/]+)/?$`);
 
   // It works just like a normal regex:
   auto m2 = match("foo/bar", ctr);   // First match found here, if any
@@ -41,19 +42,24 @@
 
 
   ---
-
+  $(SECTION Syntax and general information)
   The general usage guideline is to keep regex complexity on the side of simplicity,
-  as its capabilities reside in purely character-level manipulation,
-  and as such are ill-suited for tasks involving higher level invariants
+  as its capabilities reside in purely character-level manipulation.
+  As such it's ill-suited for tasks involving higher level invariants
   like matching an integer number $(U bounded) in an [a,b] interval.
   Checks of this sort of are better addressed by additional post-processing.
 
   The basic syntax shouldn't surprise experienced users of regular expressions.
-  Thankfully, nowadays the web is bustling with resources to help newcomers, and a good
-  $(WEB www.regular-expressions.info, reference with tutorial) on regular expressions
-  can be found.
+  For an introduction to $(D std.regex) see a 
+  $(WEB dlang.org/regular-expression.html, short tour) of the module API 
+  and its abilities.
 
-  This library uses an ECMAScript syntax flavor with the following extensions:
+  There are other web resources on regular expressions to help newcomers, 
+  and a good $(WEB www.regular-expressions.info, reference with tutorial) 
+  can easily be found.
+
+  This library uses a remarkably common ECMAScript syntax flavor 
+  with the following extensions:
   $(UL
     $(LI Named subexpressions, with Python syntax. )
     $(LI Unicode properties such as Scripts, Blocks and common binary properties e.g Alphabetic, White_Space, Hex_Digit etc.)
@@ -62,12 +68,12 @@
 
   $(REG_START Pattern syntax )
   $(I std.regex operates on codepoint level,
-    'character' in this table denotes a single unicode codepoint.)
+    'character' in this table denotes a single Unicode codepoint.)
   $(REG_TABLE
     $(REG_TITLE Pattern element, Semantics )
     $(REG_TITLE Atoms, Match single characters )
     $(REG_ROW any character except [{|*+?()^$, Matches the character itself. )
-    $(REG_ROW ., In single line mode matches any charcter.
+    $(REG_ROW ., In single line mode matches any character.
       Otherwise it matches any character except '\n' and '\r'. )
     $(REG_ROW [class], Matches a single character
       that belongs to this character class. )
@@ -82,8 +88,8 @@
     $(REG_ROW \r, Matches a carriage return character. )
     $(REG_ROW \t, Matches a tab character. )
     $(REG_ROW \v, Matches a vertical tab character. )
-    $(REG_ROW \d, Matches any unicode digit. )
-    $(REG_ROW \D, Matches any character except unicode digits. )
+    $(REG_ROW \d, Matches any Unicode digit. )
+    $(REG_ROW \D, Matches any character except Unicode digits. )
     $(REG_ROW \w, Matches any word character (note: this includes numbers).)
     $(REG_ROW \W, Matches any non-word character.)
     $(REG_ROW \s, Matches whitespace, same as \p{White_Space}.)
@@ -91,15 +97,15 @@
     $(REG_ROW \\, Matches \ character. )
     $(REG_ROW \c where c is one of [|*+?(), Matches the character c itself. )
     $(REG_ROW \p{PropertyName}, Matches a character that belongs
-      to the unicode PropertyName set.
+        to the Unicode PropertyName set.
       Single letter abbreviations can be used without surrounding {,}. )
     $(REG_ROW  \P{PropertyName}, Matches a character that does not belong
-      to the unicode PropertyName set.
+        to the Unicode PropertyName set.
       Single letter abbreviations can be used without surrounding {,}. )
     $(REG_ROW \p{InBasicLatin}, Matches any character that is part of
-        the BasicLatin unicode $(U block).)
+          the BasicLatin Unicode $(U block).)
     $(REG_ROW \P{InBasicLatin}, Matches any character except ones in
-        the BasicLatin unicode $(U block).)
+          the BasicLatin Unicode $(U block).)
     $(REG_ROW \p{Cyrilic}, Matches any character that is part of
         Cyrilic $(U script).)
     $(REG_ROW \P{Cyrilic}, Matches any character except ones in
@@ -178,7 +184,7 @@
       useful for formatting complex regular expressions. )
   )
 
-  $(B Unicode support)
+  $(SECTION Unicode support)
 
   This library provides full Level 1 support* according to
     $(WEB unicode.org/reports/tr18/, UTS 18). Specifically:
@@ -196,19 +202,42 @@
   *With exception of point 1.1.1, as of yet, normalization of input
     is expected to be enforced by user.
 
-  $(B Slicing)
+    $(SECTION Replace format string) 
+
+    A set of functions in this module that do the substitution rely 
+    on a simple format to guide the process. In particular the table below 
+    applies to the $(D format) argument of 
+    $(LREF replaceFirst) and $(LREF replaceAll).
+    
+    The format string can reference parts of match using the following notation.
+    $(REG_TABLE
+        $(REG_TITLE Format specifier, Replaced by )
+        $(REG_ROW $&, the whole match. )
+        $(REG_ROW $`, part of input $(I preceding) the match. )
+        $(REG_ROW $', part of input $(I following) the match. )
+        $(REG_ROW $$, '$' character. )
+        $(REG_ROW \c , where c is any character, the character c itself. )
+        $(REG_ROW \\, '\' character. )
+        $(REG_ROW $1 .. $99, submatch number 1 to 99 respectively. )
+    )
+
+  $(SECTION Slicing and zero memory allocations orientation)
 
   All matches returned by pattern matching functionality in this library
-  are slices of the original input, with the notable exception of the $(D replace)
-  family of functions which generate a new string from the input.
+    are slices of the original input. The notable exception is the $(D replace)
+    family of functions  that generate a new string from the input.
 
-  Copyright: Copyright Dmitry Olshansky, 2011
+    In cases where producing the replacement is the ultimate goal 
+    $(LREF replaceFirstInto) and $(LREF replaceAllInto) could come in handy 
+    as functions that  avoid allocations even for replacement.
+
+    Copyright: Copyright Dmitry Olshansky, 2011-
 
   License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
 
   Authors: Dmitry Olshansky,
 
-  API and utility constructs are based on original $(D std.regex)
+    API and utility constructs are modeled after the original $(D std.regex)
   by Walter Bright and Andrei Alexandrescu.
 
   Source: $(PHOBOSSRC std/_regex.d)
@@ -218,28 +247,33 @@ Macros:
     REG_TITLE = $(TR $(TD $(B $1)) $(TD $(B $2)) )
     REG_TABLE =  $0 
REG_START =

$0

+ SECTION =

$0

+ S_LINK = $+ +/ module std.regex; -import std.internal.uni, std.internal.uni_tab;//unicode property tables +import std.internal.uni, std.internal.uni_tab;//Unicode property tables import std.array, std.algorithm, std.range, std.conv, std.exception, std.traits, std.typetuple, - std.uni, std.utf, std.format, std.typecons, std.bitmanip, + std.utf, std.format, std.typecons, std.bitmanip, std.functional, std.exception; + import core.bitop, core.stdc.string, core.stdc.stdlib; -import ascii = std.ascii; +static import ascii = std.ascii; import std.string : representation; -debug import std.stdio; +debug(std_regex_parser) import std.stdio; //trace parser progress +debug(std_regex_search) import std.stdio; //trace prefix search engine +debug(std_regex_matcher) import std.stdio; //trace matcher engine +debug(std_regex_allocation) import std.stdio; //track object life cycle +debug(std_regex_ctr) import std.stdio; //dump ctRegex generated sources +debug(std_regex_test) import std.stdio; //trace test suite progress private: -@safe: -//uncomment to get a barrage of debug info -//debug = fred_parser; -//debug = fred_matching; -//debug = fred_charset; +import std.uni : isAlpha, isWhite; + // IR bit pattern: 0b1_xxxxx_yy // where yy indicates class of instruction, xxxxx for actual operation code @@ -385,7 +419,7 @@ struct Bytecode { assert(data < (1<<22) && code < 256 ); assert(seq >= 2 && seq < maxSequence); - raw = code<<24 | ((seq-2)<<22) | data; + raw = code << 24 | (seq - 2)<<22 | data; } //store raw data @@ -400,7 +434,7 @@ struct Bytecode @property uint data() const { return raw & 0x003f_ffff; } //ditto - @property uint sequence() const { return 2+((raw >>22) & 0x3); } + @property uint sequence() const { return 2 + (raw >> 22 & 0x3); } //ditto @property IR code() const { return cast(IR)(raw>>24); } @@ -424,28 +458,28 @@ struct Bytecode void setBackrefence() { assert(code == IR.GroupStart || code == IR.GroupEnd); - raw = raw | (1<<23); + raw = raw | 1 << 23; } //is referenced @property bool backreference() const { assert(code == IR.GroupStart || code == IR.GroupEnd); - return cast(bool)(raw & (1<<23)); + return cast(bool)(raw & 1 << 23); } //mark as local reference (for backrefs in lookarounds) void setLocalRef() { assert(code == IR.Backref); - raw = raw | (1<<23); + raw = raw | 1 << 23; } //is a local ref @property bool localRef() const { assert(code == IR.Backref); - return cast(bool)(raw & (1<<23)); + return cast(bool)(raw & 1 << 23); } //human readable name of instruction @@ -470,7 +504,7 @@ struct Bytecode @property Bytecode paired() const {//depends on bit and struct layout order assert(isStart || isEnd); - return Bytecode.fromRaw(raw ^ (0b11<<24)); + return Bytecode.fromRaw(raw ^ 0b11 << 24); } //gets an index into IR block of the respective pair @@ -503,8 +537,8 @@ static assert(Bytecode.sizeof == 4); break; case IR.RepeatEnd, IR.RepeatQEnd: //backward-jump instructions uint len = irb[pc].data; - formattedWrite(output, " pc=>%u min=%u max=%u step=%u" - , pc-len, irb[pc+3].raw, irb[pc+4].raw, irb[pc+2].raw); + formattedWrite(output, " pc=>%u min=%u max=%u step=%u", + pc - len, irb[pc + 3].raw, irb[pc + 4].raw, irb[pc + 2].raw); break; case IR.InfiniteEnd, IR.InfiniteQEnd, IR.OrEnd: //ditto uint len = irb[pc].data; @@ -544,77 +578,12 @@ static assert(Bytecode.sizeof == 4); return output.data; } -//another pretty printer, writes out the bytecode of a regex and where the pc is -@trusted void prettyPrint(Sink,Char = const(char)) - (Sink sink, const(Bytecode)[] irb, uint pc = uint.max, int indent = 3, size_t index = 0) - if (isOutputRange!(Sink,Char)) -{//formattedWrite is @system - while(irb.length > 0) - { - formattedWrite(sink,"%3d",index); - if(pc == 0 && irb[0].code!=IR.Char) - { - for (int i = 0;i < indent-2;++i) - put(sink,"="); - put(sink,"> "); - } - else - { - if(isEndIR(irb[0].code)) - { - indent -= 2; - } - if(indent > 0) - { - string spaces=" "; - put(sink,spaces[0..(indent%spaces.length)]); - for (size_t i = indent/spaces.length;i > 0;--i) - put(sink,spaces); - } - } - if(irb[0].code == IR.Char) - { - put(sink,`"`); - int i = 0; - do - { - put(sink,cast(char[])([cast(dchar)irb[i].data])); - ++i; - } while(i < irb.length && irb[i].code == IR.Char); - put(sink,"\""); - if(pc < i) - { - put(sink,"\n"); - for (int ii = indent+pc+1;ii > 0;++ii) - put(sink,"="); - put(sink,"^"); - } - index += i; - irb = irb[i..$]; - } - else - { - put(sink,irb[0].mnemonic); - put(sink,"("); - formattedWrite(sink,"%d",irb[0].data); - int nArgs= irb[0].args; - for(int iarg = 0;iarg < nArgs;++iarg) - { - if(iarg+1 < irb.length) - formattedWrite(sink,",%d",irb[iarg+1].data); - else - put(sink,"*error* incomplete irb stream"); - } - put(sink,")"); - if(isStartIR(irb[0].code)) - { - indent += 2; - } - index += lengthOfIR(irb[0].code); - irb = irb[lengthOfIR(irb[0].code)..$]; - } - put(sink,"\n"); - } +//disassemble the whole chunk +@trusted void printBytecode()(in Bytecode[] slice, in NamedGroup[] dict=[]) +{ + import std.stdio; + for(uint pc=0; pc number of submatch @@ -636,6 +605,87 @@ struct Group(DataIndex) } } +@trusted void reverseBytecode()(Bytecode[] code) +{ + Bytecode[] rev = new Bytecode[code.length]; + uint revPc = cast(uint)rev.length; + Stack!(Tuple!(uint, uint, uint)) stack; + uint start = 0; + uint end = cast(uint)code.length; + for(;;) + { + for(uint pc = start; pc < end; ) + { + uint len = code[pc].length; + if(code[pc].code == IR.GotoEndOr) + break; //pick next alternation branch + if(code[pc].isAtom) + { + rev[revPc - len .. revPc] = code[pc .. pc + len]; + revPc -= len; + pc += len; + } + else if(code[pc].isStart || code[pc].isEnd) + { + //skip over other embedded lookbehinds they are reversed + if(code[pc].code == IR.LookbehindStart + || code[pc].code == IR.NeglookbehindStart) + { + uint blockLen = len + code[pc].data + + code[pc].pairedLength; + rev[revPc - blockLen .. revPc] = code[pc .. pc + blockLen]; + pc += blockLen; + revPc -= blockLen; + continue; + } + uint second = code[pc].indexOfPair(pc); + uint secLen = code[second].length; + rev[revPc - secLen .. revPc] = code[second .. second + secLen]; + revPc -= secLen; + if(code[pc].code == IR.OrStart) + { + //we pass len bytes forward, but secLen in reverse + uint revStart = revPc - (second + len - secLen - pc); + uint r = revStart; + uint i = pc + IRL!(IR.OrStart); + while(code[i].code == IR.Option) + { + if(code[i - 1].code != IR.OrStart) + { + assert(code[i - 1].code == IR.GotoEndOr); + rev[r - 1] = code[i - 1]; + } + rev[r] = code[i]; + auto newStart = i + IRL!(IR.Option); + auto newEnd = newStart + code[i].data; + auto newRpc = r + code[i].data + IRL!(IR.Option); + if(code[newEnd].code != IR.OrEnd) + { + newRpc--; + } + stack.push(tuple(newStart, newEnd, newRpc)); + r += code[i].data + IRL!(IR.Option); + i += code[i].data + IRL!(IR.Option); + } + pc = i; + revPc = revStart; + assert(code[pc].code == IR.OrEnd); + } + else + pc += len; + } + } + if(stack.empty) + break; + start = stack.top[0]; + end = stack.top[1]; + revPc = stack.top[2]; + stack.pop(); + } + code[] = rev[]; +} + + //Regular expression engine/parser options: // global - search all nonoverlapping matches in input // casefold - case insensitive matching, do casefolding on match in unicode mode @@ -648,10 +698,13 @@ enum RegexOption: uint { nonunicode = 0x8, multiline = 0x10, singleline = 0x20 -}; -alias TypeTuple!('g', 'i', 'x', 'U', 'm', 's') RegexOptionNames;//do not reorder this list +} +//do not reorder this list +alias RegexOptionNames = TypeTuple!('g', 'i', 'x', 'U', 'm', 's'); static assert( RegexOption.max < 0x80); -enum RegexInfo : uint { oneShot = 0x80 }; +enum RegexInfo : uint { oneShot = 0x80 } +alias Escapables = TypeTuple!('[', ']', '\\', '^', '$', '.', '|', '?', ',', '-', + ';', ':', '#', '&', '%', '/', '<', '>', '`', '*', '+', '(', ')', '{', '}', '~'); private enum NEL = '\u0085', LS = '\u2028', PS = '\u2029'; @@ -681,9 +734,9 @@ dchar parseUniHex(Char)(ref Char[] str, size_t maxDigit) @system unittest //BUG canFind is system { - string[] non_hex = [ "000j", "000z", "FffG", "0Z"]; + string[] non_hex = [ "000j", "000z", "FffG", "0Z"]; string[] hex = [ "01", "ff", "00af", "10FFFF" ]; - int value[] = [ 1, 0xFF, 0xAF, 0x10FFFF ]; + int[] value = [ 1, 0xFF, 0xAF, 0x10FFFF ]; foreach(v; non_hex) assert(collectException(parseUniHex(v, v.length)).msg .canFind("invalid escape sequence")); @@ -699,7 +752,7 @@ enum maxCharsetUsed = 6; enum maxCachedTries = 8; -alias CodepointTrie!8 Trie; +alias Trie = CodepointTrie!8; Trie[const(CodepointSet)] trieCache; @@ -738,7 +791,7 @@ auto memoizeExpr(string expr)() { if(__ctfe) return mixin(expr); - alias typeof(mixin(expr)) T; + alias T = typeof(mixin(expr)); static T slot; static bool initialized; if(!initialized) @@ -754,7 +807,7 @@ auto memoizeExpr(string expr)() +/ @trusted const(CodepointSet) getUnicodeSet(in char[] name, bool negated, bool casefold) { - alias comparePropertyName ucmp; + alias ucmp = comparePropertyName; CodepointSet s; //unicode property @@ -812,40 +865,29 @@ auto memoizeExpr(string expr)() } //basic stack, just in case it gets used anywhere else then Parser -@trusted struct Stack(T, bool CTFE = false) +@trusted struct Stack(T) { - static if(!CTFE) - Appender!(T[]) stack;//compiles but bogus at CTFE - else - { - struct Proxy - { - T[] data; - void put(T val) - { - data ~= val; - } - void shrinkTo(size_t sz){ data = data[0..sz]; } - } - Proxy stack; - } - @property bool empty(){ return stack.data.empty; } - void push(T item) - { - stack.put(item); - } - @property ref T top() - { - assert(!empty); - return stack.data[$-1]; - } - @property size_t length() { return stack.data.length; } + T[] data; + @property bool empty(){ return data.empty; } + + @property size_t length(){ return data.length; } + + void push(T val){ data ~= val; } + T pop() { assert(!empty); - auto t = stack.data[$-1]; - stack.shrinkTo(stack.data.length-1); - return t; + auto val = data[$ - 1]; + data = data[0 .. $ - 1]; + if(!__ctfe) + data.assumeSafeAppend(); + return val; + } + + @property ref T top() + { + assert(!empty); + return data[$ - 1]; } } @@ -857,12 +899,9 @@ enum maxCompiledLength = 2^^18; //amounts to up to 4 Mb of auxilary table for matching enum maxCumulativeRepetitionLength = 2^^20; -template BasicElementOf(Range) -{ - alias Unqual!(ElementEncodingType!Range) BasicElementOf; -} +alias BasicElementOf(Range) = Unqual!(ElementEncodingType!Range); -struct Parser(R, bool CTFE = false) +struct Parser(R) if (isForwardRange!R && is(ElementType!R : dchar)) { enum infinite = ~0u; @@ -871,10 +910,10 @@ struct Parser(R, bool CTFE = false) R pat, origin; //keep full pattern for pretty printing error messages Bytecode[] ir; //resulting bytecode uint re_flags = 0; //global flags e.g. multiline + internal ones - Stack!(uint, CTFE) fixupStack; //stack of opened start instructions + Stack!(uint) fixupStack; //stack of opened start instructions NamedGroup[] dict; //maps name -> user group number //current num of group, group nesting level and repetitions step - Stack!(uint, CTFE) groupStack; + Stack!(uint) groupStack; uint nesting = 0; uint lookaroundNest = 0; uint counterDepth = 0; //current depth of nested counted repetitions @@ -908,7 +947,7 @@ struct Parser(R, bool CTFE = false) { if(n/32 >= backrefed.length) backrefed.length = n/32 + 1; - backrefed[n/32] |= 1<<(n & 31); + backrefed[n / 32] |= 1 << (n & 31); } @property dchar current(){ return _current; } @@ -944,20 +983,15 @@ struct Parser(R, bool CTFE = false) void put(Bytecode code) { - enforce(ir.length < maxCompiledLength - , "maximum compiled pattern length is exceeded"); - if(__ctfe) - { - ir = ir ~ code; - } - else - ir ~= code; + enforce(ir.length < maxCompiledLength, + "maximum compiled pattern length is exceeded"); + ir ~= code; } void putRaw(uint number) { - enforce(ir.length < maxCompiledLength - , "maximum compiled pattern length is exceeded"); + enforce(ir.length < maxCompiledLength, + "maximum compiled pattern length is exceeded"); ir ~= Bytecode.fromRaw(number); } @@ -1003,10 +1037,7 @@ struct Parser(R, bool CTFE = false) break L_FlagSwitch; } default: - if(__ctfe) - assert(text("unknown regex flag '",ch,"'")); - else - new RegexException(text("unknown regex flag '",ch,"'")); + throw new RegexException(text("unknown regex flag '",ch,"'")); } } } @@ -1021,7 +1052,7 @@ struct Parser(R, bool CTFE = false) while(!empty) { - debug(fred_parser) + debug(std_regex_parser) writeln("*LR*\nSource: ", pat, "\nStack: ",fixupStack.stack.data); switch(current) { @@ -1103,7 +1134,6 @@ struct Parser(R, bool CTFE = false) assert(lookaroundNest); fixLookaround(fix); lookaroundNest--; - put(ir[fix].paired); break; case IR.Option: //| xxx ) //two fixups: last option + full OR @@ -1121,7 +1151,6 @@ struct Parser(R, bool CTFE = false) lookaroundNest--; fix = fixupStack.pop(); fixLookaround(fix); - put(ir[fix].paired); break; default://(?:xxx) fixupStack.pop(); @@ -1241,11 +1270,13 @@ struct Parser(R, bool CTFE = false) } else error("Unexpected symbol in regex pattern"); + if(min > max) + error("Illegal {n,m} quantifier"); break; default: if(replace) { - copyForwardAlt(ir[offset+1..$],ir[offset..$-1]); + copyForwardAlt(ir[offset + 1 .. $],ir[offset .. $ - 1]); ir.length -= 1; } return; @@ -1299,14 +1330,7 @@ struct Parser(R, bool CTFE = false) } put(Bytecode(greedy ? IR.InfiniteStart : IR.InfiniteQStart, len)); enforce(ir.length + len < maxCompiledLength, "maximum compiled pattern length is exceeded"); - //workaround @@@BUG@@@ 9634 - if(__ctfe) - { - foreach(v; ir[offset .. offset+len]) - ir ~= v; - } - else - ir ~= ir[offset .. offset+len]; + ir ~= ir[offset .. offset+len]; //IR.InfinteX is always a hotspot put(Bytecode(greedy ? IR.InfiniteEnd : IR.InfiniteQEnd, len)); put(Bytecode.init); //merge index @@ -1380,27 +1404,32 @@ struct Parser(R, bool CTFE = false) put(Bytecode.fromRaw(0)); groupStack.push(0); lookaroundNest++; - enforce(lookaroundNest <= maxLookaroundDepth - , "maximum lookaround depth is exceeded"); + enforce(lookaroundNest <= maxLookaroundDepth, + "maximum lookaround depth is exceeded"); } - //fixup lookaround with start at offset fix + //fixup lookaround with start at offset fix and append a proper *-End opcode void fixLookaround(uint fix) { - ir[fix] = Bytecode(ir[fix].code - , cast(uint)ir.length - fix - IRL!(IR.LookaheadStart)); + ir[fix] = Bytecode(ir[fix].code, + cast(uint)ir.length - fix - IRL!(IR.LookaheadStart)); auto g = groupStack.pop(); assert(!groupStack.empty); ir[fix+1] = Bytecode.fromRaw(groupStack.top); //groups are cumulative across lookarounds ir[fix+2] = Bytecode.fromRaw(groupStack.top+g); groupStack.top += g; + if(ir[fix].code == IR.LookbehindStart || ir[fix].code == IR.NeglookbehindStart) + { + reverseBytecode(ir[fix + IRL!(IR.LookbehindStart) .. $]); + } + put(ir[fix].paired); } //CodepointSet operations relatively in order of priority enum Operator:uint { Open = 0, Negate, Difference, SymDifference, Intersection, Union, None - }; + } //parse unit of CodepointSet spec, most notably escape sequences and char ranges //also fetches next set operation @@ -1539,9 +1568,10 @@ struct Parser(R, bool CTFE = false) last = parseControlCode(); state = State.Char; break; - case '[',']','\\','^','$','.','|','?',',','-',';',':' - ,'#','&','%','/','<','>','`' - ,'*','+','(',')','{','}', '~': + foreach(val; Escapables) + { + case val: + } last = current; state = State.Char; break; @@ -1645,9 +1675,10 @@ struct Parser(R, bool CTFE = false) case 'v': end = '\v'; break; - case '[',']','\\','^','$','.','|','?',',','-',';',':' - ,'#','&','%','/','<','>','`' - ,'*','+','(',')','{','}', '~': + foreach(val; Escapables) + { + case val: + } end = current; break; case 'c': @@ -1675,8 +1706,8 @@ struct Parser(R, bool CTFE = false) return tuple(set, op); } - alias Stack!(CodepointSet, CTFE) ValStack; - alias Stack!(Operator, CTFE) OpStack; + alias ValStack = Stack!(CodepointSet); + alias OpStack = Stack!(Operator); //parse and store IR for CodepointSet void parseCharset() @@ -1720,8 +1751,6 @@ struct Parser(R, bool CTFE = false) { while(cond(opstack.top)) { - debug(fred_charset) - writeln(opstack.stack.data); if(!apply(opstack.pop(),vstack)) return false;//syntax error if(opstack.empty) @@ -1737,18 +1766,18 @@ struct Parser(R, bool CTFE = false) { case '[': opstack.push(Operator.Open); - enforce(next(), "unexpected end of CodepointSet"); + enforce(next(), "unexpected end of character class"); if(current == '^') { opstack.push(Operator.Negate); - enforce(next(), "unexpected end of CodepointSet"); + enforce(next(), "unexpected end of character class"); } //[] is prohibited - enforce(current != ']', "wrong CodepointSet"); + enforce(current != ']', "wrong character class"); goto default; case ']': - enforce(unrollWhile!(unaryFun!"a != a.Open")(vstack, opstack) - , "CodepointSet syntax error"); + enforce(unrollWhile!(unaryFun!"a != a.Open")(vstack, opstack), + "character class syntax error"); enforce(!opstack.empty, "unmatched ']'"); opstack.pop(); next(); @@ -1810,7 +1839,7 @@ struct Parser(R, bool CTFE = false) auto t = getTrie(set); put(Bytecode(IR.Trie, cast(uint)tries.length)); tries ~= t; - debug(fred_allocation) writeln("Trie generated"); + debug(std_regex_allocation) writeln("Trie generated"); } else { @@ -1886,7 +1915,7 @@ struct Parser(R, bool CTFE = false) case '1': .. case '9': uint nref = cast(uint)current - '0'; uint maxBackref; - foreach(v; groupStack.stack.data) + foreach(v; groupStack.data) maxBackref += v; uint localLimit = maxBackref - groupStack.top; enforce(nref < maxBackref, "Backref to unseen group"); @@ -1919,7 +1948,7 @@ struct Parser(R, bool CTFE = false) //\ - assumed to be processed, p - is current const(CodepointSet) parseUnicodePropertySpec(bool negated) { - alias comparePropertyName ucmp; + alias ucmp = comparePropertyName; enum MAX_PROPERTY = 128; char[MAX_PROPERTY] result; uint k = 0; @@ -1937,8 +1966,8 @@ struct Parser(R, bool CTFE = false) enforce(current < 0x80, "invalid property name"); result[k++] = cast(char)current; } - auto s = getUnicodeSet(result[0..k], negated - , cast(bool)(re_flags & RegexOption.casefold)); + auto s = getUnicodeSet(result[0..k], negated, + cast(bool)(re_flags & RegexOption.casefold)); enforce(!s.empty, "unrecognized unicode property spec"); next(); return s; @@ -1954,7 +1983,7 @@ struct Parser(R, bool CTFE = false) throw new RegexException(app.data); } - alias BasicElementOf!R Char; + alias Char = BasicElementOf!R; //packages parsing results into a RegEx object @property Regex!Char program() { @@ -1985,7 +2014,69 @@ public struct Regex(Char) assert(!r.empty); --- +/ - @property bool empty() const nothrow { return ir is null; } + @safe @property bool empty() const nothrow { return ir is null; } + + /++ + A range of all the named captures in the regex. + Example: + ---- + import std.range; + import std.algorithm; + + auto re = regex(`(?P\w+) = (?P\d+)`); + auto nc = re.namedCaptures; + static assert(isRandomAccessRange!(typeof(nc))); + assert(!nc.empty); + assert(nc.length == 2); + assert(nc.equal(["name", "var"])); + assert(nc[0] == "name"); + assert(nc[1..$].equal(["var"])); + ---- + +/ + @safe @property auto namedCaptures() + { + static struct NamedGroupRange + { + private: + NamedGroup[] groups; + size_t start; + size_t end; + public: + this(NamedGroup[] g, size_t s, size_t e) + { + assert(s <= e); + assert(e <= g.length); + groups = g; + start = s; + end = e; + } + + @property string front() { return groups[start].name; } + @property string back() { return groups[end-1].name; } + @property bool empty() { return start >= end; } + @property size_t length() { return end - start; } + alias opDollar = length; + @property NamedGroupRange save() + { + return NamedGroupRange(groups, start, end); + } + void popFront() { assert(!empty); start++; } + void popBack() { assert(!empty); end--; } + string opIndex()(size_t i) + { + assert(start + i < end, + "Requested named group is out of range."); + return groups[start+i].name; + } + NamedGroupRange opSlice(size_t low, size_t high) { + assert(low <= high); + assert(start + high <= end); + return NamedGroupRange(groups, start + low, start + high); + } + NamedGroupRange opSlice() { return this.save; } + } + return NamedGroupRange(dict, 0, dict.length); + } private: NamedGroup[] dict; //maps name -> user group number @@ -2003,7 +2094,7 @@ private: { if(n/32 >= backrefed.length) return 0; - return backrefed[n/32] & (1<<(n&31)); + return backrefed[n / 32] & (1 << (n & 31)); } //check if searching is not needed @@ -2050,8 +2141,8 @@ private: { if(ir[i].hotspot) { - assert(i + 1 < ir.length - , "unexpected end of IR while looking for hotspot"); + assert(i + 1 < ir.length, + "unexpected end of IR while looking for hotspot"); ir[i+1] = Bytecode.fromRaw(hotspotTableSize); hotspotTableSize += counterRange.top; } @@ -2066,8 +2157,8 @@ private: ir[repEnd+4].raw *= counterRange.top; ulong cntRange = cast(ulong)(max)*counterRange.top; cumRange += cntRange; - enforce(cumRange < maxCumulativeRepetitionLength - , "repetition length limit is exceeded"); + enforce(cumRange < maxCumulativeRepetitionLength, + "repetition length limit is exceeded"); counterRange.push(cast(uint)cntRange + counterRange.top); threadCount += counterRange.top; break; @@ -2092,7 +2183,7 @@ private: checkIfOneShot(); if(!(flags & RegexInfo.oneShot)) kickstart = Kickstart!Char(this, new uint[](256)); - debug(fred_allocation) writefln("IR processed, max threads: %d", threadCount); + debug(std_regex_allocation) writefln("IR processed, max threads: %d", threadCount); } //IR code validator - proper nesting, illegal instructions, etc. @@ -2103,10 +2194,10 @@ private: if(ir[pc].isStart || ir[pc].isEnd) { uint dest = ir[pc].indexOfPair(pc); - assert(dest < ir.length, text("Wrong length in opcode at pc=" - , pc, " ", dest, " vs ", ir.length)); - assert(ir[dest].paired == ir[pc] - ,text("Wrong pairing of opcodes at pc=", pc, "and pc=", dest)); + assert(dest < ir.length, text("Wrong length in opcode at pc=", + pc, " ", dest, " vs ", ir.length)); + assert(ir[dest].paired == ir[pc], + text("Wrong pairing of opcodes at pc=", pc, "and pc=", dest)); } else if(ir[pc].isAtom) { @@ -2118,11 +2209,8 @@ private: } //print out disassembly a program's IR - @trusted debug public void print() const + @trusted debug(std_regex_parser) void print() const {//@@@BUG@@@ write is system - writefln("PC\tINST\n"); - prettyPrint(delegate void(const(char)[] s){ write(s); },ir); - writefln("\n"); for(uint i = 0; i < ir.length; i += ir[i].length) { writefln("%d\t%s ", i, disassemble(ir, i, dict)); @@ -2132,12 +2220,9 @@ private: } // - this(S,bool x)(Parser!(S,x) p) + this(S)(Parser!(S) p) { - if(__ctfe)//CTFE something funky going on with array - ir = p.ir.dup; - else - ir = p.ir; + ir = p.ir; dict = p.dict; ngroup = p.groupStack.top; maxCounterDepth = p.counterDepth; @@ -2146,14 +2231,46 @@ private: tries = p.tries; backrefed = p.backrefed; lightPostprocess(); - debug(fred_parser) + debug(std_regex_parser) { print(); } - debug validate(); + version(assert) validate(); } } +unittest +{ + auto re = regex(`(?P\w+) = (?P\d+)`); + auto nc = re.namedCaptures; + static assert(isRandomAccessRange!(typeof(nc))); + assert(!nc.empty); + assert(nc.length == 2); + assert(nc.equal(["name", "var"])); + assert(nc[0] == "name"); + assert(nc[1..$].equal(["var"])); + + re = regex(`(\w+) (?P\w+) (\w+)`); + nc = re.namedCaptures; + assert(nc.length == 1); + assert(nc[0] == "named"); + assert(nc.front == "named"); + assert(nc.back == "named"); + + re = regex(`(\w+) (\w+)`); + nc = re.namedCaptures; + assert(nc.empty); + + re = regex(`(?P\d{4})/(?P\d{2})/(?P\d{2})/`); + nc = re.namedCaptures; + auto cp = nc.save; + assert(nc.equal(cp)); + nc.popFront(); + assert(nc.equal(cp[1..$])); + nc.popBack(); + assert(nc.equal(cp[1 .. $ - 1])); +} + // @trusted uint lookupNamedGroup(String)(NamedGroup[] dict, String name) {//equal is @system? @@ -2397,8 +2514,8 @@ int quickTestFwd(RegEx)(uint pc, dchar front, const ref RegEx re) public struct StaticRegex(Char) { private: - alias BacktrackingMatcher!(true) Matcher; - alias bool function(ref Matcher!Char) MatchFn; + alias Matcher = BacktrackingMatcher!(true); + alias MatchFn = bool function(ref Matcher!Char) @trusted; MatchFn nativeFn; public: Regex!Char _regex; @@ -2543,7 +2660,7 @@ public: fChar = re.ir[i].data; static if(charSize != 3) { - Char buf[dchar.sizeof/Char.sizeof]; + Char[dchar.sizeof/Char.sizeof] buf; encode(buf, fChar); fChar = buf[0]; } @@ -2741,7 +2858,7 @@ public: break; t = fetch(trs); } - debug(fred_search) + debug(std_regex_search) { writeln("Min length: ", n_length); } @@ -2761,7 +2878,7 @@ public: auto p = cast(const(ubyte)*)(haystack.ptr+idx); uint state = uint.max; uint limit = 1u<<(n_length - 1u); - debug(fred_search) writefln("Limit: %32b",limit); + debug(std_regex_search) writefln("Limit: %32b",limit); if(fChar != uint.max) { const(ubyte)* end = cast(ubyte*)(haystack.ptr + haystack.length); @@ -2815,7 +2932,7 @@ public: return (p-cast(ubyte*)haystack.ptr)/Char.sizeof -length; } - debug(fred_search) writefln("State: %32b", state); + debug(std_regex_search) writefln("State: %32b", state); } } else @@ -2855,7 +2972,7 @@ public: if(!(state & limit)) return idx+i/Char.sizeof -length; - debug(fred_search) writefln("State: %32b", state); + debug(std_regex_search) writefln("State: %32b", state); } } } @@ -2879,8 +2996,8 @@ unittest { foreach(i, v; TypeTuple!(char, wchar, dchar)) { - alias v Char; - alias immutable(v)[] String; + alias Char = v; + alias String = immutable(v)[]; auto r = regex(to!String(`abc$`)); auto kick = Kick!Char(r, new uint[256]); assert(kick.length == 3, text(Kick.stringof," ",v.stringof, " == ", kick.length)); @@ -2905,8 +3022,8 @@ unittest { foreach(i, v;TypeTuple!(char, wchar, dchar)) { - alias v Char; - alias immutable(v)[] String; + alias Char = v; + alias String = immutable(v)[]; auto r = regex(to!String(`abc[a-z]`)); auto kick = Kick!Char(r, new uint[256]); auto x = kick.search(to!String("abbabca"), 0); @@ -2936,14 +3053,15 @@ unittest test_flex!(ShiftOr)(); } -alias ShiftOr Kickstart; +alias Kickstart = ShiftOr; //Simple UTF-string abstraction compatible with stream interface struct Input(Char) if(is(Char :dchar)) { - alias size_t DataIndex; - alias const(Char)[] String; + alias DataIndex = size_t; + enum { isLoopback = false }; + alias String = const(Char)[]; String _origin; size_t _index; @@ -2983,7 +3101,8 @@ struct Input(Char) struct BackLooper { - alias size_t DataIndex; + alias DataIndex = size_t; + enum { isLoopback = true }; String _origin; size_t _index; this(Input input, size_t index) @@ -3021,14 +3140,14 @@ struct Input(Char) //unsafe, no initialization of elements @system T[] mallocArray(T)(size_t len) { - return (cast(T*)malloc(len*T.sizeof))[0..len]; + return (cast(T*)malloc(len * T.sizeof))[0 .. len]; } //very unsafe, no initialization @system T[] arrayInChunk(T)(size_t len, ref void[] chunk) { auto ret = (cast(T*)chunk.ptr)[0..len]; - chunk = chunk[len*T.sizeof..$]; + chunk = chunk[len * T.sizeof .. $]; return ret; } @@ -3041,7 +3160,7 @@ template BacktrackingMatcher(bool CTregex) @trusted struct BacktrackingMatcher(Char, Stream = Input!Char) if(is(Char : dchar)) { - alias Stream.DataIndex DataIndex; + alias DataIndex = Stream.DataIndex; struct State {//top bit in pc is set if saved along with matches DataIndex index; @@ -3051,11 +3170,11 @@ template BacktrackingMatcher(bool CTregex) enum stateSize = State.sizeof / size_t.sizeof; enum initialStack = 1<<16; alias const(Char)[] String; - static if(CTregex) - alias StaticRegex!Char RegEx; - else - alias Regex!Char RegEx; + alias RegEx = Regex!Char; + alias MatchFn = bool function (ref BacktrackingMatcher!(Char, Stream)); RegEx re; //regex program + static if(CTregex) + MatchFn nativeFn; //native code for that program //Stream state Stream s; DataIndex index; @@ -3144,19 +3263,34 @@ template BacktrackingMatcher(bool CTregex) return tmp; } - // + this(ref RegEx program, Stream stream, void[] memBlock, dchar ch, DataIndex idx) + { + initialize(program, stream, memBlock); + front = ch; + index = idx; + } + this(ref RegEx program, Stream stream, void[] memBlock) { initialize(program, stream, memBlock); next(); } - // - this(ref RegEx program, Stream stream, void[] memBlock, dchar ch, DataIndex idx) + auto fwdMatcher(ref BacktrackingMatcher matcher, void[] memBlock) { - initialize(program, stream, memBlock); - front = ch; - index = idx; + alias BackMatcherTempl = .BacktrackingMatcher!(CTregex); + alias BackMatcher = BackMatcherTempl!(Char, Stream); + auto fwdMatcher = BackMatcher(matcher.re, s, memBlock, front, index); + return fwdMatcher; + } + + auto bwdMatcher(ref BacktrackingMatcher matcher, void[] memBlock) + { + alias BackMatcherTempl = .BacktrackingMatcher!(CTregex); + alias BackMatcher = BackMatcherTempl!(Char, typeof(s.loopBack(index))); + auto fwdMatcher = + BackMatcher(matcher.re, s.loopBack(index), memBlock); + return fwdMatcher; } // @@ -3180,7 +3314,7 @@ template BacktrackingMatcher(bool CTregex) //lookup next match, fill matches with indices into input bool match(Group!DataIndex matches[]) { - debug(fred_matching) + debug(std_regex_matcher) { writeln("------------------------------------------"); } @@ -3200,26 +3334,46 @@ template BacktrackingMatcher(bool CTregex) return m; } static if(kicked) - auto searchFn = re.kickstart.empty ? &this.next :&this.search; - else - auto searchFn = &this.next; + { + if(!re.kickstart.empty) + { + for(;;) + { + + if(matchFinalize()) + return true; + else + { + if(atEnd) + break; + search(); + if(atEnd) + { + exhausted = true; + return matchFinalize(); + } + } + } + exhausted = true; + return false; //early return + } + } + //no search available - skip a char at a time for(;;) { - if(matchFinalize()) return true; else { if(atEnd) break; - searchFn(); + next(); if(atEnd) { exhausted = true; return matchFinalize(); } } - } exhausted = true; return false; @@ -3231,13 +3385,10 @@ template BacktrackingMatcher(bool CTregex) +/ bool matchImpl() { - static if(CTregex && is(typeof(re.nativeFn(this)))) + static if(CTregex && is(typeof(nativeFn(this)))) { - if(re.nativeFn) - { - version(fred_ct) debug writeln("using C-T matcher"); - return re.nativeFn(this); - } + debug(std_regex_ctr) writeln("using C-T matcher"); + return nativeFn(this); } else { @@ -3246,14 +3397,14 @@ template BacktrackingMatcher(bool CTregex) lastState = 0; infiniteNesting = -1;//intentional auto start = s._index; - debug(fred_matching) + debug(std_regex_matcher) writeln("Try match starting at ", s[index..s.lastIndex]); for(;;) { - debug(fred_matching) - writefln("PC: %s\tCNT: %s\t%s \tfront: %s src: %s" - , pc, counter, disassemble(re.ir, pc, re.dict) - , front, s._index); + debug(std_regex_matcher) + writefln("PC: %s\tCNT: %s\t%s \tfront: %s src: %s", + pc, counter, disassemble(re.ir, pc, re.dict), + front, s._index); switch(re.ir[pc].code) { case IR.OrChar://assumes IRL!(OrChar) == 1 @@ -3358,7 +3509,7 @@ template BacktrackingMatcher(bool CTregex) case IR.Eol: dchar back; DataIndex bi; - debug(fred_matching) writefln("EOL (front 0x%x) %s", front, s[index..s.lastIndex]); + debug(std_regex_matcher) writefln("EOL (front 0x%x) %s", front, s[index..s.lastIndex]); //no matching inside \r\n if(atEnd || ((re.flags & RegexOption.multiline) && endOfLine(front, s.loopBack(index).nextChar(back,bi) @@ -3434,7 +3585,7 @@ template BacktrackingMatcher(bool CTregex) case IR.InfiniteEnd: case IR.InfiniteQEnd: uint len = re.ir[pc].data; - debug(fred_matching) writeln("Infinited nesting:", infiniteNesting); + debug(std_regex_matcher) writeln("Infinited nesting:", infiniteNesting); assert(infiniteNesting < trackers.length); if(trackers[infiniteNesting] == index) @@ -3486,13 +3637,13 @@ template BacktrackingMatcher(bool CTregex) case IR.GroupStart: uint n = re.ir[pc].data; matches[n].begin = index; - debug(fred_matching) writefln("IR group #%u starts at %u", n, index); + debug(std_regex_matcher) writefln("IR group #%u starts at %u", n, index); pc += IRL!(IR.GroupStart); break; case IR.GroupEnd: uint n = re.ir[pc].data; matches[n].end = index; - debug(fred_matching) writefln("IR group #%u ends at %u", n, index); + debug(std_regex_matcher) writefln("IR group #%u ends at %u", n, index); pc += IRL!(IR.GroupEnd); break; case IR.LookaheadStart: @@ -3502,7 +3653,14 @@ template BacktrackingMatcher(bool CTregex) uint ms = re.ir[pc+1].raw, me = re.ir[pc+2].raw; auto mem = malloc(initialMemory(re))[0..initialMemory(re)]; scope(exit) free(mem.ptr); - auto matcher = BacktrackingMatcher(re, s, mem, front, index); + static if(Stream.isLoopback) + { + auto matcher = bwdMatcher(this, mem); + } + else + { + auto matcher = fwdMatcher(this, mem); + } matcher.matches = matches[ms .. me]; matcher.backrefed = backrefed.empty ? matches : backrefed; matcher.re.ir = re.ir[pc+IRL!(IR.LookaheadStart) .. pc+IRL!(IR.LookaheadStart)+len+IRL!(IR.LookaheadEnd)]; @@ -3522,11 +3680,20 @@ template BacktrackingMatcher(bool CTregex) uint ms = re.ir[pc+1].raw, me = re.ir[pc+2].raw; auto mem = malloc(initialMemory(re))[0..initialMemory(re)]; scope(exit) free(mem.ptr); - auto backMatcher = BacktrackingMatcher!(Char, typeof(s.loopBack(index)))(re, s.loopBack(index), mem); - backMatcher.matches = matches[ms .. me]; - backMatcher.re.ir = re.ir[pc .. pc+IRL!(IR.LookbehindStart)+len]; - backMatcher.backrefed = backrefed.empty ? matches : backrefed; - bool match = backMatcher.matchBackImpl() ^ (re.ir[pc].code == IR.NeglookbehindStart); + static if(Stream.isLoopback) + { + alias Matcher = BacktrackingMatcher!(Char, Stream); + auto matcher = Matcher(re, s, mem, front, index); + } + else + { + alias Matcher = BacktrackingMatcher!(Char, typeof(s.loopBack(index))); + auto matcher = Matcher(re, s.loopBack(index), mem); + } + matcher.matches = matches[ms .. me]; + matcher.re.ir = re.ir[pc + IRL!(IR.LookbehindStart) .. pc + IRL!(IR.LookbehindStart) + len + IRL!(IR.LookbehindEnd)]; + matcher.backrefed = backrefed.empty ? matches : backrefed; + bool match = matcher.matchImpl() ^ (re.ir[pc].code == IR.NeglookbehindStart); if(!match) goto L_backtrack; else @@ -3554,9 +3721,12 @@ template BacktrackingMatcher(bool CTregex) break; case IR.LookaheadEnd: case IR.NeglookaheadEnd: + case IR.LookbehindEnd: + case IR.NeglookbehindEnd: case IR.End: return true; default: + debug printBytecode(re.ir[0..$]); assert(0); L_backtrack: if(!popState()) @@ -3594,7 +3764,7 @@ template BacktrackingMatcher(bool CTregex) *cast(T*)&memory[lastState] = val; enum delta = (T.sizeof+size_t.sizeof/2)/size_t.sizeof; lastState += delta; - debug(fred_matching) writeln("push element SP= ", lastState); + debug(std_regex_matcher) writeln("push element SP= ", lastState); } void stackPush(T)(T[] val) @@ -3603,7 +3773,7 @@ template BacktrackingMatcher(bool CTregex) (cast(T*)&memory[lastState])[0..val.length] = val[0..$]; lastState += val.length*(T.sizeof/size_t.sizeof); - debug(fred_matching) writeln("push array SP= ", lastState); + debug(std_regex_matcher) writeln("push array SP= ", lastState); } void stackPop(T)(ref T val) @@ -3612,7 +3782,7 @@ template BacktrackingMatcher(bool CTregex) enum delta = (T.sizeof+size_t.sizeof/2)/size_t.sizeof; lastState -= delta; val = *cast(T*)&memory[lastState]; - debug(fred_matching) writeln("pop element SP= ", lastState); + debug(std_regex_matcher) writeln("pop element SP= ", lastState); } void stackPop(T)(T[] val) @@ -3623,7 +3793,7 @@ template BacktrackingMatcher(bool CTregex) { lastState -= val.length*(T.sizeof/size_t.sizeof); val[0..$] = (cast(T*)&memory[lastState])[0..val.length]; - debug(fred_matching) writeln("pop array SP= ", lastState); + debug(std_regex_matcher) writeln("pop array SP= ", lastState); } static if(!CTregex) @@ -3639,11 +3809,11 @@ template BacktrackingMatcher(bool CTregex) *cast(State*)&memory[lastState] = State(index, pc, counter, infiniteNesting); lastState += stateSize; - memory[lastState..lastState+2*matches.length] = (cast(size_t[])matches)[]; + memory[lastState .. lastState + 2 * matches.length] = (cast(size_t[])matches)[]; lastState += 2*matches.length; - debug(fred_matching) - writefln("Saved(pc=%s) front: %s src: %s" - , pc, front, s[index..s.lastIndex]); + debug(std_regex_matcher) + writefln("Saved(pc=%s) front: %s src: %s", + pc, front, s[index..s.lastIndex]); } //helper function, restores engine state @@ -3660,7 +3830,7 @@ template BacktrackingMatcher(bool CTregex) pc = state.pc; counter = state.counter; infiniteNesting = state.infiniteNesting; - debug(fred_matching) + debug(std_regex_matcher) { writefln("Restored matches", front, s[index .. s.lastIndex]); foreach(i, m; matches) @@ -3668,368 +3838,14 @@ template BacktrackingMatcher(bool CTregex) } s.reset(index); next(); - debug(fred_matching) - writefln("Backtracked (pc=%s) front: %s src: %s" - , pc, front, s[index..s.lastIndex]); + debug(std_regex_matcher) + writefln("Backtracked (pc=%s) front: %s src: %s", + pc, front, s[index..s.lastIndex]); return true; } - - /+ - Match subexpression against input, executing re.ir backwards. - Results are stored in matches - +/ - - bool matchBackImpl() - { - pc = cast(uint)re.ir.length-1; - counter = 0; - lastState = 0; - infiniteNesting = -1;//intentional - auto start = index; - debug(fred_matching) - writeln("Try matchBack at ",retro(s[index..s.lastIndex])); - for(;;) - { - debug(fred_matching) - writefln("PC: %s\tCNT: %s\t%s \tfront: %s src: %s" - , pc, counter, disassemble(re.ir, pc, re.dict) - , front, retro(s[index..s.lastIndex])); - switch(re.ir[pc].code) - { - case IR.OrChar://assumes IRL!(OrChar) == 1 - if(atEnd) - goto L_backtrack; - uint len = re.ir[pc].sequence; - uint end = pc - len; - if(re.ir[pc].data != front && re.ir[pc-1].data != front) - { - for(pc = pc-2; pc > end; pc--) - if(re.ir[pc].data == front) - break; - if(pc == end) - goto L_backtrack; } - pc = end; - next(); - break; - case IR.Char: - if(atEnd || front != re.ir[pc].data) - goto L_backtrack; - pc--; - next(); - break; - case IR.Any: - if(atEnd || (!(re.flags & RegexOption.singleline) - && (front == '\r' || front == '\n'))) - goto L_backtrack; - pc--; - next(); - break; - case IR.CodepointSet: - if(atEnd || !re.charsets[re.ir[pc].data].scanFor(front)) - goto L_backtrack; - next(); - pc--; - break; - case IR.Trie: - if(atEnd || !re.tries[re.ir[pc].data][front]) - goto L_backtrack; - next(); - pc--; - break; - case IR.Wordboundary: - dchar back; - DataIndex bi; - //at start & end of input - if(atStart && wordTrie[front]) - { - pc--; - break; } - else if(atEnd && s.loopBack(index).nextChar(back, bi) - && wordTrie[back]) - { - pc--; - break; } - else if(s.loopBack(index).nextChar(back, bi)) - { - bool af = wordTrie[front]; - bool ab = wordTrie[back]; - if(af ^ ab) - { - pc--; - break; - } - } - goto L_backtrack; - case IR.Notwordboundary: - dchar back; - DataIndex bi; - //at start & end of input - if(atStart && wordTrie[front]) - goto L_backtrack; - else if(atEnd && s.loopBack(index).nextChar(back, bi) - && wordTrie[back]) - goto L_backtrack; - else if(s.loopBack(index).nextChar(back, bi)) - { - bool af = wordTrie[front]; - bool ab = wordTrie[back]; - if(af ^ ab) - goto L_backtrack; - } - pc--; - break; - case IR.Bol: - dchar back; - DataIndex bi; - if(atStart) - pc--; - else if((re.flags & RegexOption.multiline) - && s.loopBack(index).nextChar(back,bi) - && endOfLine(back, front == '\n')) - { - pc--; - } - else - goto L_backtrack; - break; - case IR.Eol: - dchar back; - DataIndex bi; - debug(fred_matching) - writefln("EOL (front 0x%x) %s", front, s[index..s.lastIndex]); - //no matching inside \r\n - if((re.flags & RegexOption.multiline) - && s.loopBack(index).nextChar(back,bi) - && endOfLine(front, back == '\r')) - { - pc -= IRL!(IR.Eol); - } - else - goto L_backtrack; - break; - case IR.InfiniteStart, IR.InfiniteQStart: - uint len = re.ir[pc].data; - assert(infiniteNesting < trackers.length); - if(trackers[infiniteNesting] == index) - {//source not consumed - pc--; //out of loop - infiniteNesting--; - break; - } - else - trackers[infiniteNesting] = index; - if(re.ir[pc].code == IR.InfiniteStart)//greedy - { - infiniteNesting--; - pushState(pc-1, counter);//out of loop - infiniteNesting++; - pc += len; - } - else - { - pushState(pc+len, counter); - pc--; - infiniteNesting--; - } - break; - case IR.InfiniteEnd: - case IR.InfiniteQEnd://now it's a start - uint len = re.ir[pc].data; - trackers[infiniteNesting+1] = index; - pc -= len+IRL!(IR.InfiniteStart); - assert(re.ir[pc].code == IR.InfiniteStart - || re.ir[pc].code == IR.InfiniteQStart); - debug(fred_matching) - writeln("(backmatch) Infinite nesting:", infiniteNesting); - if(re.ir[pc].code == IR.InfiniteStart)//greedy - { - pushState(pc-1, counter); - infiniteNesting++; - pc += len; - } - else - { - infiniteNesting++; - pushState(pc + len, counter); - infiniteNesting--; - pc--; - } - break; - case IR.RepeatStart, IR.RepeatQStart: - uint len = re.ir[pc].data; - uint tail = pc + len + 1; - uint step = re.ir[tail+2].raw; - uint min = re.ir[tail+3].raw; - uint max = re.ir[tail+4].raw; - if(counter < min) - { - counter += step; - pc += len; - } - else if(counter < max) - { - if(re.ir[pc].code == IR.RepeatStart)//greedy - { - pushState(pc-1, counter%step); - counter += step; - pc += len; - } - else - { - pushState(pc + len, counter + step); - counter = counter%step; - pc--; - } - } - else - { - counter = counter%step; - pc--; - } - break; - case IR.RepeatEnd: - case IR.RepeatQEnd: - pc -= re.ir[pc].data+IRL!(IR.RepeatStart); - assert(re.ir[pc].code == IR.RepeatStart || re.ir[pc].code == IR.RepeatQStart); - goto case IR.RepeatStart; - case IR.OrEnd: - uint len = re.ir[pc].data; - pc -= len; - assert(re.ir[pc].code == IR.Option); - len = re.ir[pc].data; - auto pc_save = pc+len-IRL!(IR.GotoEndOr); - pc = pc + len + IRL!(IR.Option); - while(re.ir[pc].code == IR.Option) - { - pushState(pc-IRL!(IR.GotoEndOr)-1, counter); - len = re.ir[pc].data; - pc += len + IRL!(IR.Option); - } - assert(re.ir[pc].code == IR.OrEnd); - pc--; - if(pc != pc_save) - { - pushState(pc, counter); - pc = pc_save; - } - break; - case IR.OrStart: - assert(0); - case IR.Option: - assert(re.ir[pc].code == IR.Option); - pc += re.ir[pc].data + IRL!(IR.Option); - if(re.ir[pc].code == IR.Option) - { - pc--;//hackish, assumes size of IR.Option == 1 - if(re.ir[pc].code == IR.GotoEndOr) - { - pc += re.ir[pc].data + IRL!(IR.GotoEndOr); - } - - } - assert(re.ir[pc].code == IR.OrEnd); - pc -= re.ir[pc].data + IRL!(IR.OrStart)+1; - break; - case IR.GotoEndOr: - assert(0); - case IR.GroupStart: - uint n = re.ir[pc].data; - matches[n].begin = index; - debug(fred_matching) writefln("IR group #%u starts at %u", n, index); - pc --; - break; - case IR.GroupEnd: - uint n = re.ir[pc].data; - matches[n].end = index; - debug(fred_matching) writefln("IR group #%u ends at %u", n, index); - pc --; - break; - case IR.LookaheadStart: - case IR.NeglookaheadStart: - assert(0); - case IR.LookaheadEnd: - case IR.NeglookaheadEnd: - uint len = re.ir[pc].data; - pc -= len + IRL!(IR.LookaheadStart); - uint ms = re.ir[pc+1].raw, me = re.ir[pc+2].raw; - auto mem = malloc(initialMemory(re))[0..initialMemory(re)]; - scope(exit) free(mem.ptr); - auto matcher = BacktrackingMatcher!(Char, typeof(s.loopBack(index)))(re, s.loopBack(index), mem); - matcher.matches = matches[ms .. me]; - matcher.backrefed = backrefed.empty ? matches : backrefed; - matcher.re.ir = re.ir[pc+IRL!(IR.LookaheadStart) .. pc+IRL!(IR.LookaheadStart)+len+IRL!(IR.LookaheadEnd)]; - bool match = matcher.matchImpl() ^ (re.ir[pc].code == IR.NeglookaheadStart); - if(!match) - goto L_backtrack; - else - { - pc --; - } - break; - case IR.LookbehindEnd: - case IR.NeglookbehindEnd: - uint len = re.ir[pc].data; - pc -= len + IRL!(IR.LookbehindStart); - auto save = index; - uint ms = re.ir[pc+1].raw, me = re.ir[pc+2].raw; - auto mem = malloc(initialMemory(re))[0..initialMemory(re)]; - scope(exit) free(mem.ptr); - auto matcher = BacktrackingMatcher(re, s, mem, front, index); - matcher.re.ngroup = me - ms; - matcher.matches = matches[ms .. me]; - matcher.backrefed = backrefed.empty ? matches : backrefed; - matcher.re.ir = re.ir[pc .. pc+IRL!(IR.LookbehindStart)+len]; - bool match = matcher.matchBackImpl() ^ (re.ir[pc].code == IR.NeglookbehindStart); - s.reset(save); - next(); - if(!match) - goto L_backtrack; - else - { - pc --; - } - break; - case IR.Backref: - uint n = re.ir[pc].data; - auto referenced = re.ir[pc].localRef - ? s[matches[n].begin .. matches[n].end] - : s[backrefed[n].begin .. backrefed[n].end]; - while(!atEnd && !referenced.empty && front == referenced.front) - { - next(); - referenced.popFront(); - } - if(referenced.empty) - pc--; - else - goto L_backtrack; - break; - case IR.Nop: - pc --; - break; - case IR.LookbehindStart: - case IR.NeglookbehindStart: - return true; - default: - assert(re.ir[pc].code < 0x80); - pc --; //data - break; - L_backtrack: - if(!popState()) - { - s.reset(start); - return false; - } - } - } - return true; - } - } - } -} //very shitty string formatter, $$ replaced with next argument converted to string @trusted string ctSub( U...)(string format, U args) @@ -4043,8 +3859,8 @@ template BacktrackingMatcher(bool CTregex) { static if(args.length > 0) { - return format[0..i-1] ~ to!string(args[0]) - ~ ctSub(format[i+1..$], args[1..$]); + return format[0 .. i - 1] ~ to!string(args[0]) + ~ ctSub(format[i + 1 .. $], args[1 .. $]); } else assert(0); @@ -4083,8 +3899,11 @@ struct CtContext { //dirty flags bool counter, infNesting; - int nInfLoops; // to make a unique advancement counter per loop + // to make a unique advancement counter per nesting level of loops + int curInfLoop, nInfLoops; + //to mark the portion of matches to save int match, total_matches; + int reserved; //state of codegenerator @@ -4097,9 +3916,18 @@ struct CtContext this(Char)(Regex!Char re) { match = 1; + reserved = 1; //first match is skipped total_matches = re.ngroup; } + CtContext lookaround() + { + CtContext ct; + ct.total_matches = total_matches; + ct.match = 1; + return ct; + } + //restore state having current context string restoreCode() { @@ -4113,13 +3941,13 @@ struct CtContext if(match < total_matches) { text ~= ctSub(" - stackPop(matches[1..$$]);", match); + stackPop(matches[$$..$$]);", reserved, match); text ~= ctSub(" matches[$$..$] = typeof(matches[0]).init;", match); } else - text ~= " - stackPop(matches[1..$]);"; + text ~= ctSub(" + stackPop(matches[$$..$]);", reserved); return text; } @@ -4131,13 +3959,13 @@ struct CtContext { newStack(); lastState = 0; - }", match-1, cast(int)counter + 2); + }", match - reserved, cast(int)counter + 2); if(match < total_matches) text ~= ctSub(" - stackPush(matches[1..$$]);", match); + stackPush(matches[$$..$$]);", reserved, match); else - text ~= " - stackPush(matches[1..$]);"; + text ~= ctSub(" + stackPush(matches[$$..$]);", reserved); text ~= counter ? ctSub(" stackPush($$);", count_expr) : ""; text ~= ctSub(" @@ -4162,6 +3990,8 @@ struct CtContext // CtState ctGenGroup(ref Bytecode[] ir, int addr) { + auto bailOut = "goto L_backtrack;"; + auto nextInstr = ctSub("goto case $$;", addr+1); CtState r; assert(!ir.empty); switch(ir[0].code) @@ -4171,15 +4001,20 @@ struct CtContext ir[0].code == IR.InfiniteStart || ir[0].code == IR.InfiniteQStart; infNesting = infNesting || infLoop; if(infLoop) - nInfLoops++; + { + curInfLoop++; + nInfLoops = max(nInfLoops, curInfLoop+1); + } counter = counter || ir[0].code == IR.RepeatStart || ir[0].code == IR.RepeatQStart; uint len = ir[0].data; auto nir = ir[ir[0].length .. ir[0].length+len]; r = ctGenBlock(nir, addr+1); + if(infLoop) + curInfLoop--; //start/end codegen //r.addr is at last test+ jump of loop, addr+1 is body of loop - nir = ir[ir[0].length+len..$]; + nir = ir[ir[0].length + len .. $]; r.code = ctGenFixupCode(ir[0..ir[0].length], addr, r.addr) ~ r.code; r.code ~= ctGenFixupCode(nir, r.addr, addr+1); r.addr += 2; //account end instruction + restore state @@ -4189,10 +4024,69 @@ struct CtContext uint len = ir[0].data; auto nir = ir[ir[0].length .. ir[0].length+len]; r = ctGenAlternation(nir, addr); - ir = ir[ir[0].length+len..$]; + ir = ir[ir[0].length + len .. $]; assert(ir[0].code == IR.OrEnd); ir = ir[ir[0].length..$]; break; + case IR.LookaheadStart: + case IR.NeglookaheadStart: + case IR.LookbehindStart: + case IR.NeglookbehindStart: + uint len = ir[0].data; + bool behind = ir[0].code == IR.LookbehindStart || ir[0].code == IR.NeglookbehindStart; + bool negative = ir[0].code == IR.NeglookaheadStart || ir[0].code == IR.NeglookbehindStart; + string fwdType = "typeof(fwdMatcher(matcher, []))"; + string bwdType = "typeof(bwdMatcher(matcher, []))"; + string fwdCreate = "fwdMatcher(matcher, mem)"; + string bwdCreate = "bwdMatcher(matcher, mem)"; + uint start = IRL!(IR.LookbehindStart); + uint end = IRL!(IR.LookbehindStart)+len+IRL!(IR.LookaheadEnd); + CtContext context = lookaround(); //split off new context + auto slice = ir[start .. end]; + r.code ~= ctSub(` + case $$: //fake lookaround "atom" + static if(typeof(matcher.s).isLoopback) + alias Lookaround = $$; + else + alias Lookaround = $$; + static bool matcher_$$(ref Lookaround matcher) @trusted + { + //(neg)lookaround piece start + $$ + //(neg)lookaround piece ends + } + auto save = index; + auto mem = malloc(initialMemory(re))[0..initialMemory(re)]; + scope(exit) free(mem.ptr); + static if(typeof(matcher.s).isLoopback) + auto lookaround = $$; + else + auto lookaround = $$; + lookaround.matches = matches[$$..$$]; + lookaround.backrefed = backrefed.empty ? matches : backrefed; + lookaround.nativeFn = &matcher_$$; //hookup closure's binary code + bool match = $$; + s.reset(save); + next(); + if(match) + $$ + else + $$`, addr, + behind ? fwdType : bwdType, behind ? bwdType : fwdType, + addr, context.ctGenRegEx(slice), + behind ? fwdCreate : bwdCreate, behind ? bwdCreate : fwdCreate, + ir[1].raw, ir[2].raw, //start - end of matches slice + addr, + negative ? "!lookaround.matchImpl()" : "lookaround.matchImpl()", + nextInstr, bailOut); + ir = ir[end .. $]; + r.addr = addr + 1; + break; + case IR.LookaheadEnd: case IR.NeglookaheadEnd: + case IR.LookbehindEnd: case IR.NeglookbehindEnd: + ir = ir[IRL!(IR.LookaheadEnd) .. $]; + r.addr = addr; + break; default: assert(ir[0].isAtom, text(ir[0].mnemonic)); r = ctGenAtom(ir, addr); @@ -4209,16 +4103,16 @@ struct CtContext for(;;) { assert(ir[0].code == IR.Option); - auto len = ir[0].data; - auto nir = ir[optL .. optL+len-IRL!(IR.GotoEndOr)]; + auto len = ir[0].data; if(optL+len < ir.length && ir[optL+len].code == IR.Option)//not a last option { + auto nir = ir[optL .. optL+len-IRL!(IR.GotoEndOr)]; r = ctGenBlock(nir, addr+2);//space for Option + restore state //r.addr+1 to account GotoEndOr at end of branch r.code = ctGenFixupCode(ir[0 .. ir[0].length], addr, r.addr+1) ~ r.code; addr = r.addr+1;//leave space for GotoEndOr pieces ~= r; - ir = ir[optL+len..$]; + ir = ir[optL + len .. $]; } else { @@ -4226,7 +4120,6 @@ struct CtContext addr = pieces[$-1].addr; break; } - } r = pieces[0]; for(uint i = 1; i < pieces.length; i++) @@ -4251,18 +4144,18 @@ struct CtContext string r; string testCode; r = ctSub(` - case $$: debug(fred_matching) writeln("$$");`, + case $$: debug(std_regex_matcher) writeln("#$$");`, addr, addr); switch(ir[0].code) { case IR.InfiniteStart, IR.InfiniteQStart: r ~= ctSub( ` tracker_$$ = DataIndex.max; - goto case $$;`, nInfLoops-1, fixup); + goto case $$;`, curInfLoop, fixup); ir = ir[ir[0].length..$]; break; case IR.InfiniteEnd: - testCode = ctQuickTest(ir[IRL!(IR.InfiniteEnd)..$],addr+1); + testCode = ctQuickTest(ir[IRL!(IR.InfiniteEnd) .. $],addr + 1); r ~= ctSub( ` if(tracker_$$ == index) {//source not consumed @@ -4277,13 +4170,13 @@ struct CtContext goto case $$; case $$: //restore state and go out of loop $$ - goto case;`, nInfLoops-1, addr+2 - , nInfLoops-1, testCode, saveCode(addr+1) - , fixup, addr+1, restoreCode()); + goto case;`, curInfLoop, addr+2, + curInfLoop, testCode, saveCode(addr+1), + fixup, addr+1, restoreCode()); ir = ir[ir[0].length..$]; break; case IR.InfiniteQEnd: - testCode = ctQuickTest(ir[IRL!(IR.InfiniteEnd)..$],addr+1); + testCode = ctQuickTest(ir[IRL!(IR.InfiniteEnd) .. $],addr + 1); r ~= ctSub( ` if(tracker_$$ == index) {//source not consumed @@ -4300,9 +4193,9 @@ struct CtContext goto case $$; case $$://restore state and go inside loop $$ - goto case $$;`, nInfLoops-1, addr+2, nInfLoops-1 - , testCode, saveCode(addr+1) - , addr+2, fixup, addr+1, restoreCode(), fixup); + goto case $$;`, curInfLoop, addr+2, curInfLoop, + testCode, saveCode(addr+1), + addr+2, fixup, addr+1, restoreCode(), fixup); ir = ir[ir[0].length..$]; break; case IR.RepeatStart, IR.RepeatQStart: @@ -4319,7 +4212,7 @@ struct CtContext r ~= ctSub(` if(counter < $$) { - debug(fred_matching) writeln("RepeatEnd min case pc=", $$); + debug(std_regex_matcher) writeln("RepeatEnd min case pc=", $$); counter += $$; goto case $$; }`, min, addr, step, fixup); @@ -4353,22 +4246,22 @@ struct CtContext } case $$: //restore state $$ - goto case $$;`, step, addr+2, addr+1, restoreCode() - , ir[0].code == IR.RepeatEnd ? addr+2 : fixup ); + goto case $$;`, step, addr+2, addr+1, restoreCode(), + ir[0].code == IR.RepeatEnd ? addr+2 : fixup ); ir = ir[ir[0].length..$]; - break; + break; case IR.Option: - r ~= ctSub( ` - { - $$ - } - goto case $$; - case $$://restore thunk to go to the next group + r ~= ctSub( ` + { $$ - goto case $$;`, saveCode(addr+1), addr+2 - , addr+1, restoreCode(), fixup); + } + goto case $$; + case $$://restore thunk to go to the next group + $$ + goto case $$;`, saveCode(addr+1), addr+2, + addr+1, restoreCode(), fixup); ir = ir[ir[0].length..$]; - break; + break; default: assert(0, text(ir[0].mnemonic)); } @@ -4393,8 +4286,8 @@ struct CtContext { $$ //$$ } - if(test_$$() >= 0)`, id, code ? code : "return 0;" - , ir[pc].mnemonic, id); + if(test_$$() >= 0)`, id, code.ptr ? code : "return 0;", + ir[pc].mnemonic, id); } } return ""; @@ -4425,7 +4318,7 @@ struct CtContext bailOut = "goto L_backtrack;"; nextInstr = ctSub("goto case $$;", addr+1); code ~= ctSub( ` - case $$: debug(fred_matching) writeln("#$$"); + case $$: debug(std_regex_matcher) writeln("#$$"); `, addr, addr); } switch(ir[0].code) @@ -4498,8 +4391,7 @@ struct CtContext $$ } } - $$` - , nextInstr, nextInstr, nextInstr, bailOut); + $$`, nextInstr, nextInstr, nextInstr, bailOut); break; case IR.Notwordboundary: code ~= ctSub( ` @@ -4529,6 +4421,7 @@ struct CtContext && s.loopBack(index).nextChar(back,bi) && endOfLine(back, front == '\n'))) { + debug(std_regex_matcher) writeln("BOL matched"); $$ } else @@ -4539,12 +4432,13 @@ struct CtContext code ~= ctSub(` dchar back; DataIndex bi; - debug(fred_matching) writefln("EOL (front 0x%x) %s", front, s[index..s.lastIndex]); + debug(std_regex_matcher) writefln("EOL (front 0x%x) %s", front, s[index..s.lastIndex]); //no matching inside \r\n if(atEnd || ((re.flags & RegexOption.multiline) - && s.loopBack(index).nextChar(back,bi) - && endOfLine(front, back == '\r'))) + && endOfLine(front, s.loopBack(index).nextChar(back,bi) + && back == '\r'))) { + debug(std_regex_matcher) writeln("EOL matched"); $$ } else @@ -4563,9 +4457,12 @@ struct CtContext $$`, ir[0].data, nextInstr); break; case IR.Backref: - string mStr = ir[0].localRef - ? ctSub("matches[$$].begin .. matches[$$].end];", ir[0].data, ir[0].data) - : ctSub("s[backrefed[$$].begin .. backrefed[$$].end];",ir[0].data, ir[0].data); + string mStr = "auto referenced = "; + mStr ~= ir[0].localRef + ? ctSub("s[matches[$$].begin .. matches[$$].end];", + ir[0].data, ir[0].data) + : ctSub("s[backrefed[$$].begin .. backrefed[$$].end];", + ir[0].data, ir[0].data); code ~= ctSub( ` $$ while(!atEnd && !referenced.empty && front == referenced.front) @@ -4582,15 +4479,15 @@ struct CtContext case IR.End: break; default: - assert(0, text(ir[0].mnemonic, "is not supported yet")); + assert(0, text(ir[0].mnemonic, " is not supported yet")); } return code; } //generate D code for the whole regex - public string ctGenRegEx(Char)(ref Regex!Char re) + public string ctGenRegEx(Bytecode[] ir) { - auto bdy = ctGenBlock(re.ir, 0); + auto bdy = ctGenBlock(ir, 0); auto r = ` with(matcher) { @@ -4603,7 +4500,7 @@ struct CtContext size_t tracker_$$;`, i); r ~= ` goto StartLoop; - debug(fred_matching) writeln("Try CT matching starting at ",s[index..s.lastIndex]); + debug(std_regex_matcher) writeln("Try CT matching starting at ",s[index..s.lastIndex]); L_backtrack: if(lastState || prevStack()) { @@ -4639,7 +4536,7 @@ struct CtContext string ctGenRegExCode(Char)(Regex!Char re) { auto context = CtContext(re); - return context.ctGenRegEx(re); + return context.ctGenRegEx(re.ir); } //State of VM thread @@ -4725,7 +4622,7 @@ enum OneShot { Fwd, Bwd }; @trusted struct ThompsonMatcher(Char, Stream = Input!Char) if(is(Char : dchar)) { - alias Stream.DataIndex DataIndex; + alias DataIndex = Stream.DataIndex; Thread!DataIndex* freelist; ThreadList!DataIndex clist, nlist; DataIndex[] merge; @@ -4815,6 +4712,22 @@ enum OneShot { Fwd, Bwd }; merge = matcher.merge; genCounter = matcher.genCounter; freelist = matcher.freelist; + front = matcher.front; + index = matcher.index; + } + + auto fwdMatcher()(Bytecode[] piece) + { + auto m = ThompsonMatcher!(Char, Stream)(this, piece, s); + return m; + } + + auto bwdMatcher()(Bytecode[] piece) + { + alias BackLooper = typeof(s.loopBack(index)); + auto m = ThompsonMatcher!(Char, BackLooper)(this, piece, s.loopBack(index)); + m.next(); + return m; } auto dupTo(void[] memory) @@ -4831,10 +4744,9 @@ enum OneShot { Fwd, Bwd }; Match, } - //match the input and fill matches bool match(Group!DataIndex[] matches) { - debug(fred_matching) + debug(std_regex_matcher) writeln("------------------------------------------"); if(exhausted) { @@ -4844,15 +4756,23 @@ enum OneShot { Fwd, Bwd }; { next(); exhausted = true; - return matchOneShot!(OneShot.Fwd)(matches)==MatchResult.Match; + return matchOneShot(matches)==MatchResult.Match; } static if(kicked) - auto searchFn = re.kickstart.empty ? &this.next : &this.search; - else - auto searchFn = &this.next; - if((!matched) && clist.empty) + if(!re.kickstart.empty) + return matchImpl!(true)(matches); + return matchImpl!(false)(matches); + } + + //match the input and fill matches + bool matchImpl(bool withSearch)(Group!DataIndex[] matches) + { + if(!matched && clist.empty) { - searchFn(); + static if(withSearch) + search(); + else + next(); } else//char in question is fetched in prev call to match { @@ -4863,7 +4783,7 @@ enum OneShot { Fwd, Bwd }; for(;;) { genCounter++; - debug(fred_matching) + debug(std_regex_matcher) { writefln("Threaded matching threads at %s", s[index..s.lastIndex]); foreach(t; clist[]) @@ -4882,15 +4802,23 @@ enum OneShot { Fwd, Bwd }; eval!true(createStart(index), matches);//new thread staring at this position else if(nlist.empty) { - debug(fred_matching) writeln("Stopped matching before consuming full input"); + debug(std_regex_matcher) writeln("Stopped matching before consuming full input"); break;//not a partial match for sure } clist = nlist; nlist = (ThreadList!DataIndex).init; if(clist.tip is null) { - if(!searchFn()) - break; + static if(withSearch) + { + if(!search()) + break; + } + else + { + if(!next()) + break; + } } else if(!next()) { @@ -4901,7 +4829,7 @@ enum OneShot { Fwd, Bwd }; } genCounter++; //increment also on each end - debug(fred_matching) writefln("Threaded matching threads at end"); + debug(std_regex_matcher) writefln("Threaded matching threads at end"); //try out all zero-width posibilities for(Thread!DataIndex* t = clist.fetch(); t; t = clist.fetch()) { @@ -4929,7 +4857,7 @@ enum OneShot { Fwd, Bwd }; void finish(const(Thread!DataIndex)* t, Group!DataIndex[] matches) { matches.ptr[0..re.ngroup] = t.matches.ptr[0..re.ngroup]; - debug(fred_matching) + debug(std_regex_matcher) { writef("FOUND pc=%s prog_len=%s", t.pc, re.ir.length); @@ -4948,10 +4876,10 @@ enum OneShot { Fwd, Bwd }; void eval(bool withInput)(Thread!DataIndex* t, Group!DataIndex[] matches) { ThreadList!DataIndex worklist; - debug(fred_matching) writeln("---- Evaluating thread"); + debug(std_regex_matcher) writeln("---- Evaluating thread"); for(;;) { - debug(fred_matching) + debug(std_regex_matcher) { writef("\tpc=%s [", t.pc); foreach(x; worklist[]) @@ -4967,7 +4895,7 @@ enum OneShot { Fwd, Bwd }; //cut off low priority threads recycle(clist); recycle(worklist); - debug(fred_matching) writeln("Finished thread ", matches); + debug(std_regex_matcher) writeln("Finished thread ", matches); return; case IR.Wordboundary: dchar back; @@ -5054,7 +4982,7 @@ enum OneShot { Fwd, Bwd }; } break; case IR.Eol: - debug(fred_matching) writefln("EOL (front 0x%x) %s", front, s[index..s.lastIndex]); + debug(std_regex_matcher) writefln("EOL (front 0x%x) %s", front, s[index..s.lastIndex]); dchar back; DataIndex bi; //no matching inside \r\n @@ -5092,13 +5020,13 @@ enum OneShot { Fwd, Bwd }; } if(merge[re.ir[t.pc + 1].raw+t.counter] < genCounter) { - debug(fred_matching) writefln("A thread(pc=%s) passed there : %s ; GenCounter=%s mergetab=%s", + debug(std_regex_matcher) writefln("A thread(pc=%s) passed there : %s ; GenCounter=%s mergetab=%s", t.pc, index, genCounter, merge[re.ir[t.pc + 1].raw+t.counter] ); merge[re.ir[t.pc + 1].raw+t.counter] = genCounter; } else { - debug(fred_matching) writefln("A thread(pc=%s) got merged there : %s ; GenCounter=%s mergetab=%s", + debug(std_regex_matcher) writefln("A thread(pc=%s) got merged there : %s ; GenCounter=%s mergetab=%s", t.pc, index, genCounter, merge[re.ir[t.pc + 1].raw+t.counter] ); recycle(t); t = worklist.fetch(); @@ -5134,13 +5062,13 @@ enum OneShot { Fwd, Bwd }; case IR.InfiniteQEnd: if(merge[re.ir[t.pc + 1].raw+t.counter] < genCounter) { - debug(fred_matching) writefln("A thread(pc=%s) passed there : %s ; GenCounter=%s mergetab=%s", + debug(std_regex_matcher) writefln("A thread(pc=%s) passed there : %s ; GenCounter=%s mergetab=%s", t.pc, index, genCounter, merge[re.ir[t.pc + 1].raw+t.counter] ); merge[re.ir[t.pc + 1].raw+t.counter] = genCounter; } else { - debug(fred_matching) writefln("A thread(pc=%s) got merged there : %s ; GenCounter=%s mergetab=%s", + debug(std_regex_matcher) writefln("A thread(pc=%s) got merged there : %s ; GenCounter=%s mergetab=%s", t.pc, index, genCounter, merge[re.ir[t.pc + 1].raw+t.counter] ); recycle(t); t = worklist.fetch(); @@ -5180,15 +5108,15 @@ enum OneShot { Fwd, Bwd }; case IR.OrEnd: if(merge[re.ir[t.pc + 1].raw+t.counter] < genCounter) { - debug(fred_matching) writefln("A thread(pc=%s) passed there : %s ; GenCounter=%s mergetab=%s", - t.pc, s[index..s.lastIndex], genCounter, merge[re.ir[t.pc + 1].raw+t.counter] ); + debug(std_regex_matcher) writefln("A thread(pc=%s) passed there : %s ; GenCounter=%s mergetab=%s", + t.pc, s[index .. s.lastIndex], genCounter, merge[re.ir[t.pc + 1].raw + t.counter] ); merge[re.ir[t.pc + 1].raw+t.counter] = genCounter; t.pc += IRL!(IR.OrEnd); } else { - debug(fred_matching) writefln("A thread(pc=%s) got merged there : %s ; GenCounter=%s mergetab=%s", - t.pc, s[index..s.lastIndex], genCounter, merge[re.ir[t.pc + 1].raw+t.counter] ); + debug(std_regex_matcher) writefln("A thread(pc=%s) got merged there : %s ; GenCounter=%s mergetab=%s", + t.pc, s[index .. s.lastIndex], genCounter, merge[re.ir[t.pc + 1].raw + t.counter] ); recycle(t); t = worklist.fetch(); if(!t) @@ -5260,17 +5188,22 @@ enum OneShot { Fwd, Bwd }; break; case IR.LookbehindStart: case IR.NeglookbehindStart: - auto matcher = - ThompsonMatcher!(Char, typeof(s.loopBack(index))) - (this, re.ir[t.pc..t.pc+re.ir[t.pc].data+IRL!(IR.LookbehindStart)], s.loopBack(index)); + uint len = re.ir[t.pc].data; + uint ms = re.ir[t.pc + 1].raw, me = re.ir[t.pc + 2].raw; + uint end = t.pc + len + IRL!(IR.LookbehindEnd) + IRL!(IR.LookbehindStart); + bool positive = re.ir[t.pc].code == IR.LookbehindStart; + static if(Stream.isLoopback) + auto matcher = fwdMatcher(re.ir[t.pc .. end]); + else + auto matcher = bwdMatcher(re.ir[t.pc .. end]); matcher.re.ngroup = re.ir[t.pc+2].raw - re.ir[t.pc+1].raw; matcher.backrefed = backrefed.empty ? t.matches : backrefed; //backMatch - matcher.next(); //load first character from behind - bool match = (matcher.matchOneShot!(OneShot.Bwd)(t.matches)==MatchResult.Match) ^ (re.ir[t.pc].code == IR.LookbehindStart); + bool nomatch = (matcher.matchOneShot(t.matches, IRL!(IR.LookbehindStart)) + == MatchResult.Match) ^ positive; freelist = matcher.freelist; genCounter = matcher.genCounter; - if(match) + if(nomatch) { recycle(t); t = worklist.fetch(); @@ -5279,31 +5212,23 @@ enum OneShot { Fwd, Bwd }; break; } else - t.pc += re.ir[t.pc].data + IRL!(IR.LookbehindStart) + IRL!(IR.LookbehindEnd); + t.pc = end; break; - case IR.LookaheadEnd: - case IR.NeglookaheadEnd: - t.pc = re.ir[t.pc].indexOfPair(t.pc); - assert(re.ir[t.pc].code == IR.LookaheadStart || re.ir[t.pc].code == IR.NeglookaheadStart); - uint ms = re.ir[t.pc+1].raw, me = re.ir[t.pc+2].raw; - finish(t, matches.ptr[ms..me]); - recycle(t); - //cut off low priority threads - recycle(clist); - recycle(worklist); - return; case IR.LookaheadStart: case IR.NeglookaheadStart: auto save = index; uint len = re.ir[t.pc].data; uint ms = re.ir[t.pc+1].raw, me = re.ir[t.pc+2].raw; + uint end = t.pc+len+IRL!(IR.LookaheadEnd)+IRL!(IR.LookaheadStart); bool positive = re.ir[t.pc].code == IR.LookaheadStart; - auto matcher = ThompsonMatcher(this, re.ir[t.pc .. t.pc+len+IRL!(IR.LookaheadEnd)+IRL!(IR.LookaheadStart)], s); - matcher.front = front; - matcher.index = index; + static if(Stream.isLoopback) + auto matcher = bwdMatcher(re.ir[t.pc .. end]); + else + auto matcher = fwdMatcher(re.ir[t.pc .. end]); matcher.re.ngroup = me - ms; matcher.backrefed = backrefed.empty ? t.matches : backrefed; - bool nomatch = (matcher.matchOneShot!(OneShot.Fwd)(t.matches, IRL!(IR.LookaheadStart)) == MatchResult.Match) ^ positive; + bool nomatch = (matcher.matchOneShot(t.matches, IRL!(IR.LookaheadStart)) + == MatchResult.Match) ^ positive; freelist = matcher.freelist; genCounter = matcher.genCounter; s.reset(index); @@ -5317,11 +5242,20 @@ enum OneShot { Fwd, Bwd }; break; } else - t.pc += len + IRL!(IR.LookaheadEnd) + IRL!(IR.LookaheadStart); + t.pc = end; break; + case IR.LookaheadEnd: + case IR.NeglookaheadEnd: case IR.LookbehindEnd: case IR.NeglookbehindEnd: - assert(0); + t.pc = re.ir[t.pc].indexOfPair(t.pc); + uint ms = re.ir[t.pc+1].raw, me = re.ir[t.pc+2].raw; + finish(t, matches.ptr[ms..me]); + recycle(t); + //cut off low priority threads + recycle(clist); + recycle(worklist); + return; case IR.Nop: t.pc += IRL!(IR.Nop); break; @@ -5414,31 +5348,21 @@ enum OneShot { Fwd, Bwd }; } enum uint RestartPc = uint.max; //match the input, evaluating IR without searching - MatchResult matchOneShot(OneShot direction)(Group!DataIndex[] matches, uint startPc = 0) + MatchResult matchOneShot(Group!DataIndex[] matches, uint startPc = 0) { - debug(fred_matching) + debug(std_regex_matcher) { - writefln("---------------single shot match %s----------------- ", - direction == OneShot.Fwd ? "forward" : "backward"); + writefln("---------------single shot match ----------------- "); } - static if(direction == OneShot.Fwd) alias eval evalFn; - else - alias evalBack evalFn; assert(clist == (ThreadList!DataIndex).init || startPc == RestartPc); // incorrect after a partial match assert(nlist == (ThreadList!DataIndex).init || startPc == RestartPc); - static if(direction == OneShot.Fwd) startPc = startPc; - else - startPc = cast(uint)re.ir.length-IRL!(IR.LookbehindEnd); if(!atEnd)//if no char { - debug(fred_matching) + debug(std_regex_matcher) { - static if(direction == OneShot.Fwd) - writefln("-- Threaded matching (forward) threads at %s", s[index..s.lastIndex]); - else - writefln("-- Threaded matching (backward) threads at %s", retro(s[index..s.lastIndex])); + writefln("-- Threaded matching threads at %s", s[index..s.lastIndex]); } if(startPc!=RestartPc) { @@ -5448,9 +5372,9 @@ enum OneShot { Fwd, Bwd }; } for(;;) { - debug(fred_matching) writeln("\n-- Started iteration of main cycle"); - genCounter++; - debug(fred_matching) + debug(std_regex_matcher) writeln("\n-- Started iteration of main cycle"); + genCounter++; + debug(std_regex_matcher) { foreach(t; clist[]) { @@ -5463,7 +5387,7 @@ enum OneShot { Fwd, Bwd }; } if(nlist.empty) { - debug(fred_matching) writeln("Stopped matching before consuming full input"); + debug(std_regex_matcher) writeln("Stopped matching before consuming full input"); break;//not a partial match for sure } clist = nlist; @@ -5473,12 +5397,11 @@ enum OneShot { Fwd, Bwd }; if (!atEnd) return MatchResult.PartialMatch; break; } - debug(fred_matching) writeln("-- Ended iteration of main cycle\n"); + debug(std_regex_matcher) writeln("-- Ended iteration of main cycle\n"); } } genCounter++; //increment also on each end - debug(fred_matching) writefln("-- Threaded matching (%s) threads at end", - direction == OneShot.Fwd ? "forward" : "backward"); + debug(std_regex_matcher) writefln("-- Matching threads at end"); //try out all zero-width posibilities for(Thread!DataIndex* t = clist.fetch(); t; t = clist.fetch()) { @@ -5490,436 +5413,6 @@ enum OneShot { Fwd, Bwd }; return (matched?MatchResult.Match:MatchResult.NoMatch); } - /+ - a version of eval that executes IR backwards - +/ - void evalBack(bool withInput)(Thread!DataIndex* t, Group!DataIndex[] matches) - { - ThreadList!DataIndex worklist; - debug(fred_matching) writeln("---- Evaluating thread backwards"); - do - { - debug(fred_matching) - { - writef("\tpc=%s [", t.pc); - foreach(x; worklist[]) - writef(" %s ", x.pc); - writeln("]"); - } - debug(fred_matching) writeln(disassemble(re.ir, t.pc)); - switch(re.ir[t.pc].code) - { - case IR.Wordboundary: - dchar back; - DataIndex bi; - //at start & end of input - if(atStart && wordTrie[front]) - { - t.pc--; - break; - } - else if(atEnd && s.loopBack(index).nextChar(back, bi) - && wordTrie[back]) - { - t.pc--; - break; - } - else if(s.loopBack(index).nextChar(back, bi)) - { - bool af = wordTrie[front]; - bool ab = wordTrie[back]; - if(af ^ ab) - { - t.pc--; - break; - } - } - recycle(t); - t = worklist.fetch(); - break; - case IR.Notwordboundary: - dchar back; - DataIndex bi; - //at start & end of input - if(atStart && wordTrie[front]) - { - recycle(t); - t = worklist.fetch(); - break; - } - else if(atEnd && s.loopBack(index).nextChar(back, bi) - && wordTrie[back]) - { - recycle(t); - t = worklist.fetch(); - break; - } - else if(s.loopBack(index).nextChar(back, bi)) - { - bool af = wordTrie[front]; - bool ab = wordTrie[back]; - if(af ^ ab) - { - recycle(t); - t = worklist.fetch(); - break; - } - } - t.pc--; - break; - case IR.Bol: - dchar back; - DataIndex bi; - if(atStart - ||((re.flags & RegexOption.multiline) - && s.loopBack(index).nextChar(back,bi) - && startOfLine(back, front == '\n'))) - { - t.pc--; - } - else - { - recycle(t); - t = worklist.fetch(); - } - break; - case IR.Eol: - debug(fred_matching) writefln("EOL (front 0x%x) %s", front, s[index..s.lastIndex]); - dchar back; - DataIndex bi; - //no matching inside \r\n - if((re.flags & RegexOption.multiline) - && endOfLine(front, s.loopBack(index).nextChar(back, bi) - && back == '\r')) - { - t.pc--; - } - else - { - recycle(t); - t = worklist.fetch(); - } - break; - case IR.InfiniteStart, IR.InfiniteQStart: - uint len = re.ir[t.pc].data; - uint mIdx = t.pc + len + IRL!(IR.InfiniteEnd); //we're always pointed at the tail of instruction - if(merge[re.ir[mIdx].raw+t.counter] < genCounter) - { - debug(fred_matching) writefln("A thread(pc=%s) passed there : %s ; GenCounter=%s mergetab=%s", - t.pc, index, genCounter, merge[re.ir[mIdx].raw+t.counter] ); - merge[re.ir[mIdx].raw+t.counter] = genCounter; - } - else - { - debug(fred_matching) writefln("A thread(pc=%s) got merged there : %s ; GenCounter=%s mergetab=%s", - t.pc, index, genCounter, merge[re.ir[mIdx].raw+t.counter] ); - recycle(t); - t = worklist.fetch(); - break; - } - if(re.ir[t.pc].code == IR.InfiniteStart)//greedy - { - worklist.insertFront(fork(t, t.pc-1, t.counter)); - t.pc += len; - } - else - { - worklist.insertFront(fork(t, t.pc+len, t.counter)); - t.pc--; - } - break; - case IR.InfiniteEnd: - case IR.InfiniteQEnd://now it's a start - uint len = re.ir[t.pc].data; - t.pc -= len+IRL!(IR.InfiniteStart); - assert(re.ir[t.pc].code == IR.InfiniteStart || re.ir[t.pc].code == IR.InfiniteQStart); - goto case IR.InfiniteStart; - case IR.RepeatStart, IR.RepeatQStart: - uint len = re.ir[t.pc].data; - uint tail = t.pc + len + IRL!(IR.RepeatStart); - uint step = re.ir[tail+2].raw; - uint min = re.ir[tail+3].raw; - - if(t.counter < min) - { - t.counter += step; - t.pc += len; - break; - } - uint max = re.ir[tail+4].raw; - if(merge[re.ir[tail+1].raw+t.counter] < genCounter) - { - debug(fred_matching) writefln("A thread(pc=%s) passed there : %s ; GenCounter=%s mergetab=%s", - t.pc, index, genCounter, merge[re.ir[tail+1].raw+t.counter] ); - merge[re.ir[tail+1].raw+t.counter] = genCounter; - } - else - { - debug(fred_matching) writefln("A thread(pc=%s) got merged there : %s ; GenCounter=%s mergetab=%s", - t.pc, index, genCounter, merge[re.ir[tail+1].raw+t.counter] ); - recycle(t); - t = worklist.fetch(); - break; - } - if(t.counter < max) - { - if(re.ir[t.pc].code == IR.RepeatStart)//greedy - { - worklist.insertFront(fork(t, t.pc-1, t.counter%step)); - t.counter += step; - t.pc += len; - } - else - { - worklist.insertFront(fork(t, t.pc + len, t.counter + step)); - t.counter = t.counter%step; - t.pc--; - } - } - else - { - t.counter = t.counter%step; - t.pc--; - } - break; - case IR.RepeatEnd: - case IR.RepeatQEnd: - t.pc -= re.ir[t.pc].data+IRL!(IR.RepeatStart); - assert(re.ir[t.pc].code == IR.RepeatStart || re.ir[t.pc].code == IR.RepeatQStart); - goto case IR.RepeatStart; - case IR.OrEnd: - uint len = re.ir[t.pc].data; - t.pc -= len; - assert(re.ir[t.pc].code == IR.Option); - len = re.ir[t.pc].data; - t.pc = t.pc + len; //to IR.GotoEndOr or just before IR.OrEnd - break; - case IR.OrStart: - uint len = re.ir[t.pc].data; - uint mIdx = t.pc + len + IRL!(IR.OrEnd); //should point to the end of OrEnd - if(merge[re.ir[mIdx].raw+t.counter] < genCounter) - { - debug(fred_matching) writefln("A thread(t.pc=%s) passed there : %s ; GenCounter=%s mergetab=%s", - t.pc, index, genCounter, merge[re.ir[mIdx].raw+t.counter] ); - merge[re.ir[mIdx].raw+t.counter] = genCounter; - } - else - { - debug(fred_matching) writefln("A thread(t.pc=%s) got merged there : %s ; GenCounter=%s mergetab=%s", - t.pc, index, genCounter, merge[re.ir[mIdx].raw+t.counter] ); - recycle(t); - t = worklist.fetch(); - break; - } - t.pc--; - break; - case IR.Option: - assert(re.ir[t.pc].code == IR.Option); - t.pc += re.ir[t.pc].data + IRL!(IR.Option); - if(re.ir[t.pc].code == IR.Option) - { - t.pc--;//hackish, assumes size of IR.Option == 1 - if(re.ir[t.pc].code == IR.GotoEndOr) - { - t.pc += re.ir[t.pc].data + IRL!(IR.GotoEndOr); - } - } - assert(re.ir[t.pc].code == IR.OrEnd); - t.pc -= re.ir[t.pc].data + 1; - break; - case IR.GotoEndOr: - assert(re.ir[t.pc].code == IR.GotoEndOr); - uint npc = t.pc+IRL!(IR.GotoEndOr); - assert(re.ir[npc].code == IR.Option); - worklist.insertFront(fork(t, npc + re.ir[npc].data, t.counter));//queue next branch - t.pc--; - break; - case IR.GroupStart: - uint n = re.ir[t.pc].data; - t.matches.ptr[n].begin = index; - t.pc--; - break; - case IR.GroupEnd: - uint n = re.ir[t.pc].data; - t.matches.ptr[n].end = index; - t.pc--; - break; - case IR.Backref: - uint n = re.ir[t.pc].data; - auto source = re.ir[t.pc].localRef ? t.matches.ptr : backrefed.ptr; - assert(source); - if(source[n].begin == source[n].end)//zero-width Backref! - { - t.pc--; - } - else static if(withInput) - { - size_t idx = source[n].begin + t.uopCounter; - size_t end = source[n].end; - if(s[idx..end].front == front)//could be a BUG in backward matching - { - t.uopCounter += std.utf.stride(s[idx..end], 0); - if(t.uopCounter + source[n].begin == source[n].end) - {//last codepoint - t.pc--; - t.uopCounter = 0; - } - nlist.insertBack(t); - } - else - recycle(t); - t = worklist.fetch(); - } - else - { - recycle(t); - t = worklist.fetch(); - } - break; - - case IR.LookbehindStart: - case IR.NeglookbehindStart: - uint ms = re.ir[t.pc+1].raw, me = re.ir[t.pc+2].raw; - finish(t, matches.ptr[ms .. me]); - recycle(t); - //cut off low priority threads - recycle(clist); - recycle(worklist); - return; - case IR.LookaheadStart: - case IR.NeglookaheadStart: - assert(0); - case IR.LookaheadEnd: - case IR.NeglookaheadEnd: - uint len = re.ir[t.pc].data; - t.pc -= len + IRL!(IR.LookaheadStart); - bool positive = re.ir[t.pc].code == IR.LookaheadStart; - auto matcher = ThompsonMatcher!(Char, typeof(s.loopBack(index))) - (this - , re.ir[t.pc .. t.pc+len+IRL!(IR.LookbehindStart)+IRL!(IR.LookbehindEnd)] - , s.loopBack(index)); - matcher.re.ngroup = re.ir[t.pc+2].raw - re.ir[t.pc+1].raw; - matcher.backrefed = backrefed.empty ? t.matches : backrefed; - matcher.next(); //fetch a char, since direction was reversed - bool match = (matcher.matchOneShot!(OneShot.Fwd)(t.matches, IRL!(IR.LookaheadStart)) == MatchResult.Match) ^ positive; - freelist = matcher.freelist; - if(match) - { - recycle(t); - t = worklist.fetch(); - } - else - t.pc--; - break; - case IR.LookbehindEnd: - case IR.NeglookbehindEnd: - auto save = index; - uint len = re.ir[t.pc].data; - t.pc -= len + IRL!(IR.LookbehindStart); - uint ms = re.ir[t.pc+1].raw, me = re.ir[t.pc+2].raw; - bool positive = re.ir[t.pc].code == IR.LookbehindStart; - auto matcher = ThompsonMatcher(this, re.ir[t.pc .. t.pc+len+IRL!(IR.LookbehindStart)], s); - matcher.front = front; - matcher.index = index; - matcher.re.ngroup = me - ms; - matcher.backrefed = backrefed.empty ? t.matches : backrefed; - bool nomatch = (matcher.matchOneShot!(OneShot.Bwd)(t.matches) == MatchResult.Match) ^ positive; - freelist = matcher.freelist; - s.reset(index); - next(); - if(nomatch) - { - recycle(t); - t = worklist.fetch(); - if(!t) - return; - // - } - else - t.pc--; - break; - case IR.Nop: - t.pc--; - break; - static if(withInput) - { - case IR.OrChar://assumes IRL!(OrChar) == 1 - uint len = re.ir[t.pc].sequence; - uint end = t.pc - len; - for(; t.pc > end; t.pc--) - if(re.ir[t.pc].data == front) - break; - if(t.pc != end) - { - t.pc = end; - nlist.insertBack(t); - } - else - recycle(t); - t = worklist.fetch(); - break; - case IR.Char: - if(front == re.ir[t.pc].data) - { - t.pc--; - nlist.insertBack(t); - } - else - recycle(t); - t = worklist.fetch(); - break; - case IR.Any: - t.pc--; - if(!(re.flags & RegexOption.singleline) - && (front == '\r' || front == '\n')) - recycle(t); - else - nlist.insertBack(t); - t = worklist.fetch(); - break; - case IR.CodepointSet: - if(re.charsets[re.ir[t.pc].data].scanFor(front)) - { - t.pc--; - nlist.insertBack(t); - } - else - { - recycle(t); - } - t = worklist.fetch(); - break; - case IR.Trie: - if(re.tries[re.ir[t.pc].data][front]) - { - t.pc--; - nlist.insertBack(t); - } - else - { - recycle(t); - } - t = worklist.fetch(); - break; - default: - assert(re.ir[t.pc].code < 0x80, "Unrecognized instruction " ~ re.ir[t.pc].mnemonic); - t.pc--; - } - else - { - default: - if(re.ir[t.pc].code < 0x80) - t.pc--; - else - { - recycle(t); - t = worklist.fetch(); - } - } - } - }while(t); - } - //get a dirty recycled Thread Thread!DataIndex* allocate() { @@ -5933,7 +5426,7 @@ enum OneShot { Fwd, Bwd }; void prepareFreeList(size_t size, ref void[] memory) { void[] mem = memory[0 .. threadSize*size]; - memory = memory[threadSize*size..$]; + memory = memory[threadSize * size .. $]; freelist = cast(Thread!DataIndex*)&mem[0]; size_t i; for(i = threadSize; i < threadSize*size; i += threadSize) @@ -6018,8 +5511,8 @@ enum OneShot { Fwd, Bwd }; @trusted public struct Captures(R, DIndex = size_t) if(isSomeString!R) {//@trusted because of union inside - alias DIndex DataIndex; - alias R String; + alias DataIndex = DIndex; + alias String = R; private: R _input; bool _empty; @@ -6029,29 +5522,39 @@ private: Group!DataIndex[] big_matches; Group!DataIndex[smallString] small_matches; } - uint f, b; - uint ngroup; - NamedGroup[] names; + uint _f, _b; + uint _ngroup; + NamedGroup[] _names; + + this()(R input, uint ngroups, NamedGroup[] named) + { + _input = input; + _ngroup = ngroups; + _names = named; + newMatches(); + _b = _ngroup; + _f = 0; + } this(alias Engine)(ref RegexMatch!(R,Engine) rmatch) { _input = rmatch._input; - ngroup = rmatch._engine.re.ngroup; - names = rmatch._engine.re.dict; + _ngroup = rmatch._engine.re.ngroup; + _names = rmatch._engine.re.dict; newMatches(); - b = ngroup; - f = 0; + _b = _ngroup; + _f = 0; } @property Group!DataIndex[] matches() { - return ngroup > smallString ? big_matches : small_matches[0..ngroup]; + return _ngroup > smallString ? big_matches : small_matches[0 .. _ngroup]; } void newMatches() { - if(ngroup > smallString) - big_matches = new Group!DataIndex[ngroup]; + if(_ngroup > smallString) + big_matches = new Group!DataIndex[_ngroup]; } public: @@ -6078,41 +5581,55 @@ public: @property R front() { assert(!empty); - return _input[matches[f].begin .. matches[f].end]; + return _input[matches[_f].begin .. matches[_f].end]; } ///ditto @property R back() { assert(!empty); - return _input[matches[b-1].begin .. matches[b-1].end]; + return _input[matches[_b - 1].begin .. matches[_b - 1].end]; } ///ditto void popFront() { assert(!empty); - ++f; + ++_f; } ///ditto void popBack() { assert(!empty); - --b; + --_b; } ///ditto - @property bool empty() const { return _empty || f >= b; } + @property bool empty() const { return _empty || _f >= _b; } ///ditto R opIndex()(size_t i) /*const*/ //@@@BUG@@@ { - assert(f+i < b,text("requested submatch number ", i," is out of range")); - assert(matches[f+i].begin <= matches[f+i].end, text("wrong match: ", matches[f+i].begin, "..", matches[f+i].end)); - return _input[matches[f+i].begin..matches[f+i].end]; + assert(_f + i < _b,text("requested submatch number ", i," is out of range")); + assert(matches[_f + i].begin <= matches[_f + i].end, + text("wrong match: ", matches[_f + i].begin, "..", matches[_f + i].end)); + return _input[matches[_f + i].begin .. matches[_f + i].end]; } + /++ + Explicit cast to bool. + Useful as a shorthand for !(x.empty) in if and assert statements. + + --- + import std.regex; + + assert(!matchFirst("nothing", "something")); + --- + +/ + + @safe @property bool opCast(T:bool)() const nothrow { return !empty; } + /++ Lookup named submatch. @@ -6133,12 +5650,12 @@ public: R opIndex(String)(String i) /*const*/ //@@@BUG@@@ if(isSomeString!String) { - size_t index = lookupNamedGroup(names, i); - return _input[matches[index].begin..matches[index].end]; + size_t index = lookupNamedGroup(_names, i); + return _input[matches[index].begin .. matches[index].end]; } ///Number of matches in this object. - @property size_t length() const { return _empty ? 0 : b-f; } + @property size_t length() const { return _empty ? 0 : _b - _f; } ///A hook for compatibility with original std.regex. @property ref captures(){ return this; } @@ -6160,6 +5677,8 @@ unittest//verify example assert(c.back == "b"); popFrontN(c, 2); assert(c.empty); + + assert(!matchFirst("nothing", "something")); } /++ @@ -6168,21 +5687,21 @@ unittest//verify example Effectively it's a forward range of Captures!R, produced by lazily searching for matches in a given input. - alias Engine specifies an engine type to use during matching, + $(D alias Engine) specifies an engine type to use during matching, and is automatically deduced in a call to $(D match)/$(D bmatch). +/ @trusted public struct RegexMatch(R, alias Engine = ThompsonMatcher) if(isSomeString!R) { private: - alias BasicElementOf!R Char; - alias Engine!Char EngineType; + alias Char = BasicElementOf!R; + alias EngineType = Engine!Char; EngineType _engine; R _input; Captures!(R,EngineType.DataIndex) _captures; void[] _memory;//is ref-counted - this(RegEx)(RegEx prog, R input) + this(RegEx)(R input, RegEx prog) { _input = input; immutable size = EngineType.initialMemory(prog)+size_t.sizeof; @@ -6190,9 +5709,11 @@ private: scope(failure) free(_memory.ptr); *cast(size_t*)_memory.ptr = 1; _engine = EngineType(prog, Input!Char(input), _memory[size_t.sizeof..$]); + static if(is(RegEx == StaticRegex!(BasicElementOf!R))) + _engine.nativeFn = prog.nativeFn; _captures = Captures!(R,EngineType.DataIndex)(this); _captures._empty = !_engine.match(_captures.matches); - debug(fred_allocation) writefln("RefCount (ctor): %x %d", _memory.ptr, counter); + debug(std_regex_allocation) writefln("RefCount (ctor): %x %d", _memory.ptr, counter); } @property ref size_t counter(){ return *cast(size_t*)_memory.ptr; } @@ -6202,8 +5723,8 @@ public: if(_memory.ptr) { ++counter; - debug(fred_allocation) writefln("RefCount (postblit): %x %d" - , _memory.ptr, *cast(size_t*)_memory.ptr); + debug(std_regex_allocation) writefln("RefCount (postblit): %x %d", + _memory.ptr, *cast(size_t*)_memory.ptr); } } @@ -6211,8 +5732,8 @@ public: { if(_memory.ptr && --*cast(size_t*)_memory.ptr == 0) { - debug(fred_allocation) writefln("RefCount (dtor): %x %d" - , _memory.ptr, *cast(size_t*)_memory.ptr); + debug(std_regex_allocation) writefln("RefCount (dtor): %x %d", + _memory.ptr, *cast(size_t*)_memory.ptr); free(cast(void*)_memory.ptr); } } @@ -6283,6 +5804,35 @@ public: } +private @trusted auto matchOnce(alias Engine, RegEx, R)(R input, RegEx re) +{ + alias Char = BasicElementOf!R; + alias EngineType = Engine!Char; + + size_t size = EngineType.initialMemory(re); + void[] memory = enforce(malloc(size))[0..size]; + scope(exit) free(memory.ptr); + auto captures = Captures!(R, EngineType.DataIndex)(input, re.ngroup, re.dict); + auto engine = EngineType(re, Input!Char(input), memory); + static if(is(RegEx == StaticRegex!(BasicElementOf!R))) + engine.nativeFn = re.nativeFn; + captures._empty = !engine.match(captures.matches); + return captures; +} + +private auto matchMany(alias Engine, RegEx, R)(R input, RegEx re) +{ + re.flags |= RegexOption.global; + return RegexMatch!(R, Engine)(input, re); +} + +unittest +{ + //sanity checks for new API + auto re = regex("abc"); + assert(!"abc".matchOnce!(ThompsonMatcher)(re).empty); + assert("abc".matchOnce!(ThompsonMatcher)(re)[0] == "abc"); +} /++ Compile regular expression pattern for the later execution. Returns: $(D Regex) object that works on inputs having @@ -6306,39 +5856,27 @@ public: public auto regexImpl(S)(S pattern, const(char)[] flags="") if(isSomeString!(S)) { - alias Regex!(BasicElementOf!S) Reg; - if(!__ctfe) - { - auto parser = Parser!(Unqual!(typeof(pattern)))(pattern, flags); - Regex!(BasicElementOf!S) r = parser.program; - return r; - } - else - { - auto parser = Parser!(Unqual!(typeof(pattern)), true)(pattern, flags); - Regex!(BasicElementOf!S) r = parser.program; - return r; - } + auto parser = Parser!(Unqual!(typeof(pattern)))(pattern, flags); + auto r = parser.program; + return r; } template ctRegexImpl(alias pattern, string flags=[]) { enum r = regex(pattern, flags); - alias BasicElementOf!(typeof(pattern)) Char; + alias Char = BasicElementOf!(typeof(pattern)); enum source = ctGenRegExCode(r); - alias BacktrackingMatcher!(true) Matcher; + alias Matcher = BacktrackingMatcher!(true); @trusted bool func(ref Matcher!Char matcher) { - version(fred_ct) debug pragma(msg, source); + debug(std_regex_ctr) pragma(msg, source); mixin(source); } enum nr = StaticRegex!Char(r, &func); } /++ - Experimental feature. - Compile regular expression using CTFE and generate optimized native machine code for matching it. @@ -6348,66 +5886,174 @@ template ctRegexImpl(alias pattern, string flags=[]) pattern = Regular expression flags = The _attributes (g, i, m and x accepted) +/ -public template ctRegex(alias pattern, alias flags=[]) -{ - enum ctRegex = ctRegexImpl!(pattern, flags).nr; -} +public enum ctRegex(alias pattern, alias flags=[]) = ctRegexImpl!(pattern, flags).nr; -template isRegexFor(RegEx, R) -{ - enum isRegexFor = is(RegEx == Regex!(BasicElementOf!R)) - || is(RegEx == StaticRegex!(BasicElementOf!R)); -} +enum isRegexFor(RegEx, R) = is(RegEx == Regex!(BasicElementOf!R)) + || is(RegEx == StaticRegex!(BasicElementOf!R)); /++ Start matching $(D input) to regex pattern $(D re), using Thompson NFA matching scheme. - This is the $(U recommended) method for matching regular expression. + The use of this function is $(RED discouraged) - use either of + $(LREF matchAll) or $(LREF matchFirst). - $(D re) parameter can be one of three types: - $(UL - $(LI Plain string, in which case it's compiled to bytecode before matching. ) - $(LI Regex!char (wchar/dchar) that contains pattern in form of - precompiled bytecode. ) - $(LI StaticRegex!char (wchar/dchar) that contains pattern in form of - specially crafted native code. ) - ) + Delegating the kind of operation + to "g" flag is soon to be phased out along with the + ability to choose the exact matching scheme. The choice of + matching scheme to use depends highly on the pattern kind and + can done automatically on case by case basis. + Returns: a $(D RegexMatch) object holding engine state after first match. +/ public auto match(R, RegEx)(R input, RegEx re) if(isSomeString!R && is(RegEx == Regex!(BasicElementOf!R))) { - return RegexMatch!(Unqual!(typeof(input)),ThompsonMatcher)(re, input); + return RegexMatch!(Unqual!(typeof(input)),ThompsonMatcher)(input, re); } ///ditto public auto match(R, String)(R input, String re) if(isSomeString!R && isSomeString!String) { - return RegexMatch!(Unqual!(typeof(input)),ThompsonMatcher)(regex(re), input); + return RegexMatch!(Unqual!(typeof(input)),ThompsonMatcher)(input, regex(re)); } public auto match(R, RegEx)(R input, RegEx re) if(isSomeString!R && is(RegEx == StaticRegex!(BasicElementOf!R))) { - return RegexMatch!(Unqual!(typeof(input)),BacktrackingMatcher!true)(re, input); + return RegexMatch!(Unqual!(typeof(input)),BacktrackingMatcher!true)(input, re); } /++ - Start matching $(D input) to regex pattern $(D re), - using traditional $(LUCKY backtracking) matching scheme. + Find the first (leftmost) slice of the $(D input) that + matches the pattern $(D re). This function picks the most suitable + regular expression engine depending on the pattern properties. $(D re) parameter can be one of three types: $(UL $(LI Plain string, in which case it's compiled to bytecode before matching. ) - $(LI Regex!char (wchar/dchar) that contains pattern in form of - precompiled bytecode. ) - $(LI StaticRegex!char (wchar/dchar) that contains pattern in form of - specially crafted native code. ) + $(LI Regex!char (wchar/dchar) that contains a pattern in the form of + compiled bytecode. ) + $(LI StaticRegex!char (wchar/dchar) that contains a pattern in the form of + compiled native machine code. ) ) + Returns: + $(LREF Captures) containing the extent of a match together with all submatches + if there was a match, otherwise an empty $(LREF Captures) object. ++/ +public auto matchFirst(R, RegEx)(R input, RegEx re) + if(isSomeString!R && is(RegEx == Regex!(BasicElementOf!R))) +{ + return matchOnce!ThompsonMatcher(input, re); +} + +///ditto +public auto matchFirst(R, String)(R input, String re) + if(isSomeString!R && isSomeString!String) +{ + return matchOnce!ThompsonMatcher(input, regex(re)); +} + +public auto matchFirst(R, RegEx)(R input, RegEx re) + if(isSomeString!R && is(RegEx == StaticRegex!(BasicElementOf!R))) +{ + return matchOnce!(BacktrackingMatcher!true)(input, re); +} + +/++ + Initiate a search for all non-overlapping matches to the pattern $(D re) + in the given $(D input). The result is a lazy range of matches generated + as they are encountered in the input going left to right. + + This function picks the most suitable regular expression engine + depending on the pattern properties. + + $(D re) parameter can be one of three types: + $(UL + $(LI Plain string, in which case it's compiled to bytecode before matching. ) + $(LI Regex!char (wchar/dchar) that contains a pattern in the form of + compiled bytecode. ) + $(LI StaticRegex!char (wchar/dchar) that contains a pattern in the form of + compiled native machine code. ) + ) + + Returns: + $(LREF RegexMatch) object that represents matcher state + after the first match was found or an empty one if not present. ++/ +public auto matchAll(R, RegEx)(R input, RegEx re) + if(isSomeString!R && is(RegEx == Regex!(BasicElementOf!R))) +{ + return matchMany!ThompsonMatcher(input, re); +} + +///ditto +public auto matchAll(R, String)(R input, String re) + if(isSomeString!R && isSomeString!String) +{ + return matchMany!ThompsonMatcher(input, regex(re)); +} + +public auto matchAll(R, RegEx)(R input, RegEx re) + if(isSomeString!R && is(RegEx == StaticRegex!(BasicElementOf!R))) +{ + return matchMany!(BacktrackingMatcher!true)(input, re); +} + +// another set of tests just to cover the new API +@system unittest +{ + foreach(String; TypeTuple!(string, wstring, const(dchar)[])) + { + auto str1 = "blah-bleh".to!String(); + auto pat1 = "bl[ae]h".to!String(); + auto mf = matchFirst(str1, pat1); + assert(mf.equal(["blah".to!String()])); + auto mAll = matchAll(str1, pat1); + assert(mAll.equal!((a,b) => a.equal(b)) + ([["blah".to!String()], ["bleh".to!String()]])); + + auto str2 = "1/03/12 - 3/03/12".to!String(); + auto pat2 = regex(r"(\d+)/(\d+)/(\d+)".to!String()); + auto mf2 = matchFirst(str2, pat2); + assert(mf2.equal(["1/03/12", "1", "03", "12"].map!(to!String)())); + auto mAll2 = matchAll(str2, pat2); + assert(mAll2.front.equal(mf2)); + mAll2.popFront(); + assert(mAll2.front.equal(["3/03/12", "3", "03", "12"].map!(to!String)())); + mf2.popFrontN(3); + assert(mf2.equal(["12".to!String()])); + + auto ctPat = ctRegex!(`(?P\d+)/(?P\d+)`.to!String()); + auto str = "2 + 34/56 - 6/1".to!String(); + auto cmf = matchFirst(str, ctPat); + assert(cmf.equal(["34/56", "34", "56"].map!(to!String)())); + assert(cmf["Quot"] == "34".to!String()); + assert(cmf["Denom"] == "56".to!String()); + + auto cmAll = matchAll(str, ctPat); + assert(cmAll.front.equal(cmf)); + cmAll.popFront(); + assert(cmAll.front.equal(["6/1", "6", "1"].map!(to!String)())); + } +} + +/++ + Start matching of $(D input) to regex pattern $(D re), + using traditional $(LUCKY backtracking) matching scheme. + + The use of this function is $(RED discouraged) - use either of + $(LREF matchAll) or $(LREF matchFirst). + + Delegating the kind of operation + to "g" flag is soon to be phased out along with the + ability to choose the exact matching scheme. The choice of + matching scheme to use depends highly on the pattern kind and + can done automatically on case by case basis. + Returns: a $(D RegexMatch) object holding engine state after first match. @@ -6415,83 +6061,245 @@ public auto match(R, RegEx)(R input, RegEx re) public auto bmatch(R, RegEx)(R input, RegEx re) if(isSomeString!R && is(RegEx == Regex!(BasicElementOf!R))) { - return RegexMatch!(Unqual!(typeof(input)), BacktrackingMatcher!false)(re, input); + return RegexMatch!(Unqual!(typeof(input)), BacktrackingMatcher!false)(input, re); } ///ditto public auto bmatch(R, String)(R input, String re) if(isSomeString!R && isSomeString!String) { - return RegexMatch!(Unqual!(typeof(input)), BacktrackingMatcher!false)(regex(re), input); + return RegexMatch!(Unqual!(typeof(input)), BacktrackingMatcher!false)(input, regex(re)); } public auto bmatch(R, RegEx)(R input, RegEx re) if(isSomeString!R && is(RegEx == StaticRegex!(BasicElementOf!R))) { - return RegexMatch!(Unqual!(typeof(input)),BacktrackingMatcher!true)(re, input); + return RegexMatch!(Unqual!(typeof(input)),BacktrackingMatcher!true)(input, re); +} + + +enum isReplaceFunctor(alias fun, R) = + __traits(compiles, (Captures!R c) { fun(c); }); + +// the lowest level - just stuff replacements into the sink +private @trusted void replaceCapturesInto(alias output, Sink, R, T) + (ref Sink sink, R input, T captures) + if(isOutputRange!(Sink, dchar) && isSomeString!R) +{ + sink.put(captures.pre); + // a hack to get around bogus errors, should be simply output(captures, sink) + // "is a nested function and cannot be accessed from" + static if(isReplaceFunctor!(output, R)) + sink.put(output(captures)); //"mutator" type of function + else + output(captures, sink); //"output" type of function + sink.put(captures.post); +} + +// ditto for a range of captures +private void replaceMatchesInto(alias output, Sink, R, T) + (ref Sink sink, R input, T matches) + if(isOutputRange!(Sink, dchar) && isSomeString!R) +{ + size_t offset = 0; + foreach(cap; matches) + { + sink.put(cap.pre[offset .. $]); + // same hack, see replaceCapturesInto + static if(isReplaceFunctor!(output, R)) + sink.put(output(cap)); //"mutator" type of function + else + output(cap, sink); //"output" type of function + offset = cap.pre.length + cap.hit.length; + } + sink.put(input[offset .. $]); +} + +// a general skeleton of replaceFirst +private R replaceFirstWith(alias output, R, RegEx)(R input, RegEx re) + if(isSomeString!R && isRegexFor!(RegEx, R)) +{ + auto data = matchFirst(input, re); + if(data.empty) + return input; + auto app = appender!(R)(); + replaceCapturesInto!output(app, input, data); + return app.data; +} + +// ditto for replaceAll +// the method parameter allows old API to ride on the back of the new one +private R replaceAllWith(alias output, + alias method=matchAll, R, RegEx)(R input, RegEx re) + if(isSomeString!R && isRegexFor!(RegEx, R)) +{ + auto matches = method(input, re); //inout(C)[] fails + if(matches.empty) + return input; + auto app = appender!(R)(); + replaceMatchesInto!output(app, input, matches); + return app.data; } /++ - Construct a new string from $(D input) by replacing each match with - a string generated from match according to $(D format) specifier. + Construct a new string from $(D input) by replacing the first match with + a string generated from it according to the $(D format) specifier. - To replace all occurrences use regex with "g" flag, otherwise - only the first occurrence gets replaced. + To replace all matches use $(LREF replaceAll). Params: input = string to search re = compiled regular expression to use - format = format string to generate replacements from + format = format string to generate replacements from, + see $(S_LINK Replace format string, the format string). + + Returns: + A string of the same type with the first match (if any) replaced. + If no match is found returns the input string itself. + + Example: + --- + assert(replaceFirst("noon", regex("n"), "[$&]") == "[n]oon"); + --- ++/ +public R replaceFirst(R, C, RegEx)(R input, RegEx re, const(C)[] format) + if(isSomeString!R && is(C : dchar) && isRegexFor!(RegEx, R)) +{ + return replaceFirstWith!((m, sink) => replaceFmt(format, m, sink))(input, re); +} + +/++ + This is a general replacement tool that construct a new string by replacing + matches of pattern $(D re) in the $(D input). Unlike the other overload + there is no format string instead captures are passed to + to a user-defined functor $(D fun) that returns a new string + to use as replacement. + + This version replaces the first match in $(D input), + see $(LREF replaceAll) to replace the all of the matches. + + Returns: + A new string of the same type as $(D input) with all matches + replaced by return values of $(D fun). If no matches found + returns the $(D input) itself. + + Example: + --- + string list = "#21 out of 46"; + string newList = replaceFirst!(cap => to!string(to!int(cap.hit)+1)) + (list, regex(`[0-9]+`)); + assert(newList == "#22 out of 46"); + --- ++/ +public R replaceFirst(alias fun, R, RegEx)(R input, RegEx re) + if(isSomeString!R && isRegexFor!(RegEx, R)) +{ + return replaceFirstWith!((m, sink) => sink.put(fun(m)))(input, re); +} + +/++ + A variation on $(LREF replaceFirst) that instead of allocating a new string + on each call outputs the result piece-wise to the $(D sink). In particular + this enables efficient construction of a final output incrementally. + + Like in $(LREF replaceFirst) family of functions there is an overload + for the substitution guided by the $(D format) string + and the one with the user defined callback. + + Example: + --- + import std.array; + string m1 = "first message\n"; + string m2 = "second message\n"; + auto result = appender!string(); + replaceFirstInto(result, m1, regex(`([a-z]+) message`), "$1"); + //equivalent of the above with user-defined callback + replaceFirstInto!(cap=>cap[1])(result, m2, regex(`([a-z]+) message`)); + assert(result.data == "first\nsecond\n"); + --- ++/ +public @trusted void replaceFirstInto(Sink, R, C, RegEx) + (ref Sink sink, R input, RegEx re, const(C)[] format) + if(isOutputRange!(Sink, dchar) && isSomeString!R + && is(C : dchar) && isRegexFor!(RegEx, R)) + { + replaceCapturesInto!((m, sink) => replaceFmt(format, m, sink)) + (sink, input, matchFirst(input, re)); + } + +///ditto +public @trusted void replaceFirstInto(alias fun, Sink, R, RegEx) + (Sink sink, R input, RegEx re) + if(isOutputRange!(Sink, dchar) && isSomeString!R && isRegexFor!(RegEx, R)) +{ + replaceCapturesInto!fun(sink, input, matchFirst(input, re)); +} + +//examples for replaceFirst +@system unittest +{ + string list = "#21 out of 46"; + string newList = replaceFirst!(cap => to!string(to!int(cap.hit)+1)) + (list, regex(`[0-9]+`)); + assert(newList == "#22 out of 46"); + import std.array; + string m1 = "first message\n"; + string m2 = "second message\n"; + auto result = appender!string(); + replaceFirstInto(result, m1, regex(`([a-z]+) message`), "$1"); + //equivalent of the above with user-defined callback + replaceFirstInto!(cap=>cap[1])(result, m2, regex(`([a-z]+) message`)); + assert(result.data == "first\nsecond\n"); +} + +/++ + Construct a new string from $(D input) by replacing all of the + fragments that match a pattern $(D re) with a string generated + from the match according to the $(D format) specifier. + + To replace only the first match use $(LREF replaceFirst). + + Params: + input = string to search + re = compiled regular expression to use + format = format string to generate replacements from, + see $(S_LINK Replace format string, the format string). + + Returns: + A string of the same type as $(D input) with the all + of the matches (if any) replaced. + If no match is found returns the input string itself. Example: --- // Comify a number auto com = regex(r"(?<=\d)(?=(\d\d\d)+\b)","g"); - assert(replace("12000 + 42100 = 54100", com, ",") == "12,000 + 42,100 = 54,100"); - --- - - The format string can reference parts of match using the following notation. - $(REG_TABLE - $(REG_TITLE Format specifier, Replaced by ) - $(REG_ROW $&, the whole match. ) - $(REG_ROW $`, part of input $(I preceding) the match. ) - $(REG_ROW $', part of input $(I following) the match. ) - $(REG_ROW $$, '$' character. ) - $(REG_ROW \c , where c is any character, the character c itself. ) - $(REG_ROW \\, '\' character. ) - $(REG_ROW $1 .. $99, submatch number 1 to 99 respectively. ) - ) - --- - assert(replace("noon", regex("^n"), "[$&]") == "[n]oon"); + assert(replaceAll("12000 + 42100 = 54100", com, ",") == "12,000 + 42,100 = 54,100"); --- +/ -public @trusted R replace(alias scheme = match, R, RegEx)(R input, RegEx re, R format) - if(isSomeString!R && isRegexFor!(RegEx, R)) +public @trusted R replaceAll(R, C, RegEx)(R input, RegEx re, const(C)[] format) + if(isSomeString!R && is(C : dchar) && isRegexFor!(RegEx, R)) { - auto app = appender!(R)(); - auto matches = scheme(input, re); - size_t offset = 0; - foreach(ref m; matches) - { - app.put(m.pre[offset .. $]); - replaceFmt(format, m.captures, app); - offset = m.pre.length + m.hit.length; - } - app.put(input[offset .. $]); - return app.data; + return replaceAllWith!((m, sink) => replaceFmt(format, m, sink))(input, re); } /++ - Search string for matches using regular expression pattern $(D re) - and pass captures for each match to user-defined functor $(D fun). + This is a general replacement tool that construct a new string by replacing + matches of pattern $(D re) in the $(D input). Unlike the other overload + there is no format string instead captures are passed to + to a user-defined functor $(D fun) that returns a new string + to use as replacement. - To replace all occurrances use regex with "g" flag, otherwise - only first occurrence gets replaced. + This version replaces all of the matches found in $(D input), + see $(LREF replaceFirst) to replace the first match only. - Returns: new string with all matches replaced by return values of $(D fun). + Returns: + A new string of the same type as $(D input) with all matches + replaced by return values of $(D fun). If no matches found + returns the $(D input) itself. Params: - s = string to search + input = string to search re = compiled regular expression fun = delegate to use @@ -6502,29 +6310,131 @@ public @trusted R replace(alias scheme = match, R, RegEx)(R input, RegEx re, R f { return std.string.toUpper(m.hit); } - auto s = replace!(baz)("Strap a rocket engine on a chicken.", - regex("[ar]", "g")); + auto s = replaceAll!(baz)("Strap a rocket engine on a chicken.", + regex("[ar]")); assert(s == "StRAp A Rocket engine on A chicken."); --- +/ -public @trusted R replace(alias fun, R, RegEx, alias scheme = match)(R input, RegEx re) +public @trusted R replaceAll(alias fun, R, RegEx)(R input, RegEx re) if(isSomeString!R && isRegexFor!(RegEx, R)) { - auto app = appender!(R)(); - auto matches = scheme(input, re); - size_t offset = 0; - foreach(m; matches) - { - app.put(m.pre[offset .. $]); - app.put(fun(m)); - offset = m.pre.length + m.hit.length; - } - app.put(input[offset .. $]); - return app.data; + return replaceAllWith!((m, sink) => sink.put(fun(m)))(input, re); } -//produce replacement string from format using captures for substitue -public @trusted void replaceFmt(R, Capt, OutR) +/++ + A variation on $(LREF replaceAll) that instead of allocating a new string + on each call outputs the result piece-wise to the $(D sink). In particular + this enables efficient construction of a final output incrementally. + + As with $(LREF replaceAll) there are 2 overloads - one with a format string, + the other one with a user defined functor. + + Example: + --- + //swap all 3 letter words and bring it back + string text = "How are you doing?"; + auto sink = appender!(char[])(); + replaceAllInto!(cap => retro(cap[0]))(sink, text, regex(`\b\w{3}\b`)); + auto swapped = sink.data.dup; // make a copy explicitly + assert(swapped == "woH era uoy doing?"); + sink.clear(); + replaceAllInto!(cap => retro(cap[0]))(sink, swapped, regex(`\b\w{3}\b`)); + assert(sink.data == text); + --- ++/ +public @trusted void replaceAllInto(Sink, R, C, RegEx) + (Sink sink, R input, RegEx re, const(C)[] format) + if(isOutputRange!(Sink, dchar) && isSomeString!R + && is(C : dchar) && isRegexFor!(RegEx, R)) + { + replaceMatchesInto!((m, sink) => replaceFmt(format, m, sink)) + (sink, input, matchAll(input, re)); + } + +///ditto +public @trusted void replaceAllInto(alias fun, Sink, R, RegEx) + (Sink sink, R input, RegEx re) + if(isOutputRange!(Sink, dchar) && isSomeString!R && isRegexFor!(RegEx, R)) +{ + replaceMatchesInto!fun(sink, input, matchAll(input, re)); +} + +// a bit of examples +@system unittest +{ + //swap all 3 letter words and bring it back + string text = "How are you doing?"; + auto sink = appender!(char[])(); + replaceAllInto!(cap => retro(cap[0]))(sink, text, regex(`\b\w{3}\b`)); + auto swapped = sink.data.dup; // make a copy explicitly + assert(swapped == "woH era uoy doing?"); + sink.clear(); + replaceAllInto!(cap => retro(cap[0]))(sink, swapped, regex(`\b\w{3}\b`)); + assert(sink.data == text); +} + +// exercise all of the replace APIs +@system unittest +{ + // try and check first/all simple substitution + foreach(S; TypeTuple!(string, wstring, dstring, char[], wchar[], dchar[])) + { + S s1 = "curt trial".to!S(); + S s2 = "round dome".to!S(); + S t1F = "court trial".to!S(); + S t2F = "hound dome".to!S(); + S t1A = "court trial".to!S(); + S t2A = "hound home".to!S(); + auto re1 = regex("curt".to!S()); + auto re2 = regex("[dr]o".to!S()); + + assert(replaceFirst(s1, re1, "court") == t1F); + assert(replaceFirst(s2, re2, "ho") == t2F); + assert(replaceAll(s1, re1, "court") == t1A); + assert(replaceAll(s2, re2, "ho") == t2A); + + auto rep1 = replaceFirst!(cap => cap[0][0]~"o".to!S()~cap[0][1..$])(s1, re1); + assert(rep1 == t1F); + assert(replaceFirst!(cap => "ho".to!S())(s2, re2) == t2F); + auto rep1A = replaceAll!(cap => cap[0][0]~"o".to!S()~cap[0][1..$])(s1, re1); + assert(rep1A == t1A); + assert(replaceAll!(cap => "ho".to!S())(s2, re2) == t2A); + + auto sink = appender!S(); + replaceFirstInto(sink, s1, re1, "court"); + assert(sink.data == t1F); + replaceFirstInto(sink, s2, re2, "ho"); + assert(sink.data == t1F~t2F); + replaceAllInto(sink, s1, re1, "court"); + assert(sink.data == t1F~t2F~t1A); + replaceAllInto(sink, s2, re2, "ho"); + assert(sink.data == t1F~t2F~t1A~t2A); + } +} + +/++ + Old API for replacement, operation depends on flags of pattern $(D re). + With "g" flag it performs the equivalent of $(LREF replaceAll) otherwise it + works the same as $(LREF replaceFirst). + + The use of this function is $(RED discouraged), please use $(LREF replaceAll) + or $(LREF replaceFirst) explicitly. ++/ +public R replace(alias scheme = match, R, C, RegEx)(R input, RegEx re, const(C)[] format) + if(isSomeString!R && isRegexFor!(RegEx, R)) +{ + return replaceAllWith!((m, sink) => replaceFmt(format, m, sink), match)(input, re); +} + +///ditto +public R replace(alias fun, R, RegEx)(R input, RegEx re) + if(isSomeString!R && isRegexFor!(RegEx, R)) +{ + return replaceAllWith!(fun, match)(input, re); +} + +//produce replacement string from format using captures for substitution +private void replaceFmt(R, Capt, OutR) (R format, Capt captures, OutR sink, bool ignoreBadSubs = false) if(isOutputRange!(OutR, ElementEncodingType!R[]) && isOutputRange!(OutR, ElementEncodingType!(Capt.String)[])) @@ -6560,7 +6470,7 @@ L_Replace_Loop: } else if(format[0] == '{') { - auto x = find!"!std.ascii.isAlpha(a)"(format[1..$]); + auto x = find!(a => !ascii.isAlpha(a))(format[1..$]); enforce(!x.empty && x[0] == '}', "no matching '}' in replacement format"); auto name = format[1 .. $ - x.length]; format = x[1..$]; @@ -6610,7 +6520,7 @@ public struct Splitter(Range, alias RegEx = Regex) private: Range _input; size_t _offset; - alias typeof(match(Range.init,RegEx.init)) Rx; + alias Rx = typeof(match(Range.init,RegEx.init)); Rx _match; @trusted this(Range input, RegEx separator) @@ -6624,7 +6534,7 @@ private: } else { - _match = Rx(separator, _input); + _match = Rx(_input, separator); } } @@ -7040,7 +6950,7 @@ unittest int i; foreach(Char; TypeTuple!( char, wchar, dchar)) { - alias immutable(Char)[] String; + alias String = immutable(Char)[]; String produceExpected(M,Range)(auto ref M m, Range fmt) { auto app = appender!(String)(); @@ -7051,7 +6961,7 @@ unittest foreach(a, tvd; tv) { uint c = tvd.result[0]; - debug(fred_test) writeln(" Test #", a, " pattern: ", tvd.pattern, " with Char = ", Char.stringof); + debug(std_regex_test) writeln(" Test #", a, " pattern: ", tvd.pattern, " with Char = ", Char.stringof); try { i = 1; @@ -7060,7 +6970,7 @@ unittest catch (RegexException e) { i = 0; - debug(fred_test) writeln(e.msg); + debug(std_regex_test) writeln(e.msg); } assert((c == 'c') ? !i : i, "failed to compile pattern "~tvd.pattern); @@ -7073,442 +6983,480 @@ unittest if(c == 'y') { auto result = produceExpected(m, to!(String)(tvd.format)); - assert(result == to!String(tvd.replace), text(matchFn.stringof ~": mismatch pattern #", a, ": ", tvd.pattern," expected: ", + assert(result == to!String(tvd.replace), + text(matchFn.stringof ~": mismatch pattern #", a, ": ", tvd.pattern," expected: ", tvd.replace, " vs ", result)); } } } } - debug(fred_test) writeln("!!! FReD bulk test done "~matchFn.stringof~" !!!"); + debug(std_regex_test) writeln("!!! FReD bulk test done "~matchFn.stringof~" !!!"); } - static string generate(uint n,uint[] black_list...) - { - string s = "TypeTuple!("; - for(uint i = 0; i < n; i++) - { - uint j; - for(j =0; j < black_list.length; j++) - if(i == black_list[j]) - break; - if(j == black_list.length) - { - s ~= to!string(i); - s ~= ","; - } - } - s ~= ")"; - return s; - } - //CTFE parsing - version(fred_ct) + + void ct_tests() { - foreach(a, v; mixin(generate(140,38,39,40,52,55,57,62,63,67,80,190,191,192))) + version(std_regex_ct1) + { + pragma(msg, "Testing 1st part of ctRegex"); + alias Tests = Sequence!(0, 90); + } + else version(std_regex_ct2) + { + pragma(msg, "Testing 2nd part of ctRegex"); + alias Tests = Sequence!(90, 165); + } + else version(std_regex_ct3) + { + pragma(msg, "Testing 3rd part of ctRegex"); + alias Tests = Sequence!(185, 220); + } + else version(std_regex_ct4) + { + pragma(msg, "Testing 4th part of ctRegex"); + alias Tests = Sequence!(220, tv.length); + } + else + alias Tests = TypeTuple!(Sequence!(0, 30), Sequence!(235, tv.length-5)); + foreach(a, v; Tests) { enum tvd = tv[v]; - enum r = regex(tvd.pattern, tvd.flags); - auto nr = regex(tvd.pattern, tvd.flags); - - debug(fred_test) + static if(tvd.result == "c") { - writeln(" Test #", a, " pattern: ", tvd.pattern); - if(!equal(r.ir, nr.ir)) - { - writeln("C-T version :"); - r.print(); - writeln("R-T version :"); - nr.print(); - assert(0, text("!C-T regex! failed to compile pattern #", a ,": ", tvd.pattern)); - } + static assert(!__traits(compiles, (){ + enum r = regex(tvd.pattern, tvd.flags); + }), "errornously compiles regex pattern: " ~ tvd.pattern); } else - assert(equal(r.ir, nr.ir), text("!C-T regex! failed to compile pattern #", a ,": ", tvd.pattern)); - - } - debug(fred_test) writeln("!!! FReD C-T test done !!!"); - } - - version(fred_ct) - ct_tests(); - else - { - run_tests!bmatch(); //backtracker - run_tests!match(); //thompson VM - } -} - -version(fred_ct) -{ - unittest - { - auto cr = ctRegex!("abc"); - assert(bmatch("abc",cr).hit == "abc"); - auto cr2 = ctRegex!("ab*c"); - assert(bmatch("abbbbc",cr2).hit == "abbbbc"); - auto cr3 = ctRegex!("^abc$"); - assert(bmatch("abc",cr3).hit == "abc"); - auto cr4 = ctRegex!(`\b(a\B[a-z]b)\b`); - assert(array(match("azb",cr4).captures) == ["azb", "azb"]); - auto cr5 = ctRegex!("(?:a{2,4}b{1,3}){1,2}"); - assert(bmatch("aaabaaaabbb", cr5).hit == "aaabaaaabbb"); - auto cr6 = ctRegex!("(?:a{2,4}b{1,3}){1,2}?"w); - assert(bmatch("aaabaaaabbb"w, cr6).hit == "aaab"w); - auto cr7 = ctRegex!(`\r.*?$`,"m"); - assert(bmatch("abc\r\nxy", cr7).hit == "\r\nxy"); - auto greed = ctRegex!(""); - assert(bmatch("texttext", greed).hit - == "text"); - auto cr8 = ctRegex!("^(a)(b)?(c*)"); - auto m8 = bmatch("abcc",cr8); - assert(m8); - assert(m8.captures[1] == "a"); - assert(m8.captures[2] == "b"); - assert(m8.captures[3] == "cc"); - auto cr9 = ctRegex!("q(a|b)*q"); - auto m9 = match("xxqababqyy",cr9); - assert(m9); - assert(equal(bmatch("xxqababqyy",cr9).captures, ["qababq", "b"])); - - auto rtr = regex("a|b|c"); - enum ctr = regex("a|b|c"); - assert(equal(rtr.ir,ctr.ir)); - //CTFE parser BUG is triggered by group - //in the middle of alternation (at least not first and not last) - version(fred_bug) - { - enum testCT = regex(`abc|(edf)|xyz`); - auto testRT = regex(`abc|(edf)|xyz`); - debug - { - writeln("C-T version :"); - testCT.print(); - writeln("R-T version :"); - testRT.print(); - - } - - } - - } - - unittest - { - enum cx = ctRegex!"(A|B|C)"; - auto mx = match("B",cx); - assert(mx); - assert(equal(mx.captures, [ "B", "B"])); - enum cx2 = ctRegex!"(A|B)*"; - assert(match("BAAA",cx2)); - enum cx3 = ctRegex!("a{3,4}","i"); - auto mx3 = match("AaA",cx3); - assert(mx3); - assert(mx3.captures[0] == "AaA"); - enum cx4 = ctRegex!(`^a{3,4}?[a-zA-Z0-9~]{1,2}`,"i"); - auto mx4 = match("aaaabc", cx4); - assert(mx4); - assert(mx4.captures[0] == "aaaab"); - auto cr8 = ctRegex!("(a)(b)?(c*)"); - auto m8 = bmatch("abcc",cr8); - assert(m8); - assert(m8.captures[1] == "a"); - assert(m8.captures[2] == "b"); - assert(m8.captures[3] == "cc"); - auto cr9 = ctRegex!(".*$", "gm"); - auto m9 = match("First\rSecond"); - assert(m9); - assert(equal(map!"a.hit"(m9.captures), ["First", "", "Second"])); - } -} -else -{ - unittest - { - //global matching - void test_body(alias matchFn)() - { - string s = "a quick brown fox jumps over a lazy dog"; - auto r1 = regex("\\b[a-z]+\\b","g"); - string[] test; - foreach(m; matchFn(s, r1)) - test ~= m.hit; - assert(equal(test, [ "a", "quick", "brown", "fox", "jumps", "over", "a", "lazy", "dog"])); - auto free_reg = regex(` - - abc - \s+ - " - ( - [^"]+ - | \\ " - )+ - " - z - `, "x"); - auto m = match(`abc "quoted string with \" inside"z`,free_reg); - assert(m); - string mails = " hey@you.com no@spam.net "; - auto rm = regex(`@(?<=\S+@)\S+`,"g"); - assert(equal(map!"a[0]"(matchFn(mails, rm)), ["@you.com", "@spam.net"])); - auto m2 = matchFn("First line\nSecond line",regex(".*$","gm")); - assert(equal(map!"a[0]"(m2), ["First line", "", "Second line"])); - auto m2a = matchFn("First line\nSecond line",regex(".+$","gm")); - assert(equal(map!"a[0]"(m2a), ["First line", "Second line"])); - auto m2b = matchFn("First line\nSecond line",regex(".+?$","gm")); - assert(equal(map!"a[0]"(m2b), ["First line", "Second line"])); - debug(fred_test) writeln("!!! FReD FLAGS test done "~matchFn.stringof~" !!!"); - } - test_body!bmatch(); - test_body!match(); - } - - //tests for accomulated std.regex issues and other regressions - unittest - { - void test_body(alias matchFn)() - { - //issue 5857 - //matching goes out of control if ... in (...){x} has .*/.+ - auto c = matchFn("axxxzayyyyyzd",regex("(a.*z){2}d")).captures; - assert(c[0] == "axxxzayyyyyzd"); - assert(c[1] == "ayyyyyz"); - auto c2 = matchFn("axxxayyyyyd",regex("(a.*){2}d")).captures; - assert(c2[0] == "axxxayyyyyd"); - assert(c2[1] == "ayyyyy"); - //issue 2108 - //greedy vs non-greedy - auto nogreed = regex(""); - assert(matchFn("texttext", nogreed).hit - == "text"); - auto greed = regex(""); - assert(matchFn("texttext", greed).hit - == "texttext"); - //issue 4574 - //empty successful match still advances the input - string[] pres, posts, hits; - foreach(m; matchFn("abcabc", regex("","g"))) { - pres ~= m.pre; - posts ~= m.post; - assert(m.hit.empty); - - } - auto heads = [ - "abcabc", - "abcab", - "abca", - "abc", - "ab", - "a", - "" - ]; - auto tails = [ - "abcabc", - "bcabc", - "cabc", - "abc", - "bc", - "c", - "" - ]; - assert(pres == array(retro(heads))); - assert(posts == tails); - //issue 6076 - //regression on .* - auto re = regex("c.*|d"); - auto m = matchFn("mm", re); - assert(!m); - debug(fred_test) writeln("!!! FReD REGRESSION test done "~matchFn.stringof~" !!!"); - auto rprealloc = regex(`((.){5}.{1,10}){5}`); - auto arr = array(repeat('0',100)); - auto m2 = matchFn(arr, rprealloc); - assert(m2); - assert(collectException( - regex(r"^(import|file|binary|config)\s+([^\(]+)\(?([^\)]*)\)?\s*$") - ) is null); - foreach(ch; ['^','$','.','|','?',',','-',';',':' - ,'#','&','%','/','<','>','`' - ,'*','+','(',')','{','}']) { - assert(match(to!string(ch),regex(`[\`~ch~`]`))); - assert(!match(to!string(ch),regex(`[^\`~ch~`]`))); - if(ch != '-') //'--' is an operator - assert(match(to!string(ch),regex(`[\`~ch~`-\`~ch~`]`))); - } - //bugzilla 7718 - string strcmd = "./myApp.rb -os OSX -path \"/GIT/Ruby Apps/sec\" -conf 'notimer'"; - auto reStrCmd = regex (`(".*")|('.*')`, "g"); - assert(equal(map!"a[0]"(matchFn(strcmd, reStrCmd)), - [`"/GIT/Ruby Apps/sec"`, `'notimer'`])); - } - test_body!bmatch(); - test_body!match(); - } - - // tests for replace - unittest - { - void test(alias matchFn)() - { - foreach(i, v; TypeTuple!(string, wstring, dstring)) - { - auto baz(Cap)(Cap m) - if (is(Cap == Captures!(Cap.String))) + //BUG: tv[v] is fine but tvd is not known at compile time?! + enum r = ctRegex!(tv[v].pattern, tv[v].flags); + auto nr = regex(tvd.pattern, tvd.flags); + assert(equal(r.ir, nr.ir), + text("!C-T regex! failed to compile pattern #", a ,": ", tvd.pattern)); + auto m = match(tvd.input, r); + auto c = tvd.result[0]; + bool ok = (c == 'y') ^ m.empty; + assert(ok, text("ctRegex: failed to match pattern #", + a ,": ", tvd.pattern)); + if(c == 'y') { - return std.string.toUpper(m.hit); + import std.stdio; + auto result = produceExpected(m, tvd.format); + if(result != tvd.replace) + writeln("ctRegex mismatch pattern #", a, ": ", tvd.pattern," expected: ", + tvd.replace, " vs ", result); } - alias v String; - assert(std.regex.replace!(matchFn)(to!String("ark rapacity"), regex(to!String("r")), to!String("c")) - == to!String("ack rapacity")); - assert(std.regex.replace!(matchFn)(to!String("ark rapacity"), regex(to!String("r"), "g"), to!String("c")) - == to!String("ack capacity")); - assert(std.regex.replace!(matchFn)(to!String("noon"), regex(to!String("^n")), to!String("[$&]")) - == to!String("[n]oon")); - assert(std.regex.replace!(matchFn)(to!String("test1 test2"), regex(to!String(`\w+`),"g"), to!String("$`:$'")) - == to!String(": test2 test1 :")); - auto s = std.regex.replace!(baz!(Captures!(String)))(to!String("Strap a rocket engine on a chicken."), - regex(to!String("[ar]"), "g")); - assert(s == "StRAp A Rocket engine on A chicken."); } - debug(fred_test) writeln("!!! Replace test done "~matchFn.stringof~" !!!"); } - test!(bmatch)(); - test!(match)(); + debug(std_regex_test) writeln("!!! FReD C-T test done !!!"); } - // tests for splitter - unittest + ct_tests(); + run_tests!bmatch(); //backtracker + run_tests!match(); //thompson VM +} + +unittest +{ + auto cr = ctRegex!("abc"); + assert(bmatch("abc",cr).hit == "abc"); + auto cr2 = ctRegex!("ab*c"); + assert(bmatch("abbbbc",cr2).hit == "abbbbc"); + auto cr3 = ctRegex!("^abc$"); + assert(bmatch("abc",cr3).hit == "abc"); + auto cr4 = ctRegex!(`\b(a\B[a-z]b)\b`); + assert(array(match("azb",cr4).captures) == ["azb", "azb"]); + auto cr5 = ctRegex!("(?:a{2,4}b{1,3}){1,2}"); + assert(bmatch("aaabaaaabbb", cr5).hit == "aaabaaaabbb"); + auto cr6 = ctRegex!("(?:a{2,4}b{1,3}){1,2}?"w); + assert(bmatch("aaabaaaabbb"w, cr6).hit == "aaab"w); + auto cr7 = ctRegex!(`\r.*?$`,"sm"); + assert(bmatch("abc\r\nxy", cr7).hit == "\r\nxy"); + auto greed = ctRegex!(""); + assert(bmatch("texttext", greed).hit + == "text"); + auto cr8 = ctRegex!("^(a)(b)?(c*)"); + auto m8 = bmatch("abcc",cr8); + assert(m8); + assert(m8.captures[1] == "a"); + assert(m8.captures[2] == "b"); + assert(m8.captures[3] == "cc"); + auto cr9 = ctRegex!("q(a|b)*q"); + auto m9 = match("xxqababqyy",cr9); + assert(m9); + assert(equal(bmatch("xxqababqyy",cr9).captures, ["qababq", "b"])); + + auto rtr = regex("a|b|c"); + enum ctr = regex("a|b|c"); + assert(equal(rtr.ir,ctr.ir)); + //CTFE parser BUG is triggered by group + //in the middle of alternation (at least not first and not last) + enum testCT = regex(`abc|(edf)|xyz`); + auto testRT = regex(`abc|(edf)|xyz`); + assert(equal(testCT.ir,testRT.ir)); +} + +unittest +{ + enum cx = ctRegex!"(A|B|C)"; + auto mx = match("B",cx); + assert(mx); + assert(equal(mx.captures, [ "B", "B"])); + enum cx2 = ctRegex!"(A|B)*"; + assert(match("BAAA",cx2)); + enum cx3 = ctRegex!("a{3,4}","i"); + auto mx3 = match("AaA",cx3); + assert(mx3); + assert(mx3.captures[0] == "AaA"); + enum cx4 = ctRegex!(`^a{3,4}?[a-zA-Z0-9~]{1,2}`,"i"); + auto mx4 = match("aaaabc", cx4); + assert(mx4); + assert(mx4.captures[0] == "aaaab"); + auto cr8 = ctRegex!("(a)(b)?(c*)"); + auto m8 = bmatch("abcc",cr8); + assert(m8); + assert(m8.captures[1] == "a"); + assert(m8.captures[2] == "b"); + assert(m8.captures[3] == "cc"); + auto cr9 = ctRegex!(".*$", "gm"); + auto m9 = match("First\rSecond", cr9); + assert(m9); + assert(equal(map!"a.hit"(m9), ["First", "", "Second"])); +} + +unittest +{ +//global matching + void test_body(alias matchFn)() { - auto s1 = ", abc, de, fg, hi, "; - auto sp1 = splitter(s1, regex(", *")); - auto w1 = ["", "abc", "de", "fg", "hi", ""]; - assert(equal(sp1, w1)); + string s = "a quick brown fox jumps over a lazy dog"; + auto r1 = regex("\\b[a-z]+\\b","g"); + string[] test; + foreach(m; matchFn(s, r1)) + test ~= m.hit; + assert(equal(test, [ "a", "quick", "brown", "fox", "jumps", "over", "a", "lazy", "dog"])); + auto free_reg = regex(` - auto s2 = ", abc, de, fg, hi"; - auto sp2 = splitter(s2, regex(", *")); - auto w2 = ["", "abc", "de", "fg", "hi"]; + abc + \s+ + " + ( + [^"]+ + | \\ " + )+ + " + z + `, "x"); + auto m = match(`abc "quoted string with \" inside"z`,free_reg); + assert(m); + string mails = " hey@you.com no@spam.net "; + auto rm = regex(`@(?<=\S+@)\S+`,"g"); + assert(equal(map!"a[0]"(matchFn(mails, rm)), ["@you.com", "@spam.net"])); + auto m2 = matchFn("First line\nSecond line",regex(".*$","gm")); + assert(equal(map!"a[0]"(m2), ["First line", "", "Second line"])); + auto m2a = matchFn("First line\nSecond line",regex(".+$","gm")); + assert(equal(map!"a[0]"(m2a), ["First line", "Second line"])); + auto m2b = matchFn("First line\nSecond line",regex(".+?$","gm")); + assert(equal(map!"a[0]"(m2b), ["First line", "Second line"])); + debug(std_regex_test) writeln("!!! FReD FLAGS test done "~matchFn.stringof~" !!!"); + } + test_body!bmatch(); + test_body!match(); +} + +//tests for accumulated std.regex issues and other regressions +unittest +{ + void test_body(alias matchFn)() + { + //issue 5857 + //matching goes out of control if ... in (...){x} has .*/.+ + auto c = matchFn("axxxzayyyyyzd",regex("(a.*z){2}d")).captures; + assert(c[0] == "axxxzayyyyyzd"); + assert(c[1] == "ayyyyyz"); + auto c2 = matchFn("axxxayyyyyd",regex("(a.*){2}d")).captures; + assert(c2[0] == "axxxayyyyyd"); + assert(c2[1] == "ayyyyy"); + //issue 2108 + //greedy vs non-greedy + auto nogreed = regex(""); + assert(matchFn("texttext", nogreed).hit + == "text"); + auto greed = regex(""); + assert(matchFn("texttext", greed).hit + == "texttext"); + //issue 4574 + //empty successful match still advances the input + string[] pres, posts, hits; + foreach(m; matchFn("abcabc", regex("","g"))) { + pres ~= m.pre; + posts ~= m.post; + assert(m.hit.empty); - uint cnt; - foreach(e; sp2) { - assert(w2[cnt++] == e); } - assert(equal(sp2, w2)); - } - - unittest - { - char[] s1 = ", abc, de, fg, hi, ".dup; - auto sp2 = splitter(s1, regex(", *")); - } - - unittest - { - auto s1 = ", abc, de, fg, hi, "; - auto w1 = ["", "abc", "de", "fg", "hi", ""]; - assert(equal(split(s1, regex(", *")), w1[])); - } - - unittest - { // bugzilla 7141 - string pattern = `[a\--b]`; - assert(match("-", pattern)); - assert(match("b", pattern)); - string pattern2 = `[&-z]`; - assert(match("b", pattern2)); - } - unittest - {//bugzilla 7111 - assert(match("", regex("^"))); - } - unittest - {//bugzilla 7300 - assert(!match("a"d, "aa"d)); - } - - unittest - {//bugzilla 7674 - assert("1234".replace(regex("^"), "$$") == "$1234"); - assert("hello?".replace(regex(r"\?", "g"), r"\?") == r"hello\?"); - assert("hello?".replace(regex(r"\?", "g"), r"\\?") != r"hello\?"); - } - unittest - {// bugzilla 7679 - foreach(S; TypeTuple!(string, wstring, dstring)) + auto heads = [ + "abcabc", + "abcab", + "abca", + "abc", + "ab", + "a", + "" + ]; + auto tails = [ + "abcabc", + "bcabc", + "cabc", + "abc", + "bc", + "c", + "" + ]; + assert(pres == array(retro(heads))); + assert(posts == tails); + //issue 6076 + //regression on .* + auto re = regex("c.*|d"); + auto m = matchFn("mm", re); + assert(!m); + debug(std_regex_test) writeln("!!! FReD REGRESSION test done "~matchFn.stringof~" !!!"); + auto rprealloc = regex(`((.){5}.{1,10}){5}`); + auto arr = array(repeat('0',100)); + auto m2 = matchFn(arr, rprealloc); + assert(m2); + assert(collectException( + regex(r"^(import|file|binary|config)\s+([^\(]+)\(?([^\)]*)\)?\s*$") + ) is null); + foreach(ch; [Escapables]) { - enum re = ctRegex!(to!S(r"\.")); - auto str = to!S("a.b"); - assert(equal(std.regex.splitter(str, re), [to!S("a"), to!S("b")])); - assert(split(str, re) == [to!S("a"), to!S("b")]); + assert(match(to!string(ch),regex(`[\`~ch~`]`))); + assert(!match(to!string(ch),regex(`[^\`~ch~`]`))); + assert(match(to!string(ch),regex(`[\`~ch~`-\`~ch~`]`))); } + //bugzilla 7718 + string strcmd = "./myApp.rb -os OSX -path \"/GIT/Ruby Apps/sec\" -conf 'notimer'"; + auto reStrCmd = regex (`(".*")|('.*')`, "g"); + assert(equal(map!"a[0]"(matchFn(strcmd, reStrCmd)), + [`"/GIT/Ruby Apps/sec"`, `'notimer'`])); } - unittest - {//bugzilla 8203 - string data = " - NAME = XPAW01_STA:STATION - NAME = XPAW01_STA - "; - auto uniFileOld = data; - auto r = regex( - r"^NAME = (?P[a-zA-Z0-9_]+):*(?P[a-zA-Z0-9_]*)","gm"); - auto uniCapturesNew = match(uniFileOld, r); - for(int i = 0; i < 20; i++) - foreach (matchNew; uniCapturesNew) {} - } - unittest - {// bugzilla 8637 purity of enforce - auto m = match("hello world", regex("world")); - enforce(m); - } + test_body!bmatch(); + test_body!match(); +} - // bugzilla 8725 - unittest - { - static italic = regex( r"\* - (?!\s+) - (.*?) - (?!\s+) - \*", "gx" ); - string input = "this * is* interesting, *very* interesting"; - assert(replace(input, italic, "$1") == - "this * is* interesting, very interesting"); - } - - // bugzilla 8349 - unittest +// tests for replace +unittest +{ + void test(alias matchFn)() { - enum peakRegexStr = r"\>(wgEncode.*Tfbs.*\.(?:narrow)|(?:broad)Peak.gz)"; - enum peakRegex = ctRegex!(peakRegexStr); - //note that the regex pattern itself is probably bogus - assert(match(r"\>wgEncode-blah-Tfbs.narrow", peakRegex)); - } + import std.string : toUpper; - // bugzilla 9211 - unittest - { - auto rx_1 = regex(r"^(\w)*(\d)"); - auto m = match("1234", rx_1); - assert(equal(m.front, ["1234", "3", "4"])); - auto rx_2 = regex(r"^([0-9])*(\d)"); - auto m2 = match("1234", rx_2); - assert(equal(m2.front, ["1234", "3", "4"])); + foreach(i, v; TypeTuple!(string, wstring, dstring)) + { + auto baz(Cap)(Cap m) + if (is(Cap == Captures!(Cap.String))) + { + return std.string.toUpper(m.hit); + } + alias String = v; + assert(std.regex.replace!(matchFn)(to!String("ark rapacity"), regex(to!String("r")), to!String("c")) + == to!String("ack rapacity")); + assert(std.regex.replace!(matchFn)(to!String("ark rapacity"), regex(to!String("r"), "g"), to!String("c")) + == to!String("ack capacity")); + assert(std.regex.replace!(matchFn)(to!String("noon"), regex(to!String("^n")), to!String("[$&]")) + == to!String("[n]oon")); + assert(std.regex.replace!(matchFn)(to!String("test1 test2"), regex(to!String(`\w+`),"g"), to!String("$`:$'")) + == to!String(": test2 test1 :")); + auto s = std.regex.replace!(baz!(Captures!(String)))(to!String("Strap a rocket engine on a chicken."), + regex(to!String("[ar]"), "g")); + assert(s == "StRAp A Rocket engine on A chicken."); + } + debug(std_regex_test) writeln("!!! Replace test done "~matchFn.stringof~" !!!"); } + test!(bmatch)(); + test!(match)(); +} - // bugzilla 9280 - unittest - { - string tomatch = "a!b@c"; - static r = regex(r"^(?P.*?)!(?P.*?)@(?P.*?)$"); - auto nm = match(tomatch, r); - assert(nm); - auto c = nm.captures; - assert(c[1] == "a"); - assert(c["nick"] == "a"); - } +// tests for splitter +unittest +{ + auto s1 = ", abc, de, fg, hi, "; + auto sp1 = splitter(s1, regex(", *")); + auto w1 = ["", "abc", "de", "fg", "hi", ""]; + assert(equal(sp1, w1)); - // bugzilla 9634 - unittest - { - auto re = ctRegex!"(?:a+)"; - assert(match("aaaa", re).hit == "aaaa"); + auto s2 = ", abc, de, fg, hi"; + auto sp2 = splitter(s2, regex(", *")); + auto w2 = ["", "abc", "de", "fg", "hi"]; + + uint cnt; + foreach(e; sp2) { + assert(w2[cnt++] == e); } + assert(equal(sp2, w2)); +} + +unittest +{ + char[] s1 = ", abc, de, fg, hi, ".dup; + auto sp2 = splitter(s1, regex(", *")); +} + +unittest +{ + auto s1 = ", abc, de, fg, hi, "; + auto w1 = ["", "abc", "de", "fg", "hi", ""]; + assert(equal(split(s1, regex(", *")), w1[])); +} + +unittest +{ // bugzilla 7141 + string pattern = `[a\--b]`; + assert(match("-", pattern)); + assert(match("b", pattern)); + string pattern2 = `[&-z]`; + assert(match("b", pattern2)); +} +unittest +{//bugzilla 7111 + assert(match("", regex("^"))); +} +unittest +{//bugzilla 7300 + assert(!match("a"d, "aa"d)); +} + +unittest +{//bugzilla 7674 + assert("1234".replace(regex("^"), "$$") == "$1234"); + assert("hello?".replace(regex(r"\?", "g"), r"\?") == r"hello\?"); + assert("hello?".replace(regex(r"\?", "g"), r"\\?") != r"hello\?"); +} +unittest +{// bugzilla 7679 + foreach(S; TypeTuple!(string, wstring, dstring)) + { + enum re = ctRegex!(to!S(r"\.")); + auto str = to!S("a.b"); + assert(equal(std.regex.splitter(str, re), [to!S("a"), to!S("b")])); + assert(split(str, re) == [to!S("a"), to!S("b")]); + } +} +unittest +{//bugzilla 8203 + string data = " + NAME = XPAW01_STA:STATION + NAME = XPAW01_STA + "; + auto uniFileOld = data; + auto r = regex( + r"^NAME = (?P[a-zA-Z0-9_]+):*(?P[a-zA-Z0-9_]*)","gm"); + auto uniCapturesNew = match(uniFileOld, r); + for(int i = 0; i < 20; i++) + foreach (matchNew; uniCapturesNew) {} +} +unittest +{// bugzilla 8637 purity of enforce + auto m = match("hello world", regex("world")); + enforce(m); +} + +// bugzilla 8725 +unittest +{ + static italic = regex( r"\* + (?!\s+) + (.*?) + (?!\s+) + \*", "gx" ); + string input = "this * is* interesting, *very* interesting"; + assert(replace(input, italic, "$1") == + "this * is* interesting, very interesting"); +} + +// bugzilla 8349 +unittest +{ + enum peakRegexStr = r"\>(wgEncode.*Tfbs.*\.(?:narrow)|(?:broad)Peak.gz)"; + enum peakRegex = ctRegex!(peakRegexStr); + //note that the regex pattern itself is probably bogus + assert(match(r"\>wgEncode-blah-Tfbs.narrow", peakRegex)); +} + +// bugzilla 9211 +unittest +{ + auto rx_1 = regex(r"^(\w)*(\d)"); + auto m = match("1234", rx_1); + assert(equal(m.front, ["1234", "3", "4"])); + auto rx_2 = regex(r"^([0-9])*(\d)"); + auto m2 = match("1234", rx_2); + assert(equal(m2.front, ["1234", "3", "4"])); +} + +// bugzilla 9280 +unittest +{ + string tomatch = "a!b@c"; + static r = regex(r"^(?P.*?)!(?P.*?)@(?P.*?)$"); + auto nm = match(tomatch, r); + assert(nm); + auto c = nm.captures; + assert(c[1] == "a"); + assert(c["nick"] == "a"); +} + + +// bugzilla 9579 +unittest +{ + char[] input = ['a', 'b', 'c']; + string format = "($1)"; + // used to give a compile error: + auto re = regex(`(a)`, "g"); + auto r = replace(input, re, format); + assert(r == "(a)bc"); +} + +// bugzilla 9634 +unittest +{ + auto re = ctRegex!"(?:a+)"; + assert(match("aaaa", re).hit == "aaaa"); +} + +// bugzilla 10913 +unittest +{ + @system static string foo(const(char)[] s) + { + return s.dup; + } + @safe static string bar(const(char)[] s) + { + return s.dup; + } + () @system { + replace!((a) => foo(a.hit))("blah", regex(`a`)); + }(); + () @safe { + replace!((a) => bar(a.hit))("blah", regex(`a`)); + }(); +} + +// bugzilla 11262 +unittest +{ + enum reg = ctRegex!(r",", "g"); + auto str = "This,List"; + str = str.replace(reg, "-"); + assert(str == "This-List"); +} + +// bugzilla 11775 +unittest +{ + assert(collectException(regex("a{1,0}"))); } }//version(unittest) diff --git a/std/socket.d b/std/socket.d index 8ebf5d02d..7c799a05d 100644 --- a/std/socket.d +++ b/std/socket.d @@ -61,7 +61,7 @@ version(Windows) private alias std.c.windows.winsock.timeval _ctimeval; private alias std.c.windows.winsock.linger _clinger; - enum socket_t : SOCKET { INVALID_SOCKET }; + enum socket_t : SOCKET { INVALID_SOCKET } private const int _SOCKET_ERROR = SOCKET_ERROR; @@ -94,6 +94,7 @@ else version(Posix) static assert(false); import core.sys.posix.netdb; + import core.sys.posix.sys.un : sockaddr_un; private import core.sys.posix.fcntl; private import core.sys.posix.unistd; private import core.sys.posix.arpa.inet; @@ -1765,13 +1766,13 @@ public: /** * Construct a new $(D Internet6Address). * Params: - * node = an IPv6 host address string in the form described in RFC 2373, - * or a host name which will be resolved using $(D getAddressInfo). - * port = (optional) service name or port number. + * addr = an IPv6 host address string in the form described in RFC 2373, + * or a host name which will be resolved using $(D getAddressInfo). + * service = (optional) service name. */ - this(in char[] node, in char[] service = null) + this(in char[] addr, in char[] service = null) { - auto results = getAddressInfo(node, service, AddressFamily.INET6); + auto results = getAddressInfo(addr, service, AddressFamily.INET6); assert(results.length && results[0].family == AddressFamily.INET6); sin6 = *cast(sockaddr_in6*)results[0].address.name; } @@ -1783,19 +1784,19 @@ public: * or a host name which will be resolved using $(D getAddressInfo). * port = port number, may be $(D PORT_ANY). */ - this(in char[] node, ushort port) + this(in char[] addr, ushort port) { if (port == PORT_ANY) - this(node); + this(addr); else - this(node, to!string(port)); + this(addr, to!string(port)); } /** * Construct a new $(D Internet6Address). * Params: * addr = (optional) an IPv6 host address in host byte order, or - $(D ADDR_ANY). + * $(D ADDR_ANY). * port = port number, may be $(D PORT_ANY). */ this(ubyte[16] addr, ushort port) @@ -1893,10 +1894,10 @@ static if (is(sockaddr_un)) this(in char[] path) { - len = sockaddr_un.sun_path.offsetof + path.length + 1; + len = cast(socklen_t)(sockaddr_un.init.sun_path.offsetof + path.length + 1); sun = cast(sockaddr_un*) (new ubyte[len]).ptr; sun.sun_family = AF_UNIX; - sun.sun_path.ptr[0..path.length] = path; + sun.sun_path.ptr[0..path.length] = (cast(byte[]) path)[]; sun.sun_path.ptr[path.length] = 0; } @@ -1910,6 +1911,40 @@ static if (is(sockaddr_un)) return path; } } + + unittest + { + import core.stdc.stdio : remove; + + immutable ubyte[] data = [1, 2, 3, 4]; + Socket[2] pair; + + auto name = "unix-address-family-unittest-socket-name"; + auto address = new UnixAddress(name); + + auto listener = new Socket(AddressFamily.UNIX, SocketType.STREAM); + scope(exit) listener.close(); + + listener.bind(address); + scope(exit) remove(toStringz(name)); + + listener.listen(1); + + pair[0] = new Socket(AddressFamily.UNIX, SocketType.STREAM); + scope(exit) listener.close(); + + pair[0].connect(address); + scope(exit) pair[0].close(); + + pair[1] = listener.accept(); + scope(exit) pair[1].close(); + + pair[0].send(data); + + auto buf = new ubyte[data.length]; + pair[1].receive(buf); + assert(buf == data); + } } @@ -2885,7 +2920,9 @@ public: * randomly varies on the order of 10ms. * * Params: - * value = The timeout duration to set. Must not be negative. + * level = The level at which a socket option is defined. + * option = Either $(D SocketOption.SNDTIMEO) or $(D SocketOption.RCVTIMEO). + * value = The timeout duration to set. Must not be negative. * * Throws: $(D SocketException) if setting the options fails. * @@ -2925,7 +2962,7 @@ public: else version (Posix) { _ctimeval tv; - tv.tv_sec = to!(typeof(tv.tv_sec ))(value.total!"seconds"()); + tv.tv_sec = to!(typeof(tv.tv_sec ))(value.total!"seconds"); tv.tv_usec = to!(typeof(tv.tv_usec))(value.fracSec.usecs); setOption(level, option, (&tv)[0 .. 1]); } diff --git a/std/stdio.d b/std/stdio.d index 552158233..f8ad478f5 100644 --- a/std/stdio.d +++ b/std/stdio.d @@ -120,6 +120,8 @@ else version (MICROSOFT_STDIO) int _fgetwc_nolock(_iobuf*); void _lock_file(FILE*); void _unlock_file(FILE*); + int _setmode(int, int); + int _fileno(FILE*); } alias _fputc_nolock FPUTC; alias _fputwc_nolock FPUTWC; @@ -128,6 +130,9 @@ else version (MICROSOFT_STDIO) alias _lock_file FLOCK; alias _unlock_file FUNLOCK; + + enum _O_BINARY = 0x8000; + } else version (GCC_IO) { @@ -746,7 +751,7 @@ Throws: $(D Exception) if the file is not opened. */ void write(S...)(S args) { - auto w = lockingTextWriter; + auto w = lockingTextWriter(); foreach (arg; args) { alias typeof(arg) A; @@ -798,7 +803,7 @@ Throws: $(D Exception) if the file is not opened. */ void writef(Char, A...)(in Char[] fmt, A args) { - std.format.formattedWrite(lockingTextWriter, fmt, args); + std.format.formattedWrite(lockingTextWriter(), fmt, args); } /** @@ -810,44 +815,47 @@ Throws: $(D Exception) if the file is not opened. */ void writefln(Char, A...)(in Char[] fmt, A args) { - auto w = lockingTextWriter; + auto w = lockingTextWriter(); std.format.formattedWrite(w, fmt, args); w.put('\n'); } /** -Read line from stream $(D fp) and return it as a specified type. +Read line from the file handle and return it as a specified type. This version manages its own read buffer, which means one memory allocation per call. If you are not retaining a reference to the read data, consider the $(D File.readln(buf)) version, which may offer -better performance as it reuses its read buffer. +better performance as it can reuse its read buffer. Params: - S = Template parameter; the type of the allocated buffer, and the type returned. Defaults to $(D string) + S = Template parameter; the type of the allocated buffer, and the type returned. Defaults to $(D string). terminator = line terminator (by default, '\n') Returns: The line that was read, including the line terminator character. +Throws: + $(D StdioException) on I/O error, or $(D UnicodeException) on Unicode conversion error. + Example: --- // Reads $(D stdin) and writes it to $(D stdout). import std.stdio; -int main() +void main() { - string buf; - while ((buf = readln()) !is null) - write(buf); - return 0; + string line; + while ((line = stdin.readln()) !is null) + write(line); } --- */ S readln(S = string)(dchar terminator = '\n') + if (isSomeString!S) { Unqual!(ElementEncodingType!S)[] buf; readln(buf, terminator); - return assumeUnique(buf); + return cast(S)buf; } unittest @@ -855,13 +863,13 @@ int main() auto deleteme = testFilename(); std.file.write(deleteme, "hello\nworld\n"); scope(exit) std.file.remove(deleteme); - foreach (C; Tuple!(char, wchar, dchar).Types) + foreach (String; TypeTuple!(string, char[], wstring, wchar[], dstring, dchar[])) { auto witness = [ "hello\n", "world\n" ]; auto f = File(deleteme); uint i = 0; - immutable(C)[] buf; - while ((buf = f.readln!(typeof(buf))()).length) + String buf; + while ((buf = f.readln!String()).length) { assert(i < witness.length); assert(equal(buf, witness[i++])); @@ -870,18 +878,33 @@ int main() } } + unittest + { + auto deleteme = testFilename(); + std.file.write(deleteme, "cześć \U0002000D"); + scope(exit) std.file.remove(deleteme); + uint[] lengths=[12,8,7]; + foreach (uint i,C; Tuple!(char, wchar, dchar).Types) + { + immutable(C)[] witness = "cześć \U0002000D"; + auto buf = File(deleteme).readln!(immutable(C)[])(); + assert(buf.length==lengths[i]); + assert(buf==witness); + } + } + /** -Read line from stream $(D fp) and write it to $(D buf[]), including +Read line from the file handle and write it to $(D buf[]), including terminating character. -This is often faster than $(D buf = File.readln()) because the buffer -is reused each call. Note that reusing the buffer means that the -previous contents of it has to be copied if needed. +This can be faster than $(D line = File.readln()) because you can reuse +the buffer for each call. Note that reusing the buffer means that you +must copy the previous contents if you wish to retain them. Params: -fp = input stream buf = buffer used to store the resulting line data. buf is resized as necessary. +terminator = line terminator (by default, '\n') Returns: 0 for end of file, otherwise number of characters read @@ -891,37 +914,34 @@ conversion error. Example: --- -// Reads $(D stdin) into a buffer -// Dumps the buffer to $(D stdout) when it gets a "q" +// Read lines from $(D stdin) into a string +// Ignore lines starting with '#' +// Write the string to $(D stdout) -int main() +void main() { - string[] outBuf; - string buf; + string output; + char[] buf; while (stdin.readln(buf)) { - if (buf[0] == 'q') - break; + if (buf[0] == '#') + continue; - outBuf ~= buf.idup; + output ~= buf; } - foreach (line; outBuf) - { - write(line); - } - - return 0; + write(output); } --- -This method is more efficient than the one in the previous example +This method can be more efficient than the one in the previous example because $(D stdin.readln(buf)) reuses (if possible) memory allocated -by $(D buf), whereas $(D buf = stdin.readln()) makes a new memory allocation -with every line. +for $(D buf), whereas $(D line = stdin.readln()) makes a new memory allocation +for every line. */ - size_t readln(C)(ref C[] buf, dchar terminator = '\n') if (isSomeChar!C && !is(C == enum)) + size_t readln(C)(ref C[] buf, dchar terminator = '\n') + if (isSomeChar!C && is(Unqual!C == C) && !is(C == enum)) { static if (is(C == char)) { @@ -934,7 +954,7 @@ with every line. string s = readln(terminator); buf.length = 0; if (!s.length) return 0; - foreach (wchar c; s) + foreach (C c; s) { buf ~= c; } @@ -944,7 +964,8 @@ with every line. /** ditto */ size_t readln(C, R)(ref C[] buf, R terminator) - if (isBidirectionalRange!R && is(typeof(terminator.front == buf[0]))) + if (isSomeChar!C && is(Unqual!C == C) && !is(C == enum) && + isBidirectionalRange!R && is(typeof(terminator.front == dchar.init))) { auto last = terminator.back; C[] buf2; @@ -1051,15 +1072,149 @@ Returns the file number corresponding to this object. return .fileno(cast(FILE*) _p.handle); } -/** +// Note: This was documented until 2013/08 +/* Range that reads one line at a time. Returned by $(LREF byLine). Allows to directly use range operations on lines of a file. +*/ + struct ByLine(Char, Terminator) + { + private: + /* Ref-counting stops the source range's ByLineImpl + * from getting out of sync after the range is copied, e.g. + * when accessing range.front, then using std.range.take, + * then accessing range.front again. */ + alias Impl = RefCounted!(ByLineImpl!(Char, Terminator), + RefCountedAutoInitialize.no); + Impl impl; + + static if (isScalarType!Terminator) + enum defTerm = '\n'; + else + enum defTerm = cast(Terminator)"\n"; + + public: + this(File f, KeepTerminator kt = KeepTerminator.no, + Terminator terminator = defTerm) + { + impl = Impl(f, kt, terminator); + } + + @property bool empty() + { + return impl.refCountedPayload.empty; + } + + @property Char[] front() + { + return impl.refCountedPayload.front; + } + + void popFront() + { + impl.refCountedPayload.popFront(); + } + } + + private struct ByLineImpl(Char, Terminator) + { + private: + File file; + Char[] line; + Terminator terminator; + KeepTerminator keepTerminator; + bool first_call = true; + + public: + this(File f, KeepTerminator kt, Terminator terminator) + { + file = f; + this.terminator = terminator; + keepTerminator = kt; + } + + // Range primitive implementations. + @property bool empty() + { + if (line !is null) return false; + if (!file.isOpen) return true; + + // First read ever, must make sure stream is not empty. We + // do so by reading a character and putting it back. Doing + // so is guaranteed to work on all files opened in all + // buffering modes. + auto fp = file.getFP(); + auto c = fgetc(fp); + if (c == -1) + { + file.detach(); + return true; + } + ungetc(c, fp) == c + || assert(false, "Bug in cstdlib implementation"); + return false; + } + + @property Char[] front() + { + if (first_call) + { + popFront(); + first_call = false; + } + return line; + } + + void popFront() + { + assert(file.isOpen); + assumeSafeAppend(line); + file.readln(line, terminator); + if (line.empty) + { + file.detach(); + line = null; + } + else if (keepTerminator == KeepTerminator.no + && std.algorithm.endsWith(line, terminator)) + { + static if (isScalarType!Terminator) + enum tlen = 1; + else static if (isArray!Terminator) + { + static assert( + is(Unqual!(ElementEncodingType!Terminator) == Char)); + const tlen = terminator.length; + } + else + static assert(false); + line = line.ptr[0 .. line.length - tlen]; + } + } + } + +/** +Returns an input range set up to read from the file handle one line +at a time. + +The element type for the range will be $(D Char[]). Range primitives +may throw $(D StdioException) on I/O error. + +Note: +Each $(D front) will not persist after $(D +popFront) is called, so the caller must copy its contents (e.g. by +calling $(D to!string)) if retention is needed. + +Params: +Char = Character type for each line, defaulting to $(D char). +keepTerminator = Use $(D KeepTerminator.yes) to include the +terminator at the end of each line. +terminator = Line separator ($(D '\n') by default). Example: - ---- -import std.algorithm, std.string, std.stdio; +import std.algorithm, std.stdio, std.string; // Count words in a file using ranges. void main() { @@ -1074,97 +1229,41 @@ void main() Example: ---- -import std.stdio; -// Count lines in file using a foreach +import std.range, std.stdio; +// Read lines using foreach. void main() { - auto file = File("file.txt"); // open for reading - ulong lineCount = 0; - foreach (line; file.byLine()) + auto file = File("file.txt"); // Open for reading + auto range = file.byLine(); + // Print first three lines + foreach (line; range.take(3)) + writeln(line); + // Print remaining lines beginning with '#' + foreach (line; range) { - ++lineCount; + if (!line.empty && line[0] == '#') + writeln(line); } - writeln("Lines in file: ", lineCount); } ---- +Notice that neither example accesses the line data returned by +$(D front) after the corresponding $(D popFront) call is made (because +the contents may well have changed). */ - struct ByLine(Char, Terminator) - { - File file; - Char[] line; - Terminator terminator; - KeepTerminator keepTerminator; - bool first_call = true; - - this(File f, KeepTerminator kt = KeepTerminator.no, - Terminator terminator = '\n') - { - file = f; - this.terminator = terminator; - keepTerminator = kt; - } - - /// Range primitive implementations. - @property bool empty() const - { - if (line !is null) return false; - if (!file.isOpen) return true; - - // First read ever, must make sure stream is not empty. We - // do so by reading a character and putting it back. Doing - // so is guaranteed to work on all files opened in all - // buffering modes. Although we internally mutate the - // state of the file, we restore everything, which - // justifies the cast. - auto mutableFP = (cast(File*) &file).getFP(); - auto c = fgetc(mutableFP); - if (c == -1) - { - return true; - } - ungetc(c, mutableFP) == c - || assert(false, "Bug in cstdlib implementation"); - return false; - } - - /// Ditto - @property Char[] front() - { - if (first_call) - { - popFront(); - first_call = false; - } - return line; - } - - /// Ditto - void popFront() - { - assert(file.isOpen); - assumeSafeAppend(line); - file.readln(line, terminator); - if (line.empty) - { - file.detach(); - line = null; - } - else if (keepTerminator == KeepTerminator.no - && std.algorithm.endsWith(line, terminator)) - { - line = line.ptr[0 .. line.length - 1]; - } - } - } - -/** -Convenience function that returns the $(D LinesReader) corresponding -to this file. */ - ByLine!(Char, Terminator) byLine(Terminator = char, Char = char) + auto byLine(Terminator = char, Char = char) (KeepTerminator keepTerminator = KeepTerminator.no, Terminator terminator = '\n') + if (isScalarType!Terminator) { - return typeof(return)(this, keepTerminator, terminator); + return ByLine!(Char, Terminator)(this, keepTerminator, terminator); + } + +/// ditto + auto byLine(Terminator, Char = char) + (KeepTerminator keepTerminator, Terminator terminator) + if (is(Unqual!(ElementEncodingType!Terminator) == Char)) + { + return ByLine!(Char, Terminator)(this, keepTerminator, terminator); } unittest @@ -1181,11 +1280,11 @@ to this file. */ { assert(false); } - f.close(); + f.detach(); + assert(!f.isOpen); - void test(string txt, string[] witness, - KeepTerminator kt = KeepTerminator.no, - bool popFirstLine = false) + void testTerm(Terminator)(string txt, string[] witness, + KeepTerminator kt, Terminator term, bool popFirstLine) { uint i; std.file.write(deleteme, txt); @@ -1195,30 +1294,72 @@ to this file. */ f.close(); assert(!f.isOpen); } - auto lines = f.byLine(kt); + auto lines = f.byLine(kt, term); if (popFirstLine) { lines.popFront(); i = 1; } + assert(lines.empty || lines.front is lines.front); foreach (line; lines) { assert(line == witness[i++]); } assert(i == witness.length, text(i, " != ", witness.length)); } + /* Wrap with default args. + * Note: Having a default argument for terminator = '\n' would prevent + * instantiating Terminator=string (or "\n" would prevent Terminator=char) */ + void test(string txt, string[] witness, + KeepTerminator kt = KeepTerminator.no, + bool popFirstLine = false) + { + testTerm(txt, witness, kt, '\n', popFirstLine); + } test("", null); test("\n", [ "" ]); test("asd\ndef\nasdf", [ "asd", "def", "asdf" ]); test("asd\ndef\nasdf", [ "asd", "def", "asdf" ], KeepTerminator.no, true); test("asd\ndef\nasdf\n", [ "asd", "def", "asdf" ]); + test("foo", [ "foo" ], KeepTerminator.no, true); + testTerm("bob\r\nmarge\r\nsteve\r\n", ["bob", "marge", "steve"], + KeepTerminator.no, "\r\n", false); + testTerm("sue\r", ["sue"], KeepTerminator.no, '\r', false); test("", null, KeepTerminator.yes); test("\n", [ "\n" ], KeepTerminator.yes); test("asd\ndef\nasdf", [ "asd\n", "def\n", "asdf" ], KeepTerminator.yes); test("asd\ndef\nasdf\n", [ "asd\n", "def\n", "asdf\n" ], KeepTerminator.yes); test("asd\ndef\nasdf\n", [ "asd\n", "def\n", "asdf\n" ], KeepTerminator.yes, true); + test("foo", [ "foo" ], KeepTerminator.yes, false); + testTerm("bob\r\nmarge\r\nsteve\r\n", ["bob\r\n", "marge\r\n", "steve\r\n"], + KeepTerminator.yes, "\r\n", false); + testTerm("sue\r", ["sue\r"], KeepTerminator.yes, '\r', false); + + auto file = File.tmpfile(); + file.write("1\n2\n3\n"); + + // bug 9599 + file.rewind(); + File.ByLine!(char, char) fbl = file.byLine(); + auto fbl2 = fbl; + assert(fbl.front == "1"); + assert(fbl.front is fbl2.front); + assert(fbl.take(1).equal(["1"])); + assert(fbl.equal(["2", "3"])); + assert(fbl.empty); + assert(file.isOpen); // we still have a valid reference + + file.rewind(); + fbl = file.byLine(); + assert(!fbl.drop(2).empty); + assert(fbl.equal(["3"])); + assert(fbl.empty); + assert(file.isOpen); + + file.detach(); + assert(!file.isOpen); } template byRecord(Fields...) @@ -1248,7 +1389,8 @@ to this file. */ } - /** + // Note: This was documented until 2013/08 + /* * Range that reads a chunk at a time. */ struct ByChunk @@ -1302,10 +1444,17 @@ to this file. */ } /** -Iterates through a file a chunk at a time by using $(D foreach). +Returns an input range set up to read from the file handle a chunk at a +time. + +The element type for the range will be $(D ubyte[]). Range primitives +may throw $(D StdioException) on I/O error. + +Note: Each $(D front) will not persist after $(D +popFront) is called, so the caller must copy its contents (e.g. by +calling $(D buffer.dup)) if retention is needed. Example: - --------- void main() { @@ -1315,15 +1464,22 @@ void main() } } --------- - The content of $(D buffer) is reused across calls. In the example above, $(D buffer.length) is 4096 for all iterations, except for the last one, in which case $(D buffer.length) may be less than 4096 (but always greater than zero). -In case of an I/O error, an $(D StdioException) is thrown. +Example: +--- +import std.algorithm, std.stdio; + +void main() +{ + stdin.byChunk(1024).copy(stdout.lockingTextWriter()); +} +--- */ - ByChunk byChunk(size_t chunkSize) + auto byChunk(size_t chunkSize) { return ByChunk(this, chunkSize); } @@ -1351,7 +1507,8 @@ In case of an I/O error, an $(D StdioException) is thrown. assert(i == witness.length); } -/** +// Note: This was documented until 2013/08 +/* $(D Range) that locks the file and allows fast writing to it. */ struct LockingTextWriter @@ -1371,15 +1528,20 @@ $(D Range) that locks the file and allows fast writing to it. ~this() { - FUNLOCK(fps); - fps = null; - handle = null; + if(fps) + { + FUNLOCK(fps); + fps = null; + handle = null; + } } this(this) { - enforce(fps); - FLOCK(fps); + if(fps) + { + FLOCK(fps); + } } /// Range primitive implementations. @@ -1485,8 +1647,11 @@ $(D Range) that locks the file and allows fast writing to it. } } -/// Convenience function. - @property LockingTextWriter lockingTextWriter() +/** Returns an output range that locks the file and allows fast writing to it. + +See $(LREF byChunk) for an example. +*/ + auto lockingTextWriter() { return LockingTextWriter(this); } @@ -1739,7 +1904,8 @@ void writeln(T...)(T args) } else static if (T.length == 1 && is(typeof(args[0]) : const(char)[]) && - !is(typeof(args[0]) == enum) && !is(typeof(args[0]) == typeof(null)) && + !is(typeof(args[0]) == enum) && + !is(Unqual!(typeof(args[0])) == typeof(null)) && !isAggregateType!(typeof(args[0]))) { // Specialization for strings - a very frequent case @@ -1841,6 +2007,19 @@ unittest "A\nB\nA\nB\nA\nB\nA\nB\n"); } +unittest +{ + static auto useInit(T)(T ltw) + { + T val; + val = ltw; + val = T.init; + return val; + } + useInit(stdout.lockingTextWriter()); +} + + /*********************************** * If the first argument $(D args[0]) is a $(D FILE*), use * $(LINK2 std_format.html#format-string, the format specifier) in @@ -1975,40 +2154,102 @@ unittest } /********************************** - * Read line from stream $(D fp). + * Read line from $(D stdin). + * + * This version manages its own read buffer, which means one memory allocation per call. If you are not + * retaining a reference to the read data, consider the $(D readln(buf)) version, which may offer + * better performance as it can reuse its read buffer. + * * Returns: - * $(D null) for end of file, - * $(D char[]) for line read from $(D fp), including terminating character + * The line that was read, including the line terminator character. * Params: - * $(D fp) = input stream - * $(D terminator) = line terminator, '\n' by default + * S = Template parameter; the type of the allocated buffer, and the type returned. Defaults to $(D string). + * terminator = line terminator (by default, '\n') * Throws: - * $(D StdioException) on error + * $(D StdioException) on I/O error, or $(D UnicodeException) on Unicode conversion error. * Example: * Reads $(D stdin) and writes it to $(D stdout). --- import std.stdio; -int main() +void main() { - string buf; - while ((buf = stdin.readln()) !is null) - write(buf); - return 0; + string line; + while ((line = readln()) !is null) + write(line); } --- */ -string readln(dchar terminator = '\n') +S readln(S = string)(dchar terminator = '\n') +if (isSomeString!S) { - return stdin.readln(terminator); + return stdin.readln!S(terminator); +} + +/********************************** + * Read line from $(D stdin) and write it to buf[], including terminating character. + * + * This can be faster than $(D line = readln()) because you can reuse + * the buffer for each call. Note that reusing the buffer means that you + * must copy the previous contents if you wish to retain them. + * + * Returns: + * $(D size_t) 0 for end of file, otherwise number of characters read + * Params: + * buf = Buffer used to store the resulting line data. buf is resized as necessary. + * terminator = line terminator (by default, '\n') + * Throws: + * $(D StdioException) on I/O error, or $(D UnicodeException) on Unicode conversion error. + * Example: + * Reads $(D stdin) and writes it to $(D stdout). +--- +import std.stdio; + +void main() +{ + char[] buf; + while (readln(buf)) + write(buf); +} +--- +*/ +size_t readln(C)(ref C[] buf, dchar terminator = '\n') +if (isSomeChar!C && is(Unqual!C == C) && !is(C == enum)) +{ + return stdin.readln(buf, terminator); } /** ditto */ -size_t readln(ref char[] buf, dchar terminator = '\n') +size_t readln(C, R)(ref C[] buf, R terminator) +if (isSomeChar!C && is(Unqual!C == C) && !is(C == enum) && + isBidirectionalRange!R && is(typeof(terminator.front == dchar.init))) { return stdin.readln(buf, terminator); } +unittest +{ + //we can't actually test readln, so at the very least, + //we test compilability + void foo() + { + readln(); + readln('\t'); + foreach (String; TypeTuple!(string, char[], wstring, wchar[], dstring, dchar[])) + { + readln!String(); + readln!String('\t'); + } + foreach (String; TypeTuple!(char[], wchar[], dchar[])) + { + String buf; + readln(buf); + readln(buf, '\t'); + readln(buf, "
"); + } + } +} + /* * Convenience function that forwards to $(D core.stdc.stdio.fopen) * (to $(D _wfopen) on Windows) @@ -2328,18 +2569,17 @@ unittest } /** -Iterates through a file a chunk at a time by using $(D -foreach). +Iterates through a file a chunk at a time by using $(D foreach). Example: --------- void main() { - foreach (ubyte[] buffer; chunks(stdin, 4096)) - { - ... use buffer ... - } + foreach (ubyte[] buffer; chunks(stdin, 4096)) + { + ... use buffer ... + } } --------- @@ -2350,8 +2590,11 @@ The content of $(D buffer) is reused across calls. In the In case of an I/O error, an $(D StdioException) is thrown. */ - -struct chunks +auto chunks(File f, size_t size) +{ + return ChunksImpl(f, size); +} +private struct ChunksImpl { private File f; private size_t size; @@ -2379,7 +2622,7 @@ struct chunks int opApply(D)(scope D dg) { - const maxStackSize = 1024 * 16; + enum maxStackSize = 1024 * 16; ubyte[] buffer = void; if (size < maxStackSize) buffer = (cast(ubyte*) alloca(size))[0 .. size]; @@ -2411,7 +2654,7 @@ struct chunks unittest { - //printf("Entering test at line %d\n", __LINE__); + //printf("Entering test at line %d\n", __LINE__); scope(failure) printf("Failed test at line %d\n", __LINE__); auto deleteme = testFilename(); scope(exit) { std.file.remove(deleteme); } @@ -2454,6 +2697,8 @@ Initialize with a message and an error code. */ errno = e; version (Posix) { + import std.c.string : strerror_r; + char[256] buf = void; version (linux) { @@ -2467,13 +2712,13 @@ Initialize with a message and an error code. */ } else { - auto s = std.c.string.strerror(errno); + auto s = core.stdc.string.strerror(errno); } auto sysmsg = to!string(s); // If e is 0, we don't use the system error message. (The message // is "Success", which is rather pointless for an exception.) super(e == 0 ? message - : (message ? message ~ " (" ~ sysmsg ~ ")" : sysmsg)); + : (message.ptr ? message ~ " (" ~ sysmsg ~ ")" : sysmsg)); } /** Convenience functions that throw an $(D StdioException). */ @@ -2905,18 +3150,22 @@ private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator = '\n') Bugs: Only works on Linux */ -version(linux) { +version(linux) +{ static import linux = std.c.linux.linux; static import sock = std.c.linux.socket; + import core.stdc.string : memcpy; - File openNetwork(string host, ushort port) { + File openNetwork(string host, ushort port) + { auto h = enforce( sock.gethostbyname(std.string.toStringz(host)), new StdioException("gethostbyname")); int s = sock.socket(sock.AF_INET, sock.SOCK_STREAM, 0); enforce(s != -1, new StdioException("socket")); - scope(failure) { + scope(failure) + { linux.close(s); // want to make sure it doesn't dangle if // something throws. Upon normal exit, the // File struct's reference counting takes @@ -2928,7 +3177,7 @@ version(linux) { addr.sin_family = sock.AF_INET; addr.sin_port = sock.htons(port); - std.c.string.memcpy(&addr.sin_addr.s_addr, h.h_addr, h.h_length); + core.stdc.string.memcpy(&addr.sin_addr.s_addr, h.h_addr, h.h_length); enforce(sock.connect(s, cast(sock.sockaddr*) &addr, addr.sizeof) != -1, new StdioException("Connect failed")); diff --git a/std/stream.d b/std/stream.d index 3483947c7..fdf6cc412 100644 --- a/std/stream.d +++ b/std/stream.d @@ -84,10 +84,7 @@ private { import std.utf; import core.bitop; // for bswap import core.vararg; -} - -version (Windows) { - private import std.file; + import std.file; } /// InputStream is the interface for readable streams. @@ -1167,10 +1164,7 @@ class Stream : InputStream, OutputStream { // returns number of bytes written version (Win64) size_t printf(const(char)[] format, ...) { - va_list ap; - ap = cast(va_list) &format; - ap += format.sizeof; - return vprintf(format, ap); + return vprintf(format, _argptr); } else version (X86_64) size_t printf(const(char)[] format, ...) { diff --git a/std/string.d b/std/string.d index e2cc0772c..3da1ec273 100644 --- a/std/string.d +++ b/std/string.d @@ -24,11 +24,12 @@ Source: $(PHOBOSSRC std/_string.d) module std.string; //debug=string; // uncomment to turn on debugging printf's +debug(string) import core.stdc.stdio; import core.exception : RangeError, onRangeError; import core.vararg, core.stdc.stdlib, core.stdc.string, std.algorithm, std.ascii, std.conv, std.exception, std.format, std.functional, - std.range, std.regex, std.traits, + std.range, std.traits, std.typecons, std.typetuple, std.uni, std.utf; //Remove when repeat is finally removed. They're only here as part of the @@ -61,7 +62,7 @@ class StringException : Exception this(string msg, string file = __FILE__, size_t line = __LINE__, - Throwable next = null) + Throwable next = null) @safe pure nothrow { super(msg, file, line, next); } @@ -71,90 +72,22 @@ class StringException : Exception /++ Compares two ranges of characters lexicographically. The comparison is case insensitive. Use $(XREF algorithm, cmp) for a case sensitive - comparison. icmp works like $(XREF algorithm, cmp) except that it - converts characters to lowercase prior to applying $(D pred). Technically, - $(D icmp(r1, r2)) is equivalent to - $(D cmp!"std.uni.toLower(a) < std.uni.toLower(b)"(r1, r2)). + comparison. For details see $(XREF uni, icmp). $(BOOKTABLE, $(TR $(TD $(D < 0)) $(TD $(D s1 < s2) )) $(TR $(TD $(D = 0)) $(TD $(D s1 == s2))) $(TR $(TD $(D > 0)) $(TD $(D s1 > s2))) ) - +/ -int icmp(alias pred = "a < b", S1, S2)(S1 s1, S2 s2) - if(isSomeString!S1 && isSomeString!S2) -{ - static if(is(typeof(pred) : string)) - enum isLessThan = pred == "a < b"; - else - enum isLessThan = false; - - size_t i, j; - while(i < s1.length && j < s2.length) - { - immutable c1 = std.uni.toLower(decode(s1, i)); - immutable c2 = std.uni.toLower(decode(s2, j)); - - static if(isLessThan) - { - if(c1 != c2) - { - if(c1 < c2) return -1; - if(c1 > c2) return 1; - } - } - else - { - if(binaryFun!pred(c1, c2)) return -1; - if(binaryFun!pred(c2, c1)) return 1; - } - } - - if(i < s1.length) return 1; - if(j < s2.length) return -1; - - return 0; -} - -int icmp(alias pred = "a < b", S1, S2)(S1 s1, S2 s2) - if(!(isSomeString!S1 && isSomeString!S2) && - isForwardRange!S1 && is(Unqual!(ElementType!S1) == dchar) && - isForwardRange!S2 && is(Unqual!(ElementType!S2) == dchar)) -{ - static if(is(typeof(pred) : string)) - enum isLessThan = pred == "a < b"; - else - enum isLessThan = false; - - for(;; s1.popFront(), s2.popFront()) - { - if(s1.empty) return s2.empty ? 0 : -1; - if(s2.empty) return 1; - - immutable c1 = std.uni.toLower(s1.front); - immutable c2 = std.uni.toLower(s2.front); - - static if(isLessThan) - { - if(c1 != c2) - { - if(c1 < c2) return -1; - if(c1 > c2) return 1; - } - } - else - { - if(binaryFun!pred(c1, c2)) return -1; - if(binaryFun!pred(c2, c1)) return 1; - } - } -} ++/ +alias icmp = std.uni.icmp; unittest { debug(string) printf("string.icmp.unittest\n"); + assertCTFEable!( + { assert(icmp("Ü", "ü") == 0, "Über failure"); assert(icmp("abc", "abc") == 0); assert(icmp("ABC", "abc") == 0); @@ -200,6 +133,7 @@ unittest assert(icmp("\u0430\u0410\u0543"d, filter!"true"("\u0430\u0410\u0544")) < 0); assert(icmp(filter!"true"("\u0430\u0411\u0543"d), filter!"true"("\u0430\u0411\u0543\u0237")) < 0); assert(icmp(filter!"true"("\u0430\u0411\u0543\u0237"d), filter!"true"("\u0430\u0411\u0543")) > 0); + }); } @@ -280,9 +214,12 @@ unittest { debug(string) printf("string.toStringz.unittest\n"); + // TODO: CTFEable toStringz is really necessary? + //assertCTFEable!( + //{ auto p = toStringz("foo"); assert(strlen(p) == 3); - const(char) foo[] = "abbzxyzzy"; + const(char)[] foo = "abbzxyzzy"; p = toStringz(foo[3..5]); assert(strlen(p) == 2); @@ -297,6 +234,7 @@ unittest test = "foo\0"; p = toStringz(test); assert(p[0] == 'f' && p[1] == 'o' && p[2] == 'o' && p[3] == 0); + //}); } @@ -313,18 +251,19 @@ enum CaseSensitive { no, yes } +/ ptrdiff_t indexOf(Char)(in Char[] s, dchar c, - CaseSensitive cs = CaseSensitive.yes) pure - if(isSomeChar!Char) + CaseSensitive cs = CaseSensitive.yes) @safe pure + if (isSomeChar!Char) { if (cs == CaseSensitive.yes) { static if (Char.sizeof == 1) { - if (std.ascii.isASCII(c)) + if (std.ascii.isASCII(c) && !__ctfe) { // Plain old ASCII - auto p = cast(char*)memchr(s.ptr, c, s.length); + auto trustedmemchr() @trusted { return cast(Char*)memchr(s.ptr, c, s.length); } + auto p = trustedmemchr(); if (p) - return p - cast(char *)s; + return p - s.ptr; else return -1; } @@ -369,6 +308,8 @@ unittest { debug(string) printf("string.indexOf.unittest\n"); + assertCTFEable!( + { foreach (S; TypeTuple!(string, wstring, dstring)) { assert(indexOf(cast(S)null, cast(dchar)'a') == -1); @@ -380,6 +321,7 @@ unittest assert(indexOf(to!S("def"), cast(dchar)'a', CaseSensitive.no) == -1); assert(indexOf(to!S("Abba"), cast(dchar)'a', CaseSensitive.no) == 0); assert(indexOf(to!S("def"), cast(dchar)'F', CaseSensitive.no) == 2); + assert(indexOf(to!S("ödef"), 'ö', CaseSensitive.no) == 0); S sPlts = "Mars: the fourth Rock (Planet) from the Sun."; assert(indexOf("def", cast(char)'f', CaseSensitive.no) == 2); @@ -387,12 +329,78 @@ unittest assert(indexOf(sPlts, cast(char)'R', CaseSensitive.no) == 2); } - foreach(cs; EnumMembers!CaseSensitive) + foreach (cs; EnumMembers!CaseSensitive) { assert(indexOf("hello\U00010143\u0100\U00010143", '\u0100', cs) == 9); assert(indexOf("hello\U00010143\u0100\U00010143"w, '\u0100', cs) == 7); assert(indexOf("hello\U00010143\u0100\U00010143"d, '\u0100', cs) == 6); } + }); +} + +/++ + Returns the index of the first occurence of $(D c) in $(D s) with respect + to the start index $(D startIdx). If $(D c) is not found, then $(D -1) is + returned. If $(D c) is found the value of the returned index is at least + $(D startIdx). $(D startIdx) represents a codeunit index in $(D s). If the + sequence starting at $(D startIdx) does not represent a well formed codepoint, + then a $(XREF utf,UTFException) may be thrown. + + $(D cs) indicates whether the comparisons are case sensitive. + +/ +ptrdiff_t indexOf(Char)(const(Char)[] s, dchar c, const size_t startIdx, + CaseSensitive cs = CaseSensitive.yes) @safe pure + if (isSomeChar!Char) +{ + if (startIdx < s.length) + { + ptrdiff_t foundIdx = indexOf(s[startIdx .. $], c, cs); + if (foundIdx != -1) + { + return foundIdx + cast(ptrdiff_t)startIdx; + } + } + return -1; +} + +unittest +{ + debug(string) printf("string.indexOf(startIdx).unittest\n"); + + foreach (S; TypeTuple!(string, wstring, dstring)) + { + assert(indexOf(cast(S)null, cast(dchar)'a', 1) == -1); + assert(indexOf(to!S("def"), cast(dchar)'a', 1) == -1); + assert(indexOf(to!S("abba"), cast(dchar)'a', 1) == 3); + assert(indexOf(to!S("def"), cast(dchar)'f', 1) == 2); + + assert((to!S("def")).indexOf(cast(dchar)'a', 1, + CaseSensitive.no) == -1); + assert(indexOf(to!S("def"), cast(dchar)'a', 1, + CaseSensitive.no) == -1); + assert(indexOf(to!S("def"), cast(dchar)'a', 12, + CaseSensitive.no) == -1); + assert(indexOf(to!S("AbbA"), cast(dchar)'a', 2, + CaseSensitive.no) == 3); + assert(indexOf(to!S("def"), cast(dchar)'F', 2, CaseSensitive.no) == 2); + + S sPlts = "Mars: the fourth Rock (Planet) from the Sun."; + assert(indexOf("def", cast(char)'f', cast(uint)2, + CaseSensitive.no) == 2); + assert(indexOf(sPlts, cast(char)'P', 12, CaseSensitive.no) == 23); + assert(indexOf(sPlts, cast(char)'R', cast(ulong)1, + CaseSensitive.no) == 2); + } + + foreach(cs; EnumMembers!CaseSensitive) + { + assert(indexOf("hello\U00010143\u0100\U00010143", '\u0100', 2, cs) + == 9); + assert(indexOf("hello\U00010143\u0100\U00010143"w, '\u0100', 3, cs) + == 7); + assert(indexOf("hello\U00010143\u0100\U00010143"d, '\u0100', 6, cs) + == 6); + } } /++ @@ -404,7 +412,7 @@ unittest ptrdiff_t indexOf(Char1, Char2)(const(Char1)[] s, const(Char2)[] sub, CaseSensitive cs = CaseSensitive.yes) - if(isSomeChar!Char1 && isSomeChar!Char2) + if (isSomeChar!Char1 && isSomeChar!Char2) { const(Char1)[] balance; if (cs == CaseSensitive.yes) @@ -414,7 +422,7 @@ ptrdiff_t indexOf(Char1, Char2)(const(Char1)[] s, else { balance = std.algorithm.find! - ((dchar a, dchar b){return std.uni.toLower(a) == std.uni.toLower(b);}) + ((a, b) => std.uni.toLower(a) == std.uni.toLower(b)) (s, sub); } return balance.empty ? -1 : balance.ptr - s.ptr; @@ -424,9 +432,11 @@ unittest { debug(string) printf("string.indexOf.unittest\n"); - foreach(S; TypeTuple!(string, wstring, dstring)) + assertCTFEable!( { - foreach(T; TypeTuple!(string, wstring, dstring)) + foreach (S; TypeTuple!(string, wstring, dstring)) + { + foreach (T; TypeTuple!(string, wstring, dstring)) { assert(indexOf(cast(S)null, to!T("a")) == -1); assert(indexOf(to!S("def"), to!T("a")) == -1); @@ -459,15 +469,98 @@ unittest to!T("page-break-before"), CaseSensitive.no) == -1); } - foreach(cs; EnumMembers!CaseSensitive) + foreach (cs; EnumMembers!CaseSensitive) { assert(indexOf("hello\U00010143\u0100\U00010143", to!S("\u0100"), cs) == 9); assert(indexOf("hello\U00010143\u0100\U00010143"w, to!S("\u0100"), cs) == 7); assert(indexOf("hello\U00010143\u0100\U00010143"d, to!S("\u0100"), cs) == 6); } } + }); } +/++ + Returns the index of the first occurence of $(D sub) in $(D s) with + respect to the start index $(D startIdx). If $(D sub) is not found, then + $(D -1) is returned. If $(D sub) is found the value of the returned index + is at least $(D startIdx). $(D startIdx) represents a codeunit index in + $(D s). If the sequence starting at $(D startIdx) does not represent a well + formed codepoint, then a $(XREF utf,UTFException) may be thrown. + + $(D cs) indicates whether the comparisons are case sensitive. + +/ +ptrdiff_t indexOf(Char1, Char2)(const(Char1)[] s, const(Char2)[] sub, + const size_t startIdx, CaseSensitive cs = CaseSensitive.yes) + if (isSomeChar!Char1 && isSomeChar!Char2) +{ + if (startIdx < s.length) + { + ptrdiff_t foundIdx = indexOf(s[startIdx .. $], sub, cs); + if (foundIdx != -1) + { + return foundIdx + cast(ptrdiff_t)startIdx; + } + } + return -1; +} + +unittest +{ + debug(string) printf("string.indexOf(startIdx).unittest\n"); + + foreach(S; TypeTuple!(string, wstring, dstring)) + { + foreach(T; TypeTuple!(string, wstring, dstring)) + { + assert(indexOf(cast(S)null, to!T("a"), 1337) == -1); + assert(indexOf(to!S("def"), to!T("a"), 0) == -1); + assert(indexOf(to!S("abba"), to!T("a"), 2) == 3); + assert(indexOf(to!S("def"), to!T("f"), 1) == 2); + assert(indexOf(to!S("dfefffg"), to!T("fff"), 1) == 3); + assert(indexOf(to!S("dfeffgfff"), to!T("fff"), 5) == 6); + + assert(indexOf(to!S("dfeffgfff"), to!T("a"), 1, CaseSensitive.no) == -1); + assert(indexOf(to!S("def"), to!T("a"), 2, CaseSensitive.no) == -1); + assert(indexOf(to!S("abba"), to!T("a"), 3, CaseSensitive.no) == 3); + assert(indexOf(to!S("def"), to!T("f"), 1, CaseSensitive.no) == 2); + assert(indexOf(to!S("dfefffg"), to!T("fff"), 2, CaseSensitive.no) == 3); + assert(indexOf(to!S("dfeffgfff"), to!T("fff"), 4, CaseSensitive.no) == 6); + assert(indexOf(to!S("dfeffgffföä"), to!T("öä"), 9, CaseSensitive.no) == 9, + to!string(indexOf(to!S("dfeffgffföä"), to!T("öä"), 9, CaseSensitive.no)) + ~ " " ~ S.stringof ~ " " ~ T.stringof); + + S sPlts = "Mars: the fourth Rock (Planet) from the Sun."; + S sMars = "Who\'s \'My Favorite Maritian?\'"; + + assert(indexOf(sMars, to!T("MY fAVe"), 10, + CaseSensitive.no) == -1); + assert(indexOf(sMars, to!T("mY fAVOriTe"), 4, CaseSensitive.no) == 7); + assert(indexOf(sPlts, to!T("mArS:"), 0, CaseSensitive.no) == 0); + assert(indexOf(sPlts, to!T("rOcK"), 12, CaseSensitive.no) == 17); + assert(indexOf(sPlts, to!T("Un."), 32, CaseSensitive.no) == 41); + assert(indexOf(sPlts, to!T(sPlts), 0, CaseSensitive.no) == 0); + + assert(indexOf("\u0100", to!T("\u0100"), 0, CaseSensitive.no) == 0); + + // Thanks to Carlos Santander B. and zwang + assert(indexOf("sus mejores cortesanos. Se embarcaron en el puerto de Dubai y", + to!T("page-break-before"), 10, CaseSensitive.no) == -1); + + // In order for indexOf with and without index to be consistent + assert(indexOf(to!S(""), to!T("")) == indexOf(to!S(""), to!T(""), 0)); + } + + foreach(cs; EnumMembers!CaseSensitive) + { + assert(indexOf("hello\U00010143\u0100\U00010143", to!S("\u0100"), + 3, cs) == 9); + assert(indexOf("hello\U00010143\u0100\U00010143"w, to!S("\u0100"), + 3, cs) == 7); + assert(indexOf("hello\U00010143\u0100\U00010143"d, to!S("\u0100"), + 3, cs) == 6); + } + } +} /++ Returns the index of the last occurence of $(D c) in $(D s). If $(D c) @@ -477,55 +570,58 @@ unittest +/ ptrdiff_t lastIndexOf(Char)(const(Char)[] s, dchar c, - CaseSensitive cs = CaseSensitive.yes) - if(isSomeChar!Char) + CaseSensitive cs = CaseSensitive.yes) @safe pure + if (isSomeChar!Char) { - if(cs == CaseSensitive.yes) + if (cs == CaseSensitive.yes) { - if(cast(dchar)(cast(Char)c) == c) + if (canSearchInCodeUnits!Char(c)) { - for(auto i = s.length; i-- != 0;) + foreach_reverse (i, it; s) { - if(s[i] == c) - return cast(ptrdiff_t)i; + if (it == c) + { + return i; + } } } else { - for(size_t i = s.length; !s.empty;) + foreach_reverse (i, dchar it; s) { - if(s.back == c) - return cast(ptrdiff_t)i - codeLength!Char(c); - - i -= strideBack(s, i); - s = s[0 .. i]; + if (it == c) + { + return i; + } } } } else { - if(std.ascii.isASCII(c)) + if (std.ascii.isASCII(c)) { immutable c1 = std.ascii.toLower(c); - for(auto i = s.length; i-- != 0;) + foreach_reverse (i, it; s) { - immutable c2 = std.ascii.toLower(s[i]); - if(c1 == c2) - return cast(ptrdiff_t)i; + immutable c2 = std.ascii.toLower(it); + if (c1 == c2) + { + return i; + } } } else { immutable c1 = std.uni.toLower(c); - for(size_t i = s.length; !s.empty;) + foreach_reverse (i, dchar it; s) { - if(std.uni.toLower(s.back) == c1) - return cast(ptrdiff_t)i - codeLength!Char(c); - - i -= strideBack(s, i); - s = s[0 .. i]; + immutable c2 = std.uni.toLower(it); + if (c1 == c2) + { + return i; + } } } } @@ -533,6 +629,66 @@ ptrdiff_t lastIndexOf(Char)(const(Char)[] s, return -1; } +unittest +{ + debug(string) printf("string.lastIndexOf.unittest\n"); + + assertCTFEable!( + { + foreach (S; TypeTuple!(string, wstring, dstring)) + { + assert(lastIndexOf(cast(S) null, 'a') == -1); + assert(lastIndexOf(to!S("def"), 'a') == -1); + assert(lastIndexOf(to!S("abba"), 'a') == 3); + assert(lastIndexOf(to!S("def"), 'f') == 2); + assert(lastIndexOf(to!S("ödef"), 'ö') == 0); + + assert(lastIndexOf(cast(S) null, 'a', CaseSensitive.no) == -1); + assert(lastIndexOf(to!S("def"), 'a', CaseSensitive.no) == -1); + assert(lastIndexOf(to!S("AbbA"), 'a', CaseSensitive.no) == 3); + assert(lastIndexOf(to!S("def"), 'F', CaseSensitive.no) == 2); + assert(lastIndexOf(to!S("ödef"), 'ö', CaseSensitive.no) == 0); + assert(lastIndexOf(to!S("i\u0100def"), to!dchar("\u0100"), + CaseSensitive.no) == 1); + + S sPlts = "Mars: the fourth Rock (Planet) from the Sun."; + + assert(lastIndexOf(to!S("def"), 'f', CaseSensitive.no) == 2); + assert(lastIndexOf(sPlts, 'M', CaseSensitive.no) == 34); + assert(lastIndexOf(sPlts, 'S', CaseSensitive.no) == 40); + } + + foreach (cs; EnumMembers!CaseSensitive) + { + assert(lastIndexOf("\U00010143\u0100\U00010143hello", '\u0100', cs) == 4); + assert(lastIndexOf("\U00010143\u0100\U00010143hello"w, '\u0100', cs) == 2); + assert(lastIndexOf("\U00010143\u0100\U00010143hello"d, '\u0100', cs) == 1); + } + }); +} + +/++ + Returns the index of the last occurence of $(D c) in $(D s). If $(D c) is + not found, then $(D -1) is returned. The $(D startIdx) slices $(D s) in + the following way $(D s[0 .. startIdx]). $(D startIdx) represents a + codeunit index in $(D s). If the sequence ending at $(D startIdx) does not + represent a well formed codepoint, then a $(XREF utf,UTFException) may be + thrown. + + $(D cs) indicates whether the comparisons are case sensitive. + +/ +ptrdiff_t lastIndexOf(Char)(const(Char)[] s, dchar c, const size_t startIdx, + CaseSensitive cs = CaseSensitive.yes) @safe pure + if (isSomeChar!Char) +{ + if (startIdx <= s.length) + { + return lastIndexOf(s[0u .. startIdx], c, cs); + } + + return -1; +} + unittest { debug(string) printf("string.lastIndexOf.unittest\n"); @@ -541,19 +697,20 @@ unittest { assert(lastIndexOf(cast(S) null, 'a') == -1); assert(lastIndexOf(to!S("def"), 'a') == -1); - assert(lastIndexOf(to!S("abba"), 'a') == 3); - assert(lastIndexOf(to!S("def"), 'f') == 2); + assert(lastIndexOf(to!S("abba"), 'a', 3) == 0); + assert(lastIndexOf(to!S("deff"), 'f', 3) == 2); assert(lastIndexOf(cast(S) null, 'a', CaseSensitive.no) == -1); assert(lastIndexOf(to!S("def"), 'a', CaseSensitive.no) == -1); - assert(lastIndexOf(to!S("AbbA"), 'a', CaseSensitive.no) == 3); - assert(lastIndexOf(to!S("def"), 'F', CaseSensitive.no) == 2); + assert(lastIndexOf(to!S("AbbAa"), 'a', to!ushort(4), CaseSensitive.no) == 3, + to!string(lastIndexOf(to!S("AbbAa"), 'a', 4, CaseSensitive.no))); + assert(lastIndexOf(to!S("def"), 'F', 3, CaseSensitive.no) == 2); S sPlts = "Mars: the fourth Rock (Planet) from the Sun."; - assert(lastIndexOf(to!S("def"), 'f', CaseSensitive.no) == 2); - assert(lastIndexOf(sPlts, 'M', CaseSensitive.no) == 34); - assert(lastIndexOf(sPlts, 'S', CaseSensitive.no) == 40); + assert(lastIndexOf(to!S("def"), 'f', 4, CaseSensitive.no) == -1); + assert(lastIndexOf(sPlts, 'M', sPlts.length -2, CaseSensitive.no) == 34); + assert(lastIndexOf(sPlts, 'S', sPlts.length -2, CaseSensitive.no) == 40); } foreach(cs; EnumMembers!CaseSensitive) @@ -572,32 +729,51 @@ unittest +/ ptrdiff_t lastIndexOf(Char1, Char2)(const(Char1)[] s, const(Char2)[] sub, - CaseSensitive cs = CaseSensitive.yes) - if(isSomeChar!Char1 && isSomeChar!Char2) + CaseSensitive cs = CaseSensitive.yes) @safe pure + if (isSomeChar!Char1 && isSomeChar!Char2) { - if(sub.empty) + if (sub.empty) return s.length; - if(walkLength(sub) == 1) + if (walkLength(sub) == 1) return lastIndexOf(s, sub.front, cs); - if(cs == CaseSensitive.yes) + if (cs == CaseSensitive.yes) { - static if(is(Unqual!Char1 == Unqual!Char2)) + static if (is(Unqual!Char1 == Unqual!Char2)) { immutable c = sub[0]; - for(ptrdiff_t i = s.length - sub.length; i >= 0; --i) + for (ptrdiff_t i = s.length - sub.length; i >= 0; --i) { - if(s[i] == c && memcmp(&s[i + 1], &sub[1], sub.length - 1) == 0) - return i; + if (s[i] == c) + { + if (__ctfe) + { + foreach (j; 1 .. sub.length) + { + if (s[i + j] != sub[j]) + continue; + } + return i; + } + else + { + auto trustedMemcmp(in void* s1, in void* s2, size_t n) @trusted + { + return memcmp(s1, s2, n); + } + if (trustedMemcmp(&s[i + 1], &sub[1], sub.length - 1) == 0) + return i; + } + } } } else { - for(size_t i = s.length; !s.empty;) + for (size_t i = s.length; !s.empty;) { - if(s.endsWith(sub)) + if (s.endsWith(sub)) return cast(ptrdiff_t)i - to!(const(Char1)[])(sub).length; i -= strideBack(s, i); @@ -607,10 +783,10 @@ ptrdiff_t lastIndexOf(Char1, Char2)(const(Char1)[] s, } else { - for(size_t i = s.length; !s.empty;) + for (size_t i = s.length; !s.empty;) { - if(endsWith!((dchar a, dchar b) {return std.uni.toLower(a) == std.uni.toLower(b);}) - (s, sub)) + if (endsWith!((a, b) => std.uni.toLower(a) == std.uni.toLower(b)) + (s, sub)) { return cast(ptrdiff_t)i - to!(const(Char1)[])(sub).length; } @@ -627,9 +803,11 @@ unittest { debug(string) printf("string.lastIndexOf.unittest\n"); - foreach(S; TypeTuple!(string, wstring, dstring)) + assertCTFEable!( { - foreach(T; TypeTuple!(string, wstring, dstring)) + foreach (S; TypeTuple!(string, wstring, dstring)) + { + foreach (T; TypeTuple!(string, wstring, dstring)) { enum typeStr = S.stringof ~ " " ~ T.stringof; @@ -642,6 +820,7 @@ unittest assert(lastIndexOf(to!S("abcdefcdef"), to!T("x")) == -1, typeStr); assert(lastIndexOf(to!S("abcdefcdef"), to!T("xy")) == -1, typeStr); assert(lastIndexOf(to!S("abcdefcdef"), to!T("")) == 10, typeStr); + assert(lastIndexOf(to!S("öabcdefcdef"), to!T("ö")) == 0, typeStr); assert(lastIndexOf(cast(S)null, to!T("a"), CaseSensitive.no) == -1, typeStr); assert(lastIndexOf(to!S("abcdefCdef"), to!T("c"), CaseSensitive.no) == 6, typeStr); @@ -649,11 +828,14 @@ unittest assert(lastIndexOf(to!S("abcdefcdef"), to!T("x"), CaseSensitive.no) == -1, typeStr); assert(lastIndexOf(to!S("abcdefcdef"), to!T("xy"), CaseSensitive.no) == -1, typeStr); assert(lastIndexOf(to!S("abcdefcdef"), to!T(""), CaseSensitive.no) == 10, typeStr); + assert(lastIndexOf(to!S("öabcdefcdef"), to!T("ö"), CaseSensitive.no) == 0, typeStr); assert(lastIndexOf(to!S("abcdefcdef"), to!T("c"), CaseSensitive.no) == 6, typeStr); assert(lastIndexOf(to!S("abcdefcdef"), to!T("cd"), CaseSensitive.no) == 6, typeStr); assert(lastIndexOf(to!S("abcdefcdef"), to!T("def"), CaseSensitive.no) == 7, typeStr); + assert(lastIndexOf(to!S("ödfeffgfff"), to!T("ö"), CaseSensitive.yes) == 0); + S sPlts = "Mars: the fourth Rock (Planet) from the Sun."; S sMars = "Who\'s \'My Favorite Maritian?\'"; @@ -663,7 +845,7 @@ unittest assert(lastIndexOf(sMars, to!T(sMars), CaseSensitive.no) == 0, typeStr); } - foreach(cs; EnumMembers!CaseSensitive) + foreach (cs; EnumMembers!CaseSensitive) { enum csString = to!string(cs); @@ -672,6 +854,77 @@ unittest assert(lastIndexOf("\U00010143\u0100\U00010143hello"d, to!S("\u0100"), cs) == 1, csString); } } + }); +} + +/++ + Returns the index of the last occurence of $(D sub) in $(D s). If $(D sub) + is not found, then $(D -1) is returned. The $(D startIdx) slices $(D s) in + the following way $(D s[0 .. startIdx]). $(D startIdx) represents a + codeunit index in $(D s). If the sequence ending at $(D startIdx) does not + represent a well formed codepoint, then a $(XREF utf,UTFException) may be + thrown. + + $(D cs) indicates whether the comparisons are case sensitive. + +/ +ptrdiff_t lastIndexOf(Char1, Char2)(const(Char1)[] s, const(Char2)[] sub, + const size_t startIdx, CaseSensitive cs = CaseSensitive.yes) @safe pure + if (isSomeChar!Char1 && isSomeChar!Char2) +{ + if (startIdx <= s.length) + { + return lastIndexOf(s[0u .. startIdx], sub, cs); + } + + return -1; +} + +unittest +{ + debug(string) printf("string.lastIndexOf.unittest\n"); + + foreach(S; TypeTuple!(string, wstring, dstring)) + { + foreach(T; TypeTuple!(string, wstring, dstring)) + { + enum typeStr = S.stringof ~ " " ~ T.stringof; + + assert(lastIndexOf(cast(S)null, to!T("a")) == -1, typeStr); + assert(lastIndexOf(to!S("abcdefcdef"), to!T("c"), 5) == 2, typeStr); + assert(lastIndexOf(to!S("abcdefcdef"), to!T("cd"), 3) == -1, typeStr); + assert(lastIndexOf(to!S("abcdefcdef"), to!T("ef"), 6) == 4, typeStr ~ + format(" %u", lastIndexOf(to!S("abcdefcdef"), to!T("ef"), 6))); + assert(lastIndexOf(to!S("abcdefCdef"), to!T("c"), 5) == 2, typeStr); + assert(lastIndexOf(to!S("abcdefCdef"), to!T("cd"), 3) == -1, typeStr); + assert(lastIndexOf(to!S("abcdefcdefx"), to!T("x"), 1) == -1, typeStr); + assert(lastIndexOf(to!S("abcdefcdefxy"), to!T("xy"), 6) == -1, typeStr); + assert(lastIndexOf(to!S("abcdefcdef"), to!T(""), 8) == 8, typeStr); + assert(lastIndexOf(to!S("öafö"), to!T("ö"), 3) == 0, typeStr ~ + to!string(lastIndexOf(to!S("öafö"), to!T("ö"), 3))); //BUG 10472 + + assert(lastIndexOf(cast(S)null, to!T("a"), 1, CaseSensitive.no) == -1, typeStr); + assert(lastIndexOf(to!S("abcdefCdef"), to!T("c"), 5, CaseSensitive.no) == 2, typeStr); + assert(lastIndexOf(to!S("abcdefCdef"), to!T("cD"), 4, CaseSensitive.no) == 2, typeStr ~ + " " ~ to!string(lastIndexOf(to!S("abcdefCdef"), to!T("cD"), 3, CaseSensitive.no))); + assert(lastIndexOf(to!S("abcdefcdef"), to!T("x"),3 , CaseSensitive.no) == -1, typeStr); + assert(lastIndexOf(to!S("abcdefcdefXY"), to!T("xy"), 4, CaseSensitive.no) == -1, typeStr); + assert(lastIndexOf(to!S("abcdefcdef"), to!T(""), 7, CaseSensitive.no) == 7, typeStr); + + assert(lastIndexOf(to!S("abcdefcdef"), to!T("c"), 4, CaseSensitive.no) == 2, typeStr); + assert(lastIndexOf(to!S("abcdefcdef"), to!T("cd"), 4, CaseSensitive.no) == 2, typeStr); + assert(lastIndexOf(to!S("abcdefcdef"), to!T("def"), 6, CaseSensitive.no) == 3, typeStr); + assert(lastIndexOf(to!S(""), to!T(""), 0) == lastIndexOf(to!S(""), to!T("")), typeStr); + } + + foreach(cs; EnumMembers!CaseSensitive) + { + enum csString = to!string(cs); + + assert(lastIndexOf("\U00010143\u0100\U00010143hello", to!S("\u0100"), 6, cs) == 4, csString); + assert(lastIndexOf("\U00010143\u0100\U00010143hello"w, to!S("\u0100"), 6, cs) == 2, csString); + assert(lastIndexOf("\U00010143\u0100\U00010143hello"d, to!S("\u0100"), 3, cs) == 1, csString); + } + } } @@ -679,36 +932,32 @@ unittest * Returns the representation of a string, which has the same type * as the string except the character type is replaced by $(D ubyte), * $(D ushort), or $(D uint) depending on the character width. - * - * Example: ----- -string s = "hello"; -static assert(is(typeof(representation(s)) == immutable(ubyte)[])); -assert(representation(s) is cast(immutable(ubyte)[]) s); -assert(representation(s) == [0x68, 0x65, 0x6c, 0x6c, 0x6f]); ----- */ auto representation(Char)(Char[] s) pure nothrow - if(isSomeChar!Char) + if (isSomeChar!Char) { // Get representation type alias TypeTuple!(ubyte, ushort, uint)[Char.sizeof / 2] U; // const and immutable storage classes - static if (is(Char == immutable)) alias immutable(U) T; - else static if (is(Char == const)) alias const(U) T; - else alias U T; + static if (is(Char == immutable)) + alias T = immutable(U); + else static if (is(Char == const)) + alias T = const(U); + else + alias T = U; // shared storage class (because shared(const(T)) is possible) - static if (is(Char == shared)) alias shared(T) ST; - else alias T ST; + static if (is(Char == shared)) + alias ST = shared(T); + else + alias ST = T; return cast(ST[]) s; } - +/// unittest { - //test example string s = "hello"; static assert(is(typeof(representation(s)) == immutable(ubyte)[])); assert(representation(s) is cast(immutable(ubyte)[]) s); @@ -716,347 +965,87 @@ unittest } unittest { + assertCTFEable!( + { void test(Char, T)(Char[] str) { static assert(is(typeof(representation(str)) == T[])); assert(representation(str) is cast(T[]) str); } - foreach(Type; TypeTuple!(Tuple!(char , ubyte ), - Tuple!(wchar, ushort), - Tuple!(dchar, uint ))) + foreach (Type; TypeTuple!(Tuple!(char , ubyte ), + Tuple!(wchar, ushort), + Tuple!(dchar, uint ))) { alias Char = FieldTypeTuple!Type[0]; alias Int = FieldTypeTuple!Type[1]; enum immutable(Char)[] hello = "hello"; - test!( immutable(Char) , immutable(Int) )(hello); - test!( const(Char) , const(Int) )(hello); - test!( Char , Int )(hello.dup); - test!( shared(Char) , shared(Int) )(cast(shared) hello.dup); - test!(const(shared(Char)), const(shared(Int)))(hello); + test!( immutable Char, immutable Int)(hello); + test!( const Char, const Int)(hello); + test!( Char, Int)(hello.dup); + test!( shared Char, shared Int)(cast(shared) hello.dup); + test!(const shared Char, const shared Int)(hello); } + }); } /++ Returns a string which is identical to $(D s) except that all of its - characters are lowercase (in unicode, not just ASCII). If $(D s) does not - have any uppercase characters, then $(D s) is returned. + characters are converted to lowercase (by preforming Unicode lowercase mapping). + If none of $(D s) characters were affected, then $(D s) itself is returned. +/ -S toLower(S)(S s) @trusted pure - if(isSomeString!S) -{ - foreach (i, dchar cOuter; s) - { - if (!std.uni.isUpper(cOuter)) continue; - auto result = s[0.. i].dup; - foreach (dchar c; s[i .. $]) - { - if (std.uni.isUpper(c)) - { - c = std.uni.toLower(c); - } - result ~= c; - } - return cast(S) result; - } - return s; -} - -unittest -{ - debug(string) printf("string.toLower.unittest\n"); - - foreach(S; TypeTuple!(string, wstring, dstring, char[], wchar[], dchar[])) - { - S s = cast(S)"hello world\u0101"; - assert(toLower(s) is s); - const S sc = "hello world\u0101"; - assert(toLower(sc) is sc); - immutable S si = "hello world\u0101"; - assert(toLower(si) is si); - - S t = cast(S)"Hello World\u0100"; - assert(toLower(t) == s); - const S tc = "hello world\u0101"; - assert(toLower(tc) == s); - immutable S ti = "hello world\u0101"; - assert(toLower(ti) == s); - } -} - +alias toLower = std.uni.toLower; /++ - Converts $(D s) to lowercase (in unicode, not just ASCII) in place. + Converts $(D s) to lowercase (by performing Unicode lowercase mapping) in place. + For a few characters string length may increase after the transformation, + in such a case the function reallocates exactly once. If $(D s) does not have any uppercase characters, then $(D s) is unaltered. +/ -void toLowerInPlace(C)(ref C[] s) - if(is(C == char) || is(C == wchar)) -{ - for (size_t i = 0; i < s.length; ) - { - immutable c = s[i]; - if (std.ascii.isUpper(c)) - { - s[i++] = cast(C) (c + (cast(C)'a' - 'A')); - } - else if (!std.ascii.isASCII(c)) - { - // wide character - size_t j = i; - dchar dc = decode(s, j); - assert(j > i); - if (!std.uni.isUpper(dc)) - { - i = j; - continue; - } - auto toAdd = to!(C[])(std.uni.toLower(dc)); - s = s[0 .. i] ~ toAdd ~ s[j .. $]; - i += toAdd.length; - } - else - { - ++i; - } - } -} - -void toLowerInPlace(C)(ref C[] s) @safe pure nothrow - if(is(C == dchar)) -{ - foreach(ref c; s) - { - if(std.uni.isUpper(c)) - c = std.uni.toLower(c); - } -} - -unittest -{ - debug(string) printf("string.toLowerInPlace.unittest\n"); - - foreach(S; TypeTuple!(char[], wchar[], dchar[])) - { - S s = to!S("hello world\u0101"); - toLowerInPlace(s); - assert(s == "hello world\u0101"); - - S t = to!S("Hello World\u0100"); - toLowerInPlace(t); - assert(t == "hello world\u0101"); - } -} - -unittest -{ - debug(string) printf("string.toLower/toLowerInPlace.unittest\n"); - - string s1 = "FoL"; - string s2 = toLower(s1); - assert(cmp(s2, "fol") == 0, s2); - assert(s2 != s1); - - char[] s3 = s1.dup; - toLowerInPlace(s3); - assert(s3 == s2, s3); - - s1 = "A\u0100B\u0101d"; - s2 = toLower(s1); - s3 = s1.dup; - assert(cmp(s2, "a\u0101b\u0101d") == 0); - assert(s2 !is s1); - toLowerInPlace(s3); - assert(s3 == s2, s3); - - s1 = "A\u0460B\u0461d"; - s2 = toLower(s1); - s3 = s1.dup; - assert(cmp(s2, "a\u0461b\u0461d") == 0); - assert(s2 !is s1); - toLowerInPlace(s3); - assert(s3 == s2, s3); - - s1 = "\u0130"; - s2 = toLower(s1); - s3 = s1.dup; - assert(s2 == "i"); - assert(s2 !is s1); - toLowerInPlace(s3); - assert(s3 == s2, s3); - - // Test on wchar and dchar strings. - assert(toLower("Some String"w) == "some string"w); - assert(toLower("Some String"d) == "some string"d); -} - +alias toLowerInPlace = std.uni.toLowerInPlace; /++ Returns a string which is identical to $(D s) except that all of its - characters are uppercase (in unicode, not just ASCII). If $(D s) does not - have any lowercase characters, then $(D s) is returned. + characters are converted to uppercase (by preforming Unicode uppercase mapping). + If none of $(D s) characters were affected, then $(D s) itself is returned. +/ -S toUpper(S)(S s) @trusted pure - if(isSomeString!S) -{ - foreach (i, dchar cOuter; s) - { - if (!std.uni.isLower(cOuter)) continue; - auto result = s[0.. i].dup; - foreach (dchar c; s[i .. $]) - { - if (std.uni.isLower(c)) - { - c = std.uni.toUpper(c); - } - result ~= c; - } - return cast(S) result; - } - return s; -} - -unittest -{ - debug(string) printf("string.toUpper.unittest\n"); - - foreach(S; TypeTuple!(string, wstring, dstring, char[], wchar[], dchar[])) - { - S s = cast(S)"HELLO WORLD\u0100"; - assert(toUpper(s) is s); - const S sc = "HELLO WORLD\u0100"; - assert(toUpper(sc) is sc); - immutable S si = "HELLO WORLD\u0100"; - assert(toUpper(si) is si); - - S t = cast(S)"hello world\u0101"; - assert(toUpper(t) == s); - const S tc = "HELLO WORLD\u0100"; - assert(toUpper(tc) == s); - immutable S ti = "HELLO WORLD\u0100"; - assert(toUpper(ti) == s); - } -} +alias toUpper = std.uni.toUpper; /++ - Converts $(D s) to uppercase (in unicode, not just ASCII) in place. + Converts $(D s) to uppercase (by performing Unicode uppercase mapping) in place. + For a few characters string length may increase after the transformation, + in such a case the function reallocates exactly once. If $(D s) does not have any lowercase characters, then $(D s) is unaltered. +/ -void toUpperInPlace(C)(ref C[] s) - if(isSomeChar!C && - (is(C == char) || is(C == wchar))) -{ - for (size_t i = 0; i < s.length; ) - { - immutable c = s[i]; - if ('a' <= c && c <= 'z') - { - s[i++] = cast(C) (c - (cast(C)'a' - 'A')); - } - else if (!std.ascii.isASCII(c)) - { - // wide character - size_t j = i; - dchar dc = decode(s, j); - assert(j > i); - if (!std.uni.isLower(dc)) - { - i = j; - continue; - } - auto toAdd = to!(C[])(std.uni.toUpper(dc)); - s = s[0 .. i] ~ toAdd ~ s[j .. $]; - i += toAdd.length; - } - else - { - ++i; - } - } -} - -void toUpperInPlace(C)(ref C[] s) @safe pure nothrow - if(is(C == dchar)) -{ - foreach(ref c; s) - { - if(std.uni.isLower(c)) - c = std.uni.toUpper(c); - } -} - -unittest -{ - debug(string) printf("string.toUpperInPlace.unittest\n"); - - foreach(S; TypeTuple!(char[], wchar[], dchar[])) - { - S s = to!S("HELLO WORLD\u0100"); - toUpperInPlace(s); - assert(s == "HELLO WORLD\u0100"); - - S t = to!S("Hello World\u0101"); - toUpperInPlace(t); - assert(t == "HELLO WORLD\u0100"); - } -} - -unittest -{ - debug(string) printf("string.toUpper/toUpperInPlace.unittest\n"); - - string s1 = "FoL"; - string s2; - char[] s3; - - s2 = toUpper(s1); - s3 = s1.dup; toUpperInPlace(s3); - assert(s3 == s2, s3); - assert(cmp(s2, "FOL") == 0); - assert(s2 !is s1); - - s1 = "a\u0100B\u0101d"; - s2 = toUpper(s1); - s3 = s1.dup; toUpperInPlace(s3); - assert(s3 == s2); - assert(cmp(s2, "A\u0100B\u0100D") == 0); - assert(s2 !is s1); - - s1 = "a\u0460B\u0461d"; - s2 = toUpper(s1); - s3 = s1.dup; toUpperInPlace(s3); - assert(s3 == s2); - assert(cmp(s2, "A\u0460B\u0460D") == 0); - assert(s2 !is s1); -} - +alias toUpperInPlace = std.uni.toUpperInPlace; /++ - Capitalize the first character of $(D s) and conver the rest of $(D s) + Capitalize the first character of $(D s) and convert the rest of $(D s) to lowercase. +/ S capitalize(S)(S s) @trusted pure - if(isSomeString!S) + if (isSomeString!S) { Unqual!(typeof(s[0]))[] retval; bool changed = false; - foreach(i, dchar c; s) + foreach (i, dchar c; s) { dchar c2; - if(i == 0) + if (i == 0) { c2 = std.uni.toUpper(c); - if(c != c2) + if (c != c2) changed = true; } else { c2 = std.uni.toLower(c); - if(c != c2) + if (c != c2) { - if(!changed) + if (!changed) { changed = true; retval = s[0 .. i].dup; @@ -1064,7 +1053,7 @@ S capitalize(S)(S s) @trusted pure } } - if(changed) + if (changed) std.utf.encode(retval, c2); } @@ -1073,8 +1062,8 @@ S capitalize(S)(S s) @trusted pure unittest { - debug(string) printf("string.capitalize.unittest\n"); - + assertCTFEable!( + { foreach (S; TypeTuple!(string, wstring, dstring, char[], wchar[], dchar[])) { S s1 = to!S("FoL"); @@ -1092,10 +1081,9 @@ unittest s2 = capitalize(s1); assert(cmp(s2, "Fol") == 0); assert(s2 !is s1); - s1 = to!S("\u0131 \u0130"); s2 = capitalize(s1); - assert(cmp(s2, "\u0049 \u0069") == 0); + assert(cmp(s2, "I \u0130") == 0); assert(s2 !is s1); s1 = to!S("\u017F \u0049"); @@ -1103,9 +1091,9 @@ unittest assert(cmp(s2, "\u0053 \u0069") == 0); assert(s2 !is s1); } + }); } - /++ Split $(D s) into an array of lines using $(D '\r'), $(D '\n'), $(D "\r\n"), $(XREF uni, lineSep), and $(XREF uni, paraSep) as delimiters. @@ -1114,23 +1102,23 @@ unittest +/ enum KeepTerminator : bool { no, yes } /// ditto -S[] splitLines(S)(S s, KeepTerminator keepTerm = KeepTerminator.no) - if(isSomeString!S) +S[] splitLines(S)(S s, KeepTerminator keepTerm = KeepTerminator.no) @safe pure + if (isSomeString!S) { size_t iStart = 0; size_t nextI = 0; auto retval = appender!(S[])(); - for(size_t i; i < s.length; i = nextI) + for (size_t i; i < s.length; i = nextI) { immutable c = decode(s, nextI); - if(c == '\r' || c == '\n' || c == lineSep || c == paraSep) + if (c == '\r' || c == '\n' || c == lineSep || c == paraSep) { immutable isWinEOL = c == '\r' && i + 1 < s.length && s[i + 1] == '\n'; auto iEnd = i; - if(keepTerm == KeepTerminator.yes) + if (keepTerm == KeepTerminator.yes) { iEnd = isWinEOL? nextI + 1 : nextI; } @@ -1138,7 +1126,7 @@ S[] splitLines(S)(S s, KeepTerminator keepTerm = KeepTerminator.no) retval.put(s[iStart .. iEnd]); iStart = nextI; - if(isWinEOL) + if (isWinEOL) { ++nextI; ++iStart; @@ -1146,7 +1134,7 @@ S[] splitLines(S)(S s, KeepTerminator keepTerm = KeepTerminator.no) } } - if(iStart != nextI) + if (iStart != nextI) retval.put(s[iStart .. $]); return retval.data; @@ -1156,6 +1144,8 @@ unittest { debug(string) printf("string.splitLines.unittest\n"); + assertCTFEable!( + { foreach (S; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring)) { auto s = to!S("\rpeter\n\rpaul\r\njerry\u2028ice\u2029cream\n\nsunday\n"); @@ -1193,40 +1183,32 @@ unittest assert(lines.length == 9); assert(lines[8] == "sunday"); } + }); } /++ - Strips leading whitespace. + Strips leading whitespace (as defined by $(XREF uni, isWhite)). - Examples: --------------------- -assert(stripLeft(" hello world ") == - "hello world "); -assert(stripLeft("\n\t\v\rhello world\n\t\v\r") == - "hello world\n\t\v\r"); -assert(stripLeft("hello world") == - "hello world"); -assert(stripLeft([lineSep] ~ "hello world" ~ lineSep) == - "hello world" ~ [lineSep]); -assert(stripLeft([paraSep] ~ "hello world" ~ paraSep) == - "hello world" ~ [paraSep]); --------------------- + Returns: $(D str) stripped of leading whitespace. + + Postconditions: $(D str) and the returned value + will share the same tail (see $(XREF array, sameTail)). +/ C[] stripLeft(C)(C[] str) @safe pure - if(isSomeChar!C) + if (isSomeChar!C) { - foreach(i, dchar c; str) + foreach (i, dchar c; str) { - if(!std.uni.isWhite(c)) + if (!std.uni.isWhite(c)) return str[i .. $]; } return str[$ .. $]; //Empty string with correct type. } -//Verify Example. -unittest +/// +@safe pure unittest { assert(stripLeft(" hello world ") == "hello world "); @@ -1242,36 +1224,27 @@ unittest /++ - Strips trailing whitespace. + Strips trailing whitespace (as defined by $(XREF uni, isWhite)). - Examples: --------------------- -assert(stripRight(" hello world ") == - " hello world"); -assert(stripRight("\n\t\v\rhello world\n\t\v\r") == - "\n\t\v\rhello world"); -assert(stripRight("hello world") == - "hello world"); -assert(stripRight([lineSep] ~ "hello world" ~ lineSep) == - [lineSep] ~ "hello world"); -assert(stripRight([paraSep] ~ "hello world" ~ paraSep) == - [paraSep] ~ "hello world"); --------------------- + Returns: $(D str) stripped of trailing whitespace. + + Postconditions: $(D str) and the returned value + will share the same head (see $(XREF array, sameHead)). +/ -C[] stripRight(C)(C[] str) - if(isSomeChar!C) +C[] stripRight(C)(C[] str) @safe pure + if (isSomeChar!C) { - foreach_reverse(i, dchar c; str) + foreach_reverse (i, dchar c; str) { - if(!std.uni.isWhite(c)) + if (!std.uni.isWhite(c)) return str[0 .. i + codeLength!C(c)]; } return str[0 .. 0]; } -//Verify Example. -unittest +/// +@safe pure unittest { assert(stripRight(" hello world ") == " hello world"); @@ -1287,30 +1260,19 @@ unittest /++ - Strips both leading and trailing whitespace. + Strips both leading and trailing whitespace (as defined by + $(XREF uni, isWhite)). - Examples: --------------------- -assert(strip(" hello world ") == - "hello world"); -assert(strip("\n\t\v\rhello world\n\t\v\r") == - "hello world"); -assert(strip("hello world") == - "hello world"); -assert(strip([lineSep] ~ "hello world" ~ [lineSep]) == - "hello world"); -assert(strip([paraSep] ~ "hello world" ~ [paraSep]) == - "hello world"); --------------------- + Returns: $(D str) stripped of trailing whitespace. +/ -C[] strip(C)(C[] str) - if(isSomeChar!C) +C[] strip(C)(C[] str) @safe pure + if (isSomeChar!C) { return stripRight(stripLeft(str)); } -//Verify Example. -unittest +/// +@safe pure unittest { assert(strip(" hello world ") == "hello world"); @@ -1328,9 +1290,11 @@ unittest { debug(string) printf("string.strip.unittest\n"); - foreach(S; TypeTuple!(char[], const char[], string, - wchar[], const wchar[], wstring, - dchar[], const dchar[], dstring)) + assertCTFEable!( + { + foreach (S; TypeTuple!( char[], const char[], string, + wchar[], const wchar[], wstring, + dchar[], const dchar[], dstring)) { assert(equal(stripLeft(to!S(" foo\t ")), "foo\t ")); assert(equal(stripLeft(to!S("\u2008 foo\t \u2007")), "foo\t \u2007")); @@ -1352,13 +1316,17 @@ unittest assert(equal(strip(to!S("\U0010FFFE")), "\U0010FFFE")); assert(equal(strip(to!S("")), "")); } + }); } -unittest +@safe pure unittest { + assertCTFEable!( + { wstring s = " "; assert(s.sameTail(s.stripLeft())); assert(s.sameHead(s.stripRight())); + }); } @@ -1371,34 +1339,18 @@ unittest $(D "\r\n"), $(XREF uni, lineSep), or $(XREF uni, paraSep) is removed from the end of $(D str). If $(D str) does not end with any of those characters, then it is returned unchanged. - - Examples: --------------------- -assert(chomp(" hello world \n\r") == " hello world \n"); -assert(chomp(" hello world \r\n") == " hello world "); -assert(chomp(" hello world \n\n") == " hello world \n"); -assert(chomp(" hello world \n\n ") == " hello world \n\n "); -assert(chomp(" hello world \n\n" ~ [lineSep]) == " hello world \n\n"); -assert(chomp(" hello world \n\n" ~ [paraSep]) == " hello world \n\n"); -assert(chomp(" hello world") == " hello world"); -assert(chomp("") == ""); - -assert(chomp(" hello world", "orld") == " hello w"); -assert(chomp(" hello world", " he") == " hello world"); -assert(chomp("", "hello") == ""); --------------------- +/ -C[] chomp(C)(C[] str) - if(isSomeChar!C) +C[] chomp(C)(C[] str) @safe pure + if (isSomeChar!C) { - if(str.empty) + if (str.empty) return str; - switch(str[$ - 1]) + switch (str[$ - 1]) { case '\n': { - if(str.length > 1 && str[$ - 2] == '\r') + if (str.length > 1 && str[$ - 2] == '\r') return str[0 .. $ - 2]; goto case; } @@ -1406,14 +1358,14 @@ C[] chomp(C)(C[] str) return str[0 .. $ - 1]; //Pops off the last character if it's lineSep or paraSep. - static if(is(C : const char)) + static if (is(C : const char)) { //In UTF-8, lineSep and paraSep are [226, 128, 168], and //[226, 128, 169] respectively, so their first two bytes are the same. case 168: //Last byte of lineSep case 169: //Last byte of paraSep { - if(str.length > 2 && str[$ - 2] == 128 && str[$ - 3] == 226) + if (str.length > 2 && str[$ - 2] == 128 && str[$ - 3] == 226) return str [0 .. $ - 3]; goto default; } @@ -1430,23 +1382,23 @@ C[] chomp(C)(C[] str) } /// Ditto -C1[] chomp(C1, C2)(C1[] str, const(C2)[] delimiter) - if(isSomeChar!C1 && isSomeChar!C2) +C1[] chomp(C1, C2)(C1[] str, const(C2)[] delimiter) @safe pure + if (isSomeChar!C1 && isSomeChar!C2) { - if(delimiter.empty) + if (delimiter.empty) return chomp(str); - static if(is(Unqual!C1 == Unqual!C2)) + static if (is(Unqual!C1 == Unqual!C2)) { - if(str.endsWith(delimiter)) + if (str.endsWith(delimiter)) return str[0 .. $ - delimiter.length]; } auto orig = str; - foreach_reverse(dchar c; delimiter) + foreach_reverse (dchar c; delimiter) { - if(str.empty || str.back != c) + if (str.empty || str.back != c) return orig; str.popBack(); @@ -1455,8 +1407,8 @@ C1[] chomp(C1, C2)(C1[] str, const(C2)[] delimiter) return str; } -//Verify Example. -unittest +/// +@safe pure unittest { assert(chomp(" hello world \n\r") == " hello world \n"); assert(chomp(" hello world \r\n") == " hello world "); @@ -1477,7 +1429,9 @@ unittest debug(string) printf("string.chomp.unittest\n"); string s; - foreach(S; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring)) + assertCTFEable!( + { + foreach (S; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring)) { // @@@ BUG IN COMPILER, MUST INSERT CAST assert(chomp(cast(S)null) is null); @@ -1494,7 +1448,7 @@ unittest assert(chomp(to!S("hello\u2028\u2028")) == "hello\u2028"); assert(chomp(to!S("hello\u2029\u2029")) == "hello\u2029"); - foreach(T; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring)) + foreach (T; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring)) { // @@@ BUG IN COMPILER, MUST INSERT CAST assert(chomp(cast(S)null, cast(T)null) is null); @@ -1508,6 +1462,7 @@ unittest assert(chomp(to!S("\uFF28el\uFF4co"), to!T("l\uFF4co")) == "\uFF28e"); } } + }); } @@ -1515,21 +1470,13 @@ unittest If $(D str) starts with $(D delimiter), then the part of $(D str) following $(D delimiter) is returned. If it $(D str) does $(I not) start with $(D delimiter), then it is returned unchanged. - - Examples: --------------------- -assert(chompPrefix("hello world", "he") == "llo world"); -assert(chompPrefix("hello world", "hello w") == "orld"); -assert(chompPrefix("hello world", " world") == "hello world"); -assert(chompPrefix("", "hello") == ""); --------------------- +/ -C1[] chompPrefix(C1, C2)(C1[] str, C2[] delimiter) - if(isSomeChar!C1 && isSomeChar!C2) +C1[] chompPrefix(C1, C2)(C1[] str, C2[] delimiter) @safe pure + if (isSomeChar!C1 && isSomeChar!C2) { - static if(is(Unqual!C1 == Unqual!C2)) + static if (is(Unqual!C1 == Unqual!C2)) { - if(str.startsWith(delimiter)) + if (str.startsWith(delimiter)) return str[delimiter.length .. $]; return str; } @@ -1538,9 +1485,9 @@ C1[] chompPrefix(C1, C2)(C1[] str, C2[] delimiter) auto orig = str; size_t index = 0; - foreach(dchar c; delimiter) + foreach (dchar c; delimiter) { - if(index >= str.length || decode(str, index) != c) + if (index >= str.length || decode(str, index) != c) return orig; } @@ -1548,8 +1495,8 @@ C1[] chompPrefix(C1, C2)(C1[] str, C2[] delimiter) } } -//Verify Example. -unittest +/// +@safe pure unittest { assert(chompPrefix("hello world", "he") == "llo world"); assert(chompPrefix("hello world", "hello w") == "orld"); @@ -1557,11 +1504,13 @@ unittest assert(chompPrefix("", "hello") == ""); } -unittest +/* @safe */ pure unittest { - foreach(S; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring)) + assertCTFEable!( { - foreach(T; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring)) + foreach (S; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring)) + { + foreach (T; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring)) { assert(equal(chompPrefix(to!S("abcdefgh"), to!T("abcde")), "fgh")); assert(equal(chompPrefix(to!S("abcde"), to!T("abcdefgh")), "abcde")); @@ -1570,6 +1519,7 @@ unittest assert(equal(chompPrefix(to!S("\uFF28el"), to!T("\uFF28el\uFF4co")), "\uFF28el")); } } + }); } @@ -1577,25 +1527,14 @@ unittest Returns $(D str) without its last character, if there is one. If $(D str) ends with $(D "\r\n"), then both are removed. If $(D str) is empty, then then it is returned unchanged. - - Examples: --------------------- -assert(chop("hello world") == "hello worl"); -assert(chop("hello world\n") == "hello world"); -assert(chop("hello world\r") == "hello world"); -assert(chop("hello world\n\r") == "hello world\n"); -assert(chop("hello world\r\n") == "hello world"); -assert(chop("Walter Bright") == "Walter Brigh"); -assert(chop("") == ""); --------------------- +/ -S chop(S)(S str) - if(isSomeString!S) +S chop(S)(S str) @safe pure + if (isSomeString!S) { - if(str.empty) + if (str.empty) return str; - if(str.length >= 2 && str[$ - 1] == '\n' && str[$ - 2] == '\r') + if (str.length >= 2 && str[$ - 1] == '\n' && str[$ - 2] == '\r') return str[0 .. $ - 2]; str.popBack(); @@ -1603,8 +1542,8 @@ S chop(S)(S str) return str; } -//Verify Example. -unittest +/// +@safe pure unittest { assert(chop("hello world") == "hello worl"); assert(chop("hello world\n") == "hello world"); @@ -1619,7 +1558,9 @@ unittest { debug(string) printf("string.chop.unittest\n"); - foreach(S; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring)) + assertCTFEable!( + { + foreach (S; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring)) { assert(chop(cast(S) null) is null); assert(equal(chop(to!S("hello")), "hell")); @@ -1629,6 +1570,7 @@ unittest assert(equal(chop(to!S(`さいごの果実`)), "さいごの果")); assert(equal(chop(to!S(`ミツバチと科学者`)), "ミツバチと科学")); } + }); } @@ -1637,15 +1579,15 @@ unittest is the character that will be used to fill up the space in the field that $(D s) doesn't fill. +/ -S leftJustify(S)(S s, size_t width, dchar fillChar = ' ') @trusted - if(isSomeString!S) +S leftJustify(S)(S s, size_t width, dchar fillChar = ' ') @trusted pure + if (isSomeString!S) { - alias typeof(s[0]) C; + alias C = ElementEncodingType!S; - if(cast(dchar)(cast(C)fillChar) == fillChar) + if (canSearchInCodeUnits!C(fillChar)) { immutable len = s.walkLength(); - if(len >= width) + if (len >= width) return s; auto retval = new Unqual!(C)[width - len + s.length]; @@ -1656,7 +1598,7 @@ S leftJustify(S)(S s, size_t width, dchar fillChar = ' ') @trusted else { auto dstr = to!dstring(s); - if(dstr.length >= width) + if (dstr.length >= width) return s; auto retval = new dchar[](width); @@ -1672,18 +1614,18 @@ S leftJustify(S)(S s, size_t width, dchar fillChar = ' ') @trusted is the character that will be used to fill up the space in the field that $(D s) doesn't fill. +/ -S rightJustify(S)(S s, size_t width, dchar fillChar = ' ') @trusted - if(isSomeString!S) +S rightJustify(S)(S s, size_t width, dchar fillChar = ' ') @trusted pure + if (isSomeString!S) { - alias typeof(s[0]) C; + alias C = ElementEncodingType!S; - if(cast(dchar)(cast(C)fillChar) == fillChar) + if (canSearchInCodeUnits!C(fillChar)) { immutable len = s.walkLength(); - if(len >= width) + if (len >= width) return s; - auto retval = new Unqual!(C)[width - len + s.length]; + auto retval = new Unqual!C[width - len + s.length]; retval[0 .. $ - s.length] = cast(C)fillChar; retval[$ - s.length .. $] = s[]; return cast(S)retval; @@ -1691,7 +1633,7 @@ S rightJustify(S)(S s, size_t width, dchar fillChar = ' ') @trusted else { auto dstr = to!dstring(s); - if(dstr.length >= width) + if (dstr.length >= width) return s; auto retval = new dchar[](width); @@ -1707,18 +1649,18 @@ S rightJustify(S)(S s, size_t width, dchar fillChar = ' ') @trusted is the character that will be used to fill up the space in the field that $(D s) doesn't fill. +/ -S center(S)(S s, size_t width, dchar fillChar = ' ') @trusted - if(isSomeString!S) +S center(S)(S s, size_t width, dchar fillChar = ' ') @trusted pure + if (isSomeString!S) { - alias typeof(s[0]) C; + alias C = ElementEncodingType!S; - if(cast(dchar)(cast(C)fillChar) == fillChar) + if (canSearchInCodeUnits!C(fillChar)) { immutable len = s.walkLength(); - if(len >= width) + if (len >= width) return s; - auto retval = new Unqual!(C)[width - len + s.length]; + auto retval = new Unqual!C[width - len + s.length]; immutable left = (retval.length - s.length) / 2; retval[0 .. left] = cast(C)fillChar; retval[left .. left + s.length] = s[]; @@ -1728,7 +1670,7 @@ S center(S)(S s, size_t width, dchar fillChar = ' ') @trusted else { auto dstr = to!dstring(s); - if(dstr.length >= width) + if (dstr.length >= width) return s; auto retval = new dchar[](width); @@ -1744,7 +1686,9 @@ unittest { debug(string) printf("string.justify.unittest\n"); - foreach(S; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring)) + assertCTFEable!( + { + foreach (S; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring)) { S s = to!S("hello"); @@ -1763,7 +1707,12 @@ unittest assert(leftJustify(s, 8, '\u0100') == "hello\u0100\u0100\u0100"); assert(rightJustify(s, 8, '\u0100') == "\u0100\u0100\u0100hello"); assert(center(s, 8, '\u0100') == "\u0100hello\u0100\u0100"); + + assert(leftJustify(s, 8, 'ö') == "helloööö"); + assert(rightJustify(s, 8, 'ö') == "öööhello"); + assert(center(s, 8, 'ö') == "öhelloöö"); } + }); } @@ -1773,7 +1722,7 @@ unittest is the distance between tab stops. +/ S detab(S)(S s, size_t tabSize = 8) @trusted pure - if(isSomeString!S) + if (isSomeString!S) { assert(tabSize > 0); alias Unqual!(typeof(s[0])) C; @@ -1818,10 +1767,7 @@ S detab(S)(S s, size_t tabSize = 8) @trusted pure L1: if (changes) { - if (cast(dchar)(cast(C)c) == c) - result ~= cast(C)c; - else - std.utf.encode(result, c); + std.utf.encode(result, c); } break; } @@ -1834,6 +1780,8 @@ unittest { debug(string) printf("string.detab.unittest\n"); + assertCTFEable!( + { foreach (S; TypeTuple!(char[], wchar[], dchar[], string, wstring, dstring)) { S s = to!S("This \tis\t a fofof\tof list"); @@ -1848,9 +1796,9 @@ unittest assert(detab( " ab\t asdf ") == " ab asdf "); assert(detab( " \U00010000b\tasdf ") == " \U00010000b asdf "); } + }); } - /++ Replaces spaces in $(D s) with the optimal number of tabs. All spaces and tabs at the end of a line are removed. @@ -1860,7 +1808,7 @@ unittest tabSize = Tab columns are $(D tabSize) spaces apart. +/ S entab(S)(S s, size_t tabSize = 8) @trusted pure - if(isSomeString!S) + if (isSomeString!S) { bool changes = false; alias Unqual!(typeof(s[0])) C; @@ -1940,10 +1888,7 @@ S entab(S)(S s, size_t tabSize = 8) @trusted pure } if (changes) { - if (cast(dchar)(cast(C)c) == c) - result ~= cast(C)c; - else - std.utf.encode(result, c); + std.utf.encode(result, c); } } @@ -1962,8 +1907,8 @@ unittest { debug(string) printf("string.entab.unittest\n"); - string r; - + assertCTFEable!( + { assert(entab(cast(string) null) is null); assert(entab("").empty); assert(entab("a") == "a"); @@ -1994,6 +1939,7 @@ unittest assert(entab("a\t") == "a"); assert(entab("\uFF28\uFF45\uFF4C\uFF4C567 \t\uFF4F \t") == "\uFF28\uFF45\uFF4C\uFF4C567\t\t\uFF4F"); + }); } @@ -2014,28 +1960,19 @@ unittest transTable = The AA indicating which characters to replace and what to replace them with. toRemove = The characters to remove from the string. - - Examples: --------------------- -dchar[dchar] transTable1 = ['e' : '5', 'o' : '7', '5': 'q']; -assert(translate("hello world", transTable1) == "h5ll7 w7rld"); - -assert(translate("hello world", transTable1, "low") == "h5 rd"); - -string[dchar] transTable2 = ['e' : "5", 'o' : "orange"]; -assert(translate("hello world", transTable2) == "h5llorange worangerld"); --------------------- +/ C1[] translate(C1, C2 = immutable char)(C1[] str, dchar[dchar] transTable, - const(C2)[] toRemove = null) @safe - if(isSomeChar!C1 && isSomeChar!C2) + const(C2)[] toRemove = null) @safe pure + if (isSomeChar!C1 && isSomeChar!C2) { - return translateImpl(str, transTable, toRemove); + auto buffer = appender!(C1[])(); + translateImpl(str, transTable, toRemove, buffer); + return buffer.data; } -//Verify Examples. -unittest +/// +@safe pure unittest { dchar[dchar] transTable1 = ['e' : '5', 'o' : '7', '5': 'q']; assert(translate("hello world", transTable1) == "h5ll7 w7rld"); @@ -2046,11 +1983,13 @@ unittest assert(translate("hello world", transTable2) == "h5llorange worangerld"); } -unittest +/* @safe */ pure unittest { - foreach(S; TypeTuple!(char[], const(char)[], immutable(char)[], - wchar[], const(wchar)[], immutable(wchar)[], - dchar[], const(dchar)[], immutable(dchar)[])) + assertCTFEable!( + { + foreach (S; TypeTuple!( char[], const( char)[], immutable( char)[], + wchar[], const(wchar)[], immutable(wchar)[], + dchar[], const(dchar)[], immutable(dchar)[])) { assert(translate(to!S("hello world"), cast(dchar[dchar])['h' : 'q', 'l' : '5']) == to!S("qe55o wor5d")); @@ -2062,9 +2001,9 @@ unittest to!S("hell0 o w0rld")); assert(translate(to!S("hello world"), cast(dchar[dchar])null) == to!S("hello world")); - foreach(T; TypeTuple!(char[], const(char)[], immutable(char)[], - wchar[], const(wchar)[], immutable(wchar)[], - dchar[], const(dchar)[], immutable(dchar)[])) + foreach (T; TypeTuple!( char[], const( char)[], immutable( char)[], + wchar[], const(wchar)[], immutable(wchar)[], + dchar[], const(dchar)[], immutable(dchar)[])) { assert(translate(to!S("hello world"), cast(dchar[dchar])['h' : 'q', 'l' : '5'], @@ -2088,22 +2027,27 @@ unittest dchar[dchar] transTable = ['h' : 'q', 'l' : '5']; static assert(is(typeof(s) == typeof(translate(s, transTable)))); } + }); } /++ Ditto +/ C1[] translate(C1, S, C2 = immutable char)(C1[] str, S[dchar] transTable, - const(C2)[] toRemove = null) @safe - if(isSomeChar!C1 && isSomeString!S && isSomeChar!C2) + const(C2)[] toRemove = null) @safe pure + if (isSomeChar!C1 && isSomeString!S && isSomeChar!C2) { - return translateImpl(str, transTable, toRemove); + auto buffer = appender!(C1[])(); + translateImpl(str, transTable, toRemove, buffer); + return buffer.data; } -unittest +/* @safe */ pure unittest { - foreach(S; TypeTuple!(char[], const(char)[], immutable(char)[], - wchar[], const(wchar)[], immutable(wchar)[], - dchar[], const(dchar)[], immutable(dchar)[])) + assertCTFEable!( + { + foreach (S; TypeTuple!( char[], const( char)[], immutable( char)[], + wchar[], const(wchar)[], immutable(wchar)[], + dchar[], const(dchar)[], immutable(dchar)[])) { assert(translate(to!S("hello world"), ['h' : "yellow", 'l' : "42"]) == to!S("yellowe4242o wor42d")); @@ -2119,9 +2063,9 @@ unittest to!S("hello world")); assert(translate(to!S("hello world"), cast(string[dchar])null) == to!S("hello world")); - foreach(T; TypeTuple!(char[], const(char)[], immutable(char)[], - wchar[], const(wchar)[], immutable(wchar)[], - dchar[], const(dchar)[], immutable(dchar)[])) + foreach (T; TypeTuple!( char[], const( char)[], immutable( char)[], + wchar[], const(wchar)[], immutable(wchar)[], + dchar[], const(dchar)[], immutable(dchar)[])) { assert(translate(to!S("hello world"), ['h' : "yellow", 'l' : "42"], to!T("r")) == to!S("yellowe4242o wo42d")); @@ -2143,36 +2087,80 @@ unittest string[dchar] transTable = ['h' : "silly", 'l' : "putty"]; static assert(is(typeof(s) == typeof(translate(s, transTable)))); } + }); } -private auto translateImpl(C1, T, C2)(C1[] str, - T transTable, - const(C2)[] toRemove) @trusted -{ - auto retval = appender!(C1[])(); +/++ + This is an overload of $(D translate) which takes an existing buffer to write the contents to. + Params: + str = The original string. + transTable = The AA indicating which characters to replace and what to + replace them with. + toRemove = The characters to remove from the string. + buffer = An output range to write the contents to. + +/ +void translate(C1, C2 = immutable char, Buffer)(C1[] str, + dchar[dchar] transTable, + const(C2)[] toRemove, + Buffer buffer) + if (isSomeChar!C1 && isSomeChar!C2 && isOutputRange!(Buffer, C1)) +{ + translateImpl(str, transTable, toRemove, buffer); +} + +/// +@safe pure unittest +{ + dchar[dchar] transTable1 = ['e' : '5', 'o' : '7', '5': 'q']; + auto buffer = appender!(dchar[])(); + translate("hello world", transTable1, null, buffer); + assert(buffer.data == "h5ll7 w7rld"); + + buffer.clear(); + translate("hello world", transTable1, "low", buffer); + assert(buffer.data == "h5 rd"); + + buffer.clear(); + string[dchar] transTable2 = ['e' : "5", 'o' : "orange"]; + translate("hello world", transTable2, null, buffer); + assert(buffer.data == "h5llorange worangerld"); +} + +/++ Ditto +/ +void translate(C1, S, C2 = immutable char, Buffer)(C1[] str, + S[dchar] transTable, + const(C2)[] toRemove, + Buffer buffer) + if (isSomeChar!C1 && isSomeString!S && isSomeChar!C2 && isOutputRange!(Buffer, S)) +{ + translateImpl(str, transTable, toRemove, buffer); +} + +private void translateImpl(C1, T, C2, Buffer)(C1[] str, + T transTable, + const(C2)[] toRemove, + Buffer buffer) +{ bool[dchar] removeTable; - foreach(dchar c; toRemove) + foreach (dchar c; toRemove) removeTable[c] = true; - foreach(dchar c; str) + foreach (dchar c; str) { - if(c in removeTable) + if (c in removeTable) continue; auto newC = c in transTable; - if(newC) - retval.put(*newC); + if (newC) + put(buffer, *newC); else - retval.put(c); + put(buffer, c); } - - return retval.data; } - /++ This is an $(I $(RED ASCII-only)) overload of $(LREF _translate). It will $(I not) work with Unicode. It exists as an optimization for the @@ -2205,17 +2193,9 @@ private auto translateImpl(C1, T, C2)(C1[] str, transTable = The string indicating which characters to replace and what to replace them with. It is generated by $(LREF makeTrans). toRemove = The characters to remove from the string. - - Examples: --------------------- -auto transTable1 = makeTrans("eo5", "57q"); -assert(translate("hello world", transTable1) == "h5ll7 w7rld"); - -assert(translate("hello world", transTable1, "low") == "h5 rd"); --------------------- +/ -C[] translate(C = immutable char)(in char[] str, in char[] transTable, in char[] toRemove = null) @trusted nothrow - if(is(Unqual!C == char)) +C[] translate(C = immutable char)(in char[] str, in char[] transTable, in char[] toRemove = null) @trusted pure nothrow + if (is(Unqual!C == char)) in { assert(transTable.length == 256); @@ -2224,25 +2204,19 @@ body { bool[256] remTable = false; - foreach(char c; toRemove) + foreach (char c; toRemove) remTable[c] = true; size_t count = 0; - foreach(char c; str) + foreach (char c; str) { - if(!remTable[c]) + if (!remTable[c]) ++count; } - auto retval = new char[count]; - size_t i = 0; - foreach(char c; str) - { - if(!remTable[c]) - retval[i++] = transTable[c]; - } - - return cast(C[])(retval); + auto buffer = new char[count]; + translateImplAscii(str, transTable, remTable, buffer, toRemove); + return cast(C[])(buffer); } @@ -2252,25 +2226,25 @@ in { assert(from.length == to.length); assert(from.length <= 256); - foreach(char c; from) + foreach (char c; from) assert(std.ascii.isASCII(c)); - foreach(char c; to) + foreach (char c; to) assert(std.ascii.isASCII(c)); } body { char[] transTable = new char[256]; - foreach(i; 0 .. transTable.length) + foreach (i; 0 .. transTable.length) transTable[i] = cast(char)i; - foreach(i; 0 .. from.length) + foreach (i; 0 .. from.length) transTable[from[i]] = to[i]; return assumeUnique(transTable); } -// Verify Examples. -unittest +/// +@safe pure nothrow unittest { auto transTable1 = makeTrans("eo5", "57q"); assert(translate("hello world", transTable1) == "h5ll7 w7rld"); @@ -2278,9 +2252,11 @@ unittest assert(translate("hello world", transTable1, "low") == "h5 rd"); } -unittest +@safe pure unittest { - foreach(C; TypeTuple!(char, const char, immutable char)) + assertCTFEable!( + { + foreach (C; TypeTuple!(char, const char, immutable char)) { assert(translate!C("hello world", makeTrans("hl", "q5")) == to!(C[])("qe55o wor5d")); @@ -2289,7 +2265,7 @@ unittest static assert(is(typeof(s) == typeof(translate!C(s, transTable)))); } - foreach(S; TypeTuple!(char[], const(char)[], immutable(char)[])) + foreach (S; TypeTuple!(char[], const(char)[], immutable(char)[])) { assert(translate(to!S("hello world"), makeTrans("hl", "q5")) == to!S("qe55o wor5d")); assert(translate(to!S("hello \U00010143 world"), makeTrans("hl", "q5")) == @@ -2300,7 +2276,7 @@ unittest assert(translate(to!S("hello \U00010143 world"), makeTrans("12345", "67890")) == to!S("hello \U00010143 world")); - foreach(T; TypeTuple!(char[], const(char)[], immutable(char)[])) + foreach (T; TypeTuple!(char[], const(char)[], immutable(char)[])) { assert(translate(to!S("hello world"), makeTrans("hl", "q5"), to!T("r")) == to!S("qe55o wo5d")); @@ -2312,12 +2288,75 @@ unittest to!S("qe55o wor5d")); } } + }); } +/++ + This is an $(I $(RED ASCII-only)) overload of $(D translate) which takes an existing buffer to write the contents to. + + Params: + str = The original string. + transTable = The string indicating which characters to replace and what + to replace them with. It is generated by $(LREF makeTrans). + toRemove = The characters to remove from the string. + buffer = An output range to write the contents to. + +/ +void translate(C = immutable char, Buffer)(in char[] str, in char[] transTable, in char[] toRemove, Buffer buffer) + if (is(Unqual!C == char) && isOutputRange!(Buffer, char)) +in +{ + assert(transTable.length == 256); +} +body +{ + bool[256] remTable = false; + + foreach (char c; toRemove) + remTable[c] = true; + + translateImplAscii(str, transTable, remTable, buffer, toRemove); +} + +/// +@safe pure unittest +{ + auto buffer = appender!(char[])(); + auto transTable1 = makeTrans("eo5", "57q"); + translate("hello world", transTable1, null, buffer); + assert(buffer.data == "h5ll7 w7rld"); + + buffer.clear(); + translate("hello world", transTable1, "low", buffer); + assert(buffer.data == "h5 rd"); +} + +private void translateImplAscii(C = immutable char, Buffer)(in char[] str, in char[] transTable, ref bool[256] remTable, Buffer buffer, in char[] toRemove = null) +{ + static if (isOutputRange!(Buffer, char)) + { + foreach (char c; str) + { + if (!remTable[c]) + put(buffer, transTable[c]); + } + } + else + { + size_t i = 0; + foreach (char c; str) + { + if (!remTable[c]) + buffer[i++] = transTable[c]; + } + } +} /***************************************************** * Format arguments into a string. * + * Params: fmt = Format string. For detailed specification, see $(XREF format,formattedWrite). + * args = Variadic list of arguments to format into returned string. + * * $(RED format's current implementation has been replaced with $(LREF xformat)'s * implementation. in November 2012. * This is seamless for most code, but it makes it so that the only @@ -2326,13 +2365,13 @@ unittest * your calls to format accordingly. * * e.g.: ----- -format("key = %s", key, ", value = %s", value) ----- + * ---- + * format("key = %s", key, ", value = %s", value) + * ---- * needs to be rewritten as: ----- -format("key = %s, value = %s", key, value) ----- + * ---- + * format("key = %s, value = %s", key, value) + * ---- * ) */ string format(Char, Args...)(in Char[] fmt, Args args) @@ -2353,6 +2392,8 @@ unittest { debug(string) printf("std.string.format.unittest\n"); + assertCTFEable!( + { // assert(format(null) == ""); assert(format("foo") == "foo"); assert(format("foo%%") == "foo%"); @@ -2365,18 +2406,16 @@ unittest assertThrown!FormatException(format("foo %s")); assertThrown!FormatException(format("foo %s", 123, 456)); - assertCTFEable!( - { - assert(format("hel%slo%s%s%s", "world", -138, 'c', true) == - "helworldlo-138ctrue"); + assert(format("hel%slo%s%s%s", "world", -138, 'c', true) == + "helworldlo-138ctrue"); }); } /***************************************************** - * Format arguments into string s which must be large + * Format arguments into buffer buf which must be large * enough to hold the result. Throws RangeError if it is not. - * Returns: s + * Returns: The slice of $(D buf) containing the formatted string. * * $(RED sformat's current implementation has been replaced with $(LREF xsformat)'s * implementation. in November 2012. @@ -2386,13 +2425,13 @@ unittest * your calls to sformat accordingly. * * e.g.: ----- -sformat(buf, "key = %s", key, ", value = %s", value) ----- + * ---- + * sformat(buf, "key = %s", key, ", value = %s", value) + * ---- * needs to be rewritten as: ----- -sformat(buf, "key = %s, value = %s", key, value) ----- + * ---- + * sformat(buf, "key = %s, value = %s", key, value) + * ---- * ) */ char[] sformat(Char, Args...)(char[] buf, in Char[] fmt, Args args) @@ -2446,6 +2485,8 @@ unittest { debug(string) printf("std.string.sformat.unittest\n"); + assertCTFEable!( + { char[10] buf; assert(sformat(buf[], "foo") == "foo"); @@ -2460,12 +2501,13 @@ unittest assertThrown!FormatException(sformat(buf[], "foo %s", 123, 456)); assert(sformat(buf[], "%s %s %s", "c"c, "w"w, "d"d) == "c w d"); + }); } /***************************************************** * $(RED Deprecated. It will be removed in November 2013. - * Please us std.string.format instead) + * Please use std.string.format instead.) * * Format arguments into a string. * @@ -2478,6 +2520,8 @@ deprecated unittest { debug(string) printf("std.string.xformat.unittest\n"); + assertCTFEable!( + { // assert(xformat(null) == ""); assert(xformat("foo") == "foo"); assert(xformat("foo%%") == "foo%"); @@ -2489,12 +2533,13 @@ deprecated unittest assertThrown!FormatException(xformat("foo %s")); assertThrown!FormatException(xformat("foo %s", 123, 456)); + }); } /***************************************************** - * $(RED Deprecated. It will be removed in November 2013). - * Please us std.string.sformat instead) + * $(RED Deprecated. It will be removed in November 2013. + * Please use std.string.sformat instead.) * * Format arguments into string $(D buf) which must be large * enough to hold the result. Throws RangeError if it is not. @@ -2508,6 +2553,8 @@ deprecated unittest { debug(string) printf("std.string.xsformat.unittest\n"); + assertCTFEable!( + { char[10] buf; assert(xsformat(buf[], "foo") == "foo"); @@ -2522,6 +2569,7 @@ deprecated unittest assertThrown!FormatException(xsformat(buf[], "foo %s", 123, 456)); assert(xsformat(buf[], "%s %s %s", "c"c, "w"w, "d"d) == "c w d"); + }); } @@ -2544,7 +2592,7 @@ deprecated unittest * to be more like regular expression character classes. */ -bool inPattern(S)(dchar c, in S pattern) if (isSomeString!S) +bool inPattern(S)(dchar c, in S pattern) @safe pure if (isSomeString!S) { bool result = false; int range = 0; @@ -2552,25 +2600,26 @@ bool inPattern(S)(dchar c, in S pattern) if (isSomeString!S) foreach (size_t i, dchar p; pattern) { - if (p == '^' && i == 0) - { result = true; - if (i + 1 == pattern.length) - return (c == p); // or should this be an error? - } - else if (range) - { - range = 0; - if (lastc <= c && c <= p || c == p) - return !result; - } - else if (p == '-' && i > result && i + 1 < pattern.length) - { - range = 1; - continue; - } - else if (c == p) - return !result; - lastc = p; + if (p == '^' && i == 0) + { + result = true; + if (i + 1 == pattern.length) + return (c == p); // or should this be an error? + } + else if (range) + { + range = 0; + if (lastc <= c && c <= p || c == p) + return !result; + } + else if (p == '-' && i > result && i + 1 < pattern.length) + { + range = 1; + continue; + } + else if (c == p) + return !result; + lastc = p; } return result; } @@ -2580,46 +2629,28 @@ unittest { debug(string) printf("std.string.inPattern.unittest\n"); - int i; - - i = inPattern('x', "x"); - assert(i == 1); - i = inPattern('x', "y"); - assert(i == 0); - i = inPattern('x', cast(string)null); - assert(i == 0); - i = inPattern('x', "^y"); - assert(i == 1); - i = inPattern('x', "yxxy"); - assert(i == 1); - i = inPattern('x', "^yxxy"); - assert(i == 0); - i = inPattern('x', "^abcd"); - assert(i == 1); - i = inPattern('^', "^^"); - assert(i == 0); - i = inPattern('^', "^"); - assert(i == 1); - i = inPattern('^', "a^"); - assert(i == 1); - i = inPattern('x', "a-z"); - assert(i == 1); - i = inPattern('x', "A-Z"); - assert(i == 0); - i = inPattern('x', "^a-z"); - assert(i == 0); - i = inPattern('x', "^A-Z"); - assert(i == 1); - i = inPattern('-', "a-"); - assert(i == 1); - i = inPattern('-', "^A-"); - assert(i == 0); - i = inPattern('a', "z-a"); - assert(i == 1); - i = inPattern('z', "z-a"); - assert(i == 1); - i = inPattern('x', "z-a"); - assert(i == 0); + assertCTFEable!( + { + assert(inPattern('x', "x") == 1); + assert(inPattern('x', "y") == 0); + assert(inPattern('x', string.init) == 0); + assert(inPattern('x', "^y") == 1); + assert(inPattern('x', "yxxy") == 1); + assert(inPattern('x', "^yxxy") == 0); + assert(inPattern('x', "^abcd") == 1); + assert(inPattern('^', "^^") == 0); + assert(inPattern('^', "^") == 1); + assert(inPattern('^', "a^") == 1); + assert(inPattern('x', "a-z") == 1); + assert(inPattern('x', "A-Z") == 0); + assert(inPattern('x', "^a-z") == 0); + assert(inPattern('x', "^A-Z") == 1); + assert(inPattern('-', "a-") == 1); + assert(inPattern('-', "^A-") == 0); + assert(inPattern('a', "z-a") == 1); + assert(inPattern('z', "z-a") == 1); + assert(inPattern('x', "z-a") == 0); + }); } @@ -2627,7 +2658,7 @@ unittest * See if character c is in the intersection of the patterns. */ -bool inPattern(S)(dchar c, S[] patterns) if (isSomeString!S) +bool inPattern(S)(dchar c, S[] patterns) @safe pure if (isSomeString!S) { foreach (string pattern; patterns) { @@ -2644,7 +2675,7 @@ bool inPattern(S)(dchar c, S[] patterns) if (isSomeString!S) * Count characters in s that match pattern. */ -size_t countchars(S, S1)(S s, in S1 pattern) if (isSomeString!S && isSomeString!S1) +size_t countchars(S, S1)(S s, in S1 pattern) @safe pure if (isSomeString!S && isSomeString!S1) { size_t count; foreach (dchar c; s) @@ -2658,12 +2689,11 @@ unittest { debug(string) printf("std.string.count.unittest\n"); - size_t c; - - c = countchars("abc", "a-c"); - assert(c == 3); - c = countchars("hello world", "or"); - assert(c == 3); + assertCTFEable!( + { + assert(countchars("abc", "a-c") == 3); + assert(countchars("hello world", "or") == 3); + }); } @@ -2671,14 +2701,15 @@ unittest * Return string that is s with all characters removed that match pattern. */ -S removechars(S)(S s, in S pattern) if (isSomeString!S) +S removechars(S)(S s, in S pattern) @safe pure if (isSomeString!S) { Unqual!(typeof(s[0]))[] r; bool changed = false; foreach (size_t i, dchar c; s) { - if (inPattern(c, pattern)){ + if (inPattern(c, pattern)) + { if (!changed) { changed = true; @@ -2691,23 +2722,23 @@ S removechars(S)(S s, in S pattern) if (isSomeString!S) std.utf.encode(r, c); } } - return (changed? cast(S) r : s); + if (changed) + return r; + else + return s; } unittest { debug(string) printf("std.string.removechars.unittest\n"); - string r; - - r = removechars("abc", "a-c"); - assert(r.length == 0); - r = removechars("hello world", "or"); - assert(r == "hell wld"); - r = removechars("hello world", "d"); - assert(r == "hello worl"); - r = removechars("hah", "h"); - assert(r == "a"); + assertCTFEable!( + { + assert(removechars("abc", "a-c").length == 0); + assert(removechars("hello world", "or") == "hell wld"); + assert(removechars("hello world", "d") == "hello worl"); + assert(removechars("hah", "h") == "a"); + }); } @@ -2735,7 +2766,8 @@ S squeeze(S)(S s, in S pattern = null) { run = 1; if (changed) - { if (r is null) + { + if (r is null) r = s[0 .. lasti].dup; std.utf.encode(r, c); } @@ -2747,7 +2779,8 @@ S squeeze(S)(S s, in S pattern = null) { run = 0; if (changed) - { if (r is null) + { + if (r is null) r = s[0 .. lasti].dup; std.utf.encode(r, c); } @@ -2759,19 +2792,20 @@ S squeeze(S)(S s, in S pattern = null) unittest { debug(string) printf("std.string.squeeze.unittest\n"); - string s,r; - r = squeeze("hello"); - //writefln("r = '%s'", r); - assert(r == "helo"); + assertCTFEable!( + { + string s; + + assert(squeeze("hello") == "helo"); + s = "abcd"; - r = squeeze(s); - assert(r is s); + assert(squeeze(s) is s); s = "xyzz"; - r = squeeze(s); - assert(r.ptr == s.ptr); // should just be a slice - r = squeeze("hello goodbyee", "oe"); - assert(r == "hello godbye"); + assert(squeeze(s).ptr == s.ptr); // should just be a slice + + assert(squeeze("hello goodbyee", "oe") == "hello godbye"); + }); } /*************************************************************** @@ -2783,11 +2817,11 @@ unittest Example: --- -string s = "123abc"; -string t = munch(s, "0123456789"); -assert(t == "123" && s == "abc"); -t = munch(s, "0123456789"); -assert(t == "" && s == "abc"); + string s = "123abc"; + string t = munch(s, "0123456789"); + assert(t == "123" && s == "abc"); + t = munch(s, "0123456789"); + assert(t == "" && s == "abc"); --- The $(D_PARAM munch) function is mostly convenient for skipping @@ -2798,7 +2832,7 @@ strings. (In such cases, the return value is not used.) S1 munch(S1, S2)(ref S1 s, S2 pattern) { size_t j = s.length; - foreach (i, c; s) + foreach (i, dchar c; s) { if (!inPattern(c, pattern)) { @@ -2810,13 +2844,15 @@ S1 munch(S1, S2)(ref S1 s, S2 pattern) return s[0 .. j]; } -unittest +@safe pure unittest { - string s = "123abc"; + string s = "123€abc"; string t = munch(s, "0123456789"); - assert(t == "123" && s == "abc"); + assert(t == "123" && s == "€abc"); t = munch(s, "0123456789"); - assert(t == "" && s == "abc"); + assert(t == "" && s == "€abc"); + t = munch(s, "£$€¥"); + assert(t == "€" && s == "abc"); } @@ -2827,7 +2863,7 @@ unittest * repeated with the one to its immediate left. */ -S succ(S)(S s) if (isSomeString!S) +S succ(S)(S s) @safe pure if (isSomeString!S) { if (s.length && std.ascii.isAlphaNum(s[$ - 1])) { @@ -2856,7 +2892,7 @@ S succ(S)(S s) if (isSomeString!S) auto t = new typeof(r[0])[r.length + 1]; t[0] = cast(char) carry; t[1 .. $] = r[]; - return assumeUnique(t); + return t; } i--; break; @@ -2864,7 +2900,7 @@ S succ(S)(S s) if (isSomeString!S) default: if (std.ascii.isAlphaNum(c)) r[i]++; - return cast(S) r; + return r; } } } @@ -2875,20 +2911,15 @@ unittest { debug(string) printf("std.string.succ.unittest\n"); - string r; - - r = succ(cast(string) null); - assert(r is null); - r = succ("!@#$%"); - assert(r == "!@#$%"); - r = succ("1"); - assert(r == "2"); - r = succ("9"); - assert(r == "10"); - r = succ("999"); - assert(r == "1000"); - r = succ("zz99"); - assert(r == "aaa00"); + assertCTFEable!( + { + assert(succ(string.init) is null); + assert(succ("!@#$%") == "!@#$%"); + assert(succ("1") == "2"); + assert(succ("9") == "10"); + assert(succ("999") == "1000"); + assert(succ("zz99") == "aaa00"); + }); } @@ -3047,20 +3078,21 @@ unittest import std.algorithm; // Complete list of test types; too slow to test'em all - // alias TypeTuple!(char[], const(char)[], immutable(char)[], + // alias TestTypes = TypeTuple!( + // char[], const( char)[], immutable( char)[], // wchar[], const(wchar)[], immutable(wchar)[], - // dchar[], const(dchar)[], immutable(dchar)[]) - // TestTypes; + // dchar[], const(dchar)[], immutable(dchar)[]); // Reduced list of test types - alias TypeTuple!(char[], const(wchar)[], immutable(dchar)[]) - TestTypes; + alias TestTypes = TypeTuple!(char[], const(wchar)[], immutable(dchar)[]); - foreach(S; TestTypes) + assertCTFEable!( { - foreach(T; TestTypes) + foreach (S; TestTypes) + { + foreach (T; TestTypes) { - foreach(U; TestTypes) + foreach (U; TestTypes) { assert(equal(tr(to!S("abcdef"), to!T("cd"), to!U("CD")), "abCDef")); assert(equal(tr(to!S("abcdef"), to!T("b-d"), to!U("B-D")), "aBCDef")); @@ -3079,6 +3111,7 @@ unittest auto s = to!S("hello world"); static assert(is(typeof(s) == typeof(tr(s, "he", "if")))); } + }); } @@ -3129,7 +3162,7 @@ unittest * function, or any of the conversion functions. */ -bool isNumeric(const(char)[] s, in bool bAllowSep = false) +bool isNumeric(const(char)[] s, in bool bAllowSep = false) @safe pure { ptrdiff_t iLen = s.length; bool bDecimalPoint = false; @@ -3154,7 +3187,12 @@ bool isNumeric(const(char)[] s, in bool bAllowSep = false) // A sign is allowed only in the 1st character if (sx[0] == '-' || sx[0] == '+') + { + if (iLen == 1) // but must be followed by other characters + return false; + j++; + } for (int i = j; i < iLen; i++) { @@ -3168,6 +3206,7 @@ bool isNumeric(const(char)[] s, in bool bAllowSep = false) // Check for the complex type, and if found // reset the flags for checking the 2nd number. else if (c == '+') + { if (i > 0) { bDecimalPoint = false; @@ -3177,7 +3216,7 @@ bool isNumeric(const(char)[] s, in bool bAllowSep = false) } else return false; - + } // Allow only one exponent per number else if (c == 'e') { @@ -3274,9 +3313,10 @@ bool isNumeric(const(char)[] s, in bool bAllowSep = false) unittest { - debug (string) printf("isNumeric(in string, bool = false).unittest\n"); - string s; + debug(string) printf("isNumeric(in string, bool = false).unittest\n"); + assertCTFEable!( + { // Test the isNumeric(in string) function assert(isNumeric("1") == true ); assert(isNumeric("1.0") == true ); @@ -3302,14 +3342,23 @@ unittest assert(isNumeric("123f") == true); assert(isNumeric("123.u") == false); + // @@@BUG@@ to!string(float) is not CTFEable. + // Related: formatValue(T) if (is(FloatingPointTypeOf!T)) + if (!__ctfe) + { assert(isNumeric(to!string(real.nan)) == true); assert(isNumeric(to!string(-real.infinity)) == true); assert(isNumeric(to!string(123e+2+1234.78Li)) == true); + } - s = "$250.99-"; + string s = "$250.99-"; assert(isNumeric(s[1..s.length - 2]) == true); assert(isNumeric(s) == false); assert(isNumeric(s[0..s.length - 1]) == false); + }); + + assert(!isNumeric("-")); + assert(!isNumeric("+")); } @@ -3341,14 +3390,14 @@ unittest * but this one is the standard one. */ -char[] soundex(const(char)[] string, char[] buffer = null) +char[] soundex(const(char)[] string, char[] buffer = null) @safe pure nothrow in { - assert(!buffer || buffer.length >= 4); + assert(!buffer.ptr || buffer.length >= 4); } out (result) { - if (result) + if (result.ptr) { assert(result.length == 4); assert(result[0] >= 'A' && result[0] <= 'Z'); @@ -3373,12 +3422,13 @@ body { } else - { lastc = lastc.init; + { + lastc = lastc.init; continue; } if (b == 0) { - if (!buffer) + if (!buffer.ptr) buffer = new char[4]; buffer[0] = c; b++; @@ -3409,8 +3459,11 @@ body return buffer; } -unittest -{ char[4] buffer; +@safe pure nothrow unittest +{ + assertCTFEable!( + { + char[4] buffer; assert(soundex(null) == null); assert(soundex("") == null); @@ -3450,6 +3503,7 @@ unittest assert(soundex("johnsons") == "J525"); assert(soundex("Hardin") == "H635"); assert(soundex("Martinez") == "M635"); + }); } @@ -3487,12 +3541,12 @@ unittest *
*/ -string[string] abbrev(string[] values) +string[string] abbrev(string[] values) @safe pure { string[string] result; // Make a copy when sorting so we follow COW principles. - values = values.dup.sort; + values = values.dup.sort; // @@@BUG@@@ not CTFEable size_t values_length = values.length; size_t lasti = values_length; @@ -3502,25 +3556,30 @@ string[string] abbrev(string[] values) string lv; for (size_t i = 0; i < values_length; i = nexti) - { string value = values[i]; + { + string value = values[i]; - // Skip dups - for (nexti = i + 1; nexti < values_length; nexti++) - { nv = values[nexti]; - if (value != values[nexti]) - break; - } + // Skip dups + for (nexti = i + 1; nexti < values_length; nexti++) + { + nv = values[nexti]; + if (value != values[nexti]) + break; + } - for (size_t j = 0; j < value.length; j += std.utf.stride(value, j)) - { string v = value[0 .. j]; + for (size_t j = 0; j < value.length; j += std.utf.stride(value, j)) + { + string v = value[0 .. j]; - if ((nexti == values_length || j > nv.length || v != nv[0 .. j]) && - (lasti == values_length || j > lv.length || v != lv[0 .. j])) - result[v] = value; - } - result[value] = value; - lasti = i; - lv = value; + if ((nexti == values_length || j > nv.length || v != nv[0 .. j]) && + (lasti == values_length || j > lv.length || v != lv[0 .. j])) + { + result[v] = value; + } + } + result[value] = value; + lasti = i; + lv = value; } return result; @@ -3530,6 +3589,9 @@ unittest { debug(string) printf("string.abbrev.unittest\n"); + // @@@BUG@@@ Built-in arr.sort is not CTFEable + //assertCTFEable!( + //{ string[] values; values ~= "hello"; values ~= "hello"; @@ -3551,6 +3613,7 @@ unittest assert(r[keys[1]] == "hello"); assert(r[keys[2]] == "hello"); assert(r[keys[3]] == "hello"); + //}); } @@ -3559,7 +3622,7 @@ unittest * leftmost column, which is numbered starting from 0. */ -size_t column(S)(S str, size_t tabsize = 8) if (isSomeString!S) +size_t column(S)(S str, size_t tabsize = 8) @safe pure if (isSomeString!S) { size_t column; @@ -3590,11 +3653,14 @@ unittest { debug(string) printf("string.column.unittest\n"); - assert(column(cast(string) null) == 0); + assertCTFEable!( + { + assert(column(string.init) == 0); assert(column("") == 0); assert(column("\t") == 8); assert(column("abc\t") == 8); assert(column("12345678\t") == 16); + }); } /****************************************** @@ -3616,7 +3682,7 @@ unittest */ S wrap(S)(S s, size_t columns = 80, S firstindent = null, - S indent = null, size_t tabsize = 8) if (isSomeString!S) + S indent = null, size_t tabsize = 8) @safe pure if (isSomeString!S) { typeof(s.dup) result; int spaces; @@ -3677,22 +3743,23 @@ S wrap(S)(S s, size_t columns = 80, S firstindent = null, } result ~= '\n'; - return assumeUnique(result); + return result; } unittest { debug(string) printf("string.wrap.unittest\n"); - assert(wrap(cast(string) null) == "\n"); + assertCTFEable!( + { + assert(wrap(string.init) == "\n"); assert(wrap(" a b df ") == "a b df\n"); - //writefln("'%s'", wrap(" a b df ",3)); assert(wrap(" a b df ", 3) == "a b\ndf\n"); assert(wrap(" a bc df ", 3) == "a\nbc\ndf\n"); - //writefln("'%s'", wrap(" abcd df ",3)); assert(wrap(" abcd df ", 3) == "abcd\ndf\n"); assert(wrap("x") == "x\n"); assert(wrap("u u") == "u u\n"); + }); } /****************************************** @@ -3728,13 +3795,13 @@ unittest * */ -S outdent(S)(S str) if(isSomeString!S) +S outdent(S)(S str) @safe pure if(isSomeString!S) { return str.splitLines(KeepTerminator.yes).outdent().join(); } /// ditto -S[] outdent(S)(S[] lines) if(isSomeString!S) +S[] outdent(S)(S[] lines) @safe pure if(isSomeString!S) { if (lines.empty) { @@ -3763,7 +3830,8 @@ S[] outdent(S)(S[] lines) if(isSomeString!S) // because this function throws upon inconsistent indentation. if (shortestIndent is null || indent.length < shortestIndent.length) { - if (indent.empty) return lines; + if (indent.empty) + return lines; shortestIndent = indent; } } @@ -3772,6 +3840,7 @@ S[] outdent(S)(S[] lines) if(isSomeString!S) foreach (i; 0..lines.length) { auto stripped = __ctfe? lines[i].ctfe_strip() : lines[i].strip(); + if (stripped.empty) { // Do nothing @@ -3782,8 +3851,10 @@ S[] outdent(S)(S[] lines) if(isSomeString!S) } else { - if (__ctfe) assert(false, "outdent: Inconsistent indentation"); - else throw new StringException("outdent: Inconsistent indentation"); + if (__ctfe) + assert(false, "outdent: Inconsistent indentation"); + else + throw new StringException("outdent: Inconsistent indentation"); } } @@ -3815,8 +3886,10 @@ private S ctfe_stripRight(S)(S str) if(isSomeString!(Unqual!S)) return str[0..endIndex]; } -version(unittest) +unittest { + debug(string) printf("string.outdent.unittest\n"); + template outdent_testStr(S) { enum S outdent_testStr = @@ -3840,12 +3913,9 @@ version(unittest) \t\tX "; } -} - -unittest -{ - debug(string) printf("string.outdent.unittest\n"); + assertCTFEable!( + { static assert(ctfe_strip(" \tHi \r\n") == "Hi"); static assert(ctfe_strip(" \tHi©\u2028 \r\n") == "Hi©"); static assert(ctfe_strip("Hi") == "Hi"); @@ -3905,4 +3975,5 @@ unittest assert(testStr6.outdent() == expected6); static assert(testStr6.outdent() == expected6); } + }); } diff --git a/std/traits.d b/std/traits.d index 72203467d..ae248d6f5 100644 --- a/std/traits.d +++ b/std/traits.d @@ -4,6 +4,127 @@ * Templates with which to extract information about types and symbols at * compile time. * + * + * + * $(BOOKTABLE , + * $(TR $(TH Category) $(TH Templates)) + * $(TR $(TD Symbol Name _traits) $(TD + * $(LREF packageName) + * $(LREF moduleName) + * $(LREF fullyQualifiedName) + * )) + * $(TR $(TD Function _traits) $(TD + * $(LREF ReturnType) + * $(LREF ParameterTypeTuple) + * $(LREF arity) + * $(LREF ParameterStorageClassTuple) + * $(LREF ParameterIdentifierTuple) + * $(LREF ParameterDefaultValueTuple) + * $(LREF functionAttributes) + * $(LREF isSafe) + * $(LREF isUnsafe) + * $(LREF functionLinkage) + * $(LREF variadicFunctionStyle) + * $(LREF FunctionTypeOf) + * $(LREF SetFunctionAttributes) + * )) + * $(TR $(TD Aggregate Type _traits) $(TD + * $(LREF isNested) + * $(LREF hasNested) + * $(LREF FieldTypeTuple) + * $(LREF RepresentationTypeTuple) + * $(LREF hasAliasing) + * $(LREF hasIndirections) + * $(LREF hasUnsharedAliasing) + * $(LREF hasElaborateCopyConstructor) + * $(LREF hasElaborateAssign) + * $(LREF hasElaborateDestructor) + * $(LREF hasMember) + * $(LREF EnumMembers) + * $(LREF BaseTypeTuple) + * $(LREF BaseClassesTuple) + * $(LREF InterfacesTuple) + * $(LREF TransitiveBaseTypeTuple) + * $(LREF MemberFunctionsTuple) + * $(LREF classInstanceAlignment) + * )) + * $(TR $(TD Type Conversion) $(TD + * $(LREF CommonType) + * $(LREF ImplicitConversionTargets) + * $(LREF isImplicitlyConvertible) + * $(LREF isAssignable) + * $(LREF isCovariantWith) + * )) + * + * $(TR $(TD IsSomething) $(TD + * $(LREF isBoolean) + * $(LREF isIntegral) + * $(LREF isFloatingPoint) + * $(LREF isNumeric) + * $(LREF isScalarType) + * $(LREF isBasicType) + * $(LREF isUnsigned) + * $(LREF isSigned) + * $(LREF isSomeChar) + * $(LREF isSomeString) + * $(LREF isNarrowString) + * $(LREF isStaticArray) + * $(LREF isDynamicArray) + * $(LREF isArray) + * $(LREF isAssociativeArray) + * $(LREF isBuiltinType) + * $(LREF isPointer) + * $(LREF isAggregateType) + * )) + * $(TR $(TD xxx) $(TD + * $(LREF isIterable) + * $(LREF isMutable) + * $(LREF isInstanceOf) + * $(LREF isExpressionTuple) + * $(LREF isTypeTuple) + * $(LREF isFunctionPointer) + * $(LREF isDelegate) + * $(LREF isSomeFunction) + * $(LREF isCallable) + * $(LREF isAbstractFunction) + * $(LREF isFinalFunction) + * $(LREF isAbstractClass) + * $(LREF isFinalClass) + * )) + * $(TR $(TD General Types) $(TD + * $(LREF Unqual) + * $(LREF ForeachType) + * $(LREF OriginalType) + * $(LREF PointerTarget) + * $(LREF KeyType) + * $(LREF ValueType) + * $(LREF Unsigned) + * $(LREF Largest) + * $(LREF Signed) + * $(LREF unsigned) + * $(LREF mostNegative) + * )) + * $(TR $(TD Misc) $(TD + * $(LREF mangledName) + * $(LREF Select) + * $(LREF select) + * )) + * ) + * * Macros: * WIKI = Phobos/StdTraits * @@ -124,18 +245,53 @@ package else @property T defaultInit(); } + + // Add specific qualifier to the given type T + template MutableOf(T) { alias MutableOf = T ; } + template InoutOf(T) { alias InoutOf = inout(T) ; } + template ConstOf(T) { alias ConstOf = const(T) ; } + template SharedOf(T) { alias SharedOf = shared(T) ; } + template SharedInoutOf(T) { alias SharedInoutOf = shared(inout(T)); } + template SharedConstOf(T) { alias SharedConstOf = shared(const(T)); } + template ImmutableOf(T) { alias ImmutableOf = immutable(T) ; } + + unittest + { + static assert(is( MutableOf!int == int)); + static assert(is( InoutOf!int == inout int)); + static assert(is( ConstOf!int == const int)); + static assert(is( SharedOf!int == shared int)); + static assert(is(SharedInoutOf!int == shared inout int)); + static assert(is(SharedConstOf!int == shared const int)); + static assert(is( ImmutableOf!int == immutable int)); + } + + // Get qualifier template from the given type T + template QualifierOf(T) + { + static if (is(T == shared(const U), U)) alias QualifierOf = SharedConstOf; + else static if (is(T == const U , U)) alias QualifierOf = ConstOf; + else static if (is(T == shared(inout U), U)) alias QualifierOf = SharedInoutOf; + else static if (is(T == inout U , U)) alias QualifierOf = InoutOf; + else static if (is(T == immutable U , U)) alias QualifierOf = ImmutableOf; + else static if (is(T == shared U , U)) alias QualifierOf = SharedOf; + else alias QualifierOf = MutableOf; + } + + unittest + { + alias Qual1 = QualifierOf!( int); static assert(is(Qual1!long == long)); + alias Qual2 = QualifierOf!( inout int); static assert(is(Qual2!long == inout long)); + alias Qual3 = QualifierOf!( const int); static assert(is(Qual3!long == const long)); + alias Qual4 = QualifierOf!(shared int); static assert(is(Qual4!long == shared long)); + alias Qual5 = QualifierOf!(shared inout int); static assert(is(Qual5!long == shared inout long)); + alias Qual6 = QualifierOf!(shared const int); static assert(is(Qual6!long == shared const long)); + alias Qual7 = QualifierOf!( immutable int); static assert(is(Qual7!long == immutable long)); + } } version(unittest) { - template MutableOf(T) { alias T MutableOf; } - template ConstOf(T) { alias const(T) ConstOf; } - template SharedOf(T) { alias shared(T) SharedOf; } - template SharedConstOf(T) { alias shared(const(T)) SharedConstOf; } - template ImmutableOf(T) { alias immutable(T) ImmutableOf; } - template WildOf(T) { alias inout(T) WildOf; } - template SharedWildOf(T) { alias shared(inout(T)) SharedWildOf; } - alias TypeTuple!(MutableOf, ConstOf, SharedOf, SharedConstOf, ImmutableOf) TypeQualifierList; struct SubTypeOf(T) @@ -156,13 +312,13 @@ version(unittest) */ template packageName(alias T) { - static if (is(typeof(__traits(parent, T)))) + static if (__traits(compiles, __traits(parent, T))) enum parent = packageName!(__traits(parent, T)); else enum string parent = null; static if (T.stringof.startsWith("package ")) - enum packageName = (parent ? parent ~ '.' : "") ~ T.stringof[8 .. $]; + enum packageName = (parent.length ? parent ~ '.' : "") ~ T.stringof[8 .. $]; else static if (parent) enum packageName = parent; else @@ -288,6 +444,11 @@ version(unittest) shared(immutable(Inner) delegate(ref double, scope string) const shared @trusted nothrow) attrDeleg; } + + private enum QualifiedEnum + { + a = 42 + } } private template fullyQualifiedNameImplForSymbols(alias T) @@ -452,11 +613,11 @@ private template fullyQualifiedNameImplForTypes(T, { enum fullyQualifiedNameImplForTypes = "dstring"; } - else static if (isBasicType!T || is(T == enum)) + else static if (isBasicType!T && !is(T == enum)) { enum fullyQualifiedNameImplForTypes = chain!((Unqual!T).stringof); } - else static if (isAggregateType!T) + else static if (isAggregateType!T || is(T == enum)) { enum fullyQualifiedNameImplForTypes = chain!(fullyQualifiedNameImplForSymbols!T); } @@ -540,6 +701,8 @@ unittest // Basic qualified name static assert(fqn!(Inner) == inner_name); + static assert(fqn!(QualifiedEnum) == "std.traits.QualifiedEnum"); // type + static assert(fqn!(QualifiedEnum.a) == "std.traits.QualifiedEnum.a"); // symbol // Array types static assert(fqn!(typeof(array)) == format("%s[]", inner_name)); @@ -730,7 +893,7 @@ enum ParameterStorageClass : uint * These flags can be bitwise OR-ed together to represent complex storage * class. */ - none = 0, /// ditto + none = 0, scope_ = 0b000_1, /// ditto out_ = 0b001_0, /// ditto ref_ = 0b010_0, /// ditto @@ -829,18 +992,18 @@ static assert([ParameterIdentifierTuple!foo] == ["num", "name"]); template ParameterIdentifierTuple(func...) if (func.length == 1 && isCallable!func) { - static if (is(typeof(func[0]) PT == __parameters)) + static if (is(FunctionTypeOf!func PT == __parameters)) { template Get(size_t i) { - enum Get = __traits(identifier, PT[i..i+1]); - } - } - else static if (is(FunctionTypeOf!func PT == __parameters)) - { - template Get(size_t i) - { - enum Get = ""; + static if (!isFunctionPointer!func && !isDelegate!func) + { + enum Get = __traits(identifier, PT[i..i+1]); + } + else + { + enum Get = ""; + } } } else @@ -884,6 +1047,17 @@ unittest // might be changed in the future? void delegate(int num, string name, int[long] aa) dg; static assert([PIT!dg] == ["", "", ""]); + + interface Test + { + @property string getter(); + @property void setter(int a); + Test method(int a, long b, string c); + } + static assert([PIT!(Test.getter)] == []); + static assert([PIT!(Test.setter)] == ["a"]); + static assert([PIT!(Test.method)] == ["a", "b", "c"]); + /+ // depends on internal void baw(int, string, int[]){} @@ -912,7 +1086,7 @@ static assert( ParameterDefaultValueTuple!foo[2] == [1,2,3]); template ParameterDefaultValueTuple(func...) if (func.length == 1 && isCallable!func) { - static if (is(typeof(func[0]) PT == __parameters)) + static if (is(FunctionTypeOf!(func[0]) PT == __parameters)) { template Get(size_t i) { @@ -976,6 +1150,12 @@ unittest static assert( PDVT!baz[2] == "hello"); static assert(is(typeof(PDVT!baz) == typeof(TypeTuple!(void, 1, "hello")))); + // bug 10800 - property functions return empty string + @property void foo(int x = 3) { } + static assert(PDVT!foo.length == 1); + static assert(PDVT!foo[0] == 3); + static assert(is(typeof(PDVT!foo) == typeof(TypeTuple!(3)))); + struct Colour { ubyte a,r,g,b; @@ -1009,7 +1189,7 @@ enum FunctionAttribute : uint /** * These flags can be bitwise OR-ed together to represent complex attribute. */ - none = 0, /// ditto + none = 0, pure_ = 0b00000001, /// ditto nothrow_ = 0b00000010, /// ditto ref_ = 0b00000100, /// ditto @@ -2839,10 +3019,8 @@ template hasElaborateAssign(S) } else static if(is(S == struct)) { - @property auto ref lvalueOf() { static S s = void; return s; } - - enum hasElaborateAssign = is(typeof(S.init.opAssign(S.init))) || - is(typeof(S.init.opAssign(lvalueOf))) || + enum hasElaborateAssign = is(typeof(S.init.opAssign(rvalueOf!S))) || + is(typeof(S.init.opAssign(lvalueOf!S))) || anySatisfy!(.hasElaborateAssign, FieldTypeTuple!S); } else @@ -2875,6 +3053,13 @@ unittest } static assert( hasElaborateAssign!S4); + static struct S41 + { + void opAssign(U)(ref U u) {} + @disable void opAssign(U)(U u); + } + static assert( hasElaborateAssign!S41); + static struct S5 { @disable this(); this(int n){ s = S(); } S s; } static assert( hasElaborateAssign!S5); @@ -3027,6 +3212,12 @@ Returns: Static tuple composed of the members of the enumerated type $(D E). The members are arranged in the same order as declared in $(D E). +Note: + An enum can have multiple members which have the same value. If you want + to use EnumMembers to e.g. generate switch cases at compile-time, + you should use the $(XREF typetuple, NoDuplicates) template to avoid + generating duplicate switch cases. + Note: Returned values are strictly typed with $(D E). Thus, the following code does not work without the explicit cast: @@ -3715,14 +3906,10 @@ template ImplicitConversionTargets(T) else static if (is(T : typeof(null))) alias TypeTuple!(typeof(null)) ImplicitConversionTargets; else static if(is(T : Object)) - alias TransitiveBaseTypeTuple!T ImplicitConversionTargets; - // @@@BUG@@@ this should work - // else static if (isDynamicArray!T && !is(typeof(T.init[0]) == const)) - // alias TypeTuple!(const(typeof(T.init[0]))[]) ImplicitConversionTargets; - else static if (is(T == char[])) - alias TypeTuple!(const(char)[]) ImplicitConversionTargets; + alias TransitiveBaseTypeTuple!(T) ImplicitConversionTargets; else static if (isDynamicArray!T && !is(typeof(T.init[0]) == const)) - alias TypeTuple!(const(typeof(T.init[0]))[]) ImplicitConversionTargets; + alias ImplicitConversionTargets = + TypeTuple!(const(Unqual!(typeof(T.init[0])))[]); else static if (is(T : void*)) alias TypeTuple!(void*) ImplicitConversionTargets; else @@ -3731,7 +3918,8 @@ template ImplicitConversionTargets(T) unittest { - assert(is(ImplicitConversionTargets!double[0] == real)); + static assert(is(ImplicitConversionTargets!(double)[0] == real)); + static assert(is(ImplicitConversionTargets!(string)[0] == const(char)[])); } /** @@ -3770,41 +3958,45 @@ unittest Returns $(D true) iff a value of type $(D Rhs) can be assigned to a variable of type $(D Lhs). +$(D isAssignable) returns whether both an lvalue and rvalue can be assigned. + If you omit $(D Rhs), $(D isAssignable) will check identity assignable of $(D Lhs). - -Examples: ---- -static assert(isAssignable!(long, int)); -static assert(!isAssignable!(int, long)); -static assert( isAssignable!(const(char)[], string)); -static assert(!isAssignable!(string, char[])); - -// int is assignable to int -static assert( isAssignable!int); - -// immutable int is not assinable to immutable int -static assert(!isAssignable!(immutable int)); ---- */ -template isAssignable(Lhs, Rhs = Lhs) -{ - enum bool isAssignable = is(typeof({ - Lhs l = void; - void f(Rhs r) { l = r; } - return l; - })); -} +enum isAssignable(Lhs, Rhs = Lhs) = isRvalueAssignable!(Lhs, Rhs) && isLvalueAssignable!(Lhs, Rhs); +/// unittest { static assert( isAssignable!(long, int)); - static assert( isAssignable!(const(char)[], string)); - static assert(!isAssignable!(int, long)); + static assert( isAssignable!(const(char)[], string)); static assert(!isAssignable!(string, char[])); - static assert(!isAssignable!(immutable(int), int)); - static assert( isAssignable!(int, immutable(int))); + // int is assignable to int + static assert( isAssignable!int); + + // immutable int is not assinable to immutable int + static assert(!isAssignable!(immutable int)); +} + +// ditto +private enum isRvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, lvalueOf!Lhs = rvalueOf!Rhs); + +// ditto +private enum isLvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, lvalueOf!Lhs = lvalueOf!Rhs); + +unittest +{ + static assert(!isAssignable!(immutable int, int)); + static assert( isAssignable!(int, immutable int)); + + static assert(!isAssignable!(inout int, int)); + static assert( isAssignable!(int, inout int)); + static assert(!isAssignable!(inout int)); + + static assert( isAssignable!(shared int, int)); + static assert( isAssignable!(int, shared int)); + static assert( isAssignable!(shared int)); struct S { @disable this(); this(int n){} } static assert( isAssignable!(S, S)); @@ -3822,17 +4014,14 @@ unittest struct S4 { void opAssign(int); } static assert( isAssignable!(S4, S4)); static assert( isAssignable!(S4, int)); - static assert( isAssignable!(S4, immutable(int))); + static assert( isAssignable!(S4, immutable int)); struct S5 { @disable this(); @disable this(this); } struct S6 { void opAssign(in ref S5); } - static assert( isAssignable!(S6, S5)); - static assert( isAssignable!(S6, immutable(S5))); -} -unittest -{ - static assert( isAssignable!int); - static assert(!isAssignable!(immutable int)); + static assert(!isAssignable!(S6, S5)); + static assert(!isRvalueAssignable!(S6, S5)); + static assert( isLvalueAssignable!(S6, S5)); + static assert( isLvalueAssignable!(S6, immutable S5)); } @@ -4055,25 +4244,86 @@ unittest } +// Needed for rvalueOf/lvalueOf because "inout on return means +// inout must be on a parameter as well" +private struct __InoutWorkaroundStruct{} + +/** +Creates an lvalue or rvalue of type $(D T) for $(D typeof(...)) and +$(D __traits(compiles, ...)) purposes. No actual value is returned. + +Note: Trying to use returned value will result in a +"Symbol Undefined" error at link time. + +Examples: +--- +// Note that `f` doesn't have to be implemented +// as is isn't called. +int f(int); +bool f(ref int); +static assert(is(typeof(f(rvalueOf!int)) == int)); +static assert(is(typeof(f(lvalueOf!int)) == bool)); + +int i = rvalueOf!int; // error, no actual value is returned +--- +*/ +@property T rvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init); + +/// ditto +@property ref T lvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init); + +// Note: unittest can't be used as an example here as function overloads +// aren't allowed inside functions. + +unittest +{ + void needLvalue(T)(ref T); + static struct S { } + int i; + struct Nested { void f() { ++i; } } + foreach(T; TypeTuple!(int, immutable int, inout int, string, S, Nested, Object)) + { + static assert(!__traits(compiles, needLvalue(rvalueOf!T))); + static assert( __traits(compiles, needLvalue(lvalueOf!T))); + static assert(is(typeof(rvalueOf!T) == T)); + static assert(is(typeof(lvalueOf!T) == T)); + } + + static assert(!__traits(compiles, rvalueOf!int = 1)); + static assert( __traits(compiles, lvalueOf!byte = 127)); + static assert(!__traits(compiles, lvalueOf!byte = 128)); +} + + //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// // SomethingTypeOf //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// +private template AliasThisTypeOf(T) if (isAggregateType!T) +{ + alias members = TypeTuple!(__traits(getAliasThis, T)); + + static if (members.length == 1) + { + alias AliasThisTypeOf = typeof(__traits(getMember, T.init, members[0])); + } + else + static assert(0, T.stringof~" does not have alias this type"); +} + /* */ template BooleanTypeOf(T) { - inout(bool) idx( inout(bool) ); - shared(inout bool) idx( shared(inout bool) ); + static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT)) + alias X = BooleanTypeOf!AT; + else + alias X = OriginalType!T; - immutable(bool) idy( immutable(bool) ); - - static if (is(T == enum)) - alias .BooleanTypeOf!(OriginalType!T) BooleanTypeOf; - else static if (is(typeof(idx(T.init)) X) && !is(IntegralTypeOf!T)) - alias X BooleanTypeOf; - else static if (is(typeof(idy(T.init)) X) && is(Unqual!X == bool) && !is(IntegralTypeOf!T)) - alias X BooleanTypeOf; + static if (is(Unqual!X == bool)) + { + alias BooleanTypeOf = X; + } else static assert(0, T.stringof~" is not boolean type"); } @@ -4082,60 +4332,49 @@ unittest { // unexpected failure, maybe dmd type-merging bug foreach (T; TypeTuple!bool) - foreach (Q; TypeQualifierList) - { - static assert( is(Q!T == BooleanTypeOf!( Q!T ))); - static assert( is(Q!T == BooleanTypeOf!( SubTypeOf!(Q!T) ))); - } + foreach (Q; TypeQualifierList) + { + static assert( is(Q!T == BooleanTypeOf!( Q!T ))); + static assert( is(Q!T == BooleanTypeOf!( SubTypeOf!(Q!T) ))); + } + foreach (T; TypeTuple!(void, NumericTypeList, ImaginaryTypeList, ComplexTypeList, CharTypeList)) - foreach (Q; TypeQualifierList) + foreach (Q; TypeQualifierList) + { + static assert(!is(BooleanTypeOf!( Q!T )), Q!T.stringof); + static assert(!is(BooleanTypeOf!( SubTypeOf!(Q!T) ))); + } +} + +unittest +{ + struct B { - static assert(!is(BooleanTypeOf!( Q!T )), Q!T.stringof); - static assert(!is(BooleanTypeOf!( SubTypeOf!(Q!T) ))); + bool val; + alias val this; } + struct S + { + B b; + alias b this; + } + static assert(is(BooleanTypeOf!B == bool)); + static assert(is(BooleanTypeOf!S == bool)); } /* */ template IntegralTypeOf(T) { - inout( byte) idx( inout( byte) ); - inout( ubyte) idx( inout( ubyte) ); - inout( short) idx( inout( short) ); - inout(ushort) idx( inout(ushort) ); - inout( int) idx( inout( int) ); - inout( uint) idx( inout( uint) ); - inout( long) idx( inout( long) ); - inout( ulong) idx( inout( ulong) ); - shared(inout byte) idx( shared(inout byte) ); - shared(inout ubyte) idx( shared(inout ubyte) ); - shared(inout short) idx( shared(inout short) ); - shared(inout ushort) idx( shared(inout ushort) ); - shared(inout int) idx( shared(inout int) ); - shared(inout uint) idx( shared(inout uint) ); - shared(inout long) idx( shared(inout long) ); - shared(inout ulong) idx( shared(inout ulong) ); + static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT)) + alias X = IntegralTypeOf!AT; + else + alias X = OriginalType!T; - immutable( char) idy( immutable( char) ); - immutable( wchar) idy( immutable( wchar) ); - immutable( dchar) idy( immutable( dchar) ); - // Integrals and characers are impilcit convertible each other with value copy. - // Then adding exact overloads to detect it. - immutable( byte) idy( immutable( byte) ); - immutable( ubyte) idy( immutable( ubyte) ); - immutable( short) idy( immutable( short) ); - immutable(ushort) idy( immutable(ushort) ); - immutable( int) idy( immutable( int) ); - immutable( uint) idy( immutable( uint) ); - immutable( long) idy( immutable( long) ); - immutable( ulong) idy( immutable( ulong) ); - - static if (is(T == enum)) - alias .IntegralTypeOf!(OriginalType!T) IntegralTypeOf; - else static if (is(typeof(idx(T.init)) X)) - alias X IntegralTypeOf; - else static if (is(typeof(idy(T.init)) X) && staticIndexOf!(Unqual!X, IntegralTypeList) >= 0) - alias X IntegralTypeOf; + static if (staticIndexOf!(Unqual!X, IntegralTypeList) >= 0) + { + alias IntegralTypeOf = X; + } else static assert(0, T.stringof~" is not an integral type"); } @@ -4143,40 +4382,33 @@ template IntegralTypeOf(T) unittest { foreach (T; IntegralTypeList) - foreach (Q; TypeQualifierList) - { - static assert( is(Q!T == IntegralTypeOf!( Q!T ))); - static assert( is(Q!T == IntegralTypeOf!( SubTypeOf!(Q!T) ))); - } + foreach (Q; TypeQualifierList) + { + static assert( is(Q!T == IntegralTypeOf!( Q!T ))); + static assert( is(Q!T == IntegralTypeOf!( SubTypeOf!(Q!T) ))); + } + foreach (T; TypeTuple!(void, bool, FloatingPointTypeList, ImaginaryTypeList, ComplexTypeList, CharTypeList)) - foreach (Q; TypeQualifierList) - { - static assert(!is(IntegralTypeOf!( Q!T ))); - static assert(!is(IntegralTypeOf!( SubTypeOf!(Q!T) ))); - } + foreach (Q; TypeQualifierList) + { + static assert(!is(IntegralTypeOf!( Q!T ))); + static assert(!is(IntegralTypeOf!( SubTypeOf!(Q!T) ))); + } } /* */ template FloatingPointTypeOf(T) { - inout( float) idx( inout( float) ); - inout(double) idx( inout(double) ); - inout( real) idx( inout( real) ); - shared(inout float) idx( shared(inout float) ); - shared(inout double) idx( shared(inout double) ); - shared(inout real) idx( shared(inout real) ); + static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT)) + alias X = FloatingPointTypeOf!AT; + else + alias X = OriginalType!T; - immutable( float) idy( immutable( float) ); - immutable(double) idy( immutable(double) ); - immutable( real) idy( immutable( real) ); - - static if (is(T == enum)) - alias .FloatingPointTypeOf!(OriginalType!T) FloatingPointTypeOf; - else static if (is(typeof(idx(T.init)) X)) - alias X FloatingPointTypeOf; - else static if (is(typeof(idy(T.init)) X)) - alias X FloatingPointTypeOf; + static if (staticIndexOf!(Unqual!X, FloatingPointTypeList) >= 0) + { + alias FloatingPointTypeOf = X; + } else static assert(0, T.stringof~" is not a floating point type"); } @@ -4184,27 +4416,28 @@ template FloatingPointTypeOf(T) unittest { foreach (T; FloatingPointTypeList) - foreach (Q; TypeQualifierList) - { - static assert( is(Q!T == FloatingPointTypeOf!( Q!T ))); - static assert( is(Q!T == FloatingPointTypeOf!( SubTypeOf!(Q!T) ))); - } + foreach (Q; TypeQualifierList) + { + static assert( is(Q!T == FloatingPointTypeOf!( Q!T ))); + static assert( is(Q!T == FloatingPointTypeOf!( SubTypeOf!(Q!T) ))); + } + foreach (T; TypeTuple!(void, bool, IntegralTypeList, ImaginaryTypeList, ComplexTypeList, CharTypeList)) - foreach (Q; TypeQualifierList) - { - static assert(!is(FloatingPointTypeOf!( Q!T ))); - static assert(!is(FloatingPointTypeOf!( SubTypeOf!(Q!T) ))); - } + foreach (Q; TypeQualifierList) + { + static assert(!is(FloatingPointTypeOf!( Q!T ))); + static assert(!is(FloatingPointTypeOf!( SubTypeOf!(Q!T) ))); + } } /* */ template NumericTypeOf(T) { - static if (is(IntegralTypeOf!T X)) - alias X NumericTypeOf; - else static if (is(FloatingPointTypeOf!T X)) - alias X NumericTypeOf; + static if (is(IntegralTypeOf!T X) || is(FloatingPointTypeOf!T X)) + { + alias NumericTypeOf = X; + } else static assert(0, T.stringof~" is not a numeric type"); } @@ -4212,17 +4445,18 @@ template NumericTypeOf(T) unittest { foreach (T; NumericTypeList) - foreach (Q; TypeQualifierList) - { - static assert( is(Q!T == NumericTypeOf!( Q!T ))); - static assert( is(Q!T == NumericTypeOf!( SubTypeOf!(Q!T) ))); - } + foreach (Q; TypeQualifierList) + { + static assert( is(Q!T == NumericTypeOf!( Q!T ))); + static assert( is(Q!T == NumericTypeOf!( SubTypeOf!(Q!T) ))); + } + foreach (T; TypeTuple!(void, bool, CharTypeList, ImaginaryTypeList, ComplexTypeList)) - foreach (Q; TypeQualifierList) - { - static assert(!is(NumericTypeOf!( Q!T ))); - static assert(!is(NumericTypeOf!( SubTypeOf!(Q!T) ))); - } + foreach (Q; TypeQualifierList) + { + static assert(!is(NumericTypeOf!( Q!T ))); + static assert(!is(NumericTypeOf!( SubTypeOf!(Q!T) ))); + } } /* @@ -4231,7 +4465,7 @@ template UnsignedTypeOf(T) { static if (is(IntegralTypeOf!T X) && staticIndexOf!(Unqual!X, UnsignedIntTypeList) >= 0) - alias X UnsignedTypeOf; + alias UnsignedTypeOf = X; else static assert(0, T.stringof~" is not an unsigned type."); } @@ -4242,9 +4476,9 @@ template SignedTypeOf(T) { static if (is(IntegralTypeOf!T X) && staticIndexOf!(Unqual!X, SignedIntTypeList) >= 0) - alias X SignedTypeOf; + alias SignedTypeOf = X; else static if (is(FloatingPointTypeOf!T X)) - alias X SignedTypeOf; + alias SignedTypeOf = X; else static assert(0, T.stringof~" is not an signed type."); } @@ -4253,33 +4487,15 @@ template SignedTypeOf(T) */ template CharTypeOf(T) { - inout( char) idx( inout( char) ); - inout(wchar) idx( inout(wchar) ); - inout(dchar) idx( inout(dchar) ); - shared(inout char) idx( shared(inout char) ); - shared(inout wchar) idx( shared(inout wchar) ); - shared(inout dchar) idx( shared(inout dchar) ); + static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT)) + alias X = CharTypeOf!AT; + else + alias X = OriginalType!T; - immutable( char) idy( immutable( char) ); - immutable( wchar) idy( immutable( wchar) ); - immutable( dchar) idy( immutable( dchar) ); - // Integrals and characers are impilcit convertible each other with value copy. - // Then adding exact overloads to detect it. - immutable( byte) idy( immutable( byte) ); - immutable( ubyte) idy( immutable( ubyte) ); - immutable( short) idy( immutable( short) ); - immutable(ushort) idy( immutable(ushort) ); - immutable( int) idy( immutable( int) ); - immutable( uint) idy( immutable( uint) ); - immutable( long) idy( immutable( long) ); - immutable( ulong) idy( immutable( ulong) ); - - static if (is(T == enum)) - alias .CharTypeOf!(OriginalType!T) CharTypeOf; - else static if (is(typeof(idx(T.init)) X)) - alias X CharTypeOf; - else static if (is(typeof(idy(T.init)) X) && staticIndexOf!(Unqual!X, CharTypeList) >= 0) - alias X CharTypeOf; + static if (staticIndexOf!(Unqual!X, CharTypeList) >= 0) + { + alias CharTypeOf = X; + } else static assert(0, T.stringof~" is not a character type"); } @@ -4287,35 +4503,38 @@ template CharTypeOf(T) unittest { foreach (T; CharTypeList) - foreach (Q; TypeQualifierList) - { - static assert( is(CharTypeOf!( Q!T ))); - static assert( is(CharTypeOf!( SubTypeOf!(Q!T) ))); - } + foreach (Q; TypeQualifierList) + { + static assert( is(CharTypeOf!( Q!T ))); + static assert( is(CharTypeOf!( SubTypeOf!(Q!T) ))); + } + foreach (T; TypeTuple!(void, bool, NumericTypeList, ImaginaryTypeList, ComplexTypeList)) - foreach (Q; TypeQualifierList) - { - static assert(!is(CharTypeOf!( Q!T ))); - static assert(!is(CharTypeOf!( SubTypeOf!(Q!T) ))); - } + foreach (Q; TypeQualifierList) + { + static assert(!is(CharTypeOf!( Q!T ))); + static assert(!is(CharTypeOf!( SubTypeOf!(Q!T) ))); + } + foreach (T; TypeTuple!(string, wstring, dstring, char[4])) - foreach (Q; TypeQualifierList) - { - static assert(!is(CharTypeOf!( Q!T ))); - static assert(!is(CharTypeOf!( SubTypeOf!(Q!T) ))); - } + foreach (Q; TypeQualifierList) + { + static assert(!is(CharTypeOf!( Q!T ))); + static assert(!is(CharTypeOf!( SubTypeOf!(Q!T) ))); + } } /* */ template StaticArrayTypeOf(T) { - inout(U[n]) idx(U, size_t n)( inout(U[n]) ); + static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT)) + alias X = StaticArrayTypeOf!AT; + else + alias X = OriginalType!T; - static if (is(T == enum)) - alias .StaticArrayTypeOf!(OriginalType!T) StaticArrayTypeOf; - else static if (is(typeof(idx(defaultInit!T)) X)) - alias X StaticArrayTypeOf; + static if (is(X : E[n], E, size_t n)) + alias StaticArrayTypeOf = X; else static assert(0, T.stringof~" is not a static array type"); } @@ -4323,44 +4542,35 @@ template StaticArrayTypeOf(T) unittest { foreach (T; TypeTuple!(bool, NumericTypeList, ImaginaryTypeList, ComplexTypeList)) - foreach (Q; TypeTuple!(TypeQualifierList, WildOf, SharedWildOf)) - { - static assert(is( Q!( T[1] ) == StaticArrayTypeOf!( Q!( T[1] ) ) )); + foreach (Q; TypeTuple!(TypeQualifierList, InoutOf, SharedInoutOf)) + { + static assert(is( Q!( T[1] ) == StaticArrayTypeOf!( Q!( T[1] ) ) )); + + foreach (P; TypeQualifierList) + { // SubTypeOf cannot have inout type + static assert(is( Q!(P!(T[1])) == StaticArrayTypeOf!( Q!(SubTypeOf!(P!(T[1]))) ) )); + } + } - foreach (P; TypeQualifierList) - { // SubTypeOf cannot have inout type - static assert(is( Q!(P!(T[1])) == StaticArrayTypeOf!( Q!(SubTypeOf!(P!(T[1]))) ) )); - } - } foreach (T; TypeTuple!void) - foreach (Q; TypeTuple!TypeQualifierList) - { - static assert(is( StaticArrayTypeOf!( Q!(void[1]) ) == Q!(void[1]) )); - } + foreach (Q; TypeTuple!TypeQualifierList) + { + static assert(is( StaticArrayTypeOf!( Q!(void[1]) ) == Q!(void[1]) )); + } } /* */ template DynamicArrayTypeOf(T) { - inout(U[]) idx(U)( inout(U[]) ); + static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT)) + alias X = DynamicArrayTypeOf!AT; + else + alias X = OriginalType!T; - static if (is(T == enum)) - alias .DynamicArrayTypeOf!(OriginalType!T) DynamicArrayTypeOf; - else static if (!is(StaticArrayTypeOf!T) && - is(typeof(idx(defaultInit!T)) X)) + static if (is(Unqual!X : E[], E) && !is(typeof({ enum n = X.length; }))) { - alias typeof(defaultInit!T[0]) E; - - E[] idy( E[] ); - const(E[]) idy( const(E[]) ); - inout(E[]) idy( inout(E[]) ); - shared( E[]) idy( shared( E[]) ); - shared(const E[]) idy( shared(const E[]) ); - shared(inout E[]) idy( shared(inout E[]) ); - immutable(E[]) idy( immutable(E[]) ); - - alias typeof(idy(defaultInit!T)) DynamicArrayTypeOf; + alias DynamicArrayTypeOf = X; } else static assert(0, T.stringof~" is not a dynamic array"); @@ -4369,17 +4579,17 @@ template DynamicArrayTypeOf(T) unittest { foreach (T; TypeTuple!(/*void, */bool, NumericTypeList, ImaginaryTypeList, ComplexTypeList)) - foreach (Q; TypeTuple!(TypeQualifierList, WildOf, SharedWildOf)) - { - static assert(is( Q!T[] == DynamicArrayTypeOf!( Q!T[] ) )); - static assert(is( Q!(T[]) == DynamicArrayTypeOf!( Q!(T[]) ) )); + foreach (Q; TypeTuple!(TypeQualifierList, InoutOf, SharedInoutOf)) + { + static assert(is( Q!T[] == DynamicArrayTypeOf!( Q!T[] ) )); + static assert(is( Q!(T[]) == DynamicArrayTypeOf!( Q!(T[]) ) )); - foreach (P; TypeTuple!(MutableOf, ConstOf, ImmutableOf)) - { - static assert(is( Q!(P!T[]) == DynamicArrayTypeOf!( Q!(SubTypeOf!(P!T[])) ) )); - static assert(is( Q!(P!(T[])) == DynamicArrayTypeOf!( Q!(SubTypeOf!(P!(T[]))) ) )); - } - } + foreach (P; TypeTuple!(MutableOf, ConstOf, ImmutableOf)) + { + static assert(is( Q!(P!T[]) == DynamicArrayTypeOf!( Q!(SubTypeOf!(P!T[])) ) )); + static assert(is( Q!(P!(T[])) == DynamicArrayTypeOf!( Q!(SubTypeOf!(P!(T[]))) ) )); + } + } static assert(!is(DynamicArrayTypeOf!(int[3]))); static assert(!is(DynamicArrayTypeOf!(void[3]))); @@ -4390,10 +4600,10 @@ unittest */ template ArrayTypeOf(T) { - static if (is(StaticArrayTypeOf!T X)) - alias X ArrayTypeOf; - else static if (is(DynamicArrayTypeOf!T X)) - alias X ArrayTypeOf; + static if (is(StaticArrayTypeOf!T X) || is(DynamicArrayTypeOf!T X)) + { + alias ArrayTypeOf = X; + } else static assert(0, T.stringof~" is not an array type"); } @@ -4415,7 +4625,7 @@ template StringTypeOf(T) } else static if (is(T : const char[]) || is(T : const wchar[]) || is(T : const dchar[])) { - alias ArrayTypeOf!T StringTypeOf; + alias StringTypeOf = ArrayTypeOf!T; } else static assert(0, T.stringof~" is not a string type"); @@ -4424,63 +4634,40 @@ template StringTypeOf(T) unittest { foreach (T; CharTypeList) - foreach (Q; TypeTuple!(MutableOf, ConstOf, ImmutableOf, WildOf)) - { - static assert(is(Q!T[] == StringTypeOf!( Q!T[] ))); - - static if (!__traits(isSame, Q, WildOf)) + foreach (Q; TypeTuple!(MutableOf, ConstOf, ImmutableOf, InoutOf)) { - static assert(is(Q!T[] == StringTypeOf!( SubTypeOf!(Q!T[]) ))); + static assert(is(Q!T[] == StringTypeOf!( Q!T[] ))); - alias Q!T[] Str; - class C(Str) { Str val; alias val this; } - static assert(is(StringTypeOf!(C!Str) == Str)); + static if (!__traits(isSame, Q, InoutOf)) + { + static assert(is(Q!T[] == StringTypeOf!( SubTypeOf!(Q!T[]) ))); + + alias Q!T[] Str; + class C(Str) { Str val; alias val this; } + static assert(is(StringTypeOf!(C!Str) == Str)); + } } - } + foreach (T; CharTypeList) - foreach (Q; TypeTuple!(SharedOf, SharedConstOf, SharedWildOf)) - { - static assert(!is(StringTypeOf!( Q!T[] ))); - } + foreach (Q; TypeTuple!(SharedOf, SharedConstOf, SharedInoutOf)) + { + static assert(!is(StringTypeOf!( Q!T[] ))); + } } /* */ template AssocArrayTypeOf(T) { - immutable(V [K]) idx(K, V)( immutable(V [K]) ); + static if (is(AliasThisTypeOf!T AT) && !is(AT[] == AT)) + alias X = AssocArrayTypeOf!AT; + else + alias X = OriginalType!T; - inout(V)[K] idy(K, V)( inout(V)[K] ); - shared( V [K]) idy(K, V)( shared( V [K]) ); - - inout(V [K]) idz(K, V)( inout(V [K]) ); - shared(inout V [K]) idz(K, V)( shared(inout V [K]) ); - - inout(immutable(V)[K]) idw(K, V)( inout(immutable(V)[K]) ); - shared(inout(immutable(V)[K])) idw(K, V)( shared(inout(immutable(V)[K])) ); - - static if (is(typeof(idx(defaultInit!T)) X)) + static if (is(Unqual!X : V[K], K, V)) { - alias X AssocArrayTypeOf; + alias AssocArrayTypeOf = X; } - else static if (is(typeof(idy(defaultInit!T)) X)) - { - alias X AssocArrayTypeOf; - } - else static if (is(typeof(idz(defaultInit!T)) X)) - { - inout( V [K]) idzp(K, V)( inout( V [K]) ); - inout( const(V) [K]) idzp(K, V)( inout( const(V) [K]) ); - inout(shared(const V) [K]) idzp(K, V)( inout(shared(const V) [K]) ); - inout( immutable(V) [K]) idzp(K, V)( inout( immutable(V) [K]) ); - shared(inout V [K]) idzp(K, V)( shared(inout V [K]) ); - shared(inout const(V) [K]) idzp(K, V)( shared(inout const(V) [K]) ); - shared(inout immutable(V) [K]) idzp(K, V)( shared(inout immutable(V) [K]) ); - - alias typeof(idzp(defaultInit!T)) AssocArrayTypeOf; - } - else static if (is(typeof(idw(defaultInit!T)) X)) - alias X AssocArrayTypeOf; else static assert(0, T.stringof~" is not an associative array type"); } @@ -4488,20 +4675,21 @@ template AssocArrayTypeOf(T) unittest { foreach (T; TypeTuple!(int/*bool, CharTypeList, NumericTypeList, ImaginaryTypeList, ComplexTypeList*/)) - foreach (P; TypeTuple!(TypeQualifierList, WildOf, SharedWildOf)) - foreach (Q; TypeTuple!(TypeQualifierList, WildOf, SharedWildOf)) - foreach (R; TypeTuple!(TypeQualifierList, WildOf, SharedWildOf)) - { - static assert(is( P!(Q!T[R!T]) == AssocArrayTypeOf!( P!(Q!T[R!T]) ) )); - } + foreach (P; TypeTuple!(TypeQualifierList, InoutOf, SharedInoutOf)) + foreach (Q; TypeTuple!(TypeQualifierList, InoutOf, SharedInoutOf)) + foreach (R; TypeTuple!(TypeQualifierList, InoutOf, SharedInoutOf)) + { + static assert(is( P!(Q!T[R!T]) == AssocArrayTypeOf!( P!(Q!T[R!T]) ) )); + } + foreach (T; TypeTuple!(int/*bool, CharTypeList, NumericTypeList, ImaginaryTypeList, ComplexTypeList*/)) - foreach (O; TypeTuple!(TypeQualifierList, WildOf, SharedWildOf)) - foreach (P; TypeTuple!TypeQualifierList) - foreach (Q; TypeTuple!TypeQualifierList) - foreach (R; TypeTuple!TypeQualifierList) - { - static assert(is( O!(P!(Q!T[R!T])) == AssocArrayTypeOf!( O!(SubTypeOf!(P!(Q!T[R!T]))) ) )); - } + foreach (O; TypeTuple!(TypeQualifierList, InoutOf, SharedInoutOf)) + foreach (P; TypeTuple!TypeQualifierList) + foreach (Q; TypeTuple!TypeQualifierList) + foreach (R; TypeTuple!TypeQualifierList) + { + static assert(is( O!(P!(Q!T[R!T])) == AssocArrayTypeOf!( O!(SubTypeOf!(P!(Q!T[R!T]))) ) )); + } } /* @@ -5038,10 +5226,13 @@ unittest */ template isExpressionTuple(T ...) { - static if (T.length > 0) + static if (T.length >= 2) enum bool isExpressionTuple = - !is(T[0]) && __traits(compiles, { auto ex = T[0]; }) && - isExpressionTuple!(T[1 .. $]); + isExpressionTuple!(T[0 .. $/2]) && + isExpressionTuple!(T[$/2 .. $]); + else static if (T.length == 1) + enum bool isExpressionTuple = + !is(T[0]) && __traits(compiles, { auto ex = T[0]; }); else enum bool isExpressionTuple = true; // default } @@ -5071,8 +5262,10 @@ Detect whether tuple $(D T) is a type tuple. */ template isTypeTuple(T...) { - static if (T.length > 0) - enum bool isTypeTuple = is(T[0]) && isTypeTuple!(T[1 .. $]); + static if (T.length >= 2) + enum bool isTypeTuple = isTypeTuple!(T[0 .. $/2]) && isTypeTuple!(T[$/2 .. $]); + else static if (T.length == 1) + enum bool isTypeTuple = is(T[0]); else enum bool isTypeTuple = true; // default } @@ -5389,10 +5582,11 @@ template Unqual(T) } else // workaround { - static if (is(T U == shared(const U))) alias U Unqual; + static if (is(T U == shared(inout U))) alias U Unqual; + else static if (is(T U == shared(const U))) alias U Unqual; + else static if (is(T U == inout U )) alias U Unqual; else static if (is(T U == const U )) alias U Unqual; else static if (is(T U == immutable U )) alias U Unqual; - else static if (is(T U == inout U )) alias U Unqual; else static if (is(T U == shared U )) alias U Unqual; else alias T Unqual; } @@ -5400,12 +5594,13 @@ template Unqual(T) unittest { - static assert(is(Unqual!int == int)); - static assert(is(Unqual!(const int) == int)); - static assert(is(Unqual!(immutable int) == int)); - static assert(is(Unqual!(inout int) == int)); - static assert(is(Unqual!(shared int) == int)); - static assert(is(Unqual!(shared(const int)) == int)); + static assert(is(Unqual!( int) == int)); + static assert(is(Unqual!( const int) == int)); + static assert(is(Unqual!( inout int) == int)); + static assert(is(Unqual!( immutable int) == int)); + static assert(is(Unqual!( shared int) == int)); + static assert(is(Unqual!(shared const int) == int)); + static assert(is(Unqual!(shared inout int) == int)); alias immutable(int[]) ImmIntArr; static assert(is(Unqual!ImmIntArr == immutable(int)[])); } @@ -5413,7 +5608,9 @@ unittest // [For internal use] private template ModifyTypePreservingSTC(alias Modifier, T) { - static if (is(T U == shared(const U))) alias shared(const Modifier!U) ModifyTypePreservingSTC; + static if (is(T U == shared(inout U))) alias shared(inout Modifier!U) ModifyTypePreservingSTC; + else static if (is(T U == shared(const U))) alias shared(const Modifier!U) ModifyTypePreservingSTC; + else static if (is(T U == inout U )) alias inout(Modifier!U) ModifyTypePreservingSTC; else static if (is(T U == const U )) alias const(Modifier!U) ModifyTypePreservingSTC; else static if (is(T U == immutable U )) alias immutable(Modifier!U) ModifyTypePreservingSTC; else static if (is(T U == shared U )) alias shared(Modifier!U) ModifyTypePreservingSTC; @@ -5422,10 +5619,13 @@ private template ModifyTypePreservingSTC(alias Modifier, T) unittest { - static assert(is(ModifyTypePreservingSTC!(Intify, const real) == const int)); - static assert(is(ModifyTypePreservingSTC!(Intify, immutable real) == immutable int)); - static assert(is(ModifyTypePreservingSTC!(Intify, shared real) == shared int)); - static assert(is(ModifyTypePreservingSTC!(Intify, shared(const real)) == shared(const int))); + static assert(is(ModifyTypePreservingSTC!(Intify, real) == int)); + static assert(is(ModifyTypePreservingSTC!(Intify, shared real) == shared int)); + static assert(is(ModifyTypePreservingSTC!(Intify, immutable real) == immutable int)); + static assert(is(ModifyTypePreservingSTC!(Intify, const real) == const int)); + static assert(is(ModifyTypePreservingSTC!(Intify, inout real) == inout int)); + static assert(is(ModifyTypePreservingSTC!(Intify, shared const real) == shared const int)); + static assert(is(ModifyTypePreservingSTC!(Intify, shared inout real) == shared inout int)); } version (unittest) private template Intify(T) { alias int Intify; } @@ -5598,7 +5798,7 @@ template Largest(T...) if(T.length >= 1) } else { - alias Largest!(Largest!(T[0], T[1]), T[2..$]) Largest; + alias Largest!(Largest!(T[0 .. $/2]), Largest!(T[$/2 .. $])) Largest; } } @@ -5645,78 +5845,20 @@ unittest static assert(is(S3 == immutable(int))); } -/** - * Returns the corresponding unsigned value for $(D x), e.g. if $(D x) - * has type $(D int), returns $(D cast(uint) x). The advantage - * compared to the cast is that you do not need to rewrite the cast if - * $(D x) later changes type to e.g. $(D long). - */ -auto unsigned(T)(T x) if (isIntegral!T) -{ - static if (is(Unqual!T == byte )) return cast(ubyte ) x; - else static if (is(Unqual!T == short)) return cast(ushort) x; - else static if (is(Unqual!T == int )) return cast(uint ) x; - else static if (is(Unqual!T == long )) return cast(ulong ) x; - else - { - static assert(T.min == 0, "Bug in either unsigned or isIntegral"); - return cast(Unqual!T) x; - } -} -unittest -{ - foreach(T; TypeTuple!(byte, ubyte)) - { - static assert(is(typeof(unsigned(cast(T)1)) == ubyte)); - static assert(is(typeof(unsigned(cast(const T)1)) == ubyte)); - static assert(is(typeof(unsigned(cast(immutable T)1)) == ubyte)); - } +// Remove import when unsigned is removed. +import std.conv; - foreach(T; TypeTuple!(short, ushort)) - { - static assert(is(typeof(unsigned(cast(T)1)) == ushort)); - static assert(is(typeof(unsigned(cast(const T)1)) == ushort)); - static assert(is(typeof(unsigned(cast(immutable T)1)) == ushort)); - } +// Purposefully undocumented. Will be removed in June 2014. +deprecated("unsigned has been moved to std.conv. Please adjust your imports accordingly.") +alias std.conv.unsigned unsigned; - foreach(T; TypeTuple!(int, uint)) - { - static assert(is(typeof(unsigned(cast(T)1)) == uint)); - static assert(is(typeof(unsigned(cast(const T)1)) == uint)); - static assert(is(typeof(unsigned(cast(immutable T)1)) == uint)); - } - - foreach(T; TypeTuple!(long, ulong)) - { - static assert(is(typeof(unsigned(cast(T)1)) == ulong)); - static assert(is(typeof(unsigned(cast(const T)1)) == ulong)); - static assert(is(typeof(unsigned(cast(immutable T)1)) == ulong)); - } -} - -auto unsigned(T)(T x) if (isSomeChar!T) -{ - // All characters are unsigned - static assert(T.min == 0); - return cast(Unqual!T) x; -} - -unittest -{ - foreach(T; TypeTuple!(char, wchar, dchar)) - { - static assert(is(typeof(unsigned(cast(T)'A')) == T)); - static assert(is(typeof(unsigned(cast(const T)'A')) == T)); - static assert(is(typeof(unsigned(cast(immutable T)'A')) == T)); - } -} /** Returns the most negative value of the numeric type T. */ template mostNegative(T) - if(isNumeric!T || isSomeChar!T) + if(isNumeric!T || isSomeChar!T || isBoolean!T) { static if (is(typeof(T.min_normal))) enum mostNegative = -T.max; @@ -5731,8 +5873,9 @@ unittest static assert(mostNegative!float == -float.max); static assert(mostNegative!double == -double.max); static assert(mostNegative!real == -real.max); + static assert(mostNegative!bool == false); - foreach(T; TypeTuple!(byte, short, int, long)) + foreach(T; TypeTuple!(bool, byte, short, int, long)) static assert(mostNegative!T == T.min); foreach(T; TypeTuple!(ubyte, ushort, uint, ulong, char, wchar, dchar)) @@ -5847,10 +5990,12 @@ unittest // Test for bug 5718 import std.demangle; int foo; - assert(demangle(mangledName!foo)[$-7 .. $] == "int foo"); + auto foo_demangled = demangle(mangledName!foo); + assert(foo_demangled[0 .. 4] == "int " && foo_demangled[$-3 .. $] == "foo"); void bar(){} - assert(demangle(mangledName!bar)[$-10 .. $] == "void bar()"); + auto bar_demangled = demangle(mangledName!bar); + assert(bar_demangled[0 .. 5] == "void " && bar_demangled[$-5 .. $] == "bar()"); } diff --git a/std/typecons.d b/std/typecons.d index f5f1a1b92..e5ebe9d30 100644 --- a/std/typecons.d +++ b/std/typecons.d @@ -45,7 +45,7 @@ Authors: $(WEB erdani.org, Andrei Alexandrescu), module std.typecons; import core.memory, core.stdc.stdlib; import std.algorithm, std.array, std.conv, std.exception, std.format, - std.string, std.traits, std.typetuple, std.range; + std.math, std.string, std.traits, std.typetuple, std.range; debug(Unique) import std.stdio; @@ -397,7 +397,7 @@ template Tuple(Specs...) else { @property - ref Tuple!Types _Tuple_super() @trusted + ref inout(Tuple!Types) _Tuple_super() inout @trusted { foreach (i, _; Types) // Rely on the field layout { @@ -417,7 +417,7 @@ template Tuple(Specs...) * Constructor taking one value for each field. Each argument must be * implicitly assignable to the respective element of the target. */ - this()(Types values) + this(Types values) { field[] = values[]; } @@ -547,6 +547,7 @@ template Tuple(Specs...) /** * Converts to string. */ + static if (allSatisfy!(isPrintable, Types)) string toString() { enum header = typeof(this).stringof ~ "(", @@ -576,6 +577,14 @@ template Tuple(Specs...) } } +private template isPrintable(T) +{ + enum isPrintable = is(typeof({ + Appender!string w; + formattedWrite(w, "%s", T.init); + })); +} + private template Identity(alias T) { alias T Identity; @@ -828,6 +837,14 @@ unittest typeof(Tuple!(int, string ).tupleof))); } unittest +{ + // Bugzilla 10686 + immutable Tuple!(int) t1; + auto r1 = t1[0]; // OK + immutable Tuple!(int, "x") t2; + auto r2 = t2[0]; // error +} +unittest { // Bugzilla 10218 assertCTFEable!( @@ -836,6 +853,11 @@ unittest t = tuple(2); // assignment }); } +unittest +{ + class Foo{} + Tuple!(immutable(Foo)[]) a; +} /** Returns a $(D Tuple) object instantiated and initialized according to @@ -1094,7 +1116,8 @@ string alignForSize(E...)(string[] names...) string[7] declaration = ["", "", "", "", "", "", ""]; - foreach (i, T; E) { + foreach (i, T; E) + { auto a = T.alignof; auto k = a>=64? 0 : a>=32? 1 : a>=16? 2 : a>=8? 3 : a>=4? 4 : a>=2? 5 : 6; declaration[k] ~= T.stringof ~ " " ~ names[i] ~ ";\n"; @@ -1106,28 +1129,21 @@ string alignForSize(E...)(string[] names...) return s; } -unittest { +unittest +{ enum x = alignForSize!(int[], char[3], short, double[5])("x", "y","z", "w"); - struct Foo{ int x; } - enum y = alignForSize!(ubyte, Foo, cdouble)("x", "y","z"); + struct Foo { int x; } + enum y = alignForSize!(ubyte, Foo, cdouble)("x", "y", "z"); - static if(size_t.sizeof == uint.sizeof) - { - enum passNormalX = x == "double[5u] w;\nint[] x;\nshort z;\nchar[3u] y;\n"; - enum passNormalY = y == "cdouble z;\nFoo y;\nubyte x;\n"; + enum passNormalX = x == "double[5] w;\nint[] x;\nshort z;\nchar[3] y;\n"; + enum passNormalY = y == "cdouble z;\nFoo y;\nubyte x;\n"; - enum passAbnormalX = x == "int[] x;\ndouble[5u] w;\nshort z;\nchar[3u] y;\n"; - enum passAbnormalY = y == "Foo y;\ncdouble z;\nubyte x;\n"; - // ^ blame http://d.puremagic.com/issues/show_bug.cgi?id=231 + enum passAbnormalX = x == "int[] x;\ndouble[5] w;\nshort z;\nchar[3] y;\n"; + enum passAbnormalY = y == "Foo y;\ncdouble z;\nubyte x;\n"; + // ^ blame http://d.puremagic.com/issues/show_bug.cgi?id=231 - static assert(passNormalX || double.alignof <= (int[]).alignof && passAbnormalX); - static assert(passNormalY || double.alignof <= int.alignof && passAbnormalY); - } - else - { - static assert(x == "int[] x;\ndouble[5LU] w;\nshort z;\nchar[3LU] y;\n"); - static assert(y == "cdouble z;\nFoo y;\nubyte x;\n"); - } + static assert(passNormalX || passAbnormalX && double.alignof <= (int[]).alignof); + static assert(passNormalY || passAbnormalY && double.alignof <= int.alignof); } /*--* @@ -1187,8 +1203,7 @@ struct Nullable(T) /** Constructor initializing $(D this) with $(D value). */ - //this()(inout T value) inout // proper signature - this(U:T)(inout U value) inout // workaround for BUG 10313 + this(inout T value) inout { _value = value; _isNull = false; @@ -1426,8 +1441,7 @@ unittest { // Bugzilla 10268 import std.json; - JSONValue value = void; - value.type = JSON_TYPE.NULL; + JSONValue value = null; auto na = Nullable!JSONValue(value); struct S1 { int val; } @@ -1464,6 +1478,12 @@ unittest static assert( __traits(compiles, { auto x = immutable Nullable!S3(si); })); } } +unittest +{ + // Bugzila 10357 + import std.datetime; + Nullable!SysTime time = SysTime(0); +} /** Just like $(D Nullable!T), except that the null state is defined as a @@ -1479,7 +1499,7 @@ struct Nullable(T, T nullValue) /** Constructor initializing $(D this) with $(D value). */ - this()(T value) + this(T value) { _value = value; } @@ -1487,7 +1507,7 @@ Constructor initializing $(D this) with $(D value). /** Returns $(D true) if and only if $(D this) is in the null state. */ - @property bool isNull()() const + @property bool isNull() const { return _value == nullValue; } @@ -1513,7 +1533,7 @@ made. Note that the assignment may leave $(D this) in the null state. Gets the value. $(D this) must not be in the null state. This function is also called for the implicit conversion to $(D T). */ - @property ref inout(T) get()() inout + @property ref inout(T) get() inout { //@@@6169@@@: We avoid any call that might evaluate nullValue's %s, //Because it might messup get's purity and safety inference. @@ -1835,7 +1855,7 @@ unittest { interface I_1 { real test(); } auto o = new BlackHole!I_1; - assert(o.test() !<>= 0); // NaN + assert(o.test().isNaN); // NaN } // doc example { @@ -1852,7 +1872,7 @@ unittest auto c = new BlackHole!C(42); assert(c.value == 42); - assert(c.realValue !<>= 0); // NaN + assert(c.realValue.isNaN); // NaN c.doSomething(); } } @@ -1964,6 +1984,7 @@ Params: // Prints log messages for each call to overridden functions. string generateLogger(C, alias fun)() @property { + import std.traits; enum qname = C.stringof ~ "." ~ __traits(identifier, fun); string stmt; @@ -1971,7 +1992,7 @@ string generateLogger(C, alias fun)() @property stmt ~= `Importer.writeln$(LPAREN)"Log: ` ~ qname ~ `(", args, ")"$(RPAREN);`; static if (!__traits(isAbstractFunction, fun)) { - static if (is(typeof(return) == void)) + static if (is(ReturnType!fun == void)) stmt ~= q{ parent(args); }; else stmt ~= q{ @@ -2315,6 +2336,44 @@ unittest }+/ } +version(unittest) +{ + // Issue 10647 + private string generateDoNothing(C, alias fun)() @property + { + string stmt; + + static if (is(ReturnType!fun == void)) + stmt ~= ""; + else + { + string returnType = ReturnType!fun.stringof; + stmt ~= "return "~returnType~".init;"; + } + return stmt; + } + + private template isAlwaysTrue(alias fun) + { + enum isAlwaysTrue = true; + } + + // Do nothing template + private template DoNothing(Base) + { + alias DoNothing = AutoImplement!(Base, generateDoNothing, isAlwaysTrue); + } + + // A class to be overridden + private class Foo{ + void bar(int a) { } + } +} +unittest +{ + auto foo = new DoNothing!Foo(); + foo.bar(13); +} /* Used by MemberFunctionGenerator. @@ -2514,7 +2573,7 @@ private static: enum storageClass = make_storageClass(); // - if (isAbstractFunction!func) + if (__traits(isVirtualMethod, func)) code ~= "override "; code ~= format("extern(%s) %s %s(%s) %s %s\n", functionLinkage!(func), @@ -2658,6 +2717,54 @@ template generateAssertTrap(C, func.../+[BUG 4217]+/) ~ __traits(identifier, func) ~ `");`; } +private +{ + pragma(mangle, "_d_toObject") + extern(C) pure nothrow Object typecons_d_toObject(void* p); +} + +/* + * Avoids opCast operator overloading. + */ +private template dynamicCast(T) +if (is(T == class) || is(T == interface)) +{ + @trusted + T dynamicCast(S)(inout S source) + if (is(S == class) || is(S == interface)) + { + static if (is(Unqual!S : Unqual!T)) + { + import std.traits : QualifierOf; + alias Qual = QualifierOf!S; // SharedOf or MutableOf + alias TmpT = Qual!(Unqual!T); + inout(TmpT) tmp = source; // bypass opCast by implicit conversion + return *cast(T*)(&tmp); // + variable pointer cast + dereference + } + else + { + return cast(T)typecons_d_toObject(*cast(void**)(&source)); + } + } +} + +unittest +{ + class C { @disable opCast(T)() {} } + auto c = new C; + static assert(!__traits(compiles, cast(Object)c)); + auto o = dynamicCast!Object(c); + assert(c is o); + + interface I { @disable opCast(T)() {} Object instance(); } + interface J { @disable opCast(T)() {} Object instance(); } + class D : I, J { Object instance() { return this; } } + I i = new D(); + static assert(!__traits(compiles, cast(J)i)); + J j = dynamicCast!J(i); + assert(i.instance() is j.instance()); +} + /** * Supports structural based typesafe conversion. * @@ -2669,17 +2776,17 @@ template wrap(Targets...) if (Targets.length >= 1 && allSatisfy!(isMutable, Targets)) { // strict upcast - @property wrap(Source)(inout Source src) @trusted pure nothrow + auto wrap(Source)(inout Source src) @trusted pure nothrow if (Targets.length == 1 && is(Source : Targets[0])) { alias T = Select!(is(Source == shared), shared Targets[0], Targets[0]); - return cast(inout T)(src); + return dynamicCast!(inout T)(src); } // structural upcast template wrap(Source) if (!allSatisfy!(Bind!(isImplicitlyConvertible, Source), Targets)) { - @property wrap(inout Source src) + auto wrap(inout Source src) { static assert(hasRequireMethods!(), "Source "~Source.stringof~ @@ -2760,7 +2867,7 @@ if (Targets.length >= 1 && allSatisfy!(isMutable, Targets)) else { enum hasRequireMethods = - findCovariantFunction!(TargetMembers[i], SourceMembers) != -1 && + findCovariantFunction!(TargetMembers[i], Source, SourceMembers) != -1 && hasRequireMethods!(i + 1); } } @@ -2777,7 +2884,7 @@ if (Targets.length >= 1 && allSatisfy!(isMutable, Targets)) // BUG: making private should work with NVI. protected final inout(Object) _wrap_getSource() inout @trusted { - return cast(inout Object)(_wrap_source); + return dynamicCast!(inout Object)(_wrap_source); } import std.conv : to; @@ -2812,10 +2919,21 @@ if (Targets.length >= 1 && allSatisfy!(isMutable, Targets)) return r; } enum n = to!string(i); + static if (fa & FunctionAttribute.property) + { + static if (ParameterTypeTuple!(TargetMembers[i].type).length == 0) + enum fbody = "_wrap_source."~name; + else + enum fbody = "_wrap_source."~name~" = forward!args"; + } + else + { + enum fbody = "_wrap_source."~name~"(forward!args)"; + } enum generateFun = "override "~stc~"ReturnType!(TargetMembers["~n~"].type) " ~ name~"(ParameterTypeTuple!(TargetMembers["~n~"].type) args) "~mod~ - "{ return _wrap_source."~name~"(forward!args); }"; + "{ return "~fbody~"; }"; } public: @@ -2844,26 +2962,26 @@ template unwrap(Target) if (isMutable!Target) { // strict downcast - @property unwrap(Source)(inout Source src) @trusted pure nothrow + auto unwrap(Source)(inout Source src) @trusted pure nothrow if (is(Target : Source)) { alias T = Select!(is(Source == shared), shared Target, Target); - return cast(inout T)(src); + return dynamicCast!(inout T)(src); } // structural downcast - @property unwrap(Source)(inout Source src) @trusted pure nothrow + auto unwrap(Source)(inout Source src) @trusted pure nothrow if (!is(Target : Source)) { alias T = Select!(is(Source == shared), shared Target, Target); - Object o = cast(Object)src; // remove qualifier + Object o = dynamicCast!(Object)(src); // remove qualifier do { - if (auto a = cast(Structural)o) + if (auto a = dynamicCast!(Structural)(o)) { - if (auto d = cast(inout T)(o = a._wrap_getSource())) + if (auto d = dynamicCast!(inout T)(o = a._wrap_getSource())) return d; } - else if (auto d = cast(inout T)o) + else if (auto d = dynamicCast!(inout T)(o)) return d; else break; @@ -2930,7 +3048,7 @@ unittest // structural upcast (two steps) Quack qx = h1.wrap!Quack; // Human -> Quack Flyer fx = qx.wrap!Flyer; // Quack -> Flyer - assert(fx.height() == 20); // calls Human.height + assert(fx.height == 20); // calls Human.height // strucural downcast (two steps) Quack qy = fx.unwrap!Quack; // Flyer -> Quack Human hy = qy.unwrap!Human; // Quack -> Human @@ -3006,6 +3124,56 @@ unittest assert(d.draw(10) == 10); } } +unittest +{ + // Bugzilla 10377 + import std.range, std.algorithm; + + interface MyInputRange(T) + { + @property T front(); + void popFront(); + @property bool empty(); + } + + //auto o = iota(0,10,1).inputRangeObject(); + //pragma(msg, __traits(allMembers, typeof(o))); + auto r = iota(0,10,1).inputRangeObject().wrap!(MyInputRange!int)(); + assert(equal(r, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])); +} +unittest +{ + // Bugzilla 10536 + interface Interface + { + int foo(); + } + class Pluggable + { + int foo() { return 1; } + @disable void opCast(T, this X)(); // ! + } + + Interface i = new Pluggable().wrap!Interface; + assert(i.foo() == 1); +} +unittest +{ + // Enhancement 10538 + interface Interface + { + int foo(); + int bar(int); + } + class Pluggable + { + int opDispatch(string name, A...)(A args) { return 100; } + } + + Interface i = wrap!Interface(new Pluggable()); + assert(i.foo() == 100); + assert(i.bar(10) == 100); +} // Make a tuple of non-static function symbols private template GetOverloadedMethods(T) @@ -3017,7 +3185,7 @@ private template GetOverloadedMethods(T) { alias follows = TypeTuple!(); } - else static if (allMembers[i] == "this") + else static if (!__traits(compiles, mixin("T."~allMembers[i]))) { alias follows = follows!(i + 1); } @@ -3040,7 +3208,7 @@ private template GetOverloadedMethods(T) alias GetOverloadedMethods = follows!(); } // find a function from Fs that has same identifier and covariant type with f -private template findCovariantFunction(alias finfo, Fs...) +private template findCovariantFunction(alias finfo, Source, Fs...) { template check(size_t i = 0) { @@ -3054,7 +3222,20 @@ private template findCovariantFunction(alias finfo, Fs...) ? i : check!(i + 1); } } - enum ptrdiff_t findCovariantFunction = check!(); + enum x = check!(); + static if (x == -1 && is(typeof(Source.opDispatch))) + { + alias Params = ParameterTypeTuple!(finfo.type); + enum ptrdiff_t findCovariantFunction = + is(typeof(( Source).init.opDispatch!(finfo.name)(Params.init))) || + is(typeof(( const Source).init.opDispatch!(finfo.name)(Params.init))) || + is(typeof(( immutable Source).init.opDispatch!(finfo.name)(Params.init))) || + is(typeof(( shared Source).init.opDispatch!(finfo.name)(Params.init))) || + is(typeof((shared const Source).init.opDispatch!(finfo.name)(Params.init))) + ? ptrdiff_t.max : -1; + } + else + enum ptrdiff_t findCovariantFunction = x; } private enum TypeModifier @@ -3118,10 +3299,21 @@ unittest @property int value() { return 0; } void opEquals() {} int nomatch() { return 0; } - static assert(findCovariantFunction!(UnittestFuncInfo!draw, methods) == 0); - static assert(findCovariantFunction!(UnittestFuncInfo!value, methods) == 1); - static assert(findCovariantFunction!(UnittestFuncInfo!opEquals, methods) == -1); - static assert(findCovariantFunction!(UnittestFuncInfo!nomatch, methods) == -1); + static assert(findCovariantFunction!(UnittestFuncInfo!draw, A, methods) == 0); + static assert(findCovariantFunction!(UnittestFuncInfo!value, A, methods) == 1); + static assert(findCovariantFunction!(UnittestFuncInfo!opEquals, A, methods) == -1); + static assert(findCovariantFunction!(UnittestFuncInfo!nomatch, A, methods) == -1); + + // considering opDispatch + class B + { + void opDispatch(string name, A...)(A) {} + } + alias methodsB = GetOverloadedMethods!B; + static assert(findCovariantFunction!(UnittestFuncInfo!draw, B, methodsB) == ptrdiff_t.max); + static assert(findCovariantFunction!(UnittestFuncInfo!value, B, methodsB) == ptrdiff_t.max); + static assert(findCovariantFunction!(UnittestFuncInfo!opEquals, B, methodsB) == ptrdiff_t.max); + static assert(findCovariantFunction!(UnittestFuncInfo!nomatch, B, methodsB) == ptrdiff_t.max); } private template DerivedFunctionType(T...) @@ -3228,7 +3420,7 @@ unittest static assert(is(DerivedFunctionType!(F17, F18) == void)); } -private template staticIota(int beg, int end, int step = 1) if (step != 0) +private template staticIota(int beg, int end) { static if (beg + 1 >= end) { @@ -3304,7 +3496,7 @@ automatically initialized. Leaving $(D autoInit == RefCountedAutoInitialize.yes) (the default option) is convenient but has the cost of a test whenever the payload is accessed. If $(D autoInit == RefCountedAutoInitialize.no), user code must call either -$(D refCountedIsInitialized) or $(D refCountedEnsureInitialized) +$(D refCountedStore.isInitialized) or $(D refCountedStore.ensureInitialized) before attempting to access the payload. Not doing so results in null pointer dereference. @@ -3388,7 +3580,7 @@ if (!is(T == class)) /** Constructor that initializes the payload. -Postcondition: $(D refCountedIsInitialized) +Postcondition: $(D refCountedStore.isInitialized) */ this(A...)(auto ref A args) if (A.length > 0) { @@ -3397,7 +3589,7 @@ Postcondition: $(D refCountedIsInitialized) /** Constructor that tracks the reference count appropriately. If $(D -!refCountedIsInitialized), does nothing. +!refCountedStore.isInitialized), does nothing. */ this(this) { @@ -3407,7 +3599,7 @@ Constructor that tracks the reference count appropriately. If $(D /** Destructor that tracks the reference count appropriately. If $(D -!refCountedIsInitialized), does nothing. When the reference count goes +!refCountedStore.isInitialized), does nothing. When the reference count goes down to zero, calls $(D destroy) agaist the payload and calls $(D free) to deallocate the corresponding resource. */ @@ -3453,8 +3645,8 @@ Assignment operators /** Returns a reference to the payload. If (autoInit == RefCountedAutoInitialize.yes), calls $(D - refCountedEnsureInitialized). Otherwise, just issues $(D - assert(refCountedIsInitialized)). Used with $(D alias + refCountedStore.ensureInitialized). Otherwise, just issues $(D + assert(refCountedStore.isInitialized)). Used with $(D alias refCountedPayload this;), so callers can just use the $(D RefCounted) object as a $(D T). @@ -3487,7 +3679,7 @@ Assignment operators @property nothrow @safe ref inout(T) refCountedPayload() inout { - assert(_refCounted.isInitialized); + assert(_refCounted.isInitialized, "Attempted to access an uninitialized payload."); return _refCounted._store._payload; } } @@ -3495,8 +3687,8 @@ Assignment operators /** Returns a reference to the payload. If (autoInit == RefCountedAutoInitialize.yes), calls $(D -refCountedEnsureInitialized). Otherwise, just issues $(D -assert(refCountedIsInitialized)). +refCountedStore.ensureInitialized). Otherwise, just issues $(D +assert(refCountedStore.isInitialized)). */ alias refCountedPayload this; } @@ -4064,6 +4256,12 @@ unittest auto e2 = ScopedObject(); //Illegal, must be built via scoped!A auto e3 = ScopedObject(1); //Illegal, must be built via scoped!A }))); + + // Use as member variable + struct B + { + typeof(scoped!A()) a; // note the trailing parentheses + } // Use with alias alias makeScopedA = scoped!A; diff --git a/std/uni.d b/std/uni.d index 625750017..8fb887d08 100644 --- a/std/uni.d +++ b/std/uni.d @@ -1,1427 +1,7476 @@ // Written in the D programming language. /++ - Functions which operate on Unicode characters. + $(SECTION Overview) - For functions which operate on ASCII characters and ignore Unicode - characters, see $(LINK2 std_ascii.html, std.ascii). + $(P The $(D std.uni) module provides an implementation + of fundamental Unicode algorithms and data structures. + This doesn't include UTF encoding and decoding primitives, + see $(XREF _utf, decode) and $(XREF _utf, encode) in std.utf + for this functionality. ) + $(P All primitives listed operate on Unicode characters and + sets of characters. For functions which operate on ASCII characters + and ignore Unicode $(CHARACTERS), see $(LINK2 std_ascii.html, std.ascii). + For definitions of Unicode $(CHARACTER), $(CODEPOINT) and other terms + used throughout this module see the $(S_LINK Terminology, terminology) section + below. + ) + + $(P The focus of this module is the core needs of developing Unicode-aware + applications. To that effect it provides the following optimized primitives: + ) + $(UL + $(LI Character classification by category and common properties: + $(LREF isAlpha), $(LREF isWhite) and others. + ) + $(LI + Case-insensitive string comparison ($(LREF sicmp), $(LREF icmp)). + ) + $(LI + Converting text to any of the four normalization forms via $(LREF normalize). + ) + $(LI + Decoding ($(LREF decodeGrapheme)) and iteration ($(LREF byGrapheme), $(LREF graphemeStride)) + by user-perceived characters, that is by $(LREF Grapheme) clusters. + ) + $(LI + Decomposing and composing of individual character(s) according to canonical + or compatibility rules, see $(LREF compose) and $(LREF decompose), + including the specific version for Hangul syllables $(LREF composeJamo) + and $(LREF decomposeHangul). + ) + ) + $(P It's recognized that an application may need further enhancements + and extensions, such as less commonly known algorithms, + or tailoring existing ones for region specific needs. To help users + with building any extra functionality beyond the core primitives, + the module provides: + ) + $(UL + $(LI + $(LREF CodepointSet), a type for easy manipulation of sets of characters. + Besides the typical set algebra it provides an unusual feature: + a D source code generator for detection of $(CODEPOINTS) in this set. + This is a boon for meta-programming parser frameworks, + and is used internally to power classification in small + sets like $(LREF isWhite). + ) + $(LI + A way to construct optimal packed multi-stage tables also known as a + special case of $(LUCKY Trie). + The functions $(LREF codepointTrie), $(LREF codepointSetTrie) + construct custom tries that map dchar to value. + The end result is a fast and predictable $(BIGOH 1) lookup that powers + functions like $(LREF isAlpha) and $(LREF combiningClass), + but for user-defined data sets. + ) + $(LI + Generally useful building blocks for customized normalization: + $(LREF combiningClass) for querying combining class + and $(LREF allowedIn) for testing the Quick_Check + property of a given normalization form. + ) + $(LI + Access to a large selection of commonly used sets of $(CODEPOINTS). + $(S_LINK Unicode properties, Supported sets) include Script, + Block and General Category. The exact contents of a set can be + observed in the CLDR utility, on the + $(WEB www.unicode.org/cldr/utility/properties.jsp, property index) page + of the Unicode website. + See $(LREF unicode) for easy and (optionally) compile-time checked set + queries. + ) + ) + $(SECTION Synopsis) + --- + import std.uni; + void main() + { + // initialize code point sets using script/block or property name + // now 'set' contains code points from both scripts. + auto set = unicode("Cyrillic") | unicode("Armenian"); + // same thing but simpler and checked at compile-time + auto ascii = unicode.ASCII; + auto currency = unicode.Currency_Symbol; + + // easy set ops + auto a = set & ascii; + assert(a.empty); // as it has no intersection with ascii + a = set | ascii; + auto b = currency - a; // subtract all ASCII, Cyrillic and Armenian + + // some properties of code point sets + assert(b.length > 45); // 46 items in Unicode 6.1, even more in 6.2 + // testing presence of a code point in a set + // is just fine, it is O(logN) + assert(!b['$']); + assert(!b['\u058F']); // Armenian dram sign + assert(b['¥']); + + // building fast lookup tables, these guarantee O(1) complexity + // 1-level Trie lookup table essentially a huge bit-set ~262Kb + auto oneTrie = toTrie!1(b); + // 2-level far more compact but typically slightly slower + auto twoTrie = toTrie!2(b); + // 3-level even smaller, and a bit slower yet + auto threeTrie = toTrie!3(b); + assert(oneTrie['£']); + assert(twoTrie['£']); + assert(threeTrie['£']); + + // build the trie with the most sensible trie level + // and bind it as a functor + auto cyrillicOrArmenian = toDelegate(set); + auto balance = find!(cyrillicOrArmenian)("Hello ընկեր!"); + assert(balance == "ընկեր!"); + // compatible with bool delegate(dchar) + bool delegate(dchar) bindIt = cyrillicOrArmenian; + + // Normalization + string s = "Plain ascii (and not only), is always normalized!"; + assert(s is normalize(s));// is the same string + + string nonS = "A\u0308ffin"; // A ligature + auto nS = normalize(nonS); // to NFC, the W3C endorsed standard + assert(nS == "Äffin"); + assert(nS != nonS); + string composed = "Äffin"; + + assert(normalize!NFD(composed) == "A\u0308ffin"); + // to NFKD, compatibility decomposition useful for fuzzy matching/searching + assert(normalize!NFKD("2¹⁰") == "210"); + } + --- + $(SECTION Terminology) + $(P The following is a list of important Unicode notions + and definitions. Any conventions used specifically in this + module alone are marked as such. The descriptions are based on the formal + definition as found in ($WEB http://www.unicode.org/versions/Unicode6.2.0/ch03.pdf, + chapter three of The Unicode Standard Core Specification.) + ) + + $(P $(DEF Abstract character) A unit of information used for the organization, + control, or representation of textual data. + Note that: + $(UL + $(LI When representing data, the nature of that data + is generally symbolic as opposed to some other + kind of data (for example, visual).) + + $(LI An abstract character has no concrete form + and should not be confused with a $(S_LINK Glyph, glyph).) + + $(LI An abstract character does not necessarily + correspond to what a user thinks of as a “character” + and should not be confused with a $(LREF Grapheme).) + + $(LI The abstract characters encoded (see Encoded character) + are known as Unicode abstract characters.) + + $(LI Abstract characters not directly + encoded by the Unicode Standard can often be + represented by the use of combining character sequences.) + ) + ) + + $(P $(DEF Canonical decomposition) + The decomposition of a character or character sequence + that results from recursively applying the canonical + mappings found in the Unicode Character Database + and these described in Conjoining Jamo Behavior + (section 12 of + $(WEB www.unicode.org/uni2book/ch03.pdf, Unicode Conformance)). + ) + + $(P $(DEF Canonical composition) + The precise definition of the Canonical composition + is the algorithm as specified in $(WEB www.unicode.org/uni2book/ch03.pdf, + Unicode Conformance) section 11. + Informally it's the process that does the reverse of the canonical + decomposition with the addition of certain rules + that e.g. prevent legacy characters from appearing in the composed result. + ) + + $(P $(DEF Canonical equivalent) + Two character sequences are said to be canonical equivalents if + their full canonical decompositions are identical. + ) + + $(P $(DEF Character) Typically differs by context. + For the purpose of this documentation the term $(I character) + implies $(I encoded character), that is, a code point having + an assigned abstract character (a symbolic meaning). + ) + + $(P $(DEF Code point) Any value in the Unicode codespace; + that is, the range of integers from 0 to 10FFFF (hex). + Not all code points are assigned to encoded characters. + ) + + $(P $(DEF Code unit) The minimal bit combination that can represent + a unit of encoded text for processing or interchange. + Depending on the encoding this could be: + 8-bit code units in the UTF-8 ($(D char)), + 16-bit code units in the UTF-16 ($(D wchar)), + and 32-bit code units in the UTF-32 ($(D dchar)). + $(I Note that in UTF-32, a code unit is a code point + and is represented by the D $(D dchar) type.) + ) + + $(P $(DEF Combining character) A character with the General Category + of Combining Mark(M). + $(UL + $(LI All characters with non-zero canonical combining class + are combining characters, but the reverse is not the case: + there are combining characters with a zero combining class. + ) + $(LI These characters are not normally used in isolation + unless they are being described. They include such characters + as accents, diacritics, Hebrew points, Arabic vowel signs, + and Indic matras. + ) + ) + ) + + $(P $(DEF Combining class) + A numerical value used by the Unicode Canonical Ordering Algorithm + to determine which sequences of combining marks are to be + considered canonically equivalent and which are not. + ) + + $(P $(DEF Compatibility decomposition) + The decomposition of a character or character sequence that results + from recursively applying both the compatibility mappings and + the canonical mappings found in the Unicode Character Database, and those + described in Conjoining Jamo Behavior no characters + can be further decomposed. + ) + + $(P $(DEF Compatibility equivalent) + Two character sequences are said to be compatibility + equivalents if their full compatibility decompositions are identical. + ) + + $(P $(DEF Encoded character) An association (or mapping) + between an abstract character and a code point. + ) + + $(P $(DEF Glyph) The actual, concrete image of a glyph representation + having been rasterized or otherwise imaged onto some display surface. + ) + + $(P $(DEF Grapheme base) A character with the property + Grapheme_Base, or any standard Korean syllable block. + ) + + $(P $(DEF Grapheme cluster) Defined as the text between + grapheme boundaries as specified by Unicode Standard Annex #29, + $(WEB www.unicode.org/reports/tr29/, Unicode text segmentation). + Important general properties of a grapheme: + $(UL + $(LI The grapheme cluster represents a horizontally segmentable + unit of text, consisting of some grapheme base (which may + consist of a Korean syllable) together with any number of + nonspacing marks applied to it. + ) + $(LI A grapheme cluster typically starts with a grapheme base + and then extends across any subsequent sequence of nonspacing marks. + A grapheme cluster is most directly relevant to text rendering and + processes such as cursor placement and text selection in editing, + but may also be relevant to comparison and searching. + ) + $(LI For many processes, a grapheme cluster behaves as if it was a + single character with the same properties as its grapheme base. + Effectively, nonspacing marks apply $(I graphically) to the base, + but do not change its properties. + ) + ) + $(P This module defines a number of primitives that work with graphemes: + $(LREF Grapheme), $(LREF decodeGrapheme) and $(LREF graphemeStride). + All of them are using $(I extended grapheme) boundaries + as defined in the aforementioned standard annex. + ) + ) + + + $(P $(DEF Nonspacing mark) A combining character with the + General Category of Nonspacing Mark (Mn) or Enclosing Mark (Me). + ) + + $(P $(DEF Spacing mark) A combining character that is not a nonspacing mark.) + + + $(SECTION Normalization) + + $(P The concepts of $(S_LINK Canonical equivalent, canonical equivalent) + or $(S_LINK Compatibility equivalent, compatibility equivalent) + characters in the Unicode Standard make it necessary to have a full, formal + definition of equivalence for Unicode strings. + String equivalence is determined by a process called normalization, + whereby strings are converted into forms which are compared + directly for identity. This is the primary goal of the normalization process, + see the function $(LREF normalize) to convert into any of + the four defined forms. + ) + + $(P A very important attribute of the Unicode Normalization Forms + is that they must remain stable between versions of the Unicode Standard. + A Unicode string normalized to a particular Unicode Normalization Form + in one version of the standard is guaranteed to remain in that Normalization + Form for implementations of future versions of the standard. + ) + + $(P The Unicode Standard specifies four normalization forms. + Informally, two of these forms are defined by maximal decomposition + of equivalent sequences, and two of these forms are defined + by maximal $(I composition) of equivalent sequences. + $(UL + $(LI Normalization Form D (NFD): The $(S_LINK Canonical decomposition, + canonical decomposition) of a character sequence.) + $(LI Normalization Form KD (NFKD): The $(S_LINK Compatibility decomposition, + compatibility decomposition) of a character sequence.) + $(LI Normalization Form C (NFC): The canonical composition of the + $(S_LINK Canonical decomposition, canonical decomposition) + of a coded character sequence.) + $(LI Normalization Form KC (NFKC): The canonical composition + of the $(S_LINK Compatibility decomposition, + compatibility decomposition) of a character sequence) + ) + ) + + $(P The choice of the normalization form depends on the particular use case. + NFC is the best form for general text, since it's more compatible with + strings converted from legacy encodings. NFKC is the preferred form for + identifiers, especially where there are security concerns. NFD and NFKD + are the most useful for internal processing. + ) + + $(SECTION Construction of lookup tables) + + $(P The Unicode standard describes a set of algorithms that + depend on having the ability to quickly look up various properties + of a code point. Given the the codespace of about 1 million $(CODEPOINTS), + it is not a trivial task to provide a space-efficient solution for + the multitude of properties.) + + $(P Common approaches such as hash-tables or binary search over + sorted code point intervals (as in $(LREF InversionList)) are insufficient. + Hash-tables have enormous memory footprint and binary search + over intervals is not fast enough for some heavy-duty algorithms. + ) + + $(P The recommended solution (see Unicode Implementation Guidelines) + is using multi-stage tables that are an implementation of the + $(WEB http://en.wikipedia.org/wiki/Trie, Trie) data structure with integer + keys and a fixed number of stages. For the remainder of the section + this will be called a fixed trie. The following describes a particular + implementation that is aimed for the speed of access at the expense + of ideal size savings. + ) + + $(P Taking a 2-level Trie as an example the principle of operation is as follows. + Split the number of bits in a key (code point, 21 bits) into 2 components + (e.g. 15 and 8). The first is the number of bits in the index of the trie + and the other is number of bits in each page of the trie. + The layout of the trie is then an array of size 2^^bits-of-index followed + an array of memory chunks of size 2^^bits-of-page/bits-per-element. + ) + + $(P The number of pages is variable (but not less then 1) + unlike the number of entries in the index. The slots of the index + all have to contain a number of a page that is present. The lookup is then + just a couple of operations - slice the upper bits, + lookup an index for these, take a page at this index and use + the lower bits as an offset within this page. + + Assuming that pages are laid out consequently + in one array at $(D pages), the pseudo-code is: + ) + --- + auto elemsPerPage = (2 ^^ bits_per_page) / Value.sizeOfInBits; + pages[index[n >> bits_per_page]][n & (elemsPerPage - 1)]; + --- + $(P Where if $(D elemsPerPage) is a power of 2 the whole process is + a handful of simple instructions and 2 array reads. Subsequent levels + of the trie are introduced by recursing on this notion - the index array + is treated as values. The number of bits in index is then again + split into 2 parts, with pages over 'current-index' and the new 'upper-index'. + ) + + $(P For completeness a level 1 trie is simply an array. + The current implementation takes advantage of bit-packing values + when the range is known to be limited in advance (such as $(D bool)). + See also $(LREF BitPacked) for enforcing it manually. + The major size advantage however comes from the fact + that multiple $(B identical pages on every level are merged) by construction. + ) + + $(P The process of constructing a trie is more involved and is hidden from + the user in a form of the convenience functions $(LREF codepointTrie), + $(LREF codepointSetTrie) and the even more convenient $(LREF toTrie). + In general a set or built-in AA with $(D dchar) type + can be turned into a trie. The trie object in this module + is read-only (immutable); it's effectively frozen after construction. + ) + + $(SECTION Unicode properties) + + $(P This is a full list of Unicode properties accessible through $(LREF unicode) + with specific helpers per category nested within. Consult the + $(WEB www.unicode.org/cldr/utility/properties.jsp, CLDR utility) + when in doubt about the contents of a particular set.) + + $(P General category sets listed below are only accessible with the + $(LREF unicode) shorthand accessor.) + $(BOOKTABLE $(B General category ), + $(TR $(TH Abb.) $(TH Long form) + $(TH Abb.) $(TH Long form)$(TH Abb.) $(TH Long form)) + $(TR $(TD L) $(TD Letter) + $(TD Cn) $(TD Unassigned) $(TD Po) $(TD Other_Punctuation)) + $(TR $(TD Ll) $(TD Lowercase_Letter) + $(TD Co) $(TD Private_Use) $(TD Ps) $(TD Open_Punctuation)) + $(TR $(TD Lm) $(TD Modifier_Letter) + $(TD Cs) $(TD Surrogate) $(TD S) $(TD Symbol)) + $(TR $(TD Lo) $(TD Other_Letter) + $(TD N) $(TD Number) $(TD Sc) $(TD Currency_Symbol)) + $(TR $(TD Lt) $(TD Titlecase_Letter) + $(TD Nd) $(TD Decimal_Number) $(TD Sk) $(TD Modifier_Symbol)) + $(TR $(TD Lu) $(TD Uppercase_Letter) + $(TD Nl) $(TD Letter_Number) $(TD Sm) $(TD Math_Symbol)) + $(TR $(TD M) $(TD Mark) + $(TD No) $(TD Other_Number) $(TD So) $(TD Other_Symbol)) + $(TR $(TD Mc) $(TD Spacing_Mark) + $(TD P) $(TD Punctuation) $(TD Z) $(TD Separator)) + $(TR $(TD Me) $(TD Enclosing_Mark) + $(TD Pc) $(TD Connector_Punctuation) $(TD Zl) $(TD Line_Separator)) + $(TR $(TD Mn) $(TD Nonspacing_Mark) + $(TD Pd) $(TD Dash_Punctuation) $(TD Zp) $(TD Paragraph_Separator)) + $(TR $(TD C) $(TD Other) + $(TD Pe) $(TD Close_Punctuation) $(TD Zs) $(TD Space_Separator)) + $(TR $(TD Cc) $(TD Control) $(TD Pf) + $(TD Final_Punctuation) $(TD -) $(TD Any)) + $(TR $(TD Cf) $(TD Format) + $(TD Pi) $(TD Initial_Punctuation) $(TD -) $(TD ASCII)) + ) + $(P Sets for other commonly useful properties that are + accessible with $(LREF unicode):) + $(BOOKTABLE $(B Common binary properties), + $(TR $(TH Name) $(TH Name) $(TH Name)) + $(TR $(TD Alphabetic) $(TD Ideographic) $(TD Other_Uppercase)) + $(TR $(TD ASCII_Hex_Digit) $(TD IDS_Binary_Operator) $(TD Pattern_Syntax)) + $(TR $(TD Bidi_Control) $(TD ID_Start) $(TD Pattern_White_Space)) + $(TR $(TD Cased) $(TD IDS_Trinary_Operator) $(TD Quotation_Mark)) + $(TR $(TD Case_Ignorable) $(TD Join_Control) $(TD Radical)) + $(TR $(TD Dash) $(TD Logical_Order_Exception) $(TD Soft_Dotted)) + $(TR $(TD Default_Ignorable_Code_Point) $(TD Lowercase) $(TD STerm)) + $(TR $(TD Deprecated) $(TD Math) $(TD Terminal_Punctuation)) + $(TR $(TD Diacritic) $(TD Noncharacter_Code_Point) $(TD Unified_Ideograph)) + $(TR $(TD Extender) $(TD Other_Alphabetic) $(TD Uppercase)) + $(TR $(TD Grapheme_Base) $(TD Other_Default_Ignorable_Code_Point) $(TD Variation_Selector)) + $(TR $(TD Grapheme_Extend) $(TD Other_Grapheme_Extend) $(TD White_Space)) + $(TR $(TD Grapheme_Link) $(TD Other_ID_Continue) $(TD XID_Continue)) + $(TR $(TD Hex_Digit) $(TD Other_ID_Start) $(TD XID_Start)) + $(TR $(TD Hyphen) $(TD Other_Lowercase) ) + $(TR $(TD ID_Continue) $(TD Other_Math) ) + ) + $(P Bellow is the table with block names accepted by $(LREF unicode.block). + Note that the shorthand version $(LREF unicode) requires "In" + to be prepended to the names of blocks so as to disambiguate + scripts and blocks.) + + $(BOOKTABLE $(B Blocks), + $(TR $(TD Aegean Numbers) $(TD Ethiopic Extended) $(TD Mongolian)) + $(TR $(TD Alchemical Symbols) $(TD Ethiopic Extended-A) $(TD Musical Symbols)) + $(TR $(TD Alphabetic Presentation Forms) $(TD Ethiopic Supplement) $(TD Myanmar)) + $(TR $(TD Ancient Greek Musical Notation) $(TD General Punctuation) $(TD Myanmar Extended-A)) + $(TR $(TD Ancient Greek Numbers) $(TD Geometric Shapes) $(TD New Tai Lue)) + $(TR $(TD Ancient Symbols) $(TD Georgian) $(TD NKo)) + $(TR $(TD Arabic) $(TD Georgian Supplement) $(TD Number Forms)) + $(TR $(TD Arabic Extended-A) $(TD Glagolitic) $(TD Ogham)) + $(TR $(TD Arabic Mathematical Alphabetic Symbols) $(TD Gothic) $(TD Ol Chiki)) + $(TR $(TD Arabic Presentation Forms-A) $(TD Greek and Coptic) $(TD Old Italic)) + $(TR $(TD Arabic Presentation Forms-B) $(TD Greek Extended) $(TD Old Persian)) + $(TR $(TD Arabic Supplement) $(TD Gujarati) $(TD Old South Arabian)) + $(TR $(TD Armenian) $(TD Gurmukhi) $(TD Old Turkic)) + $(TR $(TD Arrows) $(TD Halfwidth and Fullwidth Forms) $(TD Optical Character Recognition)) + $(TR $(TD Avestan) $(TD Hangul Compatibility Jamo) $(TD Oriya)) + $(TR $(TD Balinese) $(TD Hangul Jamo) $(TD Osmanya)) + $(TR $(TD Bamum) $(TD Hangul Jamo Extended-A) $(TD Phags-pa)) + $(TR $(TD Bamum Supplement) $(TD Hangul Jamo Extended-B) $(TD Phaistos Disc)) + $(TR $(TD Basic Latin) $(TD Hangul Syllables) $(TD Phoenician)) + $(TR $(TD Batak) $(TD Hanunoo) $(TD Phonetic Extensions)) + $(TR $(TD Bengali) $(TD Hebrew) $(TD Phonetic Extensions Supplement)) + $(TR $(TD Block Elements) $(TD High Private Use Surrogates) $(TD Playing Cards)) + $(TR $(TD Bopomofo) $(TD High Surrogates) $(TD Private Use Area)) + $(TR $(TD Bopomofo Extended) $(TD Hiragana) $(TD Rejang)) + $(TR $(TD Box Drawing) $(TD Ideographic Description Characters) $(TD Rumi Numeral Symbols)) + $(TR $(TD Brahmi) $(TD Imperial Aramaic) $(TD Runic)) + $(TR $(TD Braille Patterns) $(TD Inscriptional Pahlavi) $(TD Samaritan)) + $(TR $(TD Buginese) $(TD Inscriptional Parthian) $(TD Saurashtra)) + $(TR $(TD Buhid) $(TD IPA Extensions) $(TD Sharada)) + $(TR $(TD Byzantine Musical Symbols) $(TD Javanese) $(TD Shavian)) + $(TR $(TD Carian) $(TD Kaithi) $(TD Sinhala)) + $(TR $(TD Chakma) $(TD Kana Supplement) $(TD Small Form Variants)) + $(TR $(TD Cham) $(TD Kanbun) $(TD Sora Sompeng)) + $(TR $(TD Cherokee) $(TD Kangxi Radicals) $(TD Spacing Modifier Letters)) + $(TR $(TD CJK Compatibility) $(TD Kannada) $(TD Specials)) + $(TR $(TD CJK Compatibility Forms) $(TD Katakana) $(TD Sundanese)) + $(TR $(TD CJK Compatibility Ideographs) $(TD Katakana Phonetic Extensions) $(TD Sundanese Supplement)) + $(TR $(TD CJK Compatibility Ideographs Supplement) $(TD Kayah Li) $(TD Superscripts and Subscripts)) + $(TR $(TD CJK Radicals Supplement) $(TD Kharoshthi) $(TD Supplemental Arrows-A)) + $(TR $(TD CJK Strokes) $(TD Khmer) $(TD Supplemental Arrows-B)) + $(TR $(TD CJK Symbols and Punctuation) $(TD Khmer Symbols) $(TD Supplemental Mathematical Operators)) + $(TR $(TD CJK Unified Ideographs) $(TD Lao) $(TD Supplemental Punctuation)) + $(TR $(TD CJK Unified Ideographs Extension A) $(TD Latin-1 Supplement) $(TD Supplementary Private Use Area-A)) + $(TR $(TD CJK Unified Ideographs Extension B) $(TD Latin Extended-A) $(TD Supplementary Private Use Area-B)) + $(TR $(TD CJK Unified Ideographs Extension C) $(TD Latin Extended Additional) $(TD Syloti Nagri)) + $(TR $(TD CJK Unified Ideographs Extension D) $(TD Latin Extended-B) $(TD Syriac)) + $(TR $(TD Combining Diacritical Marks) $(TD Latin Extended-C) $(TD Tagalog)) + $(TR $(TD Combining Diacritical Marks for Symbols) $(TD Latin Extended-D) $(TD Tagbanwa)) + $(TR $(TD Combining Diacritical Marks Supplement) $(TD Lepcha) $(TD Tags)) + $(TR $(TD Combining Half Marks) $(TD Letterlike Symbols) $(TD Tai Le)) + $(TR $(TD Common Indic Number Forms) $(TD Limbu) $(TD Tai Tham)) + $(TR $(TD Control Pictures) $(TD Linear B Ideograms) $(TD Tai Viet)) + $(TR $(TD Coptic) $(TD Linear B Syllabary) $(TD Tai Xuan Jing Symbols)) + $(TR $(TD Counting Rod Numerals) $(TD Lisu) $(TD Takri)) + $(TR $(TD Cuneiform) $(TD Low Surrogates) $(TD Tamil)) + $(TR $(TD Cuneiform Numbers and Punctuation) $(TD Lycian) $(TD Telugu)) + $(TR $(TD Currency Symbols) $(TD Lydian) $(TD Thaana)) + $(TR $(TD Cypriot Syllabary) $(TD Mahjong Tiles) $(TD Thai)) + $(TR $(TD Cyrillic) $(TD Malayalam) $(TD Tibetan)) + $(TR $(TD Cyrillic Extended-A) $(TD Mandaic) $(TD Tifinagh)) + $(TR $(TD Cyrillic Extended-B) $(TD Mathematical Alphanumeric Symbols) $(TD Transport And Map Symbols)) + $(TR $(TD Cyrillic Supplement) $(TD Mathematical Operators) $(TD Ugaritic)) + $(TR $(TD Deseret) $(TD Meetei Mayek) $(TD Unified Canadian Aboriginal Syllabics)) + $(TR $(TD Devanagari) $(TD Meetei Mayek Extensions) $(TD Unified Canadian Aboriginal Syllabics Extended)) + $(TR $(TD Devanagari Extended) $(TD Meroitic Cursive) $(TD Vai)) + $(TR $(TD Dingbats) $(TD Meroitic Hieroglyphs) $(TD Variation Selectors)) + $(TR $(TD Domino Tiles) $(TD Miao) $(TD Variation Selectors Supplement)) + $(TR $(TD Egyptian Hieroglyphs) $(TD Miscellaneous Mathematical Symbols-A) $(TD Vedic Extensions)) + $(TR $(TD Emoticons) $(TD Miscellaneous Mathematical Symbols-B) $(TD Vertical Forms)) + $(TR $(TD Enclosed Alphanumerics) $(TD Miscellaneous Symbols) $(TD Yijing Hexagram Symbols)) + $(TR $(TD Enclosed Alphanumeric Supplement) $(TD Miscellaneous Symbols and Arrows) $(TD Yi Radicals)) + $(TR $(TD Enclosed CJK Letters and Months) $(TD Miscellaneous Symbols And Pictographs) $(TD Yi Syllables)) + $(TR $(TD Enclosed Ideographic Supplement) $(TD Miscellaneous Technical) ) + $(TR $(TD Ethiopic) $(TD Modifier Tone Letters) ) + ) + + $(P Bellow is the table with script names accepted by $(LREF unicode.script) + and by the shorthand version $(LREF unicode):) + $(BOOKTABLE $(B Scripts), + $(TR $(TD Arabic) $(TD Hanunoo) $(TD Old_Italic)) + $(TR $(TD Armenian) $(TD Hebrew) $(TD Old_Persian)) + $(TR $(TD Avestan) $(TD Hiragana) $(TD Old_South_Arabian)) + $(TR $(TD Balinese) $(TD Imperial_Aramaic) $(TD Old_Turkic)) + $(TR $(TD Bamum) $(TD Inherited) $(TD Oriya)) + $(TR $(TD Batak) $(TD Inscriptional_Pahlavi) $(TD Osmanya)) + $(TR $(TD Bengali) $(TD Inscriptional_Parthian) $(TD Phags_Pa)) + $(TR $(TD Bopomofo) $(TD Javanese) $(TD Phoenician)) + $(TR $(TD Brahmi) $(TD Kaithi) $(TD Rejang)) + $(TR $(TD Braille) $(TD Kannada) $(TD Runic)) + $(TR $(TD Buginese) $(TD Katakana) $(TD Samaritan)) + $(TR $(TD Buhid) $(TD Kayah_Li) $(TD Saurashtra)) + $(TR $(TD Canadian_Aboriginal) $(TD Kharoshthi) $(TD Sharada)) + $(TR $(TD Carian) $(TD Khmer) $(TD Shavian)) + $(TR $(TD Chakma) $(TD Lao) $(TD Sinhala)) + $(TR $(TD Cham) $(TD Latin) $(TD Sora_Sompeng)) + $(TR $(TD Cherokee) $(TD Lepcha) $(TD Sundanese)) + $(TR $(TD Common) $(TD Limbu) $(TD Syloti_Nagri)) + $(TR $(TD Coptic) $(TD Linear_B) $(TD Syriac)) + $(TR $(TD Cuneiform) $(TD Lisu) $(TD Tagalog)) + $(TR $(TD Cypriot) $(TD Lycian) $(TD Tagbanwa)) + $(TR $(TD Cyrillic) $(TD Lydian) $(TD Tai_Le)) + $(TR $(TD Deseret) $(TD Malayalam) $(TD Tai_Tham)) + $(TR $(TD Devanagari) $(TD Mandaic) $(TD Tai_Viet)) + $(TR $(TD Egyptian_Hieroglyphs) $(TD Meetei_Mayek) $(TD Takri)) + $(TR $(TD Ethiopic) $(TD Meroitic_Cursive) $(TD Tamil)) + $(TR $(TD Georgian) $(TD Meroitic_Hieroglyphs) $(TD Telugu)) + $(TR $(TD Glagolitic) $(TD Miao) $(TD Thaana)) + $(TR $(TD Gothic) $(TD Mongolian) $(TD Thai)) + $(TR $(TD Greek) $(TD Myanmar) $(TD Tibetan)) + $(TR $(TD Gujarati) $(TD New_Tai_Lue) $(TD Tifinagh)) + $(TR $(TD Gurmukhi) $(TD Nko) $(TD Ugaritic)) + $(TR $(TD Han) $(TD Ogham) $(TD Vai)) + $(TR $(TD Hangul) $(TD Ol_Chiki) $(TD Yi)) + ) + + $(P Bellow is the table of names accepted by $(LREF unicode.hangulSyllableType).) + $(BOOKTABLE $(B Hangul syllable type), + $(TR $(TH Abb.) $(TH Long form)) + $(TR $(TD L) $(TD Leading_Jamo)) + $(TR $(TD LV) $(TD LV_Syllable)) + $(TR $(TD LVT) $(TD LVT_Syllable) ) + $(TR $(TD T) $(TD Trailing_Jamo)) + $(TR $(TD V) $(TD Vowel_Jamo)) + ) References: $(WEB www.digitalmars.com/d/ascii-table.html, ASCII Table), $(WEB en.wikipedia.org/wiki/Unicode, Wikipedia), - $(WEB www.unicode.org, The Unicode Consortium) - + $(WEB www.unicode.org, The Unicode Consortium), + $(WEB www.unicode.org/reports/tr15/, Unicode normalization forms), + $(WEB www.unicode.org/reports/tr29/, Unicode text segmentation) + $(WEB www.unicode.org/uni2book/ch05.pdf, + Unicode Implementation Guidelines) + $(WEB www.unicode.org/uni2book/ch03.pdf, + Unicode Conformance) Trademarks: Unicode(tm) is a trademark of Unicode, Inc. Macros: WIKI=Phobos/StdUni - Copyright: Copyright 2000 - + Copyright: Copyright 2013 - License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). - Authors: $(WEB digitalmars.com, Walter Bright), Jonathan M Davis, and Kenji Hara + Authors: Dmitry Olshansky Source: $(PHOBOSSRC std/_uni.d) - +/ + Standards: $(WEB www.unicode.org/versions/Unicode6.2.0/, Unicode v6.2) + +Macros: + +SECTION =

$0

+DEF =
$0
+S_LINK = $+ +CODEPOINT = $(S_LINK Code point, code point) +CODEPOINTS = $(S_LINK Code point, code points) +CHARACTER = $(S_LINK Character, character) +CHARACTERS = $(S_LINK Character, characters) +CLUSTER = $(S_LINK Grapheme cluster, grapheme cluster) ++/ module std.uni; static import std.ascii; +import std.traits, std.range, std.algorithm, std.conv, + std.typetuple, std.exception, core.stdc.stdlib; +import std.array; //@@BUG UFCS doesn't work with 'local' imports +import core.bitop; -enum dchar lineSep = '\u2028'; /// UTF line separator -enum dchar paraSep = '\u2029'; /// UTF paragraph separator +import std.typecons; -/++ - Whether or not $(D c) is a Unicode whitespace character. - (general Unicode category: Part of C0(tab, vertical tab, form feed, - carriage return, and linefeed characters), Zs, Zl, Zp, and NEL(U+0085)) - +/ -bool isWhite(dchar c) @safe pure nothrow +// debug = std_uni; + +debug(std_uni) import std.stdio; + +private: + +version(std_uni_bootstrap){} +else { - return std.ascii.isWhite(c) || - c == lineSep || c == paraSep || - c == '\u0085' || c == '\u00A0' || c == '\u1680' || c == '\u180E' || - (c >= '\u2000' && c <= '\u200A') || - c == '\u202F' || c == '\u205F' || c == '\u3000'; + import std.internal.unicode_tables; // generated file } - -/++ - Return whether $(D c) is a Unicode lowercase character. - +/ -bool isLower(dchar c) @safe pure nothrow +void copyBackwards(T)(T[] src, T[] dest) { - if(std.ascii.isASCII(c)) - return std.ascii.isLower(c); - - return isAlpha(c) && c == toLower(c); + assert(src.length == dest.length); + for(size_t i=src.length; i-- > 0; ) + dest[i] = src[i]; } - -/++ - Return whether $(D c) is a Unicode uppercase character. - +/ -bool isUpper(dchar c) @safe pure nothrow +void copyForward(T)(T[] src, T[] dest) { - if(std.ascii.isASCII(c)) - return std.ascii.isUpper(c); - - return isAlpha(c) && c == toUpper(c); + assert(src.length == dest.length); + for(size_t i=0; i= 0x00C0) + // initialize code point sets using script/block or property name + // set contains code points from both scripts. + auto set = unicode("Cyrillic") | unicode("Armenian"); + // or simpler and statically-checked look + auto ascii = unicode.ASCII; + auto currency = unicode.Currency_Symbol; + + // easy set ops + auto a = set & ascii; + assert(a.empty); // as it has no intersection with ascii + a = set | ascii; + auto b = currency - a; // subtract all ASCII, Cyrillic and Armenian + + // some properties of code point sets + assert(b.length > 45); // 46 items in Unicode 6.1, even more in 6.2 + // testing presence of a code point in a set + // is just fine, it is O(logN) + assert(!b['$']); + assert(!b['\u058F']); // Armenian dram sign + assert(b['¥']); + + // building fast lookup tables, these guarantee O(1) complexity + // 1-level Trie lookup table essentially a huge bit-set ~262Kb + auto oneTrie = toTrie!1(b); + // 2-level far more compact but typically slightly slower + auto twoTrie = toTrie!2(b); + // 3-level even smaller, and a bit slower yet + auto threeTrie = toTrie!3(b); + assert(oneTrie['£']); + assert(twoTrie['£']); + assert(threeTrie['£']); + + // build the trie with the most sensible trie level + // and bind it as a functor + auto cyrillicOrArmenian = toDelegate(set); + auto balance = find!(cyrillicOrArmenian)("Hello ընկեր!"); + assert(balance == "ընկեր!"); + // compatible with bool delegate(dchar) + bool delegate(dchar) bindIt = cyrillicOrArmenian; + + // Normalization + string s = "Plain ascii (and not only), is always normalized!"; + assert(s is normalize(s));// is the same string + + string nonS = "A\u0308ffin"; // A ligature + auto nS = normalize(nonS); // to NFC, the W3C endorsed standard + assert(nS == "Äffin"); + assert(nS != nonS); + string composed = "Äffin"; + + assert(normalize!NFD(composed) == "A\u0308ffin"); + // to NFKD, compatibility decomposition useful for fuzzy matching/searching + assert(normalize!NFKD("2¹⁰") == "210"); +} + +enum lastDchar = 0x10FFFF; + +auto force(T, F)(F from) + if(isIntegral!T && !is(T == F)) +{ + assert(from <= T.max && from >= T.min); + return cast(T)from; +} + +auto force(T, F)(F from) + if(isBitPacked!T && !is(T == F)) +{ + assert(from <= 2^^bitSizeOf!T-1); + return T(cast(TypeOfBitPacked!T)from); +} + +auto force(T, F)(F from) + if(is(T == F)) +{ + return from; +} + +// cheap algorithm grease ;) +auto adaptIntRange(T, F)(F[] src) +{ + //@@@BUG when in the 9 hells will map be copyable again?! + static struct ConvertIntegers { - if((c >= 0x00C0 && c <= 0x00D6) || - (c >= 0x00D8 && c<=0x00DE)) + private F[] data; + + @property T front() { - c += 32; + return force!T(data.front); } - else if((c >= 0x0100 && c < 0x0138) || - (c > 0x0149 && c < 0x0178)) + + void popFront(){ data.popFront(); } + + @property bool empty()const { return data.empty; } + + @property size_t length()const { return data.length; } + + auto opSlice(size_t s, size_t e) { - if(c == 0x0130) - c = 0x0069; - else if((c & 1) == 0) - ++c; + return ConvertIntegers(data[s..e]); } - else if(c == 0x0178) - c = 0x00FF; - else if((c >= 0x0139 && c < 0x0149) || - (c > 0x0178 && c < 0x017F)) + + @property size_t opDollar(){ return data.length; } + } + return ConvertIntegers(src); +} + +// repeat X times the bit-pattern in val assuming it's length is 'bits' +size_t replicateBits(size_t times, size_t bits)(size_t val) +{ + static if(times == 1) + return val; + else static if(bits == 1) + { + static if(times == size_t.sizeof*8) + return val ? size_t.max : 0; + else + return val ? (1<= 1) + offsets[i] = offsets[i-1] + + spaceFor!(bitSizeOf!(Types[i-1]))(sizes[i-1]); } - else if(c >= 0x0200 && c <= 0x0217) - { - if((c & 1) == 0) - ++c; - } - else if((c >= 0x0401 && c <= 0x040C) || - (c>= 0x040E && c <= 0x040F)) - { - c += 80; - } - else if(c >= 0x0410 && c <= 0x042F) - c += 32; - else if(c >= 0x0460 && c <= 0x047F) - { - if((c & 1) == 0) - ++c; - } - else if(c >= 0x0531 && c <= 0x0556) - c += 48; - else if(c >= 0x10A0 && c <= 0x10C5) - c += 48; - else if(c >= 0xFF21 && c <= 0xFF3A) - c += 32; + + storage = new size_t[full_size]; } - return c; -} - - -/++ - If $(D c) is a Unicode lowercase character, then its uppercase equivalent - is returned. Otherwise $(D c) is returned. - +/ -dchar toUpper(dchar c) @safe pure nothrow -{ - if(std.ascii.isLower(c)) - c -= 32; - else if(c >= 0x00E0) + this(const(size_t)[] raw_offsets, + const(size_t)[] raw_sizes, const(size_t)[] data)const { - if((c >= 0x00E0 && c <= 0x00F6) || - (c >= 0x00F8 && c <= 0x00FE)) - { - c -= 32; - } - else if(c == 0x00FF) - c = 0x0178; - else if((c >= 0x0100 && c < 0x0138) || - (c > 0x0149 && c < 0x0178)) - { - if(c == 0x0131) - c = 0x0049; - else if(c & 1) - --c; - } - else if((c >= 0x0139 && c < 0x0149) || - (c > 0x0178 && c < 0x017F)) - { - if((c & 1) == 0) - --c; - } - else if(c == 0x017F) - c = 0x0053; - else if(c >= 0x0200 && c <= 0x0217) - { - if(c & 1) - --c; - } - else if(c >= 0x0430 && c<= 0x044F) - c -= 32; - else if((c >= 0x0451 && c <= 0x045C) || - (c >=0x045E && c<= 0x045F)) - { - c -= 80; - } - else if(c >= 0x0460 && c <= 0x047F) - { - if(c & 1) - --c; - } - else if(c >= 0x0561 && c < 0x0587) - c -= 48; - else if(c >= 0xFF41 && c <= 0xFF5A) - c -= 32; + offsets[] = raw_offsets[]; + sz[] = raw_sizes[]; + storage = data; } - return c; -} - - -/++ - Returns whether $(D c) is a Unicode alpha character - (general Unicode category: Lu, Ll, Lt, Lm, and Lo). - - Standards: Unicode 5.0.0. - +/ -bool isAlpha(dchar c) @safe pure nothrow -{ - static immutable dchar[2][] table = - [ - [ 'A', 'Z' ], - [ 'a', 'z' ], - [ 0x00AA, 0x00AA ], - [ 0x00B5, 0x00B5 ], - [ 0x00BA, 0x00BA ], - [ 0x00C0, 0x00D6 ], - [ 0x00D8, 0x00F6 ], - [ 0x00F8, 0x02C1 ], - [ 0x02C6, 0x02D1 ], - [ 0x02E0, 0x02E4 ], - [ 0x02EE, 0x02EE ], - [ 0x037A, 0x037D ], - [ 0x0386, 0x0386 ], - [ 0x0388, 0x038A ], - [ 0x038C, 0x038C ], - [ 0x038E, 0x03A1 ], - [ 0x03A3, 0x03CE ], - [ 0x03D0, 0x03F5 ], - [ 0x03F7, 0x0481 ], - [ 0x048A, 0x0513 ], - [ 0x0531, 0x0556 ], - [ 0x0559, 0x0559 ], - [ 0x0561, 0x0587 ], - [ 0x05D0, 0x05EA ], - [ 0x05F0, 0x05F2 ], - [ 0x0621, 0x063A ], - [ 0x0640, 0x064A ], - [ 0x066E, 0x066F ], - [ 0x0671, 0x06D3 ], - [ 0x06D5, 0x06D5 ], - [ 0x06E5, 0x06E6 ], - [ 0x06EE, 0x06EF ], - [ 0x06FA, 0x06FC ], - [ 0x06FF, 0x06FF ], - [ 0x0710, 0x0710 ], - [ 0x0712, 0x072F ], - [ 0x074D, 0x076D ], - [ 0x0780, 0x07A5 ], - [ 0x07B1, 0x07B1 ], - [ 0x07CA, 0x07EA ], - [ 0x07F4, 0x07F5 ], - [ 0x07FA, 0x07FA ], - [ 0x0904, 0x0939 ], - [ 0x093D, 0x093D ], - [ 0x0950, 0x0950 ], - [ 0x0958, 0x0961 ], - [ 0x097B, 0x097F ], - [ 0x0985, 0x098C ], - [ 0x098F, 0x0990 ], - [ 0x0993, 0x09A8 ], - [ 0x09AA, 0x09B0 ], - [ 0x09B2, 0x09B2 ], - [ 0x09B6, 0x09B9 ], - [ 0x09BD, 0x09BD ], - [ 0x09CE, 0x09CE ], - [ 0x09DC, 0x09DD ], - [ 0x09DF, 0x09E1 ], - [ 0x09F0, 0x09F1 ], - [ 0x0A05, 0x0A0A ], - [ 0x0A0F, 0x0A10 ], - [ 0x0A13, 0x0A28 ], - [ 0x0A2A, 0x0A30 ], - [ 0x0A32, 0x0A33 ], - [ 0x0A35, 0x0A36 ], - [ 0x0A38, 0x0A39 ], - [ 0x0A59, 0x0A5C ], - [ 0x0A5E, 0x0A5E ], - [ 0x0A72, 0x0A74 ], - [ 0x0A85, 0x0A8D ], - [ 0x0A8F, 0x0A91 ], - [ 0x0A93, 0x0AA8 ], - [ 0x0AAA, 0x0AB0 ], - [ 0x0AB2, 0x0AB3 ], - [ 0x0AB5, 0x0AB9 ], - [ 0x0ABD, 0x0ABD ], - [ 0x0AD0, 0x0AD0 ], - [ 0x0AE0, 0x0AE1 ], - [ 0x0B05, 0x0B0C ], - [ 0x0B0F, 0x0B10 ], - [ 0x0B13, 0x0B28 ], - [ 0x0B2A, 0x0B30 ], - [ 0x0B32, 0x0B33 ], - [ 0x0B35, 0x0B39 ], - [ 0x0B3D, 0x0B3D ], - [ 0x0B5C, 0x0B5D ], - [ 0x0B5F, 0x0B61 ], - [ 0x0B71, 0x0B71 ], - [ 0x0B83, 0x0B83 ], - [ 0x0B85, 0x0B8A ], - [ 0x0B8E, 0x0B90 ], - [ 0x0B92, 0x0B95 ], - [ 0x0B99, 0x0B9A ], - [ 0x0B9C, 0x0B9C ], - [ 0x0B9E, 0x0B9F ], - [ 0x0BA3, 0x0BA4 ], - [ 0x0BA8, 0x0BAA ], - [ 0x0BAE, 0x0BB9 ], - [ 0x0C05, 0x0C0C ], - [ 0x0C0E, 0x0C10 ], - [ 0x0C12, 0x0C28 ], - [ 0x0C2A, 0x0C33 ], - [ 0x0C35, 0x0C39 ], - [ 0x0C60, 0x0C61 ], - [ 0x0C85, 0x0C8C ], - [ 0x0C8E, 0x0C90 ], - [ 0x0C92, 0x0CA8 ], - [ 0x0CAA, 0x0CB3 ], - [ 0x0CB5, 0x0CB9 ], - [ 0x0CBD, 0x0CBD ], - [ 0x0CDE, 0x0CDE ], - [ 0x0CE0, 0x0CE1 ], - [ 0x0D05, 0x0D0C ], - [ 0x0D0E, 0x0D10 ], - [ 0x0D12, 0x0D28 ], - [ 0x0D2A, 0x0D39 ], - [ 0x0D60, 0x0D61 ], - [ 0x0D85, 0x0D96 ], - [ 0x0D9A, 0x0DB1 ], - [ 0x0DB3, 0x0DBB ], - [ 0x0DBD, 0x0DBD ], - [ 0x0DC0, 0x0DC6 ], - [ 0x0E01, 0x0E30 ], - [ 0x0E32, 0x0E33 ], - [ 0x0E40, 0x0E46 ], - [ 0x0E81, 0x0E82 ], - [ 0x0E84, 0x0E84 ], - [ 0x0E87, 0x0E88 ], - [ 0x0E8A, 0x0E8A ], - [ 0x0E8D, 0x0E8D ], - [ 0x0E94, 0x0E97 ], - [ 0x0E99, 0x0E9F ], - [ 0x0EA1, 0x0EA3 ], - [ 0x0EA5, 0x0EA5 ], - [ 0x0EA7, 0x0EA7 ], - [ 0x0EAA, 0x0EAB ], - [ 0x0EAD, 0x0EB0 ], - [ 0x0EB2, 0x0EB3 ], - [ 0x0EBD, 0x0EBD ], - [ 0x0EC0, 0x0EC4 ], - [ 0x0EC6, 0x0EC6 ], - [ 0x0EDC, 0x0EDD ], - [ 0x0F00, 0x0F00 ], - [ 0x0F40, 0x0F47 ], - [ 0x0F49, 0x0F6A ], - [ 0x0F88, 0x0F8B ], - [ 0x1000, 0x1021 ], - [ 0x1023, 0x1027 ], - [ 0x1029, 0x102A ], - [ 0x1050, 0x1055 ], - [ 0x10A0, 0x10C5 ], - [ 0x10D0, 0x10FA ], - [ 0x10FC, 0x10FC ], - [ 0x1100, 0x1159 ], - [ 0x115F, 0x11A2 ], - [ 0x11A8, 0x11F9 ], - [ 0x1200, 0x1248 ], - [ 0x124A, 0x124D ], - [ 0x1250, 0x1256 ], - [ 0x1258, 0x1258 ], - [ 0x125A, 0x125D ], - [ 0x1260, 0x1288 ], - [ 0x128A, 0x128D ], - [ 0x1290, 0x12B0 ], - [ 0x12B2, 0x12B5 ], - [ 0x12B8, 0x12BE ], - [ 0x12C0, 0x12C0 ], - [ 0x12C2, 0x12C5 ], - [ 0x12C8, 0x12D6 ], - [ 0x12D8, 0x1310 ], - [ 0x1312, 0x1315 ], - [ 0x1318, 0x135A ], - [ 0x1380, 0x138F ], - [ 0x13A0, 0x13F4 ], - [ 0x1401, 0x166C ], - [ 0x166F, 0x1676 ], - [ 0x1681, 0x169A ], - [ 0x16A0, 0x16EA ], - [ 0x1700, 0x170C ], - [ 0x170E, 0x1711 ], - [ 0x1720, 0x1731 ], - [ 0x1740, 0x1751 ], - [ 0x1760, 0x176C ], - [ 0x176E, 0x1770 ], - [ 0x1780, 0x17B3 ], - [ 0x17D7, 0x17D7 ], - [ 0x17DC, 0x17DC ], - [ 0x1820, 0x1877 ], - [ 0x1880, 0x18A8 ], - [ 0x1900, 0x191C ], - [ 0x1950, 0x196D ], - [ 0x1970, 0x1974 ], - [ 0x1980, 0x19A9 ], - [ 0x19C1, 0x19C7 ], - [ 0x1A00, 0x1A16 ], - [ 0x1B05, 0x1B33 ], - [ 0x1B45, 0x1B4B ], - [ 0x1D00, 0x1DBF ], - [ 0x1E00, 0x1E9B ], - [ 0x1EA0, 0x1EF9 ], - [ 0x1F00, 0x1F15 ], - [ 0x1F18, 0x1F1D ], - [ 0x1F20, 0x1F45 ], - [ 0x1F48, 0x1F4D ], - [ 0x1F50, 0x1F57 ], - [ 0x1F59, 0x1F59 ], - [ 0x1F5B, 0x1F5B ], - [ 0x1F5D, 0x1F5D ], - [ 0x1F5F, 0x1F7D ], - [ 0x1F80, 0x1FB4 ], - [ 0x1FB6, 0x1FBC ], - [ 0x1FBE, 0x1FBE ], - [ 0x1FC2, 0x1FC4 ], - [ 0x1FC6, 0x1FCC ], - [ 0x1FD0, 0x1FD3 ], - [ 0x1FD6, 0x1FDB ], - [ 0x1FE0, 0x1FEC ], - [ 0x1FF2, 0x1FF4 ], - [ 0x1FF6, 0x1FFC ], - [ 0x2071, 0x2071 ], - [ 0x207F, 0x207F ], - [ 0x2090, 0x2094 ], - [ 0x2102, 0x2102 ], - [ 0x2107, 0x2107 ], - [ 0x210A, 0x2113 ], - [ 0x2115, 0x2115 ], - [ 0x2119, 0x211D ], - [ 0x2124, 0x2124 ], - [ 0x2126, 0x2126 ], - [ 0x2128, 0x2128 ], - [ 0x212A, 0x212D ], - [ 0x212F, 0x2139 ], - [ 0x213C, 0x213F ], - [ 0x2145, 0x2149 ], - [ 0x214E, 0x214E ], - [ 0x2183, 0x2184 ], - [ 0x2C00, 0x2C2E ], - [ 0x2C30, 0x2C5E ], - [ 0x2C60, 0x2C6C ], - [ 0x2C74, 0x2C77 ], - [ 0x2C80, 0x2CE4 ], - [ 0x2D00, 0x2D25 ], - [ 0x2D30, 0x2D65 ], - [ 0x2D6F, 0x2D6F ], - [ 0x2D80, 0x2D96 ], - [ 0x2DA0, 0x2DA6 ], - [ 0x2DA8, 0x2DAE ], - [ 0x2DB0, 0x2DB6 ], - [ 0x2DB8, 0x2DBE ], - [ 0x2DC0, 0x2DC6 ], - [ 0x2DC8, 0x2DCE ], - [ 0x2DD0, 0x2DD6 ], - [ 0x2DD8, 0x2DDE ], - [ 0x3005, 0x3006 ], - [ 0x3031, 0x3035 ], - [ 0x303B, 0x303C ], - [ 0x3041, 0x3096 ], - [ 0x309D, 0x309F ], - [ 0x30A1, 0x30FA ], - [ 0x30FC, 0x30FF ], - [ 0x3105, 0x312C ], - [ 0x3131, 0x318E ], - [ 0x31A0, 0x31B7 ], - [ 0x31F0, 0x31FF ], - [ 0x3400, 0x4DB5 ], - [ 0x4E00, 0x9FBB ], - [ 0xA000, 0xA48C ], - [ 0xA717, 0xA71A ], - [ 0xA800, 0xA801 ], - [ 0xA803, 0xA805 ], - [ 0xA807, 0xA80A ], - [ 0xA80C, 0xA822 ], - [ 0xA840, 0xA873 ], - [ 0xAC00, 0xD7A3 ], - [ 0xF900, 0xFA2D ], - [ 0xFA30, 0xFA6A ], - [ 0xFA70, 0xFAD9 ], - [ 0xFB00, 0xFB06 ], - [ 0xFB13, 0xFB17 ], - [ 0xFB1D, 0xFB1D ], - [ 0xFB1F, 0xFB28 ], - [ 0xFB2A, 0xFB36 ], - [ 0xFB38, 0xFB3C ], - [ 0xFB3E, 0xFB3E ], - [ 0xFB40, 0xFB41 ], - [ 0xFB43, 0xFB44 ], - [ 0xFB46, 0xFBB1 ], - [ 0xFBD3, 0xFD3D ], - [ 0xFD50, 0xFD8F ], - [ 0xFD92, 0xFDC7 ], - [ 0xFDF0, 0xFDFB ], - [ 0xFE70, 0xFE74 ], - [ 0xFE76, 0xFEFC ], - [ 0xFF21, 0xFF3A ], - [ 0xFF41, 0xFF5A ], - [ 0xFF66, 0xFFBE ], - [ 0xFFC2, 0xFFC7 ], - [ 0xFFCA, 0xFFCF ], - [ 0xFFD2, 0xFFD7 ], - [ 0xFFDA, 0xFFDC ], - [ 0x10000, 0x1000B ], - [ 0x1000D, 0x10026 ], - [ 0x10028, 0x1003A ], - [ 0x1003C, 0x1003D ], - [ 0x1003F, 0x1004D ], - [ 0x10050, 0x1005D ], - [ 0x10080, 0x100FA ], - [ 0x10300, 0x1031E ], - [ 0x10330, 0x10340 ], - [ 0x10342, 0x10349 ], - [ 0x10380, 0x1039D ], - [ 0x103A0, 0x103C3 ], - [ 0x103C8, 0x103CF ], - [ 0x10400, 0x1049D ], - [ 0x10800, 0x10805 ], - [ 0x10808, 0x10808 ], - [ 0x1080A, 0x10835 ], - [ 0x10837, 0x10838 ], - [ 0x1083C, 0x1083C ], - [ 0x1083F, 0x1083F ], - [ 0x10900, 0x10915 ], - [ 0x10A00, 0x10A00 ], - [ 0x10A10, 0x10A13 ], - [ 0x10A15, 0x10A17 ], - [ 0x10A19, 0x10A33 ], - [ 0x12000, 0x1236E ], - [ 0x1D400, 0x1D454 ], - [ 0x1D456, 0x1D49C ], - [ 0x1D49E, 0x1D49F ], - [ 0x1D4A2, 0x1D4A2 ], - [ 0x1D4A5, 0x1D4A6 ], - [ 0x1D4A9, 0x1D4AC ], - [ 0x1D4AE, 0x1D4B9 ], - [ 0x1D4BB, 0x1D4BB ], - [ 0x1D4BD, 0x1D4C3 ], - [ 0x1D4C5, 0x1D505 ], - [ 0x1D507, 0x1D50A ], - [ 0x1D50D, 0x1D514 ], - [ 0x1D516, 0x1D51C ], - [ 0x1D51E, 0x1D539 ], - [ 0x1D53B, 0x1D53E ], - [ 0x1D540, 0x1D544 ], - [ 0x1D546, 0x1D546 ], - [ 0x1D54A, 0x1D550 ], - [ 0x1D552, 0x1D6A5 ], - [ 0x1D6A8, 0x1D6C0 ], - [ 0x1D6C2, 0x1D6DA ], - [ 0x1D6DC, 0x1D6FA ], - [ 0x1D6FC, 0x1D714 ], - [ 0x1D716, 0x1D734 ], - [ 0x1D736, 0x1D74E ], - [ 0x1D750, 0x1D76E ], - [ 0x1D770, 0x1D788 ], - [ 0x1D78A, 0x1D7A8 ], - [ 0x1D7AA, 0x1D7C2 ], - [ 0x1D7C4, 0x1D7CB ], - [ 0x20000, 0x2A6D6 ], - [ 0x2F800, 0x2FA1D ], - ]; - - // optimization - if(c < 0xAA) + @property auto slice(size_t n)()inout pure nothrow { - if(c < 'A') - return false; - if(c <= 'Z') - return true; - if(c < 'a') - return false; - if(c <= 'z') - return true; - return false; + auto ptr = raw_ptr!n; + return packedArrayView!(Types[n])(ptr, sz[n]); } - return binarySearch!table(c); + @property auto ptr(size_t n)()inout pure nothrow + { + auto ptr = raw_ptr!n; + return inout(PackedPtr!(Types[n]))(ptr); + } + + template length(size_t n) + { + @property size_t length()const{ return sz[n]; } + + @property void length(size_t new_size) + { + if(new_size > sz[n]) + {// extend + size_t delta = (new_size - sz[n]); + sz[n] += delta; + delta = spaceFor!(bitSizeOf!(Types[n]))(delta); + storage.length += delta;// extend space at end + // raw_slice!x must follow resize as it could be moved! + // next stmts move all data past this array, last-one-goes-first + static if(n != dim-1) + { + auto start = raw_ptr!(n+1); + // len includes delta + size_t len = (storage.ptr+storage.length-start); + + copyBackwards(start[0..len-delta], start[delta..len]); + + start[0..delta] = 0; + // offsets are used for raw_slice, ptr etc. + foreach(i; n+1..dim) + offsets[i] += delta; + } + } + else if(new_size < sz[n]) + {// shrink + size_t delta = (sz[n] - new_size); + sz[n] -= delta; + delta = spaceFor!(bitSizeOf!(Types[n]))(delta); + // move all data past this array, forward direction + static if(n != dim-1) + { + auto start = raw_ptr!(n+1); + size_t len = (storage.ptr+storage.length-start); + copyForward(start[0..len-delta], start[delta..len]); + + // adjust offsets last, they affect raw_slice + foreach(i; n+1..dim) + offsets[i] -= delta; + } + storage.length -= delta; + } + // else - NOP + } + } + + @property size_t bytes(size_t n=size_t.max)() const + { + static if(n == size_t.max) + return storage.length*size_t.sizeof; + else static if(n != Types.length-1) + return (raw_ptr!(n+1)-raw_ptr!n)*size_t.sizeof; + else + return (storage.ptr+storage.length - raw_ptr!n)*size_t.sizeof; + } + + void store(OutRange)(scope OutRange sink) const + if(isOutputRange!(OutRange, char)) + { + import std.format; + formattedWrite(sink, "[%( 0x%x, %)]", offsets[]); + formattedWrite(sink, ", [%( 0x%x, %)]", sz[]); + formattedWrite(sink, ", [%( 0x%x, %)]", storage); + } + +private: + @property auto raw_ptr(size_t n)()inout + { + static if(n == 0) + return storage.ptr; + else + { + return storage.ptr+offsets[n]; + } + } + enum dim = Types.length; + size_t[dim] offsets;// offset for level x + size_t[dim] sz;// size of level x + alias staticMap!(bitSizeOf, Types) bitWidth; + size_t[] storage; } unittest { - for(dchar c = 0; c < 0x80; ++c) - { - if(c >= 'A' && c <= 'Z') - assert(isAlpha(c)); - else if(c >= 'a' && c <= 'z') - assert(isAlpha(c)); - else - assert(!isAlpha(c)); + enum dg = (){ + // sizes are: + // lvl0: 3, lvl1 : 2, lvl2: 1 + auto m = MultiArray!(int, ubyte, int)(3,2,1); + + static void check(size_t k, T)(ref T m, int n) + { + foreach(i; 0..n) + assert(m.slice!(k)[i] == i+1, text("level:",i," : ",m.slice!(k)[0..n])); + } + + static void checkB(size_t k, T)(ref T m, int n) + { + foreach(i; 0..n) + assert(m.slice!(k)[i] == n-i, text("level:",i," : ",m.slice!(k)[0..n])); + } + + static void fill(size_t k, T)(ref T m, int n) + { + foreach(i; 0..n) + m.slice!(k)[i] = force!ubyte(i+1); + } + + static void fillB(size_t k, T)(ref T m, int n) + { + foreach(i; 0..n) + m.slice!(k)[i] = force!ubyte(n-i); + } + + m.length!1 = 100; + fill!1(m, 100); + check!1(m, 100); + + m.length!0 = 220; + fill!0(m, 220); + check!1(m, 100); + check!0(m, 220); + + m.length!2 = 17; + fillB!2(m, 17); + checkB!2(m, 17); + check!0(m, 220); + check!1(m, 100); + + m.length!2 = 33; + checkB!2(m, 17); + fillB!2(m, 33); + checkB!2(m, 33); + check!0(m, 220); + check!1(m, 100); + + m.length!1 = 195; + fillB!1(m, 195); + checkB!1(m, 195); + checkB!2(m, 33); + check!0(m, 220); + + auto marr = MultiArray!(BitPacked!(uint, 4), BitPacked!(uint, 6))(20, 10); + marr.length!0 = 15; + marr.length!1 = 30; + fill!1(marr, 30); + fill!0(marr, 15); + check!1(marr, 30); + check!0(marr, 15); + return 0; + }; + enum ct = dg(); + auto rt = dg(); +} + +unittest +{// more bitpacking tests + alias MultiArray!(BitPacked!(size_t, 3) + , BitPacked!(size_t, 4) + , BitPacked!(size_t, 3) + , BitPacked!(size_t, 6) + , bool) Bitty; + alias sliceBits!(13, 16) fn1; + alias sliceBits!( 9, 13) fn2; + alias sliceBits!( 6, 9) fn3; + alias sliceBits!( 0, 6) fn4; + static void check(size_t lvl, MA)(ref MA arr){ + for(size_t i = 0; i< arr.length!lvl; i++) + assert(arr.slice!(lvl)[i] == i, text("Mismatch on lvl ", lvl, " idx ", i, " value: ", arr.slice!(lvl)[i])); } + + static void fillIdx(size_t lvl, MA)(ref MA arr){ + for(size_t i = 0; i< arr.length!lvl; i++) + arr.slice!(lvl)[i] = i; + } + Bitty m1; + + m1.length!4 = 10; + m1.length!3 = 2^^6; + m1.length!2 = 2^^3; + m1.length!1 = 2^^4; + m1.length!0 = 2^^3; + + m1.length!4 = 2^^16; + + for(size_t i = 0; i< m1.length!4; i++) + m1.slice!(4)[i] = i % 2; + + fillIdx!1(m1); + check!1(m1); + fillIdx!2(m1); + check!2(m1); + fillIdx!3(m1); + check!3(m1); + fillIdx!0(m1); + check!0(m1); + check!3(m1); + check!2(m1); + check!1(m1); + for(size_t i=0; i < 2^^16; i++) + { + m1.slice!(4)[i] = i % 2; + m1.slice!(0)[fn1(i)] = fn1(i); + m1.slice!(1)[fn2(i)] = fn2(i); + m1.slice!(2)[fn3(i)] = fn3(i); + m1.slice!(3)[fn4(i)] = fn4(i); + } + for(size_t i=0; i < 2^^16; i++) + { + assert(m1.slice!(4)[i] == i % 2); + assert(m1.slice!(0)[fn1(i)] == fn1(i)); + assert(m1.slice!(1)[fn2(i)] == fn2(i)); + assert(m1.slice!(2)[fn3(i)] == fn3(i)); + assert(m1.slice!(3)[fn4(i)] == fn4(i)); + } +} + +size_t spaceFor(size_t _bits)(size_t new_len) pure nothrow +{ + enum bits = _bits == 1 ? 1 : ceilPowerOf2(_bits);// see PackedArrayView + static if(bits > 8*size_t.sizeof) + { + static assert(bits % (size_t.sizeof*8) == 0); + return new_len * bits/(8*size_t.sizeof); + } + else + { + enum factor = size_t.sizeof*8/bits; + return (new_len+factor-1)/factor; // rounded up + } +} + +template isBitPackableType(T) +{ + enum isBitPackableType = isBitPacked!T + || isIntegral!T || is(T == bool) || isSomeChar!T; +} + +//============================================================================ +template PackedArrayView(T) + if((is(T dummy == BitPacked!(U, sz), U, size_t sz) + && isBitPackableType!U) || isBitPackableType!T) +{ + private enum bits = bitSizeOf!T; + alias PackedArrayView = PackedArrayViewImpl!(T, bits > 1 ? ceilPowerOf2(bits) : 1); +} + +//unsafe and fast access to a chunk of RAM as if it contains packed values +template PackedPtr(T) + if((is(T dummy == BitPacked!(U, sz), U, size_t sz) + && isBitPackableType!U) || isBitPackableType!T) +{ + private enum bits = bitSizeOf!T; + alias PackedPtr = PackedPtrImpl!(T, bits > 1 ? ceilPowerOf2(bits) : 1); +} + +@trusted struct PackedPtrImpl(T, size_t bits) +{ +pure nothrow: + static assert(isPowerOf2(bits)); + + this(inout(size_t)* ptr)inout + { + origin = ptr; + } + + private T simpleIndex(size_t n) inout + { + auto q = n / factor; + auto r = n % factor; + return cast(T)((origin[q] >> bits*r) & mask); + } + + private void simpleWrite(TypeOfBitPacked!T val, size_t n) + in + { + static if(isIntegral!T) + assert(val <= mask); + } + body + { + auto q = n / factor; + auto r = n % factor; + size_t tgt_shift = bits*r; + size_t word = origin[q]; + origin[q] = (word & ~(mask<= end) //rounded up >= then end of slice + { + //nothing to gain, use per element assignment + foreach(i; start..end) + ptr[i] = val; + return; + } + size_t pad_end = end/factor*factor; // rounded down + size_t i; + for(i=start; i= max) + { + if(pred(range[idx+m], needle)) + idx += m; + m /= 2; + } + mixin(genUnrolledSwitchSearch(max)); + return idx; +} + +// +size_t floorPowerOf2(size_t arg) @safe pure nothrow +{ + assert(arg > 1); // else bsr is undefined + return 1< 1); // else bsr is undefined + return 1< delta) + {// replace increases length + delta = stuff.length - delta;// now, new is > old by delta + static if(is(Policy == void)) + dest.length = dest.length+delta;//@@@BUG lame @property + else + dest = Policy.realloc(dest, dest.length+delta); + auto rem = copy(retro(dest[to..dest.length-delta]) + , retro(dest[to+delta..dest.length])); + assert(rem.empty); + copy(stuff, dest[from..stuff_end]); + } + else if(stuff.length == delta) + { + copy(stuff, dest[from..to]); + } + else + {// replace decreases length by delta + delta = delta - stuff.length; + copy(stuff, dest[from..stuff_end]); + auto rem = copy(dest[to..dest.length] + , dest[stuff_end..dest.length-delta]); + static if(is(Policy == void)) + dest.length = dest.length - delta;//@@@BUG lame @property + else + dest = Policy.realloc(dest, dest.length-delta); + assert(rem.empty); + } + return stuff_end; +} + + +// Simple storage manipulation policy +@trusted public struct GcPolicy +{ + static T[] dup(T)(const T[] arr) + { + return arr.dup; + } + + static T[] alloc(T)(size_t size) + { + return new T[size]; + } + + static T[] realloc(T)(T[] arr, size_t sz) + { + arr.length = sz; + return arr; + } + + static void replaceImpl(T, Range)(ref T[] dest, size_t from, size_t to, Range stuff) + { + replaceInPlace(dest, from, to, stuff); + } + + static void append(T, V)(ref T[] arr, V value) + if(!isInputRange!V) + { + arr ~= force!T(value); + } + + static void append(T, V)(ref T[] arr, V value) + if(isInputRange!V) + { + insertInPlace(arr, arr.length, value); + } + + static void destroy(T)(ref T arr) + if(isDynamicArray!T && is(Unqual!T == T)) + { + version(bug10929) //@@@BUG@@@ + { + debug + { + arr[] = cast(typeof(T.init[0]))(0xdead_beef); + } + arr = null; + } + } + + static void destroy(T)(ref T arr) + if(isDynamicArray!T && !is(Unqual!T == T)) + { + arr = null; + } +} + +// ditto +@trusted struct ReallocPolicy +{ + static T[] dup(T)(const T[] arr) + { + auto result = alloc!T(arr.length); + result[] = arr[]; + return result; + } + + static T[] alloc(T)(size_t size) + { + auto ptr = cast(T*)enforce(malloc(T.sizeof*size), "out of memory on C heap"); + return ptr[0..size]; + } + + static T[] realloc(T)(T[] arr, size_t size) + { + if(!size) + { + destroy(arr); + return null; + } + auto ptr = cast(T*)enforce(core.stdc.stdlib.realloc( + arr.ptr, T.sizeof*size), "out of memory on C heap"); + return ptr[0..size]; + } + + static void replaceImpl(T, Range)(ref T[] dest, size_t from, size_t to, Range stuff) + { + genericReplace!(ReallocPolicy)(dest, from, to, stuff); + } + + static void append(T, V)(ref T[] arr, V value) + if(!isInputRange!V) + { + arr = realloc(arr, arr.length+1); + arr[$-1] = force!T(value); + } + + static void append(T, V)(ref T[] arr, V value) + if(isInputRange!V && hasLength!V) + { + arr = realloc(arr, arr.length+value.length); + copy(value, arr[$-value.length..$]); + } + + static void destroy(T)(ref T[] arr) + { + if(arr.ptr) + free(arr.ptr); + arr = null; + } +} + +//build hack +alias Uint24Array!ReallocPolicy _RealArray; + +unittest +{ + with(ReallocPolicy) + { + bool test(T, U, V)(T orig, size_t from, size_t to, U toReplace, V result, + string file = __FILE__, size_t line = __LINE__) + { + { + replaceImpl(orig, from, to, toReplace); + scope(exit) destroy(orig); + if(!equalS(orig, result)) + return false; + } + return true; + } + static T[] arr(T)(T[] args... ) + { + return dup(args); + } + + assert(test(arr([1, 2, 3, 4]), 0, 0, [5, 6, 7], [5, 6, 7, 1, 2, 3, 4])); + assert(test(arr([1, 2, 3, 4]), 0, 2, cast(int[])[], [3, 4])); + assert(test(arr([1, 2, 3, 4]), 0, 4, [5, 6, 7], [5, 6, 7])); + assert(test(arr([1, 2, 3, 4]), 0, 2, [5, 6, 7], [5, 6, 7, 3, 4])); + assert(test(arr([1, 2, 3, 4]), 2, 3, [5, 6, 7], [1, 2, 5, 6, 7, 4])); + } +} + +/** + Tests if T is some kind a set of code points. Intended for template constraints. +*/ +public template isCodepointSet(T) +{ + static if(is(T dummy == InversionList!(Args), Args...)) + enum isCodepointSet = true; + else + enum isCodepointSet = false; +} + +/** + Tests if $(D T) is a pair of integers that implicitly convert to $(D V). + The following code must compile for any pair $(D T): + --- + (T x){ V a = x[0]; V b = x[1];} + --- + The following must not compile: + --- + (T x){ V c = x[2];} + --- +*/ +public template isIntegralPair(T, V=uint) +{ + enum isIntegralPair = is(typeof((T x){ V a = x[0]; V b = x[1];})) + && !is(typeof((T x){ V c = x[2]; })); +} + + +/** + The recommended default type for set of $(CODEPOINTS). + For details, see the current implementation: $(LREF InversionList). +*/ +public alias InversionList!GcPolicy CodepointSet; + + +//@@@BUG: std.typecons tuples depend on std.format to produce fields mixin +// which relies on std.uni.isGraphical and this chain blows up with Forward reference error +// hence below doesn't seem to work +// public alias Tuple!(uint, "a", uint, "b") CodepointInterval; + +/** + The recommended type of $(XREF _typecons, Tuple) + to represent [a, b$(RPAREN) intervals of $(CODEPOINTS). As used in $(LREF InversionList). + Any interval type should pass $(LREF isIntegralPair) trait. +*/ +public struct CodepointInterval +{ + uint[2] _tuple; + alias _tuple this; + this(uint low, uint high) + { + _tuple[0] = low; + _tuple[1] = high; + } + bool opEquals(T)(T val) const + { + return this[0] == val[0] && this[1] == val[1]; + } + @property ref uint a(){ return _tuple[0]; } + @property ref uint b(){ return _tuple[1]; } +} + +//@@@BUG another forward reference workaround +@trusted bool equalS(R1, R2)(R1 lhs, R2 rhs) +{ + for(;;){ + if(lhs.empty) + return rhs.empty; + if(rhs.empty) + return false; + if(lhs.front != rhs.front) + return false; + lhs.popFront(); + rhs.popFront(); + } +} + +/** + $(P + $(D InversionList) is a set of $(CODEPOINTS) + represented as an array of open-right [a, b$(RPAREN) + intervals (see $(LREF CodepointInterval) above). + The name comes from the way the representation reads left to right. + For instance a set of all values [10, 50$(RPAREN), [80, 90$(RPAREN), + plus a singular value 60 looks like this: + ) + --- + 10, 50, 60, 61, 80, 90 + --- + $(P + The way to read this is: start with negative meaning that all numbers + smaller then the next one are not present in this set (and positive + - the contrary). Then switch positive/negative after each + number passed from left to right. + ) + $(P This way negative spans until 10, then positive until 50, + then negative until 60, then positive until 61, and so on. + As seen this provides a space-efficient storage of highly redundant data + that comes in long runs. A description which Unicode $(CHARACTER) + properties fit nicely. The technique itself could be seen as a variation + on $(LUCKY RLE encoding). + ) + + $(P Sets are value types (just like $(D int) is) thus they + are never aliased. + ) + Example: + --- + auto a = CodepointSet('a', 'z'+1); + auto b = CodepointSet('A', 'Z'+1); + auto c = a; + a = a | b; + assert(a == CodepointSet('A', 'Z'+1, 'a', 'z'+1)); + assert(a != c); + --- + $(P See also $(LREF unicode) for simpler construction of sets + from predefined ones. + ) + + $(P Memory usage is 6 bytes per each contiguous interval in a set. + The value semantics are achieved by using the + ($WEB http://en.wikipedia.org/wiki/Copy-on-write, COW) technique + and thus it's $(RED not) safe to cast this type to $(D_KEYWORD shared). + ) + + Note: + $(P It's not recommended to rely on the template parameters + or the exact type of a current $(CODEPOINT) set in $(D std.uni). + The type and parameters may change when the standard + allocators design is finalized. + Use $(LREF isCodepointSet) with templates or just stick with the default + alias $(LREF CodepointSet) throughout the whole code base. + ) +*/ +@trusted public struct InversionList(SP=GcPolicy) +{ +public: + /** + Construct from another code point set of any type. + */ + this(Set)(Set set) + if(isCodepointSet!Set) + { + uint[] arr; + foreach(v; set.byInterval) + { + arr ~= v.a; + arr ~= v.b; + } + data = Uint24Array!(SP)(arr); + } + + /** + Construct a set from a range of sorted code point intervals. + */ + this(Range)(Range intervals) + if(isForwardRange!Range && isIntegralPair!(ElementType!Range)) + { + auto flattened = roundRobin(intervals.save.map!"a[0]"(), + intervals.save.map!"a[1]"()); + data = Uint24Array!(SP)(flattened); + } + + /** + Construct a set from plain values of sorted code point intervals. + Example: + --- + auto set = CodepointSet('a', 'z'+1, 'а', 'я'+1); + foreach(v; 'a'..'z'+1) + assert(set[v]); + // Cyrillic lowercase interval + foreach(v; 'а'..'я'+1) + assert(set[v]); + --- + */ + this()(uint[] intervals...) + in + { + assert(intervals.length % 2 == 0, "Odd number of interval bounds [a, b)!"); + for(uint i=1; i a<=b)(data[]).lowerBound(val).length & 1; + return sharSwitchLowerBound!"a<=b"(data[], val) & 1; + } + + /// Number of $(CODEPOINTS) in this set + @property size_t length() + { + size_t sum = 0; + foreach(iv; byInterval) + { + sum += iv.b - iv.a; + } + return sum; + } + +// bootstrap full set operations from 4 primitives (suitable as a template mixin): +// addInterval, skipUpTo, dropUpTo & byInterval iteration +//============================================================================ +public: + /** + $(P Sets support natural syntax for set algebra, namely: ) + $(BOOKTABLE , + $(TR $(TH Operator) $(TH Math notation) $(TH Description) ) + $(TR $(TD &) $(TD a ∩ b) $(TD intersection) ) + $(TR $(TD |) $(TD a ∪ b) $(TD union) ) + $(TR $(TD -) $(TD a ∖ b) $(TD subtraction) ) + $(TR $(TD ~) $(TD a ~ b) $(TD symmetric set difference i.e. (a ∪ b) \ (a ∩ b)) ) + ) + + Example: + --- + auto lower = unicode.LowerCase; + auto upper = unicode.UpperCase; + auto ascii = unicode.ASCII; + + assert((lower & upper).empty); // no intersection + auto lowerASCII = lower & ascii; + assert(lowerASCII.byCodepoint.equal(iota('a', 'z'+1))); + // throw away all of the lowercase ASCII + assert((ascii - lower).length == 128 - 26); + + auto onlyOneOf = lower ~ ascii; + assert(!onlyOneOf['Δ']); // not ASCII and not lowercase + assert(onlyOneOf['$']); // ASCII and not lowercase + assert(!onlyOneOf['a']); // ASCII and lowercase + assert(onlyOneOf['я']); // not ASCII but lowercase + + // throw away all cased letters from ASCII + auto noLetters = ascii - (lower | upper); + assert(noLetters.length == 128 - 26*2); + --- + */ + This opBinary(string op, U)(U rhs) + if(isCodepointSet!U || is(U:dchar)) + { + static if(op == "&" || op == "|" || op == "~") + {// symmetric ops thus can swap arguments to reuse r-value + static if(is(U:dchar)) + { + auto tmp = this; + mixin("tmp "~op~"= rhs; "); + return tmp; + } + else + { + static if(is(Unqual!U == U)) + { + // try hard to reuse r-value + mixin("rhs "~op~"= this;"); + return rhs; + } + else + { + auto tmp = this; + mixin("tmp "~op~"= rhs;"); + return tmp; + } + } + } + else static if(op == "-") // anti-symmetric + { + auto tmp = this; + tmp -= rhs; + return tmp; + } + else + static assert(0, "no operator "~op~" defined for Set"); + } + + /// The 'op=' versions of the above overloaded operators. + ref This opOpAssign(string op, U)(U rhs) + if(isCodepointSet!U || is(U:dchar)) + { + static if(op == "|") // union + { + static if(is(U:dchar)) + { + this.addInterval(rhs, rhs+1); + return this; + } + else + return this.add(rhs); + } + else static if(op == "&") // intersection + return this.intersect(rhs);// overloaded + else static if(op == "-") // set difference + return this.sub(rhs);// overloaded + else static if(op == "~") // symmetric set difference + { + auto copy = this & rhs; + this |= rhs; + this -= copy; + return this; + } + else + static assert(0, "no operator "~op~" defined for Set"); + } + + /** + Tests the presence of codepoint $(D ch) in this set, + the same as $(LREF opIndex). + */ + bool opBinaryRight(string op: "in", U)(U ch) const + if(is(U : dchar)) + { + return this[ch]; + } + + /// + unittest + { + assert('я' in unicode.Cyrillic); + assert(!('z' in unicode.Cyrillic)); + } + + + + /// Obtains a set that is the inversion of this set. See also $(LREF inverted). + auto opUnary(string op: "!")() + { + return this.inverted; + } + + /** + A range that spans each $(CODEPOINT) in this set. + + Example: + --- + import std.algorithm; + auto set = unicode.ASCII; + set.byCodepoint.equal(iota(0, 0x80)); + --- + */ + @property auto byCodepoint() + { + @trusted static struct CodepointRange + { + this(This set) + { + r = set.byInterval; + if(!r.empty) + cur = r.front.a; + } + + @property dchar front() const + { + return cast(dchar)cur; + } + + @property bool empty() const + { + return r.empty; + } + + void popFront() + { + cur++; + while(cur >= r.front.b) + { + r.popFront(); + if(r.empty) + break; + cur = r.front.a; + } + } + private: + uint cur; + typeof(This.init.byInterval) r; + } + + return CodepointRange(this); + } + + /** + $(P Obtain textual representation of this set in from of + open-right intervals and feed it to $(D sink). + ) + $(P Used by various standard formatting facilities such as + $(XREF _format, formattedWrite), $(XREF _stdio, write), + $(XREF _stdio, writef), $(XREF _conv, to) and others. + ) + Example: + --- + import std.conv; + assert(unicode.ASCII.to!string == "[0..128$(RPAREN)"); + --- + */ + void toString(scope void delegate (const(char)[]) sink) + { + import std.format; + auto range = byInterval; + if(range.empty) + return; + auto val = range.front; + formattedWrite(sink, "[%d..%d)", val.a, val.b); + range.popFront(); + foreach(i; range) + formattedWrite(sink, " [%d..%d)", i.a, i.b); + } + /** + Add an interval [a, b$(RPAREN) to this set. + + Example: + --- + CodepointSet someSet; + someSet.add('0', '5').add('A','Z'+1); + someSet.add('5', '9'+1); + assert(someSet['0']); + assert(someSet['5']); + assert(someSet['9']); + assert(someSet['Z']); + --- + */ + ref add()(uint a, uint b) + { + addInterval(a, b); + return this; + } + +private: + + ref intersect(U)(U rhs) + if(isCodepointSet!U) + { + Marker mark; + foreach( i; rhs.byInterval) + { + mark = this.dropUpTo(i.a, mark); + mark = this.skipUpTo(i.b, mark); + } + this.dropUpTo(uint.max, mark); + return this; + } + + + + ref intersect()(dchar ch) + { + foreach(i; byInterval) + if(i.a <= ch && ch < i.b) + return this = This.init.add(ch, ch+1); + this = This.init; + return this; + } + + + /// + unittest + { + assert(unicode.Cyrillic.intersect('-').byInterval.empty); + } + + ref sub()(dchar ch) + { + return subChar(ch); + } + + // same as the above except that skip & drop parts are swapped + ref sub(U)(U rhs) + if(isCodepointSet!U) + { + uint top; + Marker mark; + foreach(i; rhs.byInterval) + { + mark = this.skipUpTo(i.a, mark); + mark = this.dropUpTo(i.b, mark); + } + return this; + } + + ref add(U)(U rhs) + if(isCodepointSet!U) + { + Marker start; + foreach(i; rhs.byInterval) + { + start = addInterval(i.a, i.b, start); + } + return this; + } +// end of mixin-able part +//============================================================================ +public: + /** + Obtains a set that is the inversion of this set. + + See the '!' $(LREF opUnary) for the same but using operators. + + Example: + --- + set = unicode.ASCII; + // union with the inverse gets all of the code points in the Unicode + assert((set | set.inverted).length == 0x110000); + // no intersection with the inverse + assert((set & set.inverted).empty); + --- + */ + @property auto inverted() + { + InversionList inversion = this; + if(inversion.data.length == 0) + { + inversion.addInterval(0, lastDchar+1); + return inversion; + } + if(inversion.data[0] != 0) + genericReplace(inversion.data, 0, 0, [0]); + else + genericReplace(inversion.data, 0, 1, cast(uint[])null); + if(data[data.length-1] != lastDchar+1) + genericReplace(inversion.data, + inversion.data.length, inversion.data.length, [lastDchar+1]); + else + genericReplace(inversion.data, + inversion.data.length-1, inversion.data.length, cast(uint[])null); + + return inversion; + } + + /** + Generates string with D source code of unary function with name of + $(D funcName) taking a single $(D dchar) argument. If $(D funcName) is empty + the code is adjusted to be a lambda function. + + The function generated tests if the $(CODEPOINT) passed + belongs to this set or not. The result is to be used with string mixin. + The intended usage area is aggressive optimization via meta programming + in parser generators and the like. + + Note: Use with care for relatively small or regular sets. It + could end up being slower then just using multi-staged tables. + + Example: + --- + import std.stdio; + + // construct set directly from [a, b) intervals + auto set = CodepointSet(10, 12, 45, 65, 100, 200); + writeln(set); + writeln(set.toSourceCode("func")); + --- + + The above outputs something along the lines of: + --- + bool func(dchar ch) + { + if(ch < 45) + { + if(ch == 10 || ch == 11) return true; + return false; + } + else if (ch < 65) return true; + else + { + if(ch < 100) return false; + if(ch < 200) return true; + return false; + } + } + --- + */ + string toSourceCode(string funcName="") + { + import std.string; + enum maxBinary = 3; + static string linearScope(R)(R ivals, string indent) + { + string result = indent~"{\n"; + string deeper = indent~" "; + foreach(ival; ivals) + { + auto span = ival[1] - ival[0]; + assert(span != 0); + if(span == 1) + { + result ~= format("%sif(ch == %s) return true;\n", deeper, ival[0]); + } + else if(span == 2) + { + result ~= format("%sif(ch == %s || ch == %s) return true;\n", + deeper, ival[0], ival[0]+1); + } + else + { + if(ival[0] != 0) // dchar is unsigned and < 0 is useless + result ~= format("%sif(ch < %s) return false;\n", deeper, ival[0]); + result ~= format("%sif(ch < %s) return true;\n", deeper, ival[1]); + } + } + result ~= format("%sreturn false;\n%s}\n", deeper, indent); // including empty range of intervals + return result; + } + + static string binaryScope(R)(R ivals, string indent) + { + // time to do unrolled comparisons? + if(ivals.length < maxBinary) + return linearScope(ivals, indent); + else + return bisect(ivals, ivals.length/2, indent); + } + + // not used yet if/elsebinary search is far better with DMD as of 2.061 + // and GDC is doing fine job either way + static string switchScope(R)(R ivals, string indent) + { + string result = indent~"switch(ch){\n"; + string deeper = indent~" "; + foreach(ival; ivals) + { + if(ival[0]+1 == ival[1]) + { + result ~= format("%scase %s: return true;\n", + deeper, ival[0]); + } + else + { + result ~= format("%scase %s: .. case %s: return true;\n", + deeper, ival[0], ival[1]-1); + } + } + result ~= deeper~"default: return false;\n"~indent~"}\n"; + return result; + } + + static string bisect(R)(R range, size_t idx, string indent) + { + string deeper = indent ~ " "; + // bisect on one [a, b) interval at idx + string result = indent~"{\n"; + // less branch, < a + result ~= format("%sif(ch < %s)\n%s", + deeper, range[idx][0], binaryScope(range[0..idx], deeper)); + // middle point, >= a && < b + result ~= format("%selse if (ch < %s) return true;\n", + deeper, range[idx][1]); + // greater or equal branch, >= b + result ~= format("%selse\n%s", + deeper, binaryScope(range[idx+1..$], deeper)); + return result~indent~"}\n"; + } + + string code = format("bool %s(dchar ch) @safe pure nothrow\n", + funcName.empty ? "function" : funcName); + auto range = byInterval.array(); + // special case first bisection to be on ASCII vs beyond + auto tillAscii = countUntil!"a[0] > 0x80"(range); + if(tillAscii <= 0) // everything is ASCII or nothing is ascii (-1 & 0) + code ~= binaryScope(range, ""); + else + code ~= bisect(range, tillAscii, ""); + return code; + } + + /** + True if this set doesn't contain any $(CODEPOINTS). + Example: + --- + CodepointSet emptySet; + assert(emptySet.length == 0); + assert(emptySet.empty); + --- + */ + @property bool empty() const + { + return data.length == 0; + } + +private: + alias typeof(this) This; + alias size_t Marker; + + // special case for normal InversionList + ref subChar(dchar ch) + { + auto mark = skipUpTo(ch); + if(mark != data.length + && data[mark] == ch && data[mark-1] == ch) + { + // it has split, meaning that ch happens to be in one of intervals + data[mark] = data[mark]+1; + } + return this; + } + + // + Marker addInterval(int a, int b, Marker hint=Marker.init) + in + { + assert(a <= b, text(a, " > ", b)); + } + body + { + auto range = assumeSorted(data[]); + size_t pos; + size_t a_idx = range.lowerBound(a).length; + if(a_idx == range.length) + { + // [---+++----++++----++++++] + // [ a b] + data.append([a, b]); + return data.length-1; + } + size_t b_idx = range[a_idx..range.length].lowerBound(b).length+a_idx; + uint[] to_insert; + debug(std_uni) + { + writefln("a_idx=%d; b_idx=%d;", a_idx, b_idx); + } + if(b_idx == range.length) + { + // [-------++++++++----++++++-] + // [ s a b] + if(a_idx & 1)// a in positive + { + to_insert = [ b ]; + } + else// a in negative + { + to_insert = [a, b]; + } + genericReplace(data, a_idx, b_idx, to_insert); + return a_idx+to_insert.length-1; + } + + uint top = data[b_idx]; + + debug(std_uni) + { + writefln("a_idx=%d; b_idx=%d;", a_idx, b_idx); + writefln("a=%s; b=%s; top=%s;", a, b, top); + } + if(a_idx & 1) + {// a in positive + if(b_idx & 1)// b in positive + { + // [-------++++++++----++++++-] + // [ s a b ] + to_insert = [top]; + } + else // b in negative + { + // [-------++++++++----++++++-] + // [ s a b ] + if(top == b) + { + assert(b_idx+1 < data.length); + pos = genericReplace(data, a_idx, b_idx+2, [data[b_idx+1]]); + return pos; + } + to_insert = [b, top ]; + } + } + else + { // a in negative + if(b_idx & 1) // b in positive + { + // [----------+++++----++++++-] + // [ a b ] + to_insert = [a, top]; + } + else// b in negative + { + // [----------+++++----++++++-] + // [ a s b ] + if(top == b) + { + assert(b_idx+1 < data.length); + pos = genericReplace(data, a_idx, b_idx+2, [a, data[b_idx+1] ]); + return pos; + } + to_insert = [a, b, top]; + } + } + pos = genericReplace(data, a_idx, b_idx+1, to_insert); + debug(std_uni) + { + writefln("marker idx: %d; length=%d", pos, data[pos], data.length); + writeln("inserting ", to_insert); + } + return pos; + } + + // + Marker dropUpTo(uint a, Marker pos=Marker.init) + in + { + assert(pos % 2 == 0); // at start of interval + } + body + { + auto range = assumeSorted!"a<=b"(data[pos..data.length]); + if(range.empty) + return pos; + size_t idx = pos; + idx += range.lowerBound(a).length; + + debug(std_uni) + { + writeln("dropUpTo full length=", data.length); + writeln(pos,"~~~", idx); + } + if(idx == data.length) + return genericReplace(data, pos, idx, cast(uint[])[]); + if(idx & 1) + { // a in positive + //[--+++----++++++----+++++++------...] + // |<---si s a t + genericReplace(data, pos, idx, [a]); + } + else + { // a in negative + //[--+++----++++++----+++++++-------+++...] + // |<---si s a t + genericReplace(data, pos, idx, cast(uint[])[]); + } + return pos; + } + + // + Marker skipUpTo(uint a, Marker pos=Marker.init) + out(result) + { + assert(result % 2 == 0);// always start of interval + //(may be 0-width after-split) + } + body + { + assert(data.length % 2 == 0); + auto range = assumeSorted!"a<=b"(data[pos..data.length]); + size_t idx = pos+range.lowerBound(a).length; + + if(idx >= data.length) // could have Marker point to recently removed stuff + return data.length; + + if(idx & 1)// inside of interval, check for split + { + + uint top = data[idx]; + if(top == a)// no need to split, it's end + return idx+1; + uint start = data[idx-1]; + if(a == start) + return idx-1; + // split it up + genericReplace(data, idx, idx+1, [a, a, top]); + return idx+1; // avoid odd index + } + return idx; + } + + Uint24Array!SP data; +}; + +@system unittest +{ + // test examples + import std.algorithm, std.typecons; + auto set = CodepointSet('A', 'D'+1, 'a', 'd'+1); + set.byInterval.equalS([tuple('A', 'E'), tuple('a', 'e')]); + set = unicode.ASCII; + assert(set.byCodepoint.equalS(iota(0, 0x80))); + set = CodepointSet('a', 'z'+1, 'а', 'я'+1); + foreach(v; 'a'..'z'+1) + assert(set[v]); + // Cyrillic lowercase interval + foreach(v; 'а'..'я'+1) + assert(set[v]); + + auto gothic = unicode.Gothic; + // Gothic letter ahsa + assert(gothic['\U00010330']); + // no ascii in Gothic obviously + assert(!gothic['$']); + + CodepointSet emptySet; + assert(emptySet.length == 0); + assert(emptySet.empty); + + set = unicode.ASCII; + // union with the inverse gets all of code points in the Unicode + assert((set | set.inverted).length == 0x110000); + // no intersection with inverse + assert((set & set.inverted).empty); + + CodepointSet someSet; + someSet.add('0', '5').add('A','Z'+1); + someSet.add('5', '9'+1); + assert(someSet['0']); + assert(someSet['5']); + assert(someSet['9']); + assert(someSet['Z']); + + auto lower = unicode.LowerCase; + auto upper = unicode.UpperCase; + auto ascii = unicode.ASCII; + assert((lower & upper).empty); // no intersection + auto lowerASCII = lower & ascii; + assert(lowerASCII.byCodepoint.equalS(iota('a', 'z'+1))); + // throw away all of the lowercase ASCII + assert((ascii - lower).length == 128 - 26); + auto onlyOneOf = lower ~ ascii; + assert(!onlyOneOf['Δ']); // not ASCII and not lowercase + assert(onlyOneOf['$']); // ASCII and not lowercase + assert(!onlyOneOf['a']); // ASCII and lowercase + assert(onlyOneOf['я']); // not ASCII but lowercase + + auto noLetters = ascii - (lower | upper); + assert(noLetters.length == 128 - 26*2); + import std.conv; + assert(unicode.ASCII.to!string() == "[0..128)"); +} + +// pedantic version for ctfe, and aligned-access only architectures +@trusted uint safeRead24(const ubyte* ptr, size_t idx) pure nothrow +{ + idx *= 3; + version(LittleEndian) + return ptr[idx] + (cast(uint)ptr[idx+1]<<8) + + (cast(uint)ptr[idx+2]<<16); + else + return (cast(uint)ptr[idx]<<16) + (cast(uint)ptr[idx+1]<<8) + + ptr[idx+2]; +} + +// ditto +@trusted void safeWrite24(ubyte* ptr, uint val, size_t idx) pure nothrow +{ + idx *= 3; + version(LittleEndian) + { + ptr[idx] = val & 0xFF; + ptr[idx+1] = (val>>8) & 0xFF; + ptr[idx+2] = (val>>16) & 0xFF; + } + else + { + ptr[idx] = (val>>16) & 0xFF; + ptr[idx+1] = (val>>8) & 0xFF; + ptr[idx+2] = val & 0xFF; + } +} + +// unaligned x86-like read/write functions +@trusted uint unalignedRead24(const ubyte* ptr, size_t idx) pure nothrow +{ + uint* src = cast(uint*)(ptr+3*idx); + version(LittleEndian) + return *src & 0xFF_FFFF; + else + return *src >> 8; +} + +// ditto +@trusted void unalignedWrite24(ubyte* ptr, uint val, size_t idx) pure nothrow +{ + uint* dest = cast(uint*)(cast(ubyte*)ptr + 3*idx); + version(LittleEndian) + *dest = val | (*dest & 0xFF00_0000); + else + *dest = (val<<8) | (*dest & 0xFF); +} + +uint read24(const ubyte* ptr, size_t idx) pure nothrow +{ + static if(hasUnalignedReads) + return __ctfe ? safeRead24(ptr, idx) : unalignedRead24(ptr, idx); + else + return safeRead24(ptr, idx); +} + +void write24(ubyte* ptr, uint val, size_t idx) pure nothrow +{ + static if(hasUnalignedReads) + return __ctfe ? safeWrite24(ptr, val, idx) : unalignedWrite24(ptr, val, idx); + else + return safeWrite24(ptr, val, idx); +} + +// Packed array of 24-bit integers, COW semantics. +@trusted struct Uint24Array(SP=GcPolicy) +{ + this(Range)(Range range) + if(isInputRange!Range && hasLength!Range) + { + length = range.length; + copy(range, this[]); + } + + this(Range)(Range range) + if(isForwardRange!Range && !hasLength!Range) + { + auto len = walkLength(range.save); + length = len; + copy(range, this[]); + } + + this(this) + { + if(!empty) + { + refCount = refCount + 1; + } + } + + ~this() + { + if(!empty) + { + auto cnt = refCount; + if(cnt == 1) + SP.destroy(data); + else + refCount = cnt - 1; + } + } + + // no ref-count for empty U24 array + @property bool empty() const { return data.length == 0; } + + // report one less then actual size + @property size_t length() const + { + return data.length ? (data.length-4)/3 : 0; + } + + //+ an extra slot for ref-count + @property void length(size_t len) + { + if(len == 0) + { + if(!empty) + freeThisReference(); + return; + } + immutable bytes = len*3+4; // including ref-count + if(empty) + { + data = SP.alloc!ubyte(bytes); + refCount = 1; + return; + } + auto cur_cnt = refCount; + if(cur_cnt != 1) // have more references to this memory + { + refCount = cur_cnt - 1; + auto new_data = SP.alloc!ubyte(bytes); + // take shrinking into account + auto to_copy = min(bytes, data.length)-4; + copy(data[0..to_copy], new_data[0..to_copy]); + data = new_data; // before setting refCount! + refCount = 1; + } + else // 'this' is the only reference + { + // use the realloc (hopefully in-place operation) + data = SP.realloc(data, bytes); + refCount = 1; // setup a ref-count in the new end of the array + } + } + + alias opDollar = length; + + // Read 24-bit packed integer + uint opIndex(size_t idx)const + { + return read24(data.ptr, idx); + } + + // Write 24-bit packed integer + void opIndexAssign(uint val, size_t idx) + in + { + assert(!empty && val <= 0xFF_FFFF); + } + body + { + auto cnt = refCount; + if(cnt != 1) + dupThisReference(cnt); + write24(data.ptr, val, idx); + } + + // + auto opSlice(size_t from, size_t to) + { + return sliceOverIndexed(from, to, &this); + } + + /// + auto opSlice(size_t from, size_t to) const + { + return sliceOverIndexed(from, to, &this); + } + + // length slices before the ref count + auto opSlice() + { + return opSlice(0, length); + } + + // length slices before the ref count + auto opSlice() const + { + return opSlice(0, length); + } + + void append(Range)(Range range) + if(isInputRange!Range && hasLength!Range && is(ElementType!Range : uint)) + { + size_t nl = length + range.length; + length = nl; + copy(range, this[nl-range.length..nl]); + } + + void append()(uint val) + { + length = length + 1; + this[$-1] = val; + } + + bool opEquals()(auto const ref Uint24Array rhs)const + { + if(empty ^ rhs.empty) + return false; // one is empty and the other isn't + return empty || data[0..$-4] == rhs.data[0..$-4]; + } + +private: + // ref-count is right after the data + @property uint refCount() const + { + return read24(data.ptr, length); + } + + @property void refCount(uint cnt) + in + { + assert(cnt <= 0xFF_FFFF); + } + body + { + write24(data.ptr, cnt, length); + } + + void freeThisReference() + { + auto count = refCount; + if(count != 1) // have more references to this memory + { + // dec shared ref-count + refCount = count - 1; + data = []; + } + else + SP.destroy(data); + version(bug10929) + assert(!data.ptr); + else + data = null; + } + + void dupThisReference(uint count) + in + { + assert(!empty && count != 1 && count == refCount); + } + body + { + // dec shared ref-count + refCount = count - 1; + // copy to the new chunk of RAM + auto new_data = SP.alloc!ubyte(data.length); + // bit-blit old stuff except the counter + copy(data[0..$-4], new_data[0..$-4]); + data = new_data; // before setting refCount! + refCount = 1; // so that this updates the right one + } + + ubyte[] data; +} + +@trusted unittest// Uint24 tests //@@@BUG@@ iota is system ?! +{ + void funcRef(T)(ref T u24) + { + u24.length = 2; + u24[1] = 1024; + T u24_c = u24; + assert(u24[1] == 1024); + u24.length = 0; + assert(u24.empty); + u24.append([1, 2]); + assert(equalS(u24[], [1, 2])); + u24.append(111); + assert(equalS(u24[], [1, 2, 111])); + assert(!u24_c.empty && u24_c[1] == 1024); + u24.length = 3; + copy(iota(0, 3), u24[]); + assert(equalS(u24[], iota(0, 3))); + assert(u24_c[1] == 1024); + } + + void func2(T)(T u24) + { + T u24_2 = u24; + T u24_3; + u24_3 = u24_2; + assert(u24_2 == u24_3); + assert(equalS(u24[], u24_2[])); + assert(equalS(u24_2[], u24_3[])); + funcRef(u24_3); + + assert(equalS(u24_3[], iota(0, 3))); + assert(!equalS(u24_2[], u24_3[])); + assert(equalS(u24_2[], u24[])); + u24_2 = u24_3; + assert(equalS(u24_2[], iota(0, 3))); + // to test that passed arg is intact outside + // plus try out opEquals + u24 = u24_3; + u24 = T.init; + u24_3 = T.init; + assert(u24.empty); + assert(u24 == u24_3); + assert(u24 != u24_2); + } + + foreach(Policy; TypeTuple!(GcPolicy, ReallocPolicy)) + { + alias typeof(Uint24Array!Policy.init[]) Range; + alias Uint24Array!Policy U24A; + static assert(isForwardRange!Range); + static assert(isBidirectionalRange!Range); + static assert(isOutputRange!(Range, uint)); + static assert(isRandomAccessRange!(Range)); + + auto arr = U24A([42u, 36, 100]); + assert(arr[0] == 42); + assert(arr[1] == 36); + arr[0] = 72; + arr[1] = 0xFE_FEFE; + assert(arr[0] == 72); + assert(arr[1] == 0xFE_FEFE); + assert(arr[2] == 100); + U24A arr2 = arr; + assert(arr2[0] == 72); + arr2[0] = 11; + // test COW-ness + assert(arr[0] == 72); + assert(arr2[0] == 11); + // set this to about 100M to stress-test COW memory management + foreach(v; 0..10_000) + func2(arr); + assert(equalS(arr[], [72, 0xFE_FEFE, 100])); + + auto r2 = U24A(iota(0, 100)); + assert(equalS(r2[], iota(0, 100)), text(r2[])); + copy(iota(10, 170, 2), r2[10..90]); + assert(equalS(r2[], chain(iota(0, 10), iota(10, 170, 2), iota(90, 100))) + , text(r2[])); + } +} + +version(unittest) +{ + private alias TypeTuple!(InversionList!GcPolicy, InversionList!ReallocPolicy) AllSets; +} + +@trusted unittest// core set primitives test +{ + foreach(CodeList; AllSets) + { + CodeList a; + //"plug a hole" test + a.add(10, 20).add(25, 30).add(15, 27); + assert(a == CodeList(10, 30), text(a)); + + auto x = CodeList.init; + x.add(10, 20).add(30, 40).add(50, 60); + + a = x; + a.add(20, 49);//[10, 49) [50, 60) + assert(a == CodeList(10, 49, 50 ,60)); + + a = x; + a.add(20, 50); + assert(a == CodeList(10, 60), text(a)); + + // simple unions, mostly edge effects + x = CodeList.init; + x.add(10, 20).add(40, 60); + + a = x; + a.add(10, 25); //[10, 25) [40, 60) + assert(a == CodeList(10, 25, 40, 60)); + + a = x; + a.add(5, 15); //[5, 20) [40, 60) + assert(a == CodeList(5, 20, 40, 60)); + + a = x; + a.add(0, 10); // [0, 20) [40, 60) + assert(a == CodeList(0, 20, 40, 60)); + + a = x; + a.add(0, 5); // prepand + assert(a == CodeList(0, 5, 10, 20, 40, 60), text(a)); + + a = x; + a.add(5, 20); + assert(a == CodeList(5, 20, 40, 60)); + + a = x; + a.add(3, 37); + assert(a == CodeList(3, 37, 40, 60)); + + a = x; + a.add(37, 65); + assert(a == CodeList(10, 20, 37, 65)); + + // some tests on helpers for set intersection + x = CodeList.init.add(10, 20).add(40, 60).add(100, 120); + a = x; + + auto m = a.skipUpTo(60); + a.dropUpTo(110, m); + assert(a == CodeList(10, 20, 40, 60, 110, 120), text(a.data[])); + + a = x; + a.dropUpTo(100); + assert(a == CodeList(100, 120), text(a.data[])); + + a = x; + m = a.skipUpTo(50); + a.dropUpTo(140, m); + assert(a == CodeList(10, 20, 40, 50), text(a.data[])); + a = x; + a.dropUpTo(60); + assert(a == CodeList(100, 120), text(a.data[])); + } +} + +@trusted unittest +{ // full set operations + foreach(CodeList; AllSets) + { + CodeList a, b, c, d; + + //"plug a hole" + a.add(20, 40).add(60, 80).add(100, 140).add(150, 200); + b.add(40, 60).add(80, 100).add(140, 150); + c = a | b; + d = b | a; + assert(c == CodeList(20, 200), text(CodeList.stringof," ", c)); + assert(c == d, text(c," vs ", d)); + + b = CodeList.init.add(25, 45).add(65, 85).add(95,110).add(150, 210); + c = a | b; //[20,45) [60, 85) [95, 140) [150, 210) + d = b | a; + assert(c == CodeList(20, 45, 60, 85, 95, 140, 150, 210), text(c)); + assert(c == d, text(c," vs ", d)); + + b = CodeList.init.add(10, 20).add(30,100).add(145,200); + c = a | b;//[10, 140) [145, 200) + d = b | a; + assert(c == CodeList(10, 140, 145, 200)); + assert(c == d, text(c," vs ", d)); + + b = CodeList.init.add(0, 10).add(15, 100).add(10, 20).add(200, 220); + c = a | b;//[0, 140) [150, 220) + d = b | a; + assert(c == CodeList(0, 140, 150, 220)); + assert(c == d, text(c," vs ", d)); + + + a = CodeList.init.add(20, 40).add(60, 80); + b = CodeList.init.add(25, 35).add(65, 75); + c = a & b; + d = b & a; + assert(c == CodeList(25, 35, 65, 75), text(c)); + assert(c == d, text(c," vs ", d)); + + a = CodeList.init.add(20, 40).add(60, 80).add(100, 140).add(150, 200); + b = CodeList.init.add(25, 35).add(65, 75).add(110, 130).add(160, 180); + c = a & b; + d = b & a; + assert(c == CodeList(25, 35, 65, 75, 110, 130, 160, 180), text(c)); + assert(c == d, text(c," vs ", d)); + + a = CodeList.init.add(20, 40).add(60, 80).add(100, 140).add(150, 200); + b = CodeList.init.add(10, 30).add(60, 120).add(135, 160); + c = a & b;//[20, 30)[60, 80) [100, 120) [135, 140) [150, 160) + d = b & a; + + assert(c == CodeList(20, 30, 60, 80, 100, 120, 135, 140, 150, 160),text(c)); + assert(c == d, text(c, " vs ",d)); + assert((c & a) == c); + assert((d & b) == d); + assert((c & d) == d); + + b = CodeList.init.add(40, 60).add(80, 100).add(140, 200); + c = a & b; + d = b & a; + assert(c == CodeList(150, 200), text(c)); + assert(c == d, text(c, " vs ",d)); + assert((c & a) == c); + assert((d & b) == d); + assert((c & d) == d); + + assert((a & a) == a); + assert((b & b) == b); + + a = CodeList.init.add(20, 40).add(60, 80).add(100, 140).add(150, 200); + b = CodeList.init.add(30, 60).add(75, 120).add(190, 300); + c = a - b;// [30, 40) [60, 75) [120, 140) [150, 190) + d = b - a;// [40, 60) [80, 100) [200, 300) + assert(c == CodeList(20, 30, 60, 75, 120, 140, 150, 190), text(c)); + assert(d == CodeList(40, 60, 80, 100, 200, 300), text(d)); + assert(c - d == c, text(c-d, " vs ", c)); + assert(d - c == d, text(d-c, " vs ", d)); + assert(c - c == CodeList.init); + assert(d - d == CodeList.init); + + a = CodeList.init.add(20, 40).add( 60, 80).add(100, 140).add(150, 200); + b = CodeList.init.add(10, 50).add(60, 160).add(190, 300); + c = a - b;// [160, 190) + d = b - a;// [10, 20) [40, 50) [80, 100) [140, 150) [200, 300) + assert(c == CodeList(160, 190), text(c)); + assert(d == CodeList(10, 20, 40, 50, 80, 100, 140, 150, 200, 300), text(d)); + assert(c - d == c, text(c-d, " vs ", c)); + assert(d - c == d, text(d-c, " vs ", d)); + assert(c - c == CodeList.init); + assert(d - d == CodeList.init); + + a = CodeList.init.add(20, 40).add(60, 80).add(100, 140).add(150, 200); + b = CodeList.init.add(10, 30).add(45, 100).add(130, 190); + c = a ~ b; // [10, 20) [30, 40) [45, 60) [80, 130) [140, 150) [190, 200) + d = b ~ a; + assert(c == CodeList(10, 20, 30, 40, 45, 60, 80, 130, 140, 150, 190, 200), + text(c)); + assert(c == d, text(c, " vs ", d)); + } +} + + +@system: +unittest// vs single dchar +{ + CodepointSet a = CodepointSet(10, 100, 120, 200); + assert(a - 'A' == CodepointSet(10, 65, 66, 100, 120, 200), text(a - 'A')); + assert((a & 'B') == CodepointSet(66, 67)); +} + +unittest// iteration & opIndex +{ + import std.typecons; + foreach(CodeList; TypeTuple!(InversionList!(ReallocPolicy))) + { + auto arr = "ABCDEFGHIJKLMabcdefghijklm"d; + auto a = CodeList('A','N','a', 'n'); + assert(equalS(a.byInterval, + [tuple(cast(uint)'A', cast(uint)'N'), tuple(cast(uint)'a', cast(uint)'n')] + ), text(a.byInterval)); + + // same @@@BUG as in issue 8949 ? + version(bug8949) + { + assert(equalS(retro(a.byInterval), + [tuple(cast(uint)'a', cast(uint)'n'), tuple(cast(uint)'A', cast(uint)'N')] + ), text(retro(a.byInterval))); + } + auto achr = a.byCodepoint; + assert(equalS(achr, arr), text(a.byCodepoint)); + foreach(ch; a.byCodepoint) + assert(a[ch]); + auto x = CodeList(100, 500, 600, 900, 1200, 1500); + assert(equalS(x.byInterval, [ tuple(100, 500), tuple(600, 900), tuple(1200, 1500)]), text(x.byInterval)); + foreach(ch; x.byCodepoint) + assert(x[ch]); + static if(is(CodeList == CodepointSet)) + { + auto y = CodeList(x.byInterval); + assert(equalS(x.byInterval, y.byInterval)); + } + assert(equalS(CodepointSet.init.byInterval, cast(Tuple!(uint, uint)[])[])); + assert(equalS(CodepointSet.init.byCodepoint, cast(dchar[])[])); + } +} + +//============================================================================ +// Generic Trie template and various ways to build it +//============================================================================ + +// debug helper to get a shortened array dump +auto arrayRepr(T)(T x) +{ + if(x.length > 32) + { + return text(x[0..16],"~...~", x[x.length-16..x.length]); + } + else + return text(x); +} + +/** + Maps $(D Key) to a suitable integer index within the range of $(D size_t). + The mapping is constructed by applying predicates from $(D Prefix) left to right + and concatenating the resulting bits. + + The first (leftmost) predicate defines the most significant bits of + the resulting index. + */ +template mapTrieIndex(Prefix...) +{ + size_t mapTrieIndex(Key)(Key key) + if(isValidPrefixForTrie!(Key, Prefix)) + { + alias Prefix p; + size_t idx; + foreach(i, v; p[0..$-1]) + { + idx |= p[i](key); + idx <<= p[i+1].bitSize; + } + idx |= p[$-1](key); + return idx; + } +} + +/* + $(D TrieBuilder) is a type used for incremental construction + of $(LREF Trie)s. + + See $(LREF buildTrie) for generic helpers built on top of it. +*/ +@trusted struct TrieBuilder(Value, Key, Args...) + if(isBitPackableType!Value && isValidArgsForTrie!(Key, Args)) +{ +private: + // last index is not stored in table, it is used as an offset to values in a block. + static if(is(Value == bool))// always pack bool + alias V = BitPacked!(Value, 1); + else + alias V = Value; + static auto deduceMaxIndex(Preds...)() + { + size_t idx = 1; + foreach(v; Preds) + idx *= 2^^v.bitSize; + return idx; + } + + static if(is(typeof(Args[0]) : Key)) // Args start with upper bound on Key + { + alias Prefix = Args[1..$]; + enum lastPageSize = 2^^Prefix[$-1].bitSize; + enum translatedMaxIndex = mapTrieIndex!(Prefix)(Args[0]); + enum roughedMaxIndex = + (translatedMaxIndex + lastPageSize-1)/lastPageSize*lastPageSize; + // check warp around - if wrapped, use the default deduction rule + enum maxIndex = roughedMaxIndex < translatedMaxIndex ? + deduceMaxIndex!(Prefix)() : roughedMaxIndex; + } + else + { + alias Prefix = Args; + enum maxIndex = deduceMaxIndex!(Prefix)(); + } + + alias getIndex = mapTrieIndex!(Prefix); + + enum lastLevel = Prefix.length-1; + struct ConstructState + { + size_t idx_zeros, idx_ones; + } + // iteration over levels of Trie, each indexes its own level and thus a shortened domain + size_t[Prefix.length] indices; + // default filler value to use + Value defValue; + // this is a full-width index of next item + size_t curIndex; + // all-zeros page index, all-ones page index (+ indicator if there is such a page) + ConstructState[Prefix.length] state; + // the table being constructed + MultiArray!(idxTypes!(Key, fullBitSize!(Prefix), Prefix[0..$]), V) table; + + @disable this(); + + //shortcut for index variable at level 'level' + @property ref idx(size_t level)(){ return indices[level]; } + + // this function assumes no holes in the input so + // indices are going one by one + void addValue(size_t level, T)(T val, size_t numVals) + { + alias j = idx!level; + enum pageSize = 1<= pageSize) + { + numVals -= pageSize; + ptr[j..j+pageSize] = val; + j += pageSize; + spillToNextPage!level(ptr); + } + } + if(numVals) + { + // the leftovers, an incomplete page + ptr[j..j+numVals] = val; + j += numVals; + } + } + } + + void spillToNextPage(size_t level, Slice)(ref Slice ptr) + { + // last level (i.e. topmost) has 1 "page" + // thus it need not to add a new page on upper level + static if(level != 0) + spillToNextPageImpl!(level)(ptr); + } + + // this can re-use the current page if duplicate or allocate a new one + // it also makes sure that previous levels point to the correct page in this level + void spillToNextPageImpl(size_t level, Slice)(ref Slice ptr) + { + alias typeof(table.slice!(level-1)[0]) NextIdx; + NextIdx next_lvl_index; + enum pageSize = 1< [%s..%s]" + ,level + ,indices[level-1], pageSize, j, j+pageSize); + writeln("LEVEL(", level + , ") mapped page is: ", slice, ": ", arrayRepr(ptr[j..j+pageSize])); + writeln("LEVEL(", level + , ") src page is :", ptr, ": ", arrayRepr(slice[0..pageSize])); + } + idx!level -= pageSize; // reuse this page, it is duplicate + break; + } + } + if(j == last) + { + L_allocate_page: + next_lvl_index = force!NextIdx(idx!level/pageSize - 1); + if(state[level].idx_zeros == size_t.max && ptr.zeros(j, j+pageSize)) + { + state[level].idx_zeros = next_lvl_index; + } + // allocate next page + version(none) + { + writefln("LEVEL(%s) page allocated: %s" + , level, arrayRepr(slice[0..pageSize])); + writefln("LEVEL(%s) index: %s ; page at this index %s" + , level + , next_lvl_index + , arrayRepr( + table.slice!(level) + [pageSize*next_lvl_index..(next_lvl_index+1)*pageSize] + )); + } + table.length!level = table.length!level + pageSize; + } + L_know_index: + // for the previous level, values are indices to the pages in the current level + addValue!(level-1)(next_lvl_index, 1); + ptr = table.slice!level; //re-load the slice after moves + } + + // idx - full-width index to fill with v (full-width index != key) + // fills everything in the range of [curIndex, idx) with filler + void putAt(size_t idx, Value v) + { + assert(idx >= curIndex); + size_t numFillers = idx - curIndex; + addValue!lastLevel(defValue, numFillers); + addValue!lastLevel(v, 1); + curIndex = idx + 1; + } + + // ditto, but sets the range of [idxA, idxB) to v + void putRangeAt(size_t idxA, size_t idxB, Value v) + { + assert(idxA >= curIndex); + assert(idxB >= idxA); + size_t numFillers = idxA - curIndex; + addValue!lastLevel(defValue, numFillers); + addValue!lastLevel(v, idxB - idxA); + curIndex = idxB; // open-right + } + + enum errMsg = "non-monotonic prefix function(s), an unsorted range or " + "duplicate key->value mapping"; + +public: + /** + Construct a builder, where $(D filler) is a value + to indicate empty slots (or "not found" condition). + */ + this(Value filler) + { + curIndex = 0; + defValue = filler; + // zeros-page index, ones-page index + foreach(ref v; state) + v = ConstructState(size_t.max, size_t.max); + table = typeof(table)(indices); + // one page per level is a bootstrap minimum + foreach(i; Sequence!(0, Prefix.length)) + table.length!i = (1<= idxA && idxA >= curIndex, errMsg); + putRangeAt(idxA, idxB, v); + } + + /** + Put a value $(D v) into slot mapped by $(D key). + All slots prior to $(D key) are filled with the + default filler. + */ + void putValue(Key key, Value v) + { + auto idx = getIndex(key); + enforce(idx >= curIndex, text(errMsg, " ", idx)); + putAt(idx, v); + } + + /// Finishes construction of Trie, yielding an immutable Trie instance. + auto build() + { + static if(maxIndex != 0) // doesn't cover full range of size_t + { + assert(curIndex <= maxIndex); + addValue!lastLevel(defValue, maxIndex - curIndex); + } + else + { + if(curIndex != 0 // couldn't wrap around + || (Prefix.length != 1 && indices[lastLevel] == 0)) // can be just empty + { + addValue!lastLevel(defValue, size_t.max - curIndex); + addValue!lastLevel(defValue, 1); + } + // else curIndex already completed the full range of size_t by wrapping around + } + return Trie!(V, Key, maxIndex, Prefix)(table); + } +} + +/* + $(P A generic Trie data-structure for a fixed number of stages. + The design goal is optimal speed with smallest footprint size. + ) + $(P It's intentionally read-only and doesn't provide constructors. + To construct one use a special builder, + see $(LREF TrieBuilder) and $(LREF buildTrie). + ) + +*/ +@trusted public struct Trie(Value, Key, Args...) + if(isValidPrefixForTrie!(Key, Args) + || (isValidPrefixForTrie!(Key, Args[1..$]) + && is(typeof(Args[0]) : size_t))) +{ + static if(is(typeof(Args[0]) : size_t)) + { + enum maxIndex = Args[0]; + enum hasBoundsCheck = true; + alias Prefix = Args[1..$]; + } + else + { + enum hasBoundsCheck = false; + alias Prefix = Args; + } + + private this()(typeof(_table) table) + { + _table = table; + } + + // only for constant Tries constructed from precompiled tables + private this()(const(size_t)[] offsets, const(size_t)[] sizes, + const(size_t)[] data) const + { + _table = typeof(_table)(offsets, sizes, data); + } + + /* + $(P Lookup the $(D key) in this $(D Trie). ) + + $(P The lookup always succeeds if key fits the domain + provided during construction. The whole domain defined + is covered so instead of not found condition + the sentinel (filler) value could be used. ) + + $(P See $(LREF buildTrie), $(LREF TrieBuilder) for how to + define a domain of $(D Trie) keys and the sentinel value. ) + + Note: + Domain range-checking is only enabled in debug builds + and results in assertion failure. + */ + // templated to auto-detect pure, @safe and nothrow + TypeOfBitPacked!Value opIndex()(Key key) const + { + static if(hasBoundsCheck) + assert(mapTrieIndex!Prefix(key) < maxIndex); + size_t idx; + alias p = Prefix; + idx = cast(size_t)p[0](key); + foreach(i, v; p[0..$-1]) + idx = cast(size_t)((_table.ptr!i[idx]< 0) + alias TypeTuple!(sliceBits!(top - sizes[0], top) + , GetBitSlicing!(top - sizes[0], sizes[1..$])) GetBitSlicing; + else + alias TypeTuple!() GetBitSlicing; +} + +template callableWith(T) +{ + template callableWith(alias Pred) + { + static if(!is(typeof(Pred(T.init)))) + enum callableWith = false; + else + { + alias Result = typeof(Pred(T.init)); + enum callableWith = isBitPackableType!(TypeOfBitPacked!(Result)); + } + } +} + +/* + Check if $(D Prefix) is a valid set of predicates + for $(D Trie) template having $(D Key) as the type of keys. + This requires all predicates to be callable, take + single argument of type $(D Key) and return unsigned value. +*/ +template isValidPrefixForTrie(Key, Prefix...) +{ + enum isValidPrefixForTrie = allSatisfy!(callableWith!Key, Prefix); // TODO: tighten the screws +} + +/* + Check if $(D Args) is a set of maximum key value followed by valid predicates + for $(D Trie) template having $(D Key) as the type of keys. +*/ +template isValidArgsForTrie(Key, Args...) +{ + static if(Args.length > 1) + { + enum isValidArgsForTrie = isValidPrefixForTrie!(Key, Args) + || (isValidPrefixForTrie!(Key, Args[1..$]) && is(typeof(Args[0]) : Key)); + } + else + enum isValidArgsForTrie = isValidPrefixForTrie!Args; +} + +@property size_t sumOfIntegerTuple(ints...)() +{ + size_t count=0; + foreach(v; ints) + count += v; + return count; +} + +/** + A shorthand for creating a custom multi-level fixed Trie + from a $(D CodepointSet). $(D sizes) are numbers of bits per level, + with the most significant bits used first. + + Note: The sum of $(D sizes) must be equal 21. + + See_Also: $(LREF toTrie), which is even simpler. + + Example: + --- + { + import std.stdio; + auto set = unicode("Number"); + auto trie = codepointSetTrie!(8, 5, 8)(set); + writeln("Input code points to test:"); + foreach(line; stdin.byLine) + { + int count=0; + foreach(dchar ch; line) + if(trie[ch])// is number + count++; + writefln("Contains %d number code points.", count); + } + } + --- +*/ +public template codepointSetTrie(sizes...) + if(sumOfIntegerTuple!sizes == 21) +{ + auto codepointSetTrie(Set)(Set set) + if(isCodepointSet!Set) + { + auto builder = TrieBuilder!(bool, dchar, lastDchar+1, GetBitSlicing!(21, sizes))(false); + foreach(ival; set.byInterval) + builder.putRange(ival[0], ival[1], true); + return builder.build(); + } +} + +/// Type of Trie generated by codepointSetTrie function. +public template CodepointSetTrie(sizes...) + if(sumOfIntegerTuple!sizes == 21) +{ + alias Prefix = GetBitSlicing!(21, sizes); + alias CodepointSetTrie = typeof(TrieBuilder!(bool, dchar, lastDchar+1, Prefix)(false).build()); +} + +/** + A slightly more general tool for building fixed $(D Trie) + for the Unicode data. + + Specifically unlike $(D codepointSetTrie) it's allows creating mappings + of $(D dchar) to an arbitrary type $(D T). + + Note: Overload taking $(D CodepointSet)s will naturally convert + only to bool mapping $(D Trie)s. + + Example: + --- + // pick characters from the Greek script + auto set = unicode.Greek; + + // a user-defined property (or an expensive function) + // that we want to look up + static uint luckFactor(dchar ch) + { + // here we consider a character lucky + // if its code point has a lot of identical hex-digits + // e.g. arabic letter DDAL (\u0688) has a "luck factor" of 2 + ubyte[6] nibbles; // 6 4-bit chunks of code point + uint value = ch; + foreach(i; 0..6) + { + nibbles[i] = value & 0xF; + value >>= 4; + } + uint luck; + foreach(n; nibbles) + luck = cast(uint)max(luck, count(nibbles[], n)); + return luck; + } + + // only unsigned built-ins are supported at the moment + alias LuckFactor = BitPacked!(uint, 3); + + // create a temporary associative array (AA) + LuckFactor[dchar] map; + foreach(ch; set.byCodepoint) + map[ch] = luckFactor(ch); + + // bits per stage are chosen randomly, fell free to optimize + auto trie = codepointTrie!(LuckFactor, 8, 5, 8)(map); + + // from now on the AA is not needed + foreach(ch; set.byCodepoint) + assert(trie[ch] == luckFactor(ch)); // verify + // CJK is not Greek, thus it has the default value + assert(trie['\u4444'] == 0); + // and here is a couple of quite lucky Greek characters: + // Greek small letter epsilon with dasia + assert(trie['\u1F11'] == 3); + // Ancient Greek metretes sign + assert(trie['\U00010181'] == 3); + --- +*/ +public template codepointTrie(T, sizes...) + if(sumOfIntegerTuple!sizes == 21) +{ + alias Prefix = GetBitSlicing!(21, sizes); + + static if(is(TypeOfBitPacked!T == bool)) + { + auto codepointTrie(Set)(in Set set) + if(isCodepointSet!Set) + { + return codepointSetTrie(set); + } + } + + auto codepointTrie()(T[dchar] map, T defValue=T.init) + { + return buildTrie!(T, dchar, Prefix)(map, defValue); + } + + // unsorted range of pairs + auto codepointTrie(R)(R range, T defValue=T.init) + if(isInputRange!R + && is(typeof(ElementType!R.init[0]) : T) + && is(typeof(ElementType!R.init[1]) : dchar)) + { + // build from unsorted array of pairs + // TODO: expose index sorting functions for Trie + return buildTrie!(T, dchar, Prefix)(range, defValue, true); + } +} + +unittest // codepointTrie example +{ + // pick characters from the Greek script + auto set = unicode.Greek; + + // a user-defined property (or an expensive function) + // that we want to look up + static uint luckFactor(dchar ch) + { + // here we consider a character lucky + // if its code point has a lot of identical hex-digits + // e.g. arabic letter DDAL (\u0688) has a "luck factor" of 2 + ubyte[6] nibbles; // 6 4-bit chunks of code point + uint value = ch; + foreach(i; 0..6) + { + nibbles[i] = value & 0xF; + value >>= 4; + } + uint luck; + foreach(n; nibbles) + luck = cast(uint)max(luck, count(nibbles[], n)); + return luck; + } + + // only unsigned built-ins are supported at the moment + alias LuckFactor = BitPacked!(uint, 3); + + // create a temporary associative array (AA) + LuckFactor[dchar] map; + foreach(ch; set.byCodepoint) + map[ch] = LuckFactor(luckFactor(ch)); + + // bits per stage are chosen randomly, fell free to optimize + auto trie = codepointTrie!(LuckFactor, 8, 5, 8)(map); + + // from now on the AA is not needed + foreach(ch; set.byCodepoint) + assert(trie[ch] == luckFactor(ch)); // verify + // CJK is not Greek, thus it has the default value + assert(trie['\u4444'] == 0); + // and here is a couple of quite lucky Greek characters: + // Greek small letter epsilon with dasia + assert(trie['\u1F11'] == 3); + // Ancient Greek metretes sign + assert(trie['\U00010181'] == 3); + +} + +/// Type of Trie as generated by codepointTrie function. +public template CodepointTrie(T, sizes...) + if(sumOfIntegerTuple!sizes == 21) +{ + alias Prefix = GetBitSlicing!(21, sizes); + alias CodepointTrie = typeof(TrieBuilder!(T, dchar, lastDchar+1, Prefix)(T.init).build()); +} + +// @@@BUG multiSort can's access private symbols from uni +public template cmpK0(alias Pred) +{ + import std.typecons; + static bool cmpK0(Value, Key) + (Tuple!(Value, Key) a, Tuple!(Value, Key) b) + { + return Pred(a[1]) < Pred(b[1]); + } +} + +/* + The most general utility for construction of $(D Trie)s + short of using $(D TrieBuilder) directly. + + Provides a number of convenience overloads. + $(D Args) is tuple of maximum key value followed by + predicates to construct index from key. + + Alternatively if the first argument is not a value convertible to $(D Key) + then the whole tuple of $(D Args) is treated as predicates + and the maximum Key is deduced from predicates. +*/ +public template buildTrie(Value, Key, Args...) + if(isValidArgsForTrie!(Key, Args)) +{ + static if(is(typeof(Args[0]) : Key)) // prefix starts with upper bound on Key + { + alias Prefix = Args[1..$]; + } + else + alias Prefix = Args; + + alias getIndex = mapTrieIndex!(Prefix); + + // for multi-sort + template GetComparators(size_t n) + { + static if(n > 0) + alias GetComparators = + TypeTuple!(GetComparators!(n-1), cmpK0!(Prefix[n-1])); + else + alias GetComparators = TypeTuple!(); + } + + /* + Build $(D Trie) from a range of a Key-Value pairs, + assuming it is sorted by Key as defined by the following lambda: + ------ + (a, b) => mapTrieIndex!(Prefix)(a) < mapTrieIndex!(Prefix)(b) + ------ + Exception is thrown if it's detected that the above order doesn't hold. + + In other words $(LREF mapTrieIndex) should be a + monotonically increasing function that maps $(D Key) to an integer. + + See also: $(XREF _algorithm, sort), + $(XREF _range, SortedRange), + $(XREF _algorithm, setUnion). + */ + auto buildTrie(Range)(Range range, Value filler=Value.init) + if(isInputRange!Range && is(typeof(Range.init.front[0]) : Value) + && is(typeof(Range.init.front[1]) : Key)) + { + auto builder = TrieBuilder!(Value, Key, Prefix)(filler); + foreach(v; range) + builder.putValue(v[1], v[0]); + return builder.build(); + } + + /* + If $(D Value) is bool (or BitPacked!(bool, x)) then it's possible + to build $(D Trie) from a range of open-right intervals of $(D Key)s. + The requirement on the ordering of keys (and the behavior on the + violation of it) is the same as for Key-Value range overload. + + Intervals denote ranges of !$(D filler) i.e. the opposite of filler. + If no filler provided keys inside of the intervals map to true, + and $(D filler) is false. + */ + auto buildTrie(Range)(Range range, Value filler=Value.init) + if(is(TypeOfBitPacked!Value == bool) + && isInputRange!Range && is(typeof(Range.init.front[0]) : Key) + && is(typeof(Range.init.front[1]) : Key)) + { + auto builder = TrieBuilder!(Value, Key, Prefix)(filler); + foreach(ival; range) + builder.putRange(ival[0], ival[1], !filler); + return builder.build(); + } + + auto buildTrie(Range)(Range range, Value filler, bool unsorted) + if(isInputRange!Range + && is(typeof(Range.init.front[0]) : Value) + && is(typeof(Range.init.front[1]) : Key)) + { + alias Comps = GetComparators!(Prefix.length); + if(unsorted) + multiSort!(Comps)(range); + return buildTrie(range, filler); + } + + /* + If $(D Value) is bool (or BitPacked!(bool, x)) then it's possible + to build $(D Trie) simply from an input range of $(D Key)s. + The requirement on the ordering of keys (and the behavior on the + violation of it) is the same as for Key-Value range overload. + + Keys found in range denote !$(D filler) i.e. the opposite of filler. + If no filler provided keys map to true, and $(D filler) is false. + */ + auto buildTrie(Range)(Range range, Value filler=Value.init) + if(is(TypeOfBitPacked!Value == bool) + && isInputRange!Range && is(typeof(Range.init.front) : Key)) + { + auto builder = TrieBuilder!(Value, Key, Prefix)(filler); + foreach(v; range) + builder.putValue(v, !filler); + return builder.build(); + } + + /* + If $(D Key) is unsigned integer $(D Trie) could be constructed from array + of values where array index serves as key. + */ + auto buildTrie()(Value[] array, Value filler=Value.init) + if(isUnsigned!Key) + { + auto builder = TrieBuilder!(Value, Key, Prefix)(filler); + foreach(idx, v; array) + builder.putValue(idx, v); + return builder.build(); + } + + /* + Builds $(D Trie) from associative array. + */ + auto buildTrie(Key, Value)(Value[Key] map, Value filler=Value.init) + { + auto range = array(zip(map.values, map.keys)); + return buildTrie(range, filler, true); // sort it + } +} + +/++ + Convenience function to construct optimal configurations for + packed Trie from any $(D set) of $(CODEPOINTS). + + The parameter $(D level) indicates the number of trie levels to use, + allowed values are: 1, 2, 3 or 4. Levels represent different trade-offs + speed-size wise. + + $(P Level 1 is fastest and the most memory hungry (a bit array). ) + $(P Level 4 is the slowest and has the smallest footprint. ) + + See the $(S_LINK Synopsis, Synopsis) section for example. + + Note: + Level 4 stays very practical (being faster and more predictable) + compared to using direct lookup on the $(D set) itself. + + ++/ +public auto toTrie(size_t level, Set)(Set set) + if(isCodepointSet!Set) +{ + static if(level == 1) + return codepointSetTrie!(21)(set); + else static if(level == 2) + return codepointSetTrie!(10, 11)(set); + else static if(level == 3) + return codepointSetTrie!(8, 5, 8)(set); + else static if(level == 4) + return codepointSetTrie!(6, 4, 4, 7)(set); + else + static assert(false, + "Sorry, toTrie doesn't support levels > 4, use codepointSetTrie directly"); +} + +/** + $(P Builds a $(D Trie) with typically optimal speed-size trade-off + and wraps it into a delegate of the following type: + $(D bool delegate(dchar ch)). ) + + $(P Effectively this creates a 'tester' lambda suitable + for algorithms like std.algorithm.find that take unary predicates. ) + + See the $(S_LINK Synopsis, Synopsis) section for example. +*/ +public auto toDelegate(Set)(Set set) + if(isCodepointSet!Set) +{ + // 3 is very small and is almost as fast as 2-level (due to CPU caches?) + auto t = toTrie!3(set); + return (dchar ch) => t[ch]; +} + +/** + $(P Opaque wrapper around unsigned built-in integers and + code unit (char/wchar/dchar) types. + Parameter $(D sz) indicates that the value is confined + to the range of [0, 2^^sz$(RPAREN). With this knowledge it can be + packed more tightly when stored in certain + data-structures like trie. ) + + Note: + $(P The $(D BitPacked!(T, sz)) is implicitly convertible to $(D T) + but not vise-versa. Users have to ensure the value fits in + the range required and use the $(D cast) + operator to perform the conversion.) +*/ +struct BitPacked(T, size_t sz) + if(isIntegral!T || is(T:dchar)) +{ + enum bitSize = sz; + T _value; + alias _value this; +} + +/* + Depending on the form of the passed argument $(D bitSizeOf) returns + the amount of bits required to represent a given type + or a return type of a given functor. +*/ +template bitSizeOf(Args...) + if(Args.length == 1) +{ + alias T = Args[0]; + static if(__traits(compiles, { size_t val = T.bitSize; })) //(is(typeof(T.bitSize) : size_t)) + { + enum bitSizeOf = T.bitSize; + } + else static if(is(ReturnType!T dummy == BitPacked!(U, bits), U, size_t bits)) + { + enum bitSizeOf = bitSizeOf!(ReturnType!T); + } + else + { + enum bitSizeOf = T.sizeof*8; + } +} + +/** + Tests if $(D T) is some instantiation of $(LREF BitPacked)!(U, x) + and thus suitable for packing. +*/ +template isBitPacked(T) +{ + static if(is(T dummy == BitPacked!(U, bits), U, size_t bits)) + enum isBitPacked = true; + else + enum isBitPacked = false; +} + +/** + Gives the type $(D U) from $(LREF BitPacked)!(U, x) + or $(D T) itself for every other type. +*/ +template TypeOfBitPacked(T) +{ + static if(is(T dummy == BitPacked!(U, bits), U, size_t bits)) + alias TypeOfBitPacked = U; + else + alias TypeOfBitPacked = T; +} + +/* + Wrapper, used in definition of custom data structures from $(D Trie) template. + Applying it to a unary lambda function indicates that the returned value always + fits within $(D bits) of bits. +*/ +struct assumeSize(alias Fn, size_t bits) +{ + enum bitSize = bits; + static auto ref opCall(T)(auto ref T arg) + { + return Fn(arg); + } +} + +/* + A helper for defining lambda function that yields a slice + of certain bits from an unsigned integral value. + The resulting lambda is wrapped in assumeSize and can be used directly + with $(D Trie) template. +*/ +struct sliceBits(size_t from, size_t to) +{ + //for now bypass assumeSize, DMD has trouble inlining it + enum bitSize = to-from; + static auto opCall(T)(T x) + out(result) + { + assert(result < (1<> from) & ((1<<(to-from))-1); + } +} + +uint low_8(uint x) { return x&0xFF; } +@safe pure nothrow uint midlow_8(uint x){ return (x&0xFF00)>>8; } +alias assumeSize!(low_8, 8) lo8; +alias assumeSize!(midlow_8, 8) mlo8; + +static assert(bitSizeOf!lo8 == 8); +static assert(bitSizeOf!(sliceBits!(4, 7)) == 3); +static assert(bitSizeOf!(BitPacked!(uint, 2)) == 2); + +template Sequence(size_t start, size_t end) +{ + static if(start < end) + alias TypeTuple!(start, Sequence!(start+1, end)) Sequence; + else + alias TypeTuple!() Sequence; +} + +//---- TRIE TESTS ---- +unittest +{ + static trieStats(TRIE)(TRIE t) + { + version(std_uni_stats) + { + import std.stdio; + writeln("---TRIE FOOTPRINT STATS---"); + foreach(i; Sequence!(0, t.table.dim) ) + { + writefln("lvl%s = %s bytes; %s pages" + , i, t.bytes!i, t.pages!i); + } + writefln("TOTAL: %s bytes", t.bytes); + version(none) + { + writeln("INDEX (excluding value level):"); + foreach(i; Sequence!(0, t.table.dim-1) ) + writeln(t.table.slice!(i)[0..t.table.length!i]); + } + writeln("---------------------------"); + } + } + //@@@BUG link failure, lambdas not found by linker somehow (in case of trie2) + // alias assumeSize!(8, function (uint x) { return x&0xFF; }) lo8; + // alias assumeSize!(7, function (uint x) { return (x&0x7F00)>>8; }) next8; + alias CodepointSet Set; + auto set = Set('A','Z','a','z'); + auto trie = buildTrie!(bool, uint, 256, lo8)(set.byInterval);// simple bool array + for(int a='a'; a<'z';a++) + assert(trie[a]); + for(int a='A'; a<'Z';a++) + assert(trie[a]); + for(int a=0; a<'A'; a++) + assert(!trie[a]); + for(int a ='Z'; a<'a'; a++) + assert(!trie[a]); + trieStats(trie); + + auto redundant2 = Set( + 1, 18, 256+2, 256+111, 512+1, 512+18, 768+2, 768+111); + auto trie2 = buildTrie!(bool, uint, 1024, mlo8, lo8)(redundant2.byInterval); + trieStats(trie2); + foreach(e; redundant2.byCodepoint) + assert(trie2[e], text(cast(uint)e, " - ", trie2[e])); + foreach(i; 0..1024) + { + assert(trie2[i] == (i in redundant2)); + } + + + auto redundant3 = Set( + 2, 4, 6, 8, 16, + 2+16, 4+16, 16+6, 16+8, 16+16, + 2+32, 4+32, 32+6, 32+8, + ); + + enum max3 = 256; + // sliceBits + auto trie3 = buildTrie!(bool, uint, max3, + sliceBits!(6,8), sliceBits!(4,6), sliceBits!(0,4) + )(redundant3.byInterval); + trieStats(trie3); + foreach(i; 0..max3) + assert(trie3[i] == (i in redundant3), text(cast(uint)i)); + + auto redundant4 = Set( + 10, 64, 64+10, 128, 128+10, 256, 256+10, 512, + 1000, 2000, 3000, 4000, 5000, 6000 + ); + enum max4 = 2^^16; + auto trie4 = buildTrie!(bool, size_t, max4, + sliceBits!(13, 16), sliceBits!(9, 13), sliceBits!(6, 9) , sliceBits!(0, 6) + )(redundant4.byInterval); + foreach(i; 0..max4){ + if(i in redundant4) + assert(trie4[i], text(cast(uint)i)); + } + trieStats(trie4); + + alias mapToS = mapTrieIndex!(useItemAt!(0, char)); + string[] redundantS = ["tea", "start", "orange"]; + redundantS.sort!((a,b) => mapToS(a) < mapToS(b))(); + auto strie = buildTrie!(bool, string, useItemAt!(0, char))(redundantS); + // using first char only + assert(redundantS == ["orange", "start", "tea"]); + assert(strie["test"], text(strie["test"])); + assert(!strie["aea"]); + assert(strie["s"]); + + // a bit size test + auto a = array(map!(x => to!ubyte(x))(iota(0, 256))); + auto bt = buildTrie!(bool, ubyte, sliceBits!(7, 8), sliceBits!(5, 7), sliceBits!(0, 5))(a); + trieStats(bt); + foreach(i; 0..256) + assert(bt[cast(ubyte)i]); +} + +template useItemAt(size_t idx, T) + if(isIntegral!T || is(T: dchar)) +{ + size_t impl(in T[] arr){ return arr[idx]; } + alias useItemAt = assumeSize!(impl, 8*T.sizeof); +} + +template useLastItem(T) +{ + size_t impl(in T[] arr){ return arr[$-1]; } + alias useLastItem = assumeSize!(impl, 8*T.sizeof); +} + +template fullBitSize(Prefix...) +{ + static if(Prefix.length > 0) + enum fullBitSize = bitSizeOf!(Prefix[0])+fullBitSize!(Prefix[1..$]); + else + enum fullBitSize = 0; +} + +template idxTypes(Key, size_t fullBits, Prefix...) +{ + static if(Prefix.length == 1) + {// the last level is value level, so no index once reduced to 1-level + alias TypeTuple!() idxTypes; + } + else + { + // Important note on bit packing + // Each level has to hold enough of bits to address the next one + // The bottom level is known to hold full bit width + // thus it's size in pages is full_bit_width - size_of_last_prefix + // Recourse on this notion + alias TypeTuple!( + idxTypes!(Key, fullBits - bitSizeOf!(Prefix[$-1]), Prefix[0..$-1]), + BitPacked!(typeof(Prefix[$-2](Key.init)), fullBits - bitSizeOf!(Prefix[$-1])) + ) idxTypes; + } +} + +//============================================================================ + +@trusted int comparePropertyName(Char1, Char2)(const(Char1)[] a, const(Char2)[] b) +{ + alias low = std.ascii.toLower; + return cmp( + a.map!(x => low(x))() + .filter!(x => !isWhite(x) && x != '-' && x != '_')(), + b.map!(x => low(x))() + .filter!(x => !isWhite(x) && x != '-' && x != '_')() + ); +} + +bool propertyNameLess(Char1, Char2)(const(Char1)[] a, const(Char2)[] b) +{ + return comparePropertyName(a, b) < 0; +} + +//============================================================================ +// Utilities for compression of Unicode code point sets +//============================================================================ + +@safe void compressTo(uint val, ref ubyte[] arr) pure nothrow +{ + // not optimized as usually done 1 time (and not public interface) + if(val < 128) + arr ~= cast(ubyte)val; + else if(val < (1<<13)) + { + arr ~= (0b1_00<<5) | cast(ubyte)(val>>8); + arr ~= val & 0xFF; + } + else + { + assert(val < (1<<21)); + arr ~= (0b1_01<<5) | cast(ubyte)(val>>16); + arr ~= (val >> 8) & 0xFF; + arr ~= val & 0xFF; + } +} + +@safe uint decompressFrom(const(ubyte)[] arr, ref size_t idx) pure +{ + uint first = arr[idx++]; + if(!(first & 0x80)) // no top bit -> [0..127] + return first; + uint extra = ((first>>5) & 1) + 1; // [1, 2] + uint val = (first & 0x1F); + enforce(idx + extra <= arr.length, "bad code point interval encoding"); + foreach(j; 0..extra) + val = (val<<8) | arr[idx+j]; + idx += extra; + return val; +} + + +package ubyte[] compressIntervals(Range)(Range intervals) + if(isInputRange!Range && isIntegralPair!(ElementType!Range)) +{ + ubyte[] storage; + uint base = 0; + // RLE encode + foreach(val; intervals) + { + compressTo(val[0]-base, storage); + base = val[0]; + if(val[1] != lastDchar+1) // till the end of the domain so don't store it + { + compressTo(val[1]-base, storage); + base = val[1]; + } + } + return storage; +} + +unittest +{ + auto run = [tuple(80, 127), tuple(128, (1<<10)+128)]; + ubyte[] enc = [cast(ubyte)80, 47, 1, (0b1_00<<5) | (1<<2), 0]; + assert(compressIntervals(run) == enc); + auto run2 = [tuple(0, (1<<20)+512+1), tuple((1<<20)+512+4, lastDchar+1)]; + ubyte[] enc2 = [cast(ubyte)0, (0b1_01<<5) | (1<<4), 2, 1, 3]; // odd length-ed + assert(compressIntervals(run2) == enc2); + size_t idx = 0; + assert(decompressFrom(enc, idx) == 80); + assert(decompressFrom(enc, idx) == 47); + assert(decompressFrom(enc, idx) == 1); + assert(decompressFrom(enc, idx) == (1<<10)); + idx = 0; + assert(decompressFrom(enc2, idx) == 0); + assert(decompressFrom(enc2, idx) == (1<<20)+512+1); + assert(equalS(decompressIntervals(compressIntervals(run)), run)); + assert(equalS(decompressIntervals(compressIntervals(run2)), run2)); +} + +// Creates a range of $(D CodepointInterval) that lazily decodes compressed data. +@safe package auto decompressIntervals(const(ubyte)[] data) +{ + return DecompressedIntervals(data); +} + +@trusted struct DecompressedIntervals +{ + const(ubyte)[] _stream; + size_t _idx; + CodepointInterval _front; + + this(const(ubyte)[] stream) + { + _stream = stream; + popFront(); + } + + @property CodepointInterval front() + { + assert(!empty); + return _front; + } + + void popFront() + { + if(_idx == _stream.length) + { + _idx = size_t.max; + return; + } + uint base = _front[1]; + _front[0] = base + decompressFrom(_stream, _idx); + if(_idx == _stream.length)// odd length ---> till the end + _front[1] = lastDchar+1; + else + { + base = _front[0]; + _front[1] = base + decompressFrom(_stream, _idx); + } + } + + @property bool empty() const + { + return _idx == size_t.max; + } + + @property DecompressedIntervals save() { return this; } +} + +static assert(isInputRange!DecompressedIntervals); +static assert(isForwardRange!DecompressedIntervals); +//============================================================================ + +version(std_uni_bootstrap){} +else +{ + +// helper for looking up code point sets +@trusted ptrdiff_t findUnicodeSet(alias table, C)(in C[] name) +{ + auto range = assumeSorted!((a,b) => propertyNameLess(a,b)) + (table.map!"a.name"()); + size_t idx = range.lowerBound(name).length; + if(idx < range.length && comparePropertyName(range[idx], name) == 0) + return idx; + return -1; +} + +// another one that loads it +@trusted bool loadUnicodeSet(alias table, Set, C)(in C[] name, ref Set dest) +{ + auto idx = findUnicodeSet!table(name); + if(idx >= 0) + { + dest = Set(asSet(table[idx].compressed)); + return true; + } + return false; +} + +@trusted bool loadProperty(Set=CodepointSet, C) + (in C[] name, ref Set target) +{ + alias comparePropertyName ucmp; + // conjure cumulative properties by hand + if(ucmp(name, "L") == 0 || ucmp(name, "Letter") == 0) + { + target |= asSet(uniProps.Lu); + target |= asSet(uniProps.Ll); + target |= asSet(uniProps.Lt); + target |= asSet(uniProps.Lo); + target |= asSet(uniProps.Lm); + } + else if(ucmp(name,"LC") == 0 || ucmp(name,"Cased Letter")==0) + { + target |= asSet(uniProps.Ll); + target |= asSet(uniProps.Lu); + target |= asSet(uniProps.Lt);// Title case + } + else if(ucmp(name, "M") == 0 || ucmp(name, "Mark") == 0) + { + target |= asSet(uniProps.Mn); + target |= asSet(uniProps.Mc); + target |= asSet(uniProps.Me); + } + else if(ucmp(name, "N") == 0 || ucmp(name, "Number") == 0) + { + target |= asSet(uniProps.Nd); + target |= asSet(uniProps.Nl); + target |= asSet(uniProps.No); + } + else if(ucmp(name, "P") == 0 || ucmp(name, "Punctuation") == 0) + { + target |= asSet(uniProps.Pc); + target |= asSet(uniProps.Pd); + target |= asSet(uniProps.Ps); + target |= asSet(uniProps.Pe); + target |= asSet(uniProps.Pi); + target |= asSet(uniProps.Pf); + target |= asSet(uniProps.Po); + } + else if(ucmp(name, "S") == 0 || ucmp(name, "Symbol") == 0) + { + target |= asSet(uniProps.Sm); + target |= asSet(uniProps.Sc); + target |= asSet(uniProps.Sk); + target |= asSet(uniProps.So); + } + else if(ucmp(name, "Z") == 0 || ucmp(name, "Separator") == 0) + { + target |= asSet(uniProps.Zs); + target |= asSet(uniProps.Zl); + target |= asSet(uniProps.Zp); + } + else if(ucmp(name, "C") == 0 || ucmp(name, "Other") == 0) + { + target |= asSet(uniProps.Co); + target |= asSet(uniProps.Lo); + target |= asSet(uniProps.No); + target |= asSet(uniProps.So); + target |= asSet(uniProps.Po); + } + else if(ucmp(name, "graphical") == 0){ + target |= asSet(uniProps.Alphabetic); + + target |= asSet(uniProps.Mn); + target |= asSet(uniProps.Mc); + target |= asSet(uniProps.Me); + + target |= asSet(uniProps.Nd); + target |= asSet(uniProps.Nl); + target |= asSet(uniProps.No); + + target |= asSet(uniProps.Pc); + target |= asSet(uniProps.Pd); + target |= asSet(uniProps.Ps); + target |= asSet(uniProps.Pe); + target |= asSet(uniProps.Pi); + target |= asSet(uniProps.Pf); + target |= asSet(uniProps.Po); + + target |= asSet(uniProps.Zs); + + target |= asSet(uniProps.Sm); + target |= asSet(uniProps.Sc); + target |= asSet(uniProps.Sk); + target |= asSet(uniProps.So); + } + else if(ucmp(name, "any") == 0) + target = Set(0,0x110000); + else if(ucmp(name, "ascii") == 0) + target = Set(0,0x80); + else + return loadUnicodeSet!(uniProps.tab)(name, target); + return true; +} + +// CTFE-only helper for checking property names at compile-time +@safe bool isPrettyPropertyName(C)(in C[] name) +{ + auto names = [ + "L", "Letters", + "LC", "Cased Letter", + "M", "Mark", + "N", "Number", + "P", "Punctuation", + "S", "Symbol", + "Z", "Separator" + "Graphical", + "any", + "ascii" + ]; + auto x = find!(x => comparePropertyName(x, name) == 0)(names); + return !x.empty; +} + +// ditto, CTFE-only, not optimized +@safe private static bool findSetName(alias table, C)(in C[] name) +{ + return findUnicodeSet!table(name) >= 0; +} + +template SetSearcher(alias table, string kind) +{ + /// Run-time checked search. + static auto opCall(C)(in C[] name) + if(is(C : dchar)) + { + CodepointSet set; + if(loadUnicodeSet!table(name, set)) + return set; + throw new Exception("No unicode set for "~kind~" by name " + ~name.to!string()~" was found."); + } + /// Compile-time checked search. + static @property auto opDispatch(string name)() + { + static if(findSetName!table(name)) + { + CodepointSet set; + loadUnicodeSet!table(name, set); + return set; + } + else + static assert(false, "No unicode set for "~kind~" by name " + ~name~" was found."); + } +} + +/** + A single entry point to lookup Unicode $(CODEPOINT) sets by name or alias of + a block, script or general category. + + It uses well defined standard rules of property name lookup. + This includes fuzzy matching of names, so that + 'White_Space', 'white-SpAce' and 'whitespace' are all considered equal + and yield the same set of white space $(CHARACTERS). +*/ +@safe public struct unicode +{ + /** + Performs the lookup of set of $(CODEPOINTS) + with compile-time correctness checking. + This short-cut version combines 3 searches: + across blocks, scripts, and common binary properties. + + Note that since scripts and blocks overlap the + usual trick to disambiguate is used - to get a block use + $(D unicode.InBlockName), to search a script + use $(D unicode.ScriptName). + + See also $(LREF block), $(LREF script) + and (not included in this search) $(LREF hangulSyllableType). + + Example: + --- + auto ascii = unicode.ASCII; + assert(ascii['A']); + assert(ascii['~']); + assert(!ascii['\u00e0']); + // matching is case-insensitive + assert(ascii == unicode.ascII); + assert(!ascii['à']); + // underscores, '-' and whitespace in names are ignored too + auto latin = unicode.in_latin1_Supplement; + assert(latin['à']); + assert(!latin['$']); + // BTW Latin 1 Supplement is a block, hence "In" prefix + assert(latin == unicode("In Latin 1 Supplement")); + import std.exception; + // run-time look up throws if no such set is found + assert(collectException(unicode("InCyrilliac"))); + --- + */ + + static @property auto opDispatch(string name)() + { + static if(findAny(name)) + return loadAny(name); + else + static assert(false, "No unicode set by name "~name~" was found."); + } + + /** + The same lookup across blocks, scripts, or binary properties, + but performed at run-time. + This version is provided for cases where $(D name) + is not known beforehand; otherwise compile-time + checked $(LREF opDispatch) is typically a better choice. + + See the $(S_LINK Unicode properties, table of properties) for available + sets. + */ + static auto opCall(C)(in C[] name) + if(is(C : dchar)) + { + return loadAny(name); + } + + /** + Narrows down the search for sets of $(CODEPOINTS) to all Unicode blocks. + + See also $(S_LINK Unicode properties, table of properties). + + Note: + Here block names are unambiguous as no scripts are searched + and thus to search use simply $(D unicode.block.BlockName) notation. + + See $(S_LINK Unicode properties, table of properties) for available sets. + + Example: + --- + // use .block for explicitness + assert(unicode.block.Greek_and_Coptic == unicode.InGreek_and_Coptic); + --- + */ + struct block + { + mixin SetSearcher!(blocks.tab, "block"); + } + + /** + Narrows down the search for sets of $(CODEPOINTS) to all Unicode scripts. + + See the $(S_LINK Unicode properties, table of properties) for available + sets. + + Example: + --- + auto arabicScript = unicode.script.arabic; + auto arabicBlock = unicode.block.arabic; + // there is an intersection between script and block + assert(arabicBlock['؁']); + assert(arabicScript['؁']); + // but they are different + assert(arabicBlock != arabicScript); + assert(arabicBlock == unicode.inArabic); + assert(arabicScript == unicode.arabic); + --- + */ + struct script + { + mixin SetSearcher!(scripts.tab, "script"); + } + + /** + Fetch a set of $(CODEPOINTS) that have the given hangul syllable type. + + Other non-binary properties (once supported) follow the same + notation - $(D unicode.propertyName.propertyValue) for compile-time + checked access and $(D unicode.propertyName(propertyValue)) + for run-time checked one. + + See the $(S_LINK Unicode properties, table of properties) for available + sets. + + Example: + --- + // L here is syllable type not Letter as in unicode.L short-cut + auto leadingVowel = unicode.hangulSyllableType("L"); + // check that some leading vowels are present + foreach(vowel; '\u1110'..'\u115F') + assert(leadingVowel[vowel]); + assert(leadingVowel == unicode.hangulSyllableType.L); + --- + */ + struct hangulSyllableType + { + mixin SetSearcher!(hangul.tab, "hangul syllable type"); + } + +private: + alias ucmp = comparePropertyName; + + static bool findAny(string name) + { + return isPrettyPropertyName(name) + || findSetName!(uniProps.tab)(name) || findSetName!(scripts.tab)(name) + || (ucmp(name[0..2],"In") == 0 && findSetName!(blocks.tab)(name[2..$])); + } + + static auto loadAny(Set=CodepointSet, C)(in C[] name) + { + Set set; + bool loaded = loadProperty(name, set) || loadUnicodeSet!(scripts.tab)(name, set) + || (ucmp(name[0..2],"In") == 0 + && loadUnicodeSet!(blocks.tab)(name[2..$], set)); + if(loaded) + return set; + throw new Exception("No unicode set by name "~name.to!string()~" was found."); + } + + // FIXME: re-disable once the compiler is fixed + // Disabled to prevent the mistake of creating instances of this pseudo-struct. + //@disable ~this(); +} + +unittest +{ + auto ascii = unicode.ASCII; + assert(ascii['A']); + assert(ascii['~']); + assert(!ascii['\u00e0']); + // matching is case-insensitive + assert(ascii == unicode.ascII); + assert(!ascii['à']); + // underscores, '-' and whitespace in names are ignored too + auto latin = unicode.Inlatin1_Supplement; + assert(latin['à']); + assert(!latin['$']); + // BTW Latin 1 Supplement is a block, hence "In" prefix + assert(latin == unicode("In Latin 1 Supplement")); + import std.exception; + // R-T look up throws if no such set is found + assert(collectException(unicode("InCyrilliac"))); + + assert(unicode.block.Greek_and_Coptic == unicode.InGreek_and_Coptic); + + // L here is explicitly syllable type not "Letter" as in unicode.L + auto leadingVowel = unicode.hangulSyllableType("L"); + // check that some leading vowels are present + foreach(vowel; '\u1110'..'\u115F'+1) + assert(leadingVowel[vowel]); + assert(leadingVowel == unicode.hangulSyllableType.L); + + auto arabicScript = unicode.script.arabic; + auto arabicBlock = unicode.block.arabic; + // there is an intersection between script and block + assert(arabicBlock['؁']); + assert(arabicScript['؁']); + // but they are different + assert(arabicBlock != arabicScript); + assert(arabicBlock == unicode.inArabic); + assert(arabicScript == unicode.arabic); +} + +unittest +{ + assert(unicode("InHebrew") == asSet(blocks.Hebrew)); + assert(unicode("separator") == (asSet(uniProps.Zs) | asSet(uniProps.Zl) | asSet(uniProps.Zp))); + assert(unicode("In-Kharoshthi") == asSet(blocks.Kharoshthi)); +} + +enum EMPTY_CASE_TRIE = ushort.max;// from what gen_uni uses internally + +// control - '\r' +enum controlSwitch = ` + case '\u0000':..case '\u0008':case '\u000E':..case '\u001F':case '\u007F':..case '\u0084':case '\u0086':..case '\u009F': case '\u0009':..case '\u000C': case '\u0085': +`; +// TODO: redo the most of hangul stuff algorithmically in case of Graphemes too +// kill unrolled switches + +private static bool isRegionalIndicator(dchar ch) +{ + return ch >= '\U0001F1E6' && ch <= '\U0001F1FF'; +} + +template genericDecodeGrapheme(bool getValue) +{ + alias graphemeExtend = graphemeExtendTrie; + alias spacingMark = mcTrie; + static if(getValue) + alias Grapheme Value; + else + alias void Value; + + Value genericDecodeGrapheme(Input)(ref Input range) + { + enum GraphemeState { + Start, + CR, + RI, + L, + V, + LVT + } + static if(getValue) + Grapheme grapheme; + auto state = GraphemeState.Start; + enum eat = q{ + static if(getValue) + grapheme ~= ch; + range.popFront(); + }; + + dchar ch; + assert(!range.empty, "Attempting to decode grapheme from an empty " ~ Input.stringof); + while(!range.empty) + { + ch = range.front; + final switch(state) with(GraphemeState) + { + case Start: + mixin(eat); + if(ch == '\r') + state = CR; + else if(isRegionalIndicator(ch)) + state = RI; + else if(isHangL(ch)) + state = L; + else if(hangLV[ch] || isHangV(ch)) + state = V; + else if(hangLVT[ch]) + state = LVT; + else if(isHangT(ch)) + state = LVT; + else + { + switch(ch) + { + mixin(controlSwitch); + goto L_End; + default: + goto L_End_Extend; + } + } + break; + case CR: + if(ch == '\n') + mixin(eat); + goto L_End_Extend; + case RI: + if(isRegionalIndicator(ch)) + mixin(eat); + else + goto L_End_Extend; + break; + case L: + if(isHangL(ch)) + mixin(eat); + else if(isHangV(ch) || hangLV[ch]) + { + state = V; + mixin(eat); + } + else if(hangLVT[ch]) + { + state = LVT; + mixin(eat); + } + else + goto L_End_Extend; + break; + case V: + if(isHangV(ch)) + mixin(eat); + else if(isHangT(ch)) + { + state = LVT; + mixin(eat); + } + else + goto L_End_Extend; + break; + case LVT: + if(isHangT(ch)) + { + mixin(eat); + } + else + goto L_End_Extend; + break; + } + } + L_End_Extend: + while(!range.empty) + { + ch = range.front; + // extend & spacing marks + if(!graphemeExtend[ch] && !spacingMark[ch]) + break; + mixin(eat); + } + L_End: + static if(getValue) + return grapheme; + } + +} + +@trusted: +public: // Public API continues + +/++ + Returns the length of grapheme cluster starting at $(D index). + Both the resulting length and the $(D index) are measured + in $(S_LINK Code unit, code units). + + Example: + --- + // ASCII as usual is 1 code unit, 1 code point etc. + assert(graphemeStride(" ", 1) == 1); + // A + combing ring above + string city = "A\u030Arhus"; + size_t first = graphemeStride(city, 0); + assert(first == 3); //\u030A has 2 UTF-8 code units + assert(city[0..first] == "A\u030A"); + assert(city[first..$] == "rhus"); + --- ++/ +size_t graphemeStride(C)(in C[] input, size_t index) + if(is(C : dchar)) +{ + auto src = input[index..$]; + auto n = src.length; + genericDecodeGrapheme!(false)(src); + return n - src.length; +} + +// for now tested separately see test_grapheme.d +unittest +{ + assert(graphemeStride(" ", 1) == 1); + // A + combing ring above + string city = "A\u030Arhus"; + size_t first = graphemeStride(city, 0); + assert(first == 3); //\u030A has 2 UTF-8 code units + assert(city[0..first] == "A\u030A"); + assert(city[first..$] == "rhus"); +} + +/++ + Reads one full grapheme cluster from an input range of dchar $(D inp). + + For examples see the $(LREF Grapheme) below. + + Note: + This function modifies $(D inp) and thus $(D inp) + must be an L-value. ++/ +Grapheme decodeGrapheme(Input)(ref Input inp) + if(isInputRange!Input && is(Unqual!(ElementType!Input) == dchar)) +{ + return genericDecodeGrapheme!true(inp); +} + +unittest +{ + Grapheme gr; + string s = " \u0020\u0308 "; + gr = decodeGrapheme(s); + assert(gr.length == 1 && gr[0] == ' '); + gr = decodeGrapheme(s); + assert(gr.length == 2 && equalS(gr[0..2], " \u0308")); + s = "\u0300\u0308\u1100"; + assert(equalS(decodeGrapheme(s)[], "\u0300\u0308")); + assert(equalS(decodeGrapheme(s)[], "\u1100")); + s = "\u11A8\u0308\uAC01"; + assert(equalS(decodeGrapheme(s)[], "\u11A8\u0308")); + assert(equalS(decodeGrapheme(s)[], "\uAC01")); +} + +/++ + $(P Iterate a string by grapheme.) + + $(P Useful for doing string manipulation that needs to be aware + of graphemes.) + + See_Also: + $(LREF byCodePoint) ++/ +// TODO: Bidirectional access +auto byGrapheme(Range)(Range range) + if(isInputRange!Range && is(Unqual!(ElementType!Range) == dchar)) +{ + static struct Result + { + private Range _range; + private Grapheme _front; + + bool empty() @property + { + return _front.length == 0; + } + + Grapheme front() @property + { + return _front; + } + + void popFront() + { + _front = _range.empty ? Grapheme.init : _range.decodeGrapheme(); + } + + static if(isForwardRange!Range) + { + Result save() @property + { + return Result(_range.save, _front); + } + } + } + + auto result = Result(range); + result.popFront(); + return result; +} + +/// +unittest +{ + auto text = "noe\u0308l"; // noël using e + combining diaeresis + assert(text.walkLength == 5); // 5 code points + + auto gText = text.byGrapheme; + assert(gText.walkLength == 4); // 4 graphemes + + assert(gText.take(3).equal("noe\u0308".byGrapheme)); + assert(gText.drop(3).equal("l".byGrapheme)); +} + +// For testing non-forward-range input ranges +version(unittest) +private static struct InputRangeString +{ + private string s; + + bool empty() @property { return s.empty; } + dchar front() @property { return s.front; } + void popFront() { s.popFront(); } +} + +unittest +{ + assert("".byGrapheme.walkLength == 0); + + auto reverse = "le\u0308on"; + assert(reverse.walkLength == 5); + + auto gReverse = reverse.byGrapheme; + assert(gReverse.walkLength == 4); + + foreach(text; TypeTuple!("noe\u0308l"c, "noe\u0308l"w, "noe\u0308l"d)) + { + assert(text.walkLength == 5); + static assert(isForwardRange!(typeof(text))); + + auto gText = text.byGrapheme; + static assert(isForwardRange!(typeof(gText))); + assert(gText.walkLength == 4); + assert(gText.array.retro.equal(gReverse)); + } + + auto nonForwardRange = InputRangeString("noe\u0308l").byGrapheme; + static assert(!isForwardRange!(typeof(nonForwardRange))); + assert(nonForwardRange.walkLength == 4); +} + +/++ + $(P Lazily transform a range of $(LREF Grapheme)s to a range of code points.) + + $(P Useful for converting the result to a string after doing operations + on graphemes.) + + $(P Acts as the identity function when given a range of code points.) ++/ +// TODO: Propagate bidirectional access +auto byCodePoint(Range)(Range range) + if(isInputRange!Range && is(Unqual!(ElementType!Range) == Grapheme)) +{ + static struct Result + { + private Range _range; + private size_t i = 0; + + bool empty() @property + { + return _range.empty; + } + + dchar front() @property + { + return _range.front[i]; + } + + void popFront() + { + ++i; + + if(i >= _range.front.length) + { + _range.popFront(); + i = 0; + } + } + + static if(isForwardRange!Range) + { + Result save() @property + { + return Result(_range.save, i); + } + } + } + + return Result(range); +} + +/// Ditto +Range byCodePoint(Range)(Range range) + if(isInputRange!Range && is(Unqual!(ElementType!Range) == dchar)) +{ + return range; +} + +/// +unittest +{ + import std.string : text; + + string s = "noe\u0308l"; // noël + + // reverse it and convert the result to a string + string reverse = s.byGrapheme + .array + .retro + .byCodePoint + .text; + + assert(reverse == "le\u0308on"); // lëon +} + +unittest +{ + assert("".byGrapheme.byCodePoint.equal("")); + + string text = "noe\u0308l"; + static assert(is(typeof(text.byCodePoint) == string)); + + auto gText = InputRangeString(text).byGrapheme; + static assert(!isForwardRange!(typeof(gText))); + + auto cpText = gText.byCodePoint; + static assert(!isForwardRange!(typeof(cpText))); + + assert(cpText.walkLength == text.walkLength); +} + +/++ + $(P A structure designed to effectively pack $(CHARACTERS) + of a $(CLUSTER). + ) + + $(P $(D Grapheme) has value semantics so 2 copies of a $(D Grapheme) + always refer to distinct objects. In most actual scenarios a $(D Grapheme) + fits on the stack and avoids memory allocation overhead for all but quite + long clusters. + ) + + Example: + --- + import std.algorithm; + string bold = "ku\u0308hn"; + + // note that decodeGrapheme takes parameter by ref + // slicing a grapheme yields a range of dchar + assert(decodeGrapheme(bold)[].equal("k")); + + // the next grapheme is 2 characters long + auto wideOne = decodeGrapheme(bold); + assert(wideOne.length == 2); + assert(wideOne[].equal("u\u0308")); + + // the usual range manipulation is possible + assert(wideOne[].filter!isMark.equal("\u0308")); + --- + $(P See also $(LREF decodeGrapheme), $(LREF graphemeStride). ) ++/ +@trusted struct Grapheme +{ +public: + this(C)(in C[] chars...) + if(is(C : dchar)) + { + this ~= chars; + } + + this(Input)(Input seq) + if(!isDynamicArray!Input + && isInputRange!Input && is(ElementType!Input : dchar)) + { + this ~= seq; + } + + /// Gets a $(CODEPOINT) at the given index in this cluster. + dchar opIndex(size_t index) const pure nothrow + { + assert(index < length); + return read24(isBig ? ptr_ : small_.ptr, index); + } + + /++ + Writes a $(CODEPOINT) $(D ch) at given index in this cluster. + + Warning: + Use of this facility may invalidate grapheme cluster, + see also $(LREF Grapheme.valid). + + Example: + --- + auto g = Grapheme("A\u0302"); + assert(g[0] == 'A'); + assert(g.valid); + g[1] = '~'; // ASCII tilda is not a combining mark + assert(g[1] == '~'); + assert(!g.valid); + --- + +/ + void opIndexAssign(dchar ch, size_t index) pure nothrow + { + assert(index < length); + write24(isBig ? ptr_ : small_.ptr, ch, index); + } + + /++ + Random-access range over Grapheme's $(CHARACTERS). + + Warning: Invalidates when this Grapheme leaves the scope, + attempts to use it then would lead to memory corruption. + +/ + @system auto opSlice(size_t a, size_t b) pure nothrow + { + return sliceOverIndexed(a, b, &this); + } + + /// ditto + @system auto opSlice() pure nothrow + { + return sliceOverIndexed(0, length, &this); + } + + /// Grapheme cluster length in $(CODEPOINTS). + @property size_t length() const pure nothrow + { + return isBig ? len_ : slen_ & 0x7F; + } + + /++ + Append $(CHARACTER) $(D ch) to this grapheme. + Warning: + Use of this facility may invalidate grapheme cluster, + see also $(D valid). + + Example: + --- + auto g = Grapheme("A"); + assert(g.valid); + g ~= '\u0301'; + assert(g[].equal("A\u0301")); + assert(g.valid); + g ~= "B"; + // not a valid grapheme cluster anymore + assert(!g.valid); + // still could be useful though + assert(g[].equal("A\u0301B")); + --- + See also $(LREF Grapheme.valid) below. + +/ + ref opOpAssign(string op)(dchar ch) + { + static if(op == "~") + { + if(!isBig) + { + if(slen_ + 1 > small_cap) + convertToBig();// & fallthrough to "big" branch + else + { + write24(small_.ptr, ch, smallLength); + slen_++; + return this; + } + } + + assert(isBig); + if(len_ + 1 > cap_) + { + cap_ += grow; + ptr_ = cast(ubyte*)enforce(realloc(ptr_, 3*(cap_+1))); + } + write24(ptr_, ch, len_++); + return this; + } + else + static assert(false, "No operation "~op~" defined for Grapheme"); + } + + /// Append all $(CHARACTERS) from the input range $(D inp) to this Grapheme. + ref opOpAssign(string op, Input)(Input inp) + if(isInputRange!Input && is(ElementType!Input : dchar)) + { + static if(op == "~") + { + foreach(dchar ch; inp) + this ~= ch; + return this; + } + else + static assert(false, "No operation "~op~" defined for Grapheme"); + } + + /++ + True if this object contains valid extended grapheme cluster. + Decoding primitives of this module always return a valid $(D Grapheme). + + Appending to and direct manipulation of grapheme's $(CHARACTERS) may + render it no longer valid. Certain applications may chose to use + Grapheme as a "small string" of any $(CODEPOINTS) and ignore this property + entirely. + +/ + @property bool valid()() /*const*/ + { + auto r = this[]; + genericDecodeGrapheme!false(r); + return r.length == 0; + } + + this(this) + { + if(isBig) + {// dup it + auto raw_cap = 3*(cap_+1); + auto p = cast(ubyte*)enforce(malloc(raw_cap)); + p[0..raw_cap] = ptr_[0..raw_cap]; + ptr_ = p; + } + } + + ~this() + { + if(isBig) + { + free(ptr_); + } + } + + +private: + enum small_bytes = ((ubyte*).sizeof+3*size_t.sizeof-1); + // "out of the blue" grow rate, needs testing + // (though graphemes are typically small < 9) + enum grow = 20; + enum small_cap = small_bytes/3; + enum small_flag = 0x80, small_mask = 0x7F; + // 16 bytes in 32bits, should be enough for the majority of cases + union + { + struct + { + ubyte* ptr_; + size_t cap_; + size_t len_; + size_t padding_; + } + struct + { + ubyte[small_bytes] small_; + ubyte slen_; + } + } + + void convertToBig() + { + size_t k = smallLength; + ubyte* p = cast(ubyte*)enforce(malloc(3*(grow+1))); + for(int i=0; i len_); + cap_ = grow; + setBig(); + } + + void setBig(){ slen_ |= small_flag; } + + @property size_t smallLength() pure nothrow + { + return slen_ & small_mask; + } + @property ubyte isBig() const pure nothrow + { + return slen_ & small_flag; + } +} + +static assert(Grapheme.sizeof == size_t.sizeof*4); + +// verify the example +unittest +{ + import std.algorithm; + string bold = "ku\u0308hn"; + + // note that decodeGrapheme takes parameter by ref + auto first = decodeGrapheme(bold); + + assert(first.length == 1); + assert(first[0] == 'k'); + + // the next grapheme is 2 characters long + auto wideOne = decodeGrapheme(bold); + // slicing a grapheme yields a random-access range of dchar + assert(wideOne[].equalS("u\u0308")); + assert(wideOne.length == 2); + static assert(isRandomAccessRange!(typeof(wideOne[]))); + + // all of the usual range manipulation is possible + assert(wideOne[].filter!isMark().equalS("\u0308")); + + auto g = Grapheme("A"); + assert(g.valid); + g ~= '\u0301'; + assert(g[].equalS("A\u0301")); + assert(g.valid); + g ~= "B"; + // not a valid grapheme cluster anymore + assert(!g.valid); + // still could be useful though + assert(g[].equalS("A\u0301B")); +} + +unittest +{ + auto g = Grapheme("A\u0302"); + assert(g[0] == 'A'); + assert(g.valid); + g[1] = '~'; // ASCII tilda is not a combining mark + assert(g[1] == '~'); + assert(!g.valid); +} + +unittest +{ + // not valid clusters (but it just a test) + auto g = Grapheme('a', 'b', 'c', 'd', 'e'); + assert(g[0] == 'a'); + assert(g[1] == 'b'); + assert(g[2] == 'c'); + assert(g[3] == 'd'); + assert(g[4] == 'e'); + g[3] = 'Й'; + assert(g[2] == 'c'); + assert(g[3] == 'Й', text(g[3], " vs ", 'Й')); + assert(g[4] == 'e'); + assert(!g.valid); + + g ~= 'ц'; + g ~= '~'; + assert(g[0] == 'a'); + assert(g[1] == 'b'); + assert(g[2] == 'c'); + assert(g[3] == 'Й'); + assert(g[4] == 'e'); + assert(g[5] == 'ц'); + assert(g[6] == '~'); + assert(!g.valid); + + Grapheme copy = g; + copy[0] = 'X'; + copy[1] = '-'; + assert(g[0] == 'a' && copy[0] == 'X'); + assert(g[1] == 'b' && copy[1] == '-'); + assert(equalS(g[2..g.length], copy[2..copy.length])); + copy = Grapheme("АБВГДЕЁЖЗИКЛМ"); + assert(equalS(copy[0..8], "АБВГДЕЁЖ"), text(copy[0..8])); + copy ~= "xyz"; + assert(equalS(copy[13..15], "xy"), text(copy[13..15])); + assert(!copy.valid); + + Grapheme h; + foreach(dchar v; iota(cast(int)'A', cast(int)'Z'+1).map!"cast(dchar)a"()) + h ~= v; + assert(equalS(h[], iota(cast(int)'A', cast(int)'Z'+1))); +} + +/++ + $(P Does basic case-insensitive comparison of strings $(D str1) and $(D str2). + This function uses simpler comparison rule thus achieving better performance + then $(LREF icmp). However keep in mind the warning below.) + + Warning: + This function only handles 1:1 $(CODEPOINT) mapping + and thus is not sufficient for certain alphabets + like German, Greek and few others. + + Example: + --- + assert(sicmp("Август", "авгусТ") == 0); + // Greek also works as long as there is no 1:M mapping in sight + assert(sicmp("ΌΎ", "όύ") == 0); + // things like the following won't get matched as equal + // Greek small letter iota with dialytika and tonos + assert(sicmp("ΐ", "\u03B9\u0308\u0301") != 0); + + // while icmp has no problem with that + assert(icmp("ΐ", "\u03B9\u0308\u0301") == 0); + assert(icmp("ΌΎ", "όύ") == 0); + --- ++/ +int sicmp(S1, S2)(S1 str1, S2 str2) + if(isForwardRange!S1 && is(Unqual!(ElementType!S1) == dchar) + && isForwardRange!S2 && is(Unqual!(ElementType!S2) == dchar)) +{ + alias sTable = simpleCaseTable; + size_t ridx=0; + foreach(dchar lhs; str1) + { + if(ridx == str2.length) + return 1; + dchar rhs = std.utf.decode(str2, ridx); + int diff = lhs - rhs; + if(!diff) + continue; + size_t idx = simpleCaseTrie[lhs]; + size_t idx2 = simpleCaseTrie[rhs]; + // simpleCaseTrie is packed index table + if(idx != EMPTY_CASE_TRIE) + { + if(idx2 != EMPTY_CASE_TRIE) + {// both cased chars + // adjust idx --> start of bucket + idx = idx - sTable[idx].n; + idx2 = idx2 - sTable[idx2].n; + if(idx == idx2)// one bucket, equivalent chars + continue; + else// not the same bucket + diff = sTable[idx].ch - sTable[idx2].ch; + } + else + diff = sTable[idx - sTable[idx].n].ch - rhs; + } + else if(idx2 != EMPTY_CASE_TRIE) + { + diff = lhs - sTable[idx2 - sTable[idx2].n].ch; + } + // one of chars is not cased at all + return diff; + } + return ridx == str2.length ? 0 : -1; +} +// overloads for the most common cases to reduce compile time +@safe pure /*TODO nothrow*/ +{ + int sicmp(const(char)[] str1, const(char)[] str2) + { return sicmp!(const(char)[], const(char)[])(str1, str2); } + int sicmp(const(wchar)[] str1, const(wchar)[] str2) + { return sicmp!(const(wchar)[], const(wchar)[])(str1, str2); } + int sicmp(const(dchar)[] str1, const(dchar)[] str2) + { return sicmp!(const(dchar)[], const(dchar)[])(str1, str2); } +} + +private int fullCasedCmp(Range)(dchar lhs, dchar rhs, ref Range rtail) + @trusted pure /*TODO nothrow*/ +{ + alias fTable = fullCaseTable; + size_t idx = fullCaseTrie[lhs]; + // fullCaseTrie is packed index table + if(idx == EMPTY_CASE_TRIE) + return lhs; + size_t start = idx - fTable[idx].n; + size_t end = fTable[idx].size + start; + assert(fTable[start].entry_len == 1); + for(idx=start; idx \u1F70\u03B9", "\u1F61\u03B9 -> ᾲ") == 0); + --- ++/ +int icmp(S1, S2)(S1 str1, S2 str2) + if(isForwardRange!S1 && is(Unqual!(ElementType!S1) == dchar) + && isForwardRange!S2 && is(Unqual!(ElementType!S2) == dchar)) +{ + for(;;) + { + if(str1.empty) + return str2.empty ? 0 : -1; + dchar lhs = str1.front; + if(str2.empty) + return 1; + dchar rhs = str2.front; + str1.popFront(); + str2.popFront(); + int diff = lhs - rhs; + if(!diff) + continue; + // first try to match lhs to sequence + int cmpLR = fullCasedCmp(lhs, rhs, str2); + if(!cmpLR) + continue; + // then rhs to sequence + int cmpRL = fullCasedCmp(rhs, lhs, str1); + if(!cmpRL) + continue; + // cmpXX contain remapped codepoints + // to obtain stable ordering of icmp + diff = cmpLR - cmpRL; + return diff; + } +} +// overloads for the most common cases to reduce compile time +@safe pure /*TODO nothrow*/ +{ + int icmp(const(char)[] str1, const(char)[] str2) + { return icmp!(const(char)[], const(char)[])(str1, str2); } + int icmp(const(wchar)[] str1, const(wchar)[] str2) + { return icmp!(const(wchar)[], const(wchar)[])(str1, str2); } + int icmp(const(dchar)[] str1, const(dchar)[] str2) + { return icmp!(const(dchar)[], const(dchar)[])(str1, str2); } +} + +unittest +{ + assertCTFEable!( + { + foreach(cfunc; TypeTuple!(icmp, sicmp)) + { + foreach(S1; TypeTuple!(string, wstring, dstring)) + foreach(S2; TypeTuple!(string, wstring, dstring)) + { + assert(cfunc("".to!S1(), "".to!S2()) == 0); + assert(cfunc("A".to!S1(), "".to!S2()) > 0); + assert(cfunc("".to!S1(), "0".to!S2()) < 0); + assert(cfunc("abc".to!S1(), "abc".to!S2()) == 0); + assert(cfunc("abcd".to!S1(), "abc".to!S2()) > 0); + assert(cfunc("abc".to!S1(), "abcd".to!S2()) < 0); + assert(cfunc("Abc".to!S1(), "aBc".to!S2()) == 0); + assert(cfunc("авГуст".to!S1(), "АВгУСТ".to!S2()) == 0); + // Check example: + assert(cfunc("Август".to!S1(), "авгусТ".to!S2()) == 0); + assert(cfunc("ΌΎ".to!S1(), "όύ".to!S2()) == 0); + } + // check that the order is properly agnostic to the case + auto strs = [ "Apple", "ORANGE", "orAcle", "amp", "banana"]; + sort!((a,b) => cfunc(a,b) < 0)(strs); + assert(strs == ["amp", "Apple", "banana", "orAcle", "ORANGE"]); + } + assert(icmp("ßb", "ssa") > 0); + // Check example: + assert(icmp("Russland", "Rußland") == 0); + assert(icmp("ᾩ -> \u1F70\u03B9", "\u1F61\u03B9 -> ᾲ") == 0); + assert(icmp("ΐ"w, "\u03B9\u0308\u0301") == 0); + assert(sicmp("ΐ", "\u03B9\u0308\u0301") != 0); + //bugzilla 11057 + assert( icmp("K", "L") < 0 ); + }); +} + +/++ + $(P Returns the $(S_LINK Combining class, combining class) of $(D ch).) + + Example: + --- + // shorten the code + alias CC = combiningClass; + + // combining tilda + assert(CC('\u0303') == 230); + // combining ring below + assert(CC('\u0325') == 220); + // the simple consequence is that "tilda" should be + // placed after a "ring below" in a sequence + --- ++/ +ubyte combiningClass(dchar ch) +{ + return combiningClassTrie[ch]; +} + +unittest +{ + foreach(ch; 0..0x80) + assert(combiningClass(ch) == 0); + assert(combiningClass('\u05BD') == 22); + assert(combiningClass('\u0300') == 230); + assert(combiningClass('\u0317') == 220); + assert(combiningClass('\u1939') == 222); +} + +/// Unicode character decomposition type. +enum UnicodeDecomposition { + /// Canonical decomposition. The result is canonically equivalent sequence. + Canonical, + /** + Compatibility decomposition. The result is compatibility equivalent sequence. + Note: Compatibility decomposition is a $(B lossy) conversion, + typically suitable only for fuzzy matching and internal processing. + */ + Compatibility +}; + +/** + Shorthand aliases for character decomposition type, passed as a + template parameter to $(LREF decompose). +*/ +enum { + Canonical = UnicodeDecomposition.Canonical, + Compatibility = UnicodeDecomposition.Compatibility +}; + +/++ + Try to canonically compose 2 $(CHARACTERS). + Returns the composed $(CHARACTER) if they do compose and dchar.init otherwise. + + The assumption is that $(D first) comes before $(D second) in the original text, + usually meaning that the first is a starter. + + Note: Hangul syllables are not covered by this function. + See $(D composeJamo) below. + + Example: + --- + assert(compose('A','\u0308') == '\u00C4'); + assert(compose('A', 'B') == dchar.init); + assert(compose('C', '\u0301') == '\u0106'); + // note that the starter is the first one + // thus the following doesn't compose + assert(compose('\u0308', 'A') == dchar.init); + --- ++/ +public dchar compose(dchar first, dchar second) +{ + import std.internal.unicode_comp; + size_t packed = compositionJumpTrie[first]; + if(packed == ushort.max) + return dchar.init; + // unpack offset and length + size_t idx = packed & composeIdxMask, cnt = packed >> composeCntShift; + // TODO: optimize this micro binary search (no more then 4-5 steps) + auto r = compositionTable[idx..idx+cnt].map!"a.rhs"().assumeSorted(); + auto target = r.lowerBound(second).length; + if(target == cnt) + return dchar.init; + auto entry = compositionTable[idx+target]; + if(entry.rhs != second) + return dchar.init; + return entry.composed; +} + +/++ + Returns a full $(S_LINK Canonical decomposition, Canonical) + (by default) or $(S_LINK Compatibility decomposition, Compatibility) + decomposition of $(CHARACTER) $(D ch). + If no decomposition is available returns a $(LREF Grapheme) + with the $(D ch) itself. + + Note: + This function also decomposes hangul syllables + as prescribed by the standard. + See also $(LREF decomposeHangul) for a restricted version + that takes into account only hangul syllables but + no other decompositions. + + Example: + --- + import std.algorithm; + assert(decompose('Ĉ')[].equal("C\u0302")); + assert(decompose('D')[].equal("D")); + assert(decompose('\uD4DC')[].equal("\u1111\u1171\u11B7")); + assert(decompose!Compatibility('¹').equal("1")); + --- ++/ +public Grapheme decompose(UnicodeDecomposition decompType=Canonical)(dchar ch) +{ + import std.internal.unicode_decomp; + static if(decompType == Canonical) + { + alias table = decompCanonTable; + alias mapping = canonMappingTrie; + } + else static if(decompType == Compatibility) + { + alias table = decompCompatTable; + alias mapping = compatMappingTrie; + } + ushort idx = mapping[ch]; + if(!idx) // not found, check hangul arithmetic decomposition + return decomposeHangul(ch); + auto decomp = table[idx..$].until(0); + return Grapheme(decomp); +} + +unittest +{ + // verify examples + assert(compose('A','\u0308') == '\u00C4'); + assert(compose('A', 'B') == dchar.init); + assert(compose('C', '\u0301') == '\u0106'); + // note that the starter is the first one + // thus the following doesn't compose + assert(compose('\u0308', 'A') == dchar.init); + + import std.algorithm; + assert(decompose('Ĉ')[].equalS("C\u0302")); + assert(decompose('D')[].equalS("D")); + assert(decompose('\uD4DC')[].equalS("\u1111\u1171\u11B7")); + assert(decompose!Compatibility('¹')[].equalS("1")); +} + +//---------------------------------------------------------------------------- +// Hangul specific composition/decomposition +enum jamoSBase = 0xAC00; +enum jamoLBase = 0x1100; +enum jamoVBase = 0x1161; +enum jamoTBase = 0x11A7; +enum jamoLCount = 19, jamoVCount = 21, jamoTCount = 28; +enum jamoNCount = jamoVCount * jamoTCount; +enum jamoSCount = jamoLCount * jamoNCount; + +// Tests if $(D ch) is a Hangul leading consonant jamo. +bool isJamoL(dchar ch) +{ + // first cmp rejects ~ 1M code points above leading jamo range + return ch < jamoLBase+jamoLCount && ch >= jamoLBase; +} + +// Tests if $(D ch) is a Hangul vowel jamo. +bool isJamoT(dchar ch) +{ + // first cmp rejects ~ 1M code points above trailing jamo range + // Note: ch == jamoTBase doesn't indicate trailing jamo (TIndex must be > 0) + return ch < jamoTBase+jamoTCount && ch > jamoTBase; +} + +// Tests if $(D ch) is a Hangul trailnig consonant jamo. +bool isJamoV(dchar ch) +{ + // first cmp rejects ~ 1M code points above vowel range + return ch < jamoVBase+jamoVCount && ch >= jamoVBase; +} + +int hangulSyllableIndex(dchar ch) +{ + int idxS = cast(int)ch - jamoSBase; + return idxS >= 0 && idxS < jamoSCount ? idxS : -1; +} + +// internal helper: compose hangul syllables leaving dchar.init in holes +void hangulRecompose(dchar[] seq) +{ + for(size_t idx = 0; idx + 1 < seq.length; ) + { + if(isJamoL(seq[idx]) && isJamoV(seq[idx+1])) + { + int indexL = seq[idx] - jamoLBase; + int indexV = seq[idx+1] - jamoVBase; + int indexLV = indexL * jamoNCount + indexV * jamoTCount; + if(idx + 2 < seq.length && isJamoT(seq[idx+2])) + { + seq[idx] = jamoSBase + indexLV + seq[idx+2] - jamoTBase; + seq[idx+1] = dchar.init; + seq[idx+2] = dchar.init; + idx += 3; + } + else + { + seq[idx] = jamoSBase + indexLV; + seq[idx+1] = dchar.init; + idx += 2; + } + } + else + idx++; + } +} + +//---------------------------------------------------------------------------- +public: + +/** + Decomposes a Hangul syllable. If $(D ch) is not a composed syllable + then this function returns $(LREF Grapheme) containing only $(D ch) as is. + + Example: + --- + import std.algorithm; + assert(decomposeHangul('\uD4DB')[].equal("\u1111\u1171\u11B6")); + --- +*/ +Grapheme decomposeHangul(dchar ch) +{ + int idxS = cast(int)ch - jamoSBase; + if(idxS < 0 || idxS >= jamoSCount) return Grapheme(ch); + int idxL = idxS / jamoNCount; + int idxV = (idxS % jamoNCount) / jamoTCount; + int idxT = idxS % jamoTCount; + + int partL = jamoLBase + idxL; + int partV = jamoVBase + idxV; + if(idxT > 0) // there is a trailling consonant (T); decomposition + return Grapheme(partL, partV, jamoTBase + idxT); + else // decomposition + return Grapheme(partL, partV); +} + +/++ + Try to compose hangul syllable out of a leading consonant ($(D lead)), + a $(D vowel) and optional $(D trailing) consonant jamos. + + On success returns the composed LV or LVT hangul syllable. + + If any of $(D lead) and $(D vowel) are not a valid hangul jamo + of the respective $(CHARACTER) class returns dchar.init. + + Example: + --- + assert(composeJamo('\u1111', '\u1171', '\u11B6') == '\uD4DB'); + // leaving out T-vowel, or passing any codepoint + // that is not trailing consonant composes an LV-syllable + assert(composeJamo('\u1111', '\u1171') == '\uD4CC'); + assert(composeJamo('\u1111', '\u1171', ' ') == '\uD4CC'); + assert(composeJamo('\u1111', 'A') == dchar.init); + assert(composeJamo('A', '\u1171') == dchar.init); + --- ++/ +dchar composeJamo(dchar lead, dchar vowel, dchar trailing=dchar.init) +{ + if(!isJamoL(lead)) + return dchar.init; + int indexL = lead - jamoLBase; + if(!isJamoV(vowel)) + return dchar.init; + int indexV = vowel - jamoVBase; + int indexLV = indexL * jamoNCount + indexV * jamoTCount; + dchar syllable = jamoSBase + indexLV; + return isJamoT(trailing) ? syllable + (trailing - jamoTBase) : syllable; +} + +unittest +{ + static void testDecomp(UnicodeDecomposition T)(dchar ch, string r) + { + Grapheme g = decompose!T(ch); + assert(equalS(g[], r), text(g[], " vs ", r)); + } + testDecomp!Canonical('\u1FF4', "\u03C9\u0301\u0345"); + testDecomp!Canonical('\uF907', "\u9F9C"); + testDecomp!Compatibility('\u33FF', "\u0067\u0061\u006C"); + testDecomp!Compatibility('\uA7F9', "\u0153"); + + // check examples + assert(decomposeHangul('\uD4DB')[].equalS("\u1111\u1171\u11B6")); + assert(composeJamo('\u1111', '\u1171', '\u11B6') == '\uD4DB'); + assert(composeJamo('\u1111', '\u1171') == '\uD4CC'); // leave out T-vowel + assert(composeJamo('\u1111', '\u1171', ' ') == '\uD4CC'); + assert(composeJamo('\u1111', 'A') == dchar.init); + assert(composeJamo('A', '\u1171') == dchar.init); +} + +/** + Enumeration type for normalization forms, + passed as template parameter for functions like $(LREF normalize). +*/ +enum NormalizationForm { + NFC, + NFD, + NFKC, + NFKD +} + + +enum { + /** + Shorthand aliases from values indicating normalization forms. + */ + NFC = NormalizationForm.NFC, + ///ditto + NFD = NormalizationForm.NFD, + ///ditto + NFKC = NormalizationForm.NFKC, + ///ditto + NFKD = NormalizationForm.NFKD +}; + +/++ + Returns $(D input) string normalized to the chosen form. + Form C is used by default. + + For more information on normalization forms see + the $(S_LINK Normalization, normalization section). + + Note: + In cases where the string in question is already normalized, + it is returned unmodified and no memory allocation happens. + + Example: + --- + // any encoding works + wstring greet = "Hello world"; + assert(normalize(greet) is greet); // the same exact slice + + // An example of a character with all 4 forms being different: + // Greek upsilon with acute and hook symbol (code point 0x03D3) + assert(normalize!NFC("ϓ") == "\u03D3"); + assert(normalize!NFD("ϓ") == "\u03D2\u0301"); + assert(normalize!NFKC("ϓ") == "\u038E"); + assert(normalize!NFKD("ϓ") == "\u03A5\u0301"); + --- ++/ +inout(C)[] normalize(NormalizationForm norm=NFC, C)(inout(C)[] input) +{ + auto anchors = splitNormalized!norm(input); + if(anchors[0] == input.length && anchors[1] == input.length) + return input; + dchar[] decomposed; + decomposed.reserve(31); + ubyte[] ccc; + ccc.reserve(31); + auto app = appender!(C[])(); + do + { + app.put(input[0..anchors[0]]); + foreach(dchar ch; input[anchors[0]..anchors[1]]) + static if(norm == NFD || norm == NFC) + { + foreach(dchar c; decompose!Canonical(ch)[]) + decomposed ~= c; + } + else // NFKD & NFKC + { + foreach(dchar c; decompose!Compatibility(ch)[]) + decomposed ~= c; + } + ccc.length = decomposed.length; + size_t firstNonStable = 0; + ubyte lastClazz = 0; + + foreach(idx, dchar ch; decomposed) + { + auto clazz = combiningClass(ch); + ccc[idx] = clazz; + if(clazz == 0 && lastClazz != 0) + { + // found a stable code point after unstable ones + sort!("a[0] < b[0]", SwapStrategy.stable) + (zip(ccc[firstNonStable..idx], decomposed[firstNonStable..idx])); + firstNonStable = decomposed.length; + } + else if(clazz != 0 && lastClazz == 0) + { + // found first unstable code point after stable ones + firstNonStable = idx; + } + lastClazz = clazz; + } + sort!("a[0] < b[0]", SwapStrategy.stable) + (zip(ccc[firstNonStable..$], decomposed[firstNonStable..$])); + static if(norm == NFC || norm == NFKC) + { + size_t idx = 0; + auto first = countUntil(ccc, 0); + if(first >= 0) // no starters?? no recomposition + { + for(;;) + { + auto second = recompose(first, decomposed, ccc); + if(second == decomposed.length) + break; + first = second; + } + // 2nd pass for hangul syllables + hangulRecompose(decomposed); + } + } + static if(norm == NFD || norm == NFKD) + app.put(decomposed); + else + { + auto clean = remove!("a == dchar.init", SwapStrategy.stable)(decomposed); + app.put(decomposed[0 .. clean.length]); + } + // reset variables + decomposed.length = 0; + decomposed.assumeSafeAppend(); + ccc.length = 0; + ccc.assumeSafeAppend(); + input = input[anchors[1]..$]; + // and move on + anchors = splitNormalized!norm(input); + }while(anchors[0] != input.length); + app.put(input[0..anchors[0]]); + return cast(inout(C)[])app.data; +} + +unittest +{ + assert(normalize!NFD("abc\uF904def") == "abc\u6ED1def", text(normalize!NFD("abc\uF904def"))); + assert(normalize!NFKD("2¹⁰") == "210", normalize!NFKD("2¹⁰")); + assert(normalize!NFD("Äffin") == "A\u0308ffin"); + + // check example + + // any encoding works + wstring greet = "Hello world"; + assert(normalize(greet) is greet); // the same exact slice + + // An example of a character with all 4 forms being different: + // Greek upsilon with acute and hook symbol (code point 0x03D3) + assert(normalize!NFC("ϓ") == "\u03D3"); + assert(normalize!NFD("ϓ") == "\u03D2\u0301"); + assert(normalize!NFKC("ϓ") == "\u038E"); + assert(normalize!NFKD("ϓ") == "\u03A5\u0301"); +} + +// canonically recompose given slice of code points, works in-place and mutates data +private size_t recompose(size_t start, dchar[] input, ubyte[] ccc) +{ + assert(input.length == ccc.length); + int accumCC = -1;// so that it's out of 0..255 range + bool foundSolidStarter = false; + // writefln("recomposing %( %04x %)", input); + // first one is always a starter thus we start at i == 1 + size_t i = start+1; + for(; ; ) + { + if(i == input.length) + break; + int curCC = ccc[i]; + // In any character sequence beginning with a starter S + // a character C is blocked from S if and only if there + // is some character B between S and C, and either B + // is a starter or it has the same or higher combining class as C. + //------------------------ + // Applying to our case: + // S is input[0] + // accumCC is the maximum CCC of characters between C and S, + // as ccc are sorted + // C is input[i] + + if(curCC > accumCC) + { + dchar comp = compose(input[start], input[i]); + if(comp != dchar.init) + { + input[start] = comp; + input[i] = dchar.init;// put a sentinel + // current was merged so its CCC shouldn't affect + // composing with the next one + } + else { + // if it was a starter then accumCC is now 0, end of loop + accumCC = curCC; + if(accumCC == 0) + break; + } + } + else{ + // ditto here + accumCC = curCC; + if(accumCC == 0) + break; + } + i++; + } + return i; +} + +// returns tuple of 2 indexes that delimit: +// normalized text, piece that needs normalization and +// the rest of input starting with stable code point +private auto splitNormalized(NormalizationForm norm, C)(const(C)[] input) +{ + auto result = input; + ubyte lastCC = 0; + + foreach(idx, dchar ch; input) + { + static if(norm == NFC) + if(ch < 0x0300) + { + lastCC = 0; + continue; + } + ubyte CC = combiningClass(ch); + if(lastCC > CC && CC != 0) + { + return seekStable!norm(idx, input); + } + + if(notAllowedIn!norm(ch)) + { + return seekStable!norm(idx, input); + } + lastCC = CC; + } + return tuple(input.length, input.length); +} + +private auto seekStable(NormalizationForm norm, C)(size_t idx, in C[] input) +{ + auto br = input[0..idx]; + size_t region_start = 0;// default + for(;;) + { + if(br.empty)// start is 0 + break; + dchar ch = br.back; + if(combiningClass(ch) == 0 && allowedIn!norm(ch)) + { + region_start = br.length - std.utf.codeLength!C(ch); + break; + } + br.popFront(); + } + ///@@@BUG@@@ can't use find: " find is a nested function and can't be used..." + size_t region_end=input.length;// end is $ by default + foreach(i, dchar ch; input[idx..$]) + { + if(combiningClass(ch) == 0 && allowedIn!norm(ch)) + { + region_end = i+idx; + break; + } + } + // writeln("Region to normalize: ", input[region_start..region_end]); + return tuple(region_start, region_end); +} + +/** + Tests if dchar $(D ch) is always allowed (Quick_Check=YES) in normalization + form $(D norm). + --- + // e.g. Cyrillic is always allowed, so is ASCII + assert(allowedIn!NFC('я')); + assert(allowedIn!NFD('я')); + assert(allowedIn!NFKC('я')); + assert(allowedIn!NFKD('я')); + assert(allowedIn!NFC('Z')); + --- +*/ +public bool allowedIn(NormalizationForm norm)(dchar ch) +{ + return !notAllowedIn!norm(ch); +} + +// not user friendly name but more direct +private bool notAllowedIn(NormalizationForm norm)(dchar ch) +{ + static if(norm == NFC) + alias qcTrie = nfcQCTrie; + else static if(norm == NFD) + alias qcTrie = nfdQCTrie; + else static if(norm == NFKC) + alias qcTrie = nfkcQCTrie; + else static if(norm == NFKD) + alias qcTrie = nfkdQCTrie; + else + static assert("Unknown normalization form "~norm); + return qcTrie[ch]; +} + +unittest +{ + assert(allowedIn!NFC('я')); + assert(allowedIn!NFD('я')); + assert(allowedIn!NFKC('я')); + assert(allowedIn!NFKD('я')); + assert(allowedIn!NFC('Z')); +} + +} + +version(std_uni_bootstrap) +{ + // old version used for bootstrapping of gen_uni.d that generates + // up to date optimal versions of all of isXXX functions + @safe pure nothrow public bool isWhite(dchar c) + { + return std.ascii.isWhite(c) || + c == lineSep || c == paraSep || + c == '\u0085' || c == '\u00A0' || c == '\u1680' || c == '\u180E' || + (c >= '\u2000' && c <= '\u200A') || + c == '\u202F' || c == '\u205F' || c == '\u3000'; + } +} +else +{ + +// trusted -> avoid bounds check +@trusted pure nothrow +ushort toLowerIndex(dchar c) +{ + alias trie = toLowerIndexTrie; + return trie[c]; +} + +// trusted -> avoid bounds check +@trusted pure nothrow +dchar toLowerTab(size_t idx) +{ + return toLowerTable[idx]; +} + +// trusted -> avoid bounds check +@trusted pure nothrow +ushort toTitleIndex(dchar c) +{ + alias trie = toTitleIndexTrie; + return trie[c]; +} + +// trusted -> avoid bounds check +@trusted pure nothrow +dchar toTitleTab(size_t idx) +{ + return toTitleTable[idx]; +} + +// trusted -> avoid bounds check +@trusted pure nothrow +ushort toUpperIndex(dchar c) +{ + alias trie = toUpperIndexTrie; + return trie[c]; +} + +// trusted -> avoid bounds check +@trusted pure nothrow +dchar toUpperTab(size_t idx) +{ + return toUpperTable[idx]; +} + +public: + +/++ + Whether or not $(D c) is a Unicode whitespace $(CHARACTER). + (general Unicode category: Part of C0(tab, vertical tab, form feed, + carriage return, and linefeed characters), Zs, Zl, Zp, and NEL(U+0085)) ++/ +@safe pure nothrow +public bool isWhite(dchar c) +{ + return isWhiteGen(c); // call pregenerated binary search +} + +deprecated ("Please use std.uni.isLower instead") +bool isUniLower(dchar c) @safe pure nothrow +{ + return isLower(c); +} + +/++ + Return whether $(D c) is a Unicode lowercase $(CHARACTER). ++/ +@safe pure nothrow +bool isLower(dchar c) +{ + if(std.ascii.isASCII(c)) + return std.ascii.isLower(c); + return lowerCaseTrie[c]; +} + +@safe unittest +{ + foreach(v; 0..0x80) + assert(std.ascii.isLower(v) == isLower(v)); + assert(isLower('я')); + assert(isLower('й')); + assert(!isLower('Ж')); + // Greek HETA + assert(!isLower('\u0370')); + assert(isLower('\u0371')); + assert(!isLower('\u039C')); // capital MU + assert(isLower('\u03B2')); // beta + // from extended Greek + assert(!isLower('\u1F18')); + assert(isLower('\u1F00')); + foreach(v; unicode.lowerCase.byCodepoint) + assert(isLower(v) && !isUpper(v)); +} + + +deprecated ("Please use std.uni.isUpper instead") +@safe pure nothrow +bool isUniUpper(dchar c) +{ + return isUpper(c); +} + +/++ + Return whether $(D c) is a Unicode uppercase $(CHARACTER). ++/ +@safe pure nothrow +bool isUpper(dchar c) +{ + if(std.ascii.isASCII(c)) + return std.ascii.isUpper(c); + return upperCaseTrie[c]; +} + +@safe unittest +{ + foreach(v; 0..0x80) + assert(std.ascii.isLower(v) == isLower(v)); + assert(!isUpper('й')); + assert(isUpper('Ж')); + // Greek HETA + assert(isUpper('\u0370')); + assert(!isUpper('\u0371')); + assert(isUpper('\u039C')); // capital MU + assert(!isUpper('\u03B2')); // beta + // from extended Greek + assert(!isUpper('\u1F00')); + assert(isUpper('\u1F18')); + foreach(v; unicode.upperCase.byCodepoint) + assert(isUpper(v) && !isLower(v)); +} + + +deprecated ("Please use std.uni.toLower instead") +@safe pure nothrow +dchar toUniLower(dchar c) +{ + return toLower(c); +} + + +/++ + If $(D c) is a Unicode uppercase $(CHARACTER), then its lowercase equivalent + is returned. Otherwise $(D c) is returned. + + Warning: certain alphabets like German and Greek have no 1:1 + upper-lower mapping. Use overload of toLower which takes full string instead. ++/ +@safe pure nothrow +dchar toLower(dchar c) +{ + // optimize ASCII case + if(c < 0xAA) + { + if(c < 'A') + return c; + if(c <= 'Z') + return c + 32; + return c; + } + size_t idx = toLowerIndex(c); + if(idx < MAX_SIMPLE_LOWER) + { + return toLowerTab(idx); + } + return c; +} + +//TODO: Hidden for now, needs better API. +//Other transforms could use better API as well, but this one is a new primitive. +@safe pure nothrow +private dchar toTitlecase(dchar c) +{ + // optimize ASCII case + if(c < 0xAA) + { + if(c < 'a') + return c; + if(c <= 'z') + return c - 32; + return c; + } + size_t idx = toTitleIndex(c); + if(idx < MAX_SIMPLE_TITLE) + { + return toTitleTab(idx); + } + return c; +} + +private alias UpperTriple = TypeTuple!(toUpperIndex, MAX_SIMPLE_UPPER, toUpperTab); +private alias LowerTriple = TypeTuple!(toLowerIndex, MAX_SIMPLE_LOWER, toLowerTab); + +// generic toUpper/toLower on whole string, creates new or returns as is +private S toCase(alias indexFn, uint maxIdx, alias tableFn, S)(S s) @trusted pure + if(isSomeString!S) +{ + foreach(i, dchar cOuter; s) + { + ushort idx = indexFn(cOuter); + if(idx == ushort.max) + continue; + auto result = s[0 .. i].dup; + foreach(dchar c; s[i .. $]) + { + idx = indexFn(c); + if(idx == ushort.max) + result ~= c; + else if(idx < maxIdx) + { + c = tableFn(idx); + result ~= c; + } + else + { + auto val = tableFn(idx); + // unpack length + codepoint + uint len = val>>24; + result ~= cast(dchar)(val & 0xFF_FFFF); + foreach(j; idx+1..idx+len) + result ~= tableFn(j); + } + } + return cast(S) result; + } + return s; +} + +// TODO: helper, I wish std.utf was more flexible (and stright) +private size_t encodeTo(char[] buf, size_t idx, dchar c) @trusted pure +{ + if (c <= 0x7F) + { + buf[idx] = cast(char)c; + idx++; + } + else if (c <= 0x7FF) + { + buf[idx] = cast(char)(0xC0 | (c >> 6)); + buf[idx+1] = cast(char)(0x80 | (c & 0x3F)); + idx += 2; + } + else if (c <= 0xFFFF) + { + buf[idx] = cast(char)(0xE0 | (c >> 12)); + buf[idx+1] = cast(char)(0x80 | ((c >> 6) & 0x3F)); + buf[idx+2] = cast(char)(0x80 | (c & 0x3F)); + idx += 3; + } + else if (c <= 0x10FFFF) + { + buf[idx] = cast(char)(0xF0 | (c >> 18)); + buf[idx+1] = cast(char)(0x80 | ((c >> 12) & 0x3F)); + buf[idx+2] = cast(char)(0x80 | ((c >> 6) & 0x3F)); + buf[idx+3] = cast(char)(0x80 | (c & 0x3F)); + idx += 4; + } + else + assert(0); + return idx; +} + +unittest +{ + char[] s = "abcd".dup; + size_t i = 0; + i = encodeTo(s, i, 'X'); + assert(s == "Xbcd"); + + i = encodeTo(s, i, cast(dchar)'\u00A9'); + assert(s == "X\xC2\xA9d"); +} + +// TODO: helper, I wish std.utf was more flexible (and stright) +private size_t encodeTo(wchar[] buf, size_t idx, dchar c) @trusted pure +{ + import std.utf; + if (c <= 0xFFFF) + { + if (0xD800 <= c && c <= 0xDFFF) + throw (new UTFException("Encoding an isolated surrogate code point in UTF-16")).setSequence(c); + buf[idx] = cast(wchar)c; + idx++; + } + else if (c <= 0x10FFFF) + { + buf[idx] = cast(wchar)((((c - 0x10000) >> 10) & 0x3FF) + 0xD800); + buf[idx+1] = cast(wchar)(((c - 0x10000) & 0x3FF) + 0xDC00); + idx += 2; + } + else + assert(0); + return idx; +} + +private size_t encodeTo(dchar[] buf, size_t idx, dchar c) @trusted pure +{ + buf[idx] = c; + idx++; + return idx; +} + +private void toCaseInPlace(alias indexFn, uint maxIdx, alias tableFn, C)(ref C[] s) @trusted pure + if (is(C == char) || is(C == wchar) || is(C == dchar)) +{ + import std.utf; + size_t curIdx = 0; + size_t destIdx = 0; + alias slowToCase = toCaseInPlaceAlloc!(indexFn, maxIdx, tableFn); + size_t lastUnchanged = 0; + // in-buffer move of bytes to a new start index + // the trick is that it may not need to copy at all + static size_t moveTo(C[] str, size_t dest, size_t from, size_t to) + { + // Interestingly we may just bump pointer for a while + // then have to copy if a re-cased char was smaller the original + // later we may regain pace with char that got bigger + // In the end it sometimes flip-flops between the 2 cases below + if(dest == from) + return to; + // got to copy + foreach(C c; str[from..to]) + str[dest++] = c; + return dest; + } + while(curIdx != s.length) + { + size_t startIdx = curIdx; + dchar ch = decode(s, curIdx); + // TODO: special case for ASCII + auto caseIndex = indexFn(ch); + if(caseIndex == ushort.max) // unchanged, skip over + { + continue; + } + else if(caseIndex < maxIdx) // 1:1 codepoint mapping + { + // previous cased chars had the same length as uncased ones + // thus can just adjust pointer + destIdx = moveTo(s, destIdx, lastUnchanged, startIdx); + lastUnchanged = curIdx; + dchar cased = tableFn(caseIndex); + auto casedLen = codeLength!C(cased); + if(casedLen + destIdx > curIdx) // no place to fit cased char + { + // switch to slow codepath, where we allocate + return slowToCase(s, startIdx, destIdx); + } + else + { + destIdx = encodeTo(s, destIdx, cased); + } + } + else // 1:m codepoint mapping, slow codepath + { + destIdx = moveTo(s, destIdx, lastUnchanged, startIdx); + lastUnchanged = curIdx; + return slowToCase(s, startIdx, destIdx); + } + assert(destIdx <= curIdx); + } + if(lastUnchanged != s.length) + { + destIdx = moveTo(s, destIdx, lastUnchanged, s.length); + } + s = s[0..destIdx]; +} + +// helper to precalculate size of case-converted string +private template toCaseLength(alias indexFn, uint maxIdx, alias tableFn) +{ + size_t toCaseLength(C)(in C[] str) + { + import std.utf; + size_t codeLen = 0; + size_t lastNonTrivial = 0; + size_t curIdx = 0; + while(curIdx != str.length) + { + size_t startIdx = curIdx; + dchar ch = decode(str, curIdx); + ushort caseIndex = indexFn(ch); + if(caseIndex == ushort.max) + continue; + else if(caseIndex < maxIdx) + { + codeLen += startIdx - lastNonTrivial; + lastNonTrivial = curIdx; + dchar cased = tableFn(caseIndex); + codeLen += codeLength!C(cased); + } + else + { + codeLen += startIdx - lastNonTrivial; + lastNonTrivial = curIdx; + auto val = tableFn(caseIndex); + auto len = val>>24; + dchar cased = val & 0xFF_FFFF; + codeLen += codeLength!C(cased); + foreach(j; caseIndex+1..caseIndex+len) + codeLen += codeLength!C(tableFn(j)); + } + } + if(lastNonTrivial != str.length) + codeLen += str.length - lastNonTrivial; + return codeLen; + } +} + +unittest +{ + import std.conv; + alias toLowerLength = toCaseLength!(LowerTriple); + assert(toLowerLength("abcd") == 4); + assert(toLowerLength("аБВгд456") == 10+3); +} + +// slower code path that preallocates and then copies +// case-converted stuf to the new string +private template toCaseInPlaceAlloc(alias indexFn, uint maxIdx, alias tableFn) +{ + void toCaseInPlaceAlloc(C)(ref C[] s, size_t curIdx, + size_t destIdx) @trusted pure + if (is(C == char) || is(C == wchar) || is(C == dchar)) + { + import std.utf : decode; + alias caseLength = toCaseLength!(indexFn, maxIdx, tableFn); + auto trueLength = destIdx + caseLength(s[curIdx..$]); + C[] ns = new C[trueLength]; + ns[0..destIdx] = s[0..destIdx]; + size_t lastUnchanged = curIdx; + while(curIdx != s.length) + { + size_t startIdx = curIdx; // start of current codepoint + dchar ch = decode(s, curIdx); + auto caseIndex = indexFn(ch); + if(caseIndex == ushort.max) // skip over + { + continue; + } + else if(caseIndex < maxIdx) // 1:1 codepoint mapping + { + dchar cased = tableFn(caseIndex); + auto toCopy = startIdx - lastUnchanged; + ns[destIdx .. destIdx+toCopy] = s[lastUnchanged .. startIdx]; + lastUnchanged = curIdx; + destIdx += toCopy; + destIdx = encodeTo(ns, destIdx, cased); + } + else // 1:m codepoint mapping, slow codepath + { + auto toCopy = startIdx - lastUnchanged; + ns[destIdx .. destIdx+toCopy] = s[lastUnchanged .. startIdx]; + lastUnchanged = curIdx; + destIdx += toCopy; + auto val = tableFn(caseIndex); + // unpack length + codepoint + uint len = val>>24; + destIdx = encodeTo(ns, destIdx, cast(dchar)(val & 0xFF_FFFF)); + foreach(j; caseIndex+1..caseIndex+len) + destIdx = encodeTo(ns, destIdx, tableFn(j)); + } + } + if(lastUnchanged != s.length) + { + auto toCopy = s.length - lastUnchanged; + ns[destIdx..destIdx+toCopy] = s[lastUnchanged..$]; + destIdx += toCopy; + } + assert(ns.length == destIdx); + s = ns; + } +} + +/++ + Converts $(D s) to lowercase (by performing Unicode lowercase mapping) in place. + For a few characters string length may increase after the transformation, + in such a case the function reallocates exactly once. + If $(D s) does not have any uppercase characters, then $(D s) is unaltered. ++/ +void toLowerInPlace(C)(ref C[] s) @trusted pure + if (is(C == char) || is(C == wchar) || is(C == dchar)) +{ + toCaseInPlace!(LowerTriple)(s); +} +// overloads for the most common cases to reduce compile time +@safe pure /*TODO nothrow*/ +{ + void toLowerInPlace(ref char[] s) + { toLowerInPlace!char(s); } + void toLowerInPlace(ref wchar[] s) + { toLowerInPlace!wchar(s); } + void toLowerInPlace(ref dchar[] s) + { toLowerInPlace!dchar(s); } +} + +/++ + Converts $(D s) to uppercase (by performing Unicode uppercase mapping) in place. + For a few characters string length may increase after the transformation, + in such a case the function reallocates exactly once. + If $(D s) does not have any lowercase characters, then $(D s) is unaltered. ++/ +void toUpperInPlace(C)(ref C[] s) @trusted pure + if (is(C == char) || is(C == wchar) || is(C == dchar)) +{ + toCaseInPlace!(UpperTriple)(s); +} +// overloads for the most common cases to reduce compile time/code size +@safe pure /*TODO nothrow*/ +{ + void toUpperInPlace(ref char[] s) + { toUpperInPlace!char(s); } + void toUpperInPlace(ref wchar[] s) + { toUpperInPlace!wchar(s); } + void toUpperInPlace(ref dchar[] s) + { toUpperInPlace!dchar(s); } +} + +/++ + Returns a string which is identical to $(D s) except that all of its + characters are converted to lowercase (by preforming Unicode lowercase mapping). + If none of $(D s) characters were affected, then $(D s) itself is returned. ++/ +S toLower(S)(S s) @trusted pure + if(isSomeString!S) +{ + return toCase!(LowerTriple)(s); +} +// overloads for the most common cases to reduce compile time +@safe pure /*TODO nothrow*/ +{ + string toLower(string s) + { return toLower!string(s); } + wstring toLower(wstring s) + { return toLower!wstring(s); } + dstring toLower(dstring s) + { return toLower!dstring(s); } +} + + +@trusted unittest //@@@BUG std.format is not @safe +{ + import std.string : format; + foreach(ch; 0..0x80) + assert(std.ascii.toLower(ch) == toLower(ch)); + assert(toLower('Я') == 'я'); + assert(toLower('Δ') == 'δ'); + foreach(ch; unicode.upperCase.byCodepoint) + { + dchar low = ch.toLower(); + assert(low == ch || isLower(low), format("%s -> %s", ch, low)); + } + assert(toLower("АЯ") == "ая"); + + assert("\u1E9E".toLower == "\u00df"); + assert("\u00df".toUpper == "SS"); +} + +//bugzilla 9629 +unittest +{ + wchar[] test = "hello þ world"w.dup; + auto piece = test[6..7]; + toUpperInPlace(piece); + assert(test == "hello Þ world"); +} + + +unittest +{ + string s1 = "FoL"; + string s2 = toLower(s1); + assert(cmp(s2, "fol") == 0, s2); + assert(s2 != s1); + + char[] s3 = s1.dup; + toLowerInPlace(s3); + assert(s3 == s2); + + s1 = "A\u0100B\u0101d"; + s2 = toLower(s1); + s3 = s1.dup; + assert(cmp(s2, "a\u0101b\u0101d") == 0); + assert(s2 !is s1); + toLowerInPlace(s3); + assert(s3 == s2); + + s1 = "A\u0460B\u0461d"; + s2 = toLower(s1); + s3 = s1.dup; + assert(cmp(s2, "a\u0461b\u0461d") == 0); + assert(s2 !is s1); + toLowerInPlace(s3); + assert(s3 == s2); + + s1 = "\u0130"; + s2 = toLower(s1); + s3 = s1.dup; + assert(s2 == "i\u0307"); + assert(s2 !is s1); + toLowerInPlace(s3); + assert(s3 == s2); + + // Test on wchar and dchar strings. + assert(toLower("Some String"w) == "some string"w); + assert(toLower("Some String"d) == "some string"d); +} + + +deprecated("Please use std.uni.toUpper instead") +@safe pure nothrow +dchar toUniUpper(dchar c) +{ + return toUpper(c); +} + +/++ + If $(D c) is a Unicode lowercase $(CHARACTER), then its uppercase equivalent + is returned. Otherwise $(D c) is returned. + + Warning: + Certain alphabets like German and Greek have no 1:1 + upper-lower mapping. Use overload of toUpper which takes full string instead. ++/ +@safe pure nothrow +dchar toUpper(dchar c) +{ + // optimize ASCII case + if(c < 0xAA) + { + if(c < 'a') + return c; + if(c <= 'z') + return c - 32; + return c; + } + size_t idx = toUpperIndex(c); + if(idx < MAX_SIMPLE_UPPER) + { + return toUpperTab(idx); + } + return c; +} + +@trusted unittest +{ + import std.string : format; + foreach(ch; 0..0x80) + assert(std.ascii.toUpper(ch) == toUpper(ch)); + assert(toUpper('я') == 'Я'); + assert(toUpper('δ') == 'Δ'); + foreach(ch; unicode.lowerCase.byCodepoint) + { + dchar up = ch.toUpper(); + assert(up == ch || isUpper(up), format("%s -> %s", ch, up)); + } +} + +/++ + Returns a string which is identical to $(D s) except that all of its + characters are converted to uppercase (by preforming Unicode uppercase mapping). + If none of $(D s) characters were affected, then $(D s) itself is returned. ++/ +S toUpper(S)(S s) @trusted pure + if(isSomeString!S) +{ + return toCase!(UpperTriple)(s); +} +// overloads for the most common cases to reduce compile time +@safe pure /*TODO nothrow*/ +{ + string toUpper(string s) + { return toUpper!string(s); } + wstring toUpper(wstring s) + { return toUpper!wstring(s); } + dstring toUpper(dstring s) + { return toUpper!dstring(s); } +} + +unittest +{ + string s1 = "FoL"; + string s2; + char[] s3; + + s2 = toUpper(s1); + s3 = s1.dup; toUpperInPlace(s3); + assert(s3 == s2, s3); + assert(cmp(s2, "FOL") == 0); + assert(s2 !is s1); + + s1 = "a\u0100B\u0101d"; + s2 = toUpper(s1); + s3 = s1.dup; toUpperInPlace(s3); + assert(s3 == s2); + assert(cmp(s2, "A\u0100B\u0100D") == 0); + assert(s2 !is s1); + + s1 = "a\u0460B\u0461d"; + s2 = toUpper(s1); + s3 = s1.dup; toUpperInPlace(s3); + assert(s3 == s2); + assert(cmp(s2, "A\u0460B\u0460D") == 0); + assert(s2 !is s1); +} + +unittest +{ + static void doTest(C)(const(C)[] s, const(C)[] trueUp, const(C)[] trueLow) + { + import std.string : format; + string diff = "src: %( %x %)\nres: %( %x %)\ntru: %( %x %)"; + auto low = s.toLower() , up = s.toUpper(); + auto lowInp = s.dup, upInp = s.dup; + lowInp.toLowerInPlace(); + upInp.toUpperInPlace(); + assert(low == trueLow, format(diff, low, trueLow)); + assert(up == trueUp, format(diff, up, trueUp)); + assert(lowInp == trueLow, + format(diff, cast(ubyte[])s, cast(ubyte[])lowInp, cast(ubyte[])trueLow)); + assert(upInp == trueUp, + format(diff, cast(ubyte[])s, cast(ubyte[])upInp, cast(ubyte[])trueUp)); + } + foreach(S; TypeTuple!(dstring, wstring, string)) + { + + S easy = "123"; + S good = "abCФеж"; + S awful = "\u0131\u023f\u2126"; + S wicked = "\u0130\u1FE2"; + auto options = [easy, good, awful, wicked]; + S[] lower = ["123", "abcфеж", "\u0131\u023f\u03c9", "i\u0307\u1Fe2"]; + S[] upper = ["123", "ABCФЕЖ", "I\u2c7e\u2126", "\u0130\u03A5\u0308\u0300"]; + + foreach(val; TypeTuple!(easy, good)) + { + auto e = val.dup; + auto g = e; + e.toUpperInPlace(); + assert(e is g); + e.toLowerInPlace(); + assert(e is g); + } + foreach(i, v; options) + { + doTest(v, upper[i], lower[i]); + } + + // a few combinatorial runs + foreach(i; 0..options.length) + foreach(j; i..options.length) + foreach(k; j..options.length) + { + auto sample = options[i] ~ options[j] ~ options[k]; + auto sample2 = options[k] ~ options[j] ~ options[i]; + doTest(sample, upper[i] ~ upper[j] ~ upper[k], + lower[i] ~ lower[j] ~ lower[k]); + doTest(sample2, upper[k] ~ upper[j] ~ upper[i], + lower[k] ~ lower[j] ~ lower[i]); + } + } +} + +deprecated("Please use std.uni.isAlpha instead.") +@safe pure nothrow +bool isUniAlpha(dchar c) +{ + return isAlpha(c); +} + +/++ + Returns whether $(D c) is a Unicode alphabetic $(CHARACTER) + (general Unicode category: Alphabetic). ++/ +@safe pure nothrow +bool isAlpha(dchar c) +{ + // optimization + if(c < 0xAA) + { + size_t x = c - 'A'; + if(x <= 'Z' - 'A') + return true; + else + { + x = c - 'a'; + if(x <= 'z'-'a') + return true; + } + return false; + } + + return alphaTrie[c]; +} + +@safe unittest +{ + auto alpha = unicode("Alphabetic"); + foreach(ch; alpha.byCodepoint) + assert(isAlpha(ch)); + foreach(ch; 0..0x4000) + assert((ch in alpha) == isAlpha(ch)); } /++ Returns whether $(D c) is a Unicode mark (general Unicode category: Mn, Me, Mc). - - Standards: Unicode 6.0.0. - +/ - -bool isMark(dchar c) @safe pure nothrow ++/ +@safe pure nothrow +bool isMark(dchar c) { - static immutable dchar[2][] tableMn = - [ - [ 0x0300, 0x036F ], - [ 0x0483, 0x0487 ], - [ 0x0591, 0x05BD ], - [ 0x05BF, 0x05BF ], - [ 0x05C1, 0x05C2 ], - [ 0x05C4, 0x05C5 ], - [ 0x05C7, 0x05C7 ], - [ 0x0610, 0x061A ], - [ 0x064B, 0x065F ], - [ 0x0670, 0x0670 ], - [ 0x06D6, 0x06DC ], - [ 0x06DF, 0x06E4 ], - [ 0x06E7, 0x06E8 ], - [ 0x06EA, 0x06ED ], - [ 0x0711, 0x0711 ], - [ 0x0730, 0x074A ], - [ 0x07A6, 0x07B0 ], - [ 0x07EB, 0x07F3 ], - [ 0x0816, 0x0819 ], - [ 0x081B, 0x0823 ], - [ 0x0825, 0x0827 ], - [ 0x0829, 0x082D ], - [ 0x0859, 0x085B ], - [ 0x0900, 0x0902 ], - [ 0x093A, 0x093A ], - [ 0x093C, 0x093C ], - [ 0x0941, 0x0948 ], - [ 0x094D, 0x094D ], - [ 0x0951, 0x0957 ], - [ 0x0962, 0x0963 ], - [ 0x0981, 0x0981 ], - [ 0x09BC, 0x09BC ], - [ 0x09C1, 0x09C4 ], - [ 0x09CD, 0x09CD ], - [ 0x09E2, 0x09E3 ], - [ 0x0A01, 0x0A02 ], - [ 0x0A3C, 0x0A3C ], - [ 0x0A41, 0x0A42 ], - [ 0x0A47, 0x0A48 ], - [ 0x0A4B, 0x0A4D ], - [ 0x0A51, 0x0A51 ], - [ 0x0A70, 0x0A71 ], - [ 0x0A75, 0x0A75 ], - [ 0x0A81, 0x0A82 ], - [ 0x0ABC, 0x0ABC ], - [ 0x0AC1, 0x0AC5 ], - [ 0x0AC7, 0x0AC8 ], - [ 0x0ACD, 0x0ACD ], - [ 0x0AE2, 0x0AE3 ], - [ 0x0B01, 0x0B01 ], - [ 0x0B3C, 0x0B3C ], - [ 0x0B3F, 0x0B3F ], - [ 0x0B41, 0x0B44 ], - [ 0x0B4D, 0x0B4D ], - [ 0x0B56, 0x0B56 ], - [ 0x0B62, 0x0B63 ], - [ 0x0B82, 0x0B82 ], - [ 0x0BC0, 0x0BC0 ], - [ 0x0BCD, 0x0BCD ], - [ 0x0C3E, 0x0C40 ], - [ 0x0C46, 0x0C48 ], - [ 0x0C4A, 0x0C4D ], - [ 0x0C55, 0x0C56 ], - [ 0x0C62, 0x0C63 ], - [ 0x0CBC, 0x0CBC ], - [ 0x0CBF, 0x0CBF ], - [ 0x0CC6, 0x0CC6 ], - [ 0x0CCC, 0x0CCD ], - [ 0x0CE2, 0x0CE3 ], - [ 0x0D41, 0x0D44 ], - [ 0x0D4D, 0x0D4D ], - [ 0x0D62, 0x0D63 ], - [ 0x0DCA, 0x0DCA ], - [ 0x0DD2, 0x0DD4 ], - [ 0x0DD6, 0x0DD6 ], - [ 0x0E31, 0x0E31 ], - [ 0x0E34, 0x0E3A ], - [ 0x0E47, 0x0E4E ], - [ 0x0EB1, 0x0EB1 ], - [ 0x0EB4, 0x0EB9 ], - [ 0x0EBB, 0x0EBC ], - [ 0x0EC8, 0x0ECD ], - [ 0x0F18, 0x0F19 ], - [ 0x0F35, 0x0F35 ], - [ 0x0F37, 0x0F37 ], - [ 0x0F39, 0x0F39 ], - [ 0x0F71, 0x0F7E ], - [ 0x0F80, 0x0F84 ], - [ 0x0F86, 0x0F87 ], - [ 0x0F8D, 0x0F97 ], - [ 0x0F99, 0x0FBC ], - [ 0x0FC6, 0x0FC6 ], - [ 0x102D, 0x1030 ], - [ 0x1032, 0x1037 ], - [ 0x1039, 0x103A ], - [ 0x103D, 0x103E ], - [ 0x1058, 0x1059 ], - [ 0x105E, 0x1060 ], - [ 0x1071, 0x1074 ], - [ 0x1082, 0x1082 ], - [ 0x1085, 0x1086 ], - [ 0x108D, 0x108D ], - [ 0x109D, 0x109D ], - [ 0x135D, 0x135F ], - [ 0x1712, 0x1714 ], - [ 0x1732, 0x1734 ], - [ 0x1752, 0x1753 ], - [ 0x1772, 0x1773 ], - [ 0x17B7, 0x17BD ], - [ 0x17C6, 0x17C6 ], - [ 0x17C9, 0x17D3 ], - [ 0x17DD, 0x17DD ], - [ 0x180B, 0x180D ], - [ 0x18A9, 0x18A9 ], - [ 0x1920, 0x1922 ], - [ 0x1927, 0x1928 ], - [ 0x1932, 0x1932 ], - [ 0x1939, 0x193B ], - [ 0x1A17, 0x1A18 ], - [ 0x1A56, 0x1A56 ], - [ 0x1A58, 0x1A5E ], - [ 0x1A60, 0x1A60 ], - [ 0x1A62, 0x1A62 ], - [ 0x1A65, 0x1A6C ], - [ 0x1A73, 0x1A7C ], - [ 0x1A7F, 0x1A7F ], - [ 0x1B00, 0x1B03 ], - [ 0x1B34, 0x1B34 ], - [ 0x1B36, 0x1B3A ], - [ 0x1B3C, 0x1B3C ], - [ 0x1B42, 0x1B42 ], - [ 0x1B6B, 0x1B73 ], - [ 0x1B80, 0x1B81 ], - [ 0x1BA2, 0x1BA5 ], - [ 0x1BA8, 0x1BA9 ], - [ 0x1BE6, 0x1BE6 ], - [ 0x1BE8, 0x1BE9 ], - [ 0x1BED, 0x1BED ], - [ 0x1BEF, 0x1BF1 ], - [ 0x1C2C, 0x1C33 ], - [ 0x1C36, 0x1C37 ], - [ 0x1CD0, 0x1CD2 ], - [ 0x1CD4, 0x1CE0 ], - [ 0x1CE2, 0x1CE8 ], - [ 0x1CED, 0x1CED ], - [ 0x1DC0, 0x1DE6 ], - [ 0x1DFC, 0x1DFF ], - [ 0x20D0, 0x20DC ], - [ 0x20E1, 0x20E1 ], - [ 0x20E5, 0x20F0 ], - [ 0x2CEF, 0x2CF1 ], - [ 0x2D7F, 0x2D7F ], - [ 0x2DE0, 0x2DFF ], - [ 0x302A, 0x302F ], - [ 0x3099, 0x309A ], - [ 0xA66F, 0xA66F ], - [ 0xA67C, 0xA67D ], - [ 0xA6F0, 0xA6F1 ], - [ 0xA802, 0xA802 ], - [ 0xA806, 0xA806 ], - [ 0xA80B, 0xA80B ], - [ 0xA825, 0xA826 ], - [ 0xA8C4, 0xA8C4 ], - [ 0xA8E0, 0xA8F1 ], - [ 0xA926, 0xA92D ], - [ 0xA947, 0xA951 ], - [ 0xA980, 0xA982 ], - [ 0xA9B3, 0xA9B3 ], - [ 0xA9B6, 0xA9B9 ], - [ 0xA9BC, 0xA9BC ], - [ 0xAA29, 0xAA2E ], - [ 0xAA31, 0xAA32 ], - [ 0xAA35, 0xAA36 ], - [ 0xAA43, 0xAA43 ], - [ 0xAA4C, 0xAA4C ], - [ 0xAAB0, 0xAAB0 ], - [ 0xAAB2, 0xAAB4 ], - [ 0xAAB7, 0xAAB8 ], - [ 0xAABE, 0xAABF ], - [ 0xAAC1, 0xAAC1 ], - [ 0xABE5, 0xABE5 ], - [ 0xABE8, 0xABE8 ], - [ 0xABED, 0xABED ], - [ 0xFB1E, 0xFB1E ], - [ 0xFE00, 0xFE0F ], - [ 0xFE20, 0xFE26 ], - [ 0x101FD, 0x101FD ], - [ 0x10A01, 0x10A03 ], - [ 0x10A05, 0x10A06 ], - [ 0x10A0C, 0x10A0F ], - [ 0x10A38, 0x10A3A ], - [ 0x10A3F, 0x10A3F ], - [ 0x11001, 0x11001 ], - [ 0x11038, 0x11046 ], - [ 0x11080, 0x11081 ], - [ 0x110B3, 0x110B6 ], - [ 0x110B9, 0x110BA ], - [ 0x1D167, 0x1D169 ], - [ 0x1D17B, 0x1D182 ], - [ 0x1D185, 0x1D18B ], - [ 0x1D1AA, 0x1D1AD ], - [ 0x1D242, 0x1D244 ], - [ 0xE0100, 0xE01EF ], - ]; - - static immutable dchar[2][] tableMe = - [ - [ 0x0488, 0x0489 ], - [ 0x20DD, 0x20E0 ], - [ 0x20E2, 0x20E4 ], - [ 0xA670, 0xA672 ], - ]; - - static immutable dchar[2][] tableMc = - [ - [ 0x0903, 0x0903 ], - [ 0x093B, 0x093B ], - [ 0x093E, 0x0940 ], - [ 0x0949, 0x094C ], - [ 0x094E, 0x094F ], - [ 0x0982, 0x0983 ], - [ 0x09BE, 0x09C0 ], - [ 0x09C7, 0x09C8 ], - [ 0x09CB, 0x09CC ], - [ 0x09D7, 0x09D7 ], - [ 0x0A03, 0x0A03 ], - [ 0x0A3E, 0x0A40 ], - [ 0x0A83, 0x0A83 ], - [ 0x0ABE, 0x0AC0 ], - [ 0x0AC9, 0x0AC9 ], - [ 0x0ACB, 0x0ACC ], - [ 0x0B02, 0x0B03 ], - [ 0x0B3E, 0x0B3E ], - [ 0x0B40, 0x0B40 ], - [ 0x0B47, 0x0B48 ], - [ 0x0B4B, 0x0B4C ], - [ 0x0B57, 0x0B57 ], - [ 0x0BBE, 0x0BBF ], - [ 0x0BC1, 0x0BC2 ], - [ 0x0BC6, 0x0BC8 ], - [ 0x0BCA, 0x0BCC ], - [ 0x0BD7, 0x0BD7 ], - [ 0x0C01, 0x0C03 ], - [ 0x0C41, 0x0C44 ], - [ 0x0C82, 0x0C83 ], - [ 0x0CBE, 0x0CBE ], - [ 0x0CC0, 0x0CC4 ], - [ 0x0CC7, 0x0CC8 ], - [ 0x0CCA, 0x0CCB ], - [ 0x0CD5, 0x0CD6 ], - [ 0x0D02, 0x0D03 ], - [ 0x0D3E, 0x0D40 ], - [ 0x0D46, 0x0D48 ], - [ 0x0D4A, 0x0D4C ], - [ 0x0D57, 0x0D57 ], - [ 0x0D82, 0x0D83 ], - [ 0x0DCF, 0x0DD1 ], - [ 0x0DD8, 0x0DDF ], - [ 0x0DF2, 0x0DF3 ], - [ 0x0F3E, 0x0F3F ], - [ 0x0F7F, 0x0F7F ], - [ 0x102B, 0x102C ], - [ 0x1031, 0x1031 ], - [ 0x1038, 0x1038 ], - [ 0x103B, 0x103C ], - [ 0x1056, 0x1057 ], - [ 0x1062, 0x1064 ], - [ 0x1067, 0x106D ], - [ 0x1083, 0x1084 ], - [ 0x1087, 0x108C ], - [ 0x108F, 0x108F ], - [ 0x109A, 0x109C ], - [ 0x17B6, 0x17B6 ], - [ 0x17BE, 0x17C5 ], - [ 0x17C7, 0x17C8 ], - [ 0x1923, 0x1926 ], - [ 0x1929, 0x192B ], - [ 0x1930, 0x1931 ], - [ 0x1933, 0x1938 ], - [ 0x19B0, 0x19C0 ], - [ 0x19C8, 0x19C9 ], - [ 0x1A19, 0x1A1B ], - [ 0x1A55, 0x1A55 ], - [ 0x1A57, 0x1A57 ], - [ 0x1A61, 0x1A61 ], - [ 0x1A63, 0x1A64 ], - [ 0x1A6D, 0x1A72 ], - [ 0x1B04, 0x1B04 ], - [ 0x1B35, 0x1B35 ], - [ 0x1B3B, 0x1B3B ], - [ 0x1B3D, 0x1B41 ], - [ 0x1B43, 0x1B44 ], - [ 0x1B82, 0x1B82 ], - [ 0x1BA1, 0x1BA1 ], - [ 0x1BA6, 0x1BA7 ], - [ 0x1BAA, 0x1BAA ], - [ 0x1BE7, 0x1BE7 ], - [ 0x1BEA, 0x1BEC ], - [ 0x1BEE, 0x1BEE ], - [ 0x1BF2, 0x1BF3 ], - [ 0x1C24, 0x1C2B ], - [ 0x1C34, 0x1C35 ], - [ 0x1CE1, 0x1CE1 ], - [ 0x1CF2, 0x1CF2 ], - [ 0xA823, 0xA824 ], - [ 0xA827, 0xA827 ], - [ 0xA880, 0xA881 ], - [ 0xA8B4, 0xA8C3 ], - [ 0xA952, 0xA953 ], - [ 0xA983, 0xA983 ], - [ 0xA9B4, 0xA9B5 ], - [ 0xA9BA, 0xA9BB ], - [ 0xA9BD, 0xA9C0 ], - [ 0xAA2F, 0xAA30 ], - [ 0xAA33, 0xAA34 ], - [ 0xAA4D, 0xAA4D ], - [ 0xAA7B, 0xAA7B ], - [ 0xABE3, 0xABE4 ], - [ 0xABE6, 0xABE7 ], - [ 0xABE9, 0xABEA ], - [ 0xABEC, 0xABEC ], - [ 0x11000, 0x11000 ], - [ 0x11002, 0x11002 ], - [ 0x11082, 0x11082 ], - [ 0x110B0, 0x110B2 ], - [ 0x110B7, 0x110B8 ], - [ 0x1D165, 0x1D166 ], - [ 0x1D16D, 0x1D172 ], - ]; - - return binarySearch!tableMn(c) || binarySearch!tableMe(c) || binarySearch!tableMc(c); + return markTrie[c]; } -unittest +@safe unittest { - assert(isMark('\u0300')); - assert(isMark('\u0488')); - assert(isMark('\u0903')); + auto mark = unicode("Mark"); + foreach(ch; mark.byCodepoint) + assert(isMark(ch)); + foreach(ch; 0..0x4000) + assert((ch in mark) == isMark(ch)); } - /++ - Returns whether $(D c) is a Unicode numerical character + Returns whether $(D c) is a Unicode numerical $(CHARACTER) (general Unicode category: Nd, Nl, No). - - Standards: Unicode 6.0.0. - +/ - -bool isNumber(dchar c) @safe pure nothrow ++/ +@safe pure nothrow +bool isNumber(dchar c) { - static immutable dchar[2][] tableNd = - [ - [ 0x0030, 0x0039 ], - [ 0x0660, 0x0669 ], - [ 0x06F0, 0x06F9 ], - [ 0x07C0, 0x07C9 ], - [ 0x0966, 0x096F ], - [ 0x09E6, 0x09EF ], - [ 0x0A66, 0x0A6F ], - [ 0x0AE6, 0x0AEF ], - [ 0x0B66, 0x0B6F ], - [ 0x0BE6, 0x0BEF ], - [ 0x0C66, 0x0C6F ], - [ 0x0CE6, 0x0CEF ], - [ 0x0D66, 0x0D6F ], - [ 0x0E50, 0x0E59 ], - [ 0x0ED0, 0x0ED9 ], - [ 0x0F20, 0x0F29 ], - [ 0x1040, 0x1049 ], - [ 0x1090, 0x1099 ], - [ 0x17E0, 0x17E9 ], - [ 0x1810, 0x1819 ], - [ 0x1946, 0x194F ], - [ 0x19D0, 0x19D9 ], - [ 0x1A80, 0x1A89 ], - [ 0x1A90, 0x1A99 ], - [ 0x1B50, 0x1B59 ], - [ 0x1BB0, 0x1BB9 ], - [ 0x1C40, 0x1C49 ], - [ 0x1C50, 0x1C59 ], - [ 0xA620, 0xA629 ], - [ 0xA8D0, 0xA8D9 ], - [ 0xA900, 0xA909 ], - [ 0xA9D0, 0xA9D9 ], - [ 0xAA50, 0xAA59 ], - [ 0xABF0, 0xABF9 ], - [ 0xFF10, 0xFF19 ], - [ 0x104A0, 0x104A9 ], - [ 0x11066, 0x1106F ], - [ 0x1D7CE, 0x1D7FF ], - ]; - - static immutable dchar[2][] tableNl = - [ - [ 0x16EE, 0x16F0 ], - [ 0x2160, 0x2182 ], - [ 0x2185, 0x2188 ], - [ 0x3007, 0x3007 ], - [ 0x3021, 0x3029 ], - [ 0x3038, 0x303A ], - [ 0xA6E6, 0xA6EF ], - [ 0x10140, 0x10174 ], - [ 0x10341, 0x10341 ], - [ 0x1034A, 0x1034A ], - [ 0x103D1, 0x103D5 ], - [ 0x12400, 0x12462 ], - ]; - - static immutable dchar[2][] tableNo = - [ - [ 0x00B2, 0x00B3 ], - [ 0x00B9, 0x00B9 ], - [ 0x00BC, 0x00BE ], - [ 0x09F4, 0x09F9 ], - [ 0x0B72, 0x0B77 ], - [ 0x0BF0, 0x0BF2 ], - [ 0x0C78, 0x0C7E ], - [ 0x0D70, 0x0D75 ], - [ 0x0F2A, 0x0F33 ], - [ 0x1369, 0x137C ], - [ 0x17F0, 0x17F9 ], - [ 0x19DA, 0x19DA ], - [ 0x2070, 0x2070 ], - [ 0x2074, 0x2079 ], - [ 0x2080, 0x2089 ], - [ 0x2150, 0x215F ], - [ 0x2189, 0x2189 ], - [ 0x2460, 0x249B ], - [ 0x24EA, 0x24FF ], - [ 0x2776, 0x2793 ], - [ 0x2CFD, 0x2CFD ], - [ 0x3192, 0x3195 ], - [ 0x3220, 0x3229 ], - [ 0x3251, 0x325F ], - [ 0x3280, 0x3289 ], - [ 0x32B1, 0x32BF ], - [ 0xA830, 0xA835 ], - [ 0x10107, 0x10133 ], - [ 0x10175, 0x10178 ], - [ 0x1018A, 0x1018A ], - [ 0x10320, 0x10323 ], - [ 0x10858, 0x1085F ], - [ 0x10916, 0x1091B ], - [ 0x10A40, 0x10A47 ], - [ 0x10A7D, 0x10A7E ], - [ 0x10B58, 0x10B5F ], - [ 0x10B78, 0x10B7F ], - [ 0x10E60, 0x10E7E ], - [ 0x11052, 0x11065 ], - [ 0x1D360, 0x1D371 ], - [ 0x1F100, 0x1F10A ], - ]; - - return binarySearch!tableNd(c) - || binarySearch!tableNl(c) - || binarySearch!tableNo(c); + return numberTrie[c]; } -unittest +@safe unittest { - for (dchar c = '0'; c < '9'; ++c) - { - assert(isNumber(c)); - } + auto n = unicode("N"); + foreach(ch; n.byCodepoint) + assert(isNumber(ch)); + foreach(ch; 0..0x4000) + assert((ch in n) == isNumber(ch)); } /++ - Returns whether $(D c) is a Unicode punctuation character + Returns whether $(D c) is a Unicode punctuation $(CHARACTER) (general Unicode category: Pd, Ps, Pe, Pc, Po, Pi, Pf). - - Standards: Unicode 6.0.0. - +/ - -bool isPunctuation(dchar c) @safe pure nothrow ++/ +@safe pure nothrow +bool isPunctuation(dchar c) { - static immutable dchar[2][] tablePd = - [ - [ 0x002D, 0x002D ], - [ 0x058A, 0x058A ], - [ 0x05BE, 0x05BE ], - [ 0x1400, 0x1400 ], - [ 0x1806, 0x1806 ], - [ 0x2010, 0x2015 ], - [ 0x2E17, 0x2E17 ], - [ 0x2E1A, 0x2E1A ], - [ 0x301C, 0x301C ], - [ 0x3030, 0x3030 ], - [ 0x30A0, 0x30A0 ], - [ 0xFE31, 0xFE32 ], - [ 0xFE58, 0xFE58 ], - [ 0xFE63, 0xFE63 ], - [ 0xFF0D, 0xFF0D ], - ]; - - static immutable dchar[2][] tablePs = - [ - [ 0x0028, 0x0028 ], - [ 0x005B, 0x005B ], - [ 0x007B, 0x007B ], - [ 0x0F3A, 0x0F3A ], - [ 0x0F3C, 0x0F3C ], - [ 0x169B, 0x169B ], - [ 0x201A, 0x201A ], - [ 0x201E, 0x201E ], - [ 0x2045, 0x2045 ], - [ 0x207D, 0x207D ], - [ 0x208D, 0x208D ], - [ 0x2329, 0x2329 ], - [ 0x2768, 0x2768 ], - [ 0x276A, 0x276A ], - [ 0x276C, 0x276C ], - [ 0x276E, 0x276E ], - [ 0x2770, 0x2770 ], - [ 0x2772, 0x2772 ], - [ 0x2774, 0x2774 ], - [ 0x27C5, 0x27C5 ], - [ 0x27E6, 0x27E6 ], - [ 0x27E8, 0x27E8 ], - [ 0x27EA, 0x27EA ], - [ 0x27EC, 0x27EC ], - [ 0x27EE, 0x27EE ], - [ 0x2983, 0x2983 ], - [ 0x2985, 0x2985 ], - [ 0x2987, 0x2987 ], - [ 0x2989, 0x2989 ], - [ 0x298B, 0x298B ], - [ 0x298D, 0x298D ], - [ 0x298F, 0x298F ], - [ 0x2991, 0x2991 ], - [ 0x2993, 0x2993 ], - [ 0x2995, 0x2995 ], - [ 0x2997, 0x2997 ], - [ 0x29D8, 0x29D8 ], - [ 0x29DA, 0x29DA ], - [ 0x29FC, 0x29FC ], - [ 0x2E22, 0x2E22 ], - [ 0x2E24, 0x2E24 ], - [ 0x2E26, 0x2E26 ], - [ 0x2E28, 0x2E28 ], - [ 0x3008, 0x3008 ], - [ 0x300A, 0x300A ], - [ 0x300C, 0x300C ], - [ 0x300E, 0x300E ], - [ 0x3010, 0x3010 ], - [ 0x3014, 0x3014 ], - [ 0x3016, 0x3016 ], - [ 0x3018, 0x3018 ], - [ 0x301A, 0x301A ], - [ 0x301D, 0x301D ], - [ 0xFD3E, 0xFD3E ], - [ 0xFE17, 0xFE17 ], - [ 0xFE35, 0xFE35 ], - [ 0xFE37, 0xFE37 ], - [ 0xFE39, 0xFE39 ], - [ 0xFE3B, 0xFE3B ], - [ 0xFE3D, 0xFE3D ], - [ 0xFE3F, 0xFE3F ], - [ 0xFE41, 0xFE41 ], - [ 0xFE43, 0xFE43 ], - [ 0xFE47, 0xFE47 ], - [ 0xFE59, 0xFE59 ], - [ 0xFE5B, 0xFE5B ], - [ 0xFE5D, 0xFE5D ], - [ 0xFF08, 0xFF08 ], - [ 0xFF3B, 0xFF3B ], - [ 0xFF5B, 0xFF5B ], - [ 0xFF5F, 0xFF5F ], - [ 0xFF62, 0xFF62 ], - ]; - - static immutable dchar[2][] tablePe = - [ - [ 0x0029, 0x0029 ], - [ 0x005D, 0x005D ], - [ 0x007D, 0x007D ], - [ 0x0F3B, 0x0F3B ], - [ 0x0F3D, 0x0F3D ], - [ 0x169C, 0x169C ], - [ 0x2046, 0x2046 ], - [ 0x207E, 0x207E ], - [ 0x208E, 0x208E ], - [ 0x232A, 0x232A ], - [ 0x2769, 0x2769 ], - [ 0x276B, 0x276B ], - [ 0x276D, 0x276D ], - [ 0x276F, 0x276F ], - [ 0x2771, 0x2771 ], - [ 0x2773, 0x2773 ], - [ 0x2775, 0x2775 ], - [ 0x27C6, 0x27C6 ], - [ 0x27E7, 0x27E7 ], - [ 0x27E9, 0x27E9 ], - [ 0x27EB, 0x27EB ], - [ 0x27ED, 0x27ED ], - [ 0x27EF, 0x27EF ], - [ 0x2984, 0x2984 ], - [ 0x2986, 0x2986 ], - [ 0x2988, 0x2988 ], - [ 0x298A, 0x298A ], - [ 0x298C, 0x298C ], - [ 0x298E, 0x298E ], - [ 0x2990, 0x2990 ], - [ 0x2992, 0x2992 ], - [ 0x2994, 0x2994 ], - [ 0x2996, 0x2996 ], - [ 0x2998, 0x2998 ], - [ 0x29D9, 0x29D9 ], - [ 0x29DB, 0x29DB ], - [ 0x29FD, 0x29FD ], - [ 0x2E23, 0x2E23 ], - [ 0x2E25, 0x2E25 ], - [ 0x2E27, 0x2E27 ], - [ 0x2E29, 0x2E29 ], - [ 0x3009, 0x3009 ], - [ 0x300B, 0x300B ], - [ 0x300D, 0x300D ], - [ 0x300F, 0x300F ], - [ 0x3011, 0x3011 ], - [ 0x3015, 0x3015 ], - [ 0x3017, 0x3017 ], - [ 0x3019, 0x3019 ], - [ 0x301B, 0x301B ], - [ 0x301E, 0x301F ], - [ 0xFD3F, 0xFD3F ], - [ 0xFE18, 0xFE18 ], - [ 0xFE36, 0xFE36 ], - [ 0xFE38, 0xFE38 ], - [ 0xFE3A, 0xFE3A ], - [ 0xFE3C, 0xFE3C ], - [ 0xFE3E, 0xFE3E ], - [ 0xFE40, 0xFE40 ], - [ 0xFE42, 0xFE42 ], - [ 0xFE44, 0xFE44 ], - [ 0xFE48, 0xFE48 ], - [ 0xFE5A, 0xFE5A ], - [ 0xFE5C, 0xFE5C ], - [ 0xFE5E, 0xFE5E ], - [ 0xFF09, 0xFF09 ], - [ 0xFF3D, 0xFF3D ], - [ 0xFF5D, 0xFF5D ], - [ 0xFF60, 0xFF60 ], - [ 0xFF63, 0xFF63 ], - ]; - - static immutable dchar[2][] tablePc = - [ - [ 0x005F, 0x005F ], - [ 0x203F, 0x2040 ], - [ 0x2054, 0x2054 ], - [ 0xFE33, 0xFE34 ], - [ 0xFE4D, 0xFE4F ], - [ 0xFF3F, 0xFF3F ], - ]; - - static immutable dchar[2][] tablePo = - [ - [ 0x0021, 0x0023 ], - [ 0x0025, 0x0027 ], - [ 0x002A, 0x002A ], - [ 0x002C, 0x002C ], - [ 0x002E, 0x002F ], - [ 0x003A, 0x003B ], - [ 0x003F, 0x0040 ], - [ 0x005C, 0x005C ], - [ 0x00A1, 0x00A1 ], - [ 0x00B7, 0x00B7 ], - [ 0x00BF, 0x00BF ], - [ 0x037E, 0x037E ], - [ 0x0387, 0x0387 ], - [ 0x055A, 0x055F ], - [ 0x0589, 0x0589 ], - [ 0x05C0, 0x05C0 ], - [ 0x05C3, 0x05C3 ], - [ 0x05C6, 0x05C6 ], - [ 0x05F3, 0x05F4 ], - [ 0x0609, 0x060A ], - [ 0x060C, 0x060D ], - [ 0x061B, 0x061B ], - [ 0x061E, 0x061F ], - [ 0x066A, 0x066D ], - [ 0x06D4, 0x06D4 ], - [ 0x0700, 0x070D ], - [ 0x07F7, 0x07F9 ], - [ 0x0830, 0x083E ], - [ 0x085E, 0x085E ], - [ 0x0964, 0x0965 ], - [ 0x0970, 0x0970 ], - [ 0x0DF4, 0x0DF4 ], - [ 0x0E4F, 0x0E4F ], - [ 0x0E5A, 0x0E5B ], - [ 0x0F04, 0x0F12 ], - [ 0x0F85, 0x0F85 ], - [ 0x0FD0, 0x0FD4 ], - [ 0x0FD9, 0x0FDA ], - [ 0x104A, 0x104F ], - [ 0x10FB, 0x10FB ], - [ 0x1361, 0x1368 ], - [ 0x166D, 0x166E ], - [ 0x16EB, 0x16ED ], - [ 0x1735, 0x1736 ], - [ 0x17D4, 0x17D6 ], - [ 0x17D8, 0x17DA ], - [ 0x1800, 0x1805 ], - [ 0x1807, 0x180A ], - [ 0x1944, 0x1945 ], - [ 0x1A1E, 0x1A1F ], - [ 0x1AA0, 0x1AA6 ], - [ 0x1AA8, 0x1AAD ], - [ 0x1B5A, 0x1B60 ], - [ 0x1BFC, 0x1BFF ], - [ 0x1C3B, 0x1C3F ], - [ 0x1C7E, 0x1C7F ], - [ 0x1CD3, 0x1CD3 ], - [ 0x2016, 0x2017 ], - [ 0x2020, 0x2027 ], - [ 0x2030, 0x2038 ], - [ 0x203B, 0x203E ], - [ 0x2041, 0x2043 ], - [ 0x2047, 0x2051 ], - [ 0x2053, 0x2053 ], - [ 0x2055, 0x205E ], - [ 0x2CF9, 0x2CFC ], - [ 0x2CFE, 0x2CFF ], - [ 0x2D70, 0x2D70 ], - [ 0x2E00, 0x2E01 ], - [ 0x2E06, 0x2E08 ], - [ 0x2E0B, 0x2E0B ], - [ 0x2E0E, 0x2E16 ], - [ 0x2E18, 0x2E19 ], - [ 0x2E1B, 0x2E1B ], - [ 0x2E1E, 0x2E1F ], - [ 0x2E2A, 0x2E2E ], - [ 0x2E30, 0x2E31 ], - [ 0x3001, 0x3003 ], - [ 0x303D, 0x303D ], - [ 0x30FB, 0x30FB ], - [ 0xA4FE, 0xA4FF ], - [ 0xA60D, 0xA60F ], - [ 0xA673, 0xA673 ], - [ 0xA67E, 0xA67E ], - [ 0xA6F2, 0xA6F7 ], - [ 0xA874, 0xA877 ], - [ 0xA8CE, 0xA8CF ], - [ 0xA8F8, 0xA8FA ], - [ 0xA92E, 0xA92F ], - [ 0xA95F, 0xA95F ], - [ 0xA9C1, 0xA9CD ], - [ 0xA9DE, 0xA9DF ], - [ 0xAA5C, 0xAA5F ], - [ 0xAADE, 0xAADF ], - [ 0xABEB, 0xABEB ], - [ 0xFE10, 0xFE16 ], - [ 0xFE19, 0xFE19 ], - [ 0xFE30, 0xFE30 ], - [ 0xFE45, 0xFE46 ], - [ 0xFE49, 0xFE4C ], - [ 0xFE50, 0xFE52 ], - [ 0xFE54, 0xFE57 ], - [ 0xFE5F, 0xFE61 ], - [ 0xFE68, 0xFE68 ], - [ 0xFE6A, 0xFE6B ], - [ 0xFF01, 0xFF03 ], - [ 0xFF05, 0xFF07 ], - [ 0xFF0A, 0xFF0A ], - [ 0xFF0C, 0xFF0C ], - [ 0xFF0E, 0xFF0F ], - [ 0xFF1A, 0xFF1B ], - [ 0xFF1F, 0xFF20 ], - [ 0xFF3C, 0xFF3C ], - [ 0xFF61, 0xFF61 ], - [ 0xFF64, 0xFF65 ], - [ 0x10100, 0x10101 ], - [ 0x1039F, 0x1039F ], - [ 0x103D0, 0x103D0 ], - [ 0x10857, 0x10857 ], - [ 0x1091F, 0x1091F ], - [ 0x1093F, 0x1093F ], - [ 0x10A50, 0x10A58 ], - [ 0x10A7F, 0x10A7F ], - [ 0x10B39, 0x10B3F ], - [ 0x11047, 0x1104D ], - [ 0x110BB, 0x110BC ], - [ 0x110BE, 0x110C1 ], - [ 0x12470, 0x12473 ], - ]; - - static immutable dchar[2][] tablePi = - [ - [ 0x00AB, 0x00AB ], - [ 0x2018, 0x2018 ], - [ 0x201B, 0x201C ], - [ 0x201F, 0x201F ], - [ 0x2039, 0x2039 ], - [ 0x2E02, 0x2E02 ], - [ 0x2E04, 0x2E04 ], - [ 0x2E09, 0x2E09 ], - [ 0x2E0C, 0x2E0C ], - [ 0x2E1C, 0x2E1C ], - [ 0x2E20, 0x2E20 ], - ]; - - static immutable dchar[2][] tablePf = - [ - [ 0x00BB, 0x00BB ], - [ 0x2019, 0x2019 ], - [ 0x201D, 0x201D ], - [ 0x203A, 0x203A ], - [ 0x2E03, 0x2E03 ], - [ 0x2E05, 0x2E05 ], - [ 0x2E0A, 0x2E0A ], - [ 0x2E0D, 0x2E0D ], - [ 0x2E1D, 0x2E1D ], - [ 0x2E21, 0x2E21 ], - ]; - - return binarySearch!tablePd(c) - || binarySearch!tablePs(c) - || binarySearch!tablePe(c) - || binarySearch!tablePc(c) - || binarySearch!tablePo(c) - || binarySearch!tablePi(c) - || binarySearch!tablePf(c); + return punctuationTrie[c]; } unittest @@ -1433,1052 +7482,305 @@ unittest assert(isPunctuation('\u005F')); assert(isPunctuation('\u00AB')); assert(isPunctuation('\u00BB')); + foreach(ch; unicode("P").byCodepoint) + assert(isPunctuation(ch)); } - /++ - Returns whether $(D c) is a Unicode symbol character - (general Unicode category: Sm, Sc, Sk, So) - - Standards: Unicode 6.0.0. - +/ -bool isSymbol(dchar c) @safe pure nothrow + Returns whether $(D c) is a Unicode symbol $(CHARACTER) + (general Unicode category: Sm, Sc, Sk, So). ++/ +@safe pure nothrow +bool isSymbol(dchar c) { - static immutable dchar[2][] tableSm = - [ - [ 0x002B, 0x002B ], - [ 0x003C, 0x003E ], - [ 0x007C, 0x007C ], - [ 0x007E, 0x007E ], - [ 0x00AC, 0x00AC ], - [ 0x00B1, 0x00B1 ], - [ 0x00D7, 0x00D7 ], - [ 0x00F7, 0x00F7 ], - [ 0x03F6, 0x03F6 ], - [ 0x0606, 0x0608 ], - [ 0x2044, 0x2044 ], - [ 0x2052, 0x2052 ], - [ 0x207A, 0x207C ], - [ 0x208A, 0x208C ], - [ 0x2118, 0x2118 ], - [ 0x2140, 0x2144 ], - [ 0x214B, 0x214B ], - [ 0x2190, 0x2194 ], - [ 0x219A, 0x219B ], - [ 0x21A0, 0x21A0 ], - [ 0x21A3, 0x21A3 ], - [ 0x21A6, 0x21A6 ], - [ 0x21AE, 0x21AE ], - [ 0x21CE, 0x21CF ], - [ 0x21D2, 0x21D2 ], - [ 0x21D4, 0x21D4 ], - [ 0x21F4, 0x22FF ], - [ 0x2308, 0x230B ], - [ 0x2320, 0x2321 ], - [ 0x237C, 0x237C ], - [ 0x239B, 0x23B3 ], - [ 0x23DC, 0x23E1 ], - [ 0x25B7, 0x25B7 ], - [ 0x25C1, 0x25C1 ], - [ 0x25F8, 0x25FF ], - [ 0x266F, 0x266F ], - [ 0x27C0, 0x27C4 ], - [ 0x27C7, 0x27CA ], - [ 0x27CC, 0x27CC ], - [ 0x27CE, 0x27E5 ], - [ 0x27F0, 0x27FF ], - [ 0x2900, 0x2982 ], - [ 0x2999, 0x29D7 ], - [ 0x29DC, 0x29FB ], - [ 0x29FE, 0x2AFF ], - [ 0x2B30, 0x2B44 ], - [ 0x2B47, 0x2B4C ], - [ 0xFB29, 0xFB29 ], - [ 0xFE62, 0xFE62 ], - [ 0xFE64, 0xFE66 ], - [ 0xFF0B, 0xFF0B ], - [ 0xFF1C, 0xFF1E ], - [ 0xFF5C, 0xFF5C ], - [ 0xFF5E, 0xFF5E ], - [ 0xFFE2, 0xFFE2 ], - [ 0xFFE9, 0xFFEC ], - [ 0x1D6C1, 0x1D6C1 ], - [ 0x1D6DB, 0x1D6DB ], - [ 0x1D6FB, 0x1D6FB ], - [ 0x1D715, 0x1D715 ], - [ 0x1D735, 0x1D735 ], - [ 0x1D74F, 0x1D74F ], - [ 0x1D76F, 0x1D76F ], - [ 0x1D789, 0x1D789 ], - [ 0x1D7A9, 0x1D7A9 ], - [ 0x1D7C3, 0x1D7C3 ], - ]; - - static immutable dchar[2][] tableSc = - [ - [ 0x0024, 0x0024 ], - [ 0x00A2, 0x00A5 ], - [ 0x060B, 0x060B ], - [ 0x09F2, 0x09F3 ], - [ 0x09FB, 0x09FB ], - [ 0x0AF1, 0x0AF1 ], - [ 0x0BF9, 0x0BF9 ], - [ 0x0E3F, 0x0E3F ], - [ 0x17DB, 0x17DB ], - [ 0x20A0, 0x20B9 ], - [ 0xA838, 0xA838 ], - [ 0xFDFC, 0xFDFC ], - [ 0xFE69, 0xFE69 ], - [ 0xFF04, 0xFF04 ], - [ 0xFFE0, 0xFFE1 ], - [ 0xFFE5, 0xFFE6 ], - ]; - - static immutable dchar[2][] tableSk = - [ - [ 0x005E, 0x005E ], - [ 0x0060, 0x0060 ], - [ 0x00A8, 0x00A8 ], - [ 0x00AF, 0x00AF ], - [ 0x00B4, 0x00B4 ], - [ 0x00B8, 0x00B8 ], - [ 0x02C2, 0x02C5 ], - [ 0x02D2, 0x02DF ], - [ 0x02E5, 0x02EB ], - [ 0x02ED, 0x02ED ], - [ 0x02EF, 0x02FF ], - [ 0x0375, 0x0375 ], - [ 0x0384, 0x0385 ], - [ 0x1FBD, 0x1FBD ], - [ 0x1FBF, 0x1FC1 ], - [ 0x1FCD, 0x1FCF ], - [ 0x1FDD, 0x1FDF ], - [ 0x1FED, 0x1FEF ], - [ 0x1FFD, 0x1FFE ], - [ 0x309B, 0x309C ], - [ 0xA700, 0xA716 ], - [ 0xA720, 0xA721 ], - [ 0xA789, 0xA78A ], - [ 0xFBB2, 0xFBC1 ], - [ 0xFF3E, 0xFF3E ], - [ 0xFF40, 0xFF40 ], - [ 0xFFE3, 0xFFE3 ], - ]; - - static immutable dchar[2][] tableSo = - [ - [ 0x00A6, 0x00A7 ], - [ 0x00A9, 0x00A9 ], - [ 0x00AE, 0x00AE ], - [ 0x00B0, 0x00B0 ], - [ 0x00B6, 0x00B6 ], - [ 0x0482, 0x0482 ], - [ 0x060E, 0x060F ], - [ 0x06DE, 0x06DE ], - [ 0x06E9, 0x06E9 ], - [ 0x06FD, 0x06FE ], - [ 0x07F6, 0x07F6 ], - [ 0x09FA, 0x09FA ], - [ 0x0B70, 0x0B70 ], - [ 0x0BF3, 0x0BF8 ], - [ 0x0BFA, 0x0BFA ], - [ 0x0C7F, 0x0C7F ], - [ 0x0D79, 0x0D79 ], - [ 0x0F01, 0x0F03 ], - [ 0x0F13, 0x0F17 ], - [ 0x0F1A, 0x0F1F ], - [ 0x0F34, 0x0F34 ], - [ 0x0F36, 0x0F36 ], - [ 0x0F38, 0x0F38 ], - [ 0x0FBE, 0x0FC5 ], - [ 0x0FC7, 0x0FCC ], - [ 0x0FCE, 0x0FCF ], - [ 0x0FD5, 0x0FD8 ], - [ 0x109E, 0x109F ], - [ 0x1360, 0x1360 ], - [ 0x1390, 0x1399 ], - [ 0x1940, 0x1940 ], - [ 0x19DE, 0x19FF ], - [ 0x1B61, 0x1B6A ], - [ 0x1B74, 0x1B7C ], - [ 0x2100, 0x2101 ], - [ 0x2103, 0x2106 ], - [ 0x2108, 0x2109 ], - [ 0x2114, 0x2114 ], - [ 0x2116, 0x2117 ], - [ 0x211E, 0x2123 ], - [ 0x2125, 0x2125 ], - [ 0x2127, 0x2127 ], - [ 0x2129, 0x2129 ], - [ 0x212E, 0x212E ], - [ 0x213A, 0x213B ], - [ 0x214A, 0x214A ], - [ 0x214C, 0x214D ], - [ 0x214F, 0x214F ], - [ 0x2195, 0x2199 ], - [ 0x219C, 0x219F ], - [ 0x21A1, 0x21A2 ], - [ 0x21A4, 0x21A5 ], - [ 0x21A7, 0x21AD ], - [ 0x21AF, 0x21CD ], - [ 0x21D0, 0x21D1 ], - [ 0x21D3, 0x21D3 ], - [ 0x21D5, 0x21F3 ], - [ 0x2300, 0x2307 ], - [ 0x230C, 0x231F ], - [ 0x2322, 0x2328 ], - [ 0x232B, 0x237B ], - [ 0x237D, 0x239A ], - [ 0x23B4, 0x23DB ], - [ 0x23E2, 0x23F3 ], - [ 0x2400, 0x2426 ], - [ 0x2440, 0x244A ], - [ 0x249C, 0x24E9 ], - [ 0x2500, 0x25B6 ], - [ 0x25B8, 0x25C0 ], - [ 0x25C2, 0x25F7 ], - [ 0x2600, 0x266E ], - [ 0x2670, 0x26FF ], - [ 0x2701, 0x2767 ], - [ 0x2794, 0x27BF ], - [ 0x2800, 0x28FF ], - [ 0x2B00, 0x2B2F ], - [ 0x2B45, 0x2B46 ], - [ 0x2B50, 0x2B59 ], - [ 0x2CE5, 0x2CEA ], - [ 0x2E80, 0x2E99 ], - [ 0x2E9B, 0x2EF3 ], - [ 0x2F00, 0x2FD5 ], - [ 0x2FF0, 0x2FFB ], - [ 0x3004, 0x3004 ], - [ 0x3012, 0x3013 ], - [ 0x3020, 0x3020 ], - [ 0x3036, 0x3037 ], - [ 0x303E, 0x303F ], - [ 0x3190, 0x3191 ], - [ 0x3196, 0x319F ], - [ 0x31C0, 0x31E3 ], - [ 0x3200, 0x321E ], - [ 0x322A, 0x3250 ], - [ 0x3260, 0x327F ], - [ 0x328A, 0x32B0 ], - [ 0x32C0, 0x32FE ], - [ 0x3300, 0x33FF ], - [ 0x4DC0, 0x4DFF ], - [ 0xA490, 0xA4C6 ], - [ 0xA828, 0xA82B ], - [ 0xA836, 0xA837 ], - [ 0xA839, 0xA839 ], - [ 0xAA77, 0xAA79 ], - [ 0xFDFD, 0xFDFD ], - [ 0xFFE4, 0xFFE4 ], - [ 0xFFE8, 0xFFE8 ], - [ 0xFFED, 0xFFEE ], - [ 0xFFFC, 0xFFFD ], - [ 0x10102, 0x10102 ], - [ 0x10137, 0x1013F ], - [ 0x10179, 0x10189 ], - [ 0x10190, 0x1019B ], - [ 0x101D0, 0x101FC ], - [ 0x1D000, 0x1D0F5 ], - [ 0x1D100, 0x1D126 ], - [ 0x1D129, 0x1D164 ], - [ 0x1D16A, 0x1D16C ], - [ 0x1D183, 0x1D184 ], - [ 0x1D18C, 0x1D1A9 ], - [ 0x1D1AE, 0x1D1DD ], - [ 0x1D200, 0x1D241 ], - [ 0x1D245, 0x1D245 ], - [ 0x1D300, 0x1D356 ], - [ 0x1F000, 0x1F02B ], - [ 0x1F030, 0x1F093 ], - [ 0x1F0A0, 0x1F0AE ], - [ 0x1F0B1, 0x1F0BE ], - [ 0x1F0C1, 0x1F0CF ], - [ 0x1F0D1, 0x1F0DF ], - [ 0x1F110, 0x1F12E ], - [ 0x1F130, 0x1F169 ], - [ 0x1F170, 0x1F19A ], - [ 0x1F1E6, 0x1F202 ], - [ 0x1F210, 0x1F23A ], - [ 0x1F240, 0x1F248 ], - [ 0x1F250, 0x1F251 ], - [ 0x1F300, 0x1F320 ], - [ 0x1F330, 0x1F335 ], - [ 0x1F337, 0x1F37C ], - [ 0x1F380, 0x1F393 ], - [ 0x1F3A0, 0x1F3C4 ], - [ 0x1F3C6, 0x1F3CA ], - [ 0x1F3E0, 0x1F3F0 ], - [ 0x1F400, 0x1F43E ], - [ 0x1F440, 0x1F440 ], - [ 0x1F442, 0x1F4F7 ], - [ 0x1F4F9, 0x1F4FC ], - [ 0x1F500, 0x1F53D ], - [ 0x1F550, 0x1F567 ], - [ 0x1F5FB, 0x1F5FF ], - [ 0x1F601, 0x1F610 ], - [ 0x1F612, 0x1F614 ], - [ 0x1F616, 0x1F616 ], - [ 0x1F618, 0x1F618 ], - [ 0x1F61A, 0x1F61A ], - [ 0x1F61C, 0x1F61E ], - [ 0x1F620, 0x1F625 ], - [ 0x1F628, 0x1F62B ], - [ 0x1F62D, 0x1F62D ], - [ 0x1F630, 0x1F633 ], - [ 0x1F635, 0x1F640 ], - [ 0x1F645, 0x1F64F ], - [ 0x1F680, 0x1F6C5 ], - [ 0x1F700, 0x1F773 ], - ]; - - return binarySearch!tableSm(c) - || binarySearch!tableSc(c) - || binarySearch!tableSk(c) - || binarySearch!tableSo(c); + return symbolTrie[c]; } unittest { + import std.string; assert(isSymbol('\u0024')); assert(isSymbol('\u002B')); assert(isSymbol('\u005E')); assert(isSymbol('\u00A6')); + foreach(ch; unicode("S").byCodepoint) + assert(isSymbol(ch), format("%04x", ch)); } - /++ - Returns whether $(D c) is a Unicode whitespace character + Returns whether $(D c) is a Unicode space $(CHARACTER) (general Unicode category: Zs) - - Standards: Unicode 6.0.0. - +/ -bool isSpace(dchar c) @safe pure nothrow + Note: This doesn't include '\n', '\r', \t' and other non-space $(CHARACTER). + For commonly used less strict semantics see $(LREF isWhite). ++/ +@safe pure nothrow +bool isSpace(dchar c) { - return (c == 0x0020 || - c == 0x00A0 || c == 0x1680 || c == 0x180E || - (0x2000 <= c && c <= 0x200A) || - c == 0x202F || c == 0x205F || c == 0x3000); + return isSpaceGen(c); } unittest { assert(isSpace('\u0020')); + auto space = unicode.Zs; + foreach(ch; space.byCodepoint) + assert(isSpace(ch)); + foreach(ch; 0..0x1000) + assert(isSpace(ch) == space[ch]); } /++ - Returns whether $(D c) is a Unicode graphical character + Returns whether $(D c) is a Unicode graphical $(CHARACTER) (general Unicode category: L, M, N, P, S, Zs). - Standards: Unicode 6.0.0. - +/ - -bool isGraphical(dchar c) @safe pure nothrow ++/ +@safe pure nothrow +bool isGraphical(dchar c) { - return isAlpha(c) || isNumber(c) || isSpace(c) - || isMark(c) || isPunctuation(c) || isSymbol(c); + return graphicalTrie[c]; } + unittest { + auto set = unicode("Graphical"); + import std.string; + foreach(ch; set.byCodepoint) + assert(isGraphical(ch), format("%4x", ch)); + foreach(ch; 0..0x4000) + assert((ch in set) == isGraphical(ch)); } /++ - Returns whether $(D c) is a Unicode control character - (general Unicode category: Cc) - - Standards: Unicode 6.0.0. - +/ - -bool isControl(dchar c) @safe pure nothrow + Returns whether $(D c) is a Unicode control $(CHARACTER) + (general Unicode category: Cc). ++/ +@safe pure nothrow +bool isControl(dchar c) { - return (c <= 0x1F || (0x80 <= c && c <= 0x9F)); + return isControlGen(c); } unittest { assert(isControl('\u0000')); + assert(isControl('\u0081')); + assert(!isControl('\u0100')); + auto cc = unicode.Cc; + foreach(ch; cc.byCodepoint) + assert(isControl(ch)); + foreach(ch; 0..0x1000) + assert(isControl(ch) == cc[ch]); } /++ - Returns whether $(D c) is a Unicode formatting character - (general Unicode category: Cf) - - Standards: Unicode 6.0.0. - +/ -bool isFormat(dchar c) @safe pure nothrow + Returns whether $(D c) is a Unicode formatting $(CHARACTER) + (general Unicode category: Cf). ++/ +@safe pure nothrow +bool isFormat(dchar c) { - static immutable dchar[2][] tableCf = - [ - [ 0x00AD, 0x00AD ], - [ 0x0600, 0x0603 ], - [ 0x06DD, 0x06DD ], - [ 0x070F, 0x070F ], - [ 0x17B4, 0x17B5 ], - [ 0x200B, 0x200F ], - [ 0x202A, 0x202E ], - [ 0x2060, 0x2064 ], - [ 0x206A, 0x206F ], - [ 0xFEFF, 0xFEFF ], - [ 0xFFF9, 0xFFFB ], - [ 0x110BD, 0x110BD ], - [ 0x1D173, 0x1D17A ], - [ 0xE0001, 0xE0001 ], - [ 0xE0020, 0xE007F ], - ]; - - return binarySearch!tableCf(c); + return isFormatGen(c); } + unittest { assert(isFormat('\u00AD')); + foreach(ch; unicode("Format").byCodepoint) + assert(isFormat(ch)); } +// code points for private use, surrogates are not likely to change in near feature +// if need be they can be generated from unicode data as well /++ - Returns whether $(D c) is a Unicode Private Use character - (general Unicode category: Co) - - Standards: Unicode 6.0.0. - +/ -bool isPrivateUse(dchar c) @safe pure nothrow + Returns whether $(D c) is a Unicode Private Use $(CODEPOINT) + (general Unicode category: Co). ++/ +@safe pure nothrow +bool isPrivateUse(dchar c) { return (0x00_E000 <= c && c <= 0x00_F8FF) || (0x0F_0000 <= c && c <= 0x0F_FFFD) || (0x10_0000 <= c && c <= 0x10_FFFD); } - -unittest -{ -} - - /++ - Returns whether $(D c) is a Unicode surrogate character - (general Unicode category: Cs) - - Standards: Unicode 6.0.0. - +/ -bool isSurrogate(dchar c) @safe pure nothrow + Returns whether $(D c) is a Unicode surrogate $(CODEPOINT) + (general Unicode category: Cs). ++/ +@safe pure nothrow +bool isSurrogate(dchar c) { return (0xD800 <= c && c <= 0xDFFF); } /++ Returns whether $(D c) is a Unicode high surrogate (lead surrogate). - - Standards: Unicode 2.0. - +/ -bool isSurrogateHi(dchar c) @safe pure nothrow ++/ +@safe pure nothrow +bool isSurrogateHi(dchar c) { return (0xD800 <= c && c <= 0xDBFF); } /++ Returns whether $(D c) is a Unicode low surrogate (trail surrogate). - - Standards: Unicode 2.0. - +/ -bool isSurrogateLo(dchar c) @safe pure nothrow ++/ +@safe pure nothrow +bool isSurrogateLo(dchar c) { return (0xDC00 <= c && c <= 0xDFFF); } -unittest -{ -} - - /++ - Returns whether $(D c) is a Unicode non-character + Returns whether $(D c) is a Unicode non-character i.e. + a $(CODEPOINT) with no assigned abstract character. (general Unicode category: Cn) - - Standards: Unicode 6.0.0. - +/ -bool isNonCharacter(dchar c) @safe pure nothrow ++/ +@safe pure nothrow +bool isNonCharacter(dchar c) { - static immutable dchar[2][] table = - [ - [ 0x0378, 0x0379 ], - [ 0x037F, 0x0383 ], - [ 0x038B, 0x038B ], - [ 0x038D, 0x038D ], - [ 0x03A2, 0x03A2 ], - [ 0x0528, 0x0530 ], - [ 0x0557, 0x0558 ], - [ 0x0560, 0x0560 ], - [ 0x0588, 0x0588 ], - [ 0x058B, 0x0590 ], - [ 0x05C8, 0x05CF ], - [ 0x05EB, 0x05EF ], - [ 0x05F5, 0x05FF ], - [ 0x0604, 0x0605 ], - [ 0x061C, 0x061D ], - [ 0x070E, 0x070E ], - [ 0x074B, 0x074C ], - [ 0x07B2, 0x07BF ], - [ 0x07FB, 0x07FF ], - [ 0x082E, 0x082F ], - [ 0x083F, 0x083F ], - [ 0x085C, 0x085D ], - [ 0x085F, 0x08FF ], - [ 0x0978, 0x0978 ], - [ 0x0980, 0x0980 ], - [ 0x0984, 0x0984 ], - [ 0x098D, 0x098E ], - [ 0x0991, 0x0992 ], - [ 0x09A9, 0x09A9 ], - [ 0x09B1, 0x09B1 ], - [ 0x09B3, 0x09B5 ], - [ 0x09BA, 0x09BB ], - [ 0x09C5, 0x09C6 ], - [ 0x09C9, 0x09CA ], - [ 0x09CF, 0x09D6 ], - [ 0x09D8, 0x09DB ], - [ 0x09DE, 0x09DE ], - [ 0x09E4, 0x09E5 ], - [ 0x09FC, 0x0A00 ], - [ 0x0A04, 0x0A04 ], - [ 0x0A0B, 0x0A0E ], - [ 0x0A11, 0x0A12 ], - [ 0x0A29, 0x0A29 ], - [ 0x0A31, 0x0A31 ], - [ 0x0A34, 0x0A34 ], - [ 0x0A37, 0x0A37 ], - [ 0x0A3A, 0x0A3B ], - [ 0x0A3D, 0x0A3D ], - [ 0x0A43, 0x0A46 ], - [ 0x0A49, 0x0A4A ], - [ 0x0A4E, 0x0A50 ], - [ 0x0A52, 0x0A58 ], - [ 0x0A5D, 0x0A5D ], - [ 0x0A5F, 0x0A65 ], - [ 0x0A76, 0x0A80 ], - [ 0x0A84, 0x0A84 ], - [ 0x0A8E, 0x0A8E ], - [ 0x0A92, 0x0A92 ], - [ 0x0AA9, 0x0AA9 ], - [ 0x0AB1, 0x0AB1 ], - [ 0x0AB4, 0x0AB4 ], - [ 0x0ABA, 0x0ABB ], - [ 0x0AC6, 0x0AC6 ], - [ 0x0ACA, 0x0ACA ], - [ 0x0ACE, 0x0ACF ], - [ 0x0AD1, 0x0ADF ], - [ 0x0AE4, 0x0AE5 ], - [ 0x0AF0, 0x0AF0 ], - [ 0x0AF2, 0x0B00 ], - [ 0x0B04, 0x0B04 ], - [ 0x0B0D, 0x0B0E ], - [ 0x0B11, 0x0B12 ], - [ 0x0B29, 0x0B29 ], - [ 0x0B31, 0x0B31 ], - [ 0x0B34, 0x0B34 ], - [ 0x0B3A, 0x0B3B ], - [ 0x0B45, 0x0B46 ], - [ 0x0B49, 0x0B4A ], - [ 0x0B4E, 0x0B55 ], - [ 0x0B58, 0x0B5B ], - [ 0x0B5E, 0x0B5E ], - [ 0x0B64, 0x0B65 ], - [ 0x0B78, 0x0B81 ], - [ 0x0B84, 0x0B84 ], - [ 0x0B8B, 0x0B8D ], - [ 0x0B91, 0x0B91 ], - [ 0x0B96, 0x0B98 ], - [ 0x0B9B, 0x0B9B ], - [ 0x0B9D, 0x0B9D ], - [ 0x0BA0, 0x0BA2 ], - [ 0x0BA5, 0x0BA7 ], - [ 0x0BAB, 0x0BAD ], - [ 0x0BBA, 0x0BBD ], - [ 0x0BC3, 0x0BC5 ], - [ 0x0BC9, 0x0BC9 ], - [ 0x0BCE, 0x0BCF ], - [ 0x0BD1, 0x0BD6 ], - [ 0x0BD8, 0x0BE5 ], - [ 0x0BFB, 0x0C00 ], - [ 0x0C04, 0x0C04 ], - [ 0x0C0D, 0x0C0D ], - [ 0x0C11, 0x0C11 ], - [ 0x0C29, 0x0C29 ], - [ 0x0C34, 0x0C34 ], - [ 0x0C3A, 0x0C3C ], - [ 0x0C45, 0x0C45 ], - [ 0x0C49, 0x0C49 ], - [ 0x0C4E, 0x0C54 ], - [ 0x0C57, 0x0C57 ], - [ 0x0C5A, 0x0C5F ], - [ 0x0C64, 0x0C65 ], - [ 0x0C70, 0x0C77 ], - [ 0x0C80, 0x0C81 ], - [ 0x0C84, 0x0C84 ], - [ 0x0C8D, 0x0C8D ], - [ 0x0C91, 0x0C91 ], - [ 0x0CA9, 0x0CA9 ], - [ 0x0CB4, 0x0CB4 ], - [ 0x0CBA, 0x0CBB ], - [ 0x0CC5, 0x0CC5 ], - [ 0x0CC9, 0x0CC9 ], - [ 0x0CCE, 0x0CD4 ], - [ 0x0CD7, 0x0CDD ], - [ 0x0CDF, 0x0CDF ], - [ 0x0CE4, 0x0CE5 ], - [ 0x0CF0, 0x0CF0 ], - [ 0x0CF3, 0x0D01 ], - [ 0x0D04, 0x0D04 ], - [ 0x0D0D, 0x0D0D ], - [ 0x0D11, 0x0D11 ], - [ 0x0D3B, 0x0D3C ], - [ 0x0D45, 0x0D45 ], - [ 0x0D49, 0x0D49 ], - [ 0x0D4F, 0x0D56 ], - [ 0x0D58, 0x0D5F ], - [ 0x0D64, 0x0D65 ], - [ 0x0D76, 0x0D78 ], - [ 0x0D80, 0x0D81 ], - [ 0x0D84, 0x0D84 ], - [ 0x0D97, 0x0D99 ], - [ 0x0DB2, 0x0DB2 ], - [ 0x0DBC, 0x0DBC ], - [ 0x0DBE, 0x0DBF ], - [ 0x0DC7, 0x0DC9 ], - [ 0x0DCB, 0x0DCE ], - [ 0x0DD5, 0x0DD5 ], - [ 0x0DD7, 0x0DD7 ], - [ 0x0DE0, 0x0DF1 ], - [ 0x0DF5, 0x0E00 ], - [ 0x0E3B, 0x0E3E ], - [ 0x0E5C, 0x0E80 ], - [ 0x0E83, 0x0E83 ], - [ 0x0E85, 0x0E86 ], - [ 0x0E89, 0x0E89 ], - [ 0x0E8B, 0x0E8C ], - [ 0x0E8E, 0x0E93 ], - [ 0x0E98, 0x0E98 ], - [ 0x0EA0, 0x0EA0 ], - [ 0x0EA4, 0x0EA4 ], - [ 0x0EA6, 0x0EA6 ], - [ 0x0EA8, 0x0EA9 ], - [ 0x0EAC, 0x0EAC ], - [ 0x0EBA, 0x0EBA ], - [ 0x0EBE, 0x0EBF ], - [ 0x0EC5, 0x0EC5 ], - [ 0x0EC7, 0x0EC7 ], - [ 0x0ECE, 0x0ECF ], - [ 0x0EDA, 0x0EDB ], - [ 0x0EDE, 0x0EFF ], - [ 0x0F48, 0x0F48 ], - [ 0x0F6D, 0x0F70 ], - [ 0x0F98, 0x0F98 ], - [ 0x0FBD, 0x0FBD ], - [ 0x0FCD, 0x0FCD ], - [ 0x0FDB, 0x0FFF ], - [ 0x10C6, 0x10CF ], - [ 0x10FD, 0x10FF ], - [ 0x1249, 0x1249 ], - [ 0x124E, 0x124F ], - [ 0x1257, 0x1257 ], - [ 0x1259, 0x1259 ], - [ 0x125E, 0x125F ], - [ 0x1289, 0x1289 ], - [ 0x128E, 0x128F ], - [ 0x12B1, 0x12B1 ], - [ 0x12B6, 0x12B7 ], - [ 0x12BF, 0x12BF ], - [ 0x12C1, 0x12C1 ], - [ 0x12C6, 0x12C7 ], - [ 0x12D7, 0x12D7 ], - [ 0x1311, 0x1311 ], - [ 0x1316, 0x1317 ], - [ 0x135B, 0x135C ], - [ 0x137D, 0x137F ], - [ 0x139A, 0x139F ], - [ 0x13F5, 0x13FF ], - [ 0x169D, 0x169F ], - [ 0x16F1, 0x16FF ], - [ 0x170D, 0x170D ], - [ 0x1715, 0x171F ], - [ 0x1737, 0x173F ], - [ 0x1754, 0x175F ], - [ 0x176D, 0x176D ], - [ 0x1771, 0x1771 ], - [ 0x1774, 0x177F ], - [ 0x17DE, 0x17DF ], - [ 0x17EA, 0x17EF ], - [ 0x17FA, 0x17FF ], - [ 0x180F, 0x180F ], - [ 0x181A, 0x181F ], - [ 0x1878, 0x187F ], - [ 0x18AB, 0x18AF ], - [ 0x18F6, 0x18FF ], - [ 0x191D, 0x191F ], - [ 0x192C, 0x192F ], - [ 0x193C, 0x193F ], - [ 0x1941, 0x1943 ], - [ 0x196E, 0x196F ], - [ 0x1975, 0x197F ], - [ 0x19AC, 0x19AF ], - [ 0x19CA, 0x19CF ], - [ 0x19DB, 0x19DD ], - [ 0x1A1C, 0x1A1D ], - [ 0x1A5F, 0x1A5F ], - [ 0x1A7D, 0x1A7E ], - [ 0x1A8A, 0x1A8F ], - [ 0x1A9A, 0x1A9F ], - [ 0x1AAE, 0x1AFF ], - [ 0x1B4C, 0x1B4F ], - [ 0x1B7D, 0x1B7F ], - [ 0x1BAB, 0x1BAD ], - [ 0x1BBA, 0x1BBF ], - [ 0x1BF4, 0x1BFB ], - [ 0x1C38, 0x1C3A ], - [ 0x1C4A, 0x1C4C ], - [ 0x1C80, 0x1CCF ], - [ 0x1CF3, 0x1CFF ], - [ 0x1DE7, 0x1DFB ], - [ 0x1F16, 0x1F17 ], - [ 0x1F1E, 0x1F1F ], - [ 0x1F46, 0x1F47 ], - [ 0x1F4E, 0x1F4F ], - [ 0x1F58, 0x1F58 ], - [ 0x1F5A, 0x1F5A ], - [ 0x1F5C, 0x1F5C ], - [ 0x1F5E, 0x1F5E ], - [ 0x1F7E, 0x1F7F ], - [ 0x1FB5, 0x1FB5 ], - [ 0x1FC5, 0x1FC5 ], - [ 0x1FD4, 0x1FD5 ], - [ 0x1FDC, 0x1FDC ], - [ 0x1FF0, 0x1FF1 ], - [ 0x1FF5, 0x1FF5 ], - [ 0x1FFF, 0x1FFF ], - [ 0x2065, 0x2069 ], - [ 0x2072, 0x2073 ], - [ 0x208F, 0x208F ], - [ 0x209D, 0x209F ], - [ 0x20BA, 0x20CF ], - [ 0x20F1, 0x20FF ], - [ 0x218A, 0x218F ], - [ 0x23F4, 0x23FF ], - [ 0x2427, 0x243F ], - [ 0x244B, 0x245F ], - [ 0x2700, 0x2700 ], - [ 0x27CB, 0x27CB ], - [ 0x27CD, 0x27CD ], - [ 0x2B4D, 0x2B4F ], - [ 0x2B5A, 0x2BFF ], - [ 0x2C2F, 0x2C2F ], - [ 0x2C5F, 0x2C5F ], - [ 0x2CF2, 0x2CF8 ], - [ 0x2D26, 0x2D2F ], - [ 0x2D66, 0x2D6E ], - [ 0x2D71, 0x2D7E ], - [ 0x2D97, 0x2D9F ], - [ 0x2DA7, 0x2DA7 ], - [ 0x2DAF, 0x2DAF ], - [ 0x2DB7, 0x2DB7 ], - [ 0x2DBF, 0x2DBF ], - [ 0x2DC7, 0x2DC7 ], - [ 0x2DCF, 0x2DCF ], - [ 0x2DD7, 0x2DD7 ], - [ 0x2DDF, 0x2DDF ], - [ 0x2E32, 0x2E7F ], - [ 0x2E9A, 0x2E9A ], - [ 0x2EF4, 0x2EFF ], - [ 0x2FD6, 0x2FEF ], - [ 0x2FFC, 0x2FFF ], - [ 0x3040, 0x3040 ], - [ 0x3097, 0x3098 ], - [ 0x3100, 0x3104 ], - [ 0x312E, 0x3130 ], - [ 0x318F, 0x318F ], - [ 0x31BB, 0x31BF ], - [ 0x31E4, 0x31EF ], - [ 0x321F, 0x321F ], - [ 0x32FF, 0x32FF ], - [ 0x4DB6, 0x4DBF ], - [ 0x9FCC, 0x9FFF ], - [ 0xA48D, 0xA48F ], - [ 0xA4C7, 0xA4CF ], - [ 0xA62C, 0xA63F ], - [ 0xA674, 0xA67B ], - [ 0xA698, 0xA69F ], - [ 0xA6F8, 0xA6FF ], - [ 0xA78F, 0xA78F ], - [ 0xA792, 0xA79F ], - [ 0xA7AA, 0xA7F9 ], - [ 0xA82C, 0xA82F ], - [ 0xA83A, 0xA83F ], - [ 0xA878, 0xA87F ], - [ 0xA8C5, 0xA8CD ], - [ 0xA8DA, 0xA8DF ], - [ 0xA8FC, 0xA8FF ], - [ 0xA954, 0xA95E ], - [ 0xA97D, 0xA97F ], - [ 0xA9CE, 0xA9CE ], - [ 0xA9DA, 0xA9DD ], - [ 0xA9E0, 0xA9FF ], - [ 0xAA37, 0xAA3F ], - [ 0xAA4E, 0xAA4F ], - [ 0xAA5A, 0xAA5B ], - [ 0xAA7C, 0xAA7F ], - [ 0xAAC3, 0xAADA ], - [ 0xAAE0, 0xAB00 ], - [ 0xAB07, 0xAB08 ], - [ 0xAB0F, 0xAB10 ], - [ 0xAB17, 0xAB1F ], - [ 0xAB27, 0xAB27 ], - [ 0xAB2F, 0xABBF ], - [ 0xABEE, 0xABEF ], - [ 0xABFA, 0xABFF ], - [ 0xD7A4, 0xD7AF ], - [ 0xD7C7, 0xD7CA ], - [ 0xD7FC, 0xD7FF ], - [ 0xFA2E, 0xFA2F ], - [ 0xFA6E, 0xFA6F ], - [ 0xFADA, 0xFAFF ], - [ 0xFB07, 0xFB12 ], - [ 0xFB18, 0xFB1C ], - [ 0xFB37, 0xFB37 ], - [ 0xFB3D, 0xFB3D ], - [ 0xFB3F, 0xFB3F ], - [ 0xFB42, 0xFB42 ], - [ 0xFB45, 0xFB45 ], - [ 0xFBC2, 0xFBD2 ], - [ 0xFD40, 0xFD4F ], - [ 0xFD90, 0xFD91 ], - [ 0xFDC8, 0xFDEF ], - [ 0xFDFE, 0xFDFF ], - [ 0xFE1A, 0xFE1F ], - [ 0xFE27, 0xFE2F ], - [ 0xFE53, 0xFE53 ], - [ 0xFE67, 0xFE67 ], - [ 0xFE6C, 0xFE6F ], - [ 0xFE75, 0xFE75 ], - [ 0xFEFD, 0xFEFE ], - [ 0xFF00, 0xFF00 ], - [ 0xFFBF, 0xFFC1 ], - [ 0xFFC8, 0xFFC9 ], - [ 0xFFD0, 0xFFD1 ], - [ 0xFFD8, 0xFFD9 ], - [ 0xFFDD, 0xFFDF ], - [ 0xFFE7, 0xFFE7 ], - [ 0xFFEF, 0xFFF8 ], - [ 0xFFFE, 0xFFFF ], - [ 0x1000C, 0x1000C ], - [ 0x10027, 0x10027 ], - [ 0x1003B, 0x1003B ], - [ 0x1003E, 0x1003E ], - [ 0x1004E, 0x1004F ], - [ 0x1005E, 0x1007F ], - [ 0x100FB, 0x100FF ], - [ 0x10103, 0x10106 ], - [ 0x10134, 0x10136 ], - [ 0x1018B, 0x1018F ], - [ 0x1019C, 0x101CF ], - [ 0x101FE, 0x1027F ], - [ 0x1029D, 0x1029F ], - [ 0x102D1, 0x102FF ], - [ 0x1031F, 0x1031F ], - [ 0x10324, 0x1032F ], - [ 0x1034B, 0x1037F ], - [ 0x1039E, 0x1039E ], - [ 0x103C4, 0x103C7 ], - [ 0x103D6, 0x103FF ], - [ 0x1049E, 0x1049F ], - [ 0x104AA, 0x107FF ], - [ 0x10806, 0x10807 ], - [ 0x10809, 0x10809 ], - [ 0x10836, 0x10836 ], - [ 0x10839, 0x1083B ], - [ 0x1083D, 0x1083E ], - [ 0x10856, 0x10856 ], - [ 0x10860, 0x108FF ], - [ 0x1091C, 0x1091E ], - [ 0x1093A, 0x1093E ], - [ 0x10940, 0x109FF ], - [ 0x10A04, 0x10A04 ], - [ 0x10A07, 0x10A0B ], - [ 0x10A14, 0x10A14 ], - [ 0x10A18, 0x10A18 ], - [ 0x10A34, 0x10A37 ], - [ 0x10A3B, 0x10A3E ], - [ 0x10A48, 0x10A4F ], - [ 0x10A59, 0x10A5F ], - [ 0x10A80, 0x10AFF ], - [ 0x10B36, 0x10B38 ], - [ 0x10B56, 0x10B57 ], - [ 0x10B73, 0x10B77 ], - [ 0x10B80, 0x10BFF ], - [ 0x10C49, 0x10E5F ], - [ 0x10E7F, 0x10FFF ], - [ 0x1104E, 0x11051 ], - [ 0x11070, 0x1107F ], - [ 0x110C2, 0x11FFF ], - [ 0x1236F, 0x123FF ], - [ 0x12463, 0x1246F ], - [ 0x12474, 0x12FFF ], - [ 0x1342F, 0x167FF ], - [ 0x16A39, 0x1AFFF ], - [ 0x1B002, 0x1CFFF ], - [ 0x1D0F6, 0x1D0FF ], - [ 0x1D127, 0x1D128 ], - [ 0x1D1DE, 0x1D1FF ], - [ 0x1D246, 0x1D2FF ], - [ 0x1D357, 0x1D35F ], - [ 0x1D372, 0x1D3FF ], - [ 0x1D455, 0x1D455 ], - [ 0x1D49D, 0x1D49D ], - [ 0x1D4A0, 0x1D4A1 ], - [ 0x1D4A3, 0x1D4A4 ], - [ 0x1D4A7, 0x1D4A8 ], - [ 0x1D4AD, 0x1D4AD ], - [ 0x1D4BA, 0x1D4BA ], - [ 0x1D4BC, 0x1D4BC ], - [ 0x1D4C4, 0x1D4C4 ], - [ 0x1D506, 0x1D506 ], - [ 0x1D50B, 0x1D50C ], - [ 0x1D515, 0x1D515 ], - [ 0x1D51D, 0x1D51D ], - [ 0x1D53A, 0x1D53A ], - [ 0x1D53F, 0x1D53F ], - [ 0x1D545, 0x1D545 ], - [ 0x1D547, 0x1D549 ], - [ 0x1D551, 0x1D551 ], - [ 0x1D6A6, 0x1D6A7 ], - [ 0x1D7CC, 0x1D7CD ], - [ 0x1D800, 0x1EFFF ], - [ 0x1F02C, 0x1F02F ], - [ 0x1F094, 0x1F09F ], - [ 0x1F0AF, 0x1F0B0 ], - [ 0x1F0BF, 0x1F0C0 ], - [ 0x1F0D0, 0x1F0D0 ], - [ 0x1F0E0, 0x1F0FF ], - [ 0x1F10B, 0x1F10F ], - [ 0x1F12F, 0x1F12F ], - [ 0x1F16A, 0x1F16F ], - [ 0x1F19B, 0x1F1E5 ], - [ 0x1F203, 0x1F20F ], - [ 0x1F23B, 0x1F23F ], - [ 0x1F249, 0x1F24F ], - [ 0x1F252, 0x1F2FF ], - [ 0x1F321, 0x1F32F ], - [ 0x1F336, 0x1F336 ], - [ 0x1F37D, 0x1F37F ], - [ 0x1F394, 0x1F39F ], - [ 0x1F3C5, 0x1F3C5 ], - [ 0x1F3CB, 0x1F3DF ], - [ 0x1F3F1, 0x1F3FF ], - [ 0x1F43F, 0x1F43F ], - [ 0x1F441, 0x1F441 ], - [ 0x1F4F8, 0x1F4F8 ], - [ 0x1F4FD, 0x1F4FF ], - [ 0x1F53E, 0x1F54F ], - [ 0x1F568, 0x1F5FA ], - [ 0x1F600, 0x1F600 ], - [ 0x1F611, 0x1F611 ], - [ 0x1F615, 0x1F615 ], - [ 0x1F617, 0x1F617 ], - [ 0x1F619, 0x1F619 ], - [ 0x1F61B, 0x1F61B ], - [ 0x1F61F, 0x1F61F ], - [ 0x1F626, 0x1F627 ], - [ 0x1F62C, 0x1F62C ], - [ 0x1F62E, 0x1F62F ], - [ 0x1F634, 0x1F634 ], - [ 0x1F641, 0x1F644 ], - [ 0x1F650, 0x1F67F ], - [ 0x1F6C6, 0x1F6FF ], - [ 0x1F774, 0x1FFFF ], - [ 0x2A6D7, 0x2A6FF ], - [ 0x2B735, 0x2B73F ], - [ 0x2B81E, 0x2F7FF ], - [ 0x2FA1E, 0xE0000 ], - [ 0xE0002, 0xE001F ], - [ 0xE0080, 0xE00FF ], - [ 0xE01F0, 0xEFFFF ], - [ 0xFFFFE, 0xFFFFF ], - [ 0x10FFFE, 0x10FFFF ], - ]; - - return binarySearch!table(c); + return nonCharacterTrie[c]; } unittest { + auto set = unicode("Cn"); + foreach(ch; set.byCodepoint) + assert(isNonCharacter(ch)); } - -//============================================================================== -// Private Section. -//============================================================================== private: +// load static data from pre-generated tables into usable datastructures -bool binarySearch(alias table)(dchar c) @safe pure nothrow + +@safe auto asSet(const (ubyte)[] compressed) { - static @property bool checkTableEntry(alias table)() - { - foreach(i, entry; table) - { - assert(table[i][0] <= table[i][1]); - if(i < table.length - 1) - assert(table[i][1] < table[i + 1][0]); - } - return true; - } - static assert(checkTableEntry!table); - - return binarySearch2(c, table); + return CodepointSet(decompressIntervals(compressed)); } -bool binarySearch2(dchar c, immutable dchar[2][] table) @safe pure nothrow +@safe pure nothrow auto asTrie(T...)(in TrieEntry!T e) { - // Binary search - size_t mid; - size_t low; - size_t high; + return const(CodepointTrie!T)(e.offsets, e.sizes, e.data); +} - low = 0; - high = table.length - 1; - while(cast(int)low <= cast(int)high) +@safe pure nothrow @property +{ + // It's important to use auto return here, so that the compiler + // only runs semantic on the return type if the function gets + // used. Also these are functions rather than templates to not + // increase the object size of the caller. + auto lowerCaseTrie() { static immutable res = asTrie(lowerCaseTrieEntries); return res; } + auto upperCaseTrie() { static immutable res = asTrie(upperCaseTrieEntries); return res; } + auto simpleCaseTrie() { static immutable res = asTrie(simpleCaseTrieEntries); return res; } + auto fullCaseTrie() { static immutable res = asTrie(fullCaseTrieEntries); return res; } + auto alphaTrie() { static immutable res = asTrie(alphaTrieEntries); return res; } + auto markTrie() { static immutable res = asTrie(markTrieEntries); return res; } + auto numberTrie() { static immutable res = asTrie(numberTrieEntries); return res; } + auto punctuationTrie() { static immutable res = asTrie(punctuationTrieEntries); return res; } + auto symbolTrie() { static immutable res = asTrie(symbolTrieEntries); return res; } + auto graphicalTrie() { static immutable res = asTrie(graphicalTrieEntries); return res; } + auto nonCharacterTrie() { static immutable res = asTrie(nonCharacterTrieEntries); return res; } + + //normalization quick-check tables + auto nfcQCTrie() { - mid = (low + high) >> 1; - - if(c < table[mid][0]) - high = mid - 1; - else if(c > table[mid][1]) - low = mid + 1; - else - goto Lis; + import std.internal.unicode_norm; + static immutable res = asTrie(nfcQCTrieEntries); + return res; } -Lisnot: - debug + auto nfdQCTrie() { - for(size_t i = 0; i < table.length; ++i) - assert(c < table[i][0] || c > table[i][1]); + import std.internal.unicode_norm; + static immutable res = asTrie(nfdQCTrieEntries); + return res; } - return false; - -Lis: - debug + auto nfkcQCTrie() { - for(size_t i = 0; i < table.length; ++i) - { - if(c >= table[i][0] && c <= table[i][1]) - return true; - } - - assert(0); // should have been in table + import std.internal.unicode_norm; + static immutable res = asTrie(nfkcQCTrieEntries); + return res; } - else - return true; -}; + + auto nfkdQCTrie() + { + import std.internal.unicode_norm; + static immutable res = asTrie(nfkdQCTrieEntries); + return res; + } + + //grapheme breaking algorithm tables + auto mcTrie() + { + import std.internal.unicode_grapheme; + static immutable res = asTrie(mcTrieEntries); + return res; + } + + auto graphemeExtendTrie() + { + import std.internal.unicode_grapheme; + static immutable res = asTrie(graphemeExtendTrieEntries); + return res; + } + + auto hangLV() + { + import std.internal.unicode_grapheme; + static immutable res = asTrie(hangulLVTrieEntries); + return res; + } + + auto hangLVT() + { + import std.internal.unicode_grapheme; + static immutable res = asTrie(hangulLVTTrieEntries); + return res; + } + + // tables below are used for composition/decomposition + auto combiningClassTrie() + { + import std.internal.unicode_comp; + static immutable res = asTrie(combiningClassTrieEntries); + return res; + } + + auto compatMappingTrie() + { + import std.internal.unicode_decomp; + static immutable res = asTrie(compatMappingTrieEntries); + return res; + } + + auto canonMappingTrie() + { + import std.internal.unicode_decomp; + static immutable res = asTrie(canonMappingTrieEntries); + return res; + } + + auto compositionJumpTrie() + { + import std.internal.unicode_comp; + static immutable res = asTrie(compositionJumpTrieEntries); + return res; + } + + //case conversion tables + auto toUpperIndexTrie() { static immutable res = asTrie(toUpperIndexTrieEntries); return res; } + auto toLowerIndexTrie() { static immutable res = asTrie(toLowerIndexTrieEntries); return res; } + auto toTitleIndexTrie() { static immutable res = asTrie(toTitleIndexTrieEntries); return res; } + + +} + +}// version(!std_uni_bootstrap) + diff --git a/std/uri.d b/std/uri.d index 772a7992f..3f774068e 100644 --- a/std/uri.d +++ b/std/uri.d @@ -26,21 +26,27 @@ */ module std.uri; -//debug=uri; // uncomment to turn on debugging printf's +//debug=uri; // uncomment to turn on debugging writefln's +debug(uri) private import std.stdio; /* ====================== URI Functions ================ */ private import std.ascii; private import std.c.stdlib; private import std.utf; -private import std.stdio; -import std.exception; +import core.exception : OutOfMemoryError; +import std.exception : assumeUnique; -class URIerror : Error +class URIException : Exception { - this() + @safe pure nothrow this() { - super("URI error"); + super("URI Exception"); + } + + @safe pure nothrow this(string msg) + { + super("URI Exception: " ~ msg); } } @@ -60,19 +66,18 @@ __gshared ubyte[128] uri_flags; // indexed by character shared static this() { // Initialize uri_flags[] - static void helper(immutable char[] p, uint flags) - { int i; - - for (i = 0; i < p.length; i++) - uri_flags[p[i]] |= flags; + { + for (int i = 0; i < p.length; i++) + uri_flags[p[i]] |= flags; } uri_flags['#'] |= URI_Hash; for (int i = 'A'; i <= 'Z'; i++) - { uri_flags[i] |= URI_Alpha; - uri_flags[i + 0x20] |= URI_Alpha; // lowercase letters + { + uri_flags[i] |= URI_Alpha; + uri_flags[i + 0x20] |= URI_Alpha; // lowercase letters } helper("0123456789", URI_Digit); helper(";/?:@&=+$,", URI_Reserved); @@ -101,122 +106,127 @@ private string URI_Encode(dstring string, uint unescapedSet) for (k = 0; k != len; k++) { - C = string[k]; - // if (C in unescapedSet) - if (C < uri_flags.length && uri_flags[C] & unescapedSet) - { - if (Rlen == Rsize) - { char* R2; + C = string[k]; + // if (C in unescapedSet) + if (C < uri_flags.length && uri_flags[C] & unescapedSet) + { + if (Rlen == Rsize) + { + char* R2; - Rsize *= 2; - if (Rsize > 1024) - R2 = (new char[Rsize]).ptr; + Rsize *= 2; + if (Rsize > 1024) { + R2 = (new char[Rsize]).ptr; + } + else + { + R2 = cast(char *)alloca(Rsize * char.sizeof); + if (!R2) + throw new OutOfMemoryError("Alloca failure"); + } + R2[0..Rlen] = R[0..Rlen]; + R = R2; + } + R[Rlen] = cast(char)C; + Rlen++; + } else - { R2 = cast(char *)alloca(Rsize * char.sizeof); - if (!R2) - goto LthrowURIerror; - } - R2[0..Rlen] = R[0..Rlen]; - R = R2; - } - R[Rlen] = cast(char)C; - Rlen++; - } - else - { char[6] Octet; - uint L; + { + char[6] Octet; + uint L; - V = C; + V = C; - // Transform V into octets - if (V <= 0x7F) - { - Octet[0] = cast(char) V; - L = 1; - } - else if (V <= 0x7FF) - { - Octet[0] = cast(char)(0xC0 | (V >> 6)); - Octet[1] = cast(char)(0x80 | (V & 0x3F)); - L = 2; - } - else if (V <= 0xFFFF) - { - Octet[0] = cast(char)(0xE0 | (V >> 12)); - Octet[1] = cast(char)(0x80 | ((V >> 6) & 0x3F)); - Octet[2] = cast(char)(0x80 | (V & 0x3F)); - L = 3; - } - else if (V <= 0x1FFFFF) - { - Octet[0] = cast(char)(0xF0 | (V >> 18)); - Octet[1] = cast(char)(0x80 | ((V >> 12) & 0x3F)); - Octet[2] = cast(char)(0x80 | ((V >> 6) & 0x3F)); - Octet[3] = cast(char)(0x80 | (V & 0x3F)); - L = 4; - } - /+ - else if (V <= 0x3FFFFFF) - { - Octet[0] = cast(char)(0xF8 | (V >> 24)); - Octet[1] = cast(char)(0x80 | ((V >> 18) & 0x3F)); - Octet[2] = cast(char)(0x80 | ((V >> 12) & 0x3F)); - Octet[3] = cast(char)(0x80 | ((V >> 6) & 0x3F)); - Octet[4] = cast(char)(0x80 | (V & 0x3F)); - L = 5; - } - else if (V <= 0x7FFFFFFF) - { - Octet[0] = cast(char)(0xFC | (V >> 30)); - Octet[1] = cast(char)(0x80 | ((V >> 24) & 0x3F)); - Octet[2] = cast(char)(0x80 | ((V >> 18) & 0x3F)); - Octet[3] = cast(char)(0x80 | ((V >> 12) & 0x3F)); - Octet[4] = cast(char)(0x80 | ((V >> 6) & 0x3F)); - Octet[5] = cast(char)(0x80 | (V & 0x3F)); - L = 6; - } - +/ - else - { goto LthrowURIerror; // undefined UTF-32 code - } + // Transform V into octets + if (V <= 0x7F) + { + Octet[0] = cast(char) V; + L = 1; + } + else if (V <= 0x7FF) + { + Octet[0] = cast(char)(0xC0 | (V >> 6)); + Octet[1] = cast(char)(0x80 | (V & 0x3F)); + L = 2; + } + else if (V <= 0xFFFF) + { + Octet[0] = cast(char)(0xE0 | (V >> 12)); + Octet[1] = cast(char)(0x80 | ((V >> 6) & 0x3F)); + Octet[2] = cast(char)(0x80 | (V & 0x3F)); + L = 3; + } + else if (V <= 0x1FFFFF) + { + Octet[0] = cast(char)(0xF0 | (V >> 18)); + Octet[1] = cast(char)(0x80 | ((V >> 12) & 0x3F)); + Octet[2] = cast(char)(0x80 | ((V >> 6) & 0x3F)); + Octet[3] = cast(char)(0x80 | (V & 0x3F)); + L = 4; + } + /+ + else if (V <= 0x3FFFFFF) + { + Octet[0] = cast(char)(0xF8 | (V >> 24)); + Octet[1] = cast(char)(0x80 | ((V >> 18) & 0x3F)); + Octet[2] = cast(char)(0x80 | ((V >> 12) & 0x3F)); + Octet[3] = cast(char)(0x80 | ((V >> 6) & 0x3F)); + Octet[4] = cast(char)(0x80 | (V & 0x3F)); + L = 5; + } + else if (V <= 0x7FFFFFFF) + { + Octet[0] = cast(char)(0xFC | (V >> 30)); + Octet[1] = cast(char)(0x80 | ((V >> 24) & 0x3F)); + Octet[2] = cast(char)(0x80 | ((V >> 18) & 0x3F)); + Octet[3] = cast(char)(0x80 | ((V >> 12) & 0x3F)); + Octet[4] = cast(char)(0x80 | ((V >> 6) & 0x3F)); + Octet[5] = cast(char)(0x80 | (V & 0x3F)); + L = 6; + } + +/ + else + { + throw new URIException("Undefined UTF-32 code point"); + } - if (Rlen + L * 3 > Rsize) - { char *R2; + if (Rlen + L * 3 > Rsize) + { + char *R2; - Rsize = 2 * (Rlen + L * 3); - if (Rsize > 1024) - R2 = (new char[Rsize]).ptr; - else - { R2 = cast(char *)alloca(Rsize * char.sizeof); - if (!R2) - goto LthrowURIerror; - } - R2[0..Rlen] = R[0..Rlen]; - R = R2; - } + Rsize = 2 * (Rlen + L * 3); + if (Rsize > 1024) { + R2 = (new char[Rsize]).ptr; + } + else + { + R2 = cast(char *)alloca(Rsize * char.sizeof); + if (!R2) + throw new OutOfMemoryError("Alloca failure"); + } + R2[0..Rlen] = R[0..Rlen]; + R = R2; + } - for (j = 0; j < L; j++) - { - R[Rlen] = '%'; - R[Rlen + 1] = hex2ascii[Octet[j] >> 4]; - R[Rlen + 2] = hex2ascii[Octet[j] & 15]; + for (j = 0; j < L; j++) + { + R[Rlen] = '%'; + R[Rlen + 1] = hex2ascii[Octet[j] >> 4]; + R[Rlen + 2] = hex2ascii[Octet[j] & 15]; - Rlen += 3; + Rlen += 3; + } } } - } return R[0..Rlen].idup; - -LthrowURIerror: - throw new URIerror(); } uint ascii2hex(dchar c) { return (c <= '9') ? c - '0' : - (c <= 'F') ? c - 'A' + 10 : - c - 'a' + 10; + (c <= 'F') ? c - 'A' + 10 : + c - 'a' + 10; } private dstring URI_Decode(string string, uint reservedSet) @@ -226,8 +236,6 @@ private dstring URI_Decode(string string, uint reservedSet) uint V; dchar C; - //printf("URI_Decode('%.*s')\n", string); - // Result array, allocated on stack dchar* R; uint Rlen; @@ -237,95 +245,96 @@ private dstring URI_Decode(string string, uint reservedSet) // Preallocate result buffer R guaranteed to be large enough for result auto Rsize = len; - if (Rsize > 1024 / dchar.sizeof) - R = (new dchar[Rsize]).ptr; + if (Rsize > 1024 / dchar.sizeof) { + R = (new dchar[Rsize]).ptr; + } else - { R = cast(dchar *)alloca(Rsize * dchar.sizeof); - if (!R) - goto LthrowURIerror; + { + R = cast(dchar *)alloca(Rsize * dchar.sizeof); + if (!R) + throw new OutOfMemoryError("Alloca failure"); } Rlen = 0; for (k = 0; k != len; k++) - { char B; - uint start; - - C = s[k]; - if (C != '%') - { R[Rlen] = C; - Rlen++; - continue; - } - start = k; - if (k + 2 >= len) - goto LthrowURIerror; - if (!isHexDigit(s[k + 1]) || !isHexDigit(s[k + 2])) - goto LthrowURIerror; - B = cast(char)((ascii2hex(s[k + 1]) << 4) + ascii2hex(s[k + 2])); - k += 2; - if ((B & 0x80) == 0) { - C = B; - } - else - { uint n; + char B; + uint start; - for (n = 1; ; n++) + C = s[k]; + if (C != '%') { - if (n > 4) - goto LthrowURIerror; - if (((B << n) & 0x80) == 0) - { - if (n == 1) - goto LthrowURIerror; - break; + R[Rlen] = C; + Rlen++; + continue; } - } - - // Pick off (7 - n) significant bits of B from first byte of octet - V = B & ((1 << (7 - n)) - 1); // (!!!) - - if (k + (3 * (n - 1)) >= len) - goto LthrowURIerror; - for (j = 1; j != n; j++) - { - k++; - if (s[k] != '%') - goto LthrowURIerror; + start = k; + if (k + 2 >= len) + throw new URIException("Unexpected end of URI"); if (!isHexDigit(s[k + 1]) || !isHexDigit(s[k + 2])) - goto LthrowURIerror; + throw new URIException("Expected two hexadecimal digits after '%'"); B = cast(char)((ascii2hex(s[k + 1]) << 4) + ascii2hex(s[k + 2])); - if ((B & 0xC0) != 0x80) - goto LthrowURIerror; k += 2; - V = (V << 6) | (B & 0x3F); + if ((B & 0x80) == 0) + { + C = B; + } + else + { + uint n; + + for (n = 1; ; n++) + { + if (n > 4) + throw new URIException("UTF-32 code point size too large"); + if (((B << n) & 0x80) == 0) + { + if (n == 1) + throw new URIException("UTF-32 code point size too small"); + break; + } + } + + // Pick off (7 - n) significant bits of B from first byte of octet + V = B & ((1 << (7 - n)) - 1); // (!!!) + + if (k + (3 * (n - 1)) >= len) + throw new URIException("UTF-32 unaligned String"); + for (j = 1; j != n; j++) + { + k++; + if (s[k] != '%') + throw new URIException("Expected: '%'"); + if (!isHexDigit(s[k + 1]) || !isHexDigit(s[k + 2])) + throw new URIException("Expected two hexadecimal digits after '%'"); + B = cast(char)((ascii2hex(s[k + 1]) << 4) + ascii2hex(s[k + 2])); + if ((B & 0xC0) != 0x80) + throw new URIException("Incorrect UTF-32 multi-byte sequence"); + k += 2; + V = (V << 6) | (B & 0x3F); + } + if (V > 0x10FFFF) + throw new URIException("Unknown UTF-32 code point"); + C = V; + } + if (C < uri_flags.length && uri_flags[C] & reservedSet) + { + // R ~= s[start .. k + 1]; + int width = (k + 1) - start; + for (int ii = 0; ii < width; ii++) + R[Rlen + ii] = s[start + ii]; + Rlen += width; + } + else + { + R[Rlen] = C; + Rlen++; } - if (V > 0x10FFFF) - goto LthrowURIerror; - C = V; - } - if (C < uri_flags.length && uri_flags[C] & reservedSet) - { - // R ~= s[start .. k + 1]; - int width = (k + 1) - start; - for (int ii = 0; ii < width; ii++) - R[Rlen + ii] = s[start + ii]; - Rlen += width; - } - else - { - R[Rlen] = C; - Rlen++; - } } assert(Rlen <= Rsize); // enforce our preallocation size guarantee // Copy array on stack to array in memory return R[0..Rlen].idup; - - -LthrowURIerror: - throw new URIerror(); } /************************************* @@ -387,50 +396,60 @@ size_t uriLength(string s) * https:// * www. */ + import std.string : icmp; size_t i; if (s.length <= 4) - goto Lno; + return -1; - //writefln("isURL(%s)", s); - if (s.length > 7 && std.string.icmp(s[0 .. 7], "http://") == 0) - i = 7; - else if (s.length > 8 && std.string.icmp(s[0 .. 8], "https://") == 0) - i = 8; -// if (icmp(s[0 .. 4], "www.") == 0) -// i = 4; + if (s.length > 7 && std.string.icmp(s[0 .. 7], "http://") == 0) { + i = 7; + } else - goto Lno; + { + if (s.length > 8 && std.string.icmp(s[0 .. 8], "https://") == 0) + i = 8; + else + return -1; + } + // if (icmp(s[0 .. 4], "www.") == 0) + // i = 4; size_t lastdot; for (; i < s.length; i++) { - auto c = s[i]; - if (isAlphaNum(c)) - continue; - if (c == '-' || c == '_' || c == '?' || - c == '=' || c == '%' || c == '&' || - c == '/' || c == '+' || c == '#' || - c == '~' || c == '$') - continue; - if (c == '.') - { - lastdot = i; - continue; - } - break; + auto c = s[i]; + if (isAlphaNum(c)) + continue; + if (c == '-' || c == '_' || c == '?' || + c == '=' || c == '%' || c == '&' || + c == '/' || c == '+' || c == '#' || + c == '~' || c == '$') + continue; + if (c == '.') + { + lastdot = i; + continue; + } + break; } //if (!lastdot || (i - lastdot != 3 && i - lastdot != 4)) if (!lastdot) - goto Lno; + return -1; return i; - -Lno: - return -1; } +unittest +{ + string s1 = "http://www.digitalmars.com/~fred/fredsRX.html#foo end!"; + assert (uriLength(s1) == 49); + string s2 = "no uri here"; + assert (uriLength(s2) == -1); +} + + /*************************** * Does string s[] start with an email address? * Returns: @@ -440,81 +459,85 @@ Lno: * RFC2822 */ size_t emailLength(string s) -{ size_t i; +{ + size_t i; if (!isAlpha(s[0])) - goto Lno; + return -1; for (i = 1; 1; i++) { - if (i == s.length) - goto Lno; - auto c = s[i]; - if (isAlphaNum(c)) - continue; - if (c == '-' || c == '_' || c == '.') - continue; - if (c != '@') - goto Lno; - i++; - break; + if (i == s.length) + return -1; + auto c = s[i]; + if (isAlphaNum(c)) + continue; + if (c == '-' || c == '_' || c == '.') + continue; + if (c != '@') + return -1; + i++; + break; } - //writefln("test1 '%s'", s[0 .. i]); /* Now do the part past the '@' */ size_t lastdot; for (; i < s.length; i++) { - auto c = s[i]; - if (isAlphaNum(c)) - continue; - if (c == '-' || c == '_') - continue; - if (c == '.') - { - lastdot = i; - continue; - } - break; + auto c = s[i]; + if (isAlphaNum(c)) + continue; + if (c == '-' || c == '_') + continue; + if (c == '.') + { + lastdot = i; + continue; + } + break; } if (!lastdot || (i - lastdot != 3 && i - lastdot != 4)) - goto Lno; + return -1; return i; +} -Lno: - return -1; +unittest +{ + string s1 = "my.e-mail@www.example-domain.com with garbage added"; + assert (emailLength(s1) == 32); + string s2 = "no email address here"; + assert (emailLength(s2) == -1); } unittest { - debug(uri) printf("uri.encodeURI.unittest\n"); + debug(uri) writeln("uri.encodeURI.unittest"); string s = "http://www.digitalmars.com/~fred/fred's RX.html#foo"; string t = "http://www.digitalmars.com/~fred/fred's%20RX.html#foo"; auto r = encode(s); - debug(uri) printf("r = '%.*s'\n", r); + debug(uri) writefln("r = '%s'", r); assert(r == t); r = decode(t); - debug(uri) printf("r = '%.*s'\n", r); + debug(uri) writefln("r = '%s'", r); assert(r == s); r = encode( decode("%E3%81%82%E3%81%82") ); assert(r == "%E3%81%82%E3%81%82"); r = encodeComponent("c++"); - //printf("r = '%.*s'\n", r); assert(r == "c%2B%2B"); auto str = new char[10_000_000]; str[] = 'A'; r = encodeComponent(assumeUnique(str)); foreach (char c; r) - assert(c == 'A'); + assert(c == 'A'); r = decode("%41%42%43"); - debug(uri) writefln(r); + debug(uri) writeln(r); } diff --git a/std/utf.d b/std/utf.d index 6c28b5a7c..071edecd2 100644 --- a/std/utf.d +++ b/std/utf.d @@ -45,8 +45,8 @@ class UTFException : Exception uint[4] sequence; size_t len; - - UTFException setSequence(uint[] data...) @safe pure nothrow + @safe pure nothrow + UTFException setSequence(uint[] data...) { import std.algorithm; @@ -58,13 +58,13 @@ class UTFException : Exception return this; } - + @safe pure nothrow this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null) { super(msg, file, line, next); } - + @safe pure this(string msg, size_t index, string file = __FILE__, size_t line = __LINE__, Throwable next = null) { import std.string; @@ -75,15 +75,15 @@ class UTFException : Exception override string toString() { import std.string; - if(len == 0) + if (len == 0) return super.toString(); string result = "Invalid UTF sequence:"; - foreach(i; sequence[0 .. len]) + foreach (i; sequence[0 .. len]) result ~= format(" %02x", i); - if(super.msg.length > 0) + if (super.msg.length > 0) { result ~= " - "; result ~= super.msg; @@ -95,7 +95,7 @@ class UTFException : Exception // Explicitly undocumented. It will be removed in November 2013. -deprecated("Please use std.utf.UTFException instead.") alias UTFException UtfException; +deprecated("Please use std.utf.UTFException instead.") alias UtfException = UTFException; /++ @@ -121,18 +121,22 @@ pure nothrow bool isValidDchar(dchar c) unittest { debug(utf) printf("utf.isValidDchar.unittest\n"); - assert(isValidDchar(cast(dchar)'a') == true); - assert(isValidDchar(cast(dchar)0x1FFFFF) == false); + + assertCTFEable!( + { + assert( isValidDchar(cast(dchar)'a') == true); + assert( isValidDchar(cast(dchar)0x1FFFFF) == false); assert(!isValidDchar(cast(dchar)0x00D800)); assert(!isValidDchar(cast(dchar)0x00DBFF)); assert(!isValidDchar(cast(dchar)0x00DC00)); assert(!isValidDchar(cast(dchar)0x00DFFF)); - assert(isValidDchar(cast(dchar)0x00FFFE)); - assert(isValidDchar(cast(dchar)0x00FFFF)); - assert(isValidDchar(cast(dchar)0x01FFFF)); - assert(isValidDchar(cast(dchar)0x10FFFF)); + assert( isValidDchar(cast(dchar)0x00FFFE)); + assert( isValidDchar(cast(dchar)0x00FFFF)); + assert( isValidDchar(cast(dchar)0x01FFFF)); + assert( isValidDchar(cast(dchar)0x10FFFF)); assert(!isValidDchar(cast(dchar)0x110000)); + }); } @@ -234,6 +238,8 @@ unittest } } + assertCTFEable!( + { test("a", 'a'); test(" ", ' '); test("\u2029", '\u2029'); //paraSep @@ -250,14 +256,15 @@ unittest test("hello\U00010143\u0100\U00010143", '\u0100', 9); test("hello\U00010143\u0100\U00010143", '\U00010143', 11); - foreach(S; TypeTuple!(char[], const char[], string)) + foreach (S; TypeTuple!(char[], const char[], string)) { enum str = to!S("hello world"); - static assert(isSafe!((){stride(str, 0);})); - static assert(isSafe!((){stride(str);})); - static assert((functionAttributes!((){stride(str, 0);}) & FunctionAttribute.pure_) != 0); - static assert((functionAttributes!((){stride(str);}) & FunctionAttribute.pure_) != 0); + static assert(isSafe!({ stride(str, 0); })); + static assert(isSafe!({ stride(str); })); + static assert((functionAttributes!({ stride(str, 0); }) & FunctionAttribute.pure_) != 0); + static assert((functionAttributes!({ stride(str); }) & FunctionAttribute.pure_) != 0); } + }); } @@ -289,14 +296,14 @@ uint strideBack(S)(auto ref S str, size_t index) { static if (is(typeof(str.length) : ulong)) assert(index <= str.length, "Past the end of the UTF-8 sequence"); - assert (index > 0, "Not the end of the UTF-8 sequence"); + assert(index > 0, "Not the end of the UTF-8 sequence"); if ((str[index-1] & 0b1100_0000) != 0b1000_0000) return 1; if (index >= 4) //single verification for most common case { - foreach(i; TypeTuple!(2, 3, 4)) + foreach (i; TypeTuple!(2, 3, 4)) { if ((str[index-i] & 0b1100_0000) != 0b1000_0000) return i; @@ -304,7 +311,7 @@ uint strideBack(S)(auto ref S str, size_t index) } else { - foreach(i; TypeTuple!(2, 3)) + foreach (i; TypeTuple!(2, 3)) { if (index >= i && (str[index-i] & 0b1100_0000) != 0b1000_0000) return i; @@ -316,7 +323,7 @@ uint strideBack(S)(auto ref S str, size_t index) /// Ditto uint strideBack(S)(auto ref S str) if (is(S : const char[]) || - (isRandomAccessRange!S && hasLength!S && is(Unqual!(ElementType!S) == char))) + (isRandomAccessRange!S && hasLength!S && is(Unqual!(ElementType!S) == char))) { return strideBack(str, str.length); } @@ -326,11 +333,13 @@ uint strideBack(S)(auto ref S str) { assert(!str.empty, "Past the end of the UTF-8 sequence"); auto temp = str.save; - foreach(i; TypeTuple!(1, 2, 3, 4)) + foreach (i; TypeTuple!(1, 2, 3, 4)) { - if ((temp.back & 0b1100_0000) != 0b1000_0000) return i; + if ((temp.back & 0b1100_0000) != 0b1000_0000) + return i; temp.popBack(); - if (temp.empty) break; + if (temp.empty) + break; } throw new UTFException("The last code unit is not the end of the UTF-8 sequence"); } @@ -369,6 +378,8 @@ unittest } } + assertCTFEable!( + { test("a", 'a'); test(" ", ' '); test("\u2029", '\u2029'); //paraSep @@ -385,14 +396,15 @@ unittest test("\U00010143\u0100\U00010143hello", '\u0100', 6); test("\U00010143\u0100\U00010143hello", '\U00010143', 4); - foreach(S; TypeTuple!(char[], const char[], string)) + foreach (S; TypeTuple!(char[], const char[], string)) { enum str = to!S("hello world"); - static assert(isSafe!((){strideBack(str, 0);})); - static assert(isSafe!((){strideBack(str);})); - static assert((functionAttributes!((){strideBack(str, 0);}) & FunctionAttribute.pure_) != 0); - static assert((functionAttributes!((){strideBack(str);}) & FunctionAttribute.pure_) != 0); + static assert(isSafe!({ strideBack(str, 0); })); + static assert(isSafe!({ strideBack(str); })); + static assert((functionAttributes!({ strideBack(str, 0); }) & FunctionAttribute.pure_) != 0); + static assert((functionAttributes!({ strideBack(str); }) & FunctionAttribute.pure_) != 0); } + }); } @@ -439,7 +451,7 @@ uint stride(S)(auto ref S str) @safe pure uint stride(S)(auto ref S str) if (isInputRange!S && is(Unqual!(ElementType!S) == wchar)) { - assert (!str.empty, "UTF-16 sequence is empty"); + assert(!str.empty, "UTF-16 sequence is empty"); immutable uint u = str.front; return 1 + (u >= 0xD800 && u <= 0xDBFF); } @@ -478,6 +490,8 @@ uint stride(S)(auto ref S str) } } + assertCTFEable!( + { test("a", 'a'); test(" ", ' '); test("\u2029", '\u2029'); //paraSep @@ -494,14 +508,15 @@ uint stride(S)(auto ref S str) test("hello\U00010143\u0100\U00010143", '\u0100', 7); test("hello\U00010143\u0100\U00010143", '\U00010143', 8); - foreach(S; TypeTuple!(wchar[], const wchar[], wstring)) + foreach (S; TypeTuple!(wchar[], const wchar[], wstring)) { enum str = to!S("hello world"); - static assert(isSafe!((){stride(str, 0);})); - static assert(isSafe!((){stride(str);})); - static assert((functionAttributes!((){stride(str, 0);}) & FunctionAttribute.pure_) != 0); - static assert((functionAttributes!((){stride(str);}) & FunctionAttribute.pure_) != 0); + static assert(isSafe!({ stride(str, 0); })); + static assert(isSafe!({ stride(str); })); + static assert((functionAttributes!({ stride(str, 0); }) & FunctionAttribute.pure_) != 0); + static assert((functionAttributes!({ stride(str); }) & FunctionAttribute.pure_) != 0); } + }); } @@ -536,7 +551,7 @@ uint strideBack(S)(auto ref S str, size_t index) { static if (is(typeof(str.length) : ulong)) assert(index <= str.length, "Past the end of the UTF-16 sequence"); - assert (index > 0, "Not the end of a UTF-16 sequence"); + assert(index > 0, "Not the end of a UTF-16 sequence"); immutable c2 = str[index-1]; return 1 + (0xDC00 <= c2 && c2 < 0xE000); @@ -547,7 +562,7 @@ uint strideBack(S)(auto ref S str) if (is(S : const wchar[]) || (isBidirectionalRange!S && is(Unqual!(ElementType!S) == wchar))) { - assert (!str.empty, "UTF-16 sequence is empty"); + assert(!str.empty, "UTF-16 sequence is empty"); static if (is(S : const(wchar)[])) immutable c2 = str[$ - 1]; @@ -591,6 +606,8 @@ unittest } } + assertCTFEable!( + { test("a", 'a'); test(" ", ' '); test("\u2029", '\u2029'); //paraSep @@ -607,14 +624,15 @@ unittest test("\U00010143\u0100\U00010143hello", '\u0100', 3); test("\U00010143\u0100\U00010143hello", '\U00010143', 2); - foreach(S; TypeTuple!(wchar[], const wchar[], wstring)) + foreach (S; TypeTuple!(wchar[], const wchar[], wstring)) { enum str = to!S("hello world"); - static assert(isSafe!((){strideBack(str, 0);})); - static assert(isSafe!((){strideBack(str);})); - static assert((functionAttributes!((){strideBack(str, 0);}) & FunctionAttribute.pure_) != 0); - static assert((functionAttributes!((){strideBack(str);}) & FunctionAttribute.pure_) != 0); + static assert(isSafe!({ strideBack(str, 0); })); + static assert(isSafe!({ strideBack(str); })); + static assert((functionAttributes!({ strideBack(str, 0); }) & FunctionAttribute.pure_) != 0); + static assert((functionAttributes!({ strideBack(str); }) & FunctionAttribute.pure_) != 0); } + }); } @@ -675,6 +693,8 @@ unittest } } + assertCTFEable!( + { test("a", 'a'); test(" ", ' '); test("\u2029", '\u2029'); //paraSep @@ -691,14 +711,15 @@ unittest test("hello\U00010143\u0100\U00010143", '\u0100', 6); test("hello\U00010143\u0100\U00010143", '\U00010143', 7); - foreach(S; TypeTuple!(dchar[], const dchar[], dstring)) + foreach (S; TypeTuple!(dchar[], const dchar[], dstring)) { enum str = to!S("hello world"); - static assert(isSafe!((){stride(str, 0);})); - static assert(isSafe!((){stride(str);})); - static assert((functionAttributes!((){stride(str, 0);}) & FunctionAttribute.pure_) != 0); - static assert((functionAttributes!((){stride(str);}) & FunctionAttribute.pure_) != 0); + static assert(isSafe!({ stride(str, 0); })); + static assert(isSafe!({ stride(str); })); + static assert((functionAttributes!({ stride(str, 0); }) & FunctionAttribute.pure_) != 0); + static assert((functionAttributes!({ stride(str); }) & FunctionAttribute.pure_) != 0); } + }); } @@ -723,7 +744,7 @@ uint strideBack(S)(auto ref S str, size_t index) { static if (is(typeof(str.length) : ulong)) assert(index <= str.length, "Past the end of the UTF-32 sequence"); - assert (index > 0, "Not the end of the UTF-32 sequence"); + assert(index > 0, "Not the end of the UTF-32 sequence"); return 1; } @@ -769,6 +790,8 @@ unittest } } + assertCTFEable!( + { test("a", 'a'); test(" ", ' '); test("\u2029", '\u2029'); //paraSep @@ -785,14 +808,15 @@ unittest test("\U00010143\u0100\U00010143hello", '\u0100', 2); test("\U00010143\u0100\U00010143hello", '\U00010143', 1); - foreach(S; TypeTuple!(dchar[], const dchar[], dstring)) + foreach (S; TypeTuple!(dchar[], const dchar[], dstring)) { enum str = to!S("hello world"); - static assert(isSafe!((){strideBack(str, 0);})); - static assert(isSafe!((){strideBack(str);})); - static assert((functionAttributes!((){strideBack(str, 0);}) & FunctionAttribute.pure_) != 0); - static assert((functionAttributes!((){strideBack(str);}) & FunctionAttribute.pure_) != 0); + static assert(isSafe!({ strideBack(str, 0); })); + static assert(isSafe!({ strideBack(str); })); + static assert((functionAttributes!({ strideBack(str, 0); }) & FunctionAttribute.pure_) != 0); + static assert((functionAttributes!({ strideBack(str); }) & FunctionAttribute.pure_) != 0); } + }); } @@ -802,38 +826,23 @@ unittest up to $(D index). So, $(D index) is the index of a code unit at the beginning of a code point, and the return value is how many code points into the string that that code point is. - -Examples: --------------------- -assert(toUCSindex(`hello world`, 7) == 7); -assert(toUCSindex(`hello world`w, 7) == 7); -assert(toUCSindex(`hello world`d, 7) == 7); - -assert(toUCSindex(`Ma Chérie`, 7) == 6); -assert(toUCSindex(`Ma Chérie`w, 7) == 7); -assert(toUCSindex(`Ma Chérie`d, 7) == 7); - -assert(toUCSindex(`さいごの果実 / ミツバチと科学者`, 9) == 3); -assert(toUCSindex(`さいごの果実 / ミツバチと科学者`w, 9) == 9); -assert(toUCSindex(`さいごの果実 / ミツバチと科学者`d, 9) == 9); --------------------- +/ size_t toUCSindex(C)(const(C)[] str, size_t index) @safe pure - if(isSomeChar!C) + if (isSomeChar!C) { - static if(is(Unqual!C == dchar)) + static if (is(Unqual!C == dchar)) return index; else { size_t n = 0; size_t j = 0; - for(; j < index; ++n) + for (; j < index; ++n) j += stride(str, j); - if(j > index) + if (j > index) { - static if(is(Unqual!C == char)) + static if (is(Unqual!C == char)) throw new UTFException("Invalid UTF-8 sequence", index); else throw new UTFException("Invalid UTF-16 sequence", index); @@ -843,6 +852,7 @@ size_t toUCSindex(C)(const(C)[] str, size_t index) @safe pure } } +/// unittest { assert(toUCSindex(`hello world`, 7) == 7); @@ -863,49 +873,39 @@ unittest Given a UCS index $(D n) into $(D str), returns the UTF index. So, $(D n) is how many code points into the string the code point is, and the array index of the code unit is returned. - -Examples: --------------------- -assert(toUTFindex(`hello world`, 7) == 7); -assert(toUTFindex(`hello world`w, 7) == 7); -assert(toUTFindex(`hello world`d, 7) == 7); - -assert(toUTFindex(`Ma Chérie`, 6) == 7); -assert(toUTFindex(`Ma Chérie`w, 7) == 7); -assert(toUTFindex(`Ma Chérie`d, 7) == 7); - -assert(toUTFindex(`さいごの果実 / ミツバチと科学者`, 3) == 9); -assert(toUTFindex(`さいごの果実 / ミツバチと科学者`w, 9) == 9); -assert(toUTFindex(`さいごの果実 / ミツバチと科学者`d, 9) == 9); --------------------- +/ -size_t toUTFindex(in char[] str, size_t n) @safe pure +size_t toUTFindex(C)(const(C)[] str, size_t n) @safe pure + if (isSomeChar!C) { - size_t i; - while (n--) - i += stride(str, i); - return i; -} - -/// ditto -size_t toUTFindex(in wchar[] str, size_t n) @safe pure nothrow -{ - size_t i; - - while (n--) + static if (is(Unqual!C == dchar)) { - wchar u = str[i]; - - i += 1 + (u >= 0xD800 && u <= 0xDBFF); + return n; + } + else + { + size_t i; + while (n--) + { + i += stride(str, i); + } + return i; } - - return i; } -/// ditto -size_t toUTFindex(in dchar[] str, size_t n) @safe pure nothrow +/// +unittest { - return n; + assert(toUTFindex(`hello world`, 7) == 7); + assert(toUTFindex(`hello world`w, 7) == 7); + assert(toUTFindex(`hello world`d, 7) == 7); + + assert(toUTFindex(`Ma Chérie`, 6) == 7); + assert(toUTFindex(`Ma Chérie`w, 7) == 7); + assert(toUTFindex(`Ma Chérie`d, 7) == 7); + + assert(toUTFindex(`さいごの果実 / ミツバチと科学者`, 3) == 9); + assert(toUTFindex(`さいごの果実 / ミツバチと科学者`w, 9) == 9); + assert(toUTFindex(`さいごの果実 / ミツバチと科学者`d, 9) == 9); } @@ -1044,7 +1044,7 @@ dchar decodeFront(S)(ref S str) // Gives the maximum value that a code unit for the given range type can hold. private template codeUnitLimit(S) - if (isSomeChar!(ElementEncodingType!S)) + if (isSomeChar!(ElementEncodingType!S)) { static if (is(Unqual!(ElementEncodingType!S) == char)) enum char codeUnitLimit = 0x80; @@ -1082,7 +1082,7 @@ private dchar decodeImpl(bool canIndex, S)(auto ref S str, ref size_t index) else static if (isRandomAccessRange!S && hasSlicing!S && hasLength!S) auto pstr = str[index .. str.length]; else - alias str pstr; + alias pstr = str; //@@@BUG@@@ 8521 forces this to be done outside of decodeImpl //enum canIndex = is(S : const char[]) || (isRandomAccessRange!S && hasSlicing!S && hasLength!S); @@ -1110,7 +1110,7 @@ private dchar decodeImpl(bool canIndex, S)(auto ref S str, ref size_t index) sequence[i] = str[i]; } while (++i < str.length && i < 4 && (str[i] & 0xC0) == 0x80); - return (new UTFException(msg, i)).setSequence(sequence[0 .. i]); + return new UTFException(msg, i).setSequence(sequence[0 .. i]); } } @@ -1144,7 +1144,7 @@ private dchar decodeImpl(bool canIndex, S)(auto ref S str, ref size_t index) dchar d = fst; // upper control bits are masked out later fst <<= 1; - foreach(i; TypeTuple!(1, 2, 3)) + foreach (i; TypeTuple!(1, 2, 3)) { static if (canIndex) @@ -1203,7 +1203,7 @@ private dchar decodeImpl(bool canIndex, S)(auto ref S str, ref size_t index) else static if (isRandomAccessRange!S && hasSlicing!S && hasLength!S) auto pstr = str[index .. str.length]; else - alias str pstr; + alias pstr = str; //@@@BUG@@@ 8521 forces this to be done outside of decodeImpl //enum canIndex = is(S : const wchar[]) || (isRandomAccessRange!S && hasSlicing!S && hasLength!S); @@ -1222,7 +1222,7 @@ private dchar decodeImpl(bool canIndex, S)(auto ref S str, ref size_t index) UTFException exception(string msg) { static if (canIndex) - return (new UTFException(msg)).setSequence(pstr[0]); + return new UTFException(msg).setSequence(pstr[0]); else return new UTFException(msg); } @@ -1271,18 +1271,18 @@ private dchar decodeImpl(bool canIndex, S)(auto ref S str, ref size_t index) static if (is(S : const dchar[])) auto pstr = str.ptr; else - alias str pstr; + alias pstr = str; static if (is(S : const dchar[]) || (isRandomAccessRange!S && hasSlicing!S && hasLength!S)) { if (!isValidDchar(pstr[index])) - throw (new UTFException("Invalid UTF-32 value")).setSequence(pstr[index]); + throw new UTFException("Invalid UTF-32 value").setSequence(pstr[index]); return pstr[index++]; } else { if (!isValidDchar(pstr.front)) - throw (new UTFException("Invalid UTF-32 value")).setSequence(pstr.front); + throw new UTFException("Invalid UTF-32 value").setSequence(pstr.front); ++index; immutable retval = pstr.front; pstr.popFront(); @@ -1296,7 +1296,7 @@ version(unittest) private void testDecode(R)(R range, size_t expectedIndex, size_t line = __LINE__) { - static if(hasLength!R) + static if (hasLength!R) immutable lenBefore = range.length; static if (isRandomAccessRange!R) @@ -1307,7 +1307,7 @@ version(unittest) private void testDecode(R)(R range, new AssertError(format("decode: Wrong character: %s", result), __FILE__, line)); enforce(index == expectedIndex, new AssertError(format("decode: Wrong index: %s", index), __FILE__, line)); - static if(hasLength!R) + static if (hasLength!R) { enforce(range.length == lenBefore, new AssertError(format("decode: length changed: %s", range.length), __FILE__, line)); @@ -1321,7 +1321,7 @@ version(unittest) private void testDecodeFront(R)(ref R range, size_t expectedNumCodeUnits, size_t line = __LINE__) { - static if(hasLength!R) + static if (hasLength!R) immutable lenBefore = range.length; size_t numCodeUnits; @@ -1372,11 +1372,14 @@ version(unittest) private void testBadDecode(R)(R range, size_t index, size_t li unittest { + debug(utf) printf("utf.decode.unittest\n"); + + assertCTFEable!( + { foreach (S; TypeTuple!(to!string, InputCU!char, RandomCU!char, (string s) => new RefBidirCU!char(s), (string s) => new RefRandomCU!char(s))) { - debug(utf) printf("utf.decode.unittest\n"); enum sHasLength = hasLength!(typeof(S("abcd"))); { @@ -1426,10 +1429,13 @@ unittest testBadDecode(S("\xED\xBE\x80"), 0); testBadDecode(S("\xED\xBF\xBF"), 0); } + }); } unittest { + assertCTFEable!( + { foreach (S; TypeTuple!(to!wstring, InputCU!wchar, RandomCU!wchar, (wstring s) => new RefBidirCU!wchar(s), (wstring s) => new RefRandomCU!wchar(s))) @@ -1463,13 +1469,16 @@ unittest testDecode(str, 2, cast(dchar)0x1400, 3); testDecode(str, 3, cast(dchar)0xB9DDE, 5); } + }); } unittest { - foreach(S; TypeTuple!(to!dstring, RandomCU!dchar, InputCU!dchar, - (dstring s) => new RefBidirCU!dchar(s), - (dstring s) => new RefRandomCU!dchar(s))) + assertCTFEable!( + { + foreach (S; TypeTuple!(to!dstring, RandomCU!dchar, InputCU!dchar, + (dstring s) => new RefBidirCU!dchar(s), + (dstring s) => new RefRandomCU!dchar(s))) { testBothDecode(S([cast(dchar)0x1111]), cast(dchar)0x1111, 1); testBothDecode(S([cast(dchar)0x10000]), cast(dchar)0x10000, 1); @@ -1499,22 +1508,25 @@ unittest testDecode(str, 1, 0x1400, 2); testDecode(str, 2, 0xB9DDE, 3); } + }); } unittest { - foreach(S; TypeTuple!(char[], const(char)[], string, - wchar[], const(wchar)[], wstring, - dchar[], const(dchar)[], dstring)) + assertCTFEable!( { - static assert(isSafe!((){S str; size_t i = 0; decode(str, i);})); - static assert(isSafe!((){S str; size_t i = 0; decodeFront(str, i);})); - static assert(isSafe!((){S str; decodeFront(str);})); - static assert((functionAttributes!((){S str; size_t i = 0; decode(str, i);}) & FunctionAttribute.pure_) != 0); - static assert((functionAttributes!((){S str; size_t i = 0; decodeFront(str, i);}) & - FunctionAttribute.pure_) != 0); - static assert((functionAttributes!((){S str; decodeFront(str);}) & FunctionAttribute.pure_) != 0); + foreach (S; TypeTuple!( char[], const( char)[], string, + wchar[], const(wchar)[], wstring, + dchar[], const(dchar)[], dstring)) + { + static assert(isSafe!({ S str; size_t i = 0; decode(str, i); })); + static assert(isSafe!({ S str; size_t i = 0; decodeFront(str, i); })); + static assert(isSafe!({ S str; decodeFront(str); })); + static assert((functionAttributes!({ S str; size_t i = 0; decode(str, i); }) & FunctionAttribute.pure_) != 0); + static assert((functionAttributes!({ S str; size_t i = 0; decodeFront(str, i); }) & FunctionAttribute.pure_) != 0); + static assert((functionAttributes!({ S str; decodeFront(str); }) & FunctionAttribute.pure_) != 0); } + }); } @@ -1547,7 +1559,7 @@ size_t encode(ref char[4] buf, dchar c) @safe pure if (c <= 0xFFFF) { if (0xD800 <= c && c <= 0xDFFF) - throw (new UTFException("Encoding a surrogate code point in UTF-8")).setSequence(c); + throw new UTFException("Encoding a surrogate code point in UTF-8").setSequence(c); assert(isValidDchar(c)); buf[0] = cast(char)(0xE0 | (c >> 12)); @@ -1566,11 +1578,13 @@ size_t encode(ref char[4] buf, dchar c) @safe pure } assert(!isValidDchar(c)); - throw (new UTFException("Encoding an invalid code point in UTF-8")).setSequence(c); + throw new UTFException("Encoding an invalid code point in UTF-8").setSequence(c); } unittest { + assertCTFEable!( + { char[4] buf; assert(encode(buf, '\u0000') == 1 && buf[0 .. 1] == "\u0000"); @@ -1590,6 +1604,7 @@ unittest assertThrown!UTFException(encode(buf, cast(dchar)0xDC00)); assertThrown!UTFException(encode(buf, cast(dchar)0xDFFF)); assertThrown!UTFException(encode(buf, cast(dchar)0x110000)); + }); } @@ -1599,7 +1614,7 @@ size_t encode(ref wchar[2] buf, dchar c) @safe pure if (c <= 0xFFFF) { if (0xD800 <= c && c <= 0xDFFF) - throw (new UTFException("Encoding an isolated surrogate code point in UTF-16")).setSequence(c); + throw new UTFException("Encoding an isolated surrogate code point in UTF-16").setSequence(c); assert(isValidDchar(c)); buf[0] = cast(wchar)c; @@ -1614,11 +1629,13 @@ size_t encode(ref wchar[2] buf, dchar c) @safe pure } assert(!isValidDchar(c)); - throw (new UTFException("Encoding an invalid code point in UTF-16")).setSequence(c); + throw new UTFException("Encoding an invalid code point in UTF-16").setSequence(c); } unittest { + assertCTFEable!( + { wchar[2] buf; assert(encode(buf, '\u0000') == 1 && buf[0 .. 1] == "\u0000"); @@ -1634,6 +1651,7 @@ unittest assertThrown!UTFException(encode(buf, cast(dchar)0xDC00)); assertThrown!UTFException(encode(buf, cast(dchar)0xDFFF)); assertThrown!UTFException(encode(buf, cast(dchar)0x110000)); + }); } @@ -1667,7 +1685,7 @@ void encode(ref char[] str, dchar c) @safe pure else if (c <= 0xFFFF) { if (0xD800 <= c && c <= 0xDFFF) - throw (new UTFException("Encoding a surrogate code point in UTF-8")).setSequence(c); + throw new UTFException("Encoding a surrogate code point in UTF-8").setSequence(c); assert(isValidDchar(c)); buf[0] = cast(char)(0xE0 | (c >> 12)); @@ -1687,7 +1705,7 @@ void encode(ref char[] str, dchar c) @safe pure else { assert(!isValidDchar(c)); - throw (new UTFException("Encoding an invalid code point in UTF-8")).setSequence(c); + throw new UTFException("Encoding an invalid code point in UTF-8").setSequence(c); } r ~= buf[0 .. L]; } @@ -1698,6 +1716,8 @@ unittest { debug(utf) printf("utf.encode.unittest\n"); + assertCTFEable!( + { char[] s = "abcd".dup; encode(s, cast(dchar)'a'); assert(s.length == 5); @@ -1711,10 +1731,13 @@ unittest encode(s, cast(dchar)'\u2260'); assert(s.length == 10); assert(s == "abcda\xC2\xA9\xE2\x89\xA0"); + }); } unittest { + assertCTFEable!( + { char[] buf; encode(buf, '\u0000'); assert(buf[0 .. $] == "\u0000"); @@ -1734,6 +1757,7 @@ unittest assertThrown!UTFException(encode(buf, cast(dchar)0xDC00)); assertThrown!UTFException(encode(buf, cast(dchar)0xDFFF)); assertThrown!UTFException(encode(buf, cast(dchar)0x110000)); + }); } /// ditto @@ -1744,7 +1768,7 @@ void encode(ref wchar[] str, dchar c) @safe pure if (c <= 0xFFFF) { if (0xD800 <= c && c <= 0xDFFF) - throw (new UTFException("Encoding an isolated surrogate code point in UTF-16")).setSequence(c); + throw new UTFException("Encoding an isolated surrogate code point in UTF-16").setSequence(c); assert(isValidDchar(c)); r ~= cast(wchar)c; @@ -1761,7 +1785,7 @@ void encode(ref wchar[] str, dchar c) @safe pure else { assert(!isValidDchar(c)); - throw (new UTFException("Encoding an invalid code point in UTF-16")).setSequence(c); + throw new UTFException("Encoding an invalid code point in UTF-16").setSequence(c); } str = r; @@ -1769,6 +1793,8 @@ void encode(ref wchar[] str, dchar c) @safe pure unittest { + assertCTFEable!( + { wchar[] buf; encode(buf, '\u0000'); assert(buf[0] == '\u0000'); @@ -1784,13 +1810,14 @@ unittest assertThrown!UTFException(encode(buf, cast(dchar)0xDC00)); assertThrown!UTFException(encode(buf, cast(dchar)0xDFFF)); assertThrown!UTFException(encode(buf, cast(dchar)0x110000)); + }); } /// ditto void encode(ref dchar[] str, dchar c) @safe pure { if ((0xD800 <= c && c <= 0xDFFF) || 0x10FFFF < c) - throw (new UTFException("Encoding an invalid code point in UTF-32")).setSequence(c); + throw new UTFException("Encoding an invalid code point in UTF-32").setSequence(c); assert(isValidDchar(c)); str ~= c; @@ -1798,6 +1825,8 @@ void encode(ref dchar[] str, dchar c) @safe pure unittest { + assertCTFEable!( + { dchar[] buf; encode(buf, '\u0000'); assert(buf[0] == '\u0000'); @@ -1812,26 +1841,16 @@ unittest assertThrown!UTFException(encode(buf, cast(dchar)0xDC00)); assertThrown!UTFException(encode(buf, cast(dchar)0xDFFF)); assertThrown!UTFException(encode(buf, cast(dchar)0x110000)); + }); } /++ Returns the number of code units that are required to encode the code point $(D c) when $(D C) is the character type used to encode it. - -Examples: ------- -assert(codeLength!char('a') == 1); -assert(codeLength!wchar('a') == 1); -assert(codeLength!dchar('a') == 1); - -assert(codeLength!char('\U0010FFFF') == 4); -assert(codeLength!wchar('\U0010FFFF') == 2); -assert(codeLength!dchar('\U0010FFFF') == 1); ------- +/ ubyte codeLength(C)(dchar c) @safe pure nothrow - if(isSomeChar!C) + if (isSomeChar!C) { static if (C.sizeof == 1) { @@ -1853,7 +1872,7 @@ ubyte codeLength(C)(dchar c) @safe pure nothrow } } -//Verify Examples. +/// unittest { assert(codeLength!char('a') == 1); @@ -1871,48 +1890,25 @@ unittest in a string whose character type is $(D C). This is particularly useful when slicing one string with the length of another and the two string types use different character types. - -Examples: ------- -assert(codeLength!char("hello world") == - to!string("hello world").length); -assert(codeLength!wchar("hello world") == - to!wstring("hello world").length); -assert(codeLength!dchar("hello world") == - to!dstring("hello world").length); - -assert(codeLength!char(`プログラミング`) == - to!string(`プログラミング`).length); -assert(codeLength!wchar(`プログラミング`) == - to!wstring(`プログラミング`).length); -assert(codeLength!dchar(`プログラミング`) == - to!dstring(`プログラミング`).length); - -string haystack = `Être sans la verité, ça, ce ne serait pas bien.`; -wstring needle = `Être sans la verité`; -assert(haystack[codeLength!char(needle) .. $] == - `, ça, ce ne serait pas bien.`); ------- +/ size_t codeLength(C, InputRange)(InputRange input) - if(isInputRange!InputRange && is(ElementType!InputRange : dchar)) + if (isInputRange!InputRange && is(ElementType!InputRange : dchar)) { - alias Unqual!(ElementEncodingType!InputRange) EncType; - static if(isSomeString!InputRange && is(EncType == C) && is(typeof(input.length))) - return input.length; - else - { + alias EncType = Unqual!(ElementEncodingType!InputRange); + static if (isSomeString!InputRange && is(EncType == C) && is(typeof(input.length))) + return input.length; + else + { size_t total = 0; - foreach(dchar c; input) + foreach (dchar c; input) total += codeLength!C(c); return total; - } + } } - -//Verify Examples. +/// unittest { assert(codeLength!char("hello world") == @@ -1937,22 +1933,64 @@ unittest unittest { - foreach(S; TypeTuple!(char[], const char[], string, - wchar[], const wchar[], wstring, - dchar[], const dchar[], dstring)) + assertCTFEable!( { - foreach(C; TypeTuple!(char, wchar, dchar)) + foreach (S; TypeTuple!( char[], const char[], string, + wchar[], const wchar[], wstring, + dchar[], const dchar[], dstring)) + { + foreach (C; TypeTuple!(char, wchar, dchar)) { assert(codeLength!C(to!S("Walter Bright")) == to!(C[])("Walter Bright").length); assert(codeLength!C(to!S(`言語`)) == to!(C[])(`言語`).length); assert(codeLength!C(to!S(`ウェブサイト@La_Verité.com`)) == to!(C[])(`ウェブサイト@La_Verité.com`).length); - assert(codeLength!C(to!S(`ウェブサイト@La_Verité.com`).filter!(x => true)()) == + assert(codeLength!C(to!S(`ウェブサイト@La_Verité.com`).filter!(x => true)()) == to!(C[])(`ウェブサイト@La_Verité.com`).length); } } + }); } +/+ +Internal helper function: + +Returns true if it is safe to search for the Codepoint $(D c) inside +code units, without decoding. + +This is a runtime check that is used an optimization in various functions, +particularly, in $(D std.string). + +/ +package bool canSearchInCodeUnits(C)(dchar c) +if (isSomeChar!C) +{ + static if (C.sizeof == 1) + return c <= 0x7F; + else static if (C.sizeof == 2) + return c <= 0xD7FF || (0xE000 <= c && c <= 0xFFFF); + else static if (C.sizeof == 4) + return true; + else + static assert(0); +} +unittest +{ + assert( canSearchInCodeUnits! char('a')); + assert( canSearchInCodeUnits!wchar('a')); + assert( canSearchInCodeUnits!dchar('a')); + assert(!canSearchInCodeUnits! char('ö')); //Important test: ö <= 0xFF + assert(!canSearchInCodeUnits! char(cast(char)'ö')); //Important test: ö <= 0xFF + assert( canSearchInCodeUnits!wchar('ö')); + assert( canSearchInCodeUnits!dchar('ö')); + assert(!canSearchInCodeUnits! char('日')); + assert( canSearchInCodeUnits!wchar('日')); + assert( canSearchInCodeUnits!dchar('日')); + assert(!canSearchInCodeUnits!wchar(cast(wchar)0xDA00)); + assert( canSearchInCodeUnits!dchar(cast(dchar)0xDA00)); + assert(!canSearchInCodeUnits! char('\U00010001')); + assert(!canSearchInCodeUnits!wchar('\U00010001')); + assert( canSearchInCodeUnits!dchar('\U00010001')); +} /* =================== Validation ======================= */ @@ -1963,7 +2001,7 @@ unittest $(D UTFException) if $(D str) is not well-formed. +/ void validate(S)(in S str) @safe pure - if(isSomeString!S) + if (isSomeString!S) { immutable len = str.length; for (size_t i = 0; i < len; ) @@ -2248,16 +2286,6 @@ dstring toUTF32(in dchar[] s) @safe C function keeps it around for any reason, make sure that you keep a reference to it in your D code. Otherwise, it may go away during a garbage collection cycle and cause a nasty bug when the C code tries to use it. - - Examples: --------------------- -auto p1 = toUTFz!(char*)("hello world"); -auto p2 = toUTFz!(const(char)*)("hello world"); -auto p3 = toUTFz!(immutable(char)*)("hello world"); -auto p4 = toUTFz!(char*)("hello world"d); -auto p5 = toUTFz!(const(wchar)*)("hello world"); -auto p6 = toUTFz!(immutable(dchar)*)("hello world"w); --------------------- +/ template toUTFz(P) { @@ -2267,71 +2295,81 @@ template toUTFz(P) } } -/++ Ditto +/ -template toUTFz(P, S) +/// +unittest { - P toUTFz(S str) @system - { - return toUTFzImpl!(P, S)(str); - } + auto p1 = toUTFz!(char*)("hello world"); + auto p2 = toUTFz!(const(char)*)("hello world"); + auto p3 = toUTFz!(immutable(char)*)("hello world"); + auto p4 = toUTFz!(char*)("hello world"d); + auto p5 = toUTFz!(const(wchar)*)("hello world"); + auto p6 = toUTFz!(immutable(dchar)*)("hello world"w); } private P toUTFzImpl(P, S)(S str) @system - if(isSomeString!S && isPointer!P && isSomeChar!(typeof(*P.init)) && - is(Unqual!(typeof(*P.init)) == Unqual!(ElementEncodingType!S)) && - is(immutable(Unqual!(ElementEncodingType!S)) == ElementEncodingType!S)) + if (isSomeString!S && isPointer!P && isSomeChar!(typeof(*P.init)) && + is(Unqual!(typeof(*P.init)) == Unqual!(ElementEncodingType!S)) && + is(immutable(Unqual!(ElementEncodingType!S)) == ElementEncodingType!S)) //immutable(C)[] -> C*, const(C)*, or immutable(C)* { - if(str.empty) + if (str.empty) { typeof(*P.init)[] retval = ['\0']; return retval.ptr; } - alias Unqual!(ElementEncodingType!S) C; + alias C = Unqual!(ElementEncodingType!S); //If the P is mutable, then we have to make a copy. - static if(is(Unqual!(typeof(*P.init)) == typeof(*P.init))) + static if (is(Unqual!(typeof(*P.init)) == typeof(*P.init))) + { return toUTFzImpl!(P, const(C)[])(cast(const(C)[])str); + } else { - immutable p = str.ptr + str.length; + if (!__ctfe) + { + immutable p = str.ptr + str.length; - // Peek past end of str, if it's 0, no conversion necessary. - // Note that the compiler will put a 0 past the end of static - // strings, and the storage allocator will put a 0 past the end - // of newly allocated char[]'s. - // Is p dereferenceable? A simple test: if the p points to an - // address multiple of 4, then conservatively assume the pointer - // might be pointing to a new block of memory, which might be - // unreadable. Otherwise, it's definitely pointing to valid - // memory. - if((cast(size_t)p & 3) && *p == '\0') - return str.ptr; + // Peek past end of str, if it's 0, no conversion necessary. + // Note that the compiler will put a 0 past the end of static + // strings, and the storage allocator will put a 0 past the end + // of newly allocated char[]'s. + // Is p dereferenceable? A simple test: if the p points to an + // address multiple of 4, then conservatively assume the pointer + // might be pointing to a new block of memory, which might be + // unreadable. Otherwise, it's definitely pointing to valid + // memory. + if ((cast(size_t)p & 3) && *p == '\0') + return str.ptr; + } return toUTFzImpl!(P, const(C)[])(cast(const(C)[])str); } } private P toUTFzImpl(P, S)(S str) @system - if(isSomeString!S && isPointer!P && isSomeChar!(typeof(*P.init)) && - is(Unqual!(typeof(*P.init)) == Unqual!(ElementEncodingType!S)) && - !is(immutable(Unqual!(ElementEncodingType!S)) == ElementEncodingType!S)) + if (isSomeString!S && isPointer!P && isSomeChar!(typeof(*P.init)) && + is(Unqual!(typeof(*P.init)) == Unqual!(ElementEncodingType!S)) && + !is(immutable(Unqual!(ElementEncodingType!S)) == ElementEncodingType!S)) //C[] or const(C)[] -> C*, const(C)*, or immutable(C)* { - alias ElementEncodingType!S InChar; - alias typeof(*P.init) OutChar; + alias InChar = ElementEncodingType!S; + alias OutChar = typeof(*P.init); //const(C)[] -> const(C)* or //C[] -> C* or const(C)* - static if((is(const(Unqual!InChar) == InChar) && is(const(Unqual!OutChar) == OutChar)) || - (!is(const(Unqual!InChar) == InChar) && !is(immutable(Unqual!OutChar) == OutChar))) + static if (( is(const(Unqual!InChar) == InChar) && is(const(Unqual!OutChar) == OutChar)) || + (!is(const(Unqual!InChar) == InChar) && !is(immutable(Unqual!OutChar) == OutChar))) { - auto p = str.ptr + str.length; + if (!__ctfe) + { + auto p = str.ptr + str.length; - if((cast(size_t)p & 3) && *p == '\0') - return str.ptr; + if ((cast(size_t)p & 3) && *p == '\0') + return str.ptr; + } str ~= '\0'; return str.ptr; @@ -2349,41 +2387,28 @@ private P toUTFzImpl(P, S)(S str) @system } private P toUTFzImpl(P, S)(S str) - if(isSomeString!S && isPointer!P && isSomeChar!(typeof(*P.init)) && - !is(Unqual!(typeof(*P.init)) == Unqual!(ElementEncodingType!S))) + if (isSomeString!S && isPointer!P && isSomeChar!(typeof(*P.init)) && + !is(Unqual!(typeof(*P.init)) == Unqual!(ElementEncodingType!S))) //C1[], const(C1)[], or immutable(C1)[] -> C2*, const(C2)*, or immutable(C2)* { auto retval = appender!(typeof(*P.init)[])(); - foreach(dchar c; str) + foreach (dchar c; str) retval.put(c); retval.put('\0'); return cast(P)retval.data.ptr; } -//Verify Examples. unittest { - auto p1 = toUTFz!(char*)("hello world"); - auto p2 = toUTFz!(const(char)*)("hello world"); - auto p3 = toUTFz!(immutable(char)*)("hello world"); - auto p4 = toUTFz!(char*)("hello world"d); - auto p5 = toUTFz!(const(wchar)*)("hello world"); - auto p6 = toUTFz!(immutable(dchar)*)("hello world"w); -} - -unittest -{ - import core.exception; import std.algorithm; - import std.typetuple; - size_t zeroLen(C)(const(C)* ptr) + static size_t zeroLen(C)(const(C)* ptr) { size_t len = 0; - while(*ptr != '\0') + while (*ptr != '\0') { ++ptr; ++len; @@ -2392,9 +2417,11 @@ unittest return len; } - foreach(S; TypeTuple!(string, wstring, dstring)) + assertCTFEable!( { - alias Unqual!(ElementEncodingType!S) C; + foreach (S; TypeTuple!(string, wstring, dstring)) + { + alias C = Unqual!(ElementEncodingType!S); auto s1 = to!S("hello\U00010143\u0100\U00010143"); auto temp = new C[](s1.length + 1); @@ -2404,7 +2431,7 @@ unittest auto s2 = assumeUnique(temp); assert(s1 == s2); - foreach(P; TypeTuple!(C*, const(C)*, immutable(C)*)) + foreach (P; TypeTuple!(C*, const(C)*, immutable(C)*)) { auto p1 = toUTFz!P(s1); assert(p1[0 .. s1.length] == s1); @@ -2415,8 +2442,9 @@ unittest assert(p2[s2.length] == '\0'); } } + }); - void test(P, S)(S s, size_t line = __LINE__) + static void test(P, S)(S s, size_t line = __LINE__) { auto p = toUTFz!P(s); immutable len = zeroLen(p); @@ -2425,36 +2453,37 @@ unittest __FILE__, line)); } - foreach(P; TypeTuple!(wchar*, const(wchar)*, immutable(wchar)*, - dchar*, const(dchar)*, immutable(dchar)*)) + assertCTFEable!( + { + foreach (P; TypeTuple!(wchar*, const(wchar)*, immutable(wchar)*, + dchar*, const(dchar)*, immutable(dchar)*)) { test!P("hello\U00010143\u0100\U00010143"); } - - foreach(P; TypeTuple!(char*, const(char)*, immutable(char)*, - dchar*, const(dchar)*, immutable(dchar)*)) + foreach (P; TypeTuple!( char*, const( char)*, immutable( char)*, + dchar*, const(dchar)*, immutable(dchar)*)) { test!P("hello\U00010143\u0100\U00010143"w); } - - foreach(P; TypeTuple!(char*, const(char)*, immutable(char)*, - wchar*, const(wchar)*, immutable(wchar)*)) + foreach (P; TypeTuple!( char*, const( char)*, immutable( char)*, + wchar*, const(wchar)*, immutable(wchar)*)) { test!P("hello\U00010143\u0100\U00010143"d); } - - foreach(S; TypeTuple!(char[], wchar[], dchar[], - const(char)[], const(wchar)[], const(dchar)[])) + foreach (S; TypeTuple!( char[], const( char)[], + wchar[], const(wchar)[], + dchar[], const(dchar)[])) { auto s = to!S("hello\U00010143\u0100\U00010143"); - foreach(P; TypeTuple!(char*, wchar*, dchar*, - const(char)*, const(wchar)*, const(dchar)*, - immutable(char)*, immutable(wchar)*, immutable(dchar)*)) + foreach (P; TypeTuple!( char*, const( char)*, immutable( char)*, + wchar*, const(wchar)*, immutable(wchar)*, + dchar*, const(dchar)*, immutable(dchar)*)) { test!P(s); } } + }); } @@ -2466,18 +2495,16 @@ unittest that take an $(D LPWSTR) or $(D LPCWSTR) argument. +/ const(wchar)* toUTF16z(C)(const(C)[] str) - if(isSomeChar!C) + if (isSomeChar!C) { return toUTFz!(const(wchar)*)(str); } unittest { - import std.typetuple; - //toUTFz is already thoroughly tested, so this will just verify that //toUTF16z compiles properly for the various string types. - foreach(S; TypeTuple!(string, wstring, dstring)) + foreach (S; TypeTuple!(string, wstring, dstring)) static assert(__traits(compiles, toUTF16z(to!S("hello world")))); } @@ -2488,60 +2515,29 @@ unittest { debug(utf) printf("utf.toUTF.unittest\n"); - string c; - wstring w; - dstring d; + assertCTFEable!( + { + assert(toUTF16("hello"c) == "hello"); + assert(toUTF32("hello"c) == "hello"); + assert(toUTF8 ("hello"w) == "hello"); + assert(toUTF32("hello"w) == "hello"); + assert(toUTF8 ("hello"d) == "hello"); + assert(toUTF16("hello"d) == "hello"); - c = "hello"; - w = toUTF16(c); - assert(w == "hello"); - d = toUTF32(c); - assert(d == "hello"); - c = toUTF8(w); - assert(c == "hello"); - d = toUTF32(w); - assert(d == "hello"); + assert(toUTF16("hel\u1234o"c) == "hel\u1234o"); + assert(toUTF32("hel\u1234o"c) == "hel\u1234o"); + assert(toUTF8 ("hel\u1234o"w) == "hel\u1234o"); + assert(toUTF32("hel\u1234o"w) == "hel\u1234o"); + assert(toUTF8 ("hel\u1234o"d) == "hel\u1234o"); + assert(toUTF16("hel\u1234o"d) == "hel\u1234o"); - c = toUTF8(d); - assert(c == "hello"); - w = toUTF16(d); - assert(w == "hello"); - - - c = "hel\u1234o"; - w = toUTF16(c); - assert(w == "hel\u1234o"); - d = toUTF32(c); - assert(d == "hel\u1234o"); - - c = toUTF8(w); - assert(c == "hel\u1234o"); - d = toUTF32(w); - assert(d == "hel\u1234o"); - - c = toUTF8(d); - assert(c == "hel\u1234o"); - w = toUTF16(d); - assert(w == "hel\u1234o"); - - - c = "he\U0010AAAAllo"; - w = toUTF16(c); - //foreach (wchar c; w) printf("c = x%x\n", c); - //foreach (wchar c; cast(wstring)"he\U0010AAAAllo") printf("c = x%x\n", c); - assert(w == "he\U0010AAAAllo"); - d = toUTF32(c); - assert(d == "he\U0010AAAAllo"); - - c = toUTF8(w); - assert(c == "he\U0010AAAAllo"); - d = toUTF32(w); - assert(d == "he\U0010AAAAllo"); - - c = toUTF8(d); - assert(c == "he\U0010AAAAllo"); - w = toUTF16(d); - assert(w == "he\U0010AAAAllo"); + assert(toUTF16("he\U0010AAAAllo"c) == "he\U0010AAAAllo"); + assert(toUTF32("he\U0010AAAAllo"c) == "he\U0010AAAAllo"); + assert(toUTF8 ("he\U0010AAAAllo"w) == "he\U0010AAAAllo"); + assert(toUTF32("he\U0010AAAAllo"w) == "he\U0010AAAAllo"); + assert(toUTF8 ("he\U0010AAAAllo"d) == "he\U0010AAAAllo"); + assert(toUTF16("he\U0010AAAAllo"d) == "he\U0010AAAAllo"); + }); } @@ -2556,17 +2552,20 @@ unittest $(D UTFException) if $(D str) is not well-formed. +/ size_t count(C)(const(C)[] str) @trusted pure - if(isSomeChar!C) + if (isSomeChar!C) { return walkLength(str); } unittest { + assertCTFEable!( + { assert(count("") == 0); assert(count("a") == 1); assert(count("abc") == 3); assert(count("\u20AC100") == 4); + }); } diff --git a/std/uuid.d b/std/uuid.d index 28106ba93..9c1c2de7c 100644 --- a/std/uuid.d +++ b/std/uuid.d @@ -99,7 +99,7 @@ $(MYREF oidNamespace) $(MYREF x500Namespace) ) */ module std.uuid; -import std.algorithm, std.array, std.ascii; +import std.array, std.ascii; import std.conv, std.digest.md, std.digest.sha, std.random, std.range, std.string, std.traits; /** @@ -138,7 +138,7 @@ public struct UUID return result; } - unittest + @safe pure unittest { assert(UUID(cast(ubyte[16])[138, 179, 6, 14, 44, 186, 79, 35, 183, 76, 181, 45, 179, 189, 251, 70])._toString() == "8ab3060e-2cba-4f23-b74c-b52db3bdfb46"); @@ -215,7 +215,7 @@ public struct UUID * that is not needed right now. */ - unittest + @safe pure unittest { UUID tmp; tmp.data = cast(ubyte[16])[0,1,2,3,4,5,6,7,8,9,10,11,12, @@ -234,28 +234,25 @@ public struct UUID /** * Construct a UUID struct from the 16 byte representation * of a UUID. - * - * Examples: - * ------------------------- - * ubyte[16] data = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]; - * auto tmp = UUID(data); - * assert(tmp.data == data); - * ------------------------- */ - @safe pure nothrow this()(ubyte[16] uuidData) + @safe pure nothrow this(ref in ubyte[16] uuidData) + { + data = uuidData; + } + /// ditto + @safe pure nothrow this(in ubyte[16] uuidData) { data = uuidData; } - unittest + /// + @safe pure unittest { - ubyte[16] data = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]; - auto tmp = UUID(data); - assert(tmp.data == data); - - enum UUID ctfeID = UUID(cast(ubyte[16])[0,1,2,3,4,5,6,7,8,9,10,11,12, - 13,14,15]); - assert(ctfeID == tmp); + enum ubyte[16] data = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]; + auto uuid = UUID(data); + enum ctfe = UUID(data); + assert(uuid.data == data); + assert(ctfe.data == data); } /+ @@ -330,10 +327,8 @@ public struct UUID * enum ctfeID = UUID("8ab3060e-2cba-4f23-b74c-b52db3bdfb46"); * //here parsing is done at compile time, no runtime overhead! * ------------------------- - * - * BUGS: Could be pure, but this depends on parse!(string, 16). */ - @trusted this(T)(T[] uuid) if(isSomeChar!(Unqual!T)) + this(T)(in T[] uuid) if(isSomeChar!(Unqual!T)) { if(uuid.length < 36) { @@ -391,7 +386,7 @@ public struct UUID this.data = data2; } - unittest + @safe pure unittest { import std.exception; import std.typetuple; @@ -451,19 +446,11 @@ public struct UUID /** * Returns true if and only if the UUID is equal * to {00000000-0000-0000-0000-000000000000} - * - * Examples: - * ------------------------- - * UUID id; - * assert(id.empty); - * id = UUID("00000000-0000-0000-0000-000000000001"); - * assert(!id.empty); - * ------------------------- */ @trusted pure nothrow @property bool empty() const { if(__ctfe) - return find!"a!=0"(data[]).empty; //simple + return data == (ubyte[16]).init; auto p = cast(const(size_t*))data.ptr; static if(size_t.sizeof == 4) @@ -474,11 +461,17 @@ public struct UUID static assert(false, "nonsense, it's not 32 or 64 bit"); } - unittest + /// + @safe pure unittest { UUID id; assert(id.empty); + id = UUID("00000000-0000-0000-0000-000000000001"); + assert(!id.empty); + } + @safe pure unittest + { ubyte[16] getData(size_t i) { ubyte[16] data; @@ -493,7 +486,7 @@ public struct UUID enum ctfeEmpty = UUID.init.empty; assert(ctfeEmpty); - + bool ctfeTest() { for(size_t i = 0; i < 16; i++) @@ -516,12 +509,6 @@ public struct UUID * * See_Also: * $(MYREF3 UUID.Variant, Variant) - * - * Examples: - * ------------------------ - * assert(UUID("8ab3060e-2cba-4f23-b74c-b52db3bdfb46").variant - * == UUID.Variant.rfc4122); - * ------------------------ */ @safe pure nothrow @property Variant variant() const { @@ -542,13 +529,13 @@ public struct UUID } } - //Verify Example. - unittest + /// + @safe pure unittest { assert(UUID("8ab3060e-2cba-4f23-b74c-b52db3bdfb46").variant == UUID.Variant.rfc4122); } - unittest + pure unittest { Variant[ubyte] tests = cast(Variant[ubyte])[0x00 : Variant.ncs, 0x10 : Variant.ncs, @@ -582,12 +569,6 @@ public struct UUID * * See_Also: * $(MYREF3 UUID.Version, Version) - * - * Examples: - * ---------------------------- - * assert(UUID("8ab3060e-2cba-4f23-b74c-b52db3bdfb46").uuidVersion - * == UUID.Version.randomNumberBased); - * ---------------------------- */ @safe pure nothrow @property Version uuidVersion() const { @@ -608,7 +589,7 @@ public struct UUID return Version.unknown; } - //Verify Example. + /// unittest { assert(UUID("8ab3060e-2cba-4f23-b74c-b52db3bdfb46").uuidVersion @@ -643,38 +624,24 @@ public struct UUID /** * Swap the data of this UUID with the data of rhs. - * - * Note: linear complexity - * - * Examples: - * ---------------------------- - * UUID u1; - * auto u2 = UUID(cast(ubyte[16])[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]); - * u1.swap(u2); - * - * assert(u1.data == cast(ubyte[16])[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]); - * assert(u2.data == cast(ubyte[16])[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]); - * ---------------------------- */ - @safe nothrow void swap(ref UUID rhs) + @safe nothrow pure void swap(ref UUID rhs) { - std.algorithm.swap(this.data, rhs.data); + auto bck = data; + data = rhs.data; + rhs.data = bck; } + /// unittest { + immutable ubyte[16] data = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]; UUID u1; - auto u2 = UUID(cast(ubyte[16])[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]); + UUID u2 = UUID(data); u1.swap(u2); - auto values1 = cast(ubyte[16])[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; - auto values2 = cast(ubyte[16])[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]; - assert(u1.data == values2); - assert(u2.data == values1); - - u1.swap(u2); - assert(u2.data == values2); - assert(u1.data == values1); + assert(u1 == UUID(data)); + assert(u2 == UUID.init); } /** @@ -701,7 +668,7 @@ public struct UUID * sort(ids); * ------------------------- */ - @safe pure nothrow bool opEquals(const UUID s) const + @safe pure nothrow bool opEquals(in UUID s) const { return s.data == this.data; } @@ -709,7 +676,7 @@ public struct UUID /** * ditto */ - @safe pure nothrow bool opEquals(ref const UUID s) const + @safe pure nothrow bool opEquals(ref in UUID s) const { return s.data == this.data; } @@ -717,7 +684,7 @@ public struct UUID /** * ditto */ - @safe pure nothrow int opCmp(ref const UUID s) const + @safe pure nothrow int opCmp(in UUID s) const { return cmp(this.data[], s.data[]); } @@ -725,7 +692,7 @@ public struct UUID /** * ditto */ - @safe pure nothrow int opCmp(const UUID s) const + @safe pure nothrow int opCmp(ref in UUID s) const { return cmp(this.data[], s.data[]); } @@ -796,12 +763,6 @@ public struct UUID /** * Return the UUID as a string in the canonical form. - * - * Examples: - * ---------------------------------- - * auto id = UUID("8ab3060e-2cba-4f23-b74c-b52db3bdfb46"); - * assert(id.toString() == "8ab3060e-2cba-4f23-b74c-b52db3bdfb46"); - * ---------------------------------- */ void toString(scope void delegate(const(char)[]) sink) const { @@ -818,6 +779,14 @@ public struct UUID assert(0, "It should be impossible for idup to throw."); } + /// + @safe pure unittest + { + immutable str = "8ab3060e-2cba-4f23-b74c-b52db3bdfb46"; + auto id = UUID(str); + assert(id.toString() == str); + } + unittest { auto u1 = UUID(cast(ubyte[16])[138, 179, 6, 14, 44, 186, 79, @@ -836,11 +805,6 @@ public struct UUID } } -unittest -{ - assert(UUID.init.empty); -} - /** * This function generates a name based (Version 3) UUID from a namespace UUID and a name. @@ -891,7 +855,7 @@ unittest /** * ditto */ -@trusted pure UUID md5UUID(const(ubyte[]) data, const UUID namespace = UUID.init) +@safe pure UUID md5UUID(const(ubyte[]) data, const UUID namespace = UUID.init) { MD5 hash; hash.start(); @@ -920,7 +884,7 @@ unittest return u; } -unittest +@safe pure unittest { auto simpleID = md5UUID("test.uuid.any.string"); assert(simpleID.data == cast(ubyte[16])[126, 206, 86, 72, 29, 233, 62, 213, 178, 139, 198, 136, @@ -993,7 +957,7 @@ unittest * for strings and wstrings. It's always possible to pass wstrings and dstrings * by using the ubyte[] function overload (but be aware of endianness issues!). */ -@trusted pure UUID sha1UUID(const(char[]) name, const UUID namespace = UUID.init) +@safe pure UUID sha1UUID(in char[] name, const UUID namespace = UUID.init) { return sha1UUID(cast(const(ubyte[]))name, namespace); } @@ -1001,7 +965,7 @@ unittest /** * ditto */ -@trusted pure UUID sha1UUID(const(ubyte[]) data, const UUID namespace = UUID.init) +@safe pure UUID sha1UUID(in ubyte[] data, const UUID namespace = UUID.init) { SHA1 sha; sha.start(); @@ -1031,7 +995,7 @@ unittest return u; } -unittest +@safe pure unittest { auto simpleID = sha1UUID("test.uuid.any.string"); assert(simpleID.data == cast(ubyte[16])[16, 209, 239, 61, 99, 12, 94, 70, 159, 79, 255, 250, @@ -1079,7 +1043,7 @@ unittest * auto uuid3 = randomUUID(gen); * ------------------------------------------ */ -@trusted UUID randomUUID()() +@trusted UUID randomUUID() { return randomUUID(rndGen); } @@ -1094,7 +1058,7 @@ static assert(is(typeof(rndGen) == Mt19937)); /** * ditto */ -UUID randomUUID(RNG)(ref RNG randomGen) if(isUniformRNG!(RNG) && +@trusted UUID randomUUID(RNG)(ref RNG randomGen) if(isUniformRNG!(RNG) && isIntegral!(typeof(RNG.front))) { enum size_t elemSize = typeof(RNG.front).sizeof; @@ -1176,11 +1140,8 @@ unittest * enum ctfeID = parseUUID("8ab3060e-2cba-4f23-b74c-b52db3bdfb46"); * //here parsing is done at compile time, no runtime overhead! * ------------------------- - * - * BUGS: Could be pure, but this depends on parse!(string, 16). */ - -@trusted UUID parseUUID(T)(T uuidString) if(isSomeString!T) +UUID parseUUID(T)(T uuidString) if(isSomeString!T) { return parseUUID(uuidString); } @@ -1192,7 +1153,7 @@ UUID parseUUID(Range)(ref Range uuidRange) if(isInputRange!Range static if(isForwardRange!Range) auto errorCopy = uuidRange.save; - void parserError(size_t pos, UUIDParsingException.Reason reason, string message, Throwable next = null, + void parserError()(size_t pos, UUIDParsingException.Reason reason, string message, Throwable next = null, string file = __FILE__, size_t line = __LINE__) { static if(isForwardRange!Range) @@ -1228,7 +1189,7 @@ UUID parseUUID(Range)(ref Range uuidRange) if(isInputRange!Range size_t element = 0; //skip garbage - size_t skip() + size_t skip()() { size_t skipped; while(!uuidRange.empty && !isHexDigit(uuidRange.front)) @@ -1323,7 +1284,7 @@ UUID parseUUID(Range)(ref Range uuidRange) if(isInputRange!Range return result; } -unittest +@safe pure unittest { import std.exception; import std.typetuple; @@ -1396,7 +1357,7 @@ unittest id = parseHelper!S("///8ab3060e2cba4f23b74cb52db3bdfb46||"); enum ctfeId = parseHelper!S("8ab3060e-2cba-4f23-b74c-b52db3bdfb46"); assert(parseHelper!S("8AB3060E-2cba-4f23-b74c-b52db3bdfb46") == ctfeId); - + //Test valid, working cases assert(parseHelper!S("00000000-0000-0000-0000-000000000000").empty); assert(parseHelper!S("8AB3060E-2CBA-4F23-b74c-B52Db3BDFB46").data @@ -1517,6 +1478,7 @@ enum x500Namespace = UUID("6ba7b814-9dad-11d1-80b4-00c04fd430c8"); enum uuidRegex = r"[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}" "-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}"; +/// unittest { import std.algorithm; @@ -1535,9 +1497,10 @@ unittest { found ~= UUID(c.hit); } - assert(found.length == 2); - assert(canFind(found, UUID("6ba7b814-9dad-11d1-80b4-00c04fd430c8"))); - assert(canFind(found, UUID("8ab3060e-2cba-4f23-b74c-b52db3bdfb46"))); + assert(found == [ + UUID("6ba7b814-9dad-11d1-80b4-00c04fd430c8"), + UUID("8ab3060e-2cba-4f23-b74c-b52db3bdfb46"), + ]); } /** @@ -1546,34 +1509,33 @@ unittest */ public class UUIDParsingException : Exception { - public: - /** - * The reason why parsing the UUID string failed (if known) - */ - enum Reason - { - unknown, /// - tooLittle, ///The passed in input was correct, but more input was expected. - tooMuch, ///The input data is too long (There's no guarantee the first part of the data is valid) - invalidChar, ///Encountered an invalid character + /** + * The reason why parsing the UUID string failed (if known) + */ + enum Reason + { + unknown, /// + tooLittle, ///The passed in input was correct, but more input was expected. + tooMuch, ///The input data is too long (There's no guarantee the first part of the data is valid) + invalidChar, ///Encountered an invalid character - } - ///ditto - Reason reason; - ///The original input string which should have been parsed. - string input; - ///The position in the input string where the error occurred. - size_t position; + } + ///ditto + Reason reason; + ///The original input string which should have been parsed. + string input; + ///The position in the input string where the error occurred. + size_t position; - private this(string input, size_t pos, Reason why = Reason.unknown, string msg = "", - Throwable next = null, string file = __FILE__, size_t line = __LINE__) - { - input = input; - position = pos; - reason = why; - string message = format("An error occured in the UUID parser: %s\n" ~ - " * Input:\t'%s'\n * Position:\t%s", msg, replace(replace(input, - "\r", "\\r"), "\n", "\\n"), pos); - super(message, file, line, next); - } + private this(string input, size_t pos, Reason why = Reason.unknown, string msg = "", + Throwable next = null, string file = __FILE__, size_t line = __LINE__) pure @trusted + { + input = input; + position = pos; + reason = why; + string message = format("An error occured in the UUID parser: %s\n" ~ + " * Input:\t'%s'\n * Position:\t%s", msg, replace(replace(input, + "\r", "\\r"), "\n", "\\n"), pos); + super(message, file, line, next); + } } diff --git a/std/variant.d b/std/variant.d index 710279e0f..024ca13b4 100644 --- a/std/variant.d +++ b/std/variant.d @@ -65,7 +65,8 @@ */ module std.variant; -import std.traits, std.c.string, std.typetuple, std.conv, std.exception; +import std.c.string, std.conv, std.exception, std.traits, std.typecons, + std.typetuple; @trusted: @@ -416,7 +417,8 @@ private: { enforce(0, "Not implemented"); } - static if (isDynamicArray!(A) && allowed!(typeof(A.init[0]))) + // Can't handle void arrays as there isn't any result to return. + static if (isDynamicArray!(A) && !is(Unqual!(typeof(A.init[0])) == void) && allowed!(typeof(A.init[0]))) { // array type; input and output are the same VariantN auto result = cast(VariantN*) parm; @@ -429,7 +431,7 @@ private: && allowed!(typeof(A.init.values[0]))) { auto result = cast(VariantN*) parm; - *result = (*zis)[result.get!(typeof(A.keys[0]))]; + *result = (*zis)[result.get!(typeof(A.init.keys[0]))]; break; } else @@ -450,8 +452,8 @@ private: else static if (isAssociativeArray!(A)) { auto args = cast(VariantN*) parm; - (*zis)[args[1].get!(typeof(A.keys[0]))] - = args[0].get!(typeof(A.values[0])); + (*zis)[args[1].get!(typeof(A.init.keys[0]))] + = args[0].get!(typeof(A.init.values[0])); break; } else @@ -460,7 +462,7 @@ private: } case OpID.catAssign: - static if (is(typeof((*zis)[0])) && is(typeof((*zis) ~= *zis))) + static if (!is(Unqual!(typeof((*zis)[0])) == void) && is(typeof((*zis)[0])) && is(typeof((*zis) ~= *zis))) { // array type; parm is the element to append auto arg = cast(VariantN*) parm; @@ -493,7 +495,43 @@ private: } case OpID.apply: - assert(0); + static if (!isFunctionPointer!A && !isDelegate!A) + { + enforce(0, text("Cannot apply `()' to a value of type `", + A.stringof, "'.")); + } + else + { + alias ParamTypes = ParameterTypeTuple!A; + auto p = cast(VariantN*) parm; + auto argCount = p.get!size_t; + // To assign the tuple we need to use the unqualified version, + // otherwise we run into issues such as with const values. + // We still get the actual type from the Variant though + // to ensure that we retain const correctness. + Tuple!(staticMap!(Unqual, ParamTypes)) t; + enforce(t.length == argCount, + text("Argument count mismatch: ", + A.stringof, " expects ", t.length, + " argument(s), not ", argCount, ".")); + auto variantArgs = p[1 .. argCount + 1]; + foreach (i, T; ParamTypes) + { + t[i] = cast()variantArgs[i].get!T; + } + + auto args = cast(Tuple!(ParamTypes))t; + static if(is(ReturnType!A == void)) + { + (*zis)(args.expand); + *p = VariantN.init; // void returns uninitialized Variant. + } + else + { + *p = (*zis)(args.expand); + } + } + break; default: assert(false); } @@ -564,6 +602,18 @@ public: return this; } + VariantN opCall(P...)(auto ref P params) + { + VariantN pack[P.length + 1]; + pack[0] = P.length; + foreach (i, _; params) + { + pack[i + 1] = params[i]; + } + fptr(OpID.apply, &store, &pack); + return pack[0]; + } + /** Returns true if and only if the $(D_PARAM VariantN) object * holds a valid value (has been initialized with, or assigned * from, a valid value). @@ -787,6 +837,12 @@ public: cast(void*) &temp); } + // workaround for bug 10567 fix + int opCmp(ref const VariantN rhs) const + { + return (cast()this).opCmp!(VariantN)(cast()rhs); + } + /** * Ordering comparison used by the "<", "<=", ">", and ">=" * operators. In case comparison is not sensible between the held @@ -1095,6 +1151,18 @@ public: } } +unittest +{ + Variant v; + int foo() { return 42; } + v = &foo; + assert(v() == 42); + + static int bar(string s) { return to!int(s); } + v = &bar; + assert(v("43") == 43); +} + //Issue# 8195 unittest { @@ -1115,6 +1183,16 @@ unittest assert(v == S.init); } +// Issue #10961 +unittest +{ + // Primarily test that we can assign a void[] to a Variant. + void[] elements = cast(void[])[1, 2, 3]; + Variant v = elements; + void[] returned = v.get!(void[]); + assert(returned == elements); +} + /** * Algebraic data type restricted to a closed set of possible * types. It's an alias for a $(D_PARAM VariantN) with an @@ -1554,6 +1632,36 @@ unittest v = null; } +// Const parameters with opCall, issue 11361. +unittest +{ + static string t1(string c) { + return c ~ "a"; + } + + static const(char)[] t2(const(char)[] p) { + return p ~ "b"; + } + + static char[] t3(int p) { + return p.text.dup; + } + + Variant v1 = &t1; + Variant v2 = &t2; + Variant v3 = &t3; + + assert(v1("abc") == "abca"); + assert(v1("abc").type == typeid(string)); + assert(v2("abc") == "abcb"); + + assert(v2(cast(char[])("abc".dup)) == "abcb"); + assert(v2("abc").type == typeid(const(char)[])); + + assert(v3(4) == ['4']); + assert(v3(4).type == typeid(char[])); +} + // Ordering comparisons of incompatible types, e.g. issue 7990. unittest { @@ -1577,6 +1685,18 @@ unittest assertThrown!VariantException(Variant(A(3)) < Variant(A(4))); } +// Handling of void function pointers / delegates, e.g. issue 11360 +unittest +{ + static void t1() { } + Variant v = &t1; + assert(v() == Variant.init); + + static int t2() { return 3; } + Variant v2 = &t2; + assert(v2() == 3); +} + /** * Applies a delegate or function to the given Algebraic depending on the held type, * ensuring that all types are handled by the visiting functions. diff --git a/std/windows/charset.d b/std/windows/charset.d index 1199ca893..f99ff744e 100644 --- a/std/windows/charset.d +++ b/std/windows/charset.d @@ -16,6 +16,7 @@ * http://www.boost.org/LICENSE_1_0.txt) */ module std.windows.charset; +version (Windows): private import std.conv; private import std.c.windows.windows; diff --git a/std/windows/iunknown.d b/std/windows/iunknown.d index e85bce0c6..7305115a5 100644 --- a/std/windows/iunknown.d +++ b/std/windows/iunknown.d @@ -1,6 +1,7 @@ // Written in the D programming language. module std.windows.iunknown; +version (Windows): // Replaced by: public import std.c.windows.com; diff --git a/std/windows/registry.d b/std/windows/registry.d index f3c7b62ca..cc80074be 100644 --- a/std/windows/registry.d +++ b/std/windows/registry.d @@ -36,6 +36,7 @@ * * ////////////////////////////////////////////////////////////////////////// */ module std.windows.registry; +version (Windows): import std.array; import std.system : Endian, endian; @@ -68,11 +69,13 @@ class Win32Exception : Exception { int error; + @safe pure nothrow this(string message, string fn = __FILE__, size_t ln = __LINE__, Throwable next = null) { super(message, fn, ln, next); } + @safe pure this(string message, int errnum, string fn = __FILE__, size_t ln = __LINE__, Throwable next = null) { super(text(message, " (", errnum, ")"), fn, ln, next); @@ -116,6 +119,7 @@ public: Params: message = The message associated with the exception. */ + @safe pure this(string message, string fn = __FILE__, size_t ln = __LINE__, Throwable next = null) { super(message, fn, ln, next); @@ -128,6 +132,7 @@ public: message = The message associated with the exception. error = The Win32 error number associated with the exception. */ + @safe pure this(string message, int error, string fn = __FILE__, size_t ln = __LINE__, Throwable next = null) { super(message, error, fn, ln, next); @@ -520,6 +525,8 @@ in } body { + import core.bitop : bswap; + REG_VALUE_TYPE type; // See bugzilla 961 on this @@ -631,6 +638,8 @@ in } body { + import core.bitop : bswap; + REG_VALUE_TYPE type; DWORD cbData = value.sizeof; @@ -782,12 +791,14 @@ private void regProcessNthValue(HKEY hkey, scope void delegate(scope LONG delega */ class Key { + @safe pure nothrow invariant() { assert(m_hkey !is null); } private: + @safe pure nothrow this(HKEY hkey, string name, bool created) in { @@ -1147,12 +1158,14 @@ private: */ class Value { + @safe pure nothrow invariant() { assert(m_key !is null); } private: + @safe pure nothrow this(Key key, string name, REG_VALUE_TYPE type) in { @@ -1363,12 +1376,14 @@ foreach (string subkeyName; key.keyNames) */ class KeyNameSequence { + @safe pure nothrow invariant() { assert(m_key !is null); } private: + @safe pure nothrow this(Key key) { m_key = key; @@ -1458,12 +1473,14 @@ foreach (Key subkey; key.keys) */ class KeySequence { + @safe pure nothrow invariant() { assert(m_key !is null); } private: + @safe pure nothrow this(Key key) { m_key = key; @@ -1565,12 +1582,14 @@ foreach (string valueName; key.valueNames) */ class ValueNameSequence { + @safe pure nothrow invariant() { assert(m_key !is null); } private: + @safe pure nothrow this(Key key) { m_key = key; @@ -1659,12 +1678,14 @@ foreach (Value value; key.values) */ class ValueSequence { + @safe pure nothrow invariant() { assert(m_key !is null); } private: + @safe pure nothrow this(Key key) { m_key = key; diff --git a/std/windows/syserror.d b/std/windows/syserror.d index c870dd40e..56df1290e 100644 --- a/std/windows/syserror.d +++ b/std/windows/syserror.d @@ -3,51 +3,79 @@ /** * Convert Win32 error code to string. * - * Copyright: Copyright Digital Mars 2006 - 2009. + * Copyright: Copyright Digital Mars 2006 - 2013. * License: Boost License 1.0. * Authors: $(WEB digitalmars.com, Walter Bright) * Credits: Based on code written by Regan Heath * - * Copyright Digital Mars 2006 - 2009. + * Copyright Digital Mars 2006 - 2013. * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) */ module std.windows.syserror; +version (Windows): -private import std.windows.charset; -private import std.c.windows.windows; +import std.windows.charset; +import core.sys.windows.windows; -string sysErrorString(uint errcode) +// MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) is the user's default language +string sysErrorString( + uint errCode, + int langId = LANG_NEUTRAL, + int subLangId = SUBLANG_DEFAULT) @trusted { - char[] result; - char* buffer; - DWORD r; + wchar* pWideMessage; - r = FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - null, - errcode, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - cast(LPTSTR)&buffer, - 0, - null); + DWORD length = FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + null, + errCode, + MAKELANGID(langId, subLangId), + cast(LPWSTR)&pWideMessage, + 0, + null); + + if(length == 0) + { + throw new Exception( + "failed getting error string for WinAPI error code: " ~ + sysErrorString(GetLastError())); + } + + scope(exit) LocalFree(cast(HLOCAL)pWideMessage); /* Remove \r\n from error string */ - if (r >= 2) - r -= 2; + if (length >= 2) + length -= 2; - /* Create 0 terminated copy on GC heap because fromMBSz() - * may return it. - */ - result = new char[r + 1]; - result[0 .. r] = buffer[0 .. r]; - result[r] = 0; + static int wideToNarrow(wchar[] wide, char[] narrow) nothrow + { + return WideCharToMultiByte( + CP_UTF8, + 0, // No WC_COMPOSITECHECK, as system error messages are precomposed + wide.ptr, + cast(int)wide.length, + narrow.ptr, + cast(int)narrow.length, + null, + null); + } - auto res = std.windows.charset.fromMBSz(cast(immutable)result.ptr); + auto wideMessage = pWideMessage[0 .. length]; - LocalFree(cast(HLOCAL)buffer); - return res; + int requiredCodeUnits = wideToNarrow(wideMessage, null); + + // If FormatMessage with FORMAT_MESSAGE_FROM_SYSTEM succeeds, + // there's no reason for the returned UTF-16 to be invalid. + assert(requiredCodeUnits > 0); + + auto message = new char[requiredCodeUnits]; + auto writtenLength = wideToNarrow(wideMessage, message); + + assert(writtenLength > 0); // Ditto + + return cast(immutable)message[0 .. writtenLength]; } diff --git a/std/xml.d b/std/xml.d index aaa58e5e7..489ee95a2 100644 --- a/std/xml.d +++ b/std/xml.d @@ -377,7 +377,7 @@ S encode(S)(S s) lastI = i + 1; } - if (!result.data) return s; + if (!result.data.ptr) return s; result.put(s[lastI .. $]); return result.data; } @@ -441,6 +441,8 @@ enum DecodeMode */ string decode(string s, DecodeMode mode=DecodeMode.LOOSE) { + import std.utf : encode; + if (mode == DecodeMode.NONE) return s; char[] buffer; @@ -691,7 +693,7 @@ class Element : Item * Constructs an Element from a Tag. * * Params: - * tag = the start or empty tag of the element. + * tag_ = the start or empty tag of the element. */ this(const(Tag) tag_) { @@ -967,7 +969,7 @@ class Element : Item * $(DDOC_ENUM_MEMBERS EMPTY) Used for empty tags * */ -enum TagType { START, END, EMPTY }; +enum TagType { START, END, EMPTY } /** * Class representing an XML tag. @@ -1115,9 +1117,10 @@ class Tag override int opCmp(Object o) { const tag = toType!(const Tag)(o); + // Note that attr is an AA, so the comparison is nonsensical (bug 10381) return ((name != tag.name) ? ( name < tag.name ? -1 : 1 ) : - ((attr != tag.attr) ? ( attr < tag.attr ? -1 : 1 ) : + ((attr != tag.attr) ? ( cast(void *)attr < cast(void*)tag.attr ? -1 : 1 ) : ((type != tag.type) ? ( type < tag.type ? -1 : 1 ) : 0 ))); } @@ -1154,7 +1157,7 @@ class Tag { string s = "<" ~ name; foreach(key,val;attr) - s ~= format(" %s=\"%s\"",key,decode(val,DecodeMode.LOOSE)); + s ~= format(" %s=\"%s\"",key,encode(val)); return s; } @@ -1653,7 +1656,7 @@ class DocumentParser : ElementParser * This is enforced by the function's in contract. * * Params: - * xmltext = the entire XML document as text + * xmlText_ = the entire XML document as text * */ this(string xmlText_) @@ -2729,6 +2732,13 @@ EOS"; xml.parse(); } +unittest +{ + string s = ``; + auto doc = new Document(s); + assert(doc.toString() == s); +} + /** The base class for exceptions thrown by this module */ class XMLException : Exception { this(string msg) { super(msg); } } diff --git a/std/zip.d b/std/zip.d index b3a921b3d..b844efd18 100644 --- a/std/zip.d +++ b/std/zip.d @@ -50,25 +50,20 @@ class ZipException : Exception } } +/** + * Compression method used by ArchiveMember + */ +enum CompressionMethod : ushort +{ + none = 0, /// No compression, just archiving + deflate = 8 /// Deflate algorithm. Use zlib library to compress +} + /** * A member of the ZipArchive. */ -class ArchiveMember +final class ArchiveMember { - ushort madeVersion = 20; /// Read Only - ushort extractVersion = 20; /// Read Only - ushort flags; /// Read/Write: normally set to 0 - ushort compressionMethod; /// Read/Write: 0 for compression, 8 for deflate - std.datetime.DosFileTime time; /// Read/Write: Last modified time of the member. It's in the DOS date/time format. - uint crc32; /// Read Only: cyclic redundancy check (CRC) value - uint compressedSize; /// Read Only: size of data of member in compressed form. - uint expandedSize; /// Read Only: size of data of member in expanded form. - ushort diskNumber; /// Read Only: should be 0. - ushort internalAttributes; /// Read/Write - uint externalAttributes; /// Read/Write - - private uint offset; - /** * Read/Write: Usually the file name of the archive member; it is used to * index the archive directory for the member. Each member must have a unique @@ -78,8 +73,159 @@ class ArchiveMember ubyte[] extra; /// Read/Write: extra data for this member. string comment; /// Read/Write: comment associated with this member. - ubyte[] compressedData; /// Read Only: data of member in compressed form. - ubyte[] expandedData; /// Read/Write: data of member in uncompressed form. + + private ubyte[] _compressedData; + private ubyte[] _expandedData; + private uint offset; + private uint _crc32; + private uint _compressedSize; + private uint _expandedSize; + private CompressionMethod _compressionMethod; + private ushort _madeVersion = 20; + private ushort _extractVersion = 20; + private ushort _diskNumber; + private uint _externalAttributes; + private DosFileTime _time; + + ushort flags; /// Read/Write: normally set to 0 + ushort internalAttributes; /// Read/Write + + @property ushort madeVersion() { return _madeVersion; } /// Read Only + @property ushort extractVersion() { return _extractVersion; } /// Read Only + @property uint crc32() { return _crc32; } /// Read Only: cyclic redundancy check (CRC) value + + /// OS specific file attributes + deprecated("Please use fileAttributes instead.") + @property ref inout(uint) externalAttributes() inout @safe pure nothrow + { return _externalAttributes; } + + /// Read Only: size of data of member in compressed form. + @property uint compressedSize() { return _compressedSize; } + + /// Read Only: size of data of member in expanded form. + @property uint expandedSize() { return _expandedSize; } + @property ushort diskNumber() { return _diskNumber; } /// Read Only: should be 0. + + /// Read Only: data of member in compressed form. + @property ubyte[] compressedData() { return _compressedData; } + + /// Read data of member in uncompressed form. + @property ubyte[] expandedData() { return _expandedData; } + + /// Write data of member in uncompressed form. + @property void expandedData(ubyte[] ed) + { + _expandedData = ed; + _expandedSize = to!uint(_expandedData.length); + + // Clean old compressed data, if any + _compressedData.length = 0; + _compressedSize = 0; + } + + /** + * Set the OS specific file attributes, as obtained by + * $(XREF file,getAttributes) or $(XREF file,DirEntry.attributes), for this archive member. + */ + @property void fileAttributes(uint attr) + { + version (Posix) + { + _externalAttributes = (attr & 0xFFFF) << 16; + _madeVersion &= 0x00FF; + _madeVersion |= 0x0300; // attributes are in UNIX format + } + else version (Windows) + { + _externalAttributes = attr; + _madeVersion &= 0x00FF; // attributes are in MS-DOS and OS/2 format + } + else + { + static assert(0, "Unimplemented platform"); + } + } + + version (Posix) unittest + { + auto am = new ArchiveMember(); + am.fileAttributes = octal!100644; + assert(am._externalAttributes == octal!100644 << 16); + assert((am._madeVersion & 0xFF00) == 0x0300); + } + + /** + * Get the OS specific file attributes for the archive member. + * + * Returns: The file attributes or 0 if the file attributes were + * encoded for an incompatible OS (Windows vs. Posix). + * + */ + @property uint fileAttributes() const + { + version (Posix) + { + if ((_madeVersion & 0xFF00) == 0x0300) + return _externalAttributes >> 16; + return 0; + } + else version (Windows) + { + if ((_madeVersion & 0xFF00) == 0x0000) + return _externalAttributes; + return 0; + } + else + { + static assert(0, "Unimplemented platform"); + } + } + + /// Set the last modification time for this member. + @property void time(SysTime time) + { + _time = SysTimeToDosFileTime(time); + } + + /// ditto + @property void time(DosFileTime time) + { + _time = time; + } + + /// Get the last modification time for this member. + @property DosFileTime time() const + { + return _time; + } + + /** + * Read compression method used for this member + * See_Also: + * CompressionMethod + **/ + @property CompressionMethod compressionMethod() { return _compressionMethod; } + + deprecated("Please use the enum CompressionMethod to set this property instead.") + @property void compressionMethod(ushort cm) + { + compressionMethod = cast(CompressionMethod)(cm); + } + + /** + * Write compression method used for this member + * See_Also: + * CompressionMethod + **/ + @property void compressionMethod(CompressionMethod cm) + { + if (cm == _compressionMethod) return; + + if (_compressedSize > 0) + throw new ZipException("Can't change compression method for a compressed element"); + + _compressionMethod = cm; + } debug(print) { @@ -105,21 +251,34 @@ class ArchiveMember * Object representing the entire archive. * ZipArchives are collections of ArchiveMembers. */ -class ZipArchive +final class ZipArchive { - ubyte[] data; /// Read Only: array representing the entire contents of the archive. - uint endrecOffset; - - uint diskNumber; /// Read Only: 0 since multi-disk zip archives are not supported. - uint diskStartDir; /// Read Only: 0 since multi-disk zip archives are not supported. - uint numEntries; /// Read Only: number of ArchiveMembers in the directory. - uint totalEntries; /// Read Only: same as totalEntries. string comment; /// Read/Write: the archive comment. Must be less than 65536 bytes in length. + private ubyte[] _data; + private uint endrecOffset; + + private uint _diskNumber; + private uint _diskStartDir; + private uint _numEntries; + private uint _totalEntries; + + /// Read Only: array representing the entire contents of the archive. + @property ubyte[] data() { return _data; } + + /// Read Only: 0 since multi-disk zip archives are not supported. + @property uint diskNumber() { return _diskNumber; } + + /// Read Only: 0 since multi-disk zip archives are not supported + @property uint diskStartDir() { return _diskStartDir; } + + /// Read Only: number of ArchiveMembers in the directory. + @property uint numEntries() { return _numEntries; } + @property uint totalEntries() { return _totalEntries; } /// ditto /** * Read Only: array indexed by the name of each member of the archive. - * Example: * All the members of the archive can be accessed with a foreach loop: + * Example: * -------------------- * ZipArchive archive = new ZipArchive(data); * foreach (ArchiveMember am; archive.directory) @@ -128,7 +287,9 @@ class ZipArchive * } * -------------------- */ - ArchiveMember[string] directory; + @property ArchiveMember[string] directory() { return _directory; } + + private ArchiveMember[string] _directory; debug (print) { @@ -154,14 +315,14 @@ class ZipArchive */ void addMember(ArchiveMember de) { - directory[de.name] = de; + _directory[de.name] = de; } /** Delete de from the archive. */ void deleteMember(ArchiveMember de) { - directory.remove(de.name); + _directory.remove(de.name); } /** @@ -184,25 +345,29 @@ class ZipArchive // Compress each member; compute size uint archiveSize = 0; uint directorySize = 0; - foreach (ArchiveMember de; directory) + foreach (ArchiveMember de; _directory) { - de.expandedSize = to!uint(de.expandedData.length); - switch (de.compressionMethod) + if (!de._compressedData.length) { - case 0: - de.compressedData = de.expandedData; - break; + switch (de.compressionMethod) + { + case CompressionMethod.none: + de._compressedData = de._expandedData; + break; - case 8: - de.compressedData = cast(ubyte[])std.zlib.compress(cast(void[])de.expandedData); - de.compressedData = de.compressedData[2 .. de.compressedData.length - 4]; - break; + case CompressionMethod.deflate: + de._compressedData = cast(ubyte[])std.zlib.compress(cast(void[])de._expandedData); + de._compressedData = de._compressedData[2 .. de._compressedData.length - 4]; + break; - default: - throw new ZipException("unsupported compression method"); + default: + throw new ZipException("unsupported compression method"); + } + + de._compressedSize = to!uint(de._compressedData.length); + de._crc32 = std.zlib.crc32(0, cast(void[])de._expandedData); } - de.compressedSize = to!uint(de.compressedData.length); - de.crc32 = std.zlib.crc32(0, cast(void[])de.expandedData); + assert(de._compressedData.length == de._compressedSize); archiveSize += 30 + de.name.length + de.extra.length + @@ -212,45 +377,45 @@ class ZipArchive de.comment.length; } - data = new ubyte[archiveSize + directorySize + 22 + comment.length]; + _data = new ubyte[archiveSize + directorySize + 22 + comment.length]; // Populate the data[] // Store each archive member i = 0; - foreach (ArchiveMember de; directory) + foreach (ArchiveMember de; _directory) { de.offset = i; - data[i .. i + 4] = cast(ubyte[])"PK\x03\x04"; + _data[i .. i + 4] = cast(ubyte[])"PK\x03\x04"; putUshort(i + 4, de.extractVersion); putUshort(i + 6, de.flags); - putUshort(i + 8, de.compressionMethod); + putUshort(i + 8, de._compressionMethod); putUint (i + 10, cast(uint)de.time); putUint (i + 14, de.crc32); putUint (i + 18, de.compressedSize); - putUint (i + 22, to!uint(de.expandedData.length)); + putUint (i + 22, to!uint(de.expandedSize)); putUshort(i + 26, cast(ushort)de.name.length); putUshort(i + 28, cast(ushort)de.extra.length); i += 30; - data[i .. i + de.name.length] = (cast(ubyte[])de.name)[]; + _data[i .. i + de.name.length] = (cast(ubyte[])de.name)[]; i += de.name.length; - data[i .. i + de.extra.length] = (cast(ubyte[])de.extra)[]; + _data[i .. i + de.extra.length] = (cast(ubyte[])de.extra)[]; i += de.extra.length; - data[i .. i + de.compressedSize] = de.compressedData[]; + _data[i .. i + de.compressedSize] = de.compressedData[]; i += de.compressedSize; } // Write directory directoryOffset = i; - numEntries = 0; - foreach (ArchiveMember de; directory) + _numEntries = 0; + foreach (ArchiveMember de; _directory) { - data[i .. i + 4] = cast(ubyte[])"PK\x01\x02"; + _data[i .. i + 4] = cast(ubyte[])"PK\x01\x02"; putUshort(i + 4, de.madeVersion); putUshort(i + 6, de.extractVersion); putUshort(i + 8, de.flags); - putUshort(i + 10, de.compressionMethod); + putUshort(i + 10, de._compressionMethod); putUint (i + 12, cast(uint)de.time); putUint (i + 16, de.crc32); putUint (i + 20, de.compressedSize); @@ -260,23 +425,23 @@ class ZipArchive putUshort(i + 32, cast(ushort)de.comment.length); putUshort(i + 34, de.diskNumber); putUshort(i + 36, de.internalAttributes); - putUint (i + 38, de.externalAttributes); + putUint (i + 38, de._externalAttributes); putUint (i + 42, de.offset); i += 46; - data[i .. i + de.name.length] = (cast(ubyte[])de.name)[]; + _data[i .. i + de.name.length] = (cast(ubyte[])de.name)[]; i += de.name.length; - data[i .. i + de.extra.length] = (cast(ubyte[])de.extra)[]; + _data[i .. i + de.extra.length] = (cast(ubyte[])de.extra)[]; i += de.extra.length; - data[i .. i + de.comment.length] = (cast(ubyte[])de.comment)[]; + _data[i .. i + de.comment.length] = (cast(ubyte[])de.comment)[]; i += de.comment.length; - numEntries++; + _numEntries++; } - totalEntries = numEntries; + _totalEntries = numEntries; // Write end record endrecOffset = i; - data[i .. i + 4] = cast(ubyte[])"PK\x05\x06"; + _data[i .. i + 4] = cast(ubyte[])"PK\x05\x06"; putUshort(i + 4, cast(ushort)diskNumber); putUshort(i + 6, cast(ushort)diskStartDir); putUshort(i + 8, cast(ushort)numEntries); @@ -288,7 +453,7 @@ class ZipArchive // Write archive comment assert(i + comment.length == data.length); - data[i .. data.length] = (cast(ubyte[])comment)[]; + _data[i .. data.length] = (cast(ubyte[])comment)[]; return cast(void[])data; } @@ -317,7 +482,7 @@ class ZipArchive uint directorySize; uint directoryOffset; - this.data = cast(ubyte[]) buffer; + this._data = cast(ubyte[]) buffer; // Find 'end record index' by searching backwards for signature iend = to!uint(data.length) - 66000; @@ -328,23 +493,23 @@ class ZipArchive if (i < iend) throw new ZipException("no end record"); - if (data[i .. i + 4] == cast(ubyte[])"PK\x05\x06") + if (_data[i .. i + 4] == cast(ubyte[])"PK\x05\x06") { endcommentlength = getUshort(i + 20); if (i + 22 + endcommentlength > data.length) continue; - comment = cast(string)(data[i + 22 .. i + 22 + endcommentlength]); + comment = cast(string)(_data[i + 22 .. i + 22 + endcommentlength]); endrecOffset = i; break; } } // Read end record data - diskNumber = getUshort(i + 4); - diskStartDir = getUshort(i + 6); + _diskNumber = getUshort(i + 4); + _diskStartDir = getUshort(i + 6); - numEntries = getUshort(i + 8); - totalEntries = getUshort(i + 10); + _numEntries = getUshort(i + 8); + _totalEntries = getUshort(i + 10); if (numEntries != totalEntries) throw new ZipException("multiple disk zips not supported"); @@ -371,37 +536,38 @@ class ZipArchive uint extralen; uint commentlen; - if (data[i .. i + 4] != cast(ubyte[])"PK\x01\x02") + if (_data[i .. i + 4] != cast(ubyte[])"PK\x01\x02") throw new ZipException("invalid directory entry 1"); ArchiveMember de = new ArchiveMember(); - de.madeVersion = getUshort(i + 4); - de.extractVersion = getUshort(i + 6); + de._madeVersion = getUshort(i + 4); + de._extractVersion = getUshort(i + 6); de.flags = getUshort(i + 8); - de.compressionMethod = getUshort(i + 10); + de._compressionMethod = cast(CompressionMethod)getUshort(i + 10); de.time = cast(DosFileTime)getUint(i + 12); - de.crc32 = getUint(i + 16); - de.compressedSize = getUint(i + 20); - de.expandedSize = getUint(i + 24); + de._crc32 = getUint(i + 16); + de._compressedSize = getUint(i + 20); + de._expandedSize = getUint(i + 24); namelen = getUshort(i + 28); extralen = getUshort(i + 30); commentlen = getUshort(i + 32); - de.diskNumber = getUshort(i + 34); + de._diskNumber = getUshort(i + 34); de.internalAttributes = getUshort(i + 36); - de.externalAttributes = getUint(i + 38); + de._externalAttributes = getUint(i + 38); de.offset = getUint(i + 42); i += 46; if (i + namelen + extralen + commentlen > directoryOffset + directorySize) throw new ZipException("invalid directory entry 2"); - de.name = cast(string)(data[i .. i + namelen]); + de.name = cast(string)(_data[i .. i + namelen]); i += namelen; - de.extra = data[i .. i + extralen]; + de.extra = _data[i .. i + extralen]; i += extralen; - de.comment = cast(string)(data[i .. i + commentlen]); + de.comment = cast(string)(_data[i .. i + commentlen]); i += commentlen; - directory[de.name] = de; + _directory[de.name] = de; + } if (i != directoryOffset + directorySize) throw new ZipException("invalid directory entry 3"); @@ -418,17 +584,17 @@ class ZipArchive { uint namelen; uint extralen; - if (data[de.offset .. de.offset + 4] != cast(ubyte[])"PK\x03\x04") + if (_data[de.offset .. de.offset + 4] != cast(ubyte[])"PK\x03\x04") throw new ZipException("invalid directory entry 4"); // These values should match what is in the main zip archive directory - de.extractVersion = getUshort(de.offset + 4); + de._extractVersion = getUshort(de.offset + 4); de.flags = getUshort(de.offset + 6); - de.compressionMethod = getUshort(de.offset + 8); + de._compressionMethod = cast(CompressionMethod)getUshort(de.offset + 8); de.time = cast(DosFileTime)getUint(de.offset + 10); - de.crc32 = getUint(de.offset + 14); - de.compressedSize = max(getUint(de.offset + 18), de.compressedSize); - de.expandedSize = max(getUint(de.offset + 22), de.expandedSize); + de._crc32 = getUint(de.offset + 14); + de._compressedSize = max(getUint(de.offset + 18), de.compressedSize); + de._expandedSize = max(getUint(de.offset + 22), de.expandedSize); namelen = getUshort(de.offset + 26); extralen = getUshort(de.offset + 28); @@ -448,20 +614,20 @@ class ZipArchive if (i + de.compressedSize > endrecOffset) throw new ZipException("invalid directory entry 5"); - de.compressedData = data[i .. i + de.compressedSize]; + de._compressedData = _data[i .. i + de.compressedSize]; debug(print) arrayPrint(de.compressedData); switch (de.compressionMethod) { - case 0: - de.expandedData = de.compressedData; + case CompressionMethod.none: + de._expandedData = de.compressedData; return de.expandedData; - case 8: + case CompressionMethod.deflate: // -15 is a magic value used to decompress zip files. // It has the effect of not requiring the 2 byte header // and 4 byte trailer. - de.expandedData = cast(ubyte[])std.zlib.uncompress(cast(void[])de.compressedData, de.expandedSize, -15); + de._expandedData = cast(ubyte[])std.zlib.uncompress(cast(void[])de.compressedData, de.expandedSize, -15); return de.expandedData; default: @@ -475,12 +641,12 @@ class ZipArchive { version (LittleEndian) { - return *cast(ushort *)&data[i]; + return *cast(ushort *)&_data[i]; } else { - ubyte b0 = data[i]; - ubyte b1 = data[i + 1]; + ubyte b0 = _data[i]; + ubyte b1 = _data[i + 1]; return (b1 << 8) | b0; } } @@ -489,11 +655,11 @@ class ZipArchive { version (LittleEndian) { - return *cast(uint *)&data[i]; + return *cast(uint *)&_data[i]; } else { - return bswap(*cast(uint *)&data[i]); + return bswap(*cast(uint *)&_data[i]); } } @@ -501,12 +667,12 @@ class ZipArchive { version (LittleEndian) { - *cast(ushort *)&data[i] = us; + *cast(ushort *)&_data[i] = us; } else { - data[i] = cast(ubyte)us; - data[i + 1] = cast(ubyte)(us >> 8); + _data[i] = cast(ubyte)us; + _data[i + 1] = cast(ubyte)(us >> 8); } } @@ -516,7 +682,7 @@ class ZipArchive { ui = bswap(ui); } - *cast(uint *)&data[i] = ui; + *cast(uint *)&_data[i] = ui; } } @@ -534,3 +700,19 @@ debug(print) printf("\n"); } } + +unittest +{ + auto zip1 = new ZipArchive(); + auto zip2 = new ZipArchive(); + auto am1 = new ArchiveMember(); + am1.name = "foo"; + am1.expandedData = new ubyte[](1024); + zip1.addMember(am1); + zip1.build(); + zip2.addMember(zip1.directory["foo"]); + zip2.build(); + auto am2 = zip2.directory["foo"]; + zip2.expand(am2); + assert(am1.expandedData == am2.expandedData); +} diff --git a/std/zlib.d b/std/zlib.d index 7bf79d23c..81f74cf5d 100644 --- a/std/zlib.d +++ b/std/zlib.d @@ -143,9 +143,12 @@ const(void)[] compress(const(void)[] buf) /********************************************* * Decompresses the data in srcbuf[]. - * Params: destlen = size of the uncompressed data. - * It need not be accurate, but the decompression will be faster if the exact - * size is supplied. + * Params: + * srcbuf = buffer containing the compressed data. + * destlen = size of the uncompressed data. + * It need not be accurate, but the decompression will be faster + * if the exact size is supplied. + * winbits = the base two logarithm of the maximum window size. * Returns: the decompressed data. */ diff --git a/win32.mak b/win32.mak index 0ed68c6e8..41bfa6a12 100644 --- a/win32.mak +++ b/win32.mak @@ -38,13 +38,13 @@ CFLAGS=-mn -6 -r ## Flags for dmd D compiler -DFLAGS=-O -release -w -d -property +DFLAGS=-O -release -w -d #DFLAGS=-unittest -g -d #DFLAGS=-unittest -cov -g -d ## Flags for compiling unittests -UDFLAGS=-O -w -d -property +UDFLAGS=-O -w -d ## C compiler @@ -60,7 +60,7 @@ DMD=dmd ## Location of where to write the html documentation files -DOCSRC = . +DOCSRC = ../dlang.org STDDOC = $(DOCSRC)/std.ddoc DOC=..\..\html\d\phobos @@ -191,7 +191,9 @@ SRC_STD_C_OSX= std\c\osx\socket.d SRC_STD_C_FREEBSD= std\c\freebsd\socket.d -SRC_STD_INTERNAL= std\internal\processinit.d std\internal\uni.d std\internal\uni_tab.d +SRC_STD_INTERNAL= std\internal\processinit.d std\internal\uni.d std\internal\uni_tab.d \ + std\internal\unicode_tables.d std\internal\unicode_comp.d std\internal\unicode_decomp.d \ + std\internal\unicode_grapheme.d std\internal\unicode_norm.d SRC_STD_INTERNAL_DIGEST= std\internal\digest\sha_SSSE3.d @@ -815,5 +817,9 @@ cleanhtml: install: phobos.zip $(CP) phobos.lib phobos64.lib $(DIR)\windows\lib $(CP) $(DRUNTIME)\lib\gcstub.obj $(DRUNTIME)\lib\gcstub64.obj $(DIR)\windows\lib + +rd/s/q $(DIR)\html\d\phobos + +md $(DIR)\html\d\phobos + $(CP) $(DOCS) $(DIR)\html\d\phobos + $(CP) $(DOC)\phobos.html $(DIR)\html\d\phobos\index.html +rd/s/q $(DIR)\src\phobos unzip -o phobos.zip -d $(DIR)\src\phobos diff --git a/win64.mak b/win64.mak index 10b0ad250..4d31413c1 100644 --- a/win64.mak +++ b/win64.mak @@ -37,13 +37,13 @@ CFLAGS=/O2 /nologo /I"$(VCDIR)\INCLUDE" /I"$(SDKDIR)\Include" ## Flags for dmd D compiler -DFLAGS=-m$(MODEL) -O -release -w -d -property +DFLAGS=-m$(MODEL) -O -release -w -d #DFLAGS=-m$(MODEL) -unittest -g -d #DFLAGS=-m$(MODEL) -unittest -cov -g -d ## Flags for compiling unittests -UDFLAGS=-g -m$(MODEL) -O -w -d -property +UDFLAGS=-g -m$(MODEL) -O -w -d ## C compiler, linker, librarian @@ -60,7 +60,7 @@ DMD=dmd ## Location of where to write the html documentation files -DOCSRC = . +DOCSRC = ../dlang.org STDDOC = $(DOCSRC)/std.ddoc DOC=..\..\html\d\phobos @@ -210,13 +210,15 @@ SRC_STD_C_OSX= std\c\osx\socket.d SRC_STD_C_FREEBSD= std\c\freebsd\socket.d -SRC_STD_INTERNAL= std\internal\processinit.d std\internal\uni.d std\internal\uni_tab.d +SRC_STD_INTERNAL= std\internal\processinit.d std\internal\uni.d std\internal\uni_tab.d \ + std\internal\unicode_tables.d std\internal\unicode_comp.d std\internal\unicode_decomp.d \ + std\internal\unicode_grapheme.d std\internal\unicode_norm.d SRC_STD_INTERNAL_DIGEST= std\internal\digest\sha_SSSE3.d SRC_STD_INTERNAL_MATH= std\internal\math\biguintcore.d \ std\internal\math\biguintnoasm.d std\internal\math\biguintx86.d \ - std\internal\math\gammafunction.d std\internal\math\errorfunction.d + std\internal\math\gammafunction.d std\internal\math\errorfunction.d SRC_STD_INTERNAL_WINDOWS= std\internal\windows\advapi32.d